@evoke-platform/ui-components 1.0.0-dev.126 → 1.0.0-dev.128
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/published/components/core/Autocomplete/Autocomplete.js +2 -2
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.d.ts +1 -1
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +38 -5
- package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +1 -1
- package/dist/published/index.d.ts +0 -1
- package/dist/published/index.js +0 -1
- package/dist/published/stories/FormField.stories.d.ts +1 -0
- package/dist/published/stories/FormField.stories.js +21 -0
- package/package.json +1 -1
- package/dist/published/form-components/Buttons.d.ts +0 -10
- package/dist/published/form-components/Buttons.js +0 -37
- package/dist/published/form-components/FieldWrapper.d.ts +0 -21
- package/dist/published/form-components/FieldWrapper.js +0 -84
- package/dist/published/form-components/FormFieldComponent.d.ts +0 -34
- package/dist/published/form-components/FormFieldComponent.js +0 -160
- package/dist/published/form-components/index.d.ts +0 -21
- package/dist/published/form-components/index.js +0 -8
@@ -29,10 +29,10 @@ const Autocomplete = (props) => {
|
|
29
29
|
const isError = props.error && (props.required || props.errorMessage);
|
30
30
|
if (!!props.label && props.labelPlacement === 'outside-top') {
|
31
31
|
return (React.createElement(UIThemeProvider, null,
|
32
|
-
React.createElement(InputLabel, { "data-testid": "label-outside", htmlFor: (_b = (_a = props.label) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '', sx: { paddingBottom:
|
32
|
+
React.createElement(InputLabel, { "data-testid": "label-outside", htmlFor: (_b = (_a = props.label) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '', sx: { paddingBottom: '0px', fontSize: '14px' } }, (_c = props.label) !== null && _c !== void 0 ? _c : '',
|
33
33
|
" ",
|
34
34
|
props.required ? React.createElement("span", { style: { color: 'red' } }, "*") : null),
|
35
|
-
props.instructionText && React.createElement(Typography, {
|
35
|
+
props.instructionText && React.createElement(Typography, { fontSize: '10px', lineHeight: '14px' }, props.instructionText),
|
36
36
|
React.createElement(MUIAutocomplete, Object.assign({}, props, { sx: Object.assign({ '& fieldset': { borderRadius: '8px', borderColor: isError ? 'red' : undefined } }, props.sx), options: sortedOptions, popupIcon: (_d = props.popupIcon) !== null && _d !== void 0 ? _d : React.createElement(ExpandMore, null) })),
|
37
37
|
isError && React.createElement(FieldError, { required: props.required, label: props.errorMessage })));
|
38
38
|
}
|
@@ -15,7 +15,7 @@ export declare type ObjectProperty = {
|
|
15
15
|
declare type CustomValueEditorProps = ValueEditorProps & {
|
16
16
|
values?: AutocompleteOption[] | any[];
|
17
17
|
};
|
18
|
-
declare type Operator =
|
18
|
+
declare type Operator = '=' | '!=' | '<' | '>' | '<=' | '>=' | 'contains' | 'beginsWith' | 'endsWith' | 'doesNotContain' | 'doesNotBeginWith' | 'doesNotEndWith' | 'null' | 'notNull' | 'in' | 'notIn' | 'between' | 'notBetween';
|
19
19
|
declare type CriteriaInputProps = {
|
20
20
|
properties: ObjectProperty[];
|
21
21
|
setCriteria: Function;
|
@@ -140,6 +140,7 @@ const dynamicContentInputEditor = (props) => {
|
|
140
140
|
return determineValueEditor(valueEditor, props);
|
141
141
|
};
|
142
142
|
const determineValueEditor = (baseValueEditor, props) => {
|
143
|
+
var _a, _b;
|
143
144
|
const { handleOnChange, value, values, type, operator, inputType } = props;
|
144
145
|
const disabled = ['null', 'notNull'].includes(operator);
|
145
146
|
let valueEditor = baseValueEditor;
|
@@ -151,9 +152,35 @@ const determineValueEditor = (baseValueEditor, props) => {
|
|
151
152
|
}, renderInput: (params) => (React.createElement(TextField, Object.assign({}, params, { placeholder: "Value", size: "small", style: { width: '33%' } }))) })));
|
152
153
|
break;
|
153
154
|
case 'integer':
|
154
|
-
|
155
|
-
|
156
|
-
|
155
|
+
{
|
156
|
+
const DynamicContentInput = (_b = (_a = props.context) === null || _a === void 0 ? void 0 : _a.dynamicContentInput) === null || _b === void 0 ? void 0 : _b.component;
|
157
|
+
if (DynamicContentInput) {
|
158
|
+
if ((operator === 'in' || operator === 'notIn') && type === 'select' && values) {
|
159
|
+
valueEditor = (React.createElement(Autocomplete, { multiple: true, options: values || [], getOptionLabel: (option) => (option.label ? option.label : ''), value: Array.isArray(value) ? (disabled ? [] : value) : [], disabled: disabled, onChange: (event, newValue) => {
|
160
|
+
const uniqueSelections = Array.from(new Set(newValue.map((item) => item.label))).map((label) => {
|
161
|
+
return newValue.find((item) => item.label === label);
|
162
|
+
});
|
163
|
+
handleOnChange(uniqueSelections.length ? uniqueSelections : '');
|
164
|
+
}, isOptionEqualToValue: (option, value) => {
|
165
|
+
return option === value;
|
166
|
+
}, renderInput: (params) => (React.createElement(TextField, Object.assign({ label: params.label }, params, { size: "small" }))), style: { width: '33%' } }));
|
167
|
+
}
|
168
|
+
else if (type === 'select' && values) {
|
169
|
+
valueEditor = (React.createElement(Autocomplete, { freeSolo: true, options: values, multiple: ['in', 'notIn'].includes(operator), value: disabled ? '' : value, onChange: (event, newValue) => {
|
170
|
+
handleOnChange(newValue === null || newValue === void 0 ? void 0 : newValue.label);
|
171
|
+
}, disabled: disabled, isOptionEqualToValue: (option, value) => {
|
172
|
+
return option === value;
|
173
|
+
}, renderInput: (params) => (React.createElement(TextField, Object.assign({}, params, { size: "small", placeholder: 'Value', readOnly: value === '{{user.id}}', onChange: (event) => {
|
174
|
+
handleOnChange(event.target.value);
|
175
|
+
} }))), style: { width: '33%' }, disableClearable: true }));
|
176
|
+
}
|
177
|
+
}
|
178
|
+
else {
|
179
|
+
valueEditor = (React.createElement(TextField, { value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: ['null', 'notNull'].includes(operator), onChange: (e) => {
|
180
|
+
handleOnChange(isNaN(parseInt(e.target.value)) ? '' : parseInt(e.target.value));
|
181
|
+
}, type: "number", placeholder: "Value", size: "small", sx: { width: '33%' } }));
|
182
|
+
}
|
183
|
+
}
|
157
184
|
break;
|
158
185
|
case 'number':
|
159
186
|
valueEditor = (React.createElement(TextField, { value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: ['null', 'notNull'].includes(operator), onChange: (e) => {
|
@@ -267,11 +294,17 @@ const CriteriaBuilder = (props) => {
|
|
267
294
|
addRuleAction: customButton,
|
268
295
|
removeGroupAction: customDelete,
|
269
296
|
removeRuleAction: customDelete,
|
270
|
-
valueEditor: enablePresetValues
|
297
|
+
valueEditor: enablePresetValues
|
298
|
+
? customValueEditorWithPresets
|
299
|
+
: dynamicContentInput
|
300
|
+
? dynamicContentInputEditor
|
301
|
+
: customValueEditor,
|
271
302
|
}, context: { dynamicContentInput: dynamicContentInput }, controlClassnames: {
|
272
303
|
queryBuilder: 'queryBuilder-branches',
|
273
304
|
ruleGroup: 'container',
|
274
|
-
}, operators: operators
|
305
|
+
}, operators: operators
|
306
|
+
? ALL_OPERATORS.filter((o) => operators.includes(o.name))
|
307
|
+
: ALL_OPERATORS }))));
|
275
308
|
}
|
276
309
|
return React.createElement(React.Fragment, null);
|
277
310
|
};
|
package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js
CHANGED
@@ -47,7 +47,7 @@ const InputFieldComponent = (props) => {
|
|
47
47
|
setInputValue(selectValue);
|
48
48
|
};
|
49
49
|
const InputProps = property.type === 'number'
|
50
|
-
? { inputComponent: NumericFormat, min, max }
|
50
|
+
? { inputComponent: NumericFormat, inputProps: { min, max, readOnly } }
|
51
51
|
: property.type === 'integer'
|
52
52
|
? { inputProps: { min, max } }
|
53
53
|
: null;
|
@@ -1,6 +1,5 @@
|
|
1
1
|
export { ClickAwayListener, FormControlProps, FormHelperTextProps, GridSize, Toolbar, createTheme, } from '@mui/material';
|
2
2
|
export { CalendarPicker, DateTimePicker, MonthPicker, PickersDay, StaticDateTimePicker, StaticTimePicker, TimePicker, YearPicker, } from '@mui/x-date-pickers';
|
3
|
-
export { FormComponents } from './form-components';
|
4
3
|
export * from './components/core';
|
5
4
|
export { CriteriaBuilder, DataGrid, FormField, MenuBar, MultiSelect, RepeatableField, UserAvatar, } from './components/custom';
|
6
5
|
export { Box, Container, Grid, Stack } from './components/layout';
|
package/dist/published/index.js
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
export { ClickAwayListener, Toolbar, createTheme, } from '@mui/material';
|
2
2
|
export { CalendarPicker, DateTimePicker, MonthPicker, PickersDay, StaticDateTimePicker, StaticTimePicker, TimePicker, YearPicker, } from '@mui/x-date-pickers';
|
3
|
-
export { FormComponents } from './form-components';
|
4
3
|
export * from './components/core';
|
5
4
|
export { CriteriaBuilder, DataGrid, FormField, MenuBar, MultiSelect, RepeatableField, UserAvatar, } from './components/custom';
|
6
5
|
export { Box, Container, Grid, Stack } from './components/layout';
|
@@ -2,6 +2,7 @@ import { ComponentMeta, ComponentStory } from '@storybook/react';
|
|
2
2
|
declare const _default: ComponentMeta<(props: import("../components/custom/FormField/FormField").FormFieldProps) => any>;
|
3
3
|
export default _default;
|
4
4
|
export declare const InputField: ComponentStory<(props: import("../components/custom/FormField/FormField").FormFieldProps) => any>;
|
5
|
+
export declare const NumberField: ComponentStory<(props: import("../components/custom/FormField/FormField").FormFieldProps) => any>;
|
5
6
|
export declare const MaskedInput: ComponentStory<(props: import("../components/custom/FormField/FormField").FormFieldProps) => any>;
|
6
7
|
export declare const ChoicesSelectField: ComponentStory<(props: import("../components/custom/FormField/FormField").FormFieldProps) => any>;
|
7
8
|
export declare const DatePickerField: ComponentStory<(props: import("../components/custom/FormField/FormField").FormFieldProps) => any>;
|
@@ -26,6 +26,27 @@ InputField.args = {
|
|
26
26
|
isMultiLineText: true,
|
27
27
|
rows: 5,
|
28
28
|
};
|
29
|
+
export const NumberField = FormFieldTemplate.bind({});
|
30
|
+
NumberField.args = {
|
31
|
+
property: {
|
32
|
+
id: 'price',
|
33
|
+
name: 'Price',
|
34
|
+
type: 'number',
|
35
|
+
// enum?: string[],
|
36
|
+
required: true,
|
37
|
+
},
|
38
|
+
onChange: (id, value) => console.log('id= ', id, 'Value= ', value),
|
39
|
+
defaultValue: '12.99',
|
40
|
+
error: false,
|
41
|
+
required: true,
|
42
|
+
readOnly: true,
|
43
|
+
selectOptions: [],
|
44
|
+
locale: 'string',
|
45
|
+
size: 'small',
|
46
|
+
placeholder: 'string',
|
47
|
+
isMultiLineText: true,
|
48
|
+
rows: 5,
|
49
|
+
};
|
29
50
|
export const MaskedInput = FormFieldTemplate.bind({});
|
30
51
|
MaskedInput.args = {
|
31
52
|
mask: '999-99-9999',
|
package/package.json
CHANGED
@@ -1,10 +0,0 @@
|
|
1
|
-
import { ReactComponent } from '@formio/react';
|
2
|
-
declare class Buttons extends ReactComponent {
|
3
|
-
[x: string]: any;
|
4
|
-
constructor(component: any, options: any, data: any);
|
5
|
-
init(): void;
|
6
|
-
handleCancel: (event: any) => void;
|
7
|
-
handleSubmit: (event: any) => void;
|
8
|
-
attachReact(element: any): void;
|
9
|
-
}
|
10
|
-
export default Buttons;
|
@@ -1,37 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { Button as EvokeButton } from '../components/core';
|
3
|
-
import { ReactComponent } from '@formio/react';
|
4
|
-
import ReactDOM from 'react-dom';
|
5
|
-
import { cloneDeep, isEmpty, isEqual } from 'lodash';
|
6
|
-
class Buttons extends ReactComponent {
|
7
|
-
constructor(component, options, data) {
|
8
|
-
super(component, options, data);
|
9
|
-
this.handleCancel = (event) => {
|
10
|
-
this.component.components[0].onCancel(event);
|
11
|
-
};
|
12
|
-
this.handleSubmit = (event) => {
|
13
|
-
const submission = this.root.getValue();
|
14
|
-
this.emit('submitButton', submission);
|
15
|
-
if (isEmpty([...this.root.errors, ...this.root.customErrors])) {
|
16
|
-
this.component.components[1].onSubmit(submission);
|
17
|
-
}
|
18
|
-
};
|
19
|
-
this.handleCancel = this.handleCancel.bind(this);
|
20
|
-
this.handleSubmit = this.handleSubmit.bind(this);
|
21
|
-
}
|
22
|
-
init() {
|
23
|
-
const originalData = cloneDeep(this.root.data);
|
24
|
-
this.on('change', () => {
|
25
|
-
if (!isEqual(originalData, this.root.data)) {
|
26
|
-
this.root.formEdited = true;
|
27
|
-
this.attachReact(this.element);
|
28
|
-
}
|
29
|
-
});
|
30
|
-
}
|
31
|
-
attachReact(element) {
|
32
|
-
return ReactDOM.render(React.createElement("div", { style: { width: '100%', display: 'flex', justifyContent: 'flex-end' } },
|
33
|
-
React.createElement(EvokeButton, { sx: { margin: '5px' }, variant: this.component.components[0].variant, onClick: this.handleCancel, disabled: !this.root.formEdited }, this.component.components[0].label),
|
34
|
-
React.createElement(EvokeButton, { sx: { margin: '5px' }, variant: this.component.components[1].variant, onClick: this.handleSubmit, disabled: !this.root.formEdited }, this.component.components[1].label)), element);
|
35
|
-
}
|
36
|
-
}
|
37
|
-
export default Buttons;
|
@@ -1,21 +0,0 @@
|
|
1
|
-
/// <reference types="react" />
|
2
|
-
declare type FieldWrapperProps = {
|
3
|
-
label: string;
|
4
|
-
description?: string;
|
5
|
-
tooltip?: string;
|
6
|
-
prefix?: string;
|
7
|
-
suffix?: string;
|
8
|
-
value?: string;
|
9
|
-
validate: any;
|
10
|
-
errorMessage: string;
|
11
|
-
showCharCount?: boolean;
|
12
|
-
type: string;
|
13
|
-
onChange: Function;
|
14
|
-
children: any;
|
15
|
-
};
|
16
|
-
/**
|
17
|
-
* A component that wraps a FormField and adds a label,
|
18
|
-
* description, tooltip, prefix, suffix and word/char counts
|
19
|
-
*/
|
20
|
-
declare const FieldWrapper: (props: FieldWrapperProps) => JSX.Element;
|
21
|
-
export default FieldWrapper;
|
@@ -1,84 +0,0 @@
|
|
1
|
-
import { Typography, Tooltip, IconButton } from '../components/core';
|
2
|
-
import { Box } from '../components/layout';
|
3
|
-
import { Help } from '../icons';
|
4
|
-
import React, { useEffect, useRef } from 'react';
|
5
|
-
const PrefixSuffix = (props) => {
|
6
|
-
const { prefix, suffix, height } = props;
|
7
|
-
const text = prefix || suffix;
|
8
|
-
const prefixSuffixStyles = Object.assign(Object.assign(Object.assign({ display: 'inline-flex', alignItems: 'center', background: '#f5f5f5', padding: '5px', border: '1px solid #ccc' }, (suffix && {
|
9
|
-
borderTopRightRadius: '5px',
|
10
|
-
borderBottomRightRadius: '5px',
|
11
|
-
marginLeft: '-5px',
|
12
|
-
paddingLeft: '10px',
|
13
|
-
})), (prefix && {
|
14
|
-
borderTopLeftRadius: '5px',
|
15
|
-
borderBottomLeftRadius: '5px',
|
16
|
-
marginRight: '-5px',
|
17
|
-
paddingRight: '10px',
|
18
|
-
})), { height: height });
|
19
|
-
if (!prefix && !suffix)
|
20
|
-
return null;
|
21
|
-
return (React.createElement(Box, { sx: prefixSuffixStyles },
|
22
|
-
React.createElement(Typography, null, text)));
|
23
|
-
};
|
24
|
-
/**
|
25
|
-
* A component that wraps a FormField and adds a label,
|
26
|
-
* description, tooltip, prefix, suffix and word/char counts
|
27
|
-
*/
|
28
|
-
const FieldWrapper = (props) => {
|
29
|
-
const { label, description, tooltip, prefix, suffix, value, validate, errorMessage, showCharCount, type, onChange, children, } = props;
|
30
|
-
const [fieldHeight, setFieldHeight] = React.useState(40);
|
31
|
-
const [fieldValue, setFieldValue] = React.useState(value);
|
32
|
-
const { maxLength } = validate;
|
33
|
-
const fieldRef = useRef(null);
|
34
|
-
useEffect(() => {
|
35
|
-
//get height of field to sync with height of prefix and suffix
|
36
|
-
const fieldElement = fieldRef.current;
|
37
|
-
if (fieldElement && (prefix || suffix)) {
|
38
|
-
setFieldHeight(fieldElement.getBoundingClientRect().height - 12);
|
39
|
-
}
|
40
|
-
}, [fieldRef]);
|
41
|
-
const underFieldStyles = {
|
42
|
-
display: 'flex',
|
43
|
-
flexDirection: 'row',
|
44
|
-
justifyContent: 'space-between',
|
45
|
-
alignItems: 'center',
|
46
|
-
};
|
47
|
-
const descriptionStyles = {
|
48
|
-
color: '#999',
|
49
|
-
whiteSpace: 'normal',
|
50
|
-
};
|
51
|
-
let charCount = fieldValue && type === 'textfield' ? fieldValue.length : 0;
|
52
|
-
if (maxLength)
|
53
|
-
charCount = maxLength - charCount;
|
54
|
-
const handleChange = (key, value) => {
|
55
|
-
onChange(key, value, new Event('keydown'));
|
56
|
-
setFieldValue(value);
|
57
|
-
};
|
58
|
-
return (React.createElement(Box, null,
|
59
|
-
React.createElement(Box, null,
|
60
|
-
React.createElement(Typography, { sx: { fontWeight: 600 }, variant: "subtitle2" },
|
61
|
-
label,
|
62
|
-
validate.required ? React.createElement("span", { style: { color: 'red' } },
|
63
|
-
` *`,
|
64
|
-
" ") : null,
|
65
|
-
tooltip && (React.createElement(Tooltip, { placement: "right", title: tooltip },
|
66
|
-
React.createElement(IconButton, null,
|
67
|
-
React.createElement(Help, { sx: { fontSize: '14px' } }))))),
|
68
|
-
React.createElement(Typography, { variant: "caption", sx: descriptionStyles }, description),
|
69
|
-
React.createElement(Box, { sx: { display: 'flex', flexDirection: 'row' } },
|
70
|
-
React.createElement(PrefixSuffix, { prefix: prefix, height: fieldHeight }),
|
71
|
-
React.createElement("div", { style: { width: '100%' }, ref: fieldRef }, React.Children.map(children, (child) => {
|
72
|
-
return React.cloneElement(child, { onChange: handleChange });
|
73
|
-
})),
|
74
|
-
React.createElement(PrefixSuffix, { suffix: suffix, height: fieldHeight }))),
|
75
|
-
React.createElement(Box, { sx: underFieldStyles },
|
76
|
-
React.createElement(Box, { sx: { width: '100%', display: 'flex', justifyContent: 'space-between' } },
|
77
|
-
errorMessage ? (React.createElement(Typography, { sx: { color: 'red', whiteSpace: 'normal' }, variant: "caption" }, ' ⚠ ' + errorMessage)) : (React.createElement("span", null)),
|
78
|
-
showCharCount && (React.createElement(Typography, { variant: "caption", sx: { color: '#999', whiteSpace: 'nowrap' } },
|
79
|
-
charCount,
|
80
|
-
" ",
|
81
|
-
charCount === 1 ? 'character' : 'characters',
|
82
|
-
!!maxLength && ` remaining`))))));
|
83
|
-
};
|
84
|
-
export default FieldWrapper;
|
@@ -1,34 +0,0 @@
|
|
1
|
-
import { ReactComponent } from '@formio/react';
|
2
|
-
declare class FormFieldComponent extends ReactComponent {
|
3
|
-
[x: string]: any;
|
4
|
-
static schema: any;
|
5
|
-
errorDetails: any;
|
6
|
-
/**
|
7
|
-
* Called when the component has been instantiated. This is useful to define
|
8
|
-
* default instance variable values.
|
9
|
-
*
|
10
|
-
* @param component - The JSON representation of the component created.
|
11
|
-
* @param options - The global options for the renderer
|
12
|
-
* @param data - The contextual data object (model) used for this component.
|
13
|
-
*/
|
14
|
-
constructor(component: any, options: any, data: any);
|
15
|
-
init(): void;
|
16
|
-
handleValidation(value: string): void;
|
17
|
-
hasCustomErrors(): boolean;
|
18
|
-
manageFormErrors(): void;
|
19
|
-
beforeSubmit(): void;
|
20
|
-
/**
|
21
|
-
* Checks for errors in the data value.
|
22
|
-
* @param {any} data - The data value to check.
|
23
|
-
* @param {boolean} dirty - Whether the data value has been modified.
|
24
|
-
* @param {any} rowData - The row data.
|
25
|
-
* @returns {{ hasErrors: boolean, fieldErrorMessages: string[] }} An object containing whether the data value has errors and an array of error messages.
|
26
|
-
*/
|
27
|
-
errorCheck(data: any, dirty: any, rowData: any): {
|
28
|
-
hasErrors: boolean;
|
29
|
-
fieldErrorMessages: any[];
|
30
|
-
};
|
31
|
-
handleChange: (key: string, value: any, event: Event) => void;
|
32
|
-
attachReact(element: any): void;
|
33
|
-
}
|
34
|
-
export default FormFieldComponent;
|
@@ -1,160 +0,0 @@
|
|
1
|
-
import React from 'react';
|
2
|
-
import { FormField } from '../components/custom';
|
3
|
-
import FieldWrapper from './FieldWrapper';
|
4
|
-
import { isEmpty } from 'lodash';
|
5
|
-
import ReactDOM from 'react-dom';
|
6
|
-
import { ReactComponent } from '@formio/react';
|
7
|
-
class FormFieldComponent extends ReactComponent {
|
8
|
-
/**
|
9
|
-
* Called when the component has been instantiated. This is useful to define
|
10
|
-
* default instance variable values.
|
11
|
-
*
|
12
|
-
* @param component - The JSON representation of the component created.
|
13
|
-
* @param options - The global options for the renderer
|
14
|
-
* @param data - The contextual data object (model) used for this component.
|
15
|
-
*/
|
16
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
17
|
-
constructor(component, options, data) {
|
18
|
-
const { property } = component;
|
19
|
-
component.property = Object.assign(Object.assign({}, component.property), { type: property.type === 'string' && property.enum ? 'choices' : property.type });
|
20
|
-
let selectOptions = [];
|
21
|
-
if (!isEmpty(component.data)) {
|
22
|
-
selectOptions = component.data.values;
|
23
|
-
}
|
24
|
-
else if (property.enum) {
|
25
|
-
selectOptions = property.enum.map((val) => ({ label: val, value: val }));
|
26
|
-
}
|
27
|
-
super(Object.assign(Object.assign({}, component), { hideLabel: true, readOnly: component.readOnlyValue || !!property.formula, selectOptions }), options, data);
|
28
|
-
this.handleChange = (key, value, event) => {
|
29
|
-
event.stopPropagation();
|
30
|
-
const val = typeof value === 'object' && value.hasOwnProperty('value') ? value.value : value;
|
31
|
-
this.updateValue(val, { modified: true });
|
32
|
-
this.emit('changed-' + this.component.key, val);
|
33
|
-
this.handleValidation(val);
|
34
|
-
this.attachReact(this.element);
|
35
|
-
};
|
36
|
-
this.errorDetails = {};
|
37
|
-
this.handleChange = this.handleChange.bind(this);
|
38
|
-
}
|
39
|
-
init() {
|
40
|
-
const { conditional: { when, eq }, } = this.component;
|
41
|
-
//listens for the this.emit('changed-'... event on the 'when' component
|
42
|
-
this.on('changed-' + when, (value) => {
|
43
|
-
if (when && eq && value === eq) {
|
44
|
-
this.component.hidden = false;
|
45
|
-
this.attachReact(this.element);
|
46
|
-
}
|
47
|
-
});
|
48
|
-
}
|
49
|
-
handleValidation(value) {
|
50
|
-
const { validate } = this.component;
|
51
|
-
if ((value === undefined || value === null || value === '') && !validate.required) {
|
52
|
-
return;
|
53
|
-
}
|
54
|
-
if (!isEmpty(validate.regexes)) {
|
55
|
-
const regexes = validate.regexes;
|
56
|
-
const failedRules = validate.regexes.filter((rule) => {
|
57
|
-
if (!RegExp(rule.regex).test(value)) {
|
58
|
-
return true;
|
59
|
-
}
|
60
|
-
return false;
|
61
|
-
});
|
62
|
-
if (failedRules.length === 0) {
|
63
|
-
delete this.errorDetails['regexes'];
|
64
|
-
}
|
65
|
-
else {
|
66
|
-
if (validate.operator === 'all') {
|
67
|
-
this.errorDetails['regexes'] = failedRules.map((rule) => rule.errorMessage).join(' and ');
|
68
|
-
}
|
69
|
-
else if (validate.operator === 'any') {
|
70
|
-
if (regexes.length > failedRules.length) {
|
71
|
-
delete this.errorDetails['regexes'];
|
72
|
-
}
|
73
|
-
else {
|
74
|
-
this.errorDetails['regexes'] = failedRules.map((rule) => rule.errorMessage).join(' or ');
|
75
|
-
}
|
76
|
-
}
|
77
|
-
}
|
78
|
-
}
|
79
|
-
if (this.component.validate.minDate) {
|
80
|
-
if (value < this.component.validate.minDate || value > this.component.validate.maxDate) {
|
81
|
-
this.errorDetails['date'] = this.component.validate.customMessage;
|
82
|
-
}
|
83
|
-
else {
|
84
|
-
delete this.errorDetails['date'];
|
85
|
-
}
|
86
|
-
}
|
87
|
-
if (this.component.validate.min && value < this.component.validate.min) {
|
88
|
-
this.errorDetails['min-max'] = this.component.validate.customMessage;
|
89
|
-
}
|
90
|
-
else if (this.component.validate.max && value > this.component.validate.max) {
|
91
|
-
this.errorDetails['min-max'] = this.component.validate.customMessage;
|
92
|
-
}
|
93
|
-
else {
|
94
|
-
delete this.errorDetails['min-max'];
|
95
|
-
}
|
96
|
-
this.manageFormErrors();
|
97
|
-
}
|
98
|
-
hasCustomErrors() {
|
99
|
-
return !isEmpty(this.errorDetails);
|
100
|
-
}
|
101
|
-
manageFormErrors() {
|
102
|
-
if (!isEmpty(this.errorDetails)) {
|
103
|
-
const fieldError = {
|
104
|
-
component: this.component,
|
105
|
-
external: false,
|
106
|
-
formattedKeyOrPath: this.component.key,
|
107
|
-
message: this.component.label + ': ' + Object.values(this.errorDetails).join(', '),
|
108
|
-
};
|
109
|
-
const rootHasErrorData = this.root.customErrors.some((error) => {
|
110
|
-
return error.formattedKeyOrPath === this.component.key;
|
111
|
-
});
|
112
|
-
if (!rootHasErrorData) {
|
113
|
-
this.root.customErrors = [...this.root.customErrors, fieldError];
|
114
|
-
}
|
115
|
-
}
|
116
|
-
else {
|
117
|
-
this.root.customErrors = this.root.customErrors.filter((error) => {
|
118
|
-
return error.formattedKeyOrPath !== this.component.key;
|
119
|
-
});
|
120
|
-
}
|
121
|
-
}
|
122
|
-
beforeSubmit() {
|
123
|
-
this.handleValidation(this.dataValue);
|
124
|
-
this.attachReact(this.element);
|
125
|
-
}
|
126
|
-
/**
|
127
|
-
* Checks for errors in the data value.
|
128
|
-
* @param {any} data - The data value to check.
|
129
|
-
* @param {boolean} dirty - Whether the data value has been modified.
|
130
|
-
* @param {any} rowData - The row data.
|
131
|
-
* @returns {{ hasErrors: boolean, fieldErrorMessages: string[] }} An object containing whether the data value has errors and an array of error messages.
|
132
|
-
*/
|
133
|
-
errorCheck(data, dirty, rowData) {
|
134
|
-
//after changes, check for both custom errors and formio errors
|
135
|
-
if (this.dataValue !== this.defaultValue && !this.component.readOnlyValue) {
|
136
|
-
return {
|
137
|
-
hasErrors: this.hasCustomErrors() || !super.checkValidity(data, dirty, rowData),
|
138
|
-
fieldErrorMessages: [...this.root.errors, ...this.root.customErrors]
|
139
|
-
.filter((error) => error.component.key === this.component.key)
|
140
|
-
.map((error) => error.message),
|
141
|
-
};
|
142
|
-
}
|
143
|
-
return {
|
144
|
-
hasErrors: false,
|
145
|
-
fieldErrorMessages: [],
|
146
|
-
};
|
147
|
-
}
|
148
|
-
attachReact(element) {
|
149
|
-
var _a;
|
150
|
-
const { inputMask, hidden } = this.component;
|
151
|
-
const { hasErrors, fieldErrorMessages } = this.errorCheck(this.dataValue, false, this.data);
|
152
|
-
let root = ReactDOM.findDOMNode(element);
|
153
|
-
if (!root) {
|
154
|
-
root = element;
|
155
|
-
}
|
156
|
-
return ReactDOM.render(React.createElement("div", null, !hidden ? (React.createElement(FieldWrapper, Object.assign({}, this.component, { onChange: this.handleChange, error: hasErrors, errorMessage: fieldErrorMessages.join(', ') }),
|
157
|
-
React.createElement(FormField, Object.assign({}, this.component, { defaultValue: (_a = this.dataValue) !== null && _a !== void 0 ? _a : this.component.defaultValue, mask: inputMask, error: hasErrors })))) : null), root);
|
158
|
-
}
|
159
|
-
}
|
160
|
-
export default FormFieldComponent;
|
@@ -1,21 +0,0 @@
|
|
1
|
-
/// <reference types="react" />
|
2
|
-
import FormFieldComponent from './FormFieldComponent';
|
3
|
-
import Buttons from './Buttons';
|
4
|
-
export declare const FormComponents: {
|
5
|
-
FormFieldComponent: typeof FormFieldComponent;
|
6
|
-
Buttons: typeof Buttons;
|
7
|
-
FieldWrapper: (props: {
|
8
|
-
label: string;
|
9
|
-
description?: string | undefined;
|
10
|
-
tooltip?: string | undefined;
|
11
|
-
prefix?: string | undefined;
|
12
|
-
suffix?: string | undefined;
|
13
|
-
value?: string | undefined;
|
14
|
-
validate: any;
|
15
|
-
errorMessage: string;
|
16
|
-
showCharCount?: boolean | undefined;
|
17
|
-
type: string;
|
18
|
-
onChange: Function;
|
19
|
-
children: any;
|
20
|
-
}) => JSX.Element;
|
21
|
-
};
|