@evoke-platform/ui-components 1.1.0-testing.0 → 1.1.0-testing.10
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/DateTimePicker/DateTimePicker.js +7 -1
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.d.ts +4 -5
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +103 -31
- package/dist/published/components/custom/CriteriaBuilder/PropertyTree.js +4 -10
- package/dist/published/components/custom/CriteriaBuilder/ValueEditor.js +39 -14
- package/dist/published/components/custom/Form/Common/Form.d.ts +7 -1
- package/dist/published/components/custom/Form/Common/Form.js +112 -94
- package/dist/published/components/custom/Form/Common/FormComponentWrapper.d.ts +5 -0
- package/dist/published/components/custom/Form/Common/FormComponentWrapper.js +15 -4
- package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.d.ts +1 -0
- package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.js +1 -1
- package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectPropertyInput.js +7 -3
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/ManyToMany/DropdownRepeatableField.js +6 -2
- package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/ManyToMany/DropdownRepeatableFieldInput.js +1 -0
- package/dist/published/components/custom/Form/index.d.ts +2 -1
- package/dist/published/components/custom/Form/utils.js +21 -4
- package/dist/published/components/custom/FormField/FormField.d.ts +2 -0
- package/dist/published/components/custom/FormField/FormField.js +3 -1
- package/dist/published/components/custom/FormField/Select/Select.js +28 -4
- package/dist/published/components/custom/FormField/Select/Select.test.js +41 -0
- package/dist/published/components/custom/OverflowTextField/OverflowTextField.d.ts +4 -0
- package/dist/published/components/custom/OverflowTextField/OverflowTextField.js +13 -0
- package/dist/published/components/custom/OverflowTextField/index.d.ts +2 -0
- package/dist/published/components/custom/OverflowTextField/index.js +2 -0
- package/dist/published/components/custom/index.d.ts +3 -2
- package/dist/published/components/custom/index.js +2 -2
- package/dist/published/index.d.ts +6 -3
- package/dist/published/index.js +4 -2
- package/dist/published/stories/FormField.stories.js +2 -0
- package/dist/published/stories/OverflowTextField.stories.d.ts +5 -0
- package/dist/published/stories/OverflowTextField.stories.js +28 -0
- package/package.json +2 -8
@@ -24,6 +24,12 @@ const DateTimePicker = (props) => {
|
|
24
24
|
handleChange(newValue, keyboardInputValue);
|
25
25
|
};
|
26
26
|
return (React.createElement(UIThemeProvider, null,
|
27
|
-
React.createElement(MUIDateTimePicker, { value: value, onChange: onChange, renderInput: (params) => React.createElement(TextField, { ...params }),
|
27
|
+
React.createElement(MUIDateTimePicker, { value: value, onChange: onChange, renderInput: (params) => React.createElement(TextField, { ...params }), PaperProps: {
|
28
|
+
sx: {
|
29
|
+
'&.MuiPickersPopper-paper': {
|
30
|
+
borderRadius: '12px',
|
31
|
+
},
|
32
|
+
},
|
33
|
+
}, ...rest })));
|
28
34
|
};
|
29
35
|
export default DateTimePicker;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
/// <reference types="react" />
|
2
2
|
import 'react-querybuilder/dist/query-builder.css';
|
3
3
|
import { EvokeObject } from '../../../types';
|
4
4
|
import { ObjectProperty, Operator, PresetValue, TreeViewObject } from './types';
|
@@ -10,10 +10,9 @@ export type CriteriaInputProps = {
|
|
10
10
|
originalCriteria?: Record<string, unknown>;
|
11
11
|
enablePresetValues?: boolean;
|
12
12
|
presetValues?: PresetValue[];
|
13
|
-
|
14
|
-
component:
|
15
|
-
|
16
|
-
trigger?: Record<string, unknown>;
|
13
|
+
customValueEditor?: {
|
14
|
+
component: (props: ValueEditorProps) => JSX.Element;
|
15
|
+
props?: Record<string, unknown>;
|
17
16
|
};
|
18
17
|
operators?: Operator[];
|
19
18
|
disabledCriteria?: {
|
@@ -3,12 +3,13 @@ import { Typography } from '@mui/material';
|
|
3
3
|
import { QueryBuilderMaterial } from '@react-querybuilder/material';
|
4
4
|
import { isArray, isEmpty, startCase } from 'lodash';
|
5
5
|
import React, { useEffect, useMemo, useState } from 'react';
|
6
|
-
import { QueryBuilder, RuleGroupBodyComponents, RuleGroupHeaderComponents, TestID, defaultRuleProcessorMongoDB, formatQuery, useRuleGroup, } from 'react-querybuilder';
|
6
|
+
import { QueryBuilder, RuleGroupBodyComponents, RuleGroupHeaderComponents, TestID, add, defaultRuleProcessorMongoDB, formatQuery, useRuleGroup, } from 'react-querybuilder';
|
7
7
|
import 'react-querybuilder/dist/query-builder.css';
|
8
8
|
import escape from 'string-escape-regex';
|
9
9
|
import { TrashCan } from '../../../icons/custom';
|
10
|
-
import { Autocomplete, Button, IconButton
|
10
|
+
import { Autocomplete, Button, IconButton } from '../../core';
|
11
11
|
import { Box } from '../../layout';
|
12
|
+
import { OverflowTextField } from '../OverflowTextField';
|
12
13
|
import { difference } from '../util';
|
13
14
|
import PropertyTree from './PropertyTree';
|
14
15
|
import { parseMongoDB, traversePropertyPath } from './utils';
|
@@ -28,6 +29,13 @@ const ALL_OPERATORS = [
|
|
28
29
|
{ name: 'in', label: 'In' },
|
29
30
|
{ name: 'notIn', label: 'Not in' },
|
30
31
|
];
|
32
|
+
const styles = {
|
33
|
+
buttons: {
|
34
|
+
padding: '6px 16px',
|
35
|
+
fontSize: '0.875rem',
|
36
|
+
boxShadow: 'none',
|
37
|
+
},
|
38
|
+
};
|
31
39
|
const CustomRuleGroup = (props) => {
|
32
40
|
const rg = { ...props, ...useRuleGroup(props) };
|
33
41
|
const [addRule, addGroup, cloneGroup, toggleLockGroup, removeGroup] = [
|
@@ -73,11 +81,8 @@ const customButton = (props) => {
|
|
73
81
|
case 'Add rule':
|
74
82
|
buttonLabel = 'Add Condition';
|
75
83
|
break;
|
76
|
-
case 'Remove group':
|
77
|
-
buttonLabel = 'Clear All';
|
78
|
-
break;
|
79
84
|
}
|
80
|
-
return (React.createElement(React.Fragment, null, (path.length < nestedConditionLimit || title === 'Add rule') && (React.createElement(Button, { onClick: handleOnClick, startIcon: React.createElement(AddRounded, null), sx: {
|
85
|
+
return (React.createElement(React.Fragment, null, !!path.length && (path.length < nestedConditionLimit || title === 'Add rule') && (React.createElement(Button, { onClick: handleOnClick, startIcon: React.createElement(AddRounded, null), sx: {
|
81
86
|
padding: '6px 16px',
|
82
87
|
fontSize: '0.875rem',
|
83
88
|
marginRight: path.length === 0 ? '.5rem' : '0px',
|
@@ -193,7 +198,7 @@ const customSelector = (props) => {
|
|
193
198
|
};
|
194
199
|
return (React.createElement(React.Fragment, null, isTreeViewEnabled ? (React.createElement(PropertyTree, { value: val ?? value, rootObject: object, fetchObject: fetchObject, handleTreePropertySelect: handleTreePropertySelect })) : (React.createElement(Autocomplete, { options: opts, value: val ?? null, getOptionLabel: (option) => {
|
195
200
|
if (typeof option === 'string') {
|
196
|
-
return opts.find((o) => option === o.name)?.label ||
|
201
|
+
return opts.find((o) => option === o.name)?.label || option;
|
197
202
|
}
|
198
203
|
return option.label;
|
199
204
|
}, isOptionEqualToValue: (option, value) => {
|
@@ -207,7 +212,10 @@ const customSelector = (props) => {
|
|
207
212
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
208
213
|
onChange: (event, newValue) => {
|
209
214
|
handleOnChange(newValue?.value.name);
|
210
|
-
}, renderInput: (params) => React.createElement(
|
215
|
+
}, renderInput: (params) => (React.createElement(OverflowTextField, { value: opts.find((o) => value === o.name)?.label || '', ...params, placeholder: placeholder, size: "small", inputProps: {
|
216
|
+
...params.inputProps,
|
217
|
+
'aria-label': placeholder,
|
218
|
+
} })), sx: { width: width, background: readOnly ? '#f4f6f8' : '#fff' }, disableClearable: true, readOnly: readOnly }))));
|
211
219
|
};
|
212
220
|
const customCombinator = (props) => {
|
213
221
|
const { value, handleOnChange, context, level, path } = props;
|
@@ -272,7 +280,7 @@ export const valueEditor = (props) => {
|
|
272
280
|
return ValueEditor(props);
|
273
281
|
};
|
274
282
|
const CriteriaBuilder = (props) => {
|
275
|
-
const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators,
|
283
|
+
const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, disabled, disabledCriteria, hideBorder, presetGroupLabel, customValueEditor, treeViewOpts, disableRegexEscapeChars, } = props;
|
276
284
|
const [query, setQuery] = useState(undefined);
|
277
285
|
const [propertyTreeMap, setPropertyTreeMap] = useState();
|
278
286
|
useEffect(() => {
|
@@ -282,33 +290,41 @@ const CriteriaBuilder = (props) => {
|
|
282
290
|
!isEmpty(treeViewOpts) && updatePropertyTreeMap(updatedQuery);
|
283
291
|
setQuery({
|
284
292
|
...updatedQuery,
|
285
|
-
rules: processRules(updatedQuery.rules),
|
293
|
+
rules: processRules(updatedQuery.rules, true),
|
286
294
|
});
|
287
295
|
}
|
288
296
|
else {
|
289
297
|
setQuery({ combinator: 'and', rules: [] });
|
290
298
|
}
|
291
299
|
}, [originalCriteria]);
|
292
|
-
|
300
|
+
const processRules = (rules, isSavedValue) => {
|
293
301
|
return rules.map((rule) => {
|
294
302
|
if ('rules' in rule) {
|
295
303
|
return {
|
296
304
|
...rule,
|
297
|
-
rules: processRules(rule.rules),
|
305
|
+
rules: processRules(rule.rules, isSavedValue),
|
298
306
|
};
|
299
307
|
}
|
300
308
|
else {
|
301
309
|
const propertyType = properties.find((property) => property.id === rule.field)?.type;
|
310
|
+
let adjustedValue = rule.value;
|
311
|
+
if ((propertyType === 'array' ||
|
312
|
+
((propertyType === 'string' || propertyType === 'richText') &&
|
313
|
+
(rule.operator === 'in' || rule.operator === 'notIn'))) &&
|
314
|
+
isSavedValue) {
|
315
|
+
adjustedValue = rule.value?.split(',');
|
316
|
+
}
|
317
|
+
else if ((rule.operator === 'null' || rule.operator === 'notNull') && rule.value) {
|
318
|
+
adjustedValue = null;
|
319
|
+
}
|
302
320
|
return {
|
303
321
|
...rule,
|
304
|
-
|
305
|
-
|
306
|
-
? rule.value?.split(',')
|
307
|
-
: rule.value,
|
322
|
+
operator: propertyType === 'array' && rule.operator === '=' ? 'in' : rule.operator,
|
323
|
+
value: adjustedValue,
|
308
324
|
};
|
309
325
|
}
|
310
326
|
});
|
311
|
-
}
|
327
|
+
};
|
312
328
|
// this retrieves the properties from a treeview for each property in the query
|
313
329
|
// they are then used in the custom query builder components to determine the input type etc
|
314
330
|
const updatePropertyTreeMap = (q) => {
|
@@ -334,9 +350,31 @@ const CriteriaBuilder = (props) => {
|
|
334
350
|
setPropertyTreeMap(tempPropertyMap);
|
335
351
|
});
|
336
352
|
};
|
353
|
+
const handleClearAll = () => {
|
354
|
+
handleQueryChange({ combinator: 'and', rules: [] });
|
355
|
+
};
|
356
|
+
const handleAddRule = () => {
|
357
|
+
if (query) {
|
358
|
+
const newQuery = add(query, { field: '', operator: '', value: '' }, []);
|
359
|
+
setQuery(newQuery);
|
360
|
+
}
|
361
|
+
};
|
362
|
+
const handleAddGroup = () => {
|
363
|
+
if (query) {
|
364
|
+
const newQuery = add(query, {
|
365
|
+
combinator: 'and',
|
366
|
+
rules: [{ field: '', operator: '', value: '' }],
|
367
|
+
}, []);
|
368
|
+
setQuery(newQuery);
|
369
|
+
}
|
370
|
+
};
|
337
371
|
const handleQueryChange = (q) => {
|
338
|
-
|
339
|
-
|
372
|
+
const processedQuery = {
|
373
|
+
...q,
|
374
|
+
rules: processRules(q.rules, false),
|
375
|
+
};
|
376
|
+
setQuery(processedQuery);
|
377
|
+
const newCriteria = JSON.parse(formatQuery(processedQuery, {
|
340
378
|
format: 'mongodb',
|
341
379
|
ruleProcessor: (rule, options) => {
|
342
380
|
let newRule = rule;
|
@@ -352,16 +390,12 @@ const CriteriaBuilder = (props) => {
|
|
352
390
|
return defaultRuleProcessorMongoDB(newRule, options);
|
353
391
|
},
|
354
392
|
}));
|
355
|
-
|
356
|
-
|
357
|
-
// since the Add Condition / Add Group buttons add rules with all the fields empty,
|
358
|
-
// we need to check if the first rule was added because q will still parse to { $and: [{ $expr: true }] }
|
359
|
-
const firstRuleAdded = isEmpty(criteria) && q.rules.length > 0;
|
360
|
-
if (allRulesDeleted && !firstRuleAdded) {
|
361
|
-
setCriteria(undefined);
|
393
|
+
if (!isEmpty(difference(newCriteria, { $and: [{ $expr: true }] }))) {
|
394
|
+
setCriteria(newCriteria);
|
362
395
|
}
|
363
396
|
else {
|
364
|
-
|
397
|
+
if (q.rules.length === 0)
|
398
|
+
setCriteria(undefined);
|
365
399
|
}
|
366
400
|
};
|
367
401
|
const fields = useMemo(() => {
|
@@ -424,7 +458,9 @@ const CriteriaBuilder = (props) => {
|
|
424
458
|
'.ruleGroup .ruleGroup': { borderStyle: 'solid' },
|
425
459
|
} },
|
426
460
|
React.createElement(QueryBuilderMaterial, null,
|
427
|
-
React.createElement(QueryBuilder, { query: !criteria && !originalCriteria
|
461
|
+
React.createElement(QueryBuilder, { query: !criteria && !originalCriteria && query.rules.length === 0
|
462
|
+
? { combinator: 'and', rules: [] }
|
463
|
+
: query, fields: fields, onQueryChange: (q) => {
|
428
464
|
handleQueryChange(q);
|
429
465
|
}, onAddRule: (rule) => {
|
430
466
|
// overrides new rule and sets up an empty rule with all three fields empty
|
@@ -461,9 +497,9 @@ const CriteriaBuilder = (props) => {
|
|
461
497
|
ruleGroup: CustomRuleGroup,
|
462
498
|
removeGroupAction: customDelete,
|
463
499
|
removeRuleAction: customDelete,
|
464
|
-
valueEditor: valueEditor,
|
500
|
+
valueEditor: customValueEditor ? customValueEditor.component : valueEditor,
|
465
501
|
}, context: {
|
466
|
-
|
502
|
+
...(customValueEditor?.props ?? {}),
|
467
503
|
presetValues,
|
468
504
|
enablePresetValues,
|
469
505
|
presetGroupLabel,
|
@@ -483,7 +519,43 @@ const CriteriaBuilder = (props) => {
|
|
483
519
|
ruleGroup: 'container',
|
484
520
|
}, operators: operators
|
485
521
|
? ALL_OPERATORS.filter((o) => operators.includes(o.name))
|
486
|
-
: ALL_OPERATORS }))
|
522
|
+
: ALL_OPERATORS })),
|
523
|
+
React.createElement(Box, { sx: {
|
524
|
+
display: 'flex',
|
525
|
+
justifyContent: 'space-between',
|
526
|
+
alignItems: 'center',
|
527
|
+
marginBottom: '10px',
|
528
|
+
maxWidth: '71vw',
|
529
|
+
} },
|
530
|
+
React.createElement(Box, null,
|
531
|
+
React.createElement(Button, { sx: {
|
532
|
+
backgroundColor: 'rgba(0, 117, 167, 0.08)',
|
533
|
+
color: '#0075A7',
|
534
|
+
marginLeft: '10px',
|
535
|
+
'&:hover': {
|
536
|
+
backgroundColor: 'rgba(0, 117, 167, 0.08)',
|
537
|
+
},
|
538
|
+
...styles.buttons,
|
539
|
+
}, startIcon: React.createElement(AddRounded, null), onClick: handleAddRule }, "Add Condition"),
|
540
|
+
React.createElement(Button, { sx: {
|
541
|
+
backgroundColor: '#f6f7f8',
|
542
|
+
color: '#000',
|
543
|
+
marginLeft: '8px',
|
544
|
+
'&:hover': {
|
545
|
+
backgroundColor: '#f6f7f8',
|
546
|
+
},
|
547
|
+
...styles.buttons,
|
548
|
+
}, startIcon: React.createElement(AddRounded, null), onClick: handleAddGroup, title: "Add a rule at the bottom of the group" }, "Add Condition Group")),
|
549
|
+
React.createElement(Button, { variant: 'text', sx: {
|
550
|
+
justifyContent: 'flex-end',
|
551
|
+
color: '#000',
|
552
|
+
fontWeight: 500,
|
553
|
+
paddingLeft: '0px',
|
554
|
+
'&:hover': {
|
555
|
+
backgroundColor: 'transparent',
|
556
|
+
},
|
557
|
+
...styles.buttons,
|
558
|
+
}, onClick: handleClearAll, title: "Clear all conditions", disabled: isEmpty(query.rules) }, "Clear all"))));
|
487
559
|
}
|
488
560
|
return React.createElement(React.Fragment, null);
|
489
561
|
};
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { ChevronRight, ExpandMore } from '@mui/icons-material';
|
2
2
|
import React, { useEffect, useState } from 'react';
|
3
|
-
import { Autocomplete, MenuItem,
|
3
|
+
import { Autocomplete, MenuItem, TreeView } from '../../core';
|
4
|
+
import { OverflowTextField } from '../OverflowTextField';
|
4
5
|
import PropertyTreeItem from './PropertyTreeItem';
|
5
6
|
import { fetchDisplayNamePath, findPropertyById, setIdPaths, truncateNamePath, updateTreeNode } from './utils';
|
6
7
|
const PropertyTree = ({ fetchObject, handleTreePropertySelect, rootObject, value }) => {
|
@@ -126,15 +127,8 @@ const PropertyTree = ({ fetchObject, handleTreePropertySelect, rootObject, value
|
|
126
127
|
: objectPropertyNamePathMap[option.value] ?? '';
|
127
128
|
return truncateNamePath(namePath, NAME_PATH_LIMIT);
|
128
129
|
}, renderInput: (params) => {
|
129
|
-
|
130
|
-
|
131
|
-
let displayValue = fullDisplayValue;
|
132
|
-
if (!!displayValue && displayValue.length > NAME_PATH_LIMIT) {
|
133
|
-
isTruncated = true;
|
134
|
-
displayValue = truncateNamePath(displayValue, NAME_PATH_LIMIT);
|
135
|
-
}
|
136
|
-
return (React.createElement(Tooltip, { title: isTruncated ? fullDisplayValue : '', arrow: true },
|
137
|
-
React.createElement(TextField, { ...params, "aria-label": fullDisplayValue, value: displayValue, size: "small", placeholder: "Select a property", variant: "outlined" })));
|
130
|
+
const fullDisplayName = value && objectPropertyNamePathMap[value];
|
131
|
+
return (React.createElement(OverflowTextField, { ...params, "aria-label": fullDisplayName, value: fullDisplayName, size: "small", placeholder: "Select a property", variant: "outlined" }));
|
138
132
|
}, isOptionEqualToValue: (option, val) => {
|
139
133
|
if (typeof val === 'string') {
|
140
134
|
return option.value === val;
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import { Instant, LocalDate, LocalDateTime, LocalTime, ZoneId } from '@js-joda/core';
|
2
2
|
import { ClearRounded } from '@mui/icons-material';
|
3
3
|
import { Box, darken, lighten, styled } from '@mui/material';
|
4
|
-
import {
|
5
|
-
import React, { useRef, useState } from 'react';
|
6
|
-
import { Autocomplete, Chip, DatePicker, LocalizationProvider, Menu, MenuItem, TextField, Typography, } from '../../core';
|
4
|
+
import { TimePicker } from '@mui/x-date-pickers';
|
5
|
+
import React, { useEffect, useRef, useState } from 'react';
|
6
|
+
import { Autocomplete, Chip, DatePicker, DateTimePicker, LocalizationProvider, Menu, MenuItem, TextField, Typography, } from '../../core';
|
7
7
|
import { NumericFormat } from '../FormField/InputFieldComponent';
|
8
8
|
const GroupHeader = styled('div')(({ theme }) => ({
|
9
9
|
position: 'sticky',
|
@@ -18,7 +18,7 @@ const GroupHeader = styled('div')(({ theme }) => ({
|
|
18
18
|
}));
|
19
19
|
const GroupItems = styled('ul')({ padding: 0 });
|
20
20
|
const ValueEditor = (props) => {
|
21
|
-
const { handleOnChange, value, operator, context, level, rule } = props;
|
21
|
+
const { handleOnChange, value, operator, context, level, rule, fieldData } = props;
|
22
22
|
let inputType = props.inputType;
|
23
23
|
let values = props.values;
|
24
24
|
const property = context.propertyTreeMap?.[rule.field];
|
@@ -47,6 +47,20 @@ const ValueEditor = (props) => {
|
|
47
47
|
readOnly =
|
48
48
|
Object.entries(context.disabledCriteria.criteria).some(([key, value]) => key === rule.field && value === rule.value && rule.operator === '=') && level === context.disabledCriteria.level;
|
49
49
|
}
|
50
|
+
const styles = {
|
51
|
+
input: {
|
52
|
+
width: '33%',
|
53
|
+
background: readOnly ? '#f4f6f8' : '#fff',
|
54
|
+
},
|
55
|
+
};
|
56
|
+
useEffect(() => {
|
57
|
+
if (!['in', 'notIn'].includes(operator) && Array.isArray(value)) {
|
58
|
+
handleOnChange('');
|
59
|
+
}
|
60
|
+
else if (['in', 'notIn'].includes(operator) && !Array.isArray(value)) {
|
61
|
+
handleOnChange([]);
|
62
|
+
}
|
63
|
+
}, [operator]);
|
50
64
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
51
65
|
const onClick = (e) => {
|
52
66
|
// if property is date and date picker is open, don't open preset values
|
@@ -85,11 +99,11 @@ const ValueEditor = (props) => {
|
|
85
99
|
if (inputType === 'date') {
|
86
100
|
// date editor
|
87
101
|
return (React.createElement(LocalizationProvider, null,
|
88
|
-
React.createElement(DatePicker, { inputRef: inputRef, disabled: disabled, value: disabled ? null : value, onChange: handleOnChange, onClose: onClose, renderInput: (params) => (React.createElement(TextField, { ...params, onClick: onClick, placeholder: "Value", size: "small", sx:
|
102
|
+
React.createElement(DatePicker, { inputRef: inputRef, disabled: disabled, value: disabled ? null : value, onChange: handleOnChange, onClose: onClose, renderInput: (params) => (React.createElement(TextField, { ...params, onClick: onClick, placeholder: "Value", size: "small", sx: styles.input })), readOnly: readOnly })));
|
89
103
|
}
|
90
104
|
else if (inputType === 'time') {
|
91
105
|
return (React.createElement(LocalizationProvider, null,
|
92
|
-
React.createElement(TimePicker, { inputRef: inputRef, disabled: disabled, value: disabled || !value ? null : value, onChange: handleOnChange, renderInput: (params) => (React.createElement(TextField, { ...params, onClick: onClick, placeholder: "Value", size: "small", sx:
|
106
|
+
React.createElement(TimePicker, { inputRef: inputRef, disabled: disabled, value: disabled || !value ? null : value, onChange: handleOnChange, renderInput: (params) => (React.createElement(TextField, { ...params, onClick: onClick, placeholder: "Value", size: "small", sx: styles.input })), readOnly: readOnly })));
|
93
107
|
}
|
94
108
|
else if (inputType === 'date-time') {
|
95
109
|
const dateTimeValue = parseISOStringToLocalDateTime(value);
|
@@ -110,7 +124,7 @@ const ValueEditor = (props) => {
|
|
110
124
|
handleOnChange(new Date(localDateTime.toString()).toISOString());
|
111
125
|
}, onClose: onClose, PopperProps: {
|
112
126
|
anchorEl,
|
113
|
-
}, renderInput: (params) => (React.createElement(Box, { sx:
|
127
|
+
}, renderInput: (params) => (React.createElement(Box, { sx: styles.input, ref: setAnchorEl },
|
114
128
|
React.createElement(TextField, { ...params, disabled: disabled, onClick: onClick, placeholder: "Value", size: "small", inputRef: inputRef }))), readOnly: readOnly })));
|
115
129
|
}
|
116
130
|
else if (inputType === 'number' || inputType === 'integer') {
|
@@ -125,7 +139,7 @@ const ValueEditor = (props) => {
|
|
125
139
|
handleOnChange(uniqueSelections.length ? uniqueSelections : '');
|
126
140
|
},
|
127
141
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
128
|
-
isOptionEqualToValue: (option, value) => option === value, renderInput: (params) => (React.createElement(TextField, { label: params.label, ...params, size: "small"
|
142
|
+
isOptionEqualToValue: (option, value) => option === value, renderInput: (params) => (React.createElement(TextField, { label: params.label, ...params, size: "small" })), groupBy: (option) => isPresetValue(option.value?.name) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sx: styles.input, readOnly: readOnly }));
|
129
143
|
}
|
130
144
|
else {
|
131
145
|
return (React.createElement(TextField, { inputRef: inputRef, value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: ['null', 'notNull'].includes(operator), onChange: (e) => {
|
@@ -137,7 +151,7 @@ const ValueEditor = (props) => {
|
|
137
151
|
}
|
138
152
|
}, ...(inputType === 'number'
|
139
153
|
? { InputProps: { inputComponent: NumericFormat } }
|
140
|
-
: { type: 'number' }), placeholder: "Value", size: "small", onClick: onClick, sx:
|
154
|
+
: { type: 'number' }), placeholder: "Value", size: "small", onClick: onClick, sx: styles.input, readOnly: readOnly }));
|
141
155
|
}
|
142
156
|
}
|
143
157
|
else {
|
@@ -147,7 +161,7 @@ const ValueEditor = (props) => {
|
|
147
161
|
...(presetValues?.sort((a, b) => a.label.localeCompare(b.label)) ?? []),
|
148
162
|
];
|
149
163
|
if (isMultiple || values?.length) {
|
150
|
-
return (React.createElement(Autocomplete, { freeSolo: inputType !== 'array' &&
|
164
|
+
return (React.createElement(Autocomplete, { freeSolo: inputType !== 'array' && fieldData.valueEditorType !== 'select', multiple: isMultiple, options: options, value: isMultiple ? (Array.isArray(value) ? value : []) : Array.isArray(value) ? '' : value,
|
151
165
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
152
166
|
onChange: (event, newValue) => {
|
153
167
|
let value;
|
@@ -161,14 +175,25 @@ const ValueEditor = (props) => {
|
|
161
175
|
}
|
162
176
|
handleOnChange(value);
|
163
177
|
}, onBlur: () => {
|
164
|
-
if (inputValue &&
|
178
|
+
if (inputValue &&
|
179
|
+
(options.some((option) => option.name === inputValue) || !options.length) &&
|
180
|
+
(operator === 'in' || operator === 'notIn')) {
|
181
|
+
const newValues = Array.isArray(value) ? [...value, inputValue] : [inputValue];
|
182
|
+
handleOnChange(Array.from(new Set(newValues)));
|
183
|
+
setInputValue('');
|
184
|
+
}
|
185
|
+
}, onKeyDown: (event) => {
|
186
|
+
if (event.key === 'Enter' &&
|
187
|
+
inputValue &&
|
188
|
+
(options.some((option) => option.name === inputValue) || !options.length) &&
|
189
|
+
(operator === 'in' || operator === 'notIn')) {
|
165
190
|
const newValues = Array.isArray(value) ? [...value, inputValue] : [inputValue];
|
166
191
|
handleOnChange(Array.from(new Set(newValues)));
|
167
192
|
setInputValue('');
|
168
193
|
}
|
169
194
|
}, onInputChange: (event, newInputValue) => {
|
170
195
|
setInputValue(newInputValue);
|
171
|
-
}, inputValue: inputValue, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params?.label, ...params, size: "small"
|
196
|
+
}, inputValue: inputValue, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params?.label, ...params, size: "small" })),
|
172
197
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
173
198
|
getOptionLabel: (option) => {
|
174
199
|
if (typeof option === 'string') {
|
@@ -185,10 +210,10 @@ const ValueEditor = (props) => {
|
|
185
210
|
else {
|
186
211
|
return option?.label === value?.label;
|
187
212
|
}
|
188
|
-
}, groupBy: (option) => isPresetValue(option.value?.name) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx:
|
213
|
+
}, groupBy: (option) => isPresetValue(option.value?.name) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx: styles.input, readOnly: readOnly }));
|
189
214
|
}
|
190
215
|
else {
|
191
|
-
return (React.createElement(TextField, { inputRef: inputRef, value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: ['null', 'notNull'].includes(operator), onChange: (e) => handleOnChange(e.target.value), onClick: onClick, placeholder: "Value", size: "small", sx:
|
216
|
+
return (React.createElement(TextField, { inputRef: inputRef, value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: ['null', 'notNull'].includes(operator), onChange: (e) => handleOnChange(e.target.value), onClick: onClick, placeholder: "Value", size: "small", sx: styles.input, readOnly: readOnly }));
|
192
217
|
}
|
193
218
|
}
|
194
219
|
};
|
@@ -1,6 +1,6 @@
|
|
1
|
-
/// <reference types="react" />
|
2
1
|
import { ApiServices, Obj, ObjectInstance, UserAccount } from '@evoke-platform/context';
|
3
2
|
import { ReactComponent } from '@formio/react';
|
3
|
+
import React from 'react';
|
4
4
|
import '../../../../styles/form-component.css';
|
5
5
|
import { Document, ObjectPropertyInputProps } from '../types';
|
6
6
|
type OnSaveResponse = {
|
@@ -34,6 +34,12 @@ export type FormProps = {
|
|
34
34
|
queryAddresses?: unknown;
|
35
35
|
fieldHeight?: 'small' | 'medium';
|
36
36
|
richTextEditor?: typeof ReactComponent;
|
37
|
+
hideButtons?: boolean;
|
38
|
+
formRef?: React.MutableRefObject<FormRef | undefined>;
|
39
|
+
};
|
40
|
+
export type FormRef = {
|
41
|
+
submit: (submission: Record<string, unknown>, type: 'submit' | 'draft', setError: (error?: Record<string, unknown>) => void, setSubmitting?: (value: boolean) => void) => void;
|
42
|
+
data?: Record<string, unknown>;
|
37
43
|
};
|
38
44
|
export declare function Form(props: FormProps): JSX.Element;
|
39
45
|
export default Form;
|