@qoretechnologies/reqore 0.29.0 → 0.29.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__/checkbox.test.tsx +7 -12
- package/__tests__/multiselect.test.tsx +46 -0
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +4 -2
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Checkbox/index.d.ts +9 -2
- package/dist/components/Checkbox/index.d.ts.map +1 -1
- package/dist/components/Checkbox/index.js +61 -31
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Effect/index.d.ts +18 -4
- package/dist/components/Effect/index.d.ts.map +1 -1
- package/dist/components/Effect/index.js +67 -26
- package/dist/components/Effect/index.js.map +1 -1
- package/dist/components/Icon/index.d.ts +2 -9
- package/dist/components/Icon/index.d.ts.map +1 -1
- package/dist/components/Icon/index.js +4 -28
- package/dist/components/Icon/index.js.map +1 -1
- package/dist/components/InternalPopover/index.d.ts.map +1 -1
- package/dist/components/InternalPopover/index.js +16 -2
- package/dist/components/InternalPopover/index.js.map +1 -1
- package/dist/components/Menu/divider.d.ts +1 -1
- package/dist/components/Menu/divider.d.ts.map +1 -1
- package/dist/components/MultiSelect/index.d.ts +4 -2
- package/dist/components/MultiSelect/index.d.ts.map +1 -1
- package/dist/components/MultiSelect/index.js +15 -14
- package/dist/components/MultiSelect/index.js.map +1 -1
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js.map +1 -1
- package/dist/components/RadioGroup/index.d.ts +4 -1
- package/dist/components/RadioGroup/index.d.ts.map +1 -1
- package/dist/components/RadioGroup/index.js +2 -2
- package/dist/components/RadioGroup/index.js.map +1 -1
- package/dist/components/Tag/index.d.ts +1 -1
- package/dist/components/Tag/index.d.ts.map +1 -1
- package/dist/components/Tag/index.js +17 -14
- package/dist/components/Tag/index.js.map +1 -1
- package/dist/components/Textarea/index.js +3 -3
- 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/dist/constants/theme.d.ts +4 -1
- package/dist/constants/theme.d.ts.map +1 -1
- package/dist/constants/theme.js.map +1 -1
- package/dist/helpers/colors.d.ts +5 -4
- package/dist/helpers/colors.d.ts.map +1 -1
- package/dist/helpers/colors.js +35 -8
- package/dist/helpers/colors.js.map +1 -1
- package/dist/hooks/useReqoreEffect.d.ts +4 -0
- package/dist/hooks/useReqoreEffect.d.ts.map +1 -0
- package/dist/hooks/useReqoreEffect.js +42 -0
- package/dist/hooks/useReqoreEffect.js.map +1 -0
- package/dist/hooks/useTheme.d.ts +1 -0
- package/dist/hooks/useTheme.d.ts.map +1 -1
- package/dist/hooks/useTheme.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Button/index.tsx +5 -3
- package/src/components/Checkbox/index.tsx +217 -38
- package/src/components/Effect/index.tsx +125 -17
- package/src/components/Icon/index.tsx +4 -52
- package/src/components/InternalPopover/index.tsx +3 -0
- package/src/components/Menu/divider.tsx +1 -1
- package/src/components/MultiSelect/index.tsx +20 -11
- package/src/components/Panel/index.tsx +3 -3
- package/src/components/RadioGroup/index.tsx +10 -2
- package/src/components/Tag/index.tsx +19 -13
- package/src/components/Textarea/index.tsx +3 -3
- package/src/constants/sizes.ts +8 -0
- package/src/constants/theme.ts +8 -1
- package/src/helpers/colors.ts +54 -11
- package/src/hooks/useReqoreEffect.ts +49 -0
- package/src/hooks/useTheme.ts +2 -1
- package/src/index.tsx +2 -0
- package/src/mock/collectionData.tsx +6 -6
- package/src/mock/multiSelect.ts +8 -0
- package/src/stories/Button/Button.stories.tsx +14 -0
- package/src/stories/Checkbox/Checkbox.stories.tsx +42 -7
- package/src/stories/Icon/Icon.stories.tsx +42 -12
- package/src/stories/Menu/Menu.stories.tsx +2 -1
- package/src/stories/MultiSelect/MultiSelect.stories.tsx +9 -2
- package/src/stories/Panel/Panel.stories.tsx +1 -1
- package/src/stories/Popover/Popover.stories.tsx +19 -2
- package/src/stories/RadioGroup/RadioGroup.stories.tsx +98 -1
- package/src/stories/Tag/Tag.stories.tsx +2 -2
- package/src/stories/utils/args.ts +1 -1
- package/tests.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { rgba } from 'polished';
|
|
2
2
|
import { HTMLAttributes } from 'react';
|
|
3
|
-
import styled, { css } from 'styled-components';
|
|
3
|
+
import styled, { css, keyframes } from 'styled-components';
|
|
4
|
+
import { Colors } from '../../constants/colors';
|
|
4
5
|
import { TEXT_FROM_SIZE, TSizes, WEIGHT_TO_NUMBER } from '../../constants/sizes';
|
|
5
6
|
import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
|
|
6
7
|
import {
|
|
@@ -23,20 +24,41 @@ export type TReqoreEffectColor =
|
|
|
23
24
|
| `${TReqoreIntent}:${TReqoreEffectColorManipulation}:${TReqoreEffectColorManipulationMultiplier}`
|
|
24
25
|
| 'main'
|
|
25
26
|
| `main:${TReqoreEffectColorManipulation}`
|
|
26
|
-
| `main:${TReqoreEffectColorManipulation}:${TReqoreEffectColorManipulationMultiplier}
|
|
27
|
+
| `main:${TReqoreEffectColorManipulation}:${TReqoreEffectColorManipulationMultiplier}`
|
|
28
|
+
| `${TReqoreHexColor}:${TReqoreEffectColorManipulation}`
|
|
29
|
+
| `${TReqoreHexColor}:${TReqoreEffectColorManipulation}:${TReqoreEffectColorManipulationMultiplier}`;
|
|
27
30
|
export type TReqoreEffectColorList = [
|
|
28
31
|
'main' | TReqoreIntent | TReqoreColor,
|
|
29
32
|
TReqoreEffectColorManipulation | undefined,
|
|
30
33
|
TReqoreEffectColorManipulationMultiplier | undefined
|
|
31
34
|
];
|
|
35
|
+
export type TReqoreEffectGradientColors =
|
|
36
|
+
| 'main'
|
|
37
|
+
| TReqoreIntent
|
|
38
|
+
| TReqoreHexColor
|
|
39
|
+
| TReqoreEffectGradientColorsObject;
|
|
40
|
+
export type TReqoreEffectGradientColorsObject = Record<number, TReqoreEffectColor>;
|
|
41
|
+
export type TReqoreEffectGradientAnimationTrigger = 'always' | 'hover' | 'active' | 'never';
|
|
42
|
+
|
|
43
|
+
export interface IReqoreEffectFilters {
|
|
44
|
+
grayscale?: boolean;
|
|
45
|
+
blur?: number;
|
|
46
|
+
sepia?: boolean;
|
|
47
|
+
invert?: boolean;
|
|
48
|
+
opacity?: number;
|
|
49
|
+
brightness?: number;
|
|
50
|
+
contrast?: number;
|
|
51
|
+
saturate?: number;
|
|
52
|
+
}
|
|
32
53
|
|
|
33
|
-
export interface IReqoreEffect {
|
|
54
|
+
export interface IReqoreEffect extends IReqoreEffectFilters {
|
|
34
55
|
gradient?: {
|
|
35
56
|
type?: 'linear' | 'radial';
|
|
36
57
|
shape?: 'circle' | 'ellipse';
|
|
37
|
-
colors:
|
|
58
|
+
colors: TReqoreEffectGradientColors;
|
|
38
59
|
direction?: string;
|
|
39
60
|
borderColor?: TReqoreEffectColor;
|
|
61
|
+
animate?: TReqoreEffectGradientAnimationTrigger;
|
|
40
62
|
};
|
|
41
63
|
noWrap?: boolean;
|
|
42
64
|
color?: TReqoreEffectColor;
|
|
@@ -50,7 +72,6 @@ export interface IReqoreEffect {
|
|
|
50
72
|
color: TReqoreEffectColor;
|
|
51
73
|
inset?: boolean;
|
|
52
74
|
blur?: number;
|
|
53
|
-
useBorder?: boolean;
|
|
54
75
|
};
|
|
55
76
|
interactive?: boolean;
|
|
56
77
|
}
|
|
@@ -63,13 +84,27 @@ export interface IReqoreTextEffectProps
|
|
|
63
84
|
as?: React.ElementType;
|
|
64
85
|
theme?: IReqoreTheme;
|
|
65
86
|
active?: boolean;
|
|
87
|
+
isText?: boolean;
|
|
66
88
|
}
|
|
67
89
|
|
|
90
|
+
// Animate the gradient
|
|
91
|
+
const StyledGradientKeyframes = keyframes`
|
|
92
|
+
0% {
|
|
93
|
+
background-position: 0% 0%;
|
|
94
|
+
}
|
|
95
|
+
50% {
|
|
96
|
+
background-position: 100% 100%;
|
|
97
|
+
}
|
|
98
|
+
100% {
|
|
99
|
+
background-position: 0% 0%;
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
|
|
68
103
|
export const StyledEffect = styled.span`
|
|
69
104
|
transition: all 0.2s ease-in-out;
|
|
70
105
|
|
|
71
106
|
// If gradient was supplied
|
|
72
|
-
${({ effect, theme, minimal, active }: IReqoreTextEffectProps) => {
|
|
107
|
+
${({ effect, theme, minimal, active, isText }: IReqoreTextEffectProps) => {
|
|
73
108
|
if (!effect || !effect.gradient) {
|
|
74
109
|
return undefined;
|
|
75
110
|
}
|
|
@@ -79,7 +114,7 @@ export const StyledEffect = styled.span`
|
|
|
79
114
|
theme,
|
|
80
115
|
effect.gradient.colors,
|
|
81
116
|
0,
|
|
82
|
-
minimal && !active
|
|
117
|
+
!isText && minimal && !active
|
|
83
118
|
);
|
|
84
119
|
const gradientColorsActive = createEffectGradient(theme, effect.gradient.colors, 0.05);
|
|
85
120
|
|
|
@@ -107,7 +142,7 @@ export const StyledEffect = styled.span`
|
|
|
107
142
|
getColorFromMaybeString(theme, effect.gradient.borderColor),
|
|
108
143
|
0.15
|
|
109
144
|
)}`;
|
|
110
|
-
} else {
|
|
145
|
+
} else if (!isText) {
|
|
111
146
|
// We will use border-image and create a gradient border
|
|
112
147
|
borderColor = 'transparent';
|
|
113
148
|
borderHoverColor = 'transparent';
|
|
@@ -142,6 +177,13 @@ export const StyledEffect = styled.span`
|
|
|
142
177
|
}
|
|
143
178
|
`}
|
|
144
179
|
|
|
180
|
+
${effect.gradient.animate === 'always' || (effect.gradient.animate === 'active' && active)
|
|
181
|
+
? css`
|
|
182
|
+
background-size: 200% 200%;
|
|
183
|
+
animation: ${StyledGradientKeyframes} 1.5s linear infinite;
|
|
184
|
+
`
|
|
185
|
+
: undefined}
|
|
186
|
+
|
|
145
187
|
${effect.interactive &&
|
|
146
188
|
css`
|
|
147
189
|
cursor: pointer;
|
|
@@ -151,26 +193,43 @@ export const StyledEffect = styled.span`
|
|
|
151
193
|
&:active {
|
|
152
194
|
background: ${gradientActive};
|
|
153
195
|
border-color: ${borderHoverColor} !important;
|
|
196
|
+
|
|
197
|
+
${effect.gradient.animate === 'hover' ||
|
|
198
|
+
(effect.gradient.animate === 'active' && active) ||
|
|
199
|
+
effect.gradient.animate === 'always'
|
|
200
|
+
? css`
|
|
201
|
+
background-size: 200% 200%;
|
|
202
|
+
animation: ${StyledGradientKeyframes} 2s linear infinite;
|
|
203
|
+
`
|
|
204
|
+
: undefined}
|
|
154
205
|
}
|
|
155
206
|
`}
|
|
156
207
|
`;
|
|
157
208
|
}}
|
|
158
209
|
|
|
159
|
-
${({ effect, theme }: IReqoreTextEffectProps) => {
|
|
210
|
+
${({ effect, theme, isText }: IReqoreTextEffectProps) => {
|
|
160
211
|
if (!effect || !effect.glow) {
|
|
161
212
|
return undefined;
|
|
162
213
|
}
|
|
163
214
|
|
|
164
|
-
if (
|
|
215
|
+
if (!isText) {
|
|
165
216
|
return css`
|
|
166
|
-
|
|
167
|
-
${getColorFromMaybeString(theme, effect.glow.color)}
|
|
217
|
+
box-shadow: ${effect.glow.inset ? 'inset ' : ''} 0 0 ${effect.glow.blur || 0}px
|
|
218
|
+
${effect.glow.size || 2}px ${getColorFromMaybeString(theme, effect.glow.color)};
|
|
168
219
|
`;
|
|
169
220
|
}
|
|
170
221
|
|
|
222
|
+
const color = getColorFromMaybeString(
|
|
223
|
+
theme,
|
|
224
|
+
effect.glow.color === 'main' ? 'main:lighten:2' : effect.glow.color
|
|
225
|
+
);
|
|
226
|
+
const blur = effect.glow.blur || 0;
|
|
227
|
+
|
|
171
228
|
return css`
|
|
172
|
-
|
|
173
|
-
|
|
229
|
+
color: ${Colors.LIGHT};
|
|
230
|
+
text-shadow: 0 0 ${blur}px ${color}, 0 0 ${blur + 5}px ${color}, 0 0 ${blur + 10}px ${color},
|
|
231
|
+
0 0 1px ${getReadableColorFrom(color)}, 0 0 2px ${getReadableColorFrom(color)},
|
|
232
|
+
0 0 3px ${getReadableColorFrom(color)};
|
|
174
233
|
`;
|
|
175
234
|
}}
|
|
176
235
|
|
|
@@ -231,16 +290,65 @@ export const StyledEffect = styled.span`
|
|
|
231
290
|
text-align: ${effect.textAlign};
|
|
232
291
|
`
|
|
233
292
|
: undefined}
|
|
293
|
+
|
|
294
|
+
${({ effect }) =>
|
|
295
|
+
effect &&
|
|
296
|
+
effect.grayscale &&
|
|
297
|
+
css`
|
|
298
|
+
filter: grayscale(100%);
|
|
299
|
+
`};
|
|
300
|
+
${({ effect }) =>
|
|
301
|
+
effect &&
|
|
302
|
+
effect.blur &&
|
|
303
|
+
css`
|
|
304
|
+
filter: blur(${effect.blur}px);
|
|
305
|
+
`};
|
|
306
|
+
${({ effect }) =>
|
|
307
|
+
effect &&
|
|
308
|
+
effect.sepia &&
|
|
309
|
+
css`
|
|
310
|
+
filter: sepia(100%);
|
|
311
|
+
`};
|
|
312
|
+
${({ effect }) =>
|
|
313
|
+
effect &&
|
|
314
|
+
effect.invert &&
|
|
315
|
+
css`
|
|
316
|
+
filter: invert(100%);
|
|
317
|
+
`};
|
|
318
|
+
${({ effect }) =>
|
|
319
|
+
effect && (effect.opacity || effect.opacity === 0)
|
|
320
|
+
? css`
|
|
321
|
+
opacity: ${effect.opacity};
|
|
322
|
+
`
|
|
323
|
+
: undefined};
|
|
324
|
+
${({ effect }) =>
|
|
325
|
+
effect &&
|
|
326
|
+
effect.brightness &&
|
|
327
|
+
css`
|
|
328
|
+
filter: brightness(${effect.brightness}%);
|
|
329
|
+
`};
|
|
330
|
+
${({ effect }) =>
|
|
331
|
+
effect &&
|
|
332
|
+
effect.contrast &&
|
|
333
|
+
css`
|
|
334
|
+
filter: contrast(${effect.contrast}%);
|
|
335
|
+
`};
|
|
336
|
+
${({ effect }) =>
|
|
337
|
+
effect &&
|
|
338
|
+
effect.saturate &&
|
|
339
|
+
css`
|
|
340
|
+
filter: saturate(${effect.saturate}%);
|
|
341
|
+
`};
|
|
234
342
|
`;
|
|
235
343
|
|
|
236
|
-
export const StyledTextEffect = styled(StyledEffect)`
|
|
344
|
+
export const StyledTextEffect = styled(StyledEffect).attrs((props) => ({ ...props, isText: true }))`
|
|
237
345
|
display: inline-block;
|
|
238
346
|
|
|
239
347
|
${({ effect }: IReqoreTextEffectProps) =>
|
|
240
348
|
effect && effect.gradient
|
|
241
349
|
? css`
|
|
242
|
-
-webkit-background-clip: text;
|
|
243
|
-
-webkit-text-fill-color: transparent;
|
|
350
|
+
-webkit-background-clip: text !important;
|
|
351
|
+
-webkit-text-fill-color: transparent !important;
|
|
244
352
|
`
|
|
245
353
|
: undefined}
|
|
246
354
|
`;
|
|
@@ -7,9 +7,11 @@ import { ReqoreThemeContext } from '../..';
|
|
|
7
7
|
import { ICON_FROM_SIZE, PADDING_FROM_SIZE, TSizes } from '../../constants/sizes';
|
|
8
8
|
import { TReqoreIntent } from '../../constants/theme';
|
|
9
9
|
import { isStringSize } from '../../helpers/utils';
|
|
10
|
+
import { IWithReqoreEffect } from '../../types/global';
|
|
10
11
|
import { IReqoreIconName } from '../../types/icons';
|
|
12
|
+
import { StyledEffect } from '../Effect';
|
|
11
13
|
|
|
12
|
-
export interface IReqoreIconProps extends React.HTMLAttributes<HTMLSpanElement
|
|
14
|
+
export interface IReqoreIconProps extends React.HTMLAttributes<HTMLSpanElement>, IWithReqoreEffect {
|
|
13
15
|
icon?: IReqoreIconName;
|
|
14
16
|
color?: string;
|
|
15
17
|
size?: TSizes | string;
|
|
@@ -18,17 +20,9 @@ export interface IReqoreIconProps extends React.HTMLAttributes<HTMLSpanElement>
|
|
|
18
20
|
margin?: 'right' | 'left' | 'both';
|
|
19
21
|
image?: string;
|
|
20
22
|
rounded?: boolean;
|
|
21
|
-
grayscale?: boolean;
|
|
22
|
-
blur?: number;
|
|
23
|
-
sepia?: boolean;
|
|
24
|
-
invert?: boolean;
|
|
25
|
-
opacity?: number;
|
|
26
|
-
brightness?: number;
|
|
27
|
-
contrast?: number;
|
|
28
|
-
saturate?: number;
|
|
29
23
|
}
|
|
30
24
|
|
|
31
|
-
export const StyledIconWrapper = styled
|
|
25
|
+
export const StyledIconWrapper = styled(StyledEffect)<{ margin: 'right' | 'left' | 'both' }>`
|
|
32
26
|
display: inline-block;
|
|
33
27
|
flex: 0 0 auto;
|
|
34
28
|
vertical-align: text-bottom;
|
|
@@ -37,48 +31,6 @@ export const StyledIconWrapper = styled.span<{ margin: 'right' | 'left' | 'both'
|
|
|
37
31
|
|
|
38
32
|
border-radius: ${({ rounded }) => (rounded ? '50%' : undefined)};
|
|
39
33
|
|
|
40
|
-
${({ grayscale }) =>
|
|
41
|
-
grayscale &&
|
|
42
|
-
css`
|
|
43
|
-
filter: grayscale(100%);
|
|
44
|
-
`};
|
|
45
|
-
${({ blur }) =>
|
|
46
|
-
blur &&
|
|
47
|
-
css`
|
|
48
|
-
filter: blur(${blur}px);
|
|
49
|
-
`};
|
|
50
|
-
${({ sepia }) =>
|
|
51
|
-
sepia &&
|
|
52
|
-
css`
|
|
53
|
-
filter: sepia(100%);
|
|
54
|
-
`};
|
|
55
|
-
${({ invert }) =>
|
|
56
|
-
invert &&
|
|
57
|
-
css`
|
|
58
|
-
filter: invert(100%);
|
|
59
|
-
`};
|
|
60
|
-
${({ opacity }) =>
|
|
61
|
-
opacity || opacity === 0
|
|
62
|
-
? css`
|
|
63
|
-
opacity: ${opacity};
|
|
64
|
-
`
|
|
65
|
-
: undefined};
|
|
66
|
-
${({ brightness }) =>
|
|
67
|
-
brightness &&
|
|
68
|
-
css`
|
|
69
|
-
filter: brightness(${brightness}%);
|
|
70
|
-
`};
|
|
71
|
-
${({ contrast }) =>
|
|
72
|
-
contrast &&
|
|
73
|
-
css`
|
|
74
|
-
filter: contrast(${contrast}%);
|
|
75
|
-
`};
|
|
76
|
-
${({ saturate }) =>
|
|
77
|
-
saturate &&
|
|
78
|
-
css`
|
|
79
|
-
filter: saturate(${saturate}%);
|
|
80
|
-
`};
|
|
81
|
-
|
|
82
34
|
${({ margin, size }) =>
|
|
83
35
|
margin &&
|
|
84
36
|
css`
|
|
@@ -62,6 +62,8 @@ const StyledPopoverWrapper = styled.div<{ theme: IReqoreTheme }>`
|
|
|
62
62
|
max-height: ${({ maxHeight = '80vh' }) => maxHeight};
|
|
63
63
|
z-index: 999999;
|
|
64
64
|
border-radius: ${RADIUS_FROM_SIZE.normal}px;
|
|
65
|
+
border: ${({ flat, isString, ...rest }: any) =>
|
|
66
|
+
!flat && !isString ? `1px solid ${getPopoverArrowColor({ ...rest, flat })}` : undefined};
|
|
65
67
|
|
|
66
68
|
${({ transparent }) =>
|
|
67
69
|
!transparent &&
|
|
@@ -217,6 +219,7 @@ const InternalPopover: React.FC<IReqoreInternalPopoverProps> = ({
|
|
|
217
219
|
isOpaque={!transparent && !minimal}
|
|
218
220
|
intent={intent}
|
|
219
221
|
flat={flat}
|
|
222
|
+
isString={isString(content)}
|
|
220
223
|
dim={flat && !transparent && !effect && minimal}
|
|
221
224
|
className='reqore-popover-content'
|
|
222
225
|
ref={(el) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { size } from 'lodash';
|
|
1
|
+
import { omit, size } from 'lodash';
|
|
2
2
|
import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { useUpdateEffect } from 'react-use';
|
|
4
4
|
import { ReqoreDropdown, ReqoreInput } from '../..';
|
|
@@ -13,7 +13,7 @@ import ReqoreTag, { IReqoreTagProps } from '../Tag';
|
|
|
13
13
|
import ReqoreTagGroup from '../Tag/group';
|
|
14
14
|
|
|
15
15
|
export type TReqoreMultiSelectItem = Omit<IReqoreDropdownItem, 'color'> &
|
|
16
|
-
Pick<IReqoreTagProps, '
|
|
16
|
+
Pick<IReqoreTagProps, 'asBadge' | 'rightIcon' | 'actions'> & { isNew?: boolean };
|
|
17
17
|
|
|
18
18
|
export interface IReqoreMultiSelectProps
|
|
19
19
|
extends Omit<IReqoreControlGroupProps, 'children' | 'vertical' | 'stack'> {
|
|
@@ -21,6 +21,7 @@ export interface IReqoreMultiSelectProps
|
|
|
21
21
|
onValueChange?: (value: string[]) => void;
|
|
22
22
|
items?: TReqoreMultiSelectItem[];
|
|
23
23
|
onItemClick?: (item: IReqoreDropdownItem) => void;
|
|
24
|
+
onItemClickIcon?: IReqoreTagProps['rightIcon'];
|
|
24
25
|
canRemoveItems?: boolean;
|
|
25
26
|
canCreateItems?: boolean;
|
|
26
27
|
selectedItemEffect?: IReqoreEffect;
|
|
@@ -35,6 +36,7 @@ export interface IReqoreMultiSelectItemProps
|
|
|
35
36
|
item: TReqoreMultiSelectItem;
|
|
36
37
|
onClick?: () => void;
|
|
37
38
|
onRemoveClick?: () => void;
|
|
39
|
+
onItemClickIcon?: IReqoreTagProps['rightIcon'];
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
export const ReqoreMultiSelectItem = memo(
|
|
@@ -44,6 +46,7 @@ export const ReqoreMultiSelectItem = memo(
|
|
|
44
46
|
onClick,
|
|
45
47
|
selectedItemEffect,
|
|
46
48
|
selectedItemSize,
|
|
49
|
+
onItemClickIcon,
|
|
47
50
|
}: IReqoreMultiSelectItemProps) => {
|
|
48
51
|
if (!item) {
|
|
49
52
|
return null;
|
|
@@ -58,6 +61,7 @@ export const ReqoreMultiSelectItem = memo(
|
|
|
58
61
|
effect={!item.intent ? item.effect || selectedItemEffect : undefined}
|
|
59
62
|
size={selectedItemSize}
|
|
60
63
|
onClick={onClick}
|
|
64
|
+
rightIcon={item.rightIcon || item.disabled ? undefined : onItemClickIcon}
|
|
61
65
|
/>
|
|
62
66
|
);
|
|
63
67
|
}
|
|
@@ -77,6 +81,7 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
|
|
|
77
81
|
selectorProps,
|
|
78
82
|
openOnMount,
|
|
79
83
|
enterKeySelects,
|
|
84
|
+
onItemClickIcon,
|
|
80
85
|
...rest
|
|
81
86
|
}: IReqoreMultiSelectProps,
|
|
82
87
|
ref
|
|
@@ -85,6 +90,7 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
|
|
|
85
90
|
const [createdItems, setCreatedItems] = useState<TReqoreMultiSelectItem[]>([]);
|
|
86
91
|
const [query, setQuery] = useState<string>('');
|
|
87
92
|
const popoverData = useRef<IPopoverControls>(undefined);
|
|
93
|
+
const [focused, setFocused] = useState<boolean>(false);
|
|
88
94
|
|
|
89
95
|
useUpdateEffect(() => {
|
|
90
96
|
onValueChange?.(_value);
|
|
@@ -140,11 +146,11 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
|
|
|
140
146
|
);
|
|
141
147
|
|
|
142
148
|
/*
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
149
|
+
This code creates a list of all items that are available
|
|
150
|
+
for selection in the dropdown. It will include the items
|
|
151
|
+
that are passed in as props, as well as any items that the
|
|
152
|
+
user has created.
|
|
153
|
+
*/
|
|
148
154
|
const allItems: TReqoreMultiSelectItem[] = useMemo(() => {
|
|
149
155
|
const customItems: TReqoreMultiSelectItem[] = size(createdItems)
|
|
150
156
|
? [{ divider: true, label: 'Custom Items' }, ...createdItems]
|
|
@@ -161,7 +167,7 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
|
|
|
161
167
|
|
|
162
168
|
// Mark selected items as selected
|
|
163
169
|
filteredItems = filteredItems.map((item: TReqoreMultiSelectItem) => ({
|
|
164
|
-
...item,
|
|
170
|
+
...omit(item, ['actions', 'asBadge', 'rightIcon']),
|
|
165
171
|
selected: _value.includes(item.value),
|
|
166
172
|
}));
|
|
167
173
|
|
|
@@ -205,12 +211,12 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
|
|
|
205
211
|
|
|
206
212
|
const handleKeyDown = useCallback(
|
|
207
213
|
(e: KeyboardEvent) => {
|
|
208
|
-
if (e.key === 'Enter') {
|
|
214
|
+
if (e.key === 'Enter' && focused) {
|
|
209
215
|
const item = [...items, ...createdItems].find((item) => item.value === query);
|
|
210
216
|
|
|
211
217
|
if (item) {
|
|
212
218
|
handleItemSelect(item);
|
|
213
|
-
} else if (canCreateItems) {
|
|
219
|
+
} else if (canCreateItems && query) {
|
|
214
220
|
handleItemSelect({
|
|
215
221
|
value: query,
|
|
216
222
|
isNew: true,
|
|
@@ -218,7 +224,7 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
|
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
226
|
},
|
|
221
|
-
[items, createdItems, query, canCreateItems]
|
|
227
|
+
[items, createdItems, query, canCreateItems, focused]
|
|
222
228
|
);
|
|
223
229
|
|
|
224
230
|
const getItemByValue = useCallback(
|
|
@@ -236,6 +242,7 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
|
|
|
236
242
|
<ReqoreMultiSelectItem
|
|
237
243
|
key={v}
|
|
238
244
|
item={getItemByValue(v)}
|
|
245
|
+
onItemClickIcon={onItemClickIcon}
|
|
239
246
|
onRemoveClick={canRemoveItems ? () => addRemoveItem(getItemByValue(v)) : undefined}
|
|
240
247
|
onClick={
|
|
241
248
|
onItemClick
|
|
@@ -257,6 +264,8 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
|
|
|
257
264
|
{...selectorProps}
|
|
258
265
|
multiSelect
|
|
259
266
|
handler='focus'
|
|
267
|
+
onFocus={() => setFocused(true)}
|
|
268
|
+
onBlur={() => setFocused(false)}
|
|
260
269
|
passPopoverData={(data) => (popoverData.current = data)}
|
|
261
270
|
component={ReqoreInput}
|
|
262
271
|
onClearClick={() => setQuery('')}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { size } from 'lodash';
|
|
2
2
|
import { darken, rgba } from 'polished';
|
|
3
|
-
import {
|
|
3
|
+
import { ReactElement, forwardRef, useCallback, useMemo, useState } from 'react';
|
|
4
4
|
import { useUpdateEffect } from 'react-use';
|
|
5
5
|
import styled, { css } from 'styled-components';
|
|
6
6
|
import {
|
|
@@ -34,7 +34,7 @@ import { StyledCollectionItemContent } from '../Collection/item';
|
|
|
34
34
|
import ReqoreControlGroup from '../ControlGroup';
|
|
35
35
|
import ReqoreDropdown from '../Dropdown';
|
|
36
36
|
import { IReqoreDropdownItem } from '../Dropdown/list';
|
|
37
|
-
import { IReqoreEffect, StyledEffect } from '../Effect';
|
|
37
|
+
import { IReqoreEffect, StyledEffect, TReqoreEffectColor } from '../Effect';
|
|
38
38
|
import { ReqoreHeading } from '../Header';
|
|
39
39
|
import ReqoreIcon, { StyledIconWrapper } from '../Icon';
|
|
40
40
|
import { ReqoreSpacer } from '../Spacer';
|
|
@@ -275,7 +275,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
275
275
|
'main',
|
|
276
276
|
customTheme ||
|
|
277
277
|
(contentEffect?.gradient && minimal
|
|
278
|
-
? { main: Object.values(contentEffect.gradient.colors)[0] }
|
|
278
|
+
? { main: Object.values(contentEffect.gradient.colors)[0] as TReqoreEffectColor }
|
|
279
279
|
: undefined)
|
|
280
280
|
);
|
|
281
281
|
const { targetRef } = useCombinedRefs(ref);
|
|
@@ -19,6 +19,9 @@ export interface IReqoreRadioGroupProps
|
|
|
19
19
|
size?: TSizes;
|
|
20
20
|
disabled?: boolean;
|
|
21
21
|
asSwitch?: boolean;
|
|
22
|
+
onText?: string;
|
|
23
|
+
offText?: string;
|
|
24
|
+
margin?: 'left' | 'right' | 'both' | 'none';
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
const ReqoreRadioGroup = ({
|
|
@@ -29,6 +32,9 @@ const ReqoreRadioGroup = ({
|
|
|
29
32
|
disabled,
|
|
30
33
|
asSwitch,
|
|
31
34
|
vertical = true,
|
|
35
|
+
onText,
|
|
36
|
+
offText,
|
|
37
|
+
margin = 'left',
|
|
32
38
|
...rest
|
|
33
39
|
}: IReqoreRadioGroupProps) => (
|
|
34
40
|
<ReqoreControlGroup {...rest} vertical={vertical}>
|
|
@@ -37,13 +43,15 @@ const ReqoreRadioGroup = ({
|
|
|
37
43
|
<ReqoreMenuDivider
|
|
38
44
|
{...itemRest}
|
|
39
45
|
size={size || itemRest.size}
|
|
40
|
-
effect={{
|
|
41
|
-
margin=
|
|
46
|
+
effect={{ textAlign: 'left', ...itemRest.effect }}
|
|
47
|
+
margin={margin}
|
|
42
48
|
label={vertical ? itemRest.label : undefined}
|
|
43
49
|
/>
|
|
44
50
|
) : (
|
|
45
51
|
<ReqoreCheckbox
|
|
46
52
|
asSwitch={asSwitch}
|
|
53
|
+
onText={onText}
|
|
54
|
+
offText={offText}
|
|
47
55
|
{...itemRest}
|
|
48
56
|
key={value}
|
|
49
57
|
checked={value === selected}
|
|
@@ -53,7 +53,7 @@ export interface IReqoreTagProps
|
|
|
53
53
|
color?: TReqoreEffectColor;
|
|
54
54
|
actions?: IReqoreTagAction[];
|
|
55
55
|
width?: string;
|
|
56
|
-
|
|
56
|
+
asBadge?: boolean;
|
|
57
57
|
intent?: TReqoreIntent;
|
|
58
58
|
wrap?: boolean;
|
|
59
59
|
}
|
|
@@ -77,17 +77,18 @@ export const StyledTag = styled(StyledEffect)<IReqoreTagStyle>`
|
|
|
77
77
|
font-size: ${({ size }) => TEXT_FROM_SIZE[size]}px;
|
|
78
78
|
|
|
79
79
|
min-width: ${({ size }) => SIZE_TO_PX[size]}px;
|
|
80
|
-
border-radius: ${({
|
|
80
|
+
border-radius: ${({ asBadge, size }) => (asBadge ? 18 : RADIUS_FROM_SIZE[size])}px;
|
|
81
81
|
width: ${({ width }) => width || undefined};
|
|
82
82
|
transition: all 0.2s ease-out;
|
|
83
83
|
|
|
84
84
|
${({ wrap, hasWidth }) =>
|
|
85
85
|
wrap || hasWidth
|
|
86
86
|
? css`
|
|
87
|
-
min-height: ${({ size,
|
|
87
|
+
min-height: ${({ size, asBadge }) =>
|
|
88
|
+
asBadge ? BADGE_SIZE_TO_PX[size] : SIZE_TO_PX[size]}px;
|
|
88
89
|
`
|
|
89
90
|
: css`
|
|
90
|
-
height: ${({ size,
|
|
91
|
+
height: ${({ size, asBadge }) => (asBadge ? BADGE_SIZE_TO_PX[size] : SIZE_TO_PX[size])}px;
|
|
91
92
|
`}
|
|
92
93
|
|
|
93
94
|
${({ theme, color, labelKey, minimal }: IReqoreTagStyle) =>
|
|
@@ -220,7 +221,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
220
221
|
size = 'normal',
|
|
221
222
|
onRemoveClick,
|
|
222
223
|
actions,
|
|
223
|
-
|
|
224
|
+
asBadge,
|
|
224
225
|
intent,
|
|
225
226
|
color,
|
|
226
227
|
minimal,
|
|
@@ -236,10 +237,15 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
236
237
|
useTooltip(targetRef.current, tooltip);
|
|
237
238
|
|
|
238
239
|
// If color or intent was specified, set the color
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
const getCustomColor = (itemIntent?: TReqoreIntent): TReqoreHexColor => {
|
|
241
|
+
let customColor: TReqoreHexColor = itemIntent
|
|
242
|
+
? theme.intents[itemIntent]
|
|
243
|
+
: getColorFromMaybeString(theme, color);
|
|
244
|
+
|
|
245
|
+
customColor = minimal ? `${customColor || '#000000'}40` : customColor;
|
|
246
|
+
|
|
247
|
+
return customColor;
|
|
248
|
+
};
|
|
243
249
|
|
|
244
250
|
return (
|
|
245
251
|
<StyledTag
|
|
@@ -250,11 +256,11 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
250
256
|
}}
|
|
251
257
|
width={width}
|
|
252
258
|
labelKey={labelKey}
|
|
253
|
-
color={
|
|
259
|
+
color={getCustomColor(intent)}
|
|
254
260
|
className={`${className || ''} reqore-tag`}
|
|
255
261
|
size={size}
|
|
256
262
|
ref={targetRef}
|
|
257
|
-
|
|
263
|
+
asBadge={asBadge}
|
|
258
264
|
minimal={minimal}
|
|
259
265
|
removable={!!onRemoveClick}
|
|
260
266
|
interactive={!!onClick && !rest.disabled}
|
|
@@ -308,7 +314,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
308
314
|
component={StyledButtonWrapper}
|
|
309
315
|
componentProps={{
|
|
310
316
|
size,
|
|
311
|
-
color:
|
|
317
|
+
color: getCustomColor(action.intent),
|
|
312
318
|
className: 'reqore-tag-action',
|
|
313
319
|
onClick: action.onClick,
|
|
314
320
|
effect: rest.effect,
|
|
@@ -330,7 +336,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
330
336
|
component={StyledButtonWrapper}
|
|
331
337
|
componentProps={{
|
|
332
338
|
size,
|
|
333
|
-
color:
|
|
339
|
+
color: getCustomColor(intent),
|
|
334
340
|
className: 'reqore-tag-remove',
|
|
335
341
|
onClick: onRemoveClick,
|
|
336
342
|
effect: rest.effect,
|
|
@@ -81,9 +81,9 @@ export const StyledTextarea = styled(StyledEffect)<IReqoreTextareaStyle>`
|
|
|
81
81
|
border-radius: ${({ minimal, rounded, _size }) =>
|
|
82
82
|
minimal || !rounded ? 0 : RADIUS_FROM_SIZE[_size]}px;
|
|
83
83
|
border: ${({ minimal, theme, flat }) =>
|
|
84
|
-
!minimal && !flat ? `1px solid ${changeLightness(theme.main, 0.
|
|
84
|
+
!minimal && !flat ? `1px solid ${changeLightness(theme.main, 0.2)}` : 0};
|
|
85
85
|
border-bottom: ${({ minimal, theme, flat }) =>
|
|
86
|
-
minimal && !flat ? `0.5px solid ${changeLightness(theme.main, 0.
|
|
86
|
+
minimal && !flat ? `0.5px solid ${changeLightness(theme.main, 0.2)}` : undefined};
|
|
87
87
|
|
|
88
88
|
transition: all 0.2s ease-out;
|
|
89
89
|
|
|
@@ -94,7 +94,7 @@ export const StyledTextarea = styled(StyledEffect)<IReqoreTextareaStyle>`
|
|
|
94
94
|
&:focus,
|
|
95
95
|
&:hover {
|
|
96
96
|
outline: none;
|
|
97
|
-
border-color: ${({ theme }) => changeLightness(theme.main, 0.
|
|
97
|
+
border-color: ${({ theme }) => changeLightness(theme.main, 0.25)};
|
|
98
98
|
}
|
|
99
99
|
`
|
|
100
100
|
: undefined}
|
package/src/constants/sizes.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
export type TSizes = 'tiny' | 'small' | 'normal' | 'big' | 'huge';
|
|
2
2
|
export type TWeights = 'soft' | 'normal' | 'heavy';
|
|
3
3
|
|
|
4
|
+
export const ReqoreSizes = {
|
|
5
|
+
TINY: 'tiny',
|
|
6
|
+
SMALL: 'small',
|
|
7
|
+
NORMAL: 'normal',
|
|
8
|
+
BIG: 'big',
|
|
9
|
+
HUGE: 'huge',
|
|
10
|
+
};
|
|
11
|
+
|
|
4
12
|
export const SIZES = ['tiny', 'small', 'normal', 'big', 'huge'] as const;
|
|
5
13
|
|
|
6
14
|
export const SIZE_TO_NUMBER = {
|