@evoke-platform/ui-components 1.6.0-dev.21 → 1.6.0-dev.23
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/custom/CriteriaBuilder/CriteriaBuilder.d.ts +3 -2
- package/dist/published/components/custom/CriteriaBuilder/CriteriaBuilder.js +1 -1
- package/dist/published/components/custom/FormField/AddressFieldComponent/AddressFieldComponent.test.js +1 -1
- package/dist/published/components/custom/FormField/FormField.d.ts +2 -3
- package/dist/published/components/custom/FormField/Select/Select.test.js +41 -16
- package/dist/published/components/custom/FormV2/components/FormFieldTypes/AddressFields.js +1 -1
- package/dist/published/components/custom/FormV2/components/ValidationFiles/Validation.js +1 -1
- package/dist/published/components/custom/ResponsiveOverflow/ResponsiveOverflow.js +3 -7
- package/dist/published/stories/FormField.stories.js +1 -2
- package/package.json +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { Property } from '@evoke-platform/context';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import 'react-querybuilder/dist/query-builder.css';
|
|
3
4
|
import { EvokeObject } from '../../../types';
|
|
4
|
-
import {
|
|
5
|
+
import { Operator, PresetValue, TreeViewObject } from './types';
|
|
5
6
|
import { ValueEditorProps } from './ValueEditor';
|
|
6
7
|
export type CriteriaInputProps = {
|
|
7
|
-
properties:
|
|
8
|
+
properties: Property[];
|
|
8
9
|
setCriteria: (criteria?: Record<string, unknown> | undefined) => void;
|
|
9
10
|
criteria?: Record<string, unknown>;
|
|
10
11
|
originalCriteria?: Record<string, unknown>;
|
|
@@ -186,7 +186,7 @@ const customSelector = (props) => {
|
|
|
186
186
|
return opts.find((o) => option === o.name)?.label || option;
|
|
187
187
|
}
|
|
188
188
|
return option.label;
|
|
189
|
-
}, isOptionEqualToValue: (option, value) => {
|
|
189
|
+
}, getOptionKey: (option) => option.name, isOptionEqualToValue: (option, value) => {
|
|
190
190
|
if (typeof option === 'string') {
|
|
191
191
|
return option === value;
|
|
192
192
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { SelectOption } from '@evoke-platform/context';
|
|
1
|
+
import { Property, SelectOption } from '@evoke-platform/context';
|
|
2
2
|
import React, { FocusEventHandler, ReactNode } from 'react';
|
|
3
|
-
import { ObjectProperty } from '../../../types';
|
|
4
3
|
import { AutocompleteOption } from '../../core';
|
|
5
4
|
import { Address } from './AddressFieldComponent/addressFieldComponent';
|
|
6
5
|
export type FormFieldProps = {
|
|
7
6
|
id?: string;
|
|
8
|
-
property:
|
|
7
|
+
property: Property;
|
|
9
8
|
onChange?: Function;
|
|
10
9
|
onBlur?: FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
11
10
|
defaultValue?: unknown;
|
|
@@ -11,23 +11,28 @@ describe('Single select', () => {
|
|
|
11
11
|
const choiceProperty = {
|
|
12
12
|
id: 'selectOptions',
|
|
13
13
|
name: 'Select Options',
|
|
14
|
-
type: '
|
|
14
|
+
type: 'string',
|
|
15
15
|
};
|
|
16
16
|
it('returns selected option', async () => {
|
|
17
17
|
const onChangeMock = vi.fn((name, value, property) => { });
|
|
18
18
|
const user = userEvent.setup();
|
|
19
19
|
const options = ['option 1', 'option 2', 'option 3'];
|
|
20
|
-
render(React.createElement(Select, { id: "testSelect", property: choiceProperty, selectOptions: options, onChange: onChangeMock }));
|
|
20
|
+
render(React.createElement(Select, { id: "testSelect", property: { ...choiceProperty, enum: options }, selectOptions: options, onChange: onChangeMock }));
|
|
21
21
|
const input = screen.getByRole('combobox');
|
|
22
22
|
await user.click(input);
|
|
23
23
|
const option2 = await screen.findByRole('option', { name: 'option 2' });
|
|
24
24
|
await user.click(option2);
|
|
25
|
-
expect(onChangeMock).toBeCalledWith('selectOptions', expect.objectContaining({ label: 'option 2', value: 'option 2' }),
|
|
25
|
+
expect(onChangeMock).toBeCalledWith('selectOptions', expect.objectContaining({ label: 'option 2', value: 'option 2' }), {
|
|
26
|
+
id: 'selectOptions',
|
|
27
|
+
name: 'Select Options',
|
|
28
|
+
type: 'string',
|
|
29
|
+
enum: ['option 1', 'option 2', 'option 3'],
|
|
30
|
+
});
|
|
26
31
|
});
|
|
27
32
|
it('displays matching options', async () => {
|
|
28
33
|
const user = userEvent.setup();
|
|
29
34
|
const options = ['option 1', 'option 2', 'something different'];
|
|
30
|
-
render(React.createElement(Select, { id: "testSelect", property: choiceProperty, selectOptions: options, onChange: () => { } }));
|
|
35
|
+
render(React.createElement(Select, { id: "testSelect", property: { ...choiceProperty, enum: options }, selectOptions: options, onChange: () => { } }));
|
|
31
36
|
const input = screen.getByRole('combobox');
|
|
32
37
|
await user.type(input, 'option');
|
|
33
38
|
await screen.findByRole('option', { name: 'option 1' });
|
|
@@ -40,7 +45,7 @@ describe('Single select', () => {
|
|
|
40
45
|
{ sortBy: 'DESC', expectedValues: ['option 3', 'option 2', 'option 1'] },
|
|
41
46
|
])('shows options in $sortBy order as dropdown display', async ({ sortBy, expectedValues }) => {
|
|
42
47
|
const options = ['option 2', 'option 1', 'option 3'];
|
|
43
|
-
render(React.createElement(Select, { id: "testSelect", property: choiceProperty, selectOptions: options, displayOption: 'dropdown', sortBy: sortBy, onChange: vi.fn() }));
|
|
48
|
+
render(React.createElement(Select, { id: "testSelect", property: { ...choiceProperty, enum: options }, selectOptions: options, displayOption: 'dropdown', sortBy: sortBy, onChange: vi.fn() }));
|
|
44
49
|
const user = userEvent.setup();
|
|
45
50
|
const input = screen.getByRole('combobox');
|
|
46
51
|
await user.click(input);
|
|
@@ -52,7 +57,7 @@ describe('Single select', () => {
|
|
|
52
57
|
const onChangeMock = vi.fn((name, value, property) => { });
|
|
53
58
|
const user = userEvent.setup();
|
|
54
59
|
const options = ['option 1', 'option 2', 'option 3'];
|
|
55
|
-
render(React.createElement(Select, { id: "testSelect", property: choiceProperty, selectOptions: options, onChange: onChangeMock, isCombobox: true }));
|
|
60
|
+
render(React.createElement(Select, { id: "testSelect", property: { ...choiceProperty, enum: options }, selectOptions: options, onChange: onChangeMock, isCombobox: true }));
|
|
56
61
|
const input = screen.getByRole('combobox');
|
|
57
62
|
await user.click(input);
|
|
58
63
|
// Verify the instruction text for a combobox displays as the sub-header of the combobox.
|
|
@@ -61,7 +66,12 @@ describe('Single select', () => {
|
|
|
61
66
|
// Verify the option to add the custom value is displayed as an available option in the dropdown.
|
|
62
67
|
const customOption = await screen.findByRole('option', { name: 'Add "custom option"' });
|
|
63
68
|
await user.click(customOption);
|
|
64
|
-
expect(onChangeMock).toBeCalledWith('selectOptions', expect.objectContaining({ label: 'Add "custom option"', value: 'custom option' }),
|
|
69
|
+
expect(onChangeMock).toBeCalledWith('selectOptions', expect.objectContaining({ label: 'Add "custom option"', value: 'custom option' }), {
|
|
70
|
+
id: 'selectOptions',
|
|
71
|
+
name: 'Select Options',
|
|
72
|
+
type: 'string',
|
|
73
|
+
enum: ['option 1', 'option 2', 'option 3'],
|
|
74
|
+
});
|
|
65
75
|
});
|
|
66
76
|
});
|
|
67
77
|
describe('Multi select', () => {
|
|
@@ -76,7 +86,7 @@ describe('Multi select', () => {
|
|
|
76
86
|
const user = userEvent.setup();
|
|
77
87
|
const onChangeMock = vi.fn((name, value, property) => { });
|
|
78
88
|
const options = ['option 1', 'option 2', 'option 3'];
|
|
79
|
-
render(React.createElement(Select, { id: "testSelect", property: multiChoiceProperty, selectOptions: options, onChange: onChangeMock }));
|
|
89
|
+
render(React.createElement(Select, { id: "testSelect", property: { ...multiChoiceProperty, enum: options }, selectOptions: options, onChange: onChangeMock }));
|
|
80
90
|
const input = screen.getByRole('combobox');
|
|
81
91
|
await user.click(input);
|
|
82
92
|
const option2 = await screen.findByRole('option', { name: 'option 2' });
|
|
@@ -86,13 +96,18 @@ describe('Multi select', () => {
|
|
|
86
96
|
const option3 = await screen.findByRole('option', { name: 'option 3' });
|
|
87
97
|
await user.click(option3);
|
|
88
98
|
expect(onChangeMock).toBeCalledTimes(2);
|
|
89
|
-
expect(onChangeMock).lastCalledWith('multiSelect', ['option 2', 'option 3'],
|
|
99
|
+
expect(onChangeMock).lastCalledWith('multiSelect', ['option 2', 'option 3'], {
|
|
100
|
+
id: 'multiSelect',
|
|
101
|
+
name: 'Select Multiple',
|
|
102
|
+
type: 'array',
|
|
103
|
+
enum: ['option 1', 'option 2', 'option 3'],
|
|
104
|
+
});
|
|
90
105
|
});
|
|
91
106
|
it('allows the user to enter custom values if it is combobox component', async () => {
|
|
92
107
|
const onChangeMock = vi.fn((name, value, property) => { });
|
|
93
108
|
const user = userEvent.setup();
|
|
94
109
|
const options = ['option 1', 'option 2', 'option 3'];
|
|
95
|
-
render(React.createElement(Select, { id: "multiSelect", property: multiChoiceProperty, selectOptions: options, onChange: onChangeMock, isCombobox: true }));
|
|
110
|
+
render(React.createElement(Select, { id: "multiSelect", property: { ...multiChoiceProperty, enum: options }, selectOptions: options, onChange: onChangeMock, isCombobox: true }));
|
|
96
111
|
const input = screen.getByRole('combobox');
|
|
97
112
|
await user.click(input);
|
|
98
113
|
// Verify the instruction text for a combobox displays as the sub-header of the combobox.
|
|
@@ -104,13 +119,18 @@ describe('Multi select', () => {
|
|
|
104
119
|
const customOption2 = await screen.findByRole('option', { name: 'Add "custom option 2"' });
|
|
105
120
|
await user.click(customOption2);
|
|
106
121
|
expect(onChangeMock).toBeCalledTimes(2);
|
|
107
|
-
expect(onChangeMock).lastCalledWith('multiSelect', ['custom option 1', 'custom option 2'],
|
|
122
|
+
expect(onChangeMock).lastCalledWith('multiSelect', ['custom option 1', 'custom option 2'], {
|
|
123
|
+
id: 'multiSelect',
|
|
124
|
+
name: 'Select Multiple',
|
|
125
|
+
type: 'array',
|
|
126
|
+
enum: ['option 1', 'option 2', 'option 3'],
|
|
127
|
+
});
|
|
108
128
|
});
|
|
109
129
|
it('allows the user to enter custom values in conjunction with the predefined options if it is combobox component', async () => {
|
|
110
130
|
const onChangeMock = vi.fn((name, value, property) => { });
|
|
111
131
|
const user = userEvent.setup();
|
|
112
132
|
const options = ['option 1', 'option 2', 'option 3'];
|
|
113
|
-
render(React.createElement(Select, { id: "multiSelect", property: multiChoiceProperty, selectOptions: options, onChange: onChangeMock, isCombobox: true }));
|
|
133
|
+
render(React.createElement(Select, { id: "multiSelect", property: { ...multiChoiceProperty, enum: options }, selectOptions: options, onChange: onChangeMock, isCombobox: true }));
|
|
114
134
|
const input = screen.getByRole('combobox');
|
|
115
135
|
await user.click(input);
|
|
116
136
|
// Verify the instruction text for a combobox displays as the sub-header of the combobox.
|
|
@@ -122,14 +142,19 @@ describe('Multi select', () => {
|
|
|
122
142
|
const option1 = await screen.findByRole('option', { name: 'option 1' });
|
|
123
143
|
await user.click(option1);
|
|
124
144
|
expect(onChangeMock).toBeCalledTimes(2);
|
|
125
|
-
expect(onChangeMock).lastCalledWith('multiSelect', ['custom option 1', 'option 1'],
|
|
145
|
+
expect(onChangeMock).lastCalledWith('multiSelect', ['custom option 1', 'option 1'], {
|
|
146
|
+
id: 'multiSelect',
|
|
147
|
+
name: 'Select Multiple',
|
|
148
|
+
type: 'array',
|
|
149
|
+
enum: ['option 1', 'option 2', 'option 3'],
|
|
150
|
+
});
|
|
126
151
|
});
|
|
127
152
|
});
|
|
128
153
|
describe('Radio Single select', () => {
|
|
129
154
|
const choiceProperty = {
|
|
130
155
|
id: 'selectOptions',
|
|
131
156
|
name: 'Select Options',
|
|
132
|
-
type: '
|
|
157
|
+
type: 'string',
|
|
133
158
|
};
|
|
134
159
|
it('returns selected radio option', async () => {
|
|
135
160
|
const user = userEvent.setup();
|
|
@@ -146,7 +171,7 @@ describe('Radio Single select', () => {
|
|
|
146
171
|
{ sortBy: 'DESC', expectedValues: ['option 3', 'option 2', 'option 1'] },
|
|
147
172
|
])('shows options in $sortBy order as radio display', async ({ sortBy, expectedValues }) => {
|
|
148
173
|
const options = ['option 2', 'option 1', 'option 3'];
|
|
149
|
-
render(React.createElement(Select, { id: "testSelect", property: choiceProperty, selectOptions: options, displayOption: 'radioButton', sortBy: sortBy, onChange: vi.fn() }));
|
|
174
|
+
render(React.createElement(Select, { id: "testSelect", property: { ...choiceProperty, enum: options }, selectOptions: options, displayOption: 'radioButton', sortBy: sortBy, onChange: vi.fn() }));
|
|
150
175
|
const radioButtons = screen.getAllByRole('radio');
|
|
151
176
|
const radioValues = radioButtons.map((radioButton) => radioButton.value);
|
|
152
177
|
expect(radioValues).toEqual(expectedValues);
|
|
@@ -154,7 +179,7 @@ describe('Radio Single select', () => {
|
|
|
154
179
|
it('renders an "Other" option in the radio group if the component is configured to support a custom value', async () => {
|
|
155
180
|
const onChangeMock = vi.fn((name, value, property) => { });
|
|
156
181
|
const options = ['option 1', 'option 2', 'option 3'];
|
|
157
|
-
render(React.createElement(Select, { id: "testSelect", property: choiceProperty, selectOptions: options, displayOption: 'radioButton', sortBy: 'ASC', onChange: onChangeMock, isCombobox: true }));
|
|
182
|
+
render(React.createElement(Select, { id: "testSelect", property: { ...choiceProperty, enum: options }, selectOptions: options, displayOption: 'radioButton', sortBy: 'ASC', onChange: onChangeMock, isCombobox: true }));
|
|
158
183
|
await screen.findByRole('radio', { name: 'Other' });
|
|
159
184
|
});
|
|
160
185
|
it('renders a text field for a custom option if the "Other" option is selected', async () => {
|
|
@@ -39,7 +39,7 @@ function AddressFields(props) {
|
|
|
39
39
|
};
|
|
40
40
|
const addressErrors = errors?.[addressObject];
|
|
41
41
|
const addressFieldError = addressErrors?.[addressField];
|
|
42
|
-
return (React.createElement(FieldWrapper, { inputId: entryId, inputType: "string", label: display?.label || 'default', description: !readOnly ? display?.description : undefined, tooltip: display?.tooltip, value: fieldValue, maxLength: 'maxLength' in validation ? validation?.maxLength : 0, required:
|
|
42
|
+
return (React.createElement(FieldWrapper, { inputId: entryId, inputType: "string", label: display?.label || 'default', description: !readOnly ? display?.description : undefined, tooltip: display?.tooltip, value: fieldValue, maxLength: 'maxLength' in validation ? validation?.maxLength : 0, required: entry.display?.required || false, showCharCount: !readOnly && display?.charCount, viewOnly: !!readOnly, prefix: display?.prefix, suffix: display?.suffix }, !readOnly ? (React.createElement(FormField, { property: fieldDefinition, defaultValue: fieldValue, onChange: handleAddressChange, isMultiLineText: !!display?.rowCount, readOnly: entry.type === 'readonlyField', ...(addressField === 'line1' && { queryAddresses }), mask: validation?.mask, placeholder: display?.placeholder, isOptionEqualToValue: isOptionEqualToValue, size: fieldHeight, error: !!addressFieldError, errorMessage: addressFieldError?.message, additionalProps: {
|
|
43
43
|
...(display?.description && {
|
|
44
44
|
inputProps: {
|
|
45
45
|
'aria-describedby': `${entryId}-description`,
|
|
@@ -39,7 +39,7 @@ export const handleValidation = (entries, register, formValues, parameters, inst
|
|
|
39
39
|
const errorMsg = validation?.errorMessage;
|
|
40
40
|
const validationRules = {};
|
|
41
41
|
// Required fields
|
|
42
|
-
if (
|
|
42
|
+
if (display?.required) {
|
|
43
43
|
validationRules.required = `${fieldName} is required`;
|
|
44
44
|
}
|
|
45
45
|
if (parameter?.type === 'boolean' && parameter?.strictlyTrue) {
|
|
@@ -60,21 +60,17 @@ export const ResponsiveOverflow = (props) => {
|
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
62
|
const availableWidth = containerRef.current.getBoundingClientRect().width;
|
|
63
|
+
const moreButtonWidth = moreButtonBoxRef.current?.getBoundingClientRect().width ?? 0;
|
|
63
64
|
let usedWidth = 0;
|
|
64
65
|
let maxFit = children.length;
|
|
65
|
-
// Determine which items fit
|
|
66
|
+
// Determine which items fit, accounting for overflow button width
|
|
66
67
|
for (let i = 0; i < itemRefs.current.length; i++) {
|
|
67
68
|
const item = itemRefs.current[i];
|
|
68
69
|
if (!item) {
|
|
69
70
|
continue;
|
|
70
71
|
}
|
|
71
72
|
const itemWidth = item.getBoundingClientRect().width;
|
|
72
|
-
|
|
73
|
-
const remainingItems = itemRefs.current.length - i - 1;
|
|
74
|
-
const moreButtonWidth = remainingItems > 0 && moreButtonBoxRef.current
|
|
75
|
-
? moreButtonBoxRef.current.getBoundingClientRect().width
|
|
76
|
-
: 0;
|
|
77
|
-
if (usedWidth + itemWidth + (remainingItems > 0 ? moreButtonWidth : 0) > availableWidth) {
|
|
73
|
+
if (usedWidth + itemWidth + moreButtonWidth > availableWidth) {
|
|
78
74
|
maxFit = i;
|
|
79
75
|
break;
|
|
80
76
|
}
|