@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,348 @@
1
+ import { expect } from '@storybook/jest';
2
+ import { StoryObj } from '@storybook/react';
3
+ import { userEvent, within } from '@storybook/testing-library';
4
+ import { size } from 'lodash';
5
+ import { useState } from 'react';
6
+ import ReqoreControlGroup from '../../components/ControlGroup';
7
+ import { DatePicker } from '../../components/DatePicker';
8
+ import { DEFAULT_INTENTS, TReqoreIntent } from '../../constants/theme';
9
+ import { StoryMeta } from '../utils';
10
+ import { FlatArg, IntentArg, MinimalArg, SizeArg } from '../utils/args';
11
+
12
+ const meta = {
13
+ title: 'Form/DatePicker/Stories',
14
+ component: DatePicker,
15
+ argTypes: {
16
+ ...MinimalArg,
17
+ ...FlatArg,
18
+ ...SizeArg,
19
+ ...IntentArg,
20
+ },
21
+ parameters: {
22
+ chromatic: {
23
+ viewports: [1440],
24
+ },
25
+ mockdate: new Date('2024-04-10T08:00:00.000Z'),
26
+ },
27
+ args: {
28
+ fluid: false,
29
+ value: new Date(2024, 3, 10, 8, 0, 0),
30
+ popoverProps: {
31
+ openOnMount: process.env.NODE_ENV === 'production',
32
+ },
33
+ 'aria-label': 'Datepicker',
34
+ },
35
+ render(args) {
36
+ const [value, setValue] = useState<Date | string>(args.value);
37
+ return (
38
+ <DatePicker
39
+ {...args}
40
+ value={value}
41
+ onChange={(v) => {
42
+ setValue(v);
43
+ args.onChange?.(v);
44
+ }}
45
+ />
46
+ );
47
+ },
48
+ } as StoryMeta<typeof DatePicker>;
49
+ type Story = StoryObj<typeof meta>;
50
+
51
+ const getDateElements = async (canvasElement: HTMLElement) => {
52
+ const canvas = within(canvasElement);
53
+ const month = await canvas.findByLabelText('month, Datepicker');
54
+ const day = await canvas.findByLabelText('day, Datepicker');
55
+ const year = await canvas.findByLabelText('year, Datepicker');
56
+ const hour = await canvas.findByLabelText('hour, Datepicker');
57
+ const minute = await canvas.findByLabelText('minute, Datepicker');
58
+ const popover = await canvasElement.querySelector('reqore-popover-content');
59
+ const input = await canvasElement.querySelector('input');
60
+
61
+ return {
62
+ month,
63
+ day,
64
+ year,
65
+ hour,
66
+ minute,
67
+ popover,
68
+ input,
69
+ canvas,
70
+ };
71
+ };
72
+ const getPopoverElements = async (canvasElement: HTMLElement) => {
73
+ const popover = canvasElement.querySelector('.reqore-popover-content');
74
+ const popoverCanvas = within(popover as HTMLElement);
75
+ const previousMonth = canvasElement.querySelector('button[aria-label="Previous"]');
76
+ const nextMonth = canvasElement.querySelector('button[aria-label="Next"]');
77
+ const hourTimeField = popoverCanvas.getByLabelText('hour, Time');
78
+ const minuteTimeField = popoverCanvas.getByLabelText('minute, Time');
79
+ const headingCanvas = within(canvasElement.querySelector('.reqore-panel .reqore-panel-title'));
80
+
81
+ return {
82
+ popoverCanvas,
83
+ headingCanvas,
84
+ popover,
85
+ previousMonth,
86
+ nextMonth,
87
+ hourTimeField,
88
+ minuteTimeField,
89
+ };
90
+ };
91
+ export default meta;
92
+ export const Default: Story = {
93
+ args: {
94
+ value: new Date(2024, 4, 10, 8, 0, 0),
95
+ },
96
+ async play({ canvasElement }) {
97
+ const { month, year, day, hour, minute, input } = await getDateElements(canvasElement);
98
+
99
+ await expect(month).toBeInTheDocument();
100
+ await expect(day).toBeInTheDocument();
101
+ await expect(year).toBeInTheDocument();
102
+ await expect(hour).toBeInTheDocument();
103
+ await expect(minute).toBeInTheDocument();
104
+ await expect(input).toBeInTheDocument();
105
+
106
+ await expect(month).toHaveTextContent('05');
107
+ await expect(day).toHaveTextContent('10');
108
+ await expect(year).toHaveTextContent('2024');
109
+ await expect(hour).toHaveTextContent('08');
110
+ await expect(minute).toHaveTextContent('00');
111
+ },
112
+ };
113
+
114
+ export const WithAM_PM: Story = {
115
+ args: {
116
+ hourCycle: 12,
117
+ },
118
+ async play({ canvasElement }) {
119
+ const canvas = within(canvasElement);
120
+ const AM_PM = await canvas.findByLabelText('AM/PM, Datepicker');
121
+
122
+ await expect(AM_PM).toBeInTheDocument();
123
+ },
124
+ };
125
+ export const WithoutDefaultValue: Story = {
126
+ args: {
127
+ value: null,
128
+ popoverProps: {},
129
+ },
130
+ async play({ canvasElement }) {
131
+ const { month, year, day, hour, minute, input } = await getDateElements(canvasElement);
132
+ await expect(month).toHaveTextContent('mm');
133
+ await expect(day).toHaveTextContent('d');
134
+ await expect(year).toHaveTextContent('yyyy');
135
+ await expect(hour).toHaveTextContent('––');
136
+ await expect(minute).toHaveTextContent('––');
137
+
138
+ await userEvent.click(input);
139
+ const { headingCanvas, hourTimeField, minuteTimeField } =
140
+ await getPopoverElements(canvasElement);
141
+ const heading = headingCanvas.queryByText('April 2024');
142
+ await expect(heading).toBeInTheDocument();
143
+ await expect(hourTimeField).toHaveTextContent('––');
144
+ await expect(minuteTimeField).toHaveTextContent('––');
145
+ },
146
+ };
147
+
148
+ export const WithoutTimePicker: Story = {
149
+ args: {
150
+ granularity: 'day',
151
+ popoverProps: { openOnMount: true },
152
+ },
153
+ async play({ canvasElement }) {
154
+ const canvas = within(canvasElement);
155
+ const hour = await canvas.queryByLabelText('hour, Datepicker');
156
+ const minute = await canvas.queryByLabelText('minute, Datepicker');
157
+ const timefield = canvasElement.querySelector('.reqore-popover-content .reqore-input');
158
+
159
+ await expect(hour).toBeNull();
160
+ await expect(minute).toBeNull();
161
+ await expect(timefield).toBeNull();
162
+ },
163
+ };
164
+ export const WithIntent: Story = {
165
+ args: {
166
+ popoverProps: {
167
+ openOnMount: false,
168
+ },
169
+ },
170
+ render(args, ctx) {
171
+ return (
172
+ <ReqoreControlGroup gapSize='big' vertical>
173
+ {Object.keys(DEFAULT_INTENTS)
174
+ .reverse()
175
+ .map((intent, index) =>
176
+ meta.render(
177
+ {
178
+ ...args,
179
+ intent: intent as TReqoreIntent,
180
+ pickerActiveDayProps: {
181
+ intent: intent as TReqoreIntent,
182
+ },
183
+ popoverProps: {
184
+ openOnMount: index === size(DEFAULT_INTENTS) - 1,
185
+ },
186
+ },
187
+ ctx
188
+ )
189
+ )}
190
+ </ReqoreControlGroup>
191
+ );
192
+ },
193
+ };
194
+
195
+ export const WithEffect: Story = {
196
+ args: {
197
+ pickerProps: {
198
+ contentEffect: {
199
+ gradient: {
200
+ colors: 'info',
201
+ },
202
+ },
203
+ },
204
+ },
205
+ };
206
+ export const Minimal: Story = {
207
+ args: { minimal: true },
208
+ };
209
+ export const Pill: Story = {
210
+ args: { pill: true },
211
+ };
212
+ export const WithTooltip: Story = {
213
+ args: {
214
+ tooltip: `Tooltip content`,
215
+ },
216
+ };
217
+
218
+ export const ValueCanBeTyped: Story = {
219
+ parameters: {
220
+ chromatic: { disableSnapshot: true },
221
+ },
222
+ args: {},
223
+ async play({ canvasElement }) {
224
+ const { month, year, day, hour, minute } = await getDateElements(canvasElement);
225
+
226
+ await userEvent.type(month, '05');
227
+ await userEvent.type(day, '15');
228
+ await userEvent.type(year, '2024');
229
+ await userEvent.type(hour, '08');
230
+ await userEvent.type(minute, '30');
231
+
232
+ await expect(month).toHaveTextContent('05');
233
+ await expect(day).toHaveTextContent('15');
234
+ await expect(year).toHaveTextContent('2024');
235
+ await expect(hour).toHaveTextContent('08');
236
+ await expect(minute).toHaveTextContent('30');
237
+ },
238
+ };
239
+ export const ValueCanBeCleared: Story = {
240
+ parameters: {
241
+ chromatic: { disableSnapshot: true },
242
+ },
243
+
244
+ async play({ canvasElement }) {
245
+ const { month, year, day, hour, minute } = await getDateElements(canvasElement);
246
+ const clearBtn = await canvasElement.querySelector('.reqore-clear-input-button');
247
+ await expect(clearBtn).toBeInTheDocument();
248
+ await userEvent.click(clearBtn);
249
+ await expect(month).toHaveTextContent('mm');
250
+ await expect(day).toHaveTextContent('dd');
251
+ await expect(year).toHaveTextContent('yyyy');
252
+ await expect(hour).toHaveTextContent('––');
253
+ await expect(minute).toHaveTextContent('––');
254
+ },
255
+ };
256
+ export const ValueCanBeChosenFromPopover: Story = {
257
+ parameters: {
258
+ chromatic: { disableSnapshot: true },
259
+ },
260
+ args: {
261
+ popoverProps: {},
262
+ },
263
+ async play({ canvasElement }) {
264
+ const { month, year, day, hour, minute, input } = await getDateElements(canvasElement);
265
+ await userEvent.click(input);
266
+ const { popover, popoverCanvas, nextMonth } = await getPopoverElements(canvasElement);
267
+ await expect(popover).toBeInTheDocument();
268
+ await userEvent.click(nextMonth);
269
+ const cell = popoverCanvas.getByText('25');
270
+ await userEvent.click(cell);
271
+ await expect(month).toHaveTextContent('05');
272
+ await expect(day).toHaveTextContent('25');
273
+ await expect(year).toHaveTextContent('2024');
274
+ await expect(hour).toHaveTextContent('08');
275
+ await expect(minute).toHaveTextContent('00');
276
+ },
277
+ };
278
+
279
+ export const CurrentCalendarMonthCanBeChanged: Story = {
280
+ parameters: {
281
+ chromatic: { disableSnapshot: true },
282
+ },
283
+ args: {
284
+ popoverProps: {},
285
+ },
286
+ async play({ canvasElement }) {
287
+ const { input } = await getDateElements(canvasElement);
288
+ await userEvent.click(input);
289
+ const { popover, headingCanvas, nextMonth, previousMonth } =
290
+ await getPopoverElements(canvasElement);
291
+ await expect(popover).toBeInTheDocument();
292
+ await userEvent.click(nextMonth);
293
+ let heading = headingCanvas.queryByText('May 2024');
294
+ await expect(heading).toBeInTheDocument();
295
+
296
+ await userEvent.click(previousMonth);
297
+ heading = headingCanvas.queryByText('April 2024');
298
+ await expect(heading).toBeInTheDocument();
299
+ },
300
+ };
301
+ export const TimeCanBeChangedFromPopover: Story = {
302
+ args: {
303
+ popoverProps: {},
304
+ },
305
+ async play({ canvasElement }) {
306
+ const { input, hour, minute } = await getDateElements(canvasElement);
307
+ await userEvent.click(input);
308
+ const { hourTimeField, minuteTimeField } = await getPopoverElements(canvasElement);
309
+
310
+ await userEvent.type(hourTimeField, '10');
311
+ await userEvent.type(minuteTimeField, '15');
312
+
313
+ await expect(hour).toHaveTextContent('10');
314
+ await expect(minute).toHaveTextContent('15');
315
+ },
316
+ };
317
+ export const ShouldSaveTimeWhenDateValueIsNull: Story = {
318
+ parameters: {
319
+ chromatic: { disableSnapshot: true },
320
+ },
321
+ args: {
322
+ value: null,
323
+ popoverProps: {},
324
+ },
325
+ async play({ canvasElement }) {
326
+ const { input } = await getDateElements(canvasElement);
327
+
328
+ await userEvent.click(input);
329
+ const { month, day, year, hour, minute } = await getDateElements(canvasElement);
330
+ const { hourTimeField, minuteTimeField } = await getPopoverElements(canvasElement);
331
+ await userEvent.type(hourTimeField, '08');
332
+ await userEvent.type(minuteTimeField, '15');
333
+ await userEvent.click(canvasElement);
334
+ await userEvent.click(input);
335
+ await expect(hourTimeField).toHaveTextContent('08');
336
+ await expect(minuteTimeField).toHaveTextContent('15');
337
+
338
+ const { popoverCanvas } = await getPopoverElements(canvasElement);
339
+
340
+ const cell = popoverCanvas.getByText('25');
341
+ await userEvent.click(cell);
342
+ await expect(month).toHaveTextContent('04');
343
+ await expect(day).toHaveTextContent('25');
344
+ await expect(year).toHaveTextContent('2024');
345
+ await expect(hour).toHaveTextContent('08');
346
+ await expect(minute).toHaveTextContent('15');
347
+ },
348
+ };
@@ -176,11 +176,10 @@ const Template: StoryFn<typeof ReqoreDropdown<IReqoreButtonProps>> = (args) => {
176
176
  <ReqoreDropdown
177
177
  rightIcon='SunCloudyLine'
178
178
  caretPosition='right'
179
+ label='Custom icon with caret on right'
179
180
  {...args}
180
181
  iconColor='success:lighten:2'
181
- >
182
- Custom icon with caret on right
183
- </ReqoreDropdown>
182
+ />
184
183
  <ReqoreDropdown
185
184
  items={[
186
185
  {
@@ -235,6 +234,7 @@ export const CustomComponent: Story = {
235
234
  args: {
236
235
  component: ReqoreInput,
237
236
  placeholder: 'Custom component',
237
+ label: undefined,
238
238
  },
239
239
  };
240
240
 
@@ -0,0 +1,173 @@
1
+ import { StoryObj } from '@storybook/react';
2
+ import { useState } from 'react';
3
+ import ReqoreControlGroup from '../../components/ControlGroup';
4
+ import ReqoreSlider from '../../components/Slider';
5
+ import { StoryMeta } from '../utils';
6
+ import { DisabledArg, IconArg, MinimalArg, SizeArg } from '../utils/args';
7
+
8
+ const meta = {
9
+ title: 'Form/Slider/Stories',
10
+ component: ReqoreSlider,
11
+ argTypes: {
12
+ ...MinimalArg,
13
+ ...SizeArg,
14
+ ...DisabledArg,
15
+ ...IconArg('icon', 'Icon'),
16
+ ...IconArg('rightIcon', 'Right Icon'),
17
+ fluid: {
18
+ control: 'boolean',
19
+ defaultValue: true,
20
+ },
21
+ labelsPosition: {
22
+ control: 'select',
23
+ defaultValue: 'top',
24
+ options: ['top', 'bottom'],
25
+ },
26
+ },
27
+ args: {
28
+ value: [2, 9.6],
29
+ min: 0,
30
+ max: 10,
31
+ fluid: true,
32
+ },
33
+ render(args) {
34
+ const [value, setValue] = useState(args.value);
35
+ return (
36
+ <>
37
+ <ReqoreControlGroup style={{ width: '100%' }} vertical gapSize='huge'>
38
+ <ReqoreSlider {...args} value={value[0]} onChange={(min) => setValue([min, value[1]])} />
39
+
40
+ <ReqoreSlider {...args} value={value} onChange={setValue} />
41
+ <ReqoreControlGroup gapSize='huge'>
42
+ <ReqoreSlider
43
+ {...args}
44
+ orientation='vertical'
45
+ value={value[0]}
46
+ onChange={(min) => setValue([min, value[1]])}
47
+ />
48
+ <ReqoreSlider {...args} orientation='vertical' value={value} onChange={setValue} />
49
+ </ReqoreControlGroup>
50
+ </ReqoreControlGroup>
51
+ </>
52
+ );
53
+ },
54
+ } as StoryMeta<typeof ReqoreSlider>;
55
+ type Story = StoryObj<typeof meta>;
56
+
57
+ export default meta;
58
+ export const Default: Story = {};
59
+ export const Disabled: Story = {
60
+ args: {
61
+ disabled: true,
62
+ },
63
+ };
64
+
65
+ export const WithIcons: Story = {
66
+ args: {
67
+ icon: 'VolumeDownLine',
68
+ rightIcon: 'VolumeUpLine',
69
+ },
70
+ };
71
+ export const WithIntent: Story = {
72
+ args: {
73
+ intent: 'success',
74
+ },
75
+ render(args, ctx) {
76
+ return (
77
+ <ReqoreControlGroup vertical gapSize='huge'>
78
+ {meta.render({ ...args, intent: 'info' }, ctx)}
79
+ {meta.render({ ...args, intent: 'success', showLabels: true }, ctx)}
80
+ {meta.render(
81
+ {
82
+ ...args,
83
+ intent: 'warning',
84
+ showLabels: true,
85
+ minLabelProps: { intent: 'info' },
86
+ icon: 'WeiboFill',
87
+ },
88
+ ctx
89
+ )}
90
+ {meta.render({ ...args, intent: 'danger' }, ctx)}
91
+ </ReqoreControlGroup>
92
+ );
93
+ },
94
+ };
95
+ export const WithLabels: Story = {
96
+ args: {
97
+ showLabels: true,
98
+ },
99
+ };
100
+ export const WithLabelsBelow: Story = {
101
+ args: {
102
+ showLabels: true,
103
+ labelsPosition: 'bottom',
104
+ },
105
+ };
106
+ export const WithLabelsAndIcons: Story = {
107
+ args: {
108
+ ...WithLabels.args,
109
+ ...WithIcons.args,
110
+ },
111
+ };
112
+
113
+ export const WithCurrentValueOverThumb: Story = {
114
+ args: {
115
+ ...WithLabels.args,
116
+ ...WithIcons.args,
117
+ displayCurrentValueOverThumb: true,
118
+ },
119
+ };
120
+
121
+ export const WithSize: Story = {
122
+ args: {
123
+ ...WithLabels.args,
124
+ ...WithIcons.args,
125
+ size: 'small',
126
+ },
127
+ };
128
+
129
+ export const WithEffect: Story = {
130
+ args: {
131
+ showLabels: true,
132
+ effect: {
133
+ gradient: {
134
+ direction: 'to right bottom',
135
+ colors: { 0: '#ca74da', 100: '#521b6e' },
136
+ animate: 'active',
137
+ },
138
+ spaced: 2,
139
+ uppercase: true,
140
+ weight: 'thick',
141
+ textSize: 'small',
142
+ },
143
+
144
+ rangeProps: {
145
+ effect: {
146
+ gradient: {
147
+ direction: 'to right bottom',
148
+ colors: { 0: '#f9f9f9', 100: '#ca55a9' },
149
+ animate: 'always',
150
+ },
151
+ },
152
+ },
153
+ thumbProps: {
154
+ effect: {
155
+ gradient: {
156
+ direction: 'to right bottom',
157
+ colors: { 0: '#f9f9f9', 100: '#ca55a9' },
158
+ animate: 'active',
159
+ },
160
+ },
161
+ },
162
+
163
+ currentMaxLabelProps: {
164
+ effect: {
165
+ gradient: {
166
+ type: 'radial',
167
+ colors: { 0: '#41baea', 100: '#80ffd9' },
168
+ animate: 'hover',
169
+ },
170
+ },
171
+ },
172
+ },
173
+ };