@indico-data/design-system 2.60.8 → 2.60.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/forms/date/inputDateRangePicker/InputDateRangePicker.d.ts +6 -0
- package/lib/components/forms/select/Select.d.ts +6 -1
- package/lib/components/forms/select/Select.stories.d.ts +2 -1
- package/lib/components/forms/subcomponents/Label.d.ts +1 -1
- package/lib/index.d.ts +13 -3
- package/lib/index.esm.js +16 -6
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +16 -6
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/forms/date/inputDateRangePicker/InputDateRangePicker.stories.tsx +61 -3
- package/src/components/forms/date/inputDateRangePicker/InputDateRangePicker.tsx +37 -6
- package/src/components/forms/select/Select.stories.tsx +38 -1
- package/src/components/forms/select/Select.tsx +12 -1
- package/src/components/forms/subcomponents/Label.tsx +1 -1
- package/src/index.ts +2 -0
package/package.json
CHANGED
|
@@ -89,7 +89,7 @@ const meta: Meta<typeof InputDateRangePicker> = {
|
|
|
89
89
|
},
|
|
90
90
|
},
|
|
91
91
|
isOpen: {
|
|
92
|
-
control:
|
|
92
|
+
control: 'boolean',
|
|
93
93
|
description:
|
|
94
94
|
'Whether the floatingUI component wrapped around the date picker is opened or closed.',
|
|
95
95
|
table: {
|
|
@@ -159,6 +159,26 @@ const meta: Meta<typeof InputDateRangePicker> = {
|
|
|
159
159
|
},
|
|
160
160
|
},
|
|
161
161
|
},
|
|
162
|
+
fromLabel: {
|
|
163
|
+
control: 'text',
|
|
164
|
+
description: 'The label for the `from` input.',
|
|
165
|
+
table: {
|
|
166
|
+
category: 'Props',
|
|
167
|
+
type: {
|
|
168
|
+
summary: 'string',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
toLabel: {
|
|
173
|
+
control: 'text',
|
|
174
|
+
description: 'The label for the `to` input.',
|
|
175
|
+
table: {
|
|
176
|
+
category: 'Props',
|
|
177
|
+
type: {
|
|
178
|
+
summary: 'string',
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
162
182
|
month: {
|
|
163
183
|
control: 'date',
|
|
164
184
|
description: 'The currently displayed month.',
|
|
@@ -169,6 +189,26 @@ const meta: Meta<typeof InputDateRangePicker> = {
|
|
|
169
189
|
},
|
|
170
190
|
},
|
|
171
191
|
},
|
|
192
|
+
closeOnSelect: {
|
|
193
|
+
control: 'boolean',
|
|
194
|
+
description: 'Whether to close the date picker when a complete range is selected.',
|
|
195
|
+
table: {
|
|
196
|
+
category: 'Props',
|
|
197
|
+
type: {
|
|
198
|
+
summary: 'boolean',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
clearOnClose: {
|
|
203
|
+
control: 'boolean',
|
|
204
|
+
description: 'Whether to clear the selected dates when the picker is closed.',
|
|
205
|
+
table: {
|
|
206
|
+
category: 'Props',
|
|
207
|
+
type: {
|
|
208
|
+
summary: 'boolean',
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
},
|
|
172
212
|
'data-testid': {
|
|
173
213
|
table: {
|
|
174
214
|
disable: true,
|
|
@@ -190,16 +230,34 @@ export const RangeInput: Story = {
|
|
|
190
230
|
toErrorMessage: '',
|
|
191
231
|
fromErrorMessage: '',
|
|
192
232
|
ariaLabel: 'Date Picker',
|
|
233
|
+
fromLabel: 'From Date',
|
|
234
|
+
toLabel: 'To Date',
|
|
235
|
+
gutterWidth: 2,
|
|
193
236
|
isOpen: false,
|
|
237
|
+
closeOnSelect: true,
|
|
238
|
+
clearOnClose: false,
|
|
194
239
|
selected: { from: new Date(), to: new Date(new Date().getTime() + 5 * 24 * 60 * 60 * 1000) },
|
|
195
240
|
},
|
|
196
241
|
render: (args) => {
|
|
197
|
-
const [{ selected }, updateArgs] = useArgs();
|
|
242
|
+
const [{ selected, isOpen }, updateArgs] = useArgs();
|
|
198
243
|
|
|
199
244
|
const handleSelect = (date: DateRange | undefined) => {
|
|
200
245
|
updateArgs({ selected: date });
|
|
201
246
|
};
|
|
202
247
|
|
|
203
|
-
|
|
248
|
+
const handleSetIsOpen = (value: React.SetStateAction<boolean>) => {
|
|
249
|
+
const newIsOpen = typeof value === 'function' ? value(isOpen) : value;
|
|
250
|
+
updateArgs({ isOpen: newIsOpen });
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<InputDateRangePicker
|
|
255
|
+
{...args}
|
|
256
|
+
selected={selected}
|
|
257
|
+
onSelect={handleSelect}
|
|
258
|
+
isOpen={isOpen}
|
|
259
|
+
setIsOpen={handleSetIsOpen}
|
|
260
|
+
/>
|
|
261
|
+
);
|
|
204
262
|
},
|
|
205
263
|
};
|
|
@@ -7,6 +7,7 @@ import { DateRange } from 'react-day-picker';
|
|
|
7
7
|
import { FloatUI } from '../../../floatUI';
|
|
8
8
|
import { Col, Row } from '../../../grid';
|
|
9
9
|
import { formatDateAsString } from '../inputDatePicker/helpers';
|
|
10
|
+
import { Button } from '../../../button';
|
|
10
11
|
|
|
11
12
|
interface InputDateRangePickerProps {
|
|
12
13
|
ariaLabel: string;
|
|
@@ -19,12 +20,18 @@ interface InputDateRangePickerProps {
|
|
|
19
20
|
month?: Date;
|
|
20
21
|
selected?: DateRange | undefined;
|
|
21
22
|
isOpen?: boolean;
|
|
23
|
+
setIsOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
22
24
|
className?: string;
|
|
23
25
|
inputIconName?: IconName;
|
|
24
26
|
inputPlaceholder?: string;
|
|
25
27
|
toErrorMessage?: string | undefined;
|
|
26
28
|
fromErrorMessage?: string | undefined;
|
|
27
29
|
'data-testid'?: string;
|
|
30
|
+
gutterWidth?: number;
|
|
31
|
+
fromLabel?: string;
|
|
32
|
+
toLabel?: string;
|
|
33
|
+
closeOnSelect?: boolean;
|
|
34
|
+
clearOnClose?: boolean;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
export function InputDateRangePicker(props: InputDateRangePickerProps) {
|
|
@@ -40,10 +47,16 @@ export function InputDateRangePicker(props: InputDateRangePickerProps) {
|
|
|
40
47
|
onSelect,
|
|
41
48
|
selected,
|
|
42
49
|
isOpen,
|
|
50
|
+
setIsOpen,
|
|
43
51
|
inputPlaceholder,
|
|
44
52
|
inputIconName,
|
|
45
53
|
toErrorMessage,
|
|
46
54
|
fromErrorMessage,
|
|
55
|
+
gutterWidth,
|
|
56
|
+
fromLabel,
|
|
57
|
+
toLabel,
|
|
58
|
+
closeOnSelect,
|
|
59
|
+
clearOnClose,
|
|
47
60
|
...rest
|
|
48
61
|
} = props;
|
|
49
62
|
|
|
@@ -69,6 +82,17 @@ export function InputDateRangePicker(props: InputDateRangePickerProps) {
|
|
|
69
82
|
setLocalTextValueFrom(date.from ? formatDateAsString(date.from) : '');
|
|
70
83
|
setLocalTextValueTo(date.to ? formatDateAsString(date.to) : '');
|
|
71
84
|
onSelect(date);
|
|
85
|
+
|
|
86
|
+
// Close the picker ONLY when a complete range is selected (from and to are different dates)
|
|
87
|
+
if (
|
|
88
|
+
closeOnSelect &&
|
|
89
|
+
date.from &&
|
|
90
|
+
date.to &&
|
|
91
|
+
setIsOpen &&
|
|
92
|
+
date.from.getTime() !== date.to.getTime() // Ensure from and to are different dates
|
|
93
|
+
) {
|
|
94
|
+
setIsOpen(false);
|
|
95
|
+
}
|
|
72
96
|
}
|
|
73
97
|
};
|
|
74
98
|
|
|
@@ -98,16 +122,23 @@ export function InputDateRangePicker(props: InputDateRangePickerProps) {
|
|
|
98
122
|
|
|
99
123
|
// clear selection if clear on close is true
|
|
100
124
|
useEffect(() => {
|
|
101
|
-
if (!isOpen) {
|
|
125
|
+
if (!isOpen && clearOnClose) {
|
|
102
126
|
onSelect(undefined);
|
|
103
127
|
setLocalTextValueFrom('');
|
|
104
128
|
setLocalTextValueTo('');
|
|
105
129
|
}
|
|
106
|
-
}, [isOpen]);
|
|
130
|
+
}, [isOpen, clearOnClose]);
|
|
131
|
+
|
|
132
|
+
// Handle set date button click
|
|
133
|
+
const handleSetDate = () => {
|
|
134
|
+
if (setIsOpen) {
|
|
135
|
+
setIsOpen(false);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
107
138
|
|
|
108
139
|
return (
|
|
109
|
-
<FloatUI isOpen={isOpen} ariaLabel={ariaLabel}>
|
|
110
|
-
<Row>
|
|
140
|
+
<FloatUI isOpen={isOpen} setIsOpen={setIsOpen} ariaLabel={ariaLabel}>
|
|
141
|
+
<Row gutterWidth={gutterWidth}>
|
|
111
142
|
<Col>
|
|
112
143
|
<Input
|
|
113
144
|
id={`${inputId}-from`}
|
|
@@ -117,7 +148,7 @@ export function InputDateRangePicker(props: InputDateRangePickerProps) {
|
|
|
117
148
|
iconName={inputIconName}
|
|
118
149
|
onChange={(e) => handleInputChange(e, 'from')}
|
|
119
150
|
errorMessage={fromErrorMessage}
|
|
120
|
-
label={
|
|
151
|
+
label={fromLabel}
|
|
121
152
|
name={'From Date'}
|
|
122
153
|
data-testid="date-picker-from"
|
|
123
154
|
/>
|
|
@@ -131,7 +162,7 @@ export function InputDateRangePicker(props: InputDateRangePickerProps) {
|
|
|
131
162
|
iconName={inputIconName}
|
|
132
163
|
onChange={(e) => handleInputChange(e, 'to')}
|
|
133
164
|
errorMessage={toErrorMessage}
|
|
134
|
-
label={
|
|
165
|
+
label={toLabel}
|
|
135
166
|
name={'To Date'}
|
|
136
167
|
data-testid="date-picker-to"
|
|
137
168
|
/>
|
|
@@ -1,11 +1,45 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
import { Select, SelectProps } from './Select';
|
|
3
3
|
import { SelectOption } from './types';
|
|
4
|
+
import { LabelProps } from '../subcomponents/Label';
|
|
4
5
|
|
|
5
|
-
const meta: Meta<SelectProps<SelectOption
|
|
6
|
+
const meta: Meta<SelectProps<SelectOption> & LabelProps> = {
|
|
6
7
|
title: 'Forms/Select',
|
|
7
8
|
component: Select,
|
|
8
9
|
argTypes: {
|
|
10
|
+
name: {
|
|
11
|
+
control: 'text',
|
|
12
|
+
description: 'The name of the select component',
|
|
13
|
+
table: {
|
|
14
|
+
category: 'Props',
|
|
15
|
+
type: {
|
|
16
|
+
summary: 'string',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
defaultValue: { summary: '' },
|
|
20
|
+
},
|
|
21
|
+
hasHiddenLabel: {
|
|
22
|
+
control: 'boolean',
|
|
23
|
+
description: 'Toggles the visibility of the label',
|
|
24
|
+
table: {
|
|
25
|
+
category: 'Props',
|
|
26
|
+
type: {
|
|
27
|
+
summary: 'boolean',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
defaultValue: { summary: 'false' },
|
|
31
|
+
},
|
|
32
|
+
label: {
|
|
33
|
+
control: 'text',
|
|
34
|
+
description: 'The label for the select component',
|
|
35
|
+
table: {
|
|
36
|
+
category: 'Props',
|
|
37
|
+
type: {
|
|
38
|
+
summary: 'string',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
defaultValue: { summary: '' },
|
|
42
|
+
},
|
|
9
43
|
options: {
|
|
10
44
|
control: 'object',
|
|
11
45
|
description: 'Options for the select component',
|
|
@@ -126,6 +160,9 @@ export const Default: Story = {
|
|
|
126
160
|
isSearchable: true,
|
|
127
161
|
isDisabled: false,
|
|
128
162
|
isLoading: false,
|
|
163
|
+
hasHiddenLabel: false,
|
|
164
|
+
label: 'Select an option...',
|
|
165
|
+
name: 'select',
|
|
129
166
|
},
|
|
130
167
|
decorators: [
|
|
131
168
|
(Story) => (
|
|
@@ -2,9 +2,13 @@ import React from 'react';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import ReactSelect, { Props as ReactSelectProps, components, OptionProps } from 'react-select';
|
|
4
4
|
import { SelectOption } from './types';
|
|
5
|
+
import { withLabel } from '../subcomponents/Label';
|
|
5
6
|
|
|
6
7
|
export interface SelectProps<OptionType extends SelectOption> extends ReactSelectProps<OptionType> {
|
|
7
8
|
options: OptionType[];
|
|
9
|
+
label?: string;
|
|
10
|
+
name?: string;
|
|
11
|
+
hasHiddenLabel?: boolean;
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
const OptionComponent = <OptionType extends SelectOption>({
|
|
@@ -20,10 +24,13 @@ const OptionComponent = <OptionType extends SelectOption>({
|
|
|
20
24
|
);
|
|
21
25
|
};
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
const Select = <OptionType extends SelectOption>({
|
|
24
28
|
classNamePrefix = 'select',
|
|
25
29
|
className,
|
|
26
30
|
components: customComponents,
|
|
31
|
+
label,
|
|
32
|
+
hasHiddenLabel,
|
|
33
|
+
name,
|
|
27
34
|
...props
|
|
28
35
|
}: SelectProps<OptionType>) => {
|
|
29
36
|
const defaultComponents = {
|
|
@@ -41,3 +48,7 @@ export const Select = <OptionType extends SelectOption>({
|
|
|
41
48
|
/>
|
|
42
49
|
);
|
|
43
50
|
};
|
|
51
|
+
|
|
52
|
+
const LabeledSelect = withLabel(Select);
|
|
53
|
+
|
|
54
|
+
export { LabeledSelect as Select };
|