@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indico-data/design-system",
3
- "version": "2.60.8",
3
+ "version": "2.60.10",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "main": "lib/index.js",
@@ -89,7 +89,7 @@ const meta: Meta<typeof InputDateRangePicker> = {
89
89
  },
90
90
  },
91
91
  isOpen: {
92
- control: false,
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
- return <InputDateRangePicker {...args} selected={selected} onSelect={handleSelect} />;
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={'From Date'}
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={'To Date'}
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
- export const Select = <OptionType extends SelectOption>({
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 };
@@ -1,7 +1,7 @@
1
1
  import React, { forwardRef } from 'react';
2
2
 
3
3
  export interface LabelProps {
4
- label: string;
4
+ label?: string;
5
5
  name: string;
6
6
  isRequired?: boolean;
7
7
  hasHiddenLabel?: boolean;
package/src/index.ts CHANGED
@@ -47,3 +47,5 @@ export type {
47
47
  Row as TanstackTableRowType,
48
48
  Table as TanstackTableType,
49
49
  } from '@tanstack/react-table';
50
+ export type { DateRange } from 'react-day-picker';
51
+ export type { SelectOption } from './components/forms/select/types';