@qoretechnologies/reqore 0.29.1 → 0.29.3

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 (79) hide show
  1. package/__tests__/multiselect.test.tsx +59 -75
  2. package/dist/components/Button/index.d.ts.map +1 -1
  3. package/dist/components/Button/index.js +3 -1
  4. package/dist/components/Button/index.js.map +1 -1
  5. package/dist/components/Checkbox/index.d.ts +2 -0
  6. package/dist/components/Checkbox/index.d.ts.map +1 -1
  7. package/dist/components/Checkbox/index.js +16 -20
  8. package/dist/components/Checkbox/index.js.map +1 -1
  9. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  10. package/dist/components/ControlGroup/index.js +6 -4
  11. package/dist/components/ControlGroup/index.js.map +1 -1
  12. package/dist/components/Effect/index.d.ts +7 -3
  13. package/dist/components/Effect/index.d.ts.map +1 -1
  14. package/dist/components/Effect/index.js +41 -32
  15. package/dist/components/Effect/index.js.map +1 -1
  16. package/dist/components/Menu/divider.d.ts +1 -1
  17. package/dist/components/Menu/divider.d.ts.map +1 -1
  18. package/dist/components/MultiSelect/index.d.ts +1 -1
  19. package/dist/components/MultiSelect/index.d.ts.map +1 -1
  20. package/dist/components/MultiSelect/index.js +17 -19
  21. package/dist/components/MultiSelect/index.js.map +1 -1
  22. package/dist/components/Panel/index.d.ts.map +1 -1
  23. package/dist/components/Panel/index.js.map +1 -1
  24. package/dist/components/RadioGroup/index.d.ts +2 -1
  25. package/dist/components/RadioGroup/index.d.ts.map +1 -1
  26. package/dist/components/RadioGroup/index.js +2 -2
  27. package/dist/components/RadioGroup/index.js.map +1 -1
  28. package/dist/components/Spacer/index.d.ts +15 -1
  29. package/dist/components/Spacer/index.d.ts.map +1 -1
  30. package/dist/components/Spacer/index.js +87 -10
  31. package/dist/components/Spacer/index.js.map +1 -1
  32. package/dist/constants/sizes.d.ts +8 -0
  33. package/dist/constants/sizes.d.ts.map +1 -1
  34. package/dist/constants/sizes.js +9 -1
  35. package/dist/constants/sizes.js.map +1 -1
  36. package/dist/constants/theme.d.ts +4 -1
  37. package/dist/constants/theme.d.ts.map +1 -1
  38. package/dist/constants/theme.js.map +1 -1
  39. package/dist/helpers/colors.d.ts +5 -4
  40. package/dist/helpers/colors.d.ts.map +1 -1
  41. package/dist/helpers/colors.js +35 -8
  42. package/dist/helpers/colors.js.map +1 -1
  43. package/dist/hooks/useReqoreEffect.d.ts +4 -0
  44. package/dist/hooks/useReqoreEffect.d.ts.map +1 -0
  45. package/dist/hooks/useReqoreEffect.js +42 -0
  46. package/dist/hooks/useReqoreEffect.js.map +1 -0
  47. package/dist/hooks/useTheme.d.ts +1 -0
  48. package/dist/hooks/useTheme.d.ts.map +1 -1
  49. package/dist/hooks/useTheme.js.map +1 -1
  50. package/dist/index.d.ts +3 -1
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +8 -2
  53. package/dist/index.js.map +1 -1
  54. package/package.json +1 -1
  55. package/src/components/Button/index.tsx +4 -2
  56. package/src/components/Checkbox/index.tsx +42 -18
  57. package/src/components/ControlGroup/index.tsx +26 -24
  58. package/src/components/Effect/index.tsx +60 -10
  59. package/src/components/Menu/divider.tsx +1 -1
  60. package/src/components/MultiSelect/index.tsx +21 -23
  61. package/src/components/Panel/index.tsx +3 -3
  62. package/src/components/RadioGroup/index.tsx +4 -2
  63. package/src/components/Spacer/index.tsx +90 -5
  64. package/src/constants/sizes.ts +9 -0
  65. package/src/constants/theme.ts +8 -1
  66. package/src/helpers/colors.ts +54 -11
  67. package/src/hooks/useReqoreEffect.ts +49 -0
  68. package/src/hooks/useTheme.ts +2 -1
  69. package/src/index.tsx +3 -1
  70. package/src/mock/multiSelect.ts +1 -1
  71. package/src/stories/Button/Button.stories.tsx +14 -0
  72. package/src/stories/Checkbox/Checkbox.stories.tsx +1 -1
  73. package/src/stories/ControlGroup/ControlGroup.stories.tsx +18 -3
  74. package/src/stories/MultiSelect/MultiSelect.stories.tsx +4 -1
  75. package/src/stories/Panel/Panel.stories.tsx +1 -1
  76. package/src/stories/Popover/Popover.stories.tsx +1 -1
  77. package/src/stories/RadioGroup/RadioGroup.stories.tsx +47 -0
  78. package/src/stories/Spacer/Spacer.stories.tsx +93 -0
  79. package/tests.json +1 -1
@@ -52,6 +52,8 @@ export interface IReqoreCheckboxProps
52
52
  offText?: string | number;
53
53
  switchTextEffect?: IReqoreEffect;
54
54
  labelEffect?: IReqoreEffect;
55
+ margin?: 'left' | 'right' | 'both' | 'none';
56
+ wrapLabel?: boolean;
55
57
  }
56
58
 
57
59
  export interface IReqoreCheckboxStyle extends IReqoreCheckboxProps {
@@ -78,10 +80,10 @@ const StyledSwitchToggle = styled.div`
78
80
  : !checked
79
81
  ? parentEffect?.gradient
80
82
  ? changeLightness(getNthGradientColor(theme, parentEffect?.gradient?.colors, 1), 0.2)
81
- : theme.main
83
+ : changeLightness(theme.main, 0.2)
82
84
  : parentEffect?.gradient
83
85
  ? changeLightness(getNthGradientColor(theme, parentEffect?.gradient?.colors, 2), 0.2)
84
- : theme.main};
86
+ : changeLightness(theme.main, 0.25)};
85
87
  `;
86
88
 
87
89
  const StyledSwitch = styled(StyledEffect)<IReqoreCheckboxStyle>`
@@ -90,6 +92,7 @@ const StyledSwitch = styled(StyledEffect)<IReqoreCheckboxStyle>`
90
92
  display: flex;
91
93
  align-items: center;
92
94
  justify-content: center;
95
+ flex-shrink: 0;
93
96
 
94
97
  height: ${({ size }) => SIZE_TO_PX[size]}px;
95
98
  min-width: ${({ size }) => SIZE_TO_PX[size] * 1.8}px;
@@ -97,11 +100,7 @@ const StyledSwitch = styled(StyledEffect)<IReqoreCheckboxStyle>`
97
100
  border: 1px solid ${({ theme, checked }) => changeLightness(theme.main, checked ? 0.25 : 0.2)};
98
101
  border-radius: 50px;
99
102
 
100
- margin-right: ${({ size }) => PADDING_FROM_SIZE[size]}px;
101
- margin-left: ${({ size }) => PADDING_FROM_SIZE[size]}px;
102
-
103
- background-color: ${({ theme, checked }) =>
104
- checked ? rgba(changeLightness(theme.main, 0.15), 0.5) : 'transparent'};
103
+ background-color: ${({ theme }) => rgba(changeLightness(theme.main, 0.3), 0.1)};
105
104
 
106
105
  ${StyledIconWrapper} {
107
106
  z-index: 1;
@@ -117,13 +116,15 @@ const StyledSwitchTextWrapper = styled(StyledTextEffect)`
117
116
  `;
118
117
 
119
118
  const StyledOnSwitchText = styled(StyledSwitchTextWrapper)<IReqoreCheckboxStyle>`
120
- color: ${({ theme, checked }) =>
121
- getReadableColorFrom(!checked ? theme.originalMain : theme.main)};
119
+ color: ${({ theme, checked, parentHasGradient }) =>
120
+ !parentHasGradient &&
121
+ getReadableColorFrom(checked ? changeLightness(theme.main, 0.25) : theme.originalMain)};
122
122
  `;
123
123
 
124
124
  const StyledOffSwitchText = styled(StyledSwitchTextWrapper)<IReqoreCheckboxStyle>`
125
- color: ${({ theme, checked }) =>
126
- getReadableColorFrom(!checked ? theme.main : changeLightness(theme.main, 0.1))};
125
+ color: ${({ theme, checked, parentHasGradient }) =>
126
+ !parentHasGradient &&
127
+ getReadableColorFrom(checked ? theme.originalMain : changeLightness(theme.main, 0.2))};
127
128
  `;
128
129
 
129
130
  const StyledCheckbox = styled.div<IReqoreCheckboxStyle>`
@@ -170,6 +171,7 @@ const Checkbox = forwardRef<HTMLDivElement, IReqoreCheckboxProps>(
170
171
  labelDetail,
171
172
  labelDetailPosition = 'right',
172
173
  size = 'normal',
174
+ margin = 'left',
173
175
  checked,
174
176
  disabled,
175
177
  className,
@@ -187,6 +189,7 @@ const Checkbox = forwardRef<HTMLDivElement, IReqoreCheckboxProps>(
187
189
  intent,
188
190
  effect,
189
191
  customTheme,
192
+ wrapLabel,
190
193
  ...rest
191
194
  }: IReqoreCheckboxProps,
192
195
  ref
@@ -221,17 +224,24 @@ const Checkbox = forwardRef<HTMLDivElement, IReqoreCheckboxProps>(
221
224
  readOnly={readOnly}
222
225
  className={`${className || ''} reqore-checkbox reqore-control`}
223
226
  >
227
+ {margin === 'left' || margin === 'both' ? (
228
+ <ReqoreSpacer width={PADDING_FROM_SIZE[size]} />
229
+ ) : null}
224
230
  {label && labelPosition === 'left' ? (
225
231
  <>
226
- <ReqoreSpacer width={PADDING_FROM_SIZE[size]} />
227
232
  {labelDetailPosition === 'left' && labelDetail}
228
233
  <ReqoreTextEffect
229
234
  active={checked}
230
- effect={{ ...labelEffect, interactive: !disabled && !readOnly && !checked }}
235
+ effect={{
236
+ ...labelEffect,
237
+ interactive: !disabled && !readOnly && !checked,
238
+ noWrap: !wrapLabel,
239
+ }}
231
240
  >
232
241
  {label}
233
242
  </ReqoreTextEffect>
234
243
  {labelDetailPosition === 'right' && labelDetail}
244
+ <ReqoreSpacer width={PADDING_FROM_SIZE[size]} />
235
245
  </>
236
246
  ) : null}
237
247
  {asSwitch ? (
@@ -241,7 +251,12 @@ const Checkbox = forwardRef<HTMLDivElement, IReqoreCheckboxProps>(
241
251
  checked={checked}
242
252
  theme={theme}
243
253
  as='div'
244
- effect={effect}
254
+ effect={
255
+ {
256
+ interactive: !disabled && !readOnly,
257
+ ...effect,
258
+ } as IReqoreEffect
259
+ }
245
260
  >
246
261
  <>
247
262
  {offText || offText === 0 ? (
@@ -250,6 +265,7 @@ const Checkbox = forwardRef<HTMLDivElement, IReqoreCheckboxProps>(
250
265
  size={size}
251
266
  theme={theme}
252
267
  checked={checked}
268
+ parentHasGradient={!!effect?.gradient}
253
269
  effect={
254
270
  {
255
271
  uppercase: true,
@@ -278,13 +294,14 @@ const Checkbox = forwardRef<HTMLDivElement, IReqoreCheckboxProps>(
278
294
  size={size}
279
295
  theme={theme}
280
296
  checked={checked}
297
+ parentHasGradient={!!effect?.gradient}
281
298
  effect={
282
299
  {
283
300
  uppercase: true,
284
301
  textSize: getOneLessSize(size),
285
302
  weight: 'thick',
286
303
  ...switchTextEffect,
287
- opacity: checked ? 1 : 0.5,
304
+ opacity: checked ? 1 : 0.3,
288
305
  } as IReqoreEffect
289
306
  }
290
307
  >
@@ -330,22 +347,29 @@ const Checkbox = forwardRef<HTMLDivElement, IReqoreCheckboxProps>(
330
347
  }
331
348
  image={image}
332
349
  effect={{ grayscale: image ? !checked : undefined, opacity: checked ? 1 : 0.5 }}
333
- margin='both'
334
- intent={intent}
350
+ color={intent ? changeLightness(theme.main, 0.2) : undefined}
335
351
  />
336
352
  )}
337
353
  {label && labelPosition === 'right' ? (
338
354
  <>
355
+ <ReqoreSpacer width={PADDING_FROM_SIZE[size]} />
339
356
  {labelDetailPosition === 'left' && labelDetail}
340
357
  <ReqoreTextEffect
341
358
  active={checked}
342
- effect={{ ...labelEffect, interactive: !disabled && !readOnly && !checked }}
359
+ effect={{
360
+ ...labelEffect,
361
+ interactive: !disabled && !readOnly && !checked,
362
+ noWrap: !wrapLabel,
363
+ }}
343
364
  >
344
365
  {label}
345
366
  </ReqoreTextEffect>
346
367
  {labelDetailPosition === 'right' && labelDetail}
347
368
  </>
348
369
  ) : null}
370
+ {margin === 'right' || margin === 'both' ? (
371
+ <ReqoreSpacer width={PADDING_FROM_SIZE[size]} />
372
+ ) : null}
349
373
  </StyledCheckbox>
350
374
  );
351
375
  }
@@ -50,19 +50,20 @@ export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
50
50
 
51
51
  border-radius: ${({ stack }) => (!stack ? undefined : 0)};
52
52
 
53
- ${({ rounded, size }) =>
54
- rounded &&
55
- css`
56
- &:first-child {
57
- border-top-left-radius: ${RADIUS_FROM_SIZE[size]}px;
58
- border-top-right-radius: ${RADIUS_FROM_SIZE[size]}px;
59
- }
53
+ ${({ rounded, size, stack }) =>
54
+ rounded && stack
55
+ ? css`
56
+ &:first-child {
57
+ border-top-left-radius: ${RADIUS_FROM_SIZE[size]}px;
58
+ border-top-right-radius: ${RADIUS_FROM_SIZE[size]}px;
59
+ }
60
60
 
61
- &:last-child {
62
- border-bottom-left-radius: ${RADIUS_FROM_SIZE[size]}px;
63
- border-bottom-right-radius: ${RADIUS_FROM_SIZE[size]}px;
64
- }
65
- `}
61
+ &:last-child {
62
+ border-bottom-left-radius: ${RADIUS_FROM_SIZE[size]}px;
63
+ border-bottom-right-radius: ${RADIUS_FROM_SIZE[size]}px;
64
+ }
65
+ `
66
+ : undefined}
66
67
  }
67
68
 
68
69
  > .reqore-control-wrapper:not(:last-child) .reqore-control {
@@ -84,19 +85,20 @@ export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
84
85
 
85
86
  border-radius: ${({ stack }) => (!stack ? undefined : 0)};
86
87
 
87
- ${({ rounded, size }) =>
88
- rounded &&
89
- css`
90
- &:first-child {
91
- border-top-left-radius: ${RADIUS_FROM_SIZE[size]}px;
92
- border-bottom-left-radius: ${RADIUS_FROM_SIZE[size]}px;
93
- }
88
+ ${({ rounded, size, stack }) =>
89
+ rounded && stack
90
+ ? css`
91
+ &:first-child {
92
+ border-top-left-radius: ${RADIUS_FROM_SIZE[size]}px;
93
+ border-bottom-left-radius: ${RADIUS_FROM_SIZE[size]}px;
94
+ }
94
95
 
95
- &:last-child {
96
- border-top-right-radius: ${RADIUS_FROM_SIZE[size]}px;
97
- border-bottom-right-radius: ${RADIUS_FROM_SIZE[size]}px;
98
- }
99
- `}
96
+ &:last-child {
97
+ border-top-right-radius: ${RADIUS_FROM_SIZE[size]}px;
98
+ border-bottom-right-radius: ${RADIUS_FROM_SIZE[size]}px;
99
+ }
100
+ `
101
+ : undefined}
100
102
  }
101
103
  `}
102
104
  `;
@@ -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,12 +24,21 @@ 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';
32
42
 
33
43
  export interface IReqoreEffectFilters {
34
44
  grayscale?: boolean;
@@ -45,9 +55,11 @@ export interface IReqoreEffect extends IReqoreEffectFilters {
45
55
  gradient?: {
46
56
  type?: 'linear' | 'radial';
47
57
  shape?: 'circle' | 'ellipse';
48
- colors: Record<number, TReqoreEffectColor>;
58
+ colors: TReqoreEffectGradientColors;
49
59
  direction?: string;
50
60
  borderColor?: TReqoreEffectColor;
61
+ animate?: TReqoreEffectGradientAnimationTrigger;
62
+ animationSpeed?: 1 | 2 | 3 | 4 | 5;
51
63
  };
52
64
  noWrap?: boolean;
53
65
  color?: TReqoreEffectColor;
@@ -61,7 +73,6 @@ export interface IReqoreEffect extends IReqoreEffectFilters {
61
73
  color: TReqoreEffectColor;
62
74
  inset?: boolean;
63
75
  blur?: number;
64
- useBorder?: boolean;
65
76
  };
66
77
  interactive?: boolean;
67
78
  }
@@ -77,6 +88,19 @@ export interface IReqoreTextEffectProps
77
88
  isText?: boolean;
78
89
  }
79
90
 
91
+ // Animate the gradient
92
+ const StyledGradientKeyframes = keyframes`
93
+ 0% {
94
+ background-position: 0% 0%;
95
+ }
96
+ 50% {
97
+ background-position: 100% 100%;
98
+ }
99
+ 100% {
100
+ background-position: 0% 0%;
101
+ }
102
+ `;
103
+
80
104
  export const StyledEffect = styled.span`
81
105
  transition: all 0.2s ease-in-out;
82
106
 
@@ -154,6 +178,14 @@ export const StyledEffect = styled.span`
154
178
  }
155
179
  `}
156
180
 
181
+ ${effect.gradient.animate === 'always' || (effect.gradient.animate === 'active' && active)
182
+ ? css`
183
+ background-size: 200% 200%;
184
+ animation: ${StyledGradientKeyframes} ${effect.gradient.animationSpeed || 2}s linear
185
+ infinite;
186
+ `
187
+ : undefined}
188
+
157
189
  ${effect.interactive &&
158
190
  css`
159
191
  cursor: pointer;
@@ -163,26 +195,44 @@ export const StyledEffect = styled.span`
163
195
  &:active {
164
196
  background: ${gradientActive};
165
197
  border-color: ${borderHoverColor} !important;
198
+
199
+ ${effect.gradient.animate === 'hover' ||
200
+ (effect.gradient.animate === 'active' && active) ||
201
+ effect.gradient.animate === 'always'
202
+ ? css`
203
+ background-size: 200% 200%;
204
+ animation: ${StyledGradientKeyframes} ${effect.gradient.animationSpeed || 2}s linear
205
+ infinite;
206
+ `
207
+ : undefined}
166
208
  }
167
209
  `}
168
210
  `;
169
211
  }}
170
212
 
171
- ${({ effect, theme }: IReqoreTextEffectProps) => {
213
+ ${({ effect, theme, isText }: IReqoreTextEffectProps) => {
172
214
  if (!effect || !effect.glow) {
173
215
  return undefined;
174
216
  }
175
217
 
176
- if (effect.glow.useBorder) {
218
+ if (!isText) {
177
219
  return css`
178
- border: ${effect.glow.size || 2}px solid
179
- ${getColorFromMaybeString(theme, effect.glow.color)} !important;
220
+ box-shadow: ${effect.glow.inset ? 'inset ' : ''} 0 0 ${effect.glow.blur || 0}px
221
+ ${effect.glow.size || 2}px ${getColorFromMaybeString(theme, effect.glow.color)};
180
222
  `;
181
223
  }
182
224
 
225
+ const color = getColorFromMaybeString(
226
+ theme,
227
+ effect.glow.color === 'main' ? 'main:lighten:2' : effect.glow.color
228
+ );
229
+ const blur = effect.glow.blur || 0;
230
+
183
231
  return css`
184
- box-shadow: ${effect.glow.inset ? 'inset ' : ''} 0 0 ${effect.glow.blur || 0}px
185
- ${effect.glow.size || 2}px ${getColorFromMaybeString(theme, effect.glow.color)};
232
+ color: ${Colors.LIGHT};
233
+ text-shadow: 0 0 ${blur}px ${color}, 0 0 ${blur + 5}px ${color}, 0 0 ${blur + 10}px ${color},
234
+ 0 0 1px ${getReadableColorFrom(color)}, 0 0 2px ${getReadableColorFrom(color)},
235
+ 0 0 3px ${getReadableColorFrom(color)};
186
236
  `;
187
237
  }}
188
238
 
@@ -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,6 +1,5 @@
1
1
  import { omit, size } from 'lodash';
2
2
  import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
- import { useUpdateEffect } from 'react-use';
4
3
  import { ReqoreDropdown, ReqoreInput } from '../..';
5
4
  import { TSizes } from '../../constants/sizes';
6
5
  import { IPopoverControls } from '../../hooks/usePopover';
@@ -18,7 +17,7 @@ export type TReqoreMultiSelectItem = Omit<IReqoreDropdownItem, 'color'> &
18
17
  export interface IReqoreMultiSelectProps
19
18
  extends Omit<IReqoreControlGroupProps, 'children' | 'vertical' | 'stack'> {
20
19
  value?: string[];
21
- onValueChange?: (value: string[]) => void;
20
+ onValueChange: (value: string[]) => void;
22
21
  items?: TReqoreMultiSelectItem[];
23
22
  onItemClick?: (item: IReqoreDropdownItem) => void;
24
23
  onItemClickIcon?: IReqoreTagProps['rightIcon'];
@@ -61,7 +60,15 @@ export const ReqoreMultiSelectItem = memo(
61
60
  effect={!item.intent ? item.effect || selectedItemEffect : undefined}
62
61
  size={selectedItemSize}
63
62
  onClick={onClick}
64
- rightIcon={item.rightIcon || item.disabled ? undefined : onItemClickIcon}
63
+ rightIcon={
64
+ item.disabled
65
+ ? undefined
66
+ : item.rightIcon
67
+ ? item.rightIcon
68
+ : onClick
69
+ ? onItemClickIcon
70
+ : undefined
71
+ }
65
72
  />
66
73
  );
67
74
  }
@@ -70,7 +77,7 @@ export const ReqoreMultiSelectItem = memo(
70
77
  export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectProps>(
71
78
  (
72
79
  {
73
- value,
80
+ value = [],
74
81
  onValueChange,
75
82
  onItemClick,
76
83
  canRemoveItems,
@@ -86,20 +93,11 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
86
93
  }: IReqoreMultiSelectProps,
87
94
  ref
88
95
  ) => {
89
- const [_value, setValue] = useState<string[]>(value || []);
90
96
  const [createdItems, setCreatedItems] = useState<TReqoreMultiSelectItem[]>([]);
91
97
  const [query, setQuery] = useState<string>('');
92
98
  const popoverData = useRef<IPopoverControls>(undefined);
93
99
  const [focused, setFocused] = useState<boolean>(false);
94
100
 
95
- useUpdateEffect(() => {
96
- onValueChange?.(_value);
97
- }, [_value]);
98
-
99
- useEffect(() => {
100
- setValue(value || []);
101
- }, [value]);
102
-
103
101
  useEffect(() => {
104
102
  if (query && !popoverData.current?.isOpen()) {
105
103
  popoverData.current?.open();
@@ -118,13 +116,13 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
118
116
 
119
117
  const addRemoveItem = useCallback(
120
118
  (item: TReqoreMultiSelectItem): void => {
121
- if (_value.includes(item.value)) {
122
- setValue(_value.filter((v) => v !== item.value));
119
+ if (value.includes(item.value)) {
120
+ onValueChange(value.filter((v) => v !== item.value));
123
121
  } else {
124
- setValue([..._value, item.value]);
122
+ onValueChange([...value, item.value]);
125
123
  }
126
124
  },
127
- [_value, value]
125
+ [value]
128
126
  );
129
127
 
130
128
  const handleItemSelect = useCallback(
@@ -142,7 +140,7 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
142
140
 
143
141
  setQuery('');
144
142
  },
145
- [createdItems, _value]
143
+ [createdItems, value]
146
144
  );
147
145
 
148
146
  /*
@@ -168,7 +166,7 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
168
166
  // Mark selected items as selected
169
167
  filteredItems = filteredItems.map((item: TReqoreMultiSelectItem) => ({
170
168
  ...omit(item, ['actions', 'asBadge', 'rightIcon']),
171
- selected: _value.includes(item.value),
169
+ selected: value.includes(item.value),
172
170
  }));
173
171
 
174
172
  if (query && !size(filteredItems)) {
@@ -207,7 +205,7 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
207
205
  }
208
206
 
209
207
  return filteredItems;
210
- }, [items, createdItems, query, _value]);
208
+ }, [items, createdItems, query, value]);
211
209
 
212
210
  const handleKeyDown = useCallback(
213
211
  (e: KeyboardEvent) => {
@@ -231,14 +229,14 @@ export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectPr
231
229
  (value: string): TReqoreMultiSelectItem => {
232
230
  return [...items, ...createdItems].find((item) => item.value === value);
233
231
  },
234
- [items, createdItems, _value]
232
+ [items, createdItems, value]
235
233
  );
236
234
 
237
235
  return (
238
236
  <ReqoreControlGroup vertical fluid {...rest} ref={ref}>
239
237
  <ReqoreTagGroup minimal={rest.minimal} size={rest.size}>
240
- {size(_value) ? (
241
- _value.map((v) => (
238
+ {size(value) ? (
239
+ value.map((v) => (
242
240
  <ReqoreMultiSelectItem
243
241
  key={v}
244
242
  item={getItemByValue(v)}
@@ -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);
@@ -21,6 +21,7 @@ export interface IReqoreRadioGroupProps
21
21
  asSwitch?: boolean;
22
22
  onText?: string;
23
23
  offText?: string;
24
+ margin?: 'left' | 'right' | 'both' | 'none';
24
25
  }
25
26
 
26
27
  const ReqoreRadioGroup = ({
@@ -33,6 +34,7 @@ const ReqoreRadioGroup = ({
33
34
  vertical = true,
34
35
  onText,
35
36
  offText,
37
+ margin = 'left',
36
38
  ...rest
37
39
  }: IReqoreRadioGroupProps) => (
38
40
  <ReqoreControlGroup {...rest} vertical={vertical}>
@@ -41,8 +43,8 @@ const ReqoreRadioGroup = ({
41
43
  <ReqoreMenuDivider
42
44
  {...itemRest}
43
45
  size={size || itemRest.size}
44
- effect={{ ...itemRest.effect, textAlign: 'left' }}
45
- margin='left'
46
+ effect={{ textAlign: 'left', ...itemRest.effect }}
47
+ margin={margin}
46
48
  label={vertical ? itemRest.label : undefined}
47
49
  />
48
50
  ) : (
@@ -1,8 +1,93 @@
1
- import styled from 'styled-components';
1
+ import { memo } from 'react';
2
+ import styled, { css } from 'styled-components';
3
+ import { SIZE_TO_NUMBER, TEXT_FROM_SIZE, TSizes } from '../../constants/sizes';
4
+ import { changeLightness } from '../../helpers/colors';
5
+ import { useReqoreTheme } from '../../hooks/useTheme';
6
+ import { IReqoreIntent, IWithReqoreCustomTheme, IWithReqoreEffect } from '../../types/global';
7
+ import { StyledEffect } from '../Effect';
2
8
 
3
- export const ReqoreSpacer = styled.div`
4
- visibility: hidden;
5
- height: ${({ height }) => height || 1}px;
6
- width: ${({ width }) => width || 1}px;
9
+ export const StyledSpacer = styled(StyledEffect)`
10
+ ${({ horizontal, vertical, width, height, lineSize }) => {
11
+ if (horizontal) {
12
+ return css`
13
+ margin-left: ${width / 2}px;
14
+ margin-right: ${width / 2}px;
15
+ width: ${lineSize === 'none' ? 1 : SIZE_TO_NUMBER[lineSize]}px;
16
+ height: ${height ? `${height}px` : `${TEXT_FROM_SIZE.normal}px`};
17
+ vertical-align: middle;
18
+ display: inline-block;
19
+ `;
20
+ }
21
+
22
+ if (vertical) {
23
+ return css`
24
+ margin-top: ${height / 2}px;
25
+ margin-bottom: ${height / 2}px;
26
+ height: ${lineSize === 'none' ? 1 : SIZE_TO_NUMBER[lineSize]}px;
27
+ width: ${width ? `${width}px` : '100%'};
28
+ `;
29
+ }
30
+ }}
31
+
32
+ background-color: ${({ theme, lineSize }) =>
33
+ lineSize === 'none' ? 'transparent' : changeLightness(theme.main, 0.2)};
7
34
  flex-shrink: 0;
8
35
  `;
36
+
37
+ export interface IReqoreSpacerProps
38
+ extends React.HTMLAttributes<HTMLDivElement>,
39
+ IWithReqoreEffect,
40
+ IWithReqoreCustomTheme,
41
+ IReqoreIntent {
42
+ width?: number;
43
+ height?: number;
44
+ lineSize?: TSizes | 'none';
45
+ }
46
+
47
+ export const ReqoreSpacer = memo(
48
+ ({
49
+ customTheme,
50
+ intent,
51
+ lineSize = 'none',
52
+ ...rest
53
+ }: IReqoreSpacerProps & { horizontal?: boolean; vertical?: boolean }) => {
54
+ const theme = useReqoreTheme('main', customTheme, intent);
55
+ let { horizontal, vertical } = rest;
56
+
57
+ // The user is using old version of the component
58
+ // We will assume that the user wants a spacer based on the width or height
59
+ if (!horizontal && !vertical) {
60
+ if (rest.width) {
61
+ horizontal = true;
62
+ }
63
+
64
+ if (rest.height) {
65
+ vertical = true;
66
+ }
67
+ }
68
+
69
+ return (
70
+ <StyledSpacer
71
+ as='div'
72
+ {...rest}
73
+ theme={theme}
74
+ lineSize={lineSize}
75
+ horizontal={horizontal}
76
+ vertical={vertical}
77
+ className='reqore-spacer'
78
+ />
79
+ );
80
+ }
81
+ );
82
+
83
+ export const ReqoreHorizontalSpacer = memo(
84
+ ({ width = 1, lineSize = 'none', ...rest }: IReqoreSpacerProps) => {
85
+ return <ReqoreSpacer width={width} lineSize={lineSize} horizontal {...rest} />;
86
+ }
87
+ );
88
+
89
+ export const ReqoreVerticalSpacer = memo(
90
+ ({ height = 1, lineSize = 'none', ...rest }: IReqoreSpacerProps) => {
91
+ return <ReqoreSpacer height={height} lineSize={lineSize} vertical {...rest} />;
92
+ }
93
+ );
@@ -1,9 +1,18 @@
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 = {
15
+ none: 0,
7
16
  tiny: 1,
8
17
  small: 2,
9
18
  normal: 3,