@agregio-solutions/design-system 1.95.1 → 1.96.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.
@@ -480,6 +480,31 @@ export const ExampleWithLinks: StoryObj<typeof Combobox> = {
480
480
  },
481
481
  };
482
482
 
483
+ export const ShouldRenderALinkItemWithATarget: StoryObj<typeof Combobox> = {
484
+ args: {
485
+ ...Playground.args,
486
+ defaultItems: [
487
+ { text: "Option 1", id: "1" },
488
+ {
489
+ text: "Google",
490
+ id: "google",
491
+ href: "https://google.com",
492
+ target: "_blank",
493
+ },
494
+ ],
495
+ },
496
+ play: async ({ canvasElement }) => {
497
+ const canvas = within(canvasElement);
498
+ const user = userEvent.setup({ delay: 50 });
499
+ await user.type(canvas.getByLabelText("[Insert label]"), "Goo");
500
+ const link = (
501
+ await screen.findByText("Google", { selector: "span" })
502
+ ).closest("a");
503
+ await expect(link).toHaveAttribute("href", "https://google.com");
504
+ await expect(link).toHaveAttribute("target", "_blank");
505
+ },
506
+ };
507
+
483
508
  export const ExampleWithCustomFiltering: StoryObj<typeof Combobox> = {
484
509
  render: () => {
485
510
  const options = [
@@ -7,6 +7,9 @@ export type Props = {
7
7
  iconLeft?: IconName;
8
8
  /**
9
9
  * Optional text content for the header. Can also be a React component.
10
+ * Rendered inside the sort button: it must not contain interactive elements
11
+ * (button, link, input), which would be invalid HTML and would trigger the sort
12
+ * on click.
10
13
  */
11
14
  text?: React.ReactNode;
12
15
  /**
@@ -14,7 +17,7 @@ export type Props = {
14
17
  */
15
18
  sortDirection?: "asc" | "desc" | "none";
16
19
  /**
17
- * Callback fired when the sort icon is clicked. If not provided, the sort icon will not be displayed.
20
+ * Callback fired when the header cell is clicked. If not provided, the header is not sortable and the sort icon is not displayed.
18
21
  */
19
22
  onSortClick?: (event?: unknown) => void;
20
23
  /**
@@ -500,7 +500,7 @@ Read [the React Aria blog post](https://react-spectrum.adobe.com/blog/date-and-t
500
500
  ## Value
501
501
 
502
502
  A `DatePicker` displays a placeholder by default. An initial, uncontrolled value can be provided to the `DatePicker` using the `defaultValue` prop.
503
- Alternatively, a controlled value can be provided using the `value` and `onchange` props.
503
+ Alternatively, a controlled value can be provided using the `value` and `onChange` props.
504
504
 
505
505
  Date values are provided as string.
506
506
  This component handles correct international date manipulation across calendars, time zones, and other localization concerns.
@@ -547,7 +547,7 @@ Read [the React Aria blog post](https://react-spectrum.adobe.com/blog/date-and-t
547
547
  ## Value
548
548
 
549
549
  A `DateRangePicker` displays a placeholder by default. An initial, uncontrolled value can be provided to the `DateRangePicker` using the `defaultValue` prop.
550
- Alternatively, a controlled value can be provided using the `value` and `onchange` props.
550
+ Alternatively, a controlled value can be provided using the `value` and `onChange` props.
551
551
 
552
552
  Here is the type for the `value` prop (also valid for `defaultValue`, `onChange`, etc.):
553
553
 
@@ -1,3 +1,4 @@
1
+ import { HTMLAttributeAnchorTarget } from 'react';
1
2
  import { IconName } from '../Icon/Icon';
2
3
  export type Props = {
3
4
  /**
@@ -25,6 +26,11 @@ export type Props = {
25
26
  * A URL to link
26
27
  */
27
28
  href?: string;
29
+ /**
30
+ * Only active with the `href` prop.
31
+ * Give a target attribute to use on the rendered anchor.
32
+ */
33
+ target?: HTMLAttributeAnchorTarget;
28
34
  /**
29
35
  * Only active with the `href` prop.
30
36
  * Router-specific options to pass to the `Link` component under the hood. (configured by the RouterProvider).
@@ -41,4 +47,4 @@ export type Props = {
41
47
  */
42
48
  selectionMode?: "single" | "multiple";
43
49
  };
44
- export default function SelectItem({ text, id, iconRight, iconLeft, isSelected, href, routerOptions, className, selectionMode, ...otherProps }: Props): import("react/jsx-runtime").JSX.Element;
50
+ export default function SelectItem({ text, id, iconRight, iconLeft, isSelected, href, target, routerOptions, className, selectionMode, ...otherProps }: Props): import("react/jsx-runtime").JSX.Element;
@@ -7,7 +7,7 @@ export type Props = Pick<LabelProps, "label" | "labelIconRight" | "labelIconRigh
7
7
  */
8
8
  id: string;
9
9
  /**
10
- * Actual date value of the TimeField, should be a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) time string.
10
+ * Actual time value of the TimeField, should be a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) time string.
11
11
  */
12
12
  value?: string | null;
13
13
  /**
@@ -26,11 +26,12 @@ export type Props = Pick<LabelProps, "label" | "labelIconRight" | "labelIconRigh
26
26
  */
27
27
  ampm?: boolean;
28
28
  /**
29
- * Determines the smallest unit that is displayed in the date picker. By default, this is "day" for dates, and "minute" for times.
29
+ * Determines the smallest unit that is displayed by the TimeField, and therefore which segments are editable.
30
+ * @default "minute"
30
31
  */
31
32
  granularity?: "hour" | "minute" | "second";
32
33
  /**
33
- * Whether to always show leading zeros in the month, day, and hour fields. By default, this is determined by the user's locale.
34
+ * Whether to always show leading zeros in the hour field. By default, this is determined by the user's locale.
34
35
  */
35
36
  shouldForceLeadingZeros?: boolean;
36
37
  /**
@@ -58,10 +59,10 @@ export type Props = Pick<LabelProps, "label" | "labelIconRight" | "labelIconRigh
58
59
  */
59
60
  style?: React.CSSProperties;
60
61
  /**
61
- * Specifies the nature of the Select (mainly to change the trigger border color and helperText color).
62
+ * Specifies the nature of the TimeField (mainly to change the input outline color and helperText color).
62
63
  * If you do not pass a nature prop, the component will automatically set the nature based on the presence of success/error messages.
63
64
  */
64
- nature?: "default" | "negative" | "positive";
65
+ nature?: "default" | "negative" | "positive" | "warning";
65
66
  /**
66
67
  * Props to pass to the wrapper div (for example, style or className).
67
68
  */
@@ -81,7 +82,7 @@ declare const TimeField: React.ForwardRefExoticComponent<Pick<LabelProps, "label
81
82
  */
82
83
  id: string;
83
84
  /**
84
- * Actual date value of the TimeField, should be a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) time string.
85
+ * Actual time value of the TimeField, should be a valid [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Times) time string.
85
86
  */
86
87
  value?: string | null;
87
88
  /**
@@ -100,11 +101,12 @@ declare const TimeField: React.ForwardRefExoticComponent<Pick<LabelProps, "label
100
101
  */
101
102
  ampm?: boolean;
102
103
  /**
103
- * Determines the smallest unit that is displayed in the date picker. By default, this is "day" for dates, and "minute" for times.
104
+ * Determines the smallest unit that is displayed by the TimeField, and therefore which segments are editable.
105
+ * @default "minute"
104
106
  */
105
107
  granularity?: "hour" | "minute" | "second";
106
108
  /**
107
- * Whether to always show leading zeros in the month, day, and hour fields. By default, this is determined by the user's locale.
109
+ * Whether to always show leading zeros in the hour field. By default, this is determined by the user's locale.
108
110
  */
109
111
  shouldForceLeadingZeros?: boolean;
110
112
  /**
@@ -132,10 +134,10 @@ declare const TimeField: React.ForwardRefExoticComponent<Pick<LabelProps, "label
132
134
  */
133
135
  style?: React.CSSProperties;
134
136
  /**
135
- * Specifies the nature of the Select (mainly to change the trigger border color and helperText color).
137
+ * Specifies the nature of the TimeField (mainly to change the input outline color and helperText color).
136
138
  * If you do not pass a nature prop, the component will automatically set the nature based on the presence of success/error messages.
137
139
  */
138
- nature?: "default" | "negative" | "positive";
140
+ nature?: "default" | "negative" | "positive" | "warning";
139
141
  /**
140
142
  * Props to pass to the wrapper div (for example, style or className).
141
143
  */
@@ -16,7 +16,7 @@ Base stories:
16
16
  import { Meta, StoryObj } from "@storybook/react-vite";
17
17
  import TimeField from "./TimeField";
18
18
  import { I18nProvider } from "react-aria-components";
19
- import { fn } from "storybook/test";
19
+ import { expect, fn, within } from "storybook/test";
20
20
 
21
21
  const meta: Meta<typeof TimeField> = {
22
22
  component: TimeField,
@@ -41,6 +41,12 @@ const meta: Meta<typeof TimeField> = {
41
41
  };
42
42
  export default meta;
43
43
 
44
+ const getRoot = (canvasElement: HTMLElement) =>
45
+ canvasElement.querySelector('[data-design-system-component="TimeField"]');
46
+
47
+ const getInput = (canvasElement: HTMLElement) =>
48
+ canvasElement.querySelector("[data-nature]");
49
+
44
50
  export const Playground: StoryObj<typeof TimeField> = {
45
51
  args: {
46
52
  label: "Time Field",
@@ -50,6 +56,14 @@ export const Playground: StoryObj<typeof TimeField> = {
50
56
  labelIconRight: "help_outline",
51
57
  labelIconRightTooltip: "Additional information",
52
58
  },
59
+ play: async ({ canvasElement }) => {
60
+ const canvas = within(canvasElement);
61
+ await expect(canvas.getByText("Time Field")).toBeVisible();
62
+ await expect(getInput(canvasElement)).toHaveAttribute(
63
+ "data-nature",
64
+ "default",
65
+ );
66
+ },
53
67
  };
54
68
 
55
69
  export const Empty: StoryObj<typeof TimeField> = {
@@ -57,6 +71,13 @@ export const Empty: StoryObj<typeof TimeField> = {
57
71
  ...Playground.args,
58
72
  defaultValue: undefined,
59
73
  },
74
+ play: async ({ canvasElement }) => {
75
+ const canvas = within(canvasElement);
76
+ await expect(canvas.getByLabelText("hour, Time Field")).toHaveAttribute(
77
+ "data-placeholder",
78
+ "true",
79
+ );
80
+ },
60
81
  };
61
82
 
62
83
  export const OnlyHour: StoryObj<typeof TimeField> = {
@@ -65,6 +86,15 @@ export const OnlyHour: StoryObj<typeof TimeField> = {
65
86
  defaultValue: "12",
66
87
  granularity: "hour",
67
88
  },
89
+ play: async ({ canvasElement }) => {
90
+ const canvas = within(canvasElement);
91
+ await expect(canvas.getByLabelText("hour, Time Field")).toHaveTextContent(
92
+ "12",
93
+ );
94
+ await expect(
95
+ canvas.queryByLabelText("minute, Time Field"),
96
+ ).not.toBeInTheDocument();
97
+ },
68
98
  };
69
99
 
70
100
  export const HourMinute: StoryObj<typeof TimeField> = {
@@ -73,6 +103,18 @@ export const HourMinute: StoryObj<typeof TimeField> = {
73
103
  defaultValue: "12:34",
74
104
  granularity: "minute",
75
105
  },
106
+ play: async ({ canvasElement }) => {
107
+ const canvas = within(canvasElement);
108
+ await expect(canvas.getByLabelText("hour, Time Field")).toHaveTextContent(
109
+ "12",
110
+ );
111
+ await expect(canvas.getByLabelText("minute, Time Field")).toHaveTextContent(
112
+ "34",
113
+ );
114
+ await expect(
115
+ canvas.queryByLabelText("second, Time Field"),
116
+ ).not.toBeInTheDocument();
117
+ },
76
118
  };
77
119
 
78
120
  export const HourMinuteSecond: StoryObj<typeof TimeField> = {
@@ -81,6 +123,12 @@ export const HourMinuteSecond: StoryObj<typeof TimeField> = {
81
123
  defaultValue: "12:34:56",
82
124
  granularity: "second",
83
125
  },
126
+ play: async ({ canvasElement }) => {
127
+ const canvas = within(canvasElement);
128
+ await expect(canvas.getByLabelText("second, Time Field")).toHaveTextContent(
129
+ "56",
130
+ );
131
+ },
84
132
  };
85
133
 
86
134
  export const LocaleFR: StoryObj<typeof TimeField> = {
@@ -90,6 +138,9 @@ export const LocaleFR: StoryObj<typeof TimeField> = {
90
138
  args: {
91
139
  ...HourMinuteSecond.args,
92
140
  },
141
+ play: async ({ canvasElement }) => {
142
+ await expect(getInput(canvasElement)).toHaveTextContent("12:34:56");
143
+ },
93
144
  };
94
145
 
95
146
  export const Disabled: StoryObj<typeof TimeField> = {
@@ -97,6 +148,12 @@ export const Disabled: StoryObj<typeof TimeField> = {
97
148
  ...Playground.args,
98
149
  isDisabled: true,
99
150
  },
151
+ play: async ({ canvasElement }) => {
152
+ await expect(getInput(canvasElement)).toHaveAttribute(
153
+ "aria-disabled",
154
+ "true",
155
+ );
156
+ },
100
157
  };
101
158
 
102
159
  export const WithError: StoryObj<typeof TimeField> = {
@@ -106,6 +163,14 @@ export const WithError: StoryObj<typeof TimeField> = {
106
163
  errorHelperText: "Error message",
107
164
  errorHelperTextIcon: "error_outline",
108
165
  },
166
+ play: async ({ canvasElement }) => {
167
+ const canvas = within(canvasElement);
168
+ await expect(canvas.getByText("Error message")).toBeVisible();
169
+ await expect(getInput(canvasElement)).toHaveAttribute(
170
+ "data-nature",
171
+ "negative",
172
+ );
173
+ },
109
174
  };
110
175
 
111
176
  export const WithSuccess: StoryObj<typeof TimeField> = {
@@ -115,6 +180,14 @@ export const WithSuccess: StoryObj<typeof TimeField> = {
115
180
  successHelperText: "Success message",
116
181
  successHelperTextIcon: "check",
117
182
  },
183
+ play: async ({ canvasElement }) => {
184
+ const canvas = within(canvasElement);
185
+ await expect(canvas.getByText("Success message")).toBeVisible();
186
+ await expect(getInput(canvasElement)).toHaveAttribute(
187
+ "data-nature",
188
+ "positive",
189
+ );
190
+ },
118
191
  };
119
192
 
120
193
  export const WithWarning: StoryObj<typeof TimeField> = {
@@ -124,6 +197,14 @@ export const WithWarning: StoryObj<typeof TimeField> = {
124
197
  warningHelperText: "Warning message",
125
198
  warningHelperTextIcon: "warning_amber",
126
199
  },
200
+ play: async ({ canvasElement }) => {
201
+ const canvas = within(canvasElement);
202
+ await expect(canvas.getByText("Warning message")).toBeVisible();
203
+ await expect(getInput(canvasElement)).toHaveAttribute(
204
+ "data-nature",
205
+ "warning",
206
+ );
207
+ },
127
208
  };
128
209
 
129
210
  export const WithHorizontalOrientation: StoryObj<typeof TimeField> = {
@@ -131,6 +212,11 @@ export const WithHorizontalOrientation: StoryObj<typeof TimeField> = {
131
212
  ...Playground.args,
132
213
  orientation: "horizontal",
133
214
  },
215
+ play: async ({ canvasElement }) => {
216
+ await expect(
217
+ canvasElement.querySelector("[data-orientation]"),
218
+ ).toHaveAttribute("data-orientation", "horizontal");
219
+ },
134
220
  };
135
221
 
136
222
  export const FullWidth: StoryObj<typeof TimeField> = {
@@ -141,6 +227,12 @@ export const FullWidth: StoryObj<typeof TimeField> = {
141
227
  ...Playground.args,
142
228
  fullWidth: true,
143
229
  },
230
+ play: async ({ canvasElement }) => {
231
+ await expect(getRoot(canvasElement)).toHaveAttribute(
232
+ "data-fullwidth",
233
+ "true",
234
+ );
235
+ },
144
236
  };
145
237
  ```
146
238
 
@@ -242,23 +334,23 @@ export const ControlledShouldSelectAValue: StoryObj<typeof TimeField> = {
242
334
  export const ExampleGranularity: StoryObj<typeof TimeField> = {
243
335
  render: () => {
244
336
  function Example() {
245
- const [time, setDate] = useState("12:34");
337
+ const [time, setTime] = useState("12:34");
246
338
 
247
339
  return (
248
340
  <>
249
341
  <TimeField
250
- id="time-and-time"
251
- label="Date and time"
342
+ id="granularity-second"
343
+ label="Second granularity"
252
344
  granularity="second"
253
345
  value={time}
254
- onChange={setDate}
346
+ onChange={setTime}
255
347
  />
256
348
  <TimeField
257
- id="time"
258
- label="Date"
349
+ id="granularity-hour"
350
+ label="Hour granularity"
259
351
  granularity="hour"
260
352
  value={time}
261
- onChange={setDate}
353
+ onChange={setTime}
262
354
  />
263
355
  </>
264
356
  );
@@ -324,16 +416,24 @@ Read [the React Aria blog post](https://react-spectrum.adobe.com/blog/date-and-t
324
416
  ## Value
325
417
 
326
418
  A `TimeField` displays a placeholder by default. An initial, uncontrolled value can be provided to the `TimeField` using the `defaultValue` prop.
327
- Alternatively, a controlled value can be provided using the `value` and `onchange` props.
419
+ Alternatively, a controlled value can be provided using the `value` and `onChange` props.
328
420
 
329
421
  Time values are provided as string.
330
- This component handles correct international time manipulation across time zones and other localization concerns.
331
- TimeField supports values of the following string formats:
422
+ This component handles correct international time manipulation: hour cycle, locale-specific formatting and other localization concerns.
423
+ Values carry no date and no time zone — a `TimeField` holds a plain time of day.
424
+ TimeField accepts values in the following string formats:
425
+
426
+ - `hh`
427
+ - `hh:mm`
428
+ - `hh:mm:ss`
429
+ - `hh:mm:ss.sss`
430
+
431
+ Every format is parsed into a complete time, with the missing units defaulting to zero — `"12"` and `"12:00:00"` are therefore equivalent values.
432
+
433
+ The value format does **not** control what is rendered: the units displayed are decided by the `granularity` prop (see below).
434
+ For example, `value="12:34:56"` with the default `"minute"` granularity displays `12:34`; pass `granularity="second"` to also show the seconds.
332
435
 
333
- - `hh` -> only the hour is displayed
334
- - `hh:mm` -> only the hour and minute are displayed
335
- - `hh:mm:ss` -> only the hour, minute and second are displayed
336
- - `hh:mm:ss.sss` -> the hour, minute, second and millisecond are displayed (millisecond are not selectable by the user and will not change when the rest of the time is changed)
436
+ Milliseconds are preserved in the value but never displayed, and they are not editable by the user: they will not change when the rest of the time is changed.
337
437
 
338
438
  ## Granularity
339
439
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agregio-solutions/design-system",
3
- "version": "1.95.1",
3
+ "version": "1.96.0",
4
4
  "description": "React Component library and Storybook that is part of the Design System for Agregio Solutions",
5
5
  "type": "module",
6
6
  "module": "dist/design-system.js",
@@ -28,7 +28,6 @@
28
28
  "semantic-release": "semantic-release",
29
29
  "prettier:check": "prettier . --check --ignore-path .gitignore",
30
30
  "prettier:write": "prettier . --write --ignore-path .gitignore",
31
- "repomix": "repomix",
32
31
  "storybook": "storybook dev -p 6006",
33
32
  "storybook:test": "vitest run --project storybook",
34
33
  "storybook:test:llm": "DEBUG_PRINT_LIMIT=0 vitest run --project=storybook --reporter=dot --silent --changed --passWithNoTests",
@@ -80,7 +79,6 @@
80
79
  "react-router-dom": "7.15.1",
81
80
  "recharts": "3.8.1",
82
81
  "remark-gfm": "4.0.1",
83
- "repomix": "1.14.0",
84
82
  "semantic-release": "25.0.3",
85
83
  "storybook": "10.4.0",
86
84
  "typescript-eslint": "8.59.3",