@evoke-platform/ui-components 1.4.0-testing.9 → 1.5.0-dev.0

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 (52) hide show
  1. package/dist/published/components/core/DatePicker/DatePicker.js +1 -1
  2. package/dist/published/components/core/List/ListItemIcon/ListItemIcon.d.ts +4 -0
  3. package/dist/published/components/core/List/ListItemIcon/ListItemIcon.js +6 -0
  4. package/dist/published/components/core/List/ListItemIcon/index.d.ts +3 -0
  5. package/dist/published/components/core/List/ListItemIcon/index.js +3 -0
  6. package/dist/published/components/core/List/index.d.ts +2 -1
  7. package/dist/published/components/core/List/index.js +2 -1
  8. package/dist/published/components/core/index.d.ts +4 -2
  9. package/dist/published/components/core/index.js +2 -1
  10. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +66 -51
  11. package/dist/published/components/custom/CriteriaBuilder/PropertyTree.js +1 -1
  12. package/dist/published/components/custom/CriteriaBuilder/ValueEditor.d.ts +2 -3
  13. package/dist/published/components/custom/CriteriaBuilder/ValueEditor.js +89 -71
  14. package/dist/published/components/custom/CriteriaBuilder/utils.js +2 -2
  15. package/dist/published/components/custom/Form/Common/FormComponentWrapper.js +18 -17
  16. package/dist/published/components/custom/Form/FormComponents/CriteriaComponent/Criteria.js +52 -1
  17. package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.d.ts +1 -1
  18. package/dist/published/components/custom/Form/FormComponents/FormFieldComponent.js +7 -10
  19. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/ObjectComponent.js +8 -4
  20. package/dist/published/components/custom/Form/FormComponents/ObjectComponent/RelatedObjectInstance.js +3 -3
  21. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/DocumentViewerCell.d.ts +13 -0
  22. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/DocumentViewerCell.js +115 -0
  23. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableField.js +25 -26
  24. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableFieldComponent.js +1 -1
  25. package/dist/published/components/custom/Form/utils.js +2 -2
  26. package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.js +24 -21
  27. package/dist/published/components/custom/FormField/BooleanSelect/BooleanSelect.test.js +50 -8
  28. package/dist/published/components/custom/FormField/FormField.d.ts +4 -1
  29. package/dist/published/components/custom/FormField/FormField.js +5 -2
  30. package/dist/published/components/custom/HistoryLog/DisplayedProperty.js +1 -1
  31. package/dist/published/components/custom/Menubar/Menubar.d.ts +14 -1
  32. package/dist/published/components/custom/Menubar/Menubar.js +9 -2
  33. package/dist/published/components/custom/Menubar/Menubar.test.js +5 -0
  34. package/dist/published/components/layout/Box/Box.d.ts +3 -3
  35. package/dist/published/components/layout/Box/Box.js +4 -4
  36. package/dist/published/icons/custom/NoNavigation.d.ts +3 -0
  37. package/dist/published/icons/custom/NoNavigation.js +10 -0
  38. package/dist/published/icons/custom/SideNavigation.d.ts +3 -0
  39. package/dist/published/icons/custom/SideNavigation.js +11 -0
  40. package/dist/published/icons/custom/TopNavigation.d.ts +3 -0
  41. package/dist/published/icons/custom/TopNavigation.js +11 -0
  42. package/dist/published/icons/custom/index.d.ts +3 -0
  43. package/dist/published/icons/custom/index.js +3 -0
  44. package/dist/published/index.d.ts +1 -1
  45. package/dist/published/index.js +1 -1
  46. package/dist/published/stories/Box.stories.d.ts +3 -12
  47. package/dist/published/stories/CriteriaBuilder.stories.js +6 -0
  48. package/dist/published/stories/Form.stories.js +7 -2
  49. package/dist/published/stories/FormField.stories.js +2 -0
  50. package/dist/published/stories/MenuBar.stories.js +13 -18
  51. package/dist/published/stories/Palette.stories.d.ts +2 -12
  52. package/package.json +7 -4
@@ -21,7 +21,7 @@ const DatePicker = (props) => {
21
21
  if (newValue instanceof Error) {
22
22
  newValue = new InvalidDate(keyboardInputValue);
23
23
  }
24
- handleChange(newValue, keyboardInputValue);
24
+ handleChange(newValue instanceof InvalidDate || newValue === null ? newValue : LocalDate.from(newValue), keyboardInputValue);
25
25
  };
26
26
  return (React.createElement(UIThemeProvider, null,
27
27
  React.createElement(MUIDatePicker, { value: value, onChange: onChange, renderInput: (params) => React.createElement(TextField, { ...params }), PaperProps: {
@@ -0,0 +1,4 @@
1
+ import { ListItemIconProps } from '@mui/material';
2
+ import React from 'react';
3
+ declare const ListItemIcon: (props: ListItemIconProps) => React.JSX.Element;
4
+ export default ListItemIcon;
@@ -0,0 +1,6 @@
1
+ import { ListItemIcon as MUIListItemIcon } from '@mui/material';
2
+ import React from 'react';
3
+ const ListItemIcon = (props) => {
4
+ return React.createElement(MUIListItemIcon, { ...props });
5
+ };
6
+ export default ListItemIcon;
@@ -0,0 +1,3 @@
1
+ import ListItemIcon from './ListItemIcon';
2
+ export default ListItemIcon;
3
+ export { ListItemIcon };
@@ -0,0 +1,3 @@
1
+ import ListItemIcon from './ListItemIcon';
2
+ export default ListItemIcon;
3
+ export { ListItemIcon };
@@ -1,4 +1,5 @@
1
1
  import List from './List';
2
2
  import ListItem from './ListItem';
3
+ import ListItemIcon from './ListItemIcon';
3
4
  export default List;
4
- export { List, ListItem };
5
+ export { List, ListItem, ListItemIcon };
@@ -1,4 +1,5 @@
1
1
  import List from './List';
2
2
  import ListItem from './ListItem';
3
+ import ListItemIcon from './ListItemIcon';
3
4
  export default List;
4
- export { List, ListItem };
5
+ export { List, ListItem, ListItemIcon };
@@ -24,7 +24,7 @@ export { FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel } f
24
24
  export { IconButton } from './IconButton';
25
25
  export { LinearProgress } from './LinearProgress';
26
26
  export { Link } from './Link';
27
- export { List, ListItem } from './List';
27
+ export { List, ListItem, ListItemIcon } from './List';
28
28
  export { LoadingButton } from './LoadingButton';
29
29
  export * from './LocalizationProvider';
30
30
  export { Menu, MenuItem } from './Menu';
@@ -48,6 +48,8 @@ export { Typography } from './Typography';
48
48
  export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
49
49
  export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
50
50
  export { useGridApiRef } from '@mui/x-data-grid';
51
+ export { TreeItem as RichTreeItem, RichTreeView } from '@mui/x-tree-view';
51
52
  export type { GridSize } from '@mui/material';
52
- export type { GridCellParams, GridColDef, GridEventListener, GridFilterModel, GridInitialState, GridRowParams, GridValueFormatterParams, GridValueGetterParams, } from '@mui/x-data-grid';
53
+ export type { GridCellParams, GridColDef, GridEventListener, GridFilterModel, GridInitialState, GridRowParams, GridSortModel, GridValueFormatterParams, GridValueGetterParams, } from '@mui/x-data-grid';
54
+ export type { TreeItemProps, TreeViewBaseItem } from '@mui/x-tree-view';
53
55
  export type { AutocompleteOption } from './Autocomplete/Autocomplete';
@@ -24,7 +24,7 @@ export { FormControl, FormControlLabel, FormGroup, FormHelperText, FormLabel } f
24
24
  export { IconButton } from './IconButton';
25
25
  export { LinearProgress } from './LinearProgress';
26
26
  export { Link } from './Link';
27
- export { List, ListItem } from './List';
27
+ export { List, ListItem, ListItemIcon } from './List';
28
28
  export { LoadingButton } from './LoadingButton';
29
29
  export * from './LocalizationProvider';
30
30
  export { Menu, MenuItem } from './Menu';
@@ -49,3 +49,4 @@ export { Typography } from './Typography';
49
49
  export { TabContext, TabList, TabPanel, TreeItem, TreeView } from '@mui/lab';
50
50
  export { CardActionArea, CardActions, CardContent, CardHeader, CardMedia, Input, InputAdornment, InputLabel, ListItemButton, ListItemText, SvgIcon, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TableSortLabel, } from '@mui/material';
51
51
  export { useGridApiRef } from '@mui/x-data-grid';
52
+ export { TreeItem as RichTreeItem, RichTreeView } from '@mui/x-tree-view';
@@ -155,7 +155,7 @@ const customSelector = (props) => {
155
155
  }));
156
156
  }
157
157
  else if (inputType === 'integer' || inputType === 'number') {
158
- opts = options.filter((option) => ['=', '!=', '<', '<=', '>', '>=', 'null', 'notNull'].includes(option.name));
158
+ opts = options.filter((option) => ['=', '!=', '<', '<=', '>', '>=', 'null', 'notNull', 'in', 'notIn'].includes(option.name));
159
159
  // checks if it is a single-select property
160
160
  }
161
161
  else if (inputType === 'string' && isArray(props.fieldData?.values)) {
@@ -164,13 +164,13 @@ const customSelector = (props) => {
164
164
  else if (inputType === 'string') {
165
165
  opts = options.filter((option) => !['>', '<', '<=', '>='].includes(option.name));
166
166
  }
167
- else if (inputType === 'image') {
167
+ else if (inputType === 'image' || inputType === 'boolean') {
168
168
  opts = options.filter((option) => ['=', '!=', 'null', 'notNull'].includes(option.name));
169
169
  }
170
170
  break;
171
171
  case 'Fields':
172
172
  placeholder = 'Select Property';
173
- width = '33%';
173
+ width = '37%';
174
174
  val = options.find((option) => option.name === val)?.name;
175
175
  break;
176
176
  }
@@ -266,40 +266,19 @@ export const valueEditor = (props) => {
266
266
  };
267
267
  const CriteriaBuilder = (props) => {
268
268
  const { properties, criteria, setCriteria, originalCriteria, enablePresetValues, presetValues, operators, disabled, disabledCriteria, hideBorder, presetGroupLabel, customValueEditor, treeViewOpts, disableRegexEscapeChars, } = props;
269
- const [query, setQuery] = useState(undefined);
270
269
  const [propertyTreeMap, setPropertyTreeMap] = useState();
271
- useEffect(() => {
272
- if (criteria || originalCriteria) {
273
- const criteriaToParse = criteria || originalCriteria || {};
274
- const updatedQuery = parseMongoDB(criteriaToParse);
275
- !isEmpty(treeViewOpts) && updatePropertyTreeMap(updatedQuery);
276
- setQuery({
277
- ...updatedQuery,
278
- rules: processRules(updatedQuery.rules, true),
279
- });
280
- }
281
- else {
282
- setQuery({ combinator: 'and', rules: [] });
283
- }
284
- }, [originalCriteria]);
285
- const processRules = (rules, isSavedValue) => {
270
+ const processRules = (rules) => {
286
271
  return rules.map((rule) => {
287
272
  if ('rules' in rule) {
288
273
  return {
289
274
  ...rule,
290
- rules: processRules(rule.rules, isSavedValue),
275
+ rules: processRules(rule.rules),
291
276
  };
292
277
  }
293
278
  else {
294
279
  const propertyType = properties.find((property) => property.id === rule.field)?.type;
295
280
  let adjustedValue = rule.value;
296
- if ((propertyType === 'array' ||
297
- ((propertyType === 'string' || propertyType === 'richText') &&
298
- (rule.operator === 'in' || rule.operator === 'notIn'))) &&
299
- isSavedValue) {
300
- adjustedValue = rule.value?.split(',');
301
- }
302
- else if ((rule.operator === 'null' || rule.operator === 'notNull') && rule.value) {
281
+ if ((rule.operator === 'null' || rule.operator === 'notNull') && rule.value) {
303
282
  adjustedValue = null;
304
283
  }
305
284
  return {
@@ -310,31 +289,67 @@ const CriteriaBuilder = (props) => {
310
289
  }
311
290
  });
312
291
  };
313
- // this retrieves the properties from a treeview for each property in the query
314
- // they are then used in the custom query builder components to determine the input type etc
315
- const updatePropertyTreeMap = (q) => {
316
- const ids = [];
317
- const traverseRulesForIds = (rules) => {
318
- rules.forEach((rule) => {
319
- if ('rules' in rule) {
320
- traverseRulesForIds(rule.rules);
321
- }
322
- else {
323
- ids.push(rule.field);
292
+ useEffect(() => {
293
+ if ((criteria || originalCriteria) &&
294
+ !isEmpty(treeViewOpts) &&
295
+ treeViewOpts.object &&
296
+ treeViewOpts.fetchObject) {
297
+ const { object, fetchObject } = treeViewOpts;
298
+ // this retrieves the properties from a treeview for each property in the query
299
+ // they are then used in the custom query builder components to determine the input type etc
300
+ const updatePropertyTreeMap = async () => {
301
+ const newQuery = parseMongoDB(criteria || originalCriteria || {});
302
+ const ids = [];
303
+ const traverseRulesForIds = (rules) => {
304
+ rules.forEach((rule) => {
305
+ if ('rules' in rule) {
306
+ traverseRulesForIds(rule.rules);
307
+ }
308
+ else {
309
+ ids.push(rule.field);
310
+ }
311
+ });
312
+ };
313
+ traverseRulesForIds(newQuery.rules);
314
+ let newPropertyTreeMap = {};
315
+ const newPropertyTreeMapPromises = [];
316
+ for (const id of ids) {
317
+ if (!propertyTreeMap?.[id]) {
318
+ newPropertyTreeMapPromises.push(traversePropertyPath(id, object, fetchObject)
319
+ .then((property) => {
320
+ if (property) {
321
+ return {
322
+ [id]: property,
323
+ };
324
+ }
325
+ return {};
326
+ })
327
+ .catch((err) => {
328
+ console.error(err);
329
+ return {};
330
+ }));
331
+ }
324
332
  }
325
- });
326
- };
327
- traverseRulesForIds(q.rules);
328
- const tempPropertyMap = { ...propertyTreeMap };
329
- ids.forEach(async (id) => {
330
- if (!propertyTreeMap?.[id] && treeViewOpts?.object && treeViewOpts?.fetchObject) {
331
- const prop = await traversePropertyPath(id, treeViewOpts?.object, treeViewOpts?.fetchObject);
332
- if (prop)
333
- tempPropertyMap[id] = prop;
333
+ newPropertyTreeMap = (await Promise.all(newPropertyTreeMapPromises)).reduce((acc, currentProperty) => ({ ...acc, ...currentProperty }), {});
334
+ setPropertyTreeMap((prevPropertyTreeMap) => ({
335
+ ...prevPropertyTreeMap,
336
+ ...newPropertyTreeMap,
337
+ }));
338
+ };
339
+ updatePropertyTreeMap().catch((err) => console.error(err));
340
+ }
341
+ }, [criteria, originalCriteria, treeViewOpts]);
342
+ const initializeQuery = () => {
343
+ const criteriaToParse = criteria || originalCriteria;
344
+ const updatedQuery = criteriaToParse ? parseMongoDB(criteriaToParse || {}) : undefined;
345
+ return updatedQuery
346
+ ? {
347
+ ...updatedQuery,
348
+ rules: processRules(updatedQuery.rules),
334
349
  }
335
- setPropertyTreeMap(tempPropertyMap);
336
- });
350
+ : { combinator: 'and', rules: [] };
337
351
  };
352
+ const [query, setQuery] = useState(initializeQuery);
338
353
  const handleClearAll = () => {
339
354
  handleQueryChange({ combinator: 'and', rules: [] });
340
355
  };
@@ -356,7 +371,7 @@ const CriteriaBuilder = (props) => {
356
371
  const handleQueryChange = (q) => {
357
372
  const processedQuery = {
358
373
  ...q,
359
- rules: processRules(q.rules, false),
374
+ rules: processRules(q.rules),
360
375
  };
361
376
  setQuery(processedQuery);
362
377
  const newCriteria = JSON.parse(formatQuery(processedQuery, {
@@ -509,7 +524,7 @@ const CriteriaBuilder = (props) => {
509
524
  justifyContent: 'space-between',
510
525
  alignItems: 'center',
511
526
  marginBottom: '10px',
512
- maxWidth: '71vw',
527
+ width: '100%',
513
528
  } },
514
529
  React.createElement(Box, null,
515
530
  React.createElement(Button, { sx: {
@@ -102,7 +102,7 @@ const PropertyTree = ({ fetchObject, handleTreePropertySelect, rootObject, value
102
102
  }
103
103
  };
104
104
  return (React.createElement(Autocomplete, { "aria-label": "Property Selector", value: value, fullWidth: true, sx: {
105
- width: '33%',
105
+ width: '37%',
106
106
  }, disableClearable: true, options: propertyOptions.map((property) => {
107
107
  return {
108
108
  label: objectPropertyNamePathMap[property.id],
@@ -1,8 +1,7 @@
1
1
  import React from 'react';
2
- import { ValueEditorProps as ValueEditorBaseProps } from 'react-querybuilder';
3
- import { AutocompleteOption } from '../../core';
2
+ import { Option, ValueEditorProps as ValueEditorBaseProps } from 'react-querybuilder';
4
3
  export type ValueEditorProps = ValueEditorBaseProps & {
5
- values?: AutocompleteOption[] | any[];
4
+ values?: Option[];
6
5
  };
7
6
  declare const ValueEditor: (props: ValueEditorProps) => React.JSX.Element;
8
7
  export default ValueEditor;
@@ -1,8 +1,8 @@
1
1
  import { Instant, LocalDate, LocalDateTime, LocalTime, ZoneId } from '@js-joda/core';
2
- import { ClearRounded, CodeRounded } from '@mui/icons-material';
3
2
  import { Box, darken, lighten, styled } from '@mui/material';
4
3
  import { TimePicker } from '@mui/x-date-pickers';
5
4
  import React, { useEffect, useRef, useState } from 'react';
5
+ import { ClearRounded, CodeRounded } from '../../../icons';
6
6
  import { InvalidDate } from '../../../util';
7
7
  import { Autocomplete, Chip, DatePicker, DateTimePicker, IconButton, LocalizationProvider, Menu, MenuItem, TextField, Typography, } from '../../core';
8
8
  import { NumericFormat } from '../FormField/InputFieldComponent';
@@ -18,19 +18,22 @@ const GroupHeader = styled('div')(({ theme }) => ({
18
18
  : darken(theme.palette.primary.main, 0.8),
19
19
  }));
20
20
  const GroupItems = styled('ul')({ padding: 0 });
21
+ const isPresetValue = (value) => typeof value === 'string' && value.startsWith('{{{') && value.endsWith('}}}');
21
22
  const ValueEditor = (props) => {
22
23
  const { handleOnChange, value, operator, context, level, rule, fieldData } = props;
23
24
  let inputType = props.inputType;
24
- let values = props.values;
25
+ let values = (props.values ?? [])
26
+ .map((item) => ({
27
+ value: item.name,
28
+ label: item.label,
29
+ }))
30
+ .sort((a, b) => a.label.localeCompare(b.label));
25
31
  const property = context.propertyTreeMap?.[rule.field];
26
32
  // for tree view / related object properties, the properties are stored in the propertyTreeMap upon selection
27
33
  if (!!context.treeViewOpts && !!property) {
28
34
  inputType = property.type;
29
35
  if (property.enum) {
30
- values = property.enum.map((item) => ({
31
- name: item,
32
- label: item,
33
- }));
36
+ values = property.enum.map((item) => ({ value: item, label: item }));
34
37
  }
35
38
  }
36
39
  const [invalidDateTime, setInvalidDateTime] = useState(false);
@@ -40,10 +43,17 @@ const ValueEditor = (props) => {
40
43
  // Manages input value for Autocomplete when using 'in/not in' operators, ensuring correct handling on blur.
41
44
  const [inputValue, setInputValue] = useState('');
42
45
  const disabled = ['null', 'notNull'].includes(operator);
43
- const presetValues = context.presetValues?.filter((val) => !val.type || val.type === inputType) ?? [];
44
- const isPresetValue = (value) => value?.startsWith('{{{') && value?.endsWith('}}}');
45
- const isPresetValueSelected = presetValues && typeof value === 'string' && isPresetValue(value);
46
- const presetDisplayValue = presetValues?.find((option) => option.value.name === value)?.label ?? '';
46
+ const presetValues = context.presetValues
47
+ ?.filter((val) => !val.type || val.type === inputType)
48
+ ?.map((val) => {
49
+ return {
50
+ label: val.label,
51
+ value: val.value?.name,
52
+ sublabel: val.value?.sublabel,
53
+ type: val.type,
54
+ };
55
+ })
56
+ ?.sort((a, b) => a.label.localeCompare(b.label)) ?? [];
47
57
  let readOnly = context.disabled;
48
58
  if (!readOnly && context.disabledCriteria) {
49
59
  readOnly =
@@ -54,16 +64,15 @@ const ValueEditor = (props) => {
54
64
  width: '33%',
55
65
  background: readOnly ? '#f4f6f8' : '#fff',
56
66
  borderRadius: '8px',
57
- '& .MuiAutocomplete-tag': {
58
- backgroundColor: '#edeff1',
59
- },
67
+ '& .MuiAutocomplete-tag': { backgroundColor: '#edeff1' },
60
68
  },
61
69
  };
70
+ const isMultipleOperator = ['in', 'notIn'].includes(operator);
62
71
  useEffect(() => {
63
- if (!['in', 'notIn'].includes(operator) && Array.isArray(value)) {
72
+ if (!isMultipleOperator && Array.isArray(value)) {
64
73
  handleOnChange('');
65
74
  }
66
- else if (['in', 'notIn'].includes(operator) && !Array.isArray(value)) {
75
+ else if (isMultipleOperator && !Array.isArray(value)) {
67
76
  handleOnChange([]);
68
77
  }
69
78
  }, [operator]);
@@ -80,6 +89,7 @@ const ValueEditor = (props) => {
80
89
  };
81
90
  const clearValue = () => {
82
91
  handleOnChange('');
92
+ setInputValue('');
83
93
  };
84
94
  const setPresetValue = (value) => {
85
95
  handleOnChange(value);
@@ -131,9 +141,6 @@ const ValueEditor = (props) => {
131
141
  }
132
142
  }
133
143
  const getEditor = () => {
134
- if (isPresetValueSelected) {
135
- return;
136
- }
137
144
  if (disabled) {
138
145
  return React.createElement(React.Fragment, null);
139
146
  }
@@ -181,24 +188,40 @@ const ValueEditor = (props) => {
181
188
  console.error('Error processing date value:', error);
182
189
  setInvalidDateTime(true);
183
190
  }
184
- }, onClose: onClose, PopperProps: {
185
- anchorEl,
186
- }, renderInput: (params) => (React.createElement(Box, { sx: styles.input, ref: setAnchorEl },
191
+ }, onClose: onClose, PopperProps: { anchorEl }, renderInput: (params) => (React.createElement(Box, { sx: styles.input, ref: setAnchorEl },
187
192
  React.createElement(TextField, { ...params, disabled: disabled, onClick: onClick, placeholder: "Value", size: "small", inputRef: inputRef, error: invalidDateTime }))), readOnly: readOnly })));
188
193
  }
189
194
  else if (inputType === 'number' || inputType === 'integer') {
190
- const isMultiple = ['in', 'notIn'].includes(operator);
191
- const options = presetValues;
192
- if (isMultiple) {
193
- return (React.createElement(Autocomplete, { freeSolo: true, multiple: true, options: options, getOptionLabel: (option) => typeof option === 'object' && option?.label ? option.label : String(option), value: Array.isArray(value) ? (disabled ? [] : value) : [], disabled: disabled,
194
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
195
- onChange: (event, newValue) => {
196
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
197
- const uniqueSelections = newValue.map((item) => item.value ?? Number(item));
198
- handleOnChange(uniqueSelections.length ? uniqueSelections : '');
199
- },
200
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
201
- 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 }));
195
+ if (isMultipleOperator) {
196
+ const options = presetValues;
197
+ return (React.createElement(Autocomplete, { freeSolo: true, multiple: true, options: options, value: Array.isArray(value)
198
+ ? disabled
199
+ ? []
200
+ : value.map((v) => {
201
+ const found = options.find((o) => o.value === v);
202
+ return found ? found : { label: v, value: v };
203
+ })
204
+ : [], disabled: disabled, onChange: (event, newValue) => {
205
+ const uniqueSelections = newValue
206
+ .map((item) => {
207
+ if (typeof item === 'object' && 'value' in item) {
208
+ return item.value;
209
+ }
210
+ else if (typeof item === 'string') {
211
+ if (isPresetValue(item)) {
212
+ return item;
213
+ }
214
+ else if (item.match(/^(\+|-){0,1}\d*(\.\d+)?$/)) {
215
+ const value = Number(item);
216
+ return Number.isNaN(value) ? '' : value;
217
+ }
218
+ return '';
219
+ }
220
+ return item;
221
+ })
222
+ .filter((item) => item !== '');
223
+ handleOnChange(uniqueSelections.length ? Array.from(new Set(uniqueSelections)) : '');
224
+ }, isOptionEqualToValue: (option, value) => option.value === value.value, renderInput: (params) => (React.createElement(TextField, { label: params.label, ...params, size: "small" })), groupBy: (option) => isPresetValue(option.value) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sx: styles.input, readOnly: readOnly }));
202
225
  }
203
226
  else {
204
227
  return (React.createElement(TextField, { inputRef: inputRef, value: ['null', 'notNull'].includes(operator) ? '' : value, disabled: disabled || ['null', 'notNull'].includes(operator), onChange: (e) => {
@@ -213,29 +236,39 @@ const ValueEditor = (props) => {
213
236
  : { type: 'number' }), placeholder: "Value", size: "small", onClick: onClick, sx: styles.input, readOnly: readOnly }));
214
237
  }
215
238
  }
239
+ else if (inputType === 'boolean') {
240
+ const options = [{ label: 'True', value: true }, { label: 'False', value: false }, ...presetValues];
241
+ return (React.createElement(Autocomplete, { options: options, value: options.find((opt) => opt.value === value) ?? value, onChange: (event, newValue) => {
242
+ handleOnChange(newValue ? newValue.value : '');
243
+ }, isOptionEqualToValue: (option, value) => option.value === value.value, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params.label, ...params, size: "small" })), groupBy: (option) => isPresetValue(option.value) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx: styles.input, readOnly: readOnly }));
244
+ }
216
245
  else {
217
- const isMultiple = inputType === 'array' || ['in', 'notIn'].includes(operator);
218
- const options = [
219
- ...(values?.sort((a, b) => a.label.localeCompare(b.label)) ?? []),
220
- ...(presetValues?.sort((a, b) => a.label.localeCompare(b.label)) ?? []),
221
- ];
222
- if (isMultiple || values?.length) {
223
- return (React.createElement(Autocomplete, { freeSolo: inputType !== 'array' && fieldData.valueEditorType !== 'select', multiple: isMultiple, options: options, value: isMultiple ? (Array.isArray(value) ? value : []) : Array.isArray(value) ? '' : value,
224
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
225
- onChange: (event, newValue) => {
246
+ const isMultiple = inputType === 'array' || isMultipleOperator || values?.length;
247
+ if (isMultiple) {
248
+ const options = [...values, ...presetValues];
249
+ return (React.createElement(Autocomplete, { freeSolo: inputType !== 'array' && fieldData.valueEditorType !== 'select', multiple: isMultiple, options: options, value: isMultiple
250
+ ? Array.isArray(value)
251
+ ? value.map((item) => {
252
+ const found = options.find((o) => o.value === item);
253
+ return found ? found : { label: item, value: item };
254
+ })
255
+ : []
256
+ : Array.isArray(value)
257
+ ? ''
258
+ : value, onChange: (event, newValue) => {
226
259
  let value;
227
260
  if (isMultiple) {
228
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
229
- const values = newValue.map((item) => item.name || item.value?.name || item);
261
+ const values = newValue.map((item) => typeof item === 'string' ? item : item.value);
230
262
  value = Array.from(new Set(values));
231
263
  }
232
264
  else {
233
- value = newValue?.name ?? newValue?.value?.name ?? '';
265
+ value =
266
+ typeof newValue === 'string' ? newValue : newValue.value;
234
267
  }
235
268
  handleOnChange(value);
236
269
  }, onBlur: () => {
237
270
  if (inputValue &&
238
- (options.some((option) => option.name === inputValue) || !options.length) &&
271
+ (options.some((option) => option.value === inputValue) || !options.length) &&
239
272
  (operator === 'in' || operator === 'notIn')) {
240
273
  const newValues = Array.isArray(value) ? [...value, inputValue] : [inputValue];
241
274
  handleOnChange(Array.from(new Set(newValues)));
@@ -244,7 +277,7 @@ const ValueEditor = (props) => {
244
277
  }, onKeyDown: (event) => {
245
278
  if (event.key === 'Enter' &&
246
279
  inputValue &&
247
- (options.some((option) => option.name === inputValue) || !options.length) &&
280
+ (options.some((option) => option.value === inputValue) || !options.length) &&
248
281
  (operator === 'in' || operator === 'notIn')) {
249
282
  const newValues = Array.isArray(value) ? [...value, inputValue] : [inputValue];
250
283
  handleOnChange(Array.from(new Set(newValues)));
@@ -252,32 +285,16 @@ const ValueEditor = (props) => {
252
285
  }
253
286
  }, onInputChange: (event, newInputValue) => {
254
287
  setInputValue(newInputValue);
255
- }, inputValue: inputValue, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params?.label, ...params, size: "small" })),
256
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
257
- getOptionLabel: (option) => {
258
- if (typeof option === 'string') {
259
- const found = options.find((o) => option === o.name || option === o.value?.name);
260
- return found?.label || option;
261
- }
262
- return option?.label;
263
- },
264
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
265
- isOptionEqualToValue: (option, value) => {
266
- if (typeof value === 'string') {
267
- return option?.name === value || option?.value?.name === value;
268
- }
269
- else {
270
- return option?.label === value?.label;
271
- }
272
- }, groupBy: (option) => isPresetValue(option.value?.name) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx: styles.input, readOnly: readOnly }));
288
+ }, inputValue: inputValue, renderInput: (params) => (React.createElement(TextField, { inputRef: inputRef, label: params.label, ...params, size: "small" })), isOptionEqualToValue: (option, value) => option?.value === value.value, groupBy: (option) => isPresetValue(option.value) ? context.presetGroupLabel || 'Preset Values' : 'Options', renderGroup: groupRenderGroup, sortBy: "NONE", sx: styles.input, readOnly: readOnly }));
273
289
  }
274
290
  else {
275
291
  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 }));
276
292
  }
277
293
  }
278
294
  };
295
+ const presetDisplayValue = React.useMemo(() => presetValues?.find((option) => option.value === value)?.label || value, [presetValues, value]);
279
296
  return (React.createElement(React.Fragment, null,
280
- isPresetValueSelected ? (React.createElement(Box, { ref: inputRef, sx: {
297
+ isPresetValue(value) ? (React.createElement(Box, { ref: inputRef, sx: {
281
298
  width: '33%',
282
299
  display: 'flex',
283
300
  justifyContent: 'space-between',
@@ -298,10 +315,11 @@ const ValueEditor = (props) => {
298
315
  !readOnly && (React.createElement(IconButton, { onClick: clearValue, sx: { padding: '3px', margin: '3px' } },
299
316
  React.createElement(ClearRounded, { fontSize: "small", sx: { color: 'rgba(0, 0, 0, 0.54)' } }))))) : (getEditor()),
300
317
  !!presetValues?.length && (React.createElement(Menu, { open: openPresetValues, anchorEl: inputRef?.current, PaperProps: { sx: { borderRadius: '8px', width: inputRef?.current?.offsetWidth } }, onClose: onClose }, presetValues &&
301
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
302
- presetValues.map((option) => (React.createElement(MenuItem, { ...props, onClick: () => setPresetValue(option.value.name), sx: { padding: '8px', minHeight: '25px' } },
303
- React.createElement(Box, { padding: 0, margin: 0 },
304
- React.createElement(Typography, { fontSize: '14px', fontWeight: 500, sx: { lineHeight: '20px' } }, option.label),
305
- option.value.sublabel && (React.createElement(Typography, { fontSize: '14px', fontWeight: 500, color: 'rgba(145, 158, 171)', sx: { lineHeight: '20px' } }, option.value.sublabel))))))))));
318
+ presetValues.map((option) => {
319
+ return (React.createElement(MenuItem, { ...props, onClick: () => setPresetValue(option.value), sx: { padding: '8px', minHeight: '25px' } },
320
+ React.createElement(Box, { padding: 0, margin: 0 },
321
+ React.createElement(Typography, { fontSize: '14px', fontWeight: 500, sx: { lineHeight: '20px' } }, option.label),
322
+ !!option.sublabel && (React.createElement(Typography, { fontSize: '14px', fontWeight: 500, color: 'rgba(145, 158, 171)', sx: { lineHeight: '20px' } }, option.sublabel)))));
323
+ })))));
306
324
  };
307
325
  export default ValueEditor;
@@ -246,14 +246,14 @@ export function parseMongoDB(mongoQuery) {
246
246
  return {
247
247
  field: key,
248
248
  operator: 'in',
249
- value: (value.$in || []).join(','),
249
+ value: value.$in ?? [],
250
250
  };
251
251
  }
252
252
  else if ('$nin' in value) {
253
253
  return {
254
254
  field: key,
255
255
  operator: 'notIn',
256
- value: (value.$nin || []).join(','),
256
+ value: value.$nin ?? [],
257
257
  };
258
258
  }
259
259
  else {
@@ -67,25 +67,26 @@ export const FormComponentWrapper = (props) => {
67
67
  charCount = maxLength - charCount;
68
68
  return (React.createElement(Box, null,
69
69
  React.createElement(Box, { sx: { padding: '10px 0' } },
70
- React.createElement(Typography, { variant: "body2", color: viewOnly ? 'textSecondary' : 'textPrimary', component: "label", htmlFor: inputId, sx: { ...(displayOption === 'radioButton' && value && { marginRight: '8px' }) } },
71
- label,
72
- validate.required ? (React.createElement(Typography, { component: 'span', sx: { color: 'red', fontSize: '12px' } },
73
- ` *`,
74
- ' ')) : null,
75
- tooltip && (React.createElement(Tooltip, { placement: "right", title: tooltip },
76
- React.createElement(IconButton, null,
77
- React.createElement(Help, { sx: { fontSize: '14px' } }))))),
78
- displayOption === 'radioButton' && onChange && !viewOnly && !readOnly && value && (React.createElement(Tooltip, { title: `Clear` },
79
- React.createElement("span", null,
80
- React.createElement(IconButton, { "aria-label": `Clear`, sx: { padding: '0px' }, onClick: () => {
81
- property && onChange(property.id, '');
82
- } },
83
- React.createElement(HighlightOffOutlined, { sx: clearBtnStyles }))))),
84
- React.createElement(Box, { sx: { ...(displayOption === 'radioButton' && { display: 'flex' }) } },
85
- React.createElement(Typography, { variant: "caption", sx: descriptionStyles }, description)),
70
+ property?.type !== 'boolean' && (React.createElement(React.Fragment, null,
71
+ React.createElement(Typography, { variant: "body2", color: viewOnly ? 'textSecondary' : 'textPrimary', component: "label", htmlFor: inputId, sx: { ...(displayOption === 'radioButton' && value && { marginRight: '8px' }) } },
72
+ label,
73
+ validate.required ? (React.createElement(Typography, { component: 'span', sx: { color: 'red', fontSize: '12px' } },
74
+ ` *`,
75
+ ' ')) : null,
76
+ tooltip && (React.createElement(Tooltip, { placement: "right", title: tooltip },
77
+ React.createElement(IconButton, null,
78
+ React.createElement(Help, { sx: { fontSize: '14px' } }))))),
79
+ displayOption === 'radioButton' && onChange && !viewOnly && !readOnly && value && (React.createElement(Tooltip, { title: `Clear` },
80
+ React.createElement("span", null,
81
+ React.createElement(IconButton, { "aria-label": `Clear`, sx: { padding: '0px' }, onClick: () => {
82
+ property && onChange(property.id, '');
83
+ } },
84
+ React.createElement(HighlightOffOutlined, { sx: clearBtnStyles }))))),
85
+ React.createElement(Box, { sx: { ...(displayOption === 'radioButton' && { display: 'flex' }) } },
86
+ React.createElement(Typography, { variant: "caption", sx: descriptionStyles }, description)))),
86
87
  React.createElement(Box, { sx: { display: 'flex', flexDirection: 'row' } },
87
88
  React.createElement(PrefixSuffix, { prefix: prefix, height: fieldHeight }),
88
- React.createElement(Box, { sx: { width: '100%', paddingTop: '6px' } }, children),
89
+ React.createElement(Box, { sx: { width: '100%', paddingTop: property?.type !== 'boolean' ? '6px' : undefined } }, children),
89
90
  React.createElement(PrefixSuffix, { suffix: suffix, height: fieldHeight }))),
90
91
  React.createElement(Box, { sx: underFieldStyles },
91
92
  React.createElement(Box, { sx: { width: '100%', display: 'flex', justifyContent: 'space-between' } },