@bytebrand/fe-ui-core 4.2.65 → 4.2.67
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/__tests__/components/_common/MaterialAutocomplete/MaterialAutocomplete.test.tsx +49 -0
- package/__tests__/components/_common/MaterialField/MaterialField.test.tsx +58 -0
- package/package.json +1 -1
- package/source/components/_common/MaterialAutocomplete/MaterialAutocomplete.styled.tsx +8 -8
- package/source/components/_common/MaterialAutocomplete/MaterialAutocomplete.tsx +8 -12
- package/source/components/_common/MaterialField/MaterialField.styled.tsx +6 -6
- package/source/components/_common/MaterialField/MaterialField.tsx +1 -1
- package/source/framework/utils/CommonUtils.ts +12 -0
- package/tsconfig.json +3 -1
- package/tslint.json +0 -1
- package/utils.ts +3 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, fireEvent } from "@testing-library/react";
|
|
3
|
+
import MaterialAutocomplete from "../../../../source/components/_common/MaterialAutocomplete/MaterialAutocomplete";
|
|
4
|
+
let value: any = null;
|
|
5
|
+
const setValue = jest.fn();
|
|
6
|
+
const materialAutocompleteProps = {
|
|
7
|
+
onChange: setValue,
|
|
8
|
+
label: 'test label',
|
|
9
|
+
value: value,
|
|
10
|
+
error: false,
|
|
11
|
+
required: true,
|
|
12
|
+
items: [
|
|
13
|
+
{ value: '+49', label: '+49', icon: 'de' },
|
|
14
|
+
{ value: '+43', label: '+43', icon: 'at' }
|
|
15
|
+
],
|
|
16
|
+
listWithImage: 'true'
|
|
17
|
+
}
|
|
18
|
+
describe('MaterialAutocomplete', () => {
|
|
19
|
+
it('renders component without errors', () => {
|
|
20
|
+
const { container, getByRole, getByText } = render(<MaterialAutocomplete {...materialAutocompleteProps} />)
|
|
21
|
+
expect(container).toBeInTheDocument();
|
|
22
|
+
const input = getByRole('combobox');
|
|
23
|
+
const button = getByRole('button');
|
|
24
|
+
fireEvent.click(button);
|
|
25
|
+
const listItem = getByText('+43');
|
|
26
|
+
fireEvent.click(listItem);
|
|
27
|
+
expect(input).toHaveAttribute('value', '+43');
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('renders component, open list and choose any option from list', () => {
|
|
31
|
+
const { getByRole, getByText } = render(<MaterialAutocomplete {...materialAutocompleteProps} />)
|
|
32
|
+
const input = getByRole('combobox');
|
|
33
|
+
const button = getByRole('button');
|
|
34
|
+
fireEvent.click(button);
|
|
35
|
+
const listItem = getByText('+43');
|
|
36
|
+
fireEvent.click(listItem);
|
|
37
|
+
expect(input).toHaveAttribute('value', '+43');
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('renders component, open list and check if we have icons in list, when "listWithImage: true"', () => {
|
|
41
|
+
const { getByRole, container } = render(<MaterialAutocomplete {...materialAutocompleteProps} />)
|
|
42
|
+
const button = getByRole('button');
|
|
43
|
+
fireEvent.click(button);
|
|
44
|
+
const iconDe = container.querySelector('[id="flag-icons-de"]');
|
|
45
|
+
const iconAt = container.querySelector('[id="flag-icons-at"]');
|
|
46
|
+
expect(iconDe).toBeInTheDocument();
|
|
47
|
+
expect(iconAt).toBeInTheDocument();
|
|
48
|
+
})
|
|
49
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react';
|
|
3
|
+
import MaterialField from '../../../../source/components/_common/MaterialField/MaterialField';
|
|
4
|
+
|
|
5
|
+
describe('MaterialField', () => {
|
|
6
|
+
const props = {
|
|
7
|
+
label: 'Test Label',
|
|
8
|
+
value: 'Test Value',
|
|
9
|
+
onChange: jest.fn(),
|
|
10
|
+
disabled: false,
|
|
11
|
+
type: 'text',
|
|
12
|
+
autoComplete: 'off',
|
|
13
|
+
name: 'testName',
|
|
14
|
+
required: true,
|
|
15
|
+
multiline: false,
|
|
16
|
+
rows: 1,
|
|
17
|
+
placeholder: 'Test Placeholder'
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
it('renders the input element with the correct props', () => {
|
|
21
|
+
const { getByRole } = render(<MaterialField size='medium' {...props} />);
|
|
22
|
+
const inputElement = getByRole('textbox');
|
|
23
|
+
expect(inputElement).toBeInTheDocument();
|
|
24
|
+
expect(inputElement).toHaveAttribute('type', 'text');
|
|
25
|
+
expect(inputElement).toHaveAttribute('value', 'Test Value');
|
|
26
|
+
expect(inputElement).toHaveAttribute('name', 'testName');
|
|
27
|
+
expect(inputElement).toHaveAttribute('required');
|
|
28
|
+
expect(inputElement).toHaveAttribute('placeholder', 'Test Placeholder');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('calls the onChange prop when the input value changes', () => {
|
|
32
|
+
const { getByRole } = render(<MaterialField size='medium' {...props} />);
|
|
33
|
+
const inputElement = getByRole('textbox');
|
|
34
|
+
fireEvent.change(inputElement, { target: { value: 'New Value' } });
|
|
35
|
+
expect(props.onChange).toHaveBeenCalledTimes(1);
|
|
36
|
+
expect(props.onChange).toHaveBeenCalledWith('New Value', 'testName', expect.anything());
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('toggles password visibility when the icon button is clicked', () => {
|
|
40
|
+
const passwordProps = {
|
|
41
|
+
...props,
|
|
42
|
+
type: 'password'
|
|
43
|
+
}
|
|
44
|
+
const { getByRole, getByPlaceholderText } = render(<MaterialField size='medium' {...passwordProps} />);
|
|
45
|
+
const iconButton = getByRole('button');
|
|
46
|
+
const inputElement = getByPlaceholderText('Test Placeholder');
|
|
47
|
+
fireEvent.click(iconButton);
|
|
48
|
+
expect(inputElement).toHaveAttribute('type', 'text');
|
|
49
|
+
|
|
50
|
+
fireEvent.click(iconButton);
|
|
51
|
+
|
|
52
|
+
expect(inputElement).toHaveAttribute('type', 'password');
|
|
53
|
+
|
|
54
|
+
fireEvent.click(iconButton);
|
|
55
|
+
|
|
56
|
+
expect(inputElement).toHaveAttribute('type', 'text');
|
|
57
|
+
});
|
|
58
|
+
});
|
package/package.json
CHANGED
|
@@ -114,9 +114,9 @@ export const Theme = createTheme({
|
|
|
114
114
|
},
|
|
115
115
|
MuiInputLabel: {
|
|
116
116
|
styleOverrides: {
|
|
117
|
-
root: ({ ownerState }) => ({
|
|
117
|
+
root: ({ ownerState: { size } }: { ownerState: { size?: string } }) => ({
|
|
118
118
|
maxWidth: 'calc(100% - 28px)',
|
|
119
|
-
...(
|
|
119
|
+
...(size === 'custom' && {
|
|
120
120
|
marginTop: isMobileOnly ? '0px' :'-4px',
|
|
121
121
|
['&.MuiInputLabel-shrink, &.Mui-focused']: {
|
|
122
122
|
marginTop: 0
|
|
@@ -127,8 +127,8 @@ export const Theme = createTheme({
|
|
|
127
127
|
},
|
|
128
128
|
MuiOutlinedInput: {
|
|
129
129
|
styleOverrides: {
|
|
130
|
-
root: ({ ownerState }) => ({
|
|
131
|
-
...(
|
|
130
|
+
root: ({ ownerState: { size, name } }: { ownerState: { size?: string, name?: string } }) => ({
|
|
131
|
+
...(size === 'small' && {
|
|
132
132
|
paddingRight: '0 !important',
|
|
133
133
|
flexWrap: 'nowrap !important',
|
|
134
134
|
backgroundColor: '#fff',
|
|
@@ -150,11 +150,11 @@ export const Theme = createTheme({
|
|
|
150
150
|
opacity:'0.38'
|
|
151
151
|
},
|
|
152
152
|
['& .MuiAutocomplete-input']: {
|
|
153
|
-
...(
|
|
153
|
+
...(name === 'mobileSearch' && {
|
|
154
154
|
textAlign: isMobileOnly ? 'right !important' : 'left'
|
|
155
155
|
})
|
|
156
156
|
},
|
|
157
|
-
...(
|
|
157
|
+
...(size === 'custom' && {
|
|
158
158
|
height: isMobileOnly ? 56 : 48,
|
|
159
159
|
boxSizing: 'border-box',
|
|
160
160
|
backgroundColor: '#fff',
|
|
@@ -164,7 +164,7 @@ export const Theme = createTheme({
|
|
|
164
164
|
padding: '5.5px 4px 7.5px 6px !important'
|
|
165
165
|
}
|
|
166
166
|
}),
|
|
167
|
-
...(
|
|
167
|
+
...(name === 'mobileSearch' && {
|
|
168
168
|
color: isMobileOnly ? '#005ccb' : 'rgba(0, 0, 0, 0.87)',
|
|
169
169
|
backgroundColor: isMobileOnly ? 'transparent' : '#fff',
|
|
170
170
|
paddingRight: isMobileOnly ? '33px !important' : '42px !important',
|
|
@@ -181,7 +181,7 @@ export const Theme = createTheme({
|
|
|
181
181
|
borderWidth: isMobileOnly ? 0 : 1
|
|
182
182
|
}
|
|
183
183
|
})
|
|
184
|
-
})
|
|
184
|
+
} as any)
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
}
|
|
@@ -11,6 +11,7 @@ import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';
|
|
|
11
11
|
import { Theme, ArrowSelect, CheckboxLabel } from './MaterialAutocomplete.styled';
|
|
12
12
|
import isEqual from 'lodash/isEqual';
|
|
13
13
|
import IconSVG from '../IconSVG/IconSVG';
|
|
14
|
+
import { isMobileOnly } from 'react-device-detect';
|
|
14
15
|
|
|
15
16
|
export interface IItems {
|
|
16
17
|
value: string | number;
|
|
@@ -100,11 +101,8 @@ const MaterialAutocomplete: React.FC<IMaterialAutocompleteProps> = ({
|
|
|
100
101
|
multiple={multiple}
|
|
101
102
|
handleHomeEndKeys
|
|
102
103
|
value={value}
|
|
103
|
-
name={name}
|
|
104
|
-
error={error ? error.toString() : ''}
|
|
105
104
|
readOnly={readOnly}
|
|
106
|
-
|
|
107
|
-
onChange={(e, newValue, reason: string, details?: { option: any }) => {
|
|
105
|
+
onChange={(e, newValue, _: string, details?: { option: any }) => {
|
|
108
106
|
e.persist();
|
|
109
107
|
if (typeof newValue === 'string') {
|
|
110
108
|
onChange(newValue);
|
|
@@ -150,17 +148,16 @@ const MaterialAutocomplete: React.FC<IMaterialAutocompleteProps> = ({
|
|
|
150
148
|
}}
|
|
151
149
|
options={multiple ? items.map(option => option.label) : items}
|
|
152
150
|
ListboxProps={{
|
|
153
|
-
|
|
154
|
-
maxHeight:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
151
|
+
style: {
|
|
152
|
+
maxHeight: isMobileOnly ?
|
|
153
|
+
MOBILE_ITEM_HEIGHT * MENU_ITEMS
|
|
154
|
+
: ITEM_HEIGHT * MENU_ITEMS
|
|
158
155
|
}
|
|
159
156
|
}}
|
|
160
157
|
forcePopupIcon
|
|
161
158
|
popupIcon={disableIcon ? '' : <ArrowSelect name='arrowSelect' customDimensions />}
|
|
162
159
|
isOptionEqualToValue={(option, value) => option.value === value}
|
|
163
|
-
renderOption={(props, option) => {
|
|
160
|
+
renderOption={(props: any, option) => {
|
|
164
161
|
if (multiple) {
|
|
165
162
|
return (
|
|
166
163
|
<li {...props}>
|
|
@@ -218,8 +215,7 @@ const MaterialAutocomplete: React.FC<IMaterialAutocompleteProps> = ({
|
|
|
218
215
|
InputProps={{ ...params.InputProps, readOnly }}
|
|
219
216
|
/>
|
|
220
217
|
)}
|
|
221
|
-
|
|
222
|
-
</Autocomplete>
|
|
218
|
+
/>
|
|
223
219
|
</ThemeProvider>
|
|
224
220
|
);
|
|
225
221
|
};
|
|
@@ -12,14 +12,14 @@ export const Theme = createTheme({
|
|
|
12
12
|
},
|
|
13
13
|
MuiInputLabel: {
|
|
14
14
|
styleOverrides: {
|
|
15
|
-
root: ({ ownerState }) => ({
|
|
16
|
-
...(
|
|
15
|
+
root: ({ ownerState: { size } }: { ownerState: { size?: 'smaller' | 'custom' | 'normal' | 'small' | 'medium' } }) => ({
|
|
16
|
+
...(size === 'smaller' && {
|
|
17
17
|
marginTop: '-13px',
|
|
18
18
|
['&.MuiInputLabel-shrink, &.Mui-focused']: {
|
|
19
19
|
marginTop: 0
|
|
20
20
|
}
|
|
21
21
|
}),
|
|
22
|
-
...(
|
|
22
|
+
...(size === 'custom' && {
|
|
23
23
|
marginTop: isMobileOnly ? '0px' :'-4px',
|
|
24
24
|
['&.MuiInputLabel-shrink, &.Mui-focused']: {
|
|
25
25
|
marginTop: 0
|
|
@@ -30,13 +30,13 @@ export const Theme = createTheme({
|
|
|
30
30
|
},
|
|
31
31
|
MuiOutlinedInput: {
|
|
32
32
|
styleOverrides: {
|
|
33
|
-
input: ({ ownerState }) => ({
|
|
34
|
-
...(
|
|
33
|
+
input: ({ ownerState: { size } }: { ownerState: { size?: 'smaller' | 'custom' | 'normal' | 'small' | 'medium' } }) => ({
|
|
34
|
+
...(size === 'smaller' && {
|
|
35
35
|
height: 28,
|
|
36
36
|
boxSizing: 'border-box',
|
|
37
37
|
padding: '0 14px'
|
|
38
38
|
}),
|
|
39
|
-
...(
|
|
39
|
+
...(size === 'custom' && {
|
|
40
40
|
height: isMobileOnly ? 56 : 48,
|
|
41
41
|
boxSizing: 'border-box'
|
|
42
42
|
})
|
|
@@ -64,7 +64,7 @@ const MaterialField: React.FC<IVehicleModalProps> = ({
|
|
|
64
64
|
setShowPassword(!showPassword);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
const handleMouseDownPassword = (event) => {
|
|
67
|
+
const handleMouseDownPassword = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
|
68
68
|
event.preventDefault();
|
|
69
69
|
};
|
|
70
70
|
|
|
@@ -568,3 +568,15 @@ export const updateCookieList = () => {
|
|
|
568
568
|
// grant Hotjar cookies
|
|
569
569
|
if (isHotjarGranted && typeof window.grantHotjarCookieConsent === 'function') window.grantHotjarCookieConsent();
|
|
570
570
|
};
|
|
571
|
+
|
|
572
|
+
// function returns decimal part of number with 2 digits
|
|
573
|
+
export const getCents = (value: number, prefix?: string, postfix?: string): string => {
|
|
574
|
+
if (!Number.isFinite(value)) return '';
|
|
575
|
+
const roundedValue = Math.floor(value);
|
|
576
|
+
const result = value.toFixed(2).toString().replace(`${roundedValue}.`, '');
|
|
577
|
+
return `${prefix}${result}${postfix}`;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
export const priceParse = (value: any) => {
|
|
581
|
+
return !!value ? Number.parseFloat(value) : null;
|
|
582
|
+
};
|
package/tsconfig.json
CHANGED
package/tslint.json
CHANGED
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
"no-console": [true, "warn", "error"],
|
|
21
21
|
"switch-default": true,
|
|
22
22
|
"no-empty-interface": true,
|
|
23
|
-
// "no-magic-numbers": [true, 0, -1, 1, 2, 10, 8, 16],
|
|
24
23
|
"no-parameter-reassignment": true,
|
|
25
24
|
"no-duplicate-switch-case": true,
|
|
26
25
|
"no-duplicate-imports": true,
|