@max-ts/components 0.0.2 → 0.1.1
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/.storybook/main.ts +14 -14
- package/.turbo/turbo-build.log +11 -493
- package/.turbo/turbo-type$colon$check.log +1 -756
- package/CHANGELOG.md +12 -0
- package/dist/components/Autocomplete/styles.d.ts +1 -1
- package/dist/components/Button/Button.d.ts +4 -4
- package/dist/components/Button/useLogic/useLogic.d.ts +1 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +37 -0
- package/dist/components/ConfirmDialog/index.d.ts +1 -0
- package/dist/components/ConfirmDialog/styles.d.ts +9 -0
- package/dist/components/ConfirmDialog/useLogic/index.d.ts +1 -0
- package/dist/components/ConfirmDialog/useLogic/useLogic.d.ts +10 -0
- package/dist/components/DataGrid/Row/NestedChildren/styles.d.ts +1 -1
- package/dist/components/DataGrid/Row/styles.d.ts +1 -1
- package/dist/components/DropdownButton/DropdownButton.d.ts +9 -0
- package/dist/components/DropdownButton/index.d.ts +1 -0
- package/dist/components/Filename/Filename.d.ts +21 -0
- package/dist/components/Filename/index.d.ts +1 -0
- package/dist/components/Filename/styles.d.ts +17 -0
- package/dist/components/Filename/useLogic/index.d.ts +1 -0
- package/dist/components/Filename/useLogic/useLogic.d.ts +16 -0
- package/dist/components/Filename/useLogic/utils/findExtension/constants.d.ts +1 -0
- package/dist/components/Filename/useLogic/utils/findExtension/findExtension.d.ts +1 -0
- package/dist/components/Filename/useLogic/utils/findExtension/index.d.ts +1 -0
- package/dist/components/Filename/useLogic/utils/index.d.ts +1 -0
- package/dist/components/Filename/useLogic/utils/truncateString/constants.d.ts +1 -0
- package/dist/components/Filename/useLogic/utils/truncateString/index.d.ts +1 -0
- package/dist/components/Filename/useLogic/utils/truncateString/truncateString.d.ts +4 -0
- package/dist/components/FormLabel/FormLabel.d.ts +4 -0
- package/dist/components/FormLabel/index.d.ts +1 -0
- package/dist/components/FormLabel/styles.d.ts +1 -0
- package/dist/components/IconButton/IconButton.d.ts +2 -2
- package/dist/components/IconButton/styles.d.ts +2 -2
- package/dist/components/ListItemButton/ListItemButton.d.ts +2 -2
- package/dist/components/MenuItem/MenuItem.d.ts +1 -1
- package/dist/components/MenuList/types.d.ts +2 -2
- package/dist/components/NavMenu/Item/ItemButton/ItemButton.d.ts +1 -1
- package/dist/components/NavMenu/Item/ItemButton/styles.d.ts +1 -1
- package/dist/components/ProgressBar/ProgressBar.d.ts +12 -0
- package/dist/components/ProgressBar/index.d.ts +1 -0
- package/dist/components/Radio/Icon/Icon.d.ts +6 -0
- package/dist/components/Radio/Icon/index.d.ts +1 -0
- package/dist/components/Radio/Radio.d.ts +9 -0
- package/dist/components/Radio/constants.d.ts +8 -0
- package/dist/components/Radio/index.d.ts +1 -0
- package/dist/components/Radio/styles.d.ts +5 -0
- package/dist/components/RadioField/RadioField.d.ts +25 -0
- package/dist/components/RadioField/index.d.ts +1 -0
- package/dist/components/RadioField/styles.d.ts +2 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +30 -0
- package/dist/components/RadioGroup/RadioGroupContext/RadioGroupContext.d.ts +4 -0
- package/dist/components/RadioGroup/RadioGroupContext/RadioGroupContextProvider/RadioGroupContextProvider.d.ts +6 -0
- package/dist/components/RadioGroup/RadioGroupContext/RadioGroupContextProvider/index.d.ts +1 -0
- package/dist/components/RadioGroup/RadioGroupContext/index.d.ts +2 -0
- package/dist/components/RadioGroup/index.d.ts +2 -0
- package/dist/components/RadioGroupField/RadioGroupField.d.ts +8 -0
- package/dist/components/RadioGroupField/index.d.ts +1 -0
- package/dist/components/SearchField/styles.d.ts +1 -1
- package/dist/components/Select/styles.d.ts +2 -2
- package/dist/components/Skeleton/Skeleton.d.ts +14 -0
- package/dist/components/Skeleton/index.d.ts +1 -0
- package/dist/components/Skeleton/styles.d.ts +1 -0
- package/dist/components/Switch/Switch.d.ts +4 -0
- package/dist/components/Switch/index.d.ts +1 -0
- package/dist/components/Switch/styles.d.ts +1 -0
- package/dist/components/Tab/Tab.d.ts +7 -0
- package/dist/components/Tab/index.d.ts +1 -0
- package/dist/components/Tab/styles.d.ts +1 -0
- package/dist/components/Tabs/Tabs.d.ts +13 -0
- package/dist/components/Tabs/index.d.ts +1 -0
- package/dist/components/Tabs/styles.d.ts +2 -0
- package/dist/components/TextArea/TextArea.d.ts +3 -0
- package/dist/components/TextArea/index.d.ts +1 -0
- package/dist/components/index.d.ts +14 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useToggle/index.d.ts +1 -0
- package/dist/hooks/useToggle/useToggle.d.ts +43 -0
- package/dist/index.js +183 -49
- package/dist/index.mjs +312 -178
- package/package.json +1 -1
- package/rslib.config.ts +26 -26
- package/src/components/Accordion/Accordion.stories.tsx +2 -0
- package/src/components/ActionCell/ActionCell.stories.tsx +1 -0
- package/src/components/ActionCell/MainAction/MainAction.tsx +1 -0
- package/src/components/AsyncAutocomplete/AsyncAutocomplete.stories.tsx +1 -0
- package/src/components/Autocomplete/Autocomplete.stories.tsx +1 -0
- package/src/components/Badge/Badge.stories.tsx +1 -0
- package/src/components/BottomDrawer/BottomDrawer.stories.tsx +2 -1
- package/src/components/Button/Button.stories.tsx +2 -1
- package/src/components/Button/Button.tsx +9 -10
- package/src/components/Button/useLogic/useLogic.ts +2 -5
- package/src/components/Checkbox/Checkbox.stories.tsx +1 -3
- package/src/components/CheckboxField/CheckboxField.stories.tsx +1 -0
- package/src/components/Chevron/Chevron.stories.tsx +1 -0
- package/src/components/CircularProgress/CircularProgress.stories.tsx +1 -0
- package/src/components/Collapse/Collapse.stories.tsx +1 -0
- package/src/components/ConfirmAction/ConfirmAction.stories.tsx +1 -3
- package/src/components/ConfirmDialog/ConfirmDialog.stories.tsx +69 -0
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +83 -0
- package/src/components/ConfirmDialog/index.ts +1 -0
- package/src/components/ConfirmDialog/styles.ts +8 -0
- package/src/components/ConfirmDialog/useLogic/index.ts +1 -0
- package/src/components/ConfirmDialog/useLogic/useLogic.ts +23 -0
- package/src/components/ContentState/ContentState.stories.tsx +1 -0
- package/src/components/CopyTypography/CopyTypography.stories.tsx +1 -2
- package/src/components/DataGrid/DataGrid.stories.tsx +1 -0
- package/src/components/DataGridActionCell/DataGridActionCell.stories.tsx +1 -0
- package/src/components/DataGridPagination/DataGridPagination.stories.tsx +1 -0
- package/src/components/Description/Description.stories.tsx +1 -0
- package/src/components/DescriptionList/DescriptionList.stories.tsx +1 -0
- package/src/components/Dialog/Dialog.stories.tsx +1 -0
- package/src/components/DialogActions/DialogActions.stories.tsx +1 -3
- package/src/components/DialogContent/DialogContent.stories.tsx +1 -3
- package/src/components/DialogContentText/DialogContentText.stories.tsx +1 -0
- package/src/components/DialogHeader/DialogHeader.stories.tsx +1 -0
- package/src/components/Divider/Divider.stories.tsx +1 -0
- package/src/components/DropdownButton/DropdownButton.stories.tsx +191 -0
- package/src/components/DropdownButton/DropdownButton.tsx +46 -0
- package/src/components/DropdownButton/index.ts +1 -0
- package/src/components/ErrorBoundary/ErrorBoundary.stories.tsx +1 -0
- package/src/components/Filename/Filename.stories.tsx +244 -0
- package/src/components/Filename/Filename.tsx +57 -0
- package/src/components/Filename/index.ts +1 -0
- package/src/components/Filename/styles.ts +18 -0
- package/src/components/Filename/useLogic/index.ts +1 -0
- package/src/components/Filename/useLogic/useLogic.ts +36 -0
- package/src/components/Filename/useLogic/utils/findExtension/constants.ts +16 -0
- package/src/components/Filename/useLogic/utils/findExtension/findExtension.ts +17 -0
- package/src/components/Filename/useLogic/utils/findExtension/index.ts +1 -0
- package/src/components/Filename/useLogic/utils/index.ts +1 -0
- package/src/components/Filename/useLogic/utils/truncateString/constants.ts +1 -0
- package/src/components/Filename/useLogic/utils/truncateString/index.ts +1 -0
- package/src/components/Filename/useLogic/utils/truncateString/truncateString.ts +24 -0
- package/src/components/FormLabel/FormLabel.tsx +11 -0
- package/src/components/FormLabel/index.ts +1 -0
- package/src/components/FormLabel/styles.ts +6 -0
- package/src/components/GuidTypography/GuidTypography.stories.tsx +1 -0
- package/src/components/IconButton/IconButton.stories.tsx +1 -1
- package/src/components/IconButton/IconButton.tsx +11 -16
- package/src/components/IconButton/styles.ts +24 -24
- package/src/components/IconDropdownButton/IconDropdownButton.stories.tsx +1 -0
- package/src/components/InternalErrorPlaceholder/InternalErrorPlaceholder.stories.tsx +1 -0
- package/src/components/Link/Link.stories.tsx +1 -0
- package/src/components/List/List.stories.tsx +1 -0
- package/src/components/ListItem/ListItem.stories.tsx +1 -0
- package/src/components/ListItemButton/ListItemButton.stories.tsx +1 -0
- package/src/components/ListItemButton/ListItemButton.tsx +3 -9
- package/src/components/ListItemIcon/ListItemIcon.stories.tsx +1 -0
- package/src/components/ListItemText/ListItemText.stories.tsx +1 -0
- package/src/components/ListSubheader/ListSubheader.stories.tsx +1 -0
- package/src/components/Menu/Menu.stories.tsx +1 -0
- package/src/components/MenuItem/MenuItem.stories.tsx +1 -0
- package/src/components/MenuItem/MenuItem.tsx +1 -2
- package/src/components/MenuList/MenuList.stories.tsx +1 -0
- package/src/components/MenuList/types.ts +3 -8
- package/src/components/NavMenu/Item/ItemButton/ItemButton.tsx +1 -2
- package/src/components/NavMenu/NavMenu.stories.tsx +1 -0
- package/src/components/OutdatedReleasePlaceholder/OutdatedReleasePlaceholder.stories.tsx +1 -0
- package/src/components/OverflowTypography/OverflowTypography.stories.tsx +1 -8
- package/src/components/Pagination/Pagination.stories.tsx +1 -0
- package/src/components/Placeholder/Placeholder.stories.tsx +1 -0
- package/src/components/Popover/Popover.stories.tsx +1 -0
- package/src/components/ProgressBar/ProgressBar.stories.tsx +31 -0
- package/src/components/ProgressBar/ProgressBar.tsx +26 -0
- package/src/components/ProgressBar/index.ts +1 -0
- package/src/components/Radio/Icon/Icon.tsx +37 -0
- package/src/components/Radio/Icon/index.ts +1 -0
- package/src/components/Radio/Radio.stories.tsx +32 -0
- package/src/components/Radio/Radio.tsx +24 -0
- package/src/components/Radio/constants.ts +9 -0
- package/src/components/Radio/index.ts +1 -0
- package/src/components/Radio/styles.ts +70 -0
- package/src/components/RadioField/RadioField.stories.tsx +74 -0
- package/src/components/RadioField/RadioField.tsx +55 -0
- package/src/components/RadioField/index.ts +1 -0
- package/src/components/RadioField/styles.ts +10 -0
- package/src/components/RadioGroup/RadioGroup.stories.tsx +60 -0
- package/src/components/RadioGroup/RadioGroup.tsx +79 -0
- package/src/components/RadioGroup/RadioGroupContext/RadioGroupContext.ts +9 -0
- package/src/components/RadioGroup/RadioGroupContext/RadioGroupContextProvider/RadioGroupContextProvider.tsx +18 -0
- package/src/components/RadioGroup/RadioGroupContext/RadioGroupContextProvider/index.ts +1 -0
- package/src/components/RadioGroup/RadioGroupContext/index.ts +3 -0
- package/src/components/RadioGroup/index.ts +3 -0
- package/src/components/RadioGroupField/RadioGroupField.tsx +17 -0
- package/src/components/RadioGroupField/index.ts +1 -0
- package/src/components/Select/Select.stories.tsx +0 -4
- package/src/components/Skeleton/Skeleton.stories.tsx +78 -0
- package/src/components/Skeleton/Skeleton.tsx +31 -0
- package/src/components/Skeleton/index.ts +1 -0
- package/src/components/Skeleton/styles.ts +16 -0
- package/src/components/Switch/Switch.stories.tsx +179 -0
- package/src/components/Switch/Switch.tsx +14 -0
- package/src/components/Switch/index.ts +1 -0
- package/src/components/Switch/styles.ts +14 -0
- package/src/components/Tab/Tab.stories.tsx +53 -0
- package/src/components/Tab/Tab.tsx +20 -0
- package/src/components/Tab/index.ts +1 -0
- package/src/components/Tab/styles.ts +22 -0
- package/src/components/Tabs/Tabs.stories.tsx +74 -0
- package/src/components/Tabs/Tabs.tsx +27 -0
- package/src/components/Tabs/index.ts +1 -0
- package/src/components/Tabs/styles.ts +20 -0
- package/src/components/Tag/Tag.stories.tsx +1 -1
- package/src/components/TagBadge/TagBadge.stories.tsx +1 -5
- package/src/components/TextArea/TextArea.stories.tsx +81 -0
- package/src/components/TextArea/TextArea.tsx +8 -0
- package/src/components/TextArea/index.ts +1 -0
- package/src/components/TextField/TextField.stories.tsx +1 -4
- package/src/components/Tooltip/Tooltip.stories.tsx +1 -4
- package/src/components/Typography/Typography.stories.tsx +2 -4
- package/src/components/index.ts +28 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useToggle/index.ts +1 -0
- package/src/hooks/useToggle/useToggle.ts +76 -0
- package/test.tsx +1 -0
- package/tsconfig.json +3 -2
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import { Container, MenuItem, Typography } from '..';
|
|
4
|
+
|
|
5
|
+
import { MessageCircleMore } from 'lucide-react';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { DropdownButton } from './DropdownButton';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* DropdownButton - позволяет компактно разместить несколько вариантов действия в одном элементе.
|
|
11
|
+
*
|
|
12
|
+
* В большинстве случаев в качестве такого элемента выступает кнопка или пункт меню. Вызывается по клику или наведению на элемент.
|
|
13
|
+
|
|
14
|
+
*/
|
|
15
|
+
const meta: Meta<typeof DropdownButton> = {
|
|
16
|
+
title: 'Components/Buttons/DropdownButton',
|
|
17
|
+
component: DropdownButton,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
|
|
22
|
+
const dropdownContent = (
|
|
23
|
+
<>
|
|
24
|
+
<MenuItem onClick={() => console.log('v1')}>Вариант выбора 1</MenuItem>
|
|
25
|
+
<MenuItem onClick={() => console.log('v2')}>Вариант выбора 2</MenuItem>
|
|
26
|
+
<MenuItem onClick={() => console.log('v3')}>Вариант выбора 3</MenuItem>
|
|
27
|
+
</>
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
type Story = StoryObj<typeof DropdownButton>;
|
|
31
|
+
|
|
32
|
+
export const Interaction: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
children: dropdownContent,
|
|
35
|
+
name: 'Действие',
|
|
36
|
+
variant: 'contained',
|
|
37
|
+
color: 'primary',
|
|
38
|
+
size: 'large',
|
|
39
|
+
fullWidth: false,
|
|
40
|
+
},
|
|
41
|
+
parameters: {
|
|
42
|
+
docs: {
|
|
43
|
+
disable: true,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const Example = () => (
|
|
49
|
+
<Container gap={4}>
|
|
50
|
+
<DropdownButton name='Default'>{dropdownContent}</DropdownButton>
|
|
51
|
+
<DropdownButton disabled name='Disabled'>
|
|
52
|
+
{dropdownContent}
|
|
53
|
+
</DropdownButton>
|
|
54
|
+
<DropdownButton loading name='Loading'>
|
|
55
|
+
{dropdownContent}
|
|
56
|
+
</DropdownButton>
|
|
57
|
+
</Container>
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
export const StartIcon = () => {
|
|
61
|
+
return (
|
|
62
|
+
<DropdownButton
|
|
63
|
+
startIcon={<MessageCircleMore />}
|
|
64
|
+
variant='light'
|
|
65
|
+
name='With icon'
|
|
66
|
+
>
|
|
67
|
+
{dropdownContent}
|
|
68
|
+
</DropdownButton>
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export const Note = () => {
|
|
73
|
+
const dropdownItems = (
|
|
74
|
+
<>
|
|
75
|
+
<MenuItem note='Перейти в профиль' onClick={() => console.log('v1')}>
|
|
76
|
+
Профиль
|
|
77
|
+
</MenuItem>
|
|
78
|
+
<MenuItem onClick={() => console.log('v3')}>Выход</MenuItem>
|
|
79
|
+
</>
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<DropdownButton
|
|
84
|
+
startIcon={<MessageCircleMore />}
|
|
85
|
+
variant='light'
|
|
86
|
+
name='With icon'
|
|
87
|
+
>
|
|
88
|
+
{dropdownItems}
|
|
89
|
+
</DropdownButton>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const DisableReason = () => {
|
|
94
|
+
const dropdownItems = (
|
|
95
|
+
<>
|
|
96
|
+
<MenuItem
|
|
97
|
+
disabledReason='Заблокировано'
|
|
98
|
+
disabled
|
|
99
|
+
onClick={() => console.log('v1')}
|
|
100
|
+
>
|
|
101
|
+
Профиль
|
|
102
|
+
</MenuItem>
|
|
103
|
+
<MenuItem onClick={() => console.log('v3')}>Выход</MenuItem>
|
|
104
|
+
</>
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<DropdownButton
|
|
109
|
+
startIcon={<MessageCircleMore />}
|
|
110
|
+
variant='light'
|
|
111
|
+
name='With icon'
|
|
112
|
+
>
|
|
113
|
+
{dropdownItems}
|
|
114
|
+
</DropdownButton>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/** Для стилизации основной кнопки доступны ButtonProps */
|
|
119
|
+
export const ButtonProps = () => (
|
|
120
|
+
<Container gap={5}>
|
|
121
|
+
<Typography variant='h6'>Variant</Typography>
|
|
122
|
+
|
|
123
|
+
<Container gap={4}>
|
|
124
|
+
<DropdownButton name='Default'>{dropdownContent}</DropdownButton>
|
|
125
|
+
<DropdownButton variant='light' name='Light'>
|
|
126
|
+
{dropdownContent}
|
|
127
|
+
</DropdownButton>
|
|
128
|
+
<DropdownButton variant='text' name='Text'>
|
|
129
|
+
{dropdownContent}
|
|
130
|
+
</DropdownButton>
|
|
131
|
+
<DropdownButton variant='link' name='Link'>
|
|
132
|
+
{dropdownContent}
|
|
133
|
+
</DropdownButton>
|
|
134
|
+
</Container>
|
|
135
|
+
|
|
136
|
+
<Typography variant='h6'>Color</Typography>
|
|
137
|
+
|
|
138
|
+
<Container gap={4}>
|
|
139
|
+
<DropdownButton color='primary' name='Primary'>
|
|
140
|
+
{dropdownContent}
|
|
141
|
+
</DropdownButton>
|
|
142
|
+
<DropdownButton color='error' name='Error'>
|
|
143
|
+
{dropdownContent}
|
|
144
|
+
</DropdownButton>
|
|
145
|
+
<DropdownButton color='success' name='Success'>
|
|
146
|
+
{dropdownContent}
|
|
147
|
+
</DropdownButton>
|
|
148
|
+
<DropdownButton color='warning' name='Warning'>
|
|
149
|
+
{dropdownContent}
|
|
150
|
+
</DropdownButton>
|
|
151
|
+
</Container>
|
|
152
|
+
|
|
153
|
+
<Typography variant='h6'>Size</Typography>
|
|
154
|
+
|
|
155
|
+
<Container gap={6}>
|
|
156
|
+
<DropdownButton size='medium' name='Medium'>
|
|
157
|
+
{dropdownContent}
|
|
158
|
+
</DropdownButton>
|
|
159
|
+
<DropdownButton size='large' name='Large'>
|
|
160
|
+
{dropdownContent}
|
|
161
|
+
</DropdownButton>
|
|
162
|
+
</Container>
|
|
163
|
+
</Container>
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
/** Для управления параметрами popover доступны PopoverProps */
|
|
167
|
+
export const PopoverProps = () => {
|
|
168
|
+
return (
|
|
169
|
+
<>
|
|
170
|
+
<DropdownButton
|
|
171
|
+
name='Default'
|
|
172
|
+
variant='light'
|
|
173
|
+
popoverProps={{
|
|
174
|
+
anchorOrigin: { vertical: 'center', horizontal: 'right' },
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
{dropdownContent}
|
|
178
|
+
</DropdownButton>
|
|
179
|
+
<DropdownButton
|
|
180
|
+
name='Default'
|
|
181
|
+
variant='light'
|
|
182
|
+
popoverProps={{
|
|
183
|
+
anchorOrigin: { vertical: 'center', horizontal: 'right' },
|
|
184
|
+
transformOrigin: { vertical: 100, horizontal: 'right' },
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
{dropdownContent}
|
|
188
|
+
</DropdownButton>
|
|
189
|
+
</>
|
|
190
|
+
);
|
|
191
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ClickAwayListener, type PopoverProps } from '@mui/material';
|
|
2
|
+
|
|
3
|
+
import { useMenu } from '../../hooks';
|
|
4
|
+
import { Button, type ButtonProps } from '../Button';
|
|
5
|
+
import { Chevron } from '../Chevron';
|
|
6
|
+
import { Menu } from '../Menu';
|
|
7
|
+
|
|
8
|
+
export type DropdownButtonProps<RootComponent extends React.ElementType> = Omit<
|
|
9
|
+
ButtonProps<RootComponent>,
|
|
10
|
+
'endIcon' | 'selected' | 'onClick'
|
|
11
|
+
> & {
|
|
12
|
+
/** Название кнопки */
|
|
13
|
+
name: string;
|
|
14
|
+
/** Пропсы Popover компонента */
|
|
15
|
+
popoverProps?: Omit<PopoverProps, 'open'>;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const DropdownButton = <
|
|
19
|
+
TComponent extends React.ElementType = 'button',
|
|
20
|
+
>({
|
|
21
|
+
children,
|
|
22
|
+
name,
|
|
23
|
+
popoverProps,
|
|
24
|
+
...props
|
|
25
|
+
}: DropdownButtonProps<TComponent>) => {
|
|
26
|
+
const { open, anchorRef, handleOpenMenu, handleCloseMenu } = useMenu();
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<ClickAwayListener onClickAway={handleCloseMenu}>
|
|
31
|
+
<Button
|
|
32
|
+
{...(props as ButtonProps<'button'>)}
|
|
33
|
+
ref={anchorRef}
|
|
34
|
+
selected={open}
|
|
35
|
+
onClick={handleOpenMenu}
|
|
36
|
+
endIcon={<Chevron isActive={open} />}
|
|
37
|
+
>
|
|
38
|
+
{name}
|
|
39
|
+
</Button>
|
|
40
|
+
</ClickAwayListener>
|
|
41
|
+
<Menu open={open} anchorEl={anchorRef.current} {...popoverProps}>
|
|
42
|
+
{children}
|
|
43
|
+
</Menu>
|
|
44
|
+
</>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './DropdownButton';
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { type JSX, useEffect, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
import { ActionCell, type Actions } from '../ActionCell';
|
|
5
|
+
import {
|
|
6
|
+
DataGrid,
|
|
7
|
+
type DataGridColumns,
|
|
8
|
+
type DataGridRowOptions,
|
|
9
|
+
} from '../DataGrid';
|
|
10
|
+
|
|
11
|
+
import { styled } from '@mui/material';
|
|
12
|
+
import { Eye, Send } from 'lucide-react';
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import { Filename } from './Filename';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Filename применяется для отображения названий файлов, с автоматической проверкой текстового переполнения
|
|
18
|
+
*
|
|
19
|
+
* ### [Figma]()
|
|
20
|
+
* ### [Guide]()
|
|
21
|
+
*/
|
|
22
|
+
const meta: Meta<typeof Filename> = {
|
|
23
|
+
title: 'Components/Filename',
|
|
24
|
+
component: Filename,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default meta;
|
|
28
|
+
|
|
29
|
+
type Story = StoryObj<typeof Filename>;
|
|
30
|
+
|
|
31
|
+
export const Interaction: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
children:
|
|
34
|
+
'Версия 1.0Приложение No 10к Договору подряда No КрФ/15331/24 от\n' +
|
|
35
|
+
'25.04.2024.pdf',
|
|
36
|
+
},
|
|
37
|
+
parameters: {
|
|
38
|
+
docs: {
|
|
39
|
+
disable: true,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const Wrapper = styled('div')`
|
|
45
|
+
max-width: 400px;
|
|
46
|
+
min-width: 200px;
|
|
47
|
+
margin: 0 auto 10px;
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
type DataType = {
|
|
51
|
+
id: string;
|
|
52
|
+
documentName: JSX.Element;
|
|
53
|
+
direction: string;
|
|
54
|
+
createDate: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type SortField = 'documentName' | 'direction' | 'createDate';
|
|
58
|
+
|
|
59
|
+
const FAKE_DATA_OBJECT_TEMPLATE = {
|
|
60
|
+
id: '1',
|
|
61
|
+
documentName: <Filename>OS_FINAL_BDW_FW24_MeA_21022024.pdf</Filename>,
|
|
62
|
+
direction: 'ФНС',
|
|
63
|
+
createDate: '2022-03-24T17:50:40.206Z',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const FAKE_ACTIONS: Actions<DataType> = {
|
|
67
|
+
main: [
|
|
68
|
+
{
|
|
69
|
+
icon: <Eye />,
|
|
70
|
+
name: 'Просмотреть',
|
|
71
|
+
onClick: () => console.log('main'),
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
icon: <Send />,
|
|
75
|
+
nested: true,
|
|
76
|
+
name: 'Отправить',
|
|
77
|
+
actions: [
|
|
78
|
+
{ name: 'Туда', onClick: () => console.log('nested 1') },
|
|
79
|
+
{ name: 'Сюда', onClick: () => console.log('nested 2') },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
secondary: [
|
|
84
|
+
{ name: 'Редактировать', onClick: () => console.log('secondary 1') },
|
|
85
|
+
{ name: 'Удалить', onClick: () => console.log('secondary 2') },
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const generateRandomDate = () => {
|
|
90
|
+
const start = new Date(2022, 0, 1);
|
|
91
|
+
const end = new Date();
|
|
92
|
+
const randomTimestamp =
|
|
93
|
+
start.getTime() + Math.random() * (end.getTime() - start.getTime());
|
|
94
|
+
const randomDate = new Date(randomTimestamp);
|
|
95
|
+
|
|
96
|
+
return randomDate.toISOString();
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const generateData = (
|
|
100
|
+
dataObjTemplate: DataType,
|
|
101
|
+
options?: DataGridRowOptions<DataType>,
|
|
102
|
+
): DataType[] => {
|
|
103
|
+
const DIRECTIONS = ['ФНС', 'ФСС', 'ПФР', 'РПН'];
|
|
104
|
+
const DATA_ARRAY_LENGTH = 16;
|
|
105
|
+
const DOCUMENT_NAMES = [
|
|
106
|
+
<Filename key='1'>api-единая.-спецификация-api.docs</Filename>,
|
|
107
|
+
<Filename key='2'>OS_FINAL_BDW_FW24_MeA_21022024.pdf</Filename>,
|
|
108
|
+
<Filename key='3'>OS_FINAL_BDW_FW24_MeA.pdf</Filename>,
|
|
109
|
+
<Filename key='4'>OS_FINAL.pdf</Filename>,
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
return Array.from({ length: DATA_ARRAY_LENGTH })
|
|
113
|
+
.fill(dataObjTemplate)
|
|
114
|
+
.map((_, i) => ({
|
|
115
|
+
id: String(i + 1),
|
|
116
|
+
documentName:
|
|
117
|
+
DOCUMENT_NAMES[Math.floor(Math.random() * DOCUMENT_NAMES.length)],
|
|
118
|
+
direction: DIRECTIONS[Math.floor(Math.random() * DIRECTIONS.length)],
|
|
119
|
+
createDate: generateRandomDate(),
|
|
120
|
+
options: Math.random() < 0.5 ? options : undefined,
|
|
121
|
+
}));
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const Example = () => {
|
|
125
|
+
const fakeData = generateData(FAKE_DATA_OBJECT_TEMPLATE);
|
|
126
|
+
|
|
127
|
+
const columns: DataGridColumns<DataType>[] = [
|
|
128
|
+
{
|
|
129
|
+
field: 'documentName',
|
|
130
|
+
label: 'Наименование документа',
|
|
131
|
+
sortable: true,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
field: 'direction',
|
|
135
|
+
label: 'Направление',
|
|
136
|
+
sortable: true,
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
field: 'createDate',
|
|
140
|
+
label: 'Дата создания',
|
|
141
|
+
sortable: true,
|
|
142
|
+
format: ({ createDate }) => new Date(createDate).toLocaleDateString(),
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
label: 'Действия',
|
|
146
|
+
sortable: false,
|
|
147
|
+
align: 'center',
|
|
148
|
+
width: '120px',
|
|
149
|
+
renderCell: (row) => {
|
|
150
|
+
return <ActionCell actions={FAKE_ACTIONS} row={row} />;
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
const [isLoading, setLoading] = useState(true);
|
|
156
|
+
const [slicedData, setSlicedData] = useState<DataType[]>([]);
|
|
157
|
+
const [selected, setSelected] = useState<DataType[]>([]);
|
|
158
|
+
const handleSelect = (rows: DataType[]) => setSelected(rows);
|
|
159
|
+
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
setSlicedData(fakeData.slice(0, 10));
|
|
163
|
+
setLoading(false);
|
|
164
|
+
}, 1500);
|
|
165
|
+
}, []);
|
|
166
|
+
|
|
167
|
+
const handleRowClick = (row: DataType) => console.log('row clicked', row);
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<DataGrid<DataType, SortField>
|
|
171
|
+
keyId='id'
|
|
172
|
+
rows={slicedData}
|
|
173
|
+
columns={columns}
|
|
174
|
+
isLoading={isLoading}
|
|
175
|
+
selectedRows={selected}
|
|
176
|
+
onRowClick={handleRowClick}
|
|
177
|
+
onSelectRow={handleSelect}
|
|
178
|
+
onRetry={() => {}}
|
|
179
|
+
/>
|
|
180
|
+
);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const LongFileName = () => {
|
|
184
|
+
return (
|
|
185
|
+
<Wrapper>
|
|
186
|
+
<Filename>
|
|
187
|
+
Версия 1.0 Приложение No 10к Договору подряда No КрФ/15331/24 от
|
|
188
|
+
25.04.2024.pdf
|
|
189
|
+
</Filename>
|
|
190
|
+
</Wrapper>
|
|
191
|
+
);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const ShortFileName = () => {
|
|
195
|
+
return (
|
|
196
|
+
<Wrapper>
|
|
197
|
+
<Filename>Приложение №10.pdf</Filename>
|
|
198
|
+
</Wrapper>
|
|
199
|
+
);
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* prop ```align``` позволяет позиционировать текст
|
|
204
|
+
*/
|
|
205
|
+
export const Align = () => {
|
|
206
|
+
return (
|
|
207
|
+
<div>
|
|
208
|
+
<Wrapper>
|
|
209
|
+
<Filename>Приложение №10.pdf</Filename>
|
|
210
|
+
</Wrapper>
|
|
211
|
+
<Wrapper>
|
|
212
|
+
<Filename align='center'>Приложение №10.pdf</Filename>
|
|
213
|
+
</Wrapper>
|
|
214
|
+
<Wrapper>
|
|
215
|
+
<Filename align='right'>Приложение №10.pdf</Filename>
|
|
216
|
+
</Wrapper>
|
|
217
|
+
</div>
|
|
218
|
+
);
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
export const ComplexFileExtension = () => {
|
|
222
|
+
return (
|
|
223
|
+
<div>
|
|
224
|
+
<Wrapper>
|
|
225
|
+
<Filename>
|
|
226
|
+
Версия 1.0 Приложение No 10к Договору подряда No КрФ/15331/24 от
|
|
227
|
+
25.04.2024.xml.dist
|
|
228
|
+
</Filename>
|
|
229
|
+
</Wrapper>
|
|
230
|
+
<Wrapper>
|
|
231
|
+
<Filename>
|
|
232
|
+
Версия 1.0 Приложение No 10к Договору подряда No КрФ/15331/24 от
|
|
233
|
+
25.04.2024.tar.xz
|
|
234
|
+
</Filename>
|
|
235
|
+
</Wrapper>
|
|
236
|
+
<Wrapper>
|
|
237
|
+
<Filename>
|
|
238
|
+
Версия 1.0 Приложение No 10к Договору подряда No КрФ/15331/24 от
|
|
239
|
+
25.04.2024.xml.orig
|
|
240
|
+
</Filename>
|
|
241
|
+
</Wrapper>
|
|
242
|
+
</div>
|
|
243
|
+
);
|
|
244
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
|
|
3
|
+
import { type TooltipProps as BasicTooltipProps, Tooltip } from '../Tooltip';
|
|
4
|
+
import type { TypographyProps, TypographyVariant } from '../Typography';
|
|
5
|
+
|
|
6
|
+
import { FileBaseName, StyledTypography } from './styles';
|
|
7
|
+
import { useLogic } from './useLogic';
|
|
8
|
+
|
|
9
|
+
type TooltipProps = Omit<BasicTooltipProps, 'ref'>;
|
|
10
|
+
|
|
11
|
+
export type FileNameProps = Omit<TypographyProps, 'variant'> & {
|
|
12
|
+
/**
|
|
13
|
+
* Название файла
|
|
14
|
+
*/
|
|
15
|
+
children: string;
|
|
16
|
+
/**
|
|
17
|
+
* Cпособ кастомизировать тултип при необходимости
|
|
18
|
+
* @example <OverflowTypography tooltipProps={{placement: 'top-start'}} />
|
|
19
|
+
*/
|
|
20
|
+
tooltipProps?: Omit<TooltipProps, 'children'>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Применяет стили оформления темы
|
|
24
|
+
* @default inherit
|
|
25
|
+
*/
|
|
26
|
+
variant?: TypographyVariant | 'inherit';
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const Filename = forwardRef<HTMLElement, FileNameProps>(
|
|
30
|
+
(props, forwardedRef) => {
|
|
31
|
+
const { isOverflowed, suffixWithExtension, baseNameProps } = useLogic({
|
|
32
|
+
...props,
|
|
33
|
+
ref: forwardedRef,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const {
|
|
37
|
+
tooltipProps,
|
|
38
|
+
variant = 'inherit',
|
|
39
|
+
children,
|
|
40
|
+
align = 'left',
|
|
41
|
+
...restProps
|
|
42
|
+
} = props;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Tooltip
|
|
46
|
+
title={isOverflowed && children}
|
|
47
|
+
disableInteractive
|
|
48
|
+
{...tooltipProps}
|
|
49
|
+
>
|
|
50
|
+
<StyledTypography $align={align} variant={variant} {...restProps}>
|
|
51
|
+
<FileBaseName {...baseNameProps} />
|
|
52
|
+
<span>{suffixWithExtension}</span>
|
|
53
|
+
</StyledTypography>
|
|
54
|
+
</Tooltip>
|
|
55
|
+
);
|
|
56
|
+
},
|
|
57
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Filename';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { styled } from '@mui/material';
|
|
2
|
+
import { Typography } from '../Typography';
|
|
3
|
+
|
|
4
|
+
export const FileBaseName = styled('span')`
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
|
|
7
|
+
max-width: 100%;
|
|
8
|
+
|
|
9
|
+
text-overflow: ellipsis;
|
|
10
|
+
white-space: nowrap;
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
export const StyledTypography = styled(Typography, {
|
|
14
|
+
shouldForwardProp: (prop) => !['$align'].includes(prop.toString()),
|
|
15
|
+
})<{ $align: string }>`
|
|
16
|
+
display: flex;
|
|
17
|
+
justify-content: ${({ $align }) => $align};
|
|
18
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useLogic';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Ref } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useOverflowed } from '../../OverflowTypography/hooks';
|
|
4
|
+
import type { FileNameProps } from '../Filename';
|
|
5
|
+
|
|
6
|
+
import { truncateString } from './utils';
|
|
7
|
+
|
|
8
|
+
type SpanProps = {
|
|
9
|
+
children: string;
|
|
10
|
+
ref?: Ref<HTMLElement>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type UseLogicParams = FileNameProps & {
|
|
14
|
+
ref: Ref<HTMLElement>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type UseLogicResult = {
|
|
18
|
+
isOverflowed: boolean;
|
|
19
|
+
baseNameProps: SpanProps;
|
|
20
|
+
suffixWithExtension: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const useLogic = ({
|
|
24
|
+
ref: forwardedRef,
|
|
25
|
+
children,
|
|
26
|
+
}: UseLogicParams): UseLogicResult => {
|
|
27
|
+
const { ref, isOverflowed } = useOverflowed(forwardedRef);
|
|
28
|
+
|
|
29
|
+
const { baseName, suffixWithExtension } = truncateString(children);
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
baseNameProps: { ref, children: baseName },
|
|
33
|
+
isOverflowed,
|
|
34
|
+
suffixWithExtension,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const COMPLEX_EXTENSIONS: string[] = [
|
|
2
|
+
'.xml.dist',
|
|
3
|
+
'.xml.tpl',
|
|
4
|
+
'.xml.gz',
|
|
5
|
+
'.xml.bz2',
|
|
6
|
+
'.xml.zip',
|
|
7
|
+
'.xml.enc',
|
|
8
|
+
'.xml.sig',
|
|
9
|
+
'.xml.metadata',
|
|
10
|
+
'.xml.backup',
|
|
11
|
+
'.xml.orig',
|
|
12
|
+
'.tar.gz',
|
|
13
|
+
'.tar.bz2',
|
|
14
|
+
'.tar.xz',
|
|
15
|
+
'.tar.lz',
|
|
16
|
+
];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { COMPLEX_EXTENSIONS } from './constants';
|
|
2
|
+
|
|
3
|
+
export const findExtension = (filename: string) => {
|
|
4
|
+
for (const fileExtension of COMPLEX_EXTENSIONS) {
|
|
5
|
+
if (filename.endsWith(fileExtension)) {
|
|
6
|
+
return fileExtension;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const extensionIndex = filename.lastIndexOf('.');
|
|
11
|
+
|
|
12
|
+
if (extensionIndex !== -1) {
|
|
13
|
+
return filename.slice(extensionIndex);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return undefined;
|
|
17
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './findExtension';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './truncateString';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SUFFIX_LENGTH = 2;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './truncateString';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { findExtension } from '../findExtension';
|
|
2
|
+
|
|
3
|
+
import { SUFFIX_LENGTH } from './constants';
|
|
4
|
+
|
|
5
|
+
export const truncateString = (fileName: string) => {
|
|
6
|
+
const fileExtension = findExtension(fileName);
|
|
7
|
+
|
|
8
|
+
if (fileExtension && fileName.endsWith(fileExtension)) {
|
|
9
|
+
const baseName = fileName.slice(
|
|
10
|
+
0,
|
|
11
|
+
fileName.length - fileExtension.length - SUFFIX_LENGTH,
|
|
12
|
+
);
|
|
13
|
+
const suffixWithExtension = fileName.slice(
|
|
14
|
+
-fileExtension.length - SUFFIX_LENGTH,
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
return { baseName, suffixWithExtension };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const baseName = fileName.slice(0, -SUFFIX_LENGTH);
|
|
21
|
+
const suffixWithExtension = fileName.slice(-SUFFIX_LENGTH);
|
|
22
|
+
|
|
23
|
+
return { baseName, suffixWithExtension };
|
|
24
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FormLabelProps as MuiFormLabelProps } from '@mui/material';
|
|
2
|
+
|
|
3
|
+
import type { WithoutEmotionSpecific } from '../types';
|
|
4
|
+
|
|
5
|
+
import { StyledFormLabel } from './styles';
|
|
6
|
+
|
|
7
|
+
export type FormLabelProps = WithoutEmotionSpecific<MuiFormLabelProps>;
|
|
8
|
+
|
|
9
|
+
export const FormLabel = (props: FormLabelProps) => {
|
|
10
|
+
return <StyledFormLabel {...props} />;
|
|
11
|
+
};
|