@qoretechnologies/reqore 0.38.0 → 0.38.2
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__/dropdown.test.tsx +10 -8
- package/__tests__/table.test.tsx +0 -1
- package/build-storybook.log +144 -141
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +4 -4
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Checkbox/index.d.ts.map +1 -1
- package/dist/components/Checkbox/index.js +1 -1
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Dropdown/index.d.ts +2 -2
- package/dist/components/Dropdown/index.d.ts.map +1 -1
- package/dist/components/Dropdown/index.js +5 -5
- package/dist/components/Dropdown/index.js.map +1 -1
- package/dist/components/Dropdown/item.d.ts +6 -5
- package/dist/components/Dropdown/item.d.ts.map +1 -1
- package/dist/components/Dropdown/item.js +14 -6
- package/dist/components/Dropdown/item.js.map +1 -1
- package/dist/components/Dropdown/list.d.ts +4 -2
- package/dist/components/Dropdown/list.d.ts.map +1 -1
- package/dist/components/Dropdown/list.js +33 -7
- package/dist/components/Dropdown/list.js.map +1 -1
- package/dist/components/Input/index.d.ts.map +1 -1
- package/dist/components/Input/index.js +3 -3
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/InputClearButton/index.d.ts.map +1 -1
- package/dist/components/InputClearButton/index.js +1 -1
- package/dist/components/InputClearButton/index.js.map +1 -1
- package/dist/components/Menu/index.js +4 -4
- package/dist/components/Menu/index.js.map +1 -1
- package/dist/components/Menu/item.d.ts +1 -1
- package/dist/components/Menu/item.d.ts.map +1 -1
- package/dist/components/Menu/item.js +6 -6
- package/dist/components/Menu/item.js.map +1 -1
- package/dist/components/Message/index.d.ts.map +1 -1
- package/dist/components/Message/index.js +3 -4
- package/dist/components/Message/index.js.map +1 -1
- package/dist/components/MultiSelect/index.js +2 -2
- package/dist/components/MultiSelect/index.js.map +1 -1
- package/dist/components/Notifications/notification.d.ts +1 -0
- package/dist/components/Notifications/notification.d.ts.map +1 -1
- package/dist/components/Notifications/notification.js +10 -21
- package/dist/components/Notifications/notification.js.map +1 -1
- package/dist/components/Panel/LabelEditor.d.ts.map +1 -1
- package/dist/components/Panel/LabelEditor.js +1 -1
- package/dist/components/Panel/LabelEditor.js.map +1 -1
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js +26 -16
- package/dist/components/Panel/index.js.map +1 -1
- package/dist/components/Tabs/list.d.ts.map +1 -1
- package/dist/components/Tabs/list.js +3 -4
- package/dist/components/Tabs/list.js.map +1 -1
- package/dist/components/Tag/index.js +2 -2
- package/dist/components/Tag/index.js.map +1 -1
- package/dist/components/Textarea/index.d.ts +4 -0
- package/dist/components/Textarea/index.d.ts.map +1 -1
- package/dist/components/Textarea/index.js +29 -8
- package/dist/components/Textarea/index.js.map +1 -1
- package/dist/constants/sizes.d.ts +7 -0
- package/dist/constants/sizes.d.ts.map +1 -1
- package/dist/constants/sizes.js +8 -1
- package/dist/constants/sizes.js.map +1 -1
- package/migration-storybook.log +49 -81
- package/package.json +15 -15
- package/src/components/Button/index.tsx +5 -3
- package/src/components/Checkbox/index.tsx +7 -2
- package/src/components/Dropdown/index.tsx +16 -14
- package/src/components/Dropdown/item.tsx +26 -10
- package/src/components/Dropdown/list.tsx +80 -30
- package/src/components/Input/index.tsx +9 -3
- package/src/components/InputClearButton/index.tsx +1 -0
- package/src/components/Menu/index.tsx +2 -2
- package/src/components/Menu/item.tsx +93 -85
- package/src/components/Message/index.tsx +39 -35
- package/src/components/MultiSelect/index.tsx +2 -2
- package/src/components/Notifications/notification.tsx +34 -30
- package/src/components/Panel/LabelEditor.tsx +1 -0
- package/src/components/Panel/index.tsx +28 -17
- package/src/components/Tabs/list.tsx +7 -5
- package/src/components/Tag/index.tsx +3 -3
- package/src/components/Textarea/index.tsx +94 -30
- package/src/constants/sizes.ts +8 -0
- package/src/stories/Button/Button.stories.tsx +5 -0
- package/src/stories/Dropdown/Dropdown.stories.tsx +58 -0
- package/src/stories/Dropdown/DropdownTests.stories.tsx +111 -0
- package/src/stories/Input/Input.stories.tsx +1 -0
- package/src/stories/Message/Message.stories.tsx +13 -5
- package/src/stories/MultiSelect/MultiSelect.stories.tsx +2 -2
- package/src/stories/Panel/Panel.stories.tsx +96 -0
- package/src/stories/TextArea/TextArea.stories.tsx +50 -1
- package/src/stories/TextArea/TextAreaTests.stories.tsx +103 -0
- package/tests.json +1 -1
|
@@ -4,13 +4,7 @@ import React, { forwardRef, useEffect, useState } from 'react';
|
|
|
4
4
|
import { useMount, useUnmount } from 'react-use';
|
|
5
5
|
import styled, { css, keyframes } from 'styled-components';
|
|
6
6
|
import { SPRING_CONFIG } from '../../constants/animations';
|
|
7
|
-
import {
|
|
8
|
-
ICON_WRAPPER_FROM_HEADER_SIZE,
|
|
9
|
-
PADDING_FROM_SIZE,
|
|
10
|
-
TABS_SIZE_TO_PX,
|
|
11
|
-
TEXT_FROM_SIZE,
|
|
12
|
-
TSizes,
|
|
13
|
-
} from '../../constants/sizes';
|
|
7
|
+
import { PADDING_FROM_SIZE, TEXT_FROM_SIZE, TSizes } from '../../constants/sizes';
|
|
14
8
|
import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
|
|
15
9
|
import ReqoreThemeProvider from '../../containers/ThemeProvider';
|
|
16
10
|
import { fadeIn } from '../../helpers/animations';
|
|
@@ -82,7 +76,6 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
|
|
|
82
76
|
min-width: ${({ fluid }) => (!fluid ? '30px' : undefined)};
|
|
83
77
|
max-width: ${({ maxWidth, fluid, fixed }) => maxWidth || (fluid && !fixed ? '100%' : undefined)};
|
|
84
78
|
border-radius: 5px;
|
|
85
|
-
min-height: ${({ size = 'normal' }: IReqoreNotificationStyle) => TABS_SIZE_TO_PX[size]}px;
|
|
86
79
|
display: flex;
|
|
87
80
|
flex: ${({ fluid, fixed }) => (fixed ? '0 0 auto' : fluid ? '1 auto' : '0 0 auto')};
|
|
88
81
|
align-self: ${({ fixed, fluid }) => (fixed ? 'flex-start' : fluid ? 'stretch' : undefined)};
|
|
@@ -172,15 +165,12 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
|
|
|
172
165
|
`;
|
|
173
166
|
|
|
174
167
|
export const StyledIconWrapper = styled.div<IReqoreNotificationStyle>`
|
|
175
|
-
height: ${({ size = 'normal' }: IReqoreNotificationStyle) =>
|
|
176
|
-
ICON_WRAPPER_FROM_HEADER_SIZE[size]}px;
|
|
177
168
|
flex: 0 1 auto;
|
|
178
169
|
flex-shrink: 0;
|
|
179
170
|
display: flex;
|
|
180
171
|
justify-content: center;
|
|
181
172
|
align-items: center;
|
|
182
173
|
transition: all 0.2s ease-out;
|
|
183
|
-
margin-top: ${({ size = 'normal' }: IReqoreNotificationStyle) => `${PADDING_FROM_SIZE[size]}px`};
|
|
184
174
|
|
|
185
175
|
${({ clickable, theme, intent, type }) =>
|
|
186
176
|
clickable &&
|
|
@@ -202,12 +192,21 @@ export const StyledIconWrapper = styled.div<IReqoreNotificationStyle>`
|
|
|
202
192
|
`}
|
|
203
193
|
`;
|
|
204
194
|
|
|
205
|
-
export const
|
|
195
|
+
export const StyledNotificationInnerContent = styled.div<IReqoreNotificationStyle>`
|
|
206
196
|
flex: 1;
|
|
207
|
-
min-height: ${({ size = 'normal' }: IReqoreNotificationStyle) => TABS_SIZE_TO_PX[size]}px;
|
|
208
197
|
display: flex;
|
|
209
198
|
flex-flow: column;
|
|
210
199
|
justify-content: center;
|
|
200
|
+
|
|
201
|
+
.reqore-heading {
|
|
202
|
+
line-height: 1;
|
|
203
|
+
}
|
|
204
|
+
`;
|
|
205
|
+
|
|
206
|
+
export const StyledNotificationContentWrapper = styled.div<IReqoreNotificationStyle>`
|
|
207
|
+
flex: 1;
|
|
208
|
+
display: flex;
|
|
209
|
+
justify-content: center;
|
|
211
210
|
padding: ${({ size = 'normal' }: IReqoreNotificationStyle) => `${PADDING_FROM_SIZE[size]}px`};
|
|
212
211
|
`;
|
|
213
212
|
|
|
@@ -224,6 +223,9 @@ export const StyledNotificationContent = styled.div`
|
|
|
224
223
|
flex: 1;
|
|
225
224
|
font-size: ${({ size = 'normal' }) => TEXT_FROM_SIZE[size]}px;
|
|
226
225
|
overflow-wrap: anywhere;
|
|
226
|
+
display: flex;
|
|
227
|
+
flex-flow: column;
|
|
228
|
+
justify-content: center;
|
|
227
229
|
|
|
228
230
|
${({ hasTitle, size = 'normal' }) =>
|
|
229
231
|
hasTitle &&
|
|
@@ -317,24 +319,26 @@ const ReqoreNotification = forwardRef<HTMLDivElement, IReqoreNotificationProps>(
|
|
|
317
319
|
theme={theme}
|
|
318
320
|
maxWidth='450px'
|
|
319
321
|
>
|
|
320
|
-
{type || intent || icon ? (
|
|
321
|
-
<StyledIconWrapper type={type || intent} size={size}>
|
|
322
|
-
{intent === 'pending' || type === 'pending' ? (
|
|
323
|
-
<ReqoreSpinner size={size} type={5} iconMargin={'both'} />
|
|
324
|
-
) : (
|
|
325
|
-
<ReqoreIcon
|
|
326
|
-
icon={icon || typeToIcon[type || intent]}
|
|
327
|
-
margin={'both'}
|
|
328
|
-
size={size}
|
|
329
|
-
/>
|
|
330
|
-
)}
|
|
331
|
-
</StyledIconWrapper>
|
|
332
|
-
) : null}
|
|
333
322
|
<StyledNotificationContentWrapper size={size} theme={theme}>
|
|
334
|
-
{
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
323
|
+
{type || intent || icon ? (
|
|
324
|
+
<>
|
|
325
|
+
{intent === 'pending' || type === 'pending' ? (
|
|
326
|
+
<ReqoreSpinner size={size} type={5} iconMargin={'right'} />
|
|
327
|
+
) : (
|
|
328
|
+
<ReqoreIcon
|
|
329
|
+
icon={icon || typeToIcon[type || intent]}
|
|
330
|
+
margin={'right'}
|
|
331
|
+
size={size}
|
|
332
|
+
/>
|
|
333
|
+
)}
|
|
334
|
+
</>
|
|
335
|
+
) : null}
|
|
336
|
+
<StyledNotificationInnerContent>
|
|
337
|
+
{title && <ReqoreHeading size={size}>{title}</ReqoreHeading>}
|
|
338
|
+
<StyledNotificationContent theme={theme} hasTitle={!!title} size={size}>
|
|
339
|
+
{content}
|
|
340
|
+
</StyledNotificationContent>
|
|
341
|
+
</StyledNotificationInnerContent>
|
|
338
342
|
</StyledNotificationContentWrapper>
|
|
339
343
|
<StyledIconWrapper
|
|
340
344
|
type={type || intent}
|
|
@@ -273,11 +273,9 @@ export const StyledPanelTitle = styled.div<IStyledPanel>`
|
|
|
273
273
|
2 +
|
|
274
274
|
(SIZE_TO_PX[size] + ((transparent && flat) || minimal ? 0 : PADDING_FROM_SIZE[size]) * 2)}px;
|
|
275
275
|
align-items: center;
|
|
276
|
-
padding: ${({ noHorizontalPadding, size, transparent, flat,
|
|
276
|
+
padding: ${({ noHorizontalPadding, size, transparent, flat, intent }: IStyledPanel) =>
|
|
277
277
|
`${transparent && flat && !intent ? 0 : PADDING_FROM_SIZE[size]}px ${
|
|
278
|
-
noHorizontalPadding
|
|
279
|
-
? 0
|
|
280
|
-
: `${minimal ? PADDING_FROM_SIZE[size] / 2 : PADDING_FROM_SIZE[size]}px`
|
|
278
|
+
noHorizontalPadding ? 0 : `${PADDING_FROM_SIZE[size]}px`
|
|
281
279
|
}`};
|
|
282
280
|
border-bottom: ${({ theme, isCollapsed, flat, opacity = 1 }) =>
|
|
283
281
|
!isCollapsed && !flat
|
|
@@ -308,17 +306,21 @@ export const StyledPanelTitle = styled.div<IStyledPanel>`
|
|
|
308
306
|
`;
|
|
309
307
|
|
|
310
308
|
export const StyledPanelTopBar = styled(StyledPanelTitle)`
|
|
311
|
-
padding-bottom: ${({ minimal, padded, size }: IStyledPanel) =>
|
|
312
|
-
!padded
|
|
309
|
+
padding-bottom: ${({ minimal, padded, size, transparent, isCollapsed }: IStyledPanel) =>
|
|
310
|
+
!padded || isCollapsed
|
|
311
|
+
? `${PADDING_FROM_SIZE[size]}px`
|
|
312
|
+
: minimal || transparent
|
|
313
|
+
? 0
|
|
314
|
+
: undefined};
|
|
313
315
|
padding-top: ${({ minimal, size }: IStyledPanel) =>
|
|
314
|
-
minimal ? `${PADDING_FROM_SIZE[size]
|
|
316
|
+
minimal ? `${PADDING_FROM_SIZE[size]}px` : undefined};
|
|
315
317
|
`;
|
|
316
318
|
|
|
317
319
|
export const StyledPanelBottomActions = styled(StyledPanelTitle)`
|
|
318
|
-
padding-top: ${({ minimal, padded, size }: IStyledPanel) =>
|
|
319
|
-
!padded ? `${PADDING_FROM_SIZE[size]
|
|
320
|
+
padding-top: ${({ minimal, padded, size, transparent }: IStyledPanel) =>
|
|
321
|
+
!padded ? `${PADDING_FROM_SIZE[size]}px` : minimal || transparent ? 0 : undefined};
|
|
320
322
|
padding-bottom: ${({ minimal, size }: IStyledPanel) =>
|
|
321
|
-
minimal ? `${PADDING_FROM_SIZE[size]
|
|
323
|
+
minimal ? `${PADDING_FROM_SIZE[size]}px` : undefined};
|
|
322
324
|
border-bottom: 0;
|
|
323
325
|
border-top: ${({ theme, flat, opacity = 1 }) =>
|
|
324
326
|
!flat
|
|
@@ -333,13 +335,21 @@ export const StyledPanelContent = styled.div<IStyledPanel>`
|
|
|
333
335
|
? undefined
|
|
334
336
|
: noHorizontalPadding
|
|
335
337
|
? `${PADDING_FROM_SIZE[size]}px 0`
|
|
336
|
-
: `${
|
|
338
|
+
: `${PADDING_FROM_SIZE[size] / (minimal ? 2 : 1)}px ${PADDING_FROM_SIZE[size]}px`};
|
|
337
339
|
// The padding is not needed when the panel is minimal and has title, since
|
|
338
340
|
// the title already has padding and is transparent
|
|
339
341
|
padding-top: ${({ minimal, hasLabel, padded, size }) =>
|
|
340
|
-
minimal && hasLabel && padded
|
|
341
|
-
|
|
342
|
-
|
|
342
|
+
minimal && hasLabel && padded
|
|
343
|
+
? `${PADDING_FROM_SIZE[size] / 2}px`
|
|
344
|
+
: padded
|
|
345
|
+
? `${PADDING_FROM_SIZE[size]}px`
|
|
346
|
+
: undefined};
|
|
347
|
+
padding-bottom: ${({ minimal, padded, size, hasBottomActions }) =>
|
|
348
|
+
minimal && hasBottomActions && padded
|
|
349
|
+
? `${PADDING_FROM_SIZE[size] / 2}px`
|
|
350
|
+
: padded
|
|
351
|
+
? `${PADDING_FROM_SIZE[size]}px`
|
|
352
|
+
: undefined};
|
|
343
353
|
flex: 1;
|
|
344
354
|
overflow: auto;
|
|
345
355
|
overflow-wrap: anywhere;
|
|
@@ -719,7 +729,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
719
729
|
isMobile={isMobile || isSmall}
|
|
720
730
|
ref={measureRef}
|
|
721
731
|
padded={padded}
|
|
722
|
-
transparent={rest.transparent}
|
|
732
|
+
transparent={rest.transparent || opacity === 0}
|
|
723
733
|
intent={intent}
|
|
724
734
|
>
|
|
725
735
|
{hasTitleHeader && (
|
|
@@ -830,7 +840,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
830
840
|
<StyledPanelContent
|
|
831
841
|
as={'div'}
|
|
832
842
|
className='reqore-panel-content'
|
|
833
|
-
hasLabel={!!
|
|
843
|
+
hasLabel={!!hasTitleBar}
|
|
844
|
+
hasBottomActions={hasBottomActions}
|
|
834
845
|
isCollapsed={_isCollapsed}
|
|
835
846
|
style={contentStyle}
|
|
836
847
|
padded={padded}
|
|
@@ -850,7 +861,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
850
861
|
padded={padded}
|
|
851
862
|
intent={intent}
|
|
852
863
|
minimal={minimal}
|
|
853
|
-
transparent={rest.transparent}
|
|
864
|
+
transparent={rest.transparent || opacity === 0}
|
|
854
865
|
opacity={opacity ?? (minimal ? 0 : 1)}
|
|
855
866
|
size={contentSize || panelSize}
|
|
856
867
|
noHorizontalPadding={noHorizontalPadding}
|
|
@@ -5,10 +5,10 @@ import styled, { css } from 'styled-components';
|
|
|
5
5
|
import { IReqoreTabsListItem, IReqoreTabsProps } from '.';
|
|
6
6
|
import { ReqorePopover } from '../..';
|
|
7
7
|
import {
|
|
8
|
+
CONTROL_TEXT_FROM_SIZE,
|
|
8
9
|
GAP_FROM_SIZE,
|
|
9
10
|
ICON_FROM_SIZE,
|
|
10
11
|
PADDING_FROM_SIZE,
|
|
11
|
-
TEXT_FROM_SIZE,
|
|
12
12
|
TSizes,
|
|
13
13
|
} from '../../constants/sizes';
|
|
14
14
|
import { IReqoreBreadcrumbsTheme, IReqoreCustomTheme, IReqoreTheme } from '../../constants/theme';
|
|
@@ -100,8 +100,10 @@ const getBadgeLength = (badge: IReqoreButtonProps['badge'], tabsSize: TSizes = '
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
return (
|
|
103
|
-
calculateStringSizeInPixels(
|
|
104
|
-
|
|
103
|
+
calculateStringSizeInPixels(
|
|
104
|
+
badge.toString(),
|
|
105
|
+
CONTROL_TEXT_FROM_SIZE[getOneLessSize(tabsSize)]
|
|
106
|
+
) + PADDING_FROM_SIZE[tabsSize]
|
|
105
107
|
);
|
|
106
108
|
};
|
|
107
109
|
|
|
@@ -133,11 +135,11 @@ export const getLabelLength = (
|
|
|
133
135
|
? 0
|
|
134
136
|
: calculateStringSizeInPixels(
|
|
135
137
|
(item as IReqoreBreadcrumbItem | IReqoreTabsListItem)?.description?.toString(),
|
|
136
|
-
|
|
138
|
+
CONTROL_TEXT_FROM_SIZE[getOneLessSize(tabsSize)]
|
|
137
139
|
);
|
|
138
140
|
|
|
139
141
|
const topLabelLength =
|
|
140
|
-
calculateStringSizeInPixels(label?.toString(),
|
|
142
|
+
calculateStringSizeInPixels(label?.toString(), CONTROL_TEXT_FROM_SIZE[tabsSize]) +
|
|
141
143
|
icon +
|
|
142
144
|
rightIcon +
|
|
143
145
|
closeIconSize +
|
|
@@ -5,10 +5,10 @@ import styled, { css } from 'styled-components';
|
|
|
5
5
|
import { ReqorePopover, useReqoreTheme } from '../..';
|
|
6
6
|
import {
|
|
7
7
|
BADGE_SIZE_TO_PX,
|
|
8
|
+
CONTROL_TEXT_FROM_SIZE,
|
|
8
9
|
PADDING_FROM_SIZE,
|
|
9
10
|
RADIUS_FROM_SIZE,
|
|
10
11
|
SIZE_TO_PX,
|
|
11
|
-
TEXT_FROM_SIZE,
|
|
12
12
|
TSizes,
|
|
13
13
|
} from '../../constants/sizes';
|
|
14
14
|
import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
|
|
@@ -93,7 +93,7 @@ export const StyledTag = styled(StyledEffect)<IReqoreTagStyle>`
|
|
|
93
93
|
font-weight: 600;
|
|
94
94
|
overflow: hidden;
|
|
95
95
|
vertical-align: middle;
|
|
96
|
-
font-size: ${({ size }) =>
|
|
96
|
+
font-size: ${({ size }) => CONTROL_TEXT_FROM_SIZE[size]}px;
|
|
97
97
|
|
|
98
98
|
min-width: ${({ size }) => SIZE_TO_PX[size]}px;
|
|
99
99
|
max-width: ${({ fixed }) => (fixed !== true ? '100%' : undefined)};
|
|
@@ -213,7 +213,7 @@ const StyledTagContentKey = styled(StyledTagContent)`
|
|
|
213
213
|
|
|
214
214
|
const StyledButtonWrapper = styled.span<IReqoreTagStyle>`
|
|
215
215
|
flex-shrink: 0;
|
|
216
|
-
font-size: ${({ size }) =>
|
|
216
|
+
font-size: ${({ size }) => CONTROL_TEXT_FROM_SIZE[size]}px;
|
|
217
217
|
width: ${({ size }) => SIZE_TO_PX[size]}px;
|
|
218
218
|
display: flex;
|
|
219
219
|
justify-content: center;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { rgba } from 'polished';
|
|
2
|
-
import React, { forwardRef, useEffect, useState } from 'react';
|
|
2
|
+
import React, { forwardRef, useCallback, useEffect, useState } from 'react';
|
|
3
3
|
import styled, { css } from 'styled-components';
|
|
4
|
-
import {
|
|
4
|
+
import { ReqoreDropdown } from '../..';
|
|
5
|
+
import {
|
|
6
|
+
CONTROL_TEXT_FROM_SIZE,
|
|
7
|
+
PADDING_FROM_SIZE,
|
|
8
|
+
RADIUS_FROM_SIZE,
|
|
9
|
+
SIZE_TO_PX,
|
|
10
|
+
TSizes,
|
|
11
|
+
} from '../../constants/sizes';
|
|
5
12
|
import { IReqoreTheme } from '../../constants/theme';
|
|
6
13
|
import { changeLightness, getReadableColor } from '../../helpers/colors';
|
|
7
14
|
import { IReqoreAutoFocusRules, useAutoFocus } from '../../hooks/useAutoFocus';
|
|
@@ -18,10 +25,13 @@ import {
|
|
|
18
25
|
IWithReqoreEffect,
|
|
19
26
|
IWithReqoreTooltip,
|
|
20
27
|
} from '../../types/global';
|
|
28
|
+
import { IReqoreDropdownProps } from '../Dropdown';
|
|
21
29
|
import { StyledEffect } from '../Effect';
|
|
22
30
|
import { IReqoreInputStyle } from '../Input';
|
|
23
31
|
import ReqoreInputClearButton from '../InputClearButton';
|
|
24
32
|
|
|
33
|
+
export interface IReqoreFormTemplates extends IReqoreDropdownProps {}
|
|
34
|
+
|
|
25
35
|
export interface IReqoreTextareaProps
|
|
26
36
|
extends React.HTMLAttributes<HTMLTextAreaElement>,
|
|
27
37
|
IReqoreReadOnly,
|
|
@@ -46,6 +56,7 @@ export interface IReqoreTextareaProps
|
|
|
46
56
|
onClearClick?: () => any;
|
|
47
57
|
wrapperStyle?: React.CSSProperties;
|
|
48
58
|
focusRules?: IReqoreAutoFocusRules;
|
|
59
|
+
templates?: IReqoreFormTemplates;
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
export interface IReqoreTextareaStyle extends IReqoreTextareaProps {
|
|
@@ -62,16 +73,23 @@ export const StyledTextareaWrapper = styled.div<IReqoreTextareaStyle>`
|
|
|
62
73
|
align-self: ${({ fixed, fluid }) => (fixed ? 'flex-start' : fluid ? 'stretch' : undefined)};
|
|
63
74
|
position: relative;
|
|
64
75
|
overflow: hidden;
|
|
76
|
+
|
|
77
|
+
&:focus-within {
|
|
78
|
+
.reqore-clear-input-button {
|
|
79
|
+
display: flex;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
65
82
|
`;
|
|
66
83
|
|
|
67
84
|
export const StyledTextarea = styled(StyledEffect)<IReqoreTextareaStyle>`
|
|
68
85
|
width: 100%;
|
|
69
86
|
max-width: 100%;
|
|
70
87
|
max-height: 100%;
|
|
71
|
-
font-size: ${({ _size }) =>
|
|
88
|
+
font-size: ${({ _size }) => CONTROL_TEXT_FROM_SIZE[_size]}px;
|
|
72
89
|
margin: 0;
|
|
73
|
-
padding:
|
|
90
|
+
padding: ${({ _size }) => PADDING_FROM_SIZE[_size] / 2}px;
|
|
74
91
|
min-height: ${({ _size }) => SIZE_TO_PX[_size]}px;
|
|
92
|
+
line-height: ${({ _size }) => SIZE_TO_PX[_size] - CONTROL_TEXT_FROM_SIZE[_size]}px;
|
|
75
93
|
|
|
76
94
|
background-color: ${({ theme, minimal }: IReqoreInputStyle) =>
|
|
77
95
|
minimal ? 'transparent' : rgba(theme.main, 0.1)};
|
|
@@ -141,6 +159,7 @@ const ReqoreInput = forwardRef<HTMLTextAreaElement, IReqoreTextareaProps>(
|
|
|
141
159
|
onChange,
|
|
142
160
|
fixed,
|
|
143
161
|
focusRules,
|
|
162
|
+
templates,
|
|
144
163
|
...rest
|
|
145
164
|
}: IReqoreTextareaProps,
|
|
146
165
|
ref
|
|
@@ -158,6 +177,76 @@ const ReqoreInput = forwardRef<HTMLTextAreaElement, IReqoreTextareaProps>(
|
|
|
158
177
|
useAutosizeTextArea(inputRef, _value, scaleWithContent);
|
|
159
178
|
useAutoFocus(inputRef, rest.readOnly || rest.disabled ? undefined : focusRules, onChange);
|
|
160
179
|
|
|
180
|
+
const handleItemSelect = useCallback(
|
|
181
|
+
(item) => {
|
|
182
|
+
if (!inputRef || !item || !item.value) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// Add the value of the selected item to the current value at the cursor position
|
|
186
|
+
const value = `${_value.slice(0, inputRef.selectionStart)}${item.value}${_value.slice(
|
|
187
|
+
inputRef.selectionEnd
|
|
188
|
+
)}`;
|
|
189
|
+
|
|
190
|
+
setValue(value);
|
|
191
|
+
},
|
|
192
|
+
[inputRef, _value]
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const renderChildren = () => {
|
|
196
|
+
return (
|
|
197
|
+
<>
|
|
198
|
+
<StyledTextarea
|
|
199
|
+
{...rest}
|
|
200
|
+
effect={{
|
|
201
|
+
interactive: !rest?.disabled && !rest.readOnly,
|
|
202
|
+
...rest?.effect,
|
|
203
|
+
}}
|
|
204
|
+
onChange={(e) => {
|
|
205
|
+
setValue(e.target.value);
|
|
206
|
+
onChange?.(e);
|
|
207
|
+
}}
|
|
208
|
+
as='textarea'
|
|
209
|
+
className={`${className || ''} reqore-control reqore-textarea`}
|
|
210
|
+
_size={size}
|
|
211
|
+
ref={(ref) => setInputRef(ref)}
|
|
212
|
+
theme={theme}
|
|
213
|
+
rounded={rounded}
|
|
214
|
+
rows={1}
|
|
215
|
+
value={_value}
|
|
216
|
+
readonly={rest?.readOnly}
|
|
217
|
+
tabIndex={rest?.disabled ? -1 : 0}
|
|
218
|
+
/>
|
|
219
|
+
<ReqoreInputClearButton
|
|
220
|
+
enabled={!rest?.readOnly && !rest?.disabled && !!(onClearClick && onChange)}
|
|
221
|
+
show={_value && _value !== ''}
|
|
222
|
+
onClick={onClearClick}
|
|
223
|
+
size={size}
|
|
224
|
+
/>
|
|
225
|
+
</>
|
|
226
|
+
);
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
if (templates) {
|
|
230
|
+
return (
|
|
231
|
+
<ReqoreDropdown<Omit<IReqoreTextareaStyle & { ref: any }, 'content'>>
|
|
232
|
+
component={StyledTextareaWrapper}
|
|
233
|
+
className={`${className || ''} reqore-control-wrapper`}
|
|
234
|
+
width={width}
|
|
235
|
+
height={height}
|
|
236
|
+
fluid={fluid}
|
|
237
|
+
fixed={fixed}
|
|
238
|
+
_size={size}
|
|
239
|
+
theme={theme}
|
|
240
|
+
style={wrapperStyle}
|
|
241
|
+
ref={targetRef}
|
|
242
|
+
onItemSelect={handleItemSelect}
|
|
243
|
+
{...templates}
|
|
244
|
+
>
|
|
245
|
+
{renderChildren()}
|
|
246
|
+
</ReqoreDropdown>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
161
250
|
return (
|
|
162
251
|
<StyledTextareaWrapper
|
|
163
252
|
className={`${className || ''} reqore-control-wrapper`}
|
|
@@ -170,32 +259,7 @@ const ReqoreInput = forwardRef<HTMLTextAreaElement, IReqoreTextareaProps>(
|
|
|
170
259
|
style={wrapperStyle}
|
|
171
260
|
ref={targetRef}
|
|
172
261
|
>
|
|
173
|
-
|
|
174
|
-
{...rest}
|
|
175
|
-
effect={{
|
|
176
|
-
interactive: !rest?.disabled && !rest.readOnly,
|
|
177
|
-
...rest?.effect,
|
|
178
|
-
}}
|
|
179
|
-
onChange={(e) => {
|
|
180
|
-
setValue(e.target.value);
|
|
181
|
-
onChange?.(e);
|
|
182
|
-
}}
|
|
183
|
-
as='textarea'
|
|
184
|
-
className={`${className || ''} reqore-control reqore-textarea`}
|
|
185
|
-
_size={size}
|
|
186
|
-
ref={(ref) => setInputRef(ref)}
|
|
187
|
-
theme={theme}
|
|
188
|
-
rounded={rounded}
|
|
189
|
-
rows={1}
|
|
190
|
-
value={_value}
|
|
191
|
-
readonly={rest?.readOnly}
|
|
192
|
-
/>
|
|
193
|
-
<ReqoreInputClearButton
|
|
194
|
-
enabled={!rest?.readOnly && !rest?.disabled && !!(onClearClick && onChange)}
|
|
195
|
-
show={_value && _value !== ''}
|
|
196
|
-
onClick={onClearClick}
|
|
197
|
-
size={size}
|
|
198
|
-
/>
|
|
262
|
+
{renderChildren()}
|
|
199
263
|
</StyledTextareaWrapper>
|
|
200
264
|
);
|
|
201
265
|
}
|
package/src/constants/sizes.ts
CHANGED
|
@@ -109,6 +109,14 @@ export const TEXT_FROM_SIZE = {
|
|
|
109
109
|
huge: 21,
|
|
110
110
|
};
|
|
111
111
|
|
|
112
|
+
export const CONTROL_TEXT_FROM_SIZE = {
|
|
113
|
+
tiny: 7,
|
|
114
|
+
small: 10,
|
|
115
|
+
normal: 13,
|
|
116
|
+
big: 16,
|
|
117
|
+
huge: 19,
|
|
118
|
+
};
|
|
119
|
+
|
|
112
120
|
export const ICON_FROM_SIZE = {
|
|
113
121
|
tiny: 13,
|
|
114
122
|
small: 17,
|
|
@@ -48,6 +48,11 @@ const Template: StoryFn<typeof ReqoreButton> = (buttonProps) => {
|
|
|
48
48
|
<ReqoreButton {...buttonProps} minimal flat>
|
|
49
49
|
Minimal
|
|
50
50
|
</ReqoreButton>
|
|
51
|
+
<ReqoreButton {...buttonProps} icon={undefined} rightIcon={undefined} compact>
|
|
52
|
+
Compact
|
|
53
|
+
</ReqoreButton>
|
|
54
|
+
<ReqoreButton {...buttonProps} rightIcon={undefined} compact />
|
|
55
|
+
<ReqoreButton {...buttonProps} compact />
|
|
51
56
|
<ReqoreButton {...buttonProps} readOnly onClick={alert}>
|
|
52
57
|
Read only
|
|
53
58
|
</ReqoreButton>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { StoryFn, StoryObj } from '@storybook/react';
|
|
2
|
+
import { fireEvent, within } from '@storybook/testing-library';
|
|
2
3
|
import ReqoreButton, { IReqoreButtonProps } from '../../components/Button';
|
|
3
4
|
import { IReqoreDropdownProps } from '../../components/Dropdown';
|
|
5
|
+
import { sleep } from '../../helpers/utils';
|
|
4
6
|
import { ReqoreControlGroup, ReqoreDropdown, ReqoreInput } from '../../index';
|
|
5
7
|
import { StoryMeta } from '../utils';
|
|
6
8
|
import { argManager } from '../utils/args';
|
|
@@ -315,3 +317,59 @@ export const WithCustomPaging: Story = {
|
|
|
315
317
|
|
|
316
318
|
play: () => {},
|
|
317
319
|
};
|
|
320
|
+
|
|
321
|
+
export const WithChildItems: Story = {
|
|
322
|
+
render: (args) => <ReqoreDropdown {...args} />,
|
|
323
|
+
args: {
|
|
324
|
+
label: 'Dropdown with child items',
|
|
325
|
+
items: [
|
|
326
|
+
{
|
|
327
|
+
label: 'Test',
|
|
328
|
+
description: 'I have children',
|
|
329
|
+
rightIcon: 'MenuLine',
|
|
330
|
+
rightIconColor: 'info:lighten:2',
|
|
331
|
+
items: [
|
|
332
|
+
{
|
|
333
|
+
label: 'Test child 1',
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
label: 'Test child 2',
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
label: 'Test child 3',
|
|
340
|
+
description: 'I have children too',
|
|
341
|
+
items: [
|
|
342
|
+
{
|
|
343
|
+
label: 'Test deep child 1',
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
label: 'Test deep child 2',
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
label: 'Test deep child 3',
|
|
350
|
+
},
|
|
351
|
+
],
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
label: 'Test child 4',
|
|
355
|
+
},
|
|
356
|
+
],
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
label: 'Normal item',
|
|
360
|
+
description: 'I have no children',
|
|
361
|
+
},
|
|
362
|
+
],
|
|
363
|
+
},
|
|
364
|
+
play: async ({ canvasElement }) => {
|
|
365
|
+
const canvas = within(canvasElement);
|
|
366
|
+
|
|
367
|
+
await sleep(200);
|
|
368
|
+
|
|
369
|
+
await fireEvent.click(canvas.getAllByText('Dropdown with child items')[0]);
|
|
370
|
+
|
|
371
|
+
await sleep(200);
|
|
372
|
+
|
|
373
|
+
await fireEvent.click(canvas.getAllByText('Test')[0]);
|
|
374
|
+
},
|
|
375
|
+
};
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { expect } from '@storybook/jest';
|
|
2
|
+
import { StoryObj } from '@storybook/react';
|
|
3
|
+
import { fireEvent, waitFor, within } from '@storybook/testing-library';
|
|
4
|
+
import ReqoreButton, { IReqoreButtonProps } from '../../components/Button';
|
|
5
|
+
import { IReqoreDropdownProps } from '../../components/Dropdown';
|
|
6
|
+
import { sleep } from '../../helpers/utils';
|
|
7
|
+
import { ReqoreDropdown } from '../../index';
|
|
8
|
+
import { StoryMeta } from '../utils';
|
|
9
|
+
import { argManager } from '../utils/args';
|
|
10
|
+
import { WithChildItems } from './Dropdown.stories';
|
|
11
|
+
|
|
12
|
+
const { createArg, disableArg } = argManager<IReqoreDropdownProps>();
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: 'Form/Dropdown/Tests',
|
|
16
|
+
component: ReqoreDropdown,
|
|
17
|
+
parameters: {
|
|
18
|
+
chromatic: {
|
|
19
|
+
delay: 1500,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
argTypes: {
|
|
23
|
+
...disableArg('multiSelect'),
|
|
24
|
+
...createArg('component', {
|
|
25
|
+
defaultValue: ReqoreButton,
|
|
26
|
+
table: {
|
|
27
|
+
disable: true,
|
|
28
|
+
},
|
|
29
|
+
}),
|
|
30
|
+
...createArg('filterable', {
|
|
31
|
+
defaultValue: true,
|
|
32
|
+
name: 'Filterable',
|
|
33
|
+
type: 'boolean',
|
|
34
|
+
}),
|
|
35
|
+
...createArg('items', {
|
|
36
|
+
table: {
|
|
37
|
+
disable: true,
|
|
38
|
+
},
|
|
39
|
+
}),
|
|
40
|
+
},
|
|
41
|
+
args: {
|
|
42
|
+
component: ReqoreButton,
|
|
43
|
+
filterable: true,
|
|
44
|
+
},
|
|
45
|
+
} as StoryMeta<typeof ReqoreDropdown<IReqoreButtonProps>>;
|
|
46
|
+
|
|
47
|
+
export default meta;
|
|
48
|
+
|
|
49
|
+
type Story = StoryObj<typeof meta>;
|
|
50
|
+
|
|
51
|
+
export const ListIsClosedWhenItemIsClicked: Story = {
|
|
52
|
+
args: {
|
|
53
|
+
label: 'Default dropdown',
|
|
54
|
+
items: [
|
|
55
|
+
{
|
|
56
|
+
label: 'Test item 1',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: 'Test item 2',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
label: 'Test item 3',
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
play: async ({ canvasElement, ...rest }) => {
|
|
67
|
+
const canvas = within(canvasElement);
|
|
68
|
+
|
|
69
|
+
await sleep(200);
|
|
70
|
+
|
|
71
|
+
await fireEvent.click(canvas.getAllByText('Default dropdown')[0]);
|
|
72
|
+
|
|
73
|
+
await sleep(200);
|
|
74
|
+
|
|
75
|
+
await fireEvent.click(canvas.getAllByText('Test item 1')[0]);
|
|
76
|
+
|
|
77
|
+
await sleep(200);
|
|
78
|
+
|
|
79
|
+
await expect(document.querySelector('.reqore-popover-content')).toBeFalsy();
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const ItemsCanBeTraversed: Story = {
|
|
84
|
+
...WithChildItems,
|
|
85
|
+
play: async ({ canvasElement, ...rest }) => {
|
|
86
|
+
const canvas = within(canvasElement);
|
|
87
|
+
|
|
88
|
+
await WithChildItems.play({ canvasElement, ...rest });
|
|
89
|
+
|
|
90
|
+
await waitFor(() => expect(canvas.getAllByText('Test child 3')[0]).toBeTruthy(), {
|
|
91
|
+
timeout: 5000,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
await fireEvent.click(canvas.getAllByText('Test child 3')[0]);
|
|
95
|
+
|
|
96
|
+
await expect(canvas.getAllByText('Test deep child 3')[0]).toBeTruthy();
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export const BackButtonsWork: Story = {
|
|
101
|
+
...ItemsCanBeTraversed,
|
|
102
|
+
play: async ({ canvasElement, ...rest }) => {
|
|
103
|
+
const canvas = within(canvasElement);
|
|
104
|
+
|
|
105
|
+
await ItemsCanBeTraversed.play({ canvasElement, ...rest });
|
|
106
|
+
|
|
107
|
+
await fireEvent.click(document.querySelector('.reqore-dropdown-back-button'));
|
|
108
|
+
|
|
109
|
+
await expect(canvas.getAllByText('Test child 3')[0]).toBeTruthy();
|
|
110
|
+
},
|
|
111
|
+
};
|
|
@@ -107,6 +107,7 @@ const Template: StoryFn<typeof ReqoreInput> = (args: IReqoreInputProps) => {
|
|
|
107
107
|
placeholder='Clearable Input'
|
|
108
108
|
onClearClick={handleValueClear}
|
|
109
109
|
value={value}
|
|
110
|
+
focusRules={{ type: 'auto' }}
|
|
110
111
|
onChange={handleValueChange}
|
|
111
112
|
/>
|
|
112
113
|
<ReqoreInput
|