@evoke-platform/ui-components 1.10.0-testing.8 → 1.10.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 (80) hide show
  1. package/dist/published/components/core/Autocomplete/Autocomplete.js +4 -2
  2. package/dist/published/components/core/Autocomplete/Autocomplete.test.js +112 -3
  3. package/dist/published/components/core/TextField/TextField.js +1 -1
  4. package/dist/published/components/core/TextField/TextField.test.js +0 -2
  5. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +25 -3
  6. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.test.d.ts +1 -0
  7. package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.test.js +473 -0
  8. package/dist/published/components/custom/CriteriaBuilder/ValueEditor.js +19 -6
  9. package/dist/published/components/custom/Form/FormComponents/DocumentComponent/Document.js +2 -1
  10. package/dist/published/components/custom/Form/FormComponents/RepeatableFieldComponent/RepeatableField.js +1 -1
  11. package/dist/published/components/custom/Form/tests/Form.test.js +0 -2
  12. package/dist/published/components/custom/FormField/DatePickerSelect/DatePickerSelect.js +36 -7
  13. package/dist/published/components/custom/FormField/DateTimePickerSelect/DateTimePickerSelect.js +14 -1
  14. package/dist/published/components/custom/FormField/FormField.d.ts +3 -1
  15. package/dist/published/components/custom/FormField/FormField.js +17 -5
  16. package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.js +6 -4
  17. package/dist/published/components/custom/FormField/InputFieldComponent/InputFieldComponent.test.js +0 -2
  18. package/dist/published/components/custom/FormField/Select/Select.test.js +0 -2
  19. package/dist/published/components/custom/FormField/TimePickerSelect/TimePickerSelect.js +14 -1
  20. package/dist/published/components/custom/FormV2/FormRenderer.d.ts +2 -1
  21. package/dist/published/components/custom/FormV2/FormRenderer.js +46 -8
  22. package/dist/published/components/custom/FormV2/FormRendererContainer.js +178 -153
  23. package/dist/published/components/custom/FormV2/components/AccordionSections.js +7 -2
  24. package/dist/published/components/custom/FormV2/components/Body.d.ts +1 -1
  25. package/dist/published/components/custom/FormV2/components/DefaultValues.d.ts +2 -2
  26. package/dist/published/components/custom/FormV2/components/DefaultValues.js +36 -28
  27. package/dist/published/components/custom/FormV2/components/FieldWrapper.js +1 -1
  28. package/dist/published/components/custom/FormV2/components/Footer.d.ts +1 -0
  29. package/dist/published/components/custom/FormV2/components/Footer.js +8 -5
  30. package/dist/published/components/custom/FormV2/components/FormContext.d.ts +3 -2
  31. package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.d.ts +9 -0
  32. package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.js +32 -15
  33. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/ActionDialog.js +2 -2
  34. package/dist/published/components/custom/FormV2/components/FormFieldTypes/CollectionFiles/RepeatableField.js +6 -23
  35. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Criteria.js +16 -3
  36. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/Document.js +22 -4
  37. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.d.ts +2 -1
  38. package/dist/published/components/custom/FormV2/components/FormFieldTypes/DocumentFiles/DocumentList.js +16 -3
  39. package/dist/published/components/custom/FormV2/components/FormFieldTypes/Image.js +31 -5
  40. package/dist/published/components/custom/FormV2/components/FormFieldTypes/UserProperty.js +15 -3
  41. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/ObjectPropertyInput.js +115 -87
  42. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.d.ts +2 -3
  43. package/dist/published/components/custom/FormV2/components/FormFieldTypes/relatedObjectFiles/RelatedObjectInstance.js +43 -20
  44. package/dist/published/components/custom/FormV2/components/Header.d.ts +5 -3
  45. package/dist/published/components/custom/FormV2/components/Header.js +47 -9
  46. package/dist/published/components/custom/FormV2/components/PropertyProtection.d.ts +16 -0
  47. package/dist/published/components/custom/FormV2/components/PropertyProtection.js +113 -0
  48. package/dist/published/components/custom/FormV2/components/RecursiveEntryRenderer.js +47 -24
  49. package/dist/published/components/custom/FormV2/components/ValidationFiles/ValidationErrors.js +1 -1
  50. package/dist/published/components/custom/FormV2/components/types.d.ts +2 -0
  51. package/dist/published/components/custom/FormV2/components/utils.d.ts +6 -4
  52. package/dist/published/components/custom/FormV2/components/utils.js +83 -13
  53. package/dist/published/components/custom/FormV2/tests/FormRenderer.test.js +413 -46
  54. package/dist/published/components/custom/FormV2/tests/FormRendererContainer.test.js +983 -16
  55. package/dist/published/components/custom/FormV2/tests/test-data.d.ts +1 -0
  56. package/dist/published/components/custom/FormV2/tests/test-data.js +138 -0
  57. package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.d.ts +3 -0
  58. package/dist/published/components/custom/ViewDetailsV2/InstanceEntryRenderer.js +165 -0
  59. package/dist/published/components/custom/ViewDetailsV2/ViewDetailsV2Container.d.ts +13 -0
  60. package/dist/published/components/custom/ViewDetailsV2/ViewDetailsV2Container.js +144 -0
  61. package/dist/published/components/custom/ViewDetailsV2/index.d.ts +3 -0
  62. package/dist/published/components/custom/ViewDetailsV2/index.js +2 -0
  63. package/dist/published/components/custom/index.d.ts +2 -0
  64. package/dist/published/components/custom/index.js +1 -0
  65. package/dist/published/index.d.ts +6 -6
  66. package/dist/published/index.js +1 -1
  67. package/dist/published/stories/CriteriaBuilder.stories.js +6 -0
  68. package/dist/published/stories/FormRenderer.stories.d.ts +8 -4
  69. package/dist/published/stories/FormRendererContainer.stories.d.ts +26 -0
  70. package/dist/published/stories/FormRendererContainer.stories.js +5 -0
  71. package/dist/published/stories/FormRendererData.d.ts +12 -0
  72. package/dist/published/stories/FormRendererData.js +26 -1
  73. package/dist/published/stories/ViewDetailsV2Container.stories.d.ts +26 -0
  74. package/dist/published/stories/ViewDetailsV2Container.stories.js +37 -0
  75. package/dist/published/stories/ViewDetailsV2Data.d.ts +4 -0
  76. package/dist/published/stories/ViewDetailsV2Data.js +203 -0
  77. package/dist/published/stories/sharedMswHandlers.js +49 -10
  78. package/dist/published/theme/hooks.d.ts +4 -3
  79. package/dist/published/types.d.ts +3 -0
  80. package/package.json +12 -8
@@ -1,5 +1,6 @@
1
1
  import { ExpandMore, InfoRounded } from '@mui/icons-material';
2
2
  import { InputLabel, Autocomplete as MUIAutocomplete } from '@mui/material';
3
+ import { omit } from 'lodash';
3
4
  import React from 'react';
4
5
  import UIThemeProvider from '../../../theme';
5
6
  import FieldError from '../FieldError';
@@ -37,6 +38,7 @@ const Autocomplete = (props) => {
37
38
  return props.instructionText;
38
39
  }
39
40
  };
41
+ const muiAutocompleteProps = omit(props, 'sortBy', 'error', 'errorMessage', 'labelPlacement', 'instructionText');
40
42
  if (!!props.label && props.labelPlacement === 'outside-top') {
41
43
  return (React.createElement(UIThemeProvider, null,
42
44
  React.createElement(InputLabel, { htmlFor: props.id ?? '', sx: { display: 'flex', paddingBottom: '0px', fontSize: '14px' } },
@@ -50,7 +52,7 @@ const Autocomplete = (props) => {
50
52
  color: (theme) => theme.palette.text.secondary,
51
53
  } })))),
52
54
  renderInstructionText(),
53
- React.createElement(MUIAutocomplete, { ...props, sx: {
55
+ React.createElement(MUIAutocomplete, { ...muiAutocompleteProps, sx: {
54
56
  '& fieldset': { borderRadius: '8px', borderColor: props.error ? 'red' : undefined },
55
57
  '& .MuiOutlinedInput-notchedOutline': {
56
58
  border: props.readOnly ? 'none' : 'auto',
@@ -67,7 +69,7 @@ const Autocomplete = (props) => {
67
69
  }
68
70
  else {
69
71
  return (React.createElement(UIThemeProvider, null,
70
- React.createElement(MUIAutocomplete, { ...props, sx: {
72
+ React.createElement(MUIAutocomplete, { ...muiAutocompleteProps, sx: {
71
73
  '& fieldset': { borderRadius: '8px', borderColor: props.error ? 'red' : undefined },
72
74
  '& .MuiOutlinedInput-notchedOutline': {
73
75
  border: props.readOnly ? 'none' : 'auto',
@@ -1,11 +1,120 @@
1
1
  import { render, screen } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
2
3
  import React from 'react';
3
4
  import { it } from 'vitest';
4
5
  import TextField from '../TextField';
5
6
  import Autocomplete from './Autocomplete';
6
- const renderInput = (params) => React.createElement(TextField, { ...params });
7
+ const renderInputFactory = (label) => (params) => React.createElement(TextField, { ...params, label: label });
7
8
  const options = [];
8
- it('renders with label outside outline', () => {
9
- render(React.createElement(Autocomplete, { id: "testinput", labelPlacement: "outside-top", label: "Title", renderInput: renderInput, options: options }));
9
+ it('should render with label outside outline', () => {
10
+ render(React.createElement(Autocomplete, { id: "testinput", labelPlacement: "outside-top", label: "Title", renderInput: renderInputFactory(), options: options }));
10
11
  screen.getByRole('combobox', { name: 'Title' });
11
12
  });
13
+ it('should render label outside outline with asterisk when required', () => {
14
+ render(React.createElement(Autocomplete, { id: "testinput", labelPlacement: "outside-top", label: "Title", renderInput: renderInputFactory(), options: options, required: true }));
15
+ screen.getByRole('combobox', { name: 'Title *' });
16
+ });
17
+ it('should render instruction text when provided when there is an outside-top label', () => {
18
+ render(React.createElement(Autocomplete, { id: "testinput", labelPlacement: "outside-top", label: "Title", instructionText: "This is an instruction", renderInput: renderInputFactory(), options: options }));
19
+ screen.getByText('This is an instruction');
20
+ });
21
+ it('should not render instruction text when there is not an outside-top label', () => {
22
+ render(React.createElement(Autocomplete, { id: "testinput", instructionText: "This is an instruction", renderInput: renderInputFactory(), options: options }));
23
+ const instructionText = screen.queryByText('This is an instruction');
24
+ expect(instructionText).not.toBeInTheDocument();
25
+ });
26
+ it('should render a tooltip if one is provided and there is an outside-top label', async () => {
27
+ const user = userEvent.setup();
28
+ render(React.createElement(Autocomplete, { id: "testinput", labelPlacement: "outside-top", label: "Title", tooltip: "This is a tooltip", renderInput: renderInputFactory(), options: options }));
29
+ expect(screen.queryByText('This is a tooltip')).not.toBeInTheDocument();
30
+ await user.hover(screen.getByLabelText('This is a tooltip'));
31
+ await screen.findByText('This is a tooltip');
32
+ });
33
+ it('should sort options in ascending order if sortBy is ASC', async () => {
34
+ const user = userEvent.setup();
35
+ const unsortedOptions = [
36
+ { label: 'Banana', value: 1 },
37
+ { label: 'Apple', value: 2 },
38
+ { label: 'Cherry', value: 3 },
39
+ ];
40
+ render(React.createElement(Autocomplete, { id: "testinput", sortBy: "ASC", renderInput: renderInputFactory('Fruits'), options: unsortedOptions }));
41
+ const comboBox = screen.getByRole('combobox', { name: 'Fruits' });
42
+ await user.click(comboBox);
43
+ const options = screen.getAllByRole('option');
44
+ const labels = options.map((option) => option.textContent);
45
+ expect(labels).toEqual(['Apple', 'Banana', 'Cherry']);
46
+ });
47
+ it('should sort options in descending order if sortBy is DESC', async () => {
48
+ const user = userEvent.setup();
49
+ const unsortedOptions = [
50
+ { label: 'Banana', value: 1 },
51
+ { label: 'Apple', value: 2 },
52
+ { label: 'Cherry', value: 3 },
53
+ ];
54
+ render(React.createElement(Autocomplete, { id: "testinput", sortBy: "DESC", renderInput: renderInputFactory('Fruits'), options: unsortedOptions }));
55
+ const comboBox = screen.getByRole('combobox', { name: 'Fruits' });
56
+ await user.click(comboBox);
57
+ const options = screen.getAllByRole('option');
58
+ const labels = options.map((option) => option.textContent);
59
+ expect(labels).toEqual(['Cherry', 'Banana', 'Apple']);
60
+ });
61
+ it('should not sort options if sortBy is NONE', async () => {
62
+ const user = userEvent.setup();
63
+ const unsortedOptions = [
64
+ { label: 'Banana', value: 1 },
65
+ { label: 'Apple', value: 2 },
66
+ { label: 'Cherry', value: 3 },
67
+ ];
68
+ render(React.createElement(Autocomplete, { id: "testinput", sortBy: "NONE", renderInput: renderInputFactory('Fruits'), options: unsortedOptions }));
69
+ const comboBox = screen.getByRole('combobox', { name: 'Fruits' });
70
+ await user.click(comboBox);
71
+ const options = screen.getAllByRole('option');
72
+ const labels = options.map((option) => option.textContent);
73
+ expect(labels).toEqual(['Banana', 'Apple', 'Cherry']);
74
+ });
75
+ it('should sort options in ascending order by default', async () => {
76
+ const user = userEvent.setup();
77
+ const unsortedOptions = [
78
+ { label: 'Banana', value: 1 },
79
+ { label: 'Apple', value: 2 },
80
+ { label: 'Cherry', value: 3 },
81
+ ];
82
+ render(React.createElement(Autocomplete, { id: "testinput", renderInput: renderInputFactory('Fruits'), options: unsortedOptions }));
83
+ const comboBox = screen.getByRole('combobox', { name: 'Fruits' });
84
+ await user.click(comboBox);
85
+ const options = screen.getAllByRole('option');
86
+ const labels = options.map((option) => option.textContent);
87
+ expect(labels).toEqual(['Apple', 'Banana', 'Cherry']);
88
+ });
89
+ it('should sort string options', async () => {
90
+ const user = userEvent.setup();
91
+ const unsortedOptions = ['Banana', 'Apple', 'Cherry'];
92
+ render(React.createElement(Autocomplete, { id: "testinput", sortBy: "ASC", renderInput: renderInputFactory('Fruit Options'), options: unsortedOptions }));
93
+ const comboBox = screen.getByRole('combobox', { name: 'Fruit Options' });
94
+ await user.click(comboBox);
95
+ const options = screen.getAllByRole('option');
96
+ const labels = options.map((option) => option.textContent);
97
+ expect(labels).toEqual(['Apple', 'Banana', 'Cherry']);
98
+ });
99
+ it('should render an error when error prop is true', () => {
100
+ render(React.createElement(Autocomplete, { id: "testinput", label: "Title", error: true, errorMessage: "This is an error", labelPlacement: "outside-top", renderInput: renderInputFactory(), options: options }));
101
+ screen.getByText('This is an error');
102
+ });
103
+ it('should show popupIcon when not disabled', () => {
104
+ render(React.createElement(Autocomplete, { id: "testinput", label: "Title", disabled: false, renderInput: renderInputFactory(), options: options }));
105
+ screen.getByTestId('ExpandMoreIcon');
106
+ });
107
+ it('should hide popupIcon when disabled', () => {
108
+ render(React.createElement(Autocomplete, { id: "testinput", label: "Title", disabled: true, renderInput: renderInputFactory(), options: options }));
109
+ const popupIcon = screen.queryByTestId('ExpandMoreIcon');
110
+ expect(popupIcon).not.toBeInTheDocument();
111
+ });
112
+ it('should hide popupIcon when readOnly', () => {
113
+ render(React.createElement(Autocomplete, { id: "testinput", label: "Title", readOnly: true, renderInput: renderInputFactory(), options: options }));
114
+ const popupIcon = screen.queryByTestId('ExpandMoreIcon');
115
+ expect(popupIcon).not.toBeInTheDocument();
116
+ });
117
+ it('should show custom popupIcon when provided', () => {
118
+ render(React.createElement(Autocomplete, { id: "testinput", label: "Title", popupIcon: React.createElement("span", { "data-testid": "custom-icon" }, "^"), renderInput: renderInputFactory(), options: options }));
119
+ screen.getByTestId('custom-icon');
120
+ });
@@ -36,7 +36,7 @@ const TextField = (props) => {
36
36
  ...props.sx,
37
37
  } }),
38
38
  error && React.createElement(FieldError, { required: required, label: errorMessage }))) : (React.createElement(React.Fragment, null,
39
- React.createElement(MUITextField, { inputProps: { readOnly: readOnly, 'aria-readonly': !!readOnly, 'data-testid': 'label-inside' }, ...props, sx: readOnly
39
+ React.createElement(MUITextField, { inputProps: { readOnly: readOnly, 'aria-readonly': !!readOnly, 'data-testid': 'label-inside' }, ...muiProps, sx: readOnly
40
40
  ? { ...readOnlyStyles, ...props.sx }
41
41
  : { '& fieldset': { borderRadius: '8px' }, ...props.sx } }),
42
42
  error && React.createElement(FieldError, { required: required, label: errorMessage })))));
@@ -1,9 +1,7 @@
1
- import * as matchers from '@testing-library/jest-dom/matchers';
2
1
  import { render, screen } from '@testing-library/react';
3
2
  import React from 'react';
4
3
  import { expect, it } from 'vitest';
5
4
  import TextField from './index';
6
- expect.extend(matchers);
7
5
  it('render TextField and check for data-testid === label-outside when labelPlacement === outside-top && variant === outlined', () => {
8
6
  render(React.createElement(TextField, { id: "testinput", labelPlacement: "outside-top", variant: "outlined", label: "Title" }));
9
7
  const textField = screen.getByRole('textbox', { name: 'Title' });
@@ -248,7 +248,7 @@ const customDelete = (props) => {
248
248
  '&:hover': { backgroundColor: 'transparent', boxShadow: 'none' },
249
249
  color: '#212B36',
250
250
  fontWeight: '400',
251
- } }, "Delete group")) : (React.createElement(IconButton, { onClick: handleOnClick, size: "small" },
251
+ } }, "Delete group")) : (React.createElement(IconButton, { onClick: handleOnClick, size: "small", "aria-label": "Delete rule" },
252
252
  React.createElement(TrashCan, { sx: { ':hover': { color: '#637381' } } })))) : (React.createElement(React.Fragment, null));
253
253
  };
254
254
  export const valueEditor = (props) => {
@@ -400,9 +400,31 @@ const CriteriaBuilder = (props) => {
400
400
  const fields = useMemo(() => {
401
401
  return properties
402
402
  .filter(({ type }) => type !== 'collection')
403
- .map((property) => {
403
+ .flatMap((property) => {
404
+ if (property.type === 'object') {
405
+ const result = [
406
+ {
407
+ name: `${property.id}.id`,
408
+ label: `${property.name} ID`,
409
+ inputType: property.type,
410
+ },
411
+ {
412
+ name: `${property.id}.name`,
413
+ label: `${property.name} Name`,
414
+ inputType: property.type,
415
+ },
416
+ ];
417
+ if (!property.objectId) {
418
+ result.push({
419
+ name: `${property.id}.objectId`,
420
+ label: `${property.name} Object ID`,
421
+ inputType: property.type,
422
+ });
423
+ }
424
+ return result;
425
+ }
404
426
  return {
405
- name: property.type === 'object' ? `${property.id}.id` : property.id,
427
+ name: property.id,
406
428
  label: property.name,
407
429
  inputType: property.type,
408
430
  ...(property.enum && {