@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.
Files changed (91) hide show
  1. package/__tests__/checkbox.test.tsx +7 -12
  2. package/__tests__/multiselect.test.tsx +46 -0
  3. package/dist/components/Button/index.d.ts.map +1 -1
  4. package/dist/components/Button/index.js +4 -2
  5. package/dist/components/Button/index.js.map +1 -1
  6. package/dist/components/Checkbox/index.d.ts +9 -2
  7. package/dist/components/Checkbox/index.d.ts.map +1 -1
  8. package/dist/components/Checkbox/index.js +61 -31
  9. package/dist/components/Checkbox/index.js.map +1 -1
  10. package/dist/components/Effect/index.d.ts +18 -4
  11. package/dist/components/Effect/index.d.ts.map +1 -1
  12. package/dist/components/Effect/index.js +67 -26
  13. package/dist/components/Effect/index.js.map +1 -1
  14. package/dist/components/Icon/index.d.ts +2 -9
  15. package/dist/components/Icon/index.d.ts.map +1 -1
  16. package/dist/components/Icon/index.js +4 -28
  17. package/dist/components/Icon/index.js.map +1 -1
  18. package/dist/components/InternalPopover/index.d.ts.map +1 -1
  19. package/dist/components/InternalPopover/index.js +16 -2
  20. package/dist/components/InternalPopover/index.js.map +1 -1
  21. package/dist/components/Menu/divider.d.ts +1 -1
  22. package/dist/components/Menu/divider.d.ts.map +1 -1
  23. package/dist/components/MultiSelect/index.d.ts +4 -2
  24. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  25. package/dist/components/MultiSelect/index.js +15 -14
  26. package/dist/components/MultiSelect/index.js.map +1 -1
  27. package/dist/components/Panel/index.d.ts.map +1 -1
  28. package/dist/components/Panel/index.js.map +1 -1
  29. package/dist/components/RadioGroup/index.d.ts +4 -1
  30. package/dist/components/RadioGroup/index.d.ts.map +1 -1
  31. package/dist/components/RadioGroup/index.js +2 -2
  32. package/dist/components/RadioGroup/index.js.map +1 -1
  33. package/dist/components/Tag/index.d.ts +1 -1
  34. package/dist/components/Tag/index.d.ts.map +1 -1
  35. package/dist/components/Tag/index.js +17 -14
  36. package/dist/components/Tag/index.js.map +1 -1
  37. package/dist/components/Textarea/index.js +3 -3
  38. package/dist/components/Textarea/index.js.map +1 -1
  39. package/dist/constants/sizes.d.ts +7 -0
  40. package/dist/constants/sizes.d.ts.map +1 -1
  41. package/dist/constants/sizes.js +8 -1
  42. package/dist/constants/sizes.js.map +1 -1
  43. package/dist/constants/theme.d.ts +4 -1
  44. package/dist/constants/theme.d.ts.map +1 -1
  45. package/dist/constants/theme.js.map +1 -1
  46. package/dist/helpers/colors.d.ts +5 -4
  47. package/dist/helpers/colors.d.ts.map +1 -1
  48. package/dist/helpers/colors.js +35 -8
  49. package/dist/helpers/colors.js.map +1 -1
  50. package/dist/hooks/useReqoreEffect.d.ts +4 -0
  51. package/dist/hooks/useReqoreEffect.d.ts.map +1 -0
  52. package/dist/hooks/useReqoreEffect.js +42 -0
  53. package/dist/hooks/useReqoreEffect.js.map +1 -0
  54. package/dist/hooks/useTheme.d.ts +1 -0
  55. package/dist/hooks/useTheme.d.ts.map +1 -1
  56. package/dist/hooks/useTheme.js.map +1 -1
  57. package/dist/index.d.ts +2 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +5 -1
  60. package/dist/index.js.map +1 -1
  61. package/package.json +1 -1
  62. package/src/components/Button/index.tsx +5 -3
  63. package/src/components/Checkbox/index.tsx +217 -38
  64. package/src/components/Effect/index.tsx +125 -17
  65. package/src/components/Icon/index.tsx +4 -52
  66. package/src/components/InternalPopover/index.tsx +3 -0
  67. package/src/components/Menu/divider.tsx +1 -1
  68. package/src/components/MultiSelect/index.tsx +20 -11
  69. package/src/components/Panel/index.tsx +3 -3
  70. package/src/components/RadioGroup/index.tsx +10 -2
  71. package/src/components/Tag/index.tsx +19 -13
  72. package/src/components/Textarea/index.tsx +3 -3
  73. package/src/constants/sizes.ts +8 -0
  74. package/src/constants/theme.ts +8 -1
  75. package/src/helpers/colors.ts +54 -11
  76. package/src/hooks/useReqoreEffect.ts +49 -0
  77. package/src/hooks/useTheme.ts +2 -1
  78. package/src/index.tsx +2 -0
  79. package/src/mock/collectionData.tsx +6 -6
  80. package/src/mock/multiSelect.ts +8 -0
  81. package/src/stories/Button/Button.stories.tsx +14 -0
  82. package/src/stories/Checkbox/Checkbox.stories.tsx +42 -7
  83. package/src/stories/Icon/Icon.stories.tsx +42 -12
  84. package/src/stories/Menu/Menu.stories.tsx +2 -1
  85. package/src/stories/MultiSelect/MultiSelect.stories.tsx +9 -2
  86. package/src/stories/Panel/Panel.stories.tsx +1 -1
  87. package/src/stories/Popover/Popover.stories.tsx +19 -2
  88. package/src/stories/RadioGroup/RadioGroup.stories.tsx +98 -1
  89. package/src/stories/Tag/Tag.stories.tsx +2 -2
  90. package/src/stories/utils/args.ts +1 -1
  91. 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: Record<number, TReqoreEffectColor>;
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 (effect.glow.useBorder) {
215
+ if (!isText) {
165
216
  return css`
166
- border: ${effect.glow.size || 2}px solid
167
- ${getColorFromMaybeString(theme, effect.glow.color)} !important;
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
- box-shadow: ${effect.glow.inset ? 'inset ' : ''} 0 0 ${effect.glow.blur || 0}px
173
- ${effect.glow.size || 2}px ${getColorFromMaybeString(theme, effect.glow.color)};
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.span<{ margin: 'right' | 'left' | 'both' }>`
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) => {
@@ -11,7 +11,7 @@ export interface IReqoreMenuDividerProps
11
11
  IWithReqoreEffect,
12
12
  IWithReqoreSize {
13
13
  label?: string | number;
14
- margin?: 'left' | 'right' | 'both';
14
+ margin?: 'left' | 'right' | 'both' | 'none';
15
15
  align?: 'left' | 'center' | 'right';
16
16
  }
17
17
 
@@ -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, 'badge'> & { isNew?: boolean };
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
- This code creates a list of all items that are available
144
- for selection in the dropdown. It will include the items
145
- that are passed in as props, as well as any items that the
146
- user has created.
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 { forwardRef, ReactElement, useCallback, useMemo, useState } from 'react';
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={{ ...itemRest.effect, textAlign: 'left' }}
41
- margin='left'
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
- badge?: boolean;
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: ${({ badge, size }) => (badge ? 18 : RADIUS_FROM_SIZE[size])}px;
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, badge }) => (badge ? BADGE_SIZE_TO_PX[size] : SIZE_TO_PX[size])}px;
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, badge }) => (badge ? BADGE_SIZE_TO_PX[size] : SIZE_TO_PX[size])}px;
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
- badge,
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
- let customColor: TReqoreHexColor = intent
240
- ? theme.intents[intent]
241
- : getColorFromMaybeString(theme, color);
242
- customColor = minimal ? `${customColor || '#000000'}40` : customColor;
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={customColor}
259
+ color={getCustomColor(intent)}
254
260
  className={`${className || ''} reqore-tag`}
255
261
  size={size}
256
262
  ref={targetRef}
257
- badge={badge}
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: customColor,
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: customColor,
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.05)}` : 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.05)}` : undefined};
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.1)};
97
+ border-color: ${({ theme }) => changeLightness(theme.main, 0.25)};
98
98
  }
99
99
  `
100
100
  : undefined}
@@ -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 = {