@qoretechnologies/reqore 0.42.0 → 0.44.0

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 (46) hide show
  1. package/dist/components/Button/index.d.ts +1 -0
  2. package/dist/components/Button/index.d.ts.map +1 -1
  3. package/dist/components/Button/index.js +6 -2
  4. package/dist/components/Button/index.js.map +1 -1
  5. package/dist/components/ControlGroup/index.d.ts +1 -0
  6. package/dist/components/ControlGroup/index.d.ts.map +1 -1
  7. package/dist/components/ControlGroup/index.js +18 -4
  8. package/dist/components/ControlGroup/index.js.map +1 -1
  9. package/dist/components/DatePicker/index.d.ts +29 -0
  10. package/dist/components/DatePicker/index.d.ts.map +1 -0
  11. package/dist/components/DatePicker/index.js +147 -0
  12. package/dist/components/DatePicker/index.js.map +1 -0
  13. package/dist/components/Effect/index.d.ts +1 -1
  14. package/dist/components/Effect/index.d.ts.map +1 -1
  15. package/dist/components/Effect/index.js.map +1 -1
  16. package/dist/components/Input/index.d.ts +3 -1
  17. package/dist/components/Input/index.d.ts.map +1 -1
  18. package/dist/components/Input/index.js +5 -1
  19. package/dist/components/Input/index.js.map +1 -1
  20. package/dist/components/InternalPopover/index.d.ts +2 -0
  21. package/dist/components/InternalPopover/index.d.ts.map +1 -1
  22. package/dist/components/InternalPopover/index.js +5 -4
  23. package/dist/components/InternalPopover/index.js.map +1 -1
  24. package/dist/components/Slider/index.d.ts +40 -0
  25. package/dist/components/Slider/index.d.ts.map +1 -0
  26. package/dist/components/Slider/index.js +148 -0
  27. package/dist/components/Slider/index.js.map +1 -0
  28. package/dist/components/Tag/index.js.map +1 -1
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +2 -0
  32. package/dist/index.js.map +1 -1
  33. package/package.json +5 -1
  34. package/src/components/Button/index.tsx +7 -2
  35. package/src/components/ControlGroup/index.tsx +19 -3
  36. package/src/components/DatePicker/index.tsx +347 -0
  37. package/src/components/Effect/index.tsx +1 -0
  38. package/src/components/Input/index.tsx +18 -5
  39. package/src/components/InternalPopover/index.tsx +10 -10
  40. package/src/components/Slider/index.tsx +358 -0
  41. package/src/components/Tag/index.tsx +4 -4
  42. package/src/index.tsx +2 -0
  43. package/src/stories/DatePicker/DatePicker.stories.tsx +348 -0
  44. package/src/stories/Dropdown/Dropdown.stories.tsx +3 -3
  45. package/src/stories/Slider/Slider.stories.tsx +173 -0
  46. package/tests.json +1 -1
@@ -0,0 +1,358 @@
1
+ import * as Slider from '@radix-ui/react-slider';
2
+ import { useCallback, useMemo, useState } from 'react';
3
+ import styled, { css } from 'styled-components';
4
+ import { HALF_PADDING_FROM_SIZE, ICON_FROM_SIZE, TSizes } from '../../constants/sizes';
5
+ import { IReqoreCustomTheme, TReqoreIntent } from '../../constants/theme';
6
+ import { changeLightness, getReadableColor } from '../../helpers/colors';
7
+ import { useReqoreTheme } from '../../hooks/useTheme';
8
+ import { useTooltip } from '../../hooks/useTooltip';
9
+ import { TReqoreTooltipProp } from '../../types/global';
10
+ import { IReqoreIconName } from '../../types/icons';
11
+ import ReqoreControlGroup, { IReqoreControlGroupProps } from '../ControlGroup';
12
+ import { IReqoreEffect, IReqoreTextEffectProps, StyledEffect, TReqoreEffectColor } from '../Effect';
13
+ import ReqoreIcon, { IReqoreIconProps } from '../Icon';
14
+ import { IReqoreParagraphProps, ReqoreP } from '../Paragraph';
15
+ import ReqoreTag, { IReqoreTagProps } from '../Tag';
16
+
17
+ export interface ISliderProps<T extends number | [number, number] = number>
18
+ extends Omit<Slider.SliderProps, 'onChange' | 'value' | 'defaultValue' | 'onValueChange'> {
19
+ value: T;
20
+ onChange(values: T): void;
21
+ fluid?: boolean;
22
+
23
+ icon?: IReqoreIconName;
24
+ iconColor?: TReqoreEffectColor;
25
+ iconProps?: IReqoreIconProps;
26
+
27
+ rightIcon?: IReqoreIconName;
28
+ rightIconColor?: TReqoreEffectColor;
29
+ rightIconProps?: IReqoreIconProps;
30
+
31
+ showLabels?: boolean;
32
+ size?: TSizes;
33
+ labelsPosition: 'top' | 'bottom';
34
+ customTheme?: IReqoreCustomTheme;
35
+ intent?: TReqoreIntent;
36
+ effect?: IReqoreEffect;
37
+ tooltip: TReqoreTooltipProp;
38
+
39
+ trackProps?: Partial<IReqoreTextEffectProps>;
40
+ rangeProps?: Partial<IReqoreTextEffectProps>;
41
+ thumbProps?: Partial<IReqoreTextEffectProps>;
42
+
43
+ minLabelProps?: IReqoreParagraphProps;
44
+ currentMinLabelProps?: IReqoreTagProps;
45
+ maxLabelProps?: IReqoreParagraphProps;
46
+ currentMaxLabelProps?: IReqoreTagProps;
47
+ wrapperProps?: IReqoreControlGroupProps;
48
+
49
+ displayCurrentValueOverThumb?: boolean;
50
+ }
51
+
52
+ const StyledControlGroupWrapper = styled(ReqoreControlGroup)`
53
+ &[data-orientation='horizontal'] {
54
+ &[data-fluid='false'] {
55
+ max-width: 200px;
56
+ min-width: 200px;
57
+ }
58
+ }
59
+ &[data-orientation='vertical'] {
60
+ &[data-fluid='false'] {
61
+ max-height: 200px;
62
+ }
63
+ }
64
+ `;
65
+
66
+ const StyledTrack = styled(Slider.Track)`
67
+ background-color: ${(props) => props.background};
68
+ position: relative;
69
+ border-radius: 9999px;
70
+ `;
71
+ const StyledRange = styled(Slider.Range)`
72
+ position: absolute;
73
+ background-color: ${(props) => props.background};
74
+ border-radius: 9999px;
75
+ `;
76
+ const StyledThumb = styled(Slider.Thumb)`
77
+ display: block;
78
+ background-color: ${(props) => props.background};
79
+ border-radius: 9999px;
80
+ transition: all 0.2s ease-out;
81
+
82
+ &:focus {
83
+ box-shadow: 0 0 0 8px ${(props) => props.background}15;
84
+ outline: none;
85
+ }
86
+ `;
87
+ const StyledRoot = styled(Slider.Root)`
88
+ position: relative;
89
+ display: inline-flex;
90
+ align-items: center;
91
+ cursor: pointer;
92
+ flex-grow: 1;
93
+
94
+ &[aria-disabled='true'] {
95
+ opacity: 0.5;
96
+ cursor: not-allowed;
97
+ pointer-events: none;
98
+ }
99
+
100
+ ${({ 'data-size': size }) => css`
101
+ ${StyledThumb} {
102
+ width: ${ICON_FROM_SIZE[size]}px;
103
+ height: ${ICON_FROM_SIZE[size]}px;
104
+ min-width: ${ICON_FROM_SIZE[size]}px;
105
+ }
106
+ `}
107
+
108
+ &[data-orientation='horizontal'] {
109
+ width: 100%;
110
+
111
+ ${({ 'data-size': size }) => css`
112
+ height: ${ICON_FROM_SIZE[size]}px;
113
+
114
+ ${StyledTrack} {
115
+ height: ${HALF_PADDING_FROM_SIZE[size]}px;
116
+ }
117
+ `}
118
+
119
+ ${StyledTrack} {
120
+ flex-grow: 1;
121
+ }
122
+ ${StyledRange} {
123
+ height: 100%;
124
+ }
125
+ }
126
+
127
+ &[data-orientation='vertical'] {
128
+ flex-direction: column;
129
+ justify-content: center;
130
+ height: 200px;
131
+
132
+ ${({ 'data-size': size }) => css`
133
+ width: ${ICON_FROM_SIZE[size]}px;
134
+
135
+ ${StyledTrack} {
136
+ width: ${HALF_PADDING_FROM_SIZE[size]}px;
137
+ }
138
+ `}
139
+
140
+ ${StyledTrack} {
141
+ flex-grow: 1;
142
+ }
143
+ ${StyledRange} {
144
+ width: 100%;
145
+ }
146
+ }
147
+ `;
148
+
149
+ const StyledCurrentValue = styled(ReqoreTag)`
150
+ position: absolute;
151
+ ${({ position, isAboveThreshold, isBelowThreshold }) =>
152
+ css`
153
+ ${position}: ${isAboveThreshold || isBelowThreshold ? '-5px' : '-35px'};
154
+ ${position === 'left' || position === 'right' ? 'top' : 'left'}: 50%;
155
+ transform: ${position === 'left' || position === 'right'
156
+ ? 'translateY(-50%)'
157
+ : 'translateX(-50%)'};
158
+ `}
159
+ `;
160
+
161
+ const SliderRootWrapper = styled(ReqoreControlGroup)`
162
+ align-items: center;
163
+ flex-grow: 1;
164
+ width: 100%;
165
+ `;
166
+
167
+ export function ReqoreSlider<T extends number | [number, number] = number>({
168
+ value,
169
+ onChange,
170
+ step = 0.1,
171
+ orientation = 'horizontal',
172
+ fluid = true,
173
+ showLabels,
174
+ icon,
175
+ iconColor,
176
+ iconProps,
177
+ rightIcon,
178
+ rightIconColor,
179
+ rightIconProps,
180
+ customTheme,
181
+ intent,
182
+ effect,
183
+ trackProps,
184
+ rangeProps,
185
+ thumbProps,
186
+ minLabelProps,
187
+ maxLabelProps,
188
+ size = 'normal',
189
+ wrapperProps,
190
+ labelsPosition = 'top',
191
+ tooltip,
192
+ currentMaxLabelProps,
193
+ currentMinLabelProps,
194
+ displayCurrentValueOverThumb,
195
+ ...props
196
+ }: ISliderProps<T>) {
197
+ const [wrapperRef, setWrapperRef] = useState<HTMLDivElement>(undefined);
198
+ const theme = useReqoreTheme('main', customTheme, intent);
199
+
200
+ useTooltip(wrapperRef, tooltip);
201
+
202
+ const background = intent
203
+ ? changeLightness(theme.main, 0.2)
204
+ : getReadableColor(theme, undefined, undefined, true);
205
+ const trackBackground = intent
206
+ ? changeLightness(theme.main, 0.05)
207
+ : changeLightness(theme.main, 0.2);
208
+ const isRange = Array.isArray(value);
209
+
210
+ const renderLabels = useCallback(() => {
211
+ if (!showLabels) {
212
+ return null;
213
+ }
214
+
215
+ return (
216
+ <ReqoreControlGroup fluid spaceBetween vertical={orientation === 'vertical'} fill>
217
+ <ReqoreControlGroup fixed vertical={orientation === 'vertical'} horizontalAlign='center'>
218
+ {icon && (
219
+ <ReqoreIcon icon={icon} size={size} color={iconColor} intent={intent} {...iconProps} />
220
+ )}
221
+ {props.min || props.min === 0 ? (
222
+ <ReqoreP size={size} intent={intent} effect={effect} {...minLabelProps}>
223
+ {props.min}
224
+ </ReqoreP>
225
+ ) : null}
226
+ </ReqoreControlGroup>
227
+ <ReqoreControlGroup fixed vertical={orientation === 'vertical'} horizontalAlign='center'>
228
+ {props.max || props.max === 0 ? (
229
+ <ReqoreP size={size} intent={intent} effect={effect} {...maxLabelProps}>
230
+ {props.max}
231
+ </ReqoreP>
232
+ ) : null}
233
+ {rightIcon && (
234
+ <ReqoreIcon
235
+ icon={rightIcon}
236
+ size={size}
237
+ color={rightIconColor}
238
+ intent={intent}
239
+ {...rightIconProps}
240
+ />
241
+ )}
242
+ </ReqoreControlGroup>
243
+ </ReqoreControlGroup>
244
+ );
245
+ }, [
246
+ icon,
247
+ rightIcon,
248
+ iconProps,
249
+ rightIconProps,
250
+ minLabelProps,
251
+ maxLabelProps,
252
+ size,
253
+ intent,
254
+ props.min,
255
+ props.max,
256
+ showLabels,
257
+ orientation,
258
+ effect,
259
+ ]);
260
+
261
+ const currentValuePosition = useMemo(() => {
262
+ return orientation === 'horizontal'
263
+ ? labelsPosition === 'top'
264
+ ? 'top'
265
+ : 'bottom'
266
+ : labelsPosition === 'top'
267
+ ? 'left'
268
+ : 'right';
269
+ }, [orientation, labelsPosition]);
270
+
271
+ const isMinValueBelowThreshold = useMemo(() => {
272
+ const _value: number = isRange ? value[0] : value;
273
+
274
+ return _value < props.min + step * 5;
275
+ }, [value, props.min]);
276
+
277
+ const isMaxValueAboveThreshold = useMemo(() => {
278
+ if (!isRange) return false;
279
+
280
+ const _value: number = value[1];
281
+
282
+ return _value > props.max - step * 5;
283
+ }, [value, props.max]);
284
+
285
+ return (
286
+ <StyledControlGroupWrapper
287
+ ref={setWrapperRef}
288
+ data-orientation={orientation}
289
+ data-labels-position={labelsPosition}
290
+ data-fluid={fluid}
291
+ fluid={fluid}
292
+ vertical={orientation === 'horizontal'}
293
+ fill
294
+ gapSize={orientation === 'horizontal' ? 'big' : 'normal'}
295
+ {...wrapperProps}
296
+ >
297
+ {labelsPosition === 'top' && renderLabels()}
298
+ <SliderRootWrapper vertical={orientation === 'vertical'}>
299
+ <StyledRoot
300
+ data-size={size}
301
+ orientation={orientation}
302
+ minStepsBetweenThumbs={step}
303
+ inverted={orientation === 'vertical'}
304
+ step={step}
305
+ {...props}
306
+ value={isRange ? value : [value]}
307
+ onValueChange={(values) => {
308
+ onChange((isRange ? values : values[0]) as T);
309
+ }}
310
+ >
311
+ <StyledTrack background={trackBackground} asChild>
312
+ <StyledEffect effect={effect} {...trackProps}>
313
+ <StyledRange background={background} asChild>
314
+ <StyledEffect effect={effect} {...rangeProps} />
315
+ </StyledRange>
316
+ </StyledEffect>
317
+ </StyledTrack>
318
+
319
+ <StyledThumb background={background} asChild>
320
+ <StyledEffect effect={effect} {...thumbProps}>
321
+ {showLabels && (
322
+ <StyledCurrentValue
323
+ size={size}
324
+ effect={effect}
325
+ intent={intent}
326
+ position={currentValuePosition}
327
+ label={isRange ? value[0] : value}
328
+ isBelowThreshold={displayCurrentValueOverThumb || isMinValueBelowThreshold}
329
+ {...currentMinLabelProps}
330
+ />
331
+ )}
332
+ </StyledEffect>
333
+ </StyledThumb>
334
+ {isRange && (
335
+ <StyledThumb background={background} asChild>
336
+ <StyledEffect effect={effect} {...thumbProps}>
337
+ {showLabels && (
338
+ <StyledCurrentValue
339
+ size={size}
340
+ effect={effect}
341
+ intent={intent}
342
+ position={currentValuePosition}
343
+ isAboveThreshold={displayCurrentValueOverThumb || isMaxValueAboveThreshold}
344
+ label={value[1]}
345
+ {...currentMaxLabelProps}
346
+ />
347
+ )}
348
+ </StyledEffect>
349
+ </StyledThumb>
350
+ )}
351
+ </StyledRoot>
352
+ </SliderRootWrapper>
353
+ {labelsPosition === 'bottom' && renderLabels()}
354
+ </StyledControlGroupWrapper>
355
+ );
356
+ }
357
+
358
+ export default ReqoreSlider;
@@ -150,8 +150,8 @@ export const StyledTag = styled(StyledEffect)<IReqoreTagStyle>`
150
150
  color: ${minimal
151
151
  ? getReadableColor(theme, undefined, undefined, true)
152
152
  : color && color !== 'transparent'
153
- ? getReadableColorFrom(color)
154
- : getReadableColorFrom(changeLightness(theme.main, 0.1))};
153
+ ? getReadableColorFrom(color)
154
+ : getReadableColorFrom(changeLightness(theme.main, 0.1))};
155
155
 
156
156
  ${StyledTagKeyWrapper} {
157
157
  background-color: ${labelKey ? rgba('#000000', 0.2) : undefined};
@@ -175,8 +175,8 @@ export const StyledTag = styled(StyledEffect)<IReqoreTagStyle>`
175
175
  color: ${minimal
176
176
  ? getReadableColor(theme, undefined, undefined, false, theme.originalMain)
177
177
  : color
178
- ? getReadableColorFrom(color)
179
- : getReadableColor(theme, undefined, undefined)};
178
+ ? getReadableColorFrom(color)
179
+ : getReadableColor(theme, undefined, undefined)};
180
180
  `}
181
181
  }
182
182
  `
package/src/index.tsx CHANGED
@@ -9,6 +9,7 @@ export { ReqoreComment } from './components/Comment';
9
9
  export { ReqoreCommentFeed } from './components/CommentFeed';
10
10
  export { default as ReqoreContent } from './components/Content';
11
11
  export { default as ReqoreControlGroup } from './components/ControlGroup';
12
+ export * from './components/DatePicker';
12
13
  export { ReqoreDrawer } from './components/Drawer';
13
14
  export { ReqoreBackdrop } from './components/Drawer/backdrop';
14
15
  export { default as ReqoreDropdown } from './components/Dropdown';
@@ -46,6 +47,7 @@ export { ReqorePanel } from './components/Panel';
46
47
  export { ReqoreP, ReqoreP as ReqoreParagraph } from './components/Paragraph';
47
48
  export { default as ReqorePopover } from './components/Popover';
48
49
  export { default as ReqoreRadioGroup } from './components/RadioGroup';
50
+ export * from './components/Slider';
49
51
  export { ReqoreHorizontalSpacer, ReqoreSpacer, ReqoreVerticalSpacer } from './components/Spacer';
50
52
  export { ReqoreSpinner } from './components/Spinner';
51
53
  export { default as ReqoreTable } from './components/Table';