@astral/ui 1.39.3 → 1.39.4
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/Autocomplete/Autocomplete.d.ts +1 -1
- package/Autocomplete/Autocomplete.js +1 -1
- package/Autocomplete/Autocomplete.test.d.ts +1 -0
- package/Autocomplete/Autocomplete.test.js +98 -0
- package/Autocomplete/constants.d.ts +0 -4
- package/Autocomplete/constants.js +1 -6
- package/Autocomplete/enums.d.ts +4 -0
- package/Autocomplete/enums.js +8 -0
- package/Button/Button.test.d.ts +1 -0
- package/Button/Button.test.js +35 -0
- package/DataGrid/DataGrid.js +2 -1
- package/DataGrid/DataGrid.test.d.ts +1 -0
- package/DataGrid/DataGrid.test.js +117 -0
- package/DataGrid/DataGridHead/DataGridHead.js +5 -5
- package/DataGrid/DataGridHeadColumn/DataGridHeadColumn.js +3 -3
- package/DataGrid/{constants.d.ts → enums.d.ts} +0 -0
- package/DataGrid/{constants.js → enums.js} +0 -0
- package/DataGrid/types.d.ts +1 -1
- package/Select/Select.d.ts +2 -2
- package/esm/Autocomplete/Autocomplete.d.ts +1 -1
- package/esm/Autocomplete/Autocomplete.js +2 -2
- package/esm/Autocomplete/Autocomplete.test.d.ts +1 -0
- package/esm/Autocomplete/Autocomplete.test.js +96 -0
- package/esm/Autocomplete/constants.d.ts +0 -4
- package/esm/Autocomplete/constants.js +0 -5
- package/esm/Autocomplete/enums.d.ts +4 -0
- package/esm/Autocomplete/enums.js +5 -0
- package/esm/Button/Button.test.d.ts +1 -0
- package/esm/Button/Button.test.js +33 -0
- package/esm/DataGrid/DataGrid.js +2 -1
- package/esm/DataGrid/DataGrid.test.d.ts +1 -0
- package/esm/DataGrid/DataGrid.test.js +115 -0
- package/esm/DataGrid/DataGridHead/DataGridHead.js +1 -1
- package/esm/DataGrid/DataGridHeadColumn/DataGridHeadColumn.js +1 -1
- package/esm/DataGrid/{constants.d.ts → enums.d.ts} +0 -0
- package/esm/DataGrid/{constants.js → enums.js} +0 -0
- package/esm/DataGrid/types.d.ts +1 -1
- package/esm/Select/Select.d.ts +2 -2
- package/esm/hooks/useEscapeClickEffect/useEscapeClickEffect.test.d.ts +1 -0
- package/esm/hooks/useEscapeClickEffect/useEscapeClickEffect.test.js +25 -0
- package/esm/hooks/useMenu/index.d.ts +1 -0
- package/esm/hooks/useMenu/index.js +1 -0
- package/esm/hooks/{useMenu.d.ts → useMenu/useMenu.d.ts} +0 -0
- package/esm/hooks/{useMenu.js → useMenu/useMenu.js} +0 -0
- package/esm/theme/components/MuiAutocomplete.js +1 -1
- package/hooks/useEscapeClickEffect/useEscapeClickEffect.test.d.ts +1 -0
- package/hooks/useEscapeClickEffect/useEscapeClickEffect.test.js +27 -0
- package/hooks/useMenu/index.d.ts +1 -0
- package/hooks/useMenu/index.js +17 -0
- package/hooks/{useMenu.d.ts → useMenu/useMenu.d.ts} +0 -0
- package/hooks/{useMenu.js → useMenu/useMenu.js} +0 -0
- package/package.json +2 -2
- package/theme/components/MuiAutocomplete.js +2 -2
|
@@ -3,7 +3,7 @@ import { AutocompleteProps as MuiAutocompleteProps } from '@mui/material';
|
|
|
3
3
|
import { TextFieldProps } from '../TextField';
|
|
4
4
|
import { OverflowedElementProps } from '../OverflowTypography';
|
|
5
5
|
import { WithoutEmotionSpecific } from '../types';
|
|
6
|
-
import { AutocompleteSizes } from './
|
|
6
|
+
import { AutocompleteSizes } from './enums';
|
|
7
7
|
export declare type AutocompleteSize = `${AutocompleteSizes}`;
|
|
8
8
|
export declare type AutocompleteProps<AutocompleteValueProps, Multiple extends boolean, DisableClearable extends boolean, FreeSolo extends boolean> = Omit<WithoutEmotionSpecific<MuiAutocompleteProps<AutocompleteValueProps, Multiple, DisableClearable, FreeSolo>>, 'size' | 'renderInput'> & Pick<TextFieldProps, 'error' | 'success' | 'helperText' | 'label'> & {
|
|
9
9
|
size?: AutocompleteSize;
|
|
@@ -41,7 +41,7 @@ const Autocomplete = (props) => {
|
|
|
41
41
|
}
|
|
42
42
|
const selected = Boolean(optionProps['aria-selected']);
|
|
43
43
|
return ((0, react_1.createElement)(MenuItem_1.MenuItem, Object.assign({}, optionProps, { key: optionProps.id }),
|
|
44
|
-
multiple && ((0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: selected }) })),
|
|
44
|
+
multiple && ((0, jsx_runtime_1.jsx)(material_1.ListItemIcon, { children: (0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { role: "menuitemcheckbox", checked: selected }) })),
|
|
45
45
|
(0, jsx_runtime_1.jsx)(OverflowTypography_1.OverflowTypography, Object.assign({ rowsCount: constants_1.DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT }, overflowOption, { children: optionProps.key }))));
|
|
46
46
|
}, [multiple, externalRenderOption]);
|
|
47
47
|
return ((0, jsx_runtime_1.jsx)(material_1.Autocomplete, Object.assign({}, restProps, { size: size, multiple: multiple, getOptionLabel: getOptionLabel, disableCloseOnSelect: multiple, renderTags: renderTags, renderInput: renderInput, renderOption: renderOption, popupIcon: (0, jsx_runtime_1.jsx)(icons_1.ChevronDOutlineMd, {}), clearIcon: (0, jsx_runtime_1.jsx)(icons_1.CrossSmOutlineSm, {}), isOptionEqualToValue: isOptionEqualToValue, componentsProps: { clearIndicator: { disableRipple: true } }, noOptionsText: "\u041D\u0435\u0442 \u0434\u0430\u043D\u043D\u044B\u0445" })));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
13
|
+
const tests_1 = require("@astral/tests");
|
|
14
|
+
const Autocomplete_1 = require("./Autocomplete");
|
|
15
|
+
describe('Autocomplete', () => {
|
|
16
|
+
it('Prop:options: при пустом массиве отображается плейсхолдер', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Autocomplete_1.Autocomplete, { options: [] }));
|
|
18
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('combobox'));
|
|
19
|
+
const noDataPlaceholder = tests_1.screen.getByText('Нет данных');
|
|
20
|
+
expect(noDataPlaceholder).toBeVisible();
|
|
21
|
+
}));
|
|
22
|
+
it('Focus: не отображается popover', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Autocomplete_1.Autocomplete, { options: [] }));
|
|
24
|
+
tests_1.fireEvent.focus(tests_1.screen.getByRole('combobox'));
|
|
25
|
+
const noDataPlaceholder = tests_1.screen.queryByText('Нет данных');
|
|
26
|
+
expect(noDataPlaceholder).toBeNull();
|
|
27
|
+
}));
|
|
28
|
+
it('Prop:getOptionLabel: позволяет отображать в popover label', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
29
|
+
const options = [
|
|
30
|
+
{ name: 'Vasya', surname: 'Pupkin' },
|
|
31
|
+
{ name: 'Kolya', surname: 'Kolin' },
|
|
32
|
+
];
|
|
33
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Autocomplete_1.Autocomplete, { options: options, getOptionLabel: (option) => option.surname }));
|
|
34
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('combobox'));
|
|
35
|
+
const vasya = tests_1.screen.getByText('Pupkin');
|
|
36
|
+
const kolya = tests_1.screen.getByText('Kolin');
|
|
37
|
+
expect(vasya).toBeVisible();
|
|
38
|
+
expect(kolya).toBeVisible();
|
|
39
|
+
}));
|
|
40
|
+
it('Закрывается popover после выбора значения', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
+
const options = [
|
|
42
|
+
{ name: 'Vasya', surname: 'Pupkin' },
|
|
43
|
+
{ name: 'Kolya', surname: 'Kolin' },
|
|
44
|
+
];
|
|
45
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Autocomplete_1.Autocomplete, { options: options, getOptionLabel: (option) => option.surname }));
|
|
46
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('combobox'));
|
|
47
|
+
const selectedOption = tests_1.screen.getByRole('option', { name: 'Pupkin' });
|
|
48
|
+
yield tests_1.userEvents.click(selectedOption);
|
|
49
|
+
expect(tests_1.screen.queryByRole('option')).toBeNull();
|
|
50
|
+
}));
|
|
51
|
+
it('Props:multiple=false: в инпут сетится label после выбора option', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
52
|
+
const options = [
|
|
53
|
+
{ name: 'Vasya', surname: 'Pupkin' },
|
|
54
|
+
{ name: 'Kolya', surname: 'Kolin' },
|
|
55
|
+
];
|
|
56
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Autocomplete_1.Autocomplete, { options: options, getOptionLabel: (option) => option.surname }));
|
|
57
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('combobox'));
|
|
58
|
+
const option = tests_1.screen.getByRole('option', { name: 'Pupkin' });
|
|
59
|
+
yield tests_1.userEvents.click(option);
|
|
60
|
+
const input = tests_1.screen.getByRole('combobox');
|
|
61
|
+
expect(input).toHaveAttribute('value', 'Pupkin');
|
|
62
|
+
}));
|
|
63
|
+
it('Prop:multiple: в options отображаются чекбоксы', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
64
|
+
const options = [{ name: 'Vasya', surname: 'Pupkin' }];
|
|
65
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Autocomplete_1.Autocomplete, { multiple: true, options: options, getOptionLabel: (option) => option.surname }));
|
|
66
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('combobox'));
|
|
67
|
+
const checkbox = tests_1.screen.getByRole('menuitemcheckbox');
|
|
68
|
+
expect(checkbox).toBeVisible();
|
|
69
|
+
}));
|
|
70
|
+
it('Prop:multiple: после выбора option в инпуте появляется tag', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
+
const options = [{ name: 'Vasya', surname: 'Pupkin' }];
|
|
72
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Autocomplete_1.Autocomplete, { multiple: true, options: options, getOptionLabel: (option) => option.surname }));
|
|
73
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('combobox'));
|
|
74
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('menuitemcheckbox'));
|
|
75
|
+
const checkbox = tests_1.screen
|
|
76
|
+
.getByRole('menuitemcheckbox')
|
|
77
|
+
.getElementsByTagName('input')[0];
|
|
78
|
+
expect(checkbox).toBeChecked();
|
|
79
|
+
const tag = tests_1.screen.getByRole('button', { name: 'Pupkin' });
|
|
80
|
+
expect(tag).toBeVisible();
|
|
81
|
+
}));
|
|
82
|
+
it('Prop:multiple: tag из инпута можно удалить', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
83
|
+
const options = [{ name: 'Vasya', surname: 'Pupkin' }];
|
|
84
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Autocomplete_1.Autocomplete, { multiple: true, options: options, getOptionLabel: (option) => option.surname }));
|
|
85
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('combobox'));
|
|
86
|
+
yield tests_1.userEvents.click(tests_1.screen.getByRole('menuitemcheckbox'));
|
|
87
|
+
const tagDeleteIcon = tests_1.screen
|
|
88
|
+
.getByRole('button', { name: 'Pupkin' })
|
|
89
|
+
.getElementsByTagName('svg')[0];
|
|
90
|
+
yield tests_1.userEvents.click(tagDeleteIcon);
|
|
91
|
+
const checkbox = tests_1.screen
|
|
92
|
+
.getByRole('menuitemcheckbox')
|
|
93
|
+
.getElementsByTagName('input')[0];
|
|
94
|
+
expect(checkbox).not.toBeChecked();
|
|
95
|
+
const tag = tests_1.screen.queryByRole('button', { name: 'Pupkin' });
|
|
96
|
+
expect(tag).toBeNull();
|
|
97
|
+
}));
|
|
98
|
+
});
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT =
|
|
4
|
-
var AutocompleteSizes;
|
|
5
|
-
(function (AutocompleteSizes) {
|
|
6
|
-
AutocompleteSizes["medium"] = "medium";
|
|
7
|
-
AutocompleteSizes["small"] = "small";
|
|
8
|
-
})(AutocompleteSizes = exports.AutocompleteSizes || (exports.AutocompleteSizes = {}));
|
|
3
|
+
exports.DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT = void 0;
|
|
9
4
|
exports.DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT = 2;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AutocompleteSizes = void 0;
|
|
4
|
+
var AutocompleteSizes;
|
|
5
|
+
(function (AutocompleteSizes) {
|
|
6
|
+
AutocompleteSizes["medium"] = "medium";
|
|
7
|
+
AutocompleteSizes["small"] = "small";
|
|
8
|
+
})(AutocompleteSizes = exports.AutocompleteSizes || (exports.AutocompleteSizes = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
const tests_1 = require("@astral/tests");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const Button_1 = require("./Button");
|
|
7
|
+
describe('Button', () => {
|
|
8
|
+
it('Prop:ref: is present', () => {
|
|
9
|
+
const resultRef = { current: null };
|
|
10
|
+
const ButtonWithRef = () => {
|
|
11
|
+
const ref = (0, react_1.useRef)(null);
|
|
12
|
+
(0, react_1.useEffect)(() => {
|
|
13
|
+
resultRef.current = ref.current;
|
|
14
|
+
}, []);
|
|
15
|
+
return (0, jsx_runtime_1.jsx)(Button_1.Button, Object.assign({ ref: ref }, { children: "Btn" }));
|
|
16
|
+
};
|
|
17
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(ButtonWithRef, {}));
|
|
18
|
+
expect(resultRef === null || resultRef === void 0 ? void 0 : resultRef.current).not.toBeNull();
|
|
19
|
+
});
|
|
20
|
+
it('Prop:disabled: блокирует кнопку', () => {
|
|
21
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Button_1.Button, Object.assign({ disabled: true }, { children: "Btn" })));
|
|
22
|
+
const button = tests_1.screen.getByRole('button');
|
|
23
|
+
expect(button).toBeDisabled();
|
|
24
|
+
});
|
|
25
|
+
it('Prop:loading: блокирует кнопку', () => {
|
|
26
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Button_1.Button, Object.assign({ loading: true }, { children: "Btn" })));
|
|
27
|
+
const button = tests_1.screen.getByRole('button');
|
|
28
|
+
expect(button).toBeDisabled();
|
|
29
|
+
});
|
|
30
|
+
it('Prop:loading: отображается лоадер', () => {
|
|
31
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(Button_1.Button, Object.assign({ loading: true }, { children: "Btn" })));
|
|
32
|
+
const loader = tests_1.screen.getByRole('progressbar');
|
|
33
|
+
expect(loader).toBeVisible();
|
|
34
|
+
});
|
|
35
|
+
});
|
package/DataGrid/DataGrid.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.DataGrid = void 0;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const react_1 = require("react");
|
|
9
|
+
const lodash_es_1 = require("lodash-es");
|
|
9
10
|
const Table_1 = require("../Table");
|
|
10
11
|
const DataGridHead_1 = require("./DataGridHead");
|
|
11
12
|
const DataGridBody_1 = require("./DataGridBody");
|
|
@@ -20,7 +21,7 @@ function DataGrid({ columns, rows = [], selectedRows = [], sorting, maxHeight, m
|
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
23
|
if (event.target.checked) {
|
|
23
|
-
const mergedSelectedRows = [...selectedRows, ...rows];
|
|
24
|
+
const mergedSelectedRows = (0, lodash_es_1.uniqBy)([...selectedRows, ...rows], keyId);
|
|
24
25
|
return onSelectRow(mergedSelectedRows);
|
|
25
26
|
}
|
|
26
27
|
const filteredRows = selectedRows.filter((selectedRow) => !rows.find((row) => row[keyId] === selectedRow[keyId]));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
13
|
+
const tests_1 = require("@astral/tests");
|
|
14
|
+
const react_1 = require("react");
|
|
15
|
+
const DataGrid_1 = require("./DataGrid");
|
|
16
|
+
describe('DataGrid', () => {
|
|
17
|
+
it('Props:columns: отображаются названия колонок', () => {
|
|
18
|
+
const columns = [
|
|
19
|
+
{
|
|
20
|
+
field: 'name',
|
|
21
|
+
label: 'Наименование',
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(DataGrid_1.DataGrid, { keyId: "id", rows: [], columns: columns }));
|
|
25
|
+
const title = tests_1.screen.getByText('Наименование');
|
|
26
|
+
expect(title).toBeVisible();
|
|
27
|
+
});
|
|
28
|
+
it('Props:columns:sortable: отображается иконка сортировки', () => {
|
|
29
|
+
const columns = [
|
|
30
|
+
{
|
|
31
|
+
field: 'name',
|
|
32
|
+
label: 'Наименование',
|
|
33
|
+
sortable: true,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(DataGrid_1.DataGrid, { keyId: "id", rows: [], columns: columns }));
|
|
37
|
+
const icon = tests_1.screen.getByText('Наименование').querySelector('svg');
|
|
38
|
+
expect(icon).not.toBeNull();
|
|
39
|
+
});
|
|
40
|
+
it('Props:columns:sortable: по клику на head cell вызывается onSort', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
|
+
const columns = [
|
|
42
|
+
{
|
|
43
|
+
field: 'name',
|
|
44
|
+
label: 'Наименование',
|
|
45
|
+
sortable: true,
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
let currentSort;
|
|
49
|
+
const TestComponent = () => {
|
|
50
|
+
const [sorting, setSorting] = (0, react_1.useState)();
|
|
51
|
+
const handleSort = (sort) => {
|
|
52
|
+
currentSort = sort;
|
|
53
|
+
setSorting(sort);
|
|
54
|
+
};
|
|
55
|
+
return ((0, jsx_runtime_1.jsx)(DataGrid_1.DataGrid, { keyId: "name", rows: [], sorting: sorting, onSort: handleSort, columns: columns }));
|
|
56
|
+
};
|
|
57
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(TestComponent, {}));
|
|
58
|
+
expect(currentSort).toBe(undefined);
|
|
59
|
+
yield tests_1.userEvents.click(tests_1.screen.getByText('Наименование'));
|
|
60
|
+
expect(currentSort).toEqual({ fieldId: 'name', sort: 'asc' });
|
|
61
|
+
yield tests_1.userEvents.click(tests_1.screen.getByText('Наименование'));
|
|
62
|
+
expect(currentSort).toEqual({ fieldId: 'name', sort: 'desc' });
|
|
63
|
+
yield tests_1.userEvents.click(tests_1.screen.getByText('Наименование'));
|
|
64
|
+
expect(currentSort).toBe(undefined);
|
|
65
|
+
}));
|
|
66
|
+
it('Props:columns:field: отображает в строке данные по field', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
67
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(DataGrid_1.DataGrid, { keyId: "name", rows: [{ name: 'Vasya' }], columns: [
|
|
68
|
+
{
|
|
69
|
+
field: 'name',
|
|
70
|
+
label: 'Наименование',
|
|
71
|
+
},
|
|
72
|
+
] }));
|
|
73
|
+
const title = tests_1.screen.getByText('Vasya');
|
|
74
|
+
expect(title).toBeVisible();
|
|
75
|
+
}));
|
|
76
|
+
it('Props:options=[]: отображается placeholder', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
77
|
+
const columns = [
|
|
78
|
+
{
|
|
79
|
+
field: 'name',
|
|
80
|
+
label: 'Наименование',
|
|
81
|
+
},
|
|
82
|
+
];
|
|
83
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(DataGrid_1.DataGrid, { keyId: "id", rows: [], columns: columns }));
|
|
84
|
+
const title = tests_1.screen.getByText('Нет данных');
|
|
85
|
+
expect(title).toBeVisible();
|
|
86
|
+
}));
|
|
87
|
+
it('Props:onRowClick: по клику на строку получаем данные row', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
88
|
+
const onRowClick = jest.fn();
|
|
89
|
+
(0, tests_1.renderWithTheme)((0, jsx_runtime_1.jsx)(DataGrid_1.DataGrid, { keyId: "name", rows: [{ name: 'Vasya' }], onRowClick: onRowClick, columns: [
|
|
90
|
+
{
|
|
91
|
+
field: 'name',
|
|
92
|
+
label: 'Наименование',
|
|
93
|
+
},
|
|
94
|
+
] }));
|
|
95
|
+
yield tests_1.userEvents.click(tests_1.screen.getByText('Vasya'));
|
|
96
|
+
expect(onRowClick.mock.calls[0][0]).toEqual({ name: 'Vasya' });
|
|
97
|
+
}));
|
|
98
|
+
// TODO: https://astraltrack.atlassian.net/browse/UIKIT-309
|
|
99
|
+
// it('Props:emptyCellValue: по дефолту для пустого значения отображается -', async () => {
|
|
100
|
+
// renderWithTheme(
|
|
101
|
+
// <DataGrid<{ name?: string }>
|
|
102
|
+
// keyId="name"
|
|
103
|
+
// rows={[{}]}
|
|
104
|
+
// columns={[
|
|
105
|
+
// {
|
|
106
|
+
// field: 'name',
|
|
107
|
+
// label: 'Наименование',
|
|
108
|
+
// },
|
|
109
|
+
// ]}
|
|
110
|
+
// />,
|
|
111
|
+
// );
|
|
112
|
+
//
|
|
113
|
+
// const emptySymbol = screen.getByText('-');
|
|
114
|
+
//
|
|
115
|
+
// expect(emptySymbol).toBeVisible();
|
|
116
|
+
// });
|
|
117
|
+
});
|
|
@@ -6,7 +6,7 @@ const react_1 = require("react");
|
|
|
6
6
|
const TableHead_1 = require("../../Table/TableHead");
|
|
7
7
|
const Table_1 = require("../../Table");
|
|
8
8
|
const Checkbox_1 = require("../../Checkbox");
|
|
9
|
-
const
|
|
9
|
+
const enums_1 = require("../enums");
|
|
10
10
|
const DataGridHeadColumn_1 = require("../DataGridHeadColumn");
|
|
11
11
|
function DataGridHead({ columns, selectable, onSelectAllRows, rowsCount, onSort, sorting, uncheckedRowsCount, }) {
|
|
12
12
|
const checked = (0, react_1.useMemo)(() => !Boolean(uncheckedRowsCount) && rowsCount > 0, [uncheckedRowsCount, rowsCount]);
|
|
@@ -17,15 +17,15 @@ function DataGridHead({ columns, selectable, onSelectAllRows, rowsCount, onSort,
|
|
|
17
17
|
}
|
|
18
18
|
const isCurrentField = (sorting === null || sorting === void 0 ? void 0 : sorting.fieldId) === field;
|
|
19
19
|
// если для выбранного столбца текущая сортировка ASC - меняем на DESC
|
|
20
|
-
if (isCurrentField && sorting.sort ===
|
|
21
|
-
return onSort({ fieldId: field, sort:
|
|
20
|
+
if (isCurrentField && sorting.sort === enums_1.SortStates.ASC) {
|
|
21
|
+
return onSort({ fieldId: field, sort: enums_1.SortStates.DESC });
|
|
22
22
|
}
|
|
23
23
|
// если для выбранного столбца текущая сортировка DESC - убираем сортировку
|
|
24
|
-
if (isCurrentField && sorting.sort ===
|
|
24
|
+
if (isCurrentField && sorting.sort === enums_1.SortStates.DESC) {
|
|
25
25
|
return onSort(undefined);
|
|
26
26
|
}
|
|
27
27
|
// если для выбранного столбца нет сортировки - добавляем сортировку ASC
|
|
28
|
-
onSort({ fieldId: field, sort:
|
|
28
|
+
onSort({ fieldId: field, sort: enums_1.SortStates.ASC });
|
|
29
29
|
}, [sorting, onSort]);
|
|
30
30
|
const renderColumns = (0, react_1.useMemo)(() => {
|
|
31
31
|
return columns.map(({ field, label, sortable, align, width }) => {
|
|
@@ -4,7 +4,7 @@ exports.DataGridHeadColumn = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const icons_1 = require("@astral/icons");
|
|
7
|
-
const
|
|
7
|
+
const enums_1 = require("../enums");
|
|
8
8
|
const styles_1 = require("./styles");
|
|
9
9
|
function DataGridHeadColumn({ onSort, field, sortable, align, label, sorting, width, }) {
|
|
10
10
|
const sortIcon = (0, react_1.useMemo)(() => {
|
|
@@ -15,9 +15,9 @@ function DataGridHeadColumn({ onSort, field, sortable, align, label, sorting, wi
|
|
|
15
15
|
return (0, jsx_runtime_1.jsx)(icons_1.SortFillSm, {});
|
|
16
16
|
}
|
|
17
17
|
switch (sorting === null || sorting === void 0 ? void 0 : sorting.sort) {
|
|
18
|
-
case
|
|
18
|
+
case enums_1.SortStates.ASC:
|
|
19
19
|
return (0, jsx_runtime_1.jsx)(icons_1.SortUpFillSm, { color: "primary" });
|
|
20
|
-
case
|
|
20
|
+
case enums_1.SortStates.DESC:
|
|
21
21
|
return (0, jsx_runtime_1.jsx)(icons_1.SortDownFillSm, { color: "primary" });
|
|
22
22
|
default:
|
|
23
23
|
return (0, jsx_runtime_1.jsx)(icons_1.SortFillSm, {});
|
|
File without changes
|
|
File without changes
|
package/DataGrid/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import { TableCellProps } from '@mui/material';
|
|
3
|
-
import { SortStates } from './
|
|
3
|
+
import { SortStates } from './enums';
|
|
4
4
|
export declare type CellValue = string | number | boolean | Date | undefined | object;
|
|
5
5
|
export declare type SortState = `${SortStates}`;
|
|
6
6
|
export declare type RenderCell<Data> = (params: Data) => ReactNode;
|
package/Select/Select.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
import { SelectProps as MuiSelectProps } from '@mui/material';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
3
|
import { WithoutEmotionSpecific } from '../types';
|
|
4
4
|
export declare type SelectProps<Value> = WithoutEmotionSpecific<MuiSelectProps<Value>> & {
|
|
5
5
|
loading?: boolean;
|
|
6
6
|
placeholder?: string;
|
|
7
7
|
getOptionLabel?: (value: string | number) => string | number;
|
|
8
|
-
helperText?:
|
|
8
|
+
helperText?: ReactNode;
|
|
9
9
|
success?: boolean;
|
|
10
10
|
error?: boolean;
|
|
11
11
|
label?: string;
|
|
@@ -3,7 +3,7 @@ import { AutocompleteProps as MuiAutocompleteProps } from '@mui/material';
|
|
|
3
3
|
import { TextFieldProps } from '../TextField';
|
|
4
4
|
import { OverflowedElementProps } from '../OverflowTypography';
|
|
5
5
|
import { WithoutEmotionSpecific } from '../types';
|
|
6
|
-
import { AutocompleteSizes } from './
|
|
6
|
+
import { AutocompleteSizes } from './enums';
|
|
7
7
|
export declare type AutocompleteSize = `${AutocompleteSizes}`;
|
|
8
8
|
export declare type AutocompleteProps<AutocompleteValueProps, Multiple extends boolean, DisableClearable extends boolean, FreeSolo extends boolean> = Omit<WithoutEmotionSpecific<MuiAutocompleteProps<AutocompleteValueProps, Multiple, DisableClearable, FreeSolo>>, 'size' | 'renderInput'> & Pick<TextFieldProps, 'error' | 'success' | 'helperText' | 'label'> & {
|
|
9
9
|
size?: AutocompleteSize;
|
|
@@ -19,7 +19,7 @@ import { Tag } from '../Tag';
|
|
|
19
19
|
import { MenuItem } from '../MenuItem';
|
|
20
20
|
import { Checkbox } from '../Checkbox';
|
|
21
21
|
import { OverflowTypography, } from '../OverflowTypography';
|
|
22
|
-
import { DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT
|
|
22
|
+
import { DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT } from './constants';
|
|
23
23
|
export const Autocomplete = (props) => {
|
|
24
24
|
const { multiple, placeholder, error, success, helperText, label, size = 'medium', getOptionLabel, renderOption: externalRenderOption, overflowOption } = props, restProps = __rest(props, ["multiple", "placeholder", "error", "success", "helperText", "label", "size", "getOptionLabel", "renderOption", "overflowOption"]);
|
|
25
25
|
const renderTags = useCallback((tags, getTagProps) => {
|
|
@@ -38,7 +38,7 @@ export const Autocomplete = (props) => {
|
|
|
38
38
|
}
|
|
39
39
|
const selected = Boolean(optionProps['aria-selected']);
|
|
40
40
|
return (_createElement(MenuItem, Object.assign({}, optionProps, { key: optionProps.id }),
|
|
41
|
-
multiple && (_jsx(ListItemIcon, { children: _jsx(Checkbox, { checked: selected }) })),
|
|
41
|
+
multiple && (_jsx(ListItemIcon, { children: _jsx(Checkbox, { role: "menuitemcheckbox", checked: selected }) })),
|
|
42
42
|
_jsx(OverflowTypography, Object.assign({ rowsCount: DEFAULT_AUTOCOMPLETE_ELEMENT_ROWS_COUNT }, overflowOption, { children: optionProps.key }))));
|
|
43
43
|
}, [multiple, externalRenderOption]);
|
|
44
44
|
return (_jsx(MuiAutocomplete, Object.assign({}, restProps, { size: size, multiple: multiple, getOptionLabel: getOptionLabel, disableCloseOnSelect: multiple, renderTags: renderTags, renderInput: renderInput, renderOption: renderOption, popupIcon: _jsx(ChevronDOutlineMd, {}), clearIcon: _jsx(CrossSmOutlineSm, {}), isOptionEqualToValue: isOptionEqualToValue, componentsProps: { clearIndicator: { disableRipple: true } }, noOptionsText: "\u041D\u0435\u0442 \u0434\u0430\u043D\u043D\u044B\u0445" })));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { fireEvent, renderWithTheme, screen, userEvents } from '@astral/tests';
|
|
12
|
+
import { Autocomplete } from './Autocomplete';
|
|
13
|
+
describe('Autocomplete', () => {
|
|
14
|
+
it('Prop:options: при пустом массиве отображается плейсхолдер', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
renderWithTheme(_jsx(Autocomplete, { options: [] }));
|
|
16
|
+
yield userEvents.click(screen.getByRole('combobox'));
|
|
17
|
+
const noDataPlaceholder = screen.getByText('Нет данных');
|
|
18
|
+
expect(noDataPlaceholder).toBeVisible();
|
|
19
|
+
}));
|
|
20
|
+
it('Focus: не отображается popover', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
renderWithTheme(_jsx(Autocomplete, { options: [] }));
|
|
22
|
+
fireEvent.focus(screen.getByRole('combobox'));
|
|
23
|
+
const noDataPlaceholder = screen.queryByText('Нет данных');
|
|
24
|
+
expect(noDataPlaceholder).toBeNull();
|
|
25
|
+
}));
|
|
26
|
+
it('Prop:getOptionLabel: позволяет отображать в popover label', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
const options = [
|
|
28
|
+
{ name: 'Vasya', surname: 'Pupkin' },
|
|
29
|
+
{ name: 'Kolya', surname: 'Kolin' },
|
|
30
|
+
];
|
|
31
|
+
renderWithTheme(_jsx(Autocomplete, { options: options, getOptionLabel: (option) => option.surname }));
|
|
32
|
+
yield userEvents.click(screen.getByRole('combobox'));
|
|
33
|
+
const vasya = screen.getByText('Pupkin');
|
|
34
|
+
const kolya = screen.getByText('Kolin');
|
|
35
|
+
expect(vasya).toBeVisible();
|
|
36
|
+
expect(kolya).toBeVisible();
|
|
37
|
+
}));
|
|
38
|
+
it('Закрывается popover после выбора значения', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
const options = [
|
|
40
|
+
{ name: 'Vasya', surname: 'Pupkin' },
|
|
41
|
+
{ name: 'Kolya', surname: 'Kolin' },
|
|
42
|
+
];
|
|
43
|
+
renderWithTheme(_jsx(Autocomplete, { options: options, getOptionLabel: (option) => option.surname }));
|
|
44
|
+
yield userEvents.click(screen.getByRole('combobox'));
|
|
45
|
+
const selectedOption = screen.getByRole('option', { name: 'Pupkin' });
|
|
46
|
+
yield userEvents.click(selectedOption);
|
|
47
|
+
expect(screen.queryByRole('option')).toBeNull();
|
|
48
|
+
}));
|
|
49
|
+
it('Props:multiple=false: в инпут сетится label после выбора option', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
50
|
+
const options = [
|
|
51
|
+
{ name: 'Vasya', surname: 'Pupkin' },
|
|
52
|
+
{ name: 'Kolya', surname: 'Kolin' },
|
|
53
|
+
];
|
|
54
|
+
renderWithTheme(_jsx(Autocomplete, { options: options, getOptionLabel: (option) => option.surname }));
|
|
55
|
+
yield userEvents.click(screen.getByRole('combobox'));
|
|
56
|
+
const option = screen.getByRole('option', { name: 'Pupkin' });
|
|
57
|
+
yield userEvents.click(option);
|
|
58
|
+
const input = screen.getByRole('combobox');
|
|
59
|
+
expect(input).toHaveAttribute('value', 'Pupkin');
|
|
60
|
+
}));
|
|
61
|
+
it('Prop:multiple: в options отображаются чекбоксы', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
62
|
+
const options = [{ name: 'Vasya', surname: 'Pupkin' }];
|
|
63
|
+
renderWithTheme(_jsx(Autocomplete, { multiple: true, options: options, getOptionLabel: (option) => option.surname }));
|
|
64
|
+
yield userEvents.click(screen.getByRole('combobox'));
|
|
65
|
+
const checkbox = screen.getByRole('menuitemcheckbox');
|
|
66
|
+
expect(checkbox).toBeVisible();
|
|
67
|
+
}));
|
|
68
|
+
it('Prop:multiple: после выбора option в инпуте появляется tag', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
69
|
+
const options = [{ name: 'Vasya', surname: 'Pupkin' }];
|
|
70
|
+
renderWithTheme(_jsx(Autocomplete, { multiple: true, options: options, getOptionLabel: (option) => option.surname }));
|
|
71
|
+
yield userEvents.click(screen.getByRole('combobox'));
|
|
72
|
+
yield userEvents.click(screen.getByRole('menuitemcheckbox'));
|
|
73
|
+
const checkbox = screen
|
|
74
|
+
.getByRole('menuitemcheckbox')
|
|
75
|
+
.getElementsByTagName('input')[0];
|
|
76
|
+
expect(checkbox).toBeChecked();
|
|
77
|
+
const tag = screen.getByRole('button', { name: 'Pupkin' });
|
|
78
|
+
expect(tag).toBeVisible();
|
|
79
|
+
}));
|
|
80
|
+
it('Prop:multiple: tag из инпута можно удалить', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
81
|
+
const options = [{ name: 'Vasya', surname: 'Pupkin' }];
|
|
82
|
+
renderWithTheme(_jsx(Autocomplete, { multiple: true, options: options, getOptionLabel: (option) => option.surname }));
|
|
83
|
+
yield userEvents.click(screen.getByRole('combobox'));
|
|
84
|
+
yield userEvents.click(screen.getByRole('menuitemcheckbox'));
|
|
85
|
+
const tagDeleteIcon = screen
|
|
86
|
+
.getByRole('button', { name: 'Pupkin' })
|
|
87
|
+
.getElementsByTagName('svg')[0];
|
|
88
|
+
yield userEvents.click(tagDeleteIcon);
|
|
89
|
+
const checkbox = screen
|
|
90
|
+
.getByRole('menuitemcheckbox')
|
|
91
|
+
.getElementsByTagName('input')[0];
|
|
92
|
+
expect(checkbox).not.toBeChecked();
|
|
93
|
+
const tag = screen.queryByRole('button', { name: 'Pupkin' });
|
|
94
|
+
expect(tag).toBeNull();
|
|
95
|
+
}));
|
|
96
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { renderWithTheme, screen } from '@astral/tests';
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
import { Button } from './Button';
|
|
5
|
+
describe('Button', () => {
|
|
6
|
+
it('Prop:ref: is present', () => {
|
|
7
|
+
const resultRef = { current: null };
|
|
8
|
+
const ButtonWithRef = () => {
|
|
9
|
+
const ref = useRef(null);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
resultRef.current = ref.current;
|
|
12
|
+
}, []);
|
|
13
|
+
return _jsx(Button, Object.assign({ ref: ref }, { children: "Btn" }));
|
|
14
|
+
};
|
|
15
|
+
renderWithTheme(_jsx(ButtonWithRef, {}));
|
|
16
|
+
expect(resultRef === null || resultRef === void 0 ? void 0 : resultRef.current).not.toBeNull();
|
|
17
|
+
});
|
|
18
|
+
it('Prop:disabled: блокирует кнопку', () => {
|
|
19
|
+
renderWithTheme(_jsx(Button, Object.assign({ disabled: true }, { children: "Btn" })));
|
|
20
|
+
const button = screen.getByRole('button');
|
|
21
|
+
expect(button).toBeDisabled();
|
|
22
|
+
});
|
|
23
|
+
it('Prop:loading: блокирует кнопку', () => {
|
|
24
|
+
renderWithTheme(_jsx(Button, Object.assign({ loading: true }, { children: "Btn" })));
|
|
25
|
+
const button = screen.getByRole('button');
|
|
26
|
+
expect(button).toBeDisabled();
|
|
27
|
+
});
|
|
28
|
+
it('Prop:loading: отображается лоадер', () => {
|
|
29
|
+
renderWithTheme(_jsx(Button, Object.assign({ loading: true }, { children: "Btn" })));
|
|
30
|
+
const loader = screen.getByRole('progressbar');
|
|
31
|
+
expect(loader).toBeVisible();
|
|
32
|
+
});
|
|
33
|
+
});
|
package/esm/DataGrid/DataGrid.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useMemo } from 'react';
|
|
3
|
+
import { uniqBy } from 'lodash-es';
|
|
3
4
|
import { Table } from '../Table';
|
|
4
5
|
import { DataGridHead } from './DataGridHead';
|
|
5
6
|
import { DataGridBody } from './DataGridBody';
|
|
@@ -14,7 +15,7 @@ export function DataGrid({ columns, rows = [], selectedRows = [], sorting, maxHe
|
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
17
|
if (event.target.checked) {
|
|
17
|
-
const mergedSelectedRows = [...selectedRows, ...rows];
|
|
18
|
+
const mergedSelectedRows = uniqBy([...selectedRows, ...rows], keyId);
|
|
18
19
|
return onSelectRow(mergedSelectedRows);
|
|
19
20
|
}
|
|
20
21
|
const filteredRows = selectedRows.filter((selectedRow) => !rows.find((row) => row[keyId] === selectedRow[keyId]));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { renderWithTheme, screen, userEvents } from '@astral/tests';
|
|
12
|
+
import { useState } from 'react';
|
|
13
|
+
import { DataGrid } from './DataGrid';
|
|
14
|
+
describe('DataGrid', () => {
|
|
15
|
+
it('Props:columns: отображаются названия колонок', () => {
|
|
16
|
+
const columns = [
|
|
17
|
+
{
|
|
18
|
+
field: 'name',
|
|
19
|
+
label: 'Наименование',
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
renderWithTheme(_jsx(DataGrid, { keyId: "id", rows: [], columns: columns }));
|
|
23
|
+
const title = screen.getByText('Наименование');
|
|
24
|
+
expect(title).toBeVisible();
|
|
25
|
+
});
|
|
26
|
+
it('Props:columns:sortable: отображается иконка сортировки', () => {
|
|
27
|
+
const columns = [
|
|
28
|
+
{
|
|
29
|
+
field: 'name',
|
|
30
|
+
label: 'Наименование',
|
|
31
|
+
sortable: true,
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
renderWithTheme(_jsx(DataGrid, { keyId: "id", rows: [], columns: columns }));
|
|
35
|
+
const icon = screen.getByText('Наименование').querySelector('svg');
|
|
36
|
+
expect(icon).not.toBeNull();
|
|
37
|
+
});
|
|
38
|
+
it('Props:columns:sortable: по клику на head cell вызывается onSort', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
const columns = [
|
|
40
|
+
{
|
|
41
|
+
field: 'name',
|
|
42
|
+
label: 'Наименование',
|
|
43
|
+
sortable: true,
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
let currentSort;
|
|
47
|
+
const TestComponent = () => {
|
|
48
|
+
const [sorting, setSorting] = useState();
|
|
49
|
+
const handleSort = (sort) => {
|
|
50
|
+
currentSort = sort;
|
|
51
|
+
setSorting(sort);
|
|
52
|
+
};
|
|
53
|
+
return (_jsx(DataGrid, { keyId: "name", rows: [], sorting: sorting, onSort: handleSort, columns: columns }));
|
|
54
|
+
};
|
|
55
|
+
renderWithTheme(_jsx(TestComponent, {}));
|
|
56
|
+
expect(currentSort).toBe(undefined);
|
|
57
|
+
yield userEvents.click(screen.getByText('Наименование'));
|
|
58
|
+
expect(currentSort).toEqual({ fieldId: 'name', sort: 'asc' });
|
|
59
|
+
yield userEvents.click(screen.getByText('Наименование'));
|
|
60
|
+
expect(currentSort).toEqual({ fieldId: 'name', sort: 'desc' });
|
|
61
|
+
yield userEvents.click(screen.getByText('Наименование'));
|
|
62
|
+
expect(currentSort).toBe(undefined);
|
|
63
|
+
}));
|
|
64
|
+
it('Props:columns:field: отображает в строке данные по field', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
+
renderWithTheme(_jsx(DataGrid, { keyId: "name", rows: [{ name: 'Vasya' }], columns: [
|
|
66
|
+
{
|
|
67
|
+
field: 'name',
|
|
68
|
+
label: 'Наименование',
|
|
69
|
+
},
|
|
70
|
+
] }));
|
|
71
|
+
const title = screen.getByText('Vasya');
|
|
72
|
+
expect(title).toBeVisible();
|
|
73
|
+
}));
|
|
74
|
+
it('Props:options=[]: отображается placeholder', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
75
|
+
const columns = [
|
|
76
|
+
{
|
|
77
|
+
field: 'name',
|
|
78
|
+
label: 'Наименование',
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
renderWithTheme(_jsx(DataGrid, { keyId: "id", rows: [], columns: columns }));
|
|
82
|
+
const title = screen.getByText('Нет данных');
|
|
83
|
+
expect(title).toBeVisible();
|
|
84
|
+
}));
|
|
85
|
+
it('Props:onRowClick: по клику на строку получаем данные row', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
86
|
+
const onRowClick = jest.fn();
|
|
87
|
+
renderWithTheme(_jsx(DataGrid, { keyId: "name", rows: [{ name: 'Vasya' }], onRowClick: onRowClick, columns: [
|
|
88
|
+
{
|
|
89
|
+
field: 'name',
|
|
90
|
+
label: 'Наименование',
|
|
91
|
+
},
|
|
92
|
+
] }));
|
|
93
|
+
yield userEvents.click(screen.getByText('Vasya'));
|
|
94
|
+
expect(onRowClick.mock.calls[0][0]).toEqual({ name: 'Vasya' });
|
|
95
|
+
}));
|
|
96
|
+
// TODO: https://astraltrack.atlassian.net/browse/UIKIT-309
|
|
97
|
+
// it('Props:emptyCellValue: по дефолту для пустого значения отображается -', async () => {
|
|
98
|
+
// renderWithTheme(
|
|
99
|
+
// <DataGrid<{ name?: string }>
|
|
100
|
+
// keyId="name"
|
|
101
|
+
// rows={[{}]}
|
|
102
|
+
// columns={[
|
|
103
|
+
// {
|
|
104
|
+
// field: 'name',
|
|
105
|
+
// label: 'Наименование',
|
|
106
|
+
// },
|
|
107
|
+
// ]}
|
|
108
|
+
// />,
|
|
109
|
+
// );
|
|
110
|
+
//
|
|
111
|
+
// const emptySymbol = screen.getByText('-');
|
|
112
|
+
//
|
|
113
|
+
// expect(emptySymbol).toBeVisible();
|
|
114
|
+
// });
|
|
115
|
+
});
|
|
@@ -3,7 +3,7 @@ import { useCallback, useMemo } from 'react';
|
|
|
3
3
|
import { TableHead } from '../../Table/TableHead';
|
|
4
4
|
import { TableCell, TableRow } from '../../Table';
|
|
5
5
|
import { Checkbox } from '../../Checkbox';
|
|
6
|
-
import { SortStates } from '../
|
|
6
|
+
import { SortStates } from '../enums';
|
|
7
7
|
import { DataGridHeadColumn } from '../DataGridHeadColumn';
|
|
8
8
|
export function DataGridHead({ columns, selectable, onSelectAllRows, rowsCount, onSort, sorting, uncheckedRowsCount, }) {
|
|
9
9
|
const checked = useMemo(() => !Boolean(uncheckedRowsCount) && rowsCount > 0, [uncheckedRowsCount, rowsCount]);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMemo } from 'react';
|
|
3
3
|
import { SortDownFillSm, SortFillSm, SortUpFillSm } from '@astral/icons';
|
|
4
|
-
import { SortStates } from '../
|
|
4
|
+
import { SortStates } from '../enums';
|
|
5
5
|
import { StyledTableCell, TableCellTitle } from './styles';
|
|
6
6
|
export function DataGridHeadColumn({ onSort, field, sortable, align, label, sorting, width, }) {
|
|
7
7
|
const sortIcon = useMemo(() => {
|
|
File without changes
|
|
File without changes
|
package/esm/DataGrid/types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import { TableCellProps } from '@mui/material';
|
|
3
|
-
import { SortStates } from './
|
|
3
|
+
import { SortStates } from './enums';
|
|
4
4
|
export declare type CellValue = string | number | boolean | Date | undefined | object;
|
|
5
5
|
export declare type SortState = `${SortStates}`;
|
|
6
6
|
export declare type RenderCell<Data> = (params: Data) => ReactNode;
|
package/esm/Select/Select.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
import { SelectProps as MuiSelectProps } from '@mui/material';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
3
|
import { WithoutEmotionSpecific } from '../types';
|
|
4
4
|
export declare type SelectProps<Value> = WithoutEmotionSpecific<MuiSelectProps<Value>> & {
|
|
5
5
|
loading?: boolean;
|
|
6
6
|
placeholder?: string;
|
|
7
7
|
getOptionLabel?: (value: string | number) => string | number;
|
|
8
|
-
helperText?:
|
|
8
|
+
helperText?: ReactNode;
|
|
9
9
|
success?: boolean;
|
|
10
10
|
error?: boolean;
|
|
11
11
|
label?: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { renderHook, userEvents } from '@astral/tests';
|
|
11
|
+
import { useEscapeClickEffect } from './useEscapeClickEffect';
|
|
12
|
+
describe('useEscapeClickEffect', () => {
|
|
13
|
+
it('Props:isActive=true: при нажатии esc вызывается onEscape', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
14
|
+
const onEscape = jest.fn();
|
|
15
|
+
renderHook(() => useEscapeClickEffect({ isActive: true, onEscape }));
|
|
16
|
+
yield userEvents.keyboard('{Escape}');
|
|
17
|
+
expect(onEscape).toBeCalled();
|
|
18
|
+
}));
|
|
19
|
+
it('Props:isActive=false: при нажатии esc onEscape не вызывается', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
const onEscape = jest.fn();
|
|
21
|
+
renderHook(() => useEscapeClickEffect({ isActive: false, onEscape }));
|
|
22
|
+
yield userEvents.keyboard('{Escape}');
|
|
23
|
+
expect(onEscape).not.toBeCalled();
|
|
24
|
+
}));
|
|
25
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useMenu';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useMenu';
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const tests_1 = require("@astral/tests");
|
|
13
|
+
const useEscapeClickEffect_1 = require("./useEscapeClickEffect");
|
|
14
|
+
describe('useEscapeClickEffect', () => {
|
|
15
|
+
it('Props:isActive=true: при нажатии esc вызывается onEscape', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
+
const onEscape = jest.fn();
|
|
17
|
+
(0, tests_1.renderHook)(() => (0, useEscapeClickEffect_1.useEscapeClickEffect)({ isActive: true, onEscape }));
|
|
18
|
+
yield tests_1.userEvents.keyboard('{Escape}');
|
|
19
|
+
expect(onEscape).toBeCalled();
|
|
20
|
+
}));
|
|
21
|
+
it('Props:isActive=false: при нажатии esc onEscape не вызывается', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
+
const onEscape = jest.fn();
|
|
23
|
+
(0, tests_1.renderHook)(() => (0, useEscapeClickEffect_1.useEscapeClickEffect)({ isActive: false, onEscape }));
|
|
24
|
+
yield tests_1.userEvents.keyboard('{Escape}');
|
|
25
|
+
expect(onEscape).not.toBeCalled();
|
|
26
|
+
}));
|
|
27
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useMenu';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./useMenu"), exports);
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astral/ui",
|
|
3
|
-
"version": "1.39.
|
|
3
|
+
"version": "1.39.4",
|
|
4
4
|
"browser": "./esm/index.js",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@astral/icons": "^1.39.
|
|
7
|
+
"@astral/icons": "^1.39.4",
|
|
8
8
|
"@emotion/cache": "11.7.1",
|
|
9
9
|
"@emotion/react": "11.9.0",
|
|
10
10
|
"@emotion/server": "11.4.0",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MuiAutocomplete = void 0;
|
|
4
|
-
const
|
|
4
|
+
const enums_1 = require("../../Autocomplete/enums");
|
|
5
5
|
exports.MuiAutocomplete = {
|
|
6
6
|
styleOverrides: {
|
|
7
7
|
inputRoot({ theme, ownerState: { size } }) {
|
|
@@ -9,7 +9,7 @@ exports.MuiAutocomplete = {
|
|
|
9
9
|
paddingTop: `${theme.spacing(1)} !important`,
|
|
10
10
|
paddingBottom: `${theme.spacing(1)} !important`,
|
|
11
11
|
paddingLeft: `${theme.spacing(1)} !important`,
|
|
12
|
-
minHeight: size ===
|
|
12
|
+
minHeight: size === enums_1.AutocompleteSizes.small ? '32px' : '40px',
|
|
13
13
|
};
|
|
14
14
|
},
|
|
15
15
|
input({ theme }) {
|