@ultraviolet/ui 1.43.2 → 1.45.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.
package/dist/index.d.ts CHANGED
@@ -1682,13 +1682,14 @@ type ExpandableProps = {
1682
1682
  minHeight?: number;
1683
1683
  className?: string;
1684
1684
  'data-testid'?: string;
1685
+ animationDuration?: number;
1685
1686
  };
1686
1687
  /**
1687
1688
  * The Expandable component is a dynamic React component that allows for the expansion of its children content
1688
1689
  * based on its height. The component comes with a sleek and smooth animation, providing a visually pleasing
1689
1690
  * user experience.
1690
1691
  */
1691
- declare const Expandable: ({ children, opened, minHeight, className, "data-testid": dataTestId, }: ExpandableProps) => _emotion_react_jsx_runtime.JSX.Element;
1692
+ declare const Expandable: ({ children, opened, minHeight, className, "data-testid": dataTestId, animationDuration, }: ExpandableProps) => _emotion_react_jsx_runtime.JSX.Element;
1692
1693
 
1693
1694
  type Transformer = (value: DatumValue) => string;
1694
1695
  type CustomLegendProps = {
@@ -1996,10 +1997,10 @@ type NoticeProps = {
1996
1997
  */
1997
1998
  declare const Notice: ({ children, className, "data-testid": dataTestId, }: NoticeProps) => _emotion_react_jsx_runtime.JSX.Element;
1998
1999
 
1999
- type CheckboxGroupCheckboxProps = Omit<ComponentProps<typeof Checkbox>, 'onChange' | 'checked' | 'required'> & {
2000
+ type CheckboxGroupCheckboxProps = Omit<ComponentProps<typeof Checkbox>, 'onChange' | 'checked'> & {
2000
2001
  value: string;
2001
2002
  };
2002
- declare const CheckboxGroupCheckbox: ({ onFocus, onBlur, disabled, error, name, value, children, helper, className, autoFocus, "data-testid": dataTestId, }: CheckboxGroupCheckboxProps) => _emotion_react_jsx_runtime.JSX.Element;
2003
+ declare const CheckboxGroupCheckbox: ({ onFocus, onBlur, disabled, error, name, value, children, helper, className, autoFocus, "data-testid": dataTestId, required, }: CheckboxGroupCheckboxProps) => _emotion_react_jsx_runtime.JSX.Element;
2003
2004
  type CheckboxGroupProps = {
2004
2005
  legend: string;
2005
2006
  value?: string[];
@@ -2015,7 +2016,7 @@ type CheckboxGroupProps = {
2015
2016
  */
2016
2017
  declare const CheckboxGroup: {
2017
2018
  ({ legend, value, className, helper, error, direction, children, onChange, name, required, }: CheckboxGroupProps): _emotion_react_jsx_runtime.JSX.Element;
2018
- Checkbox: ({ onFocus, onBlur, disabled, error, name, value, children, helper, className, autoFocus, "data-testid": dataTestId, }: CheckboxGroupCheckboxProps) => _emotion_react_jsx_runtime.JSX.Element;
2019
+ Checkbox: ({ onFocus, onBlur, disabled, error, name, value, children, helper, className, autoFocus, "data-testid": dataTestId, required, }: CheckboxGroupCheckboxProps) => _emotion_react_jsx_runtime.JSX.Element;
2019
2020
  };
2020
2021
 
2021
2022
  declare const containerSizes: {
@@ -2505,13 +2506,15 @@ type SkeletonProps = {
2505
2506
  length?: number;
2506
2507
  col?: number;
2507
2508
  className?: string;
2509
+ 'aria-label'?: string;
2510
+ 'data-testid'?: string;
2508
2511
  };
2509
2512
  /**
2510
2513
  * Skeleton component is used to indicate that the data is loading.
2511
2514
  * It is used to provide a better user experience by showing a temporary placeholder reflecting the dimensions of the
2512
2515
  * content that will eventually be loaded on the screen.
2513
2516
  */
2514
- declare const Skeleton: ({ variant, length, col, className, }: SkeletonProps) => _emotion_react_jsx_runtime.JSX.Element;
2517
+ declare const Skeleton: ({ variant, length, col, className, "aria-label": ariaLabel, "data-testid": dataTestId, }: SkeletonProps) => _emotion_react_jsx_runtime.JSX.Element;
2515
2518
 
2516
2519
  type Prefixes = 'lines' | 'command';
2517
2520
  type SnippetProps = {
@@ -4,14 +4,15 @@ import { jsx } from '@emotion/react/jsx-runtime';
4
4
 
5
5
  const formatTextToAvatar = text => {
6
6
  if (!text) return '';
7
- if (text.length <= 2) {
8
- return text.toUpperCase();
7
+ const textCleaned = text.replace(/\s+/g, ' ').trim();
8
+ if (textCleaned.length <= 2) {
9
+ return textCleaned.toUpperCase();
9
10
  }
10
- if (text.split(' ').length > 1) {
11
- const [a, b] = text.split(' ');
11
+ if (textCleaned.split(' ').length > 1) {
12
+ const [a, b] = textCleaned.split(' ');
12
13
  return `${a[0]}${b[0]}`.toUpperCase();
13
14
  }
14
- return text.substring(0, 2).toUpperCase();
15
+ return textCleaned.substring(0, 2).toUpperCase();
15
16
  };
16
17
  const StyledTextAvatar = /*#__PURE__*/_styled("span", {
17
18
  target: "ec0473m1"
@@ -8,6 +8,16 @@ import { jsx, jsxs } from '@emotion/react/jsx-runtime';
8
8
 
9
9
  function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
10
10
  const CheckboxGroupContext = /*#__PURE__*/createContext(undefined);
11
+ const StyledCheckbox = /*#__PURE__*/_styled(Checkbox, {
12
+ target: "e1k5uyng2"
13
+ })(process.env.NODE_ENV === "production" ? {
14
+ name: "6vgcqf",
15
+ styles: "label{width:fit-content;}"
16
+ } : {
17
+ name: "6vgcqf",
18
+ styles: "label{width:fit-content;}",
19
+ toString: _EMOTION_STRINGIFIED_CSS_ERROR__
20
+ });
11
21
  const CheckboxGroupCheckbox = ({
12
22
  onFocus,
13
23
  onBlur,
@@ -19,7 +29,8 @@ const CheckboxGroupCheckbox = ({
19
29
  helper,
20
30
  className,
21
31
  autoFocus,
22
- 'data-testid': dataTestId
32
+ 'data-testid': dataTestId,
33
+ required
23
34
  }) => {
24
35
  const context = useContext(CheckboxGroupContext);
25
36
  if (!context) {
@@ -32,7 +43,7 @@ const CheckboxGroupCheckbox = ({
32
43
  } = context;
33
44
  const checkboxName = `${groupName}.${name ?? ''}`;
34
45
  const checkboxValue = `${value}`;
35
- return jsx(Checkbox, {
46
+ return jsx(StyledCheckbox, {
36
47
  onChange: onChange,
37
48
  checked: groupValues?.includes(checkboxValue),
38
49
  onFocus: onFocus,
@@ -45,6 +56,7 @@ const CheckboxGroupCheckbox = ({
45
56
  className: className,
46
57
  autoFocus: autoFocus,
47
58
  "data-testid": dataTestId,
59
+ required: required,
48
60
  children: children
49
61
  });
50
62
  };
@@ -86,8 +98,9 @@ const CheckboxGroup = ({
86
98
  const contextValue = useMemo(() => ({
87
99
  groupName: name,
88
100
  groupValues: value ?? [],
89
- onChange
90
- }), [name, value, onChange]);
101
+ onChange,
102
+ required
103
+ }), [name, value, onChange, required]);
91
104
  return jsx(CheckboxGroupContext.Provider, {
92
105
  value: contextValue,
93
106
  children: jsxs(Stack, {
@@ -5,9 +5,13 @@ import { jsx } from '@emotion/react/jsx-runtime';
5
5
  const ANIMATION_DURATION = 300; // in ms
6
6
 
7
7
  const StyledExpandable = /*#__PURE__*/_styled('div', {
8
- shouldForwardProp: prop => !['opened', 'minHeight'].includes(prop),
8
+ shouldForwardProp: prop => !['opened', 'minHeight', 'animationDuration'].includes(prop),
9
9
  target: "e5hc7t70"
10
- })("transition:max-height ", ANIMATION_DURATION, "ms ease-out,opacity ", ANIMATION_DURATION, "ms ease-out;overflow:", ({
10
+ })("transition:max-height ", ({
11
+ animationDuration
12
+ }) => animationDuration, "ms ease-out,opacity ", ({
13
+ animationDuration
14
+ }) => animationDuration, "ms ease-out;overflow:", ({
11
15
  opened
12
16
  }) => opened ? 'visible' : 'hidden', ";height:auto;max-height:", ({
13
17
  opened,
@@ -24,7 +28,8 @@ const Expandable = ({
24
28
  opened,
25
29
  minHeight = 0,
26
30
  className,
27
- 'data-testid': dataTestId
31
+ 'data-testid': dataTestId,
32
+ animationDuration = ANIMATION_DURATION
28
33
  }) => {
29
34
  const [height, setHeight] = useState(null);
30
35
  const transitionTimer = useRef();
@@ -76,6 +81,7 @@ const Expandable = ({
76
81
  className: className,
77
82
  opened: opened,
78
83
  minHeight: minHeight,
84
+ animationDuration: animationDuration,
79
85
  children: children
80
86
  });
81
87
  };
@@ -9,7 +9,6 @@ import { Tooltip } from '../Tooltip/index.js';
9
9
  import { jsxs, jsx } from '@emotion/react/jsx-runtime';
10
10
 
11
11
  function _EMOTION_STRINGIFIED_CSS_ERROR__() { return "You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."; }
12
- const NUMBER_INPUT_MAX_STR_LENGTH = /*#__PURE__*/Number.MAX_SAFE_INTEGER.toString().length;
13
12
  const SIZES = {
14
13
  small: '30px',
15
14
  medium: '38px',
@@ -139,27 +138,6 @@ const NumberInputV2 = /*#__PURE__*/forwardRef(({
139
138
  }
140
139
  onChange?.(parseInt(localRef.current?.value ?? '', 10) ?? min);
141
140
  }, [localRef, min, onChange]);
142
- const onChangeValue = inputStr => {
143
- if (onChange) {
144
- let numericValue;
145
- if (inputStr.length > NUMBER_INPUT_MAX_STR_LENGTH && inputStr.startsWith('-')) {
146
- numericValue = min;
147
- } else if (inputStr.length > NUMBER_INPUT_MAX_STR_LENGTH) {
148
- numericValue = max;
149
- } else {
150
- numericValue = parseInt(inputStr, 10);
151
- if (Number.isNaN(numericValue) || numericValue < min) {
152
- numericValue = min;
153
- } else if (numericValue > max) {
154
- numericValue = max;
155
- }
156
- }
157
- onChange(numericValue);
158
- if (localRef.current) {
159
- localRef.current.value = numericValue.toString();
160
- }
161
- }
162
- };
163
141
  const isMinusDisabled = useMemo(() => {
164
142
  if (!localRef?.current?.value || localRef?.current?.value === '') {
165
143
  return false;
@@ -191,6 +169,10 @@ const NumberInputV2 = /*#__PURE__*/forwardRef(({
191
169
  }
192
170
  return 'neutral';
193
171
  }, [error, success]);
172
+ let inputValue;
173
+ if (value !== undefined) {
174
+ inputValue = value !== null && Number.isInteger(value) ? value.toString() : '';
175
+ }
194
176
  return jsxs(Stack, {
195
177
  gap: "0.5",
196
178
  className: className,
@@ -246,28 +228,13 @@ const NumberInputV2 = /*#__PURE__*/forwardRef(({
246
228
  name: name,
247
229
  id: localId,
248
230
  placeholder: placeholder,
249
- onKeyDown: event => {
250
- if (event.key === 'Enter') {
251
- if (!localRef.current?.value) {
252
- onChange?.(null);
253
- } else if (onChange) {
254
- onChangeValue(localRef.current?.value ?? '');
255
- }
256
- }
257
- },
258
- onBlur: event => {
259
- if (event.target.value === '') {
260
- onBlur?.(event);
261
- onChange?.(null);
262
- return;
263
- }
264
- if (onChange) {
265
- onChangeValue(event.target.value);
266
- }
267
- onBlur?.(event);
268
- },
269
- defaultValue: value?.toString(),
231
+ onChange: onChange ? event => {
232
+ const newNumber = parseInt(event.target.value, 10);
233
+ onChange(Number.isNaN(newNumber) ? null : newNumber);
234
+ } : undefined,
235
+ value: inputValue,
270
236
  onFocus: onFocus,
237
+ onBlur: onBlur,
271
238
  "data-size": size,
272
239
  step: step,
273
240
  disabled: disabled,
@@ -2,7 +2,6 @@ import _styled from '@emotion/styled/base';
2
2
  import { useTheme, css } from '@emotion/react';
3
3
  import { Icon } from '@ultraviolet/icons';
4
4
  import { forwardRef, useState, useId, useMemo, useEffect } from 'react';
5
- import flattenChildren from 'react-flatten-children';
6
5
  import Select, { components } from 'react-select';
7
6
  import isJSONString from '../../helpers/isJSON.js';
8
7
  import * as animations from '../../utils/animations.js';
@@ -531,7 +530,7 @@ const FwdSelectInput = ({
531
530
  const currentValue = value?.value;
532
531
 
533
532
  // Options need to keep the same reference otherwise react-select doesn't focus the selected option
534
- const selectOptions = useMemo(() => options || flattenChildren(children).map(({
533
+ const selectOptions = useMemo(() => options || (children ?? []).map(({
535
534
  props: {
536
535
  children: label,
537
536
  ...subProps
@@ -105,7 +105,7 @@ const SelectableCardGroup = ({
105
105
  className: className,
106
106
  children: jsxs(Stack, {
107
107
  gap: 1.5,
108
- children: [jsxs(Text, {
108
+ children: [legend ? jsxs(Text, {
109
109
  as: "legend",
110
110
  variant: "bodyStrong",
111
111
  children: [legend && jsxs(Fragment, {
@@ -115,7 +115,7 @@ const SelectableCardGroup = ({
115
115
  color: "danger",
116
116
  size: 8
117
117
  }) : null]
118
- }), jsx(Row, {
118
+ }) : null, jsx(Row, {
119
119
  gap: 2,
120
120
  templateColumns: `repeat(${columns}, auto)`,
121
121
  children: children
@@ -13,7 +13,7 @@ const StyledIcon = /*#__PURE__*/_styled(Icon, {
13
13
  })("fill:", ({
14
14
  color,
15
15
  theme
16
- }) => theme.colors[color].border, ";");
16
+ }) => theme.colors[color].borderWeak, ";");
17
17
  const StyledHr = /*#__PURE__*/_styled('hr', {
18
18
  shouldForwardProp: prop => !['direction', 'thickness', 'color', 'hasIcon'].includes(prop),
19
19
  target: "e1d1zom90"
@@ -26,7 +26,7 @@ const StyledHr = /*#__PURE__*/_styled('hr', {
26
26
  }) => direction === 'horizontal' ? `${thickness}px` : 'auto', ";flex-shrink:0;background-color:", ({
27
27
  theme,
28
28
  color
29
- }) => theme.colors[color].border, ";", ({
29
+ }) => theme.colors[color].borderWeak, ";", ({
30
30
  hasIcon
31
31
  }) => hasIcon && `flex: 1;`, ";");
32
32
  /**
@@ -61,13 +61,17 @@ const Skeleton = ({
61
61
  variant = 'blocks',
62
62
  length,
63
63
  col,
64
- className
64
+ className,
65
+ 'aria-label': ariaLabel,
66
+ 'data-testid': dataTestId
65
67
  }) => {
66
68
  const Component = variants[variant];
67
69
  return jsxs(StyledContainer, {
68
70
  className: className,
69
71
  "aria-busy": true,
70
72
  "aria-live": "polite",
73
+ "aria-label": ariaLabel,
74
+ "data-testid": dataTestId,
71
75
  children: [jsx(Component, {
72
76
  length: length,
73
77
  col: col
@@ -1,7 +1,6 @@
1
1
  import _styled from '@emotion/styled/base';
2
2
  import { keyframes, css } from '@emotion/react';
3
3
  import { Children, Fragment } from 'react';
4
- import flattenChildren from 'react-flatten-children';
5
4
  import { Bullet } from '../Bullet/index.js';
6
5
  import { Text } from '../Text/index.js';
7
6
  import { jsx, jsxs } from '@emotion/react/jsx-runtime';
@@ -121,7 +120,7 @@ const Stepper = ({
121
120
  "data-testid": dataTestId,
122
121
  labelPosition: labelPosition,
123
122
  size: size,
124
- children: flattenChildren(children).map((child, index) => {
123
+ children: Children.map(children, (child, index) => {
125
124
  const getTemporal = () => {
126
125
  if (selected > index) return 'previous';
127
126
  if (selected === index) return 'current';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraviolet/ui",
3
- "version": "1.43.2",
3
+ "version": "1.45.0",
4
4
  "description": "Ultraviolet UI",
5
5
  "homepage": "https://github.com/scaleway/ultraviolet#readme",
6
6
  "repository": {
@@ -39,13 +39,13 @@
39
39
  "react-dom": "18.2.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@babel/core": "7.24.0",
42
+ "@babel/core": "7.24.3",
43
43
  "@emotion/babel-plugin": "11.11.0",
44
44
  "@emotion/react": "11.11.4",
45
45
  "@emotion/styled": "11.11.0",
46
- "@types/react": "18.2.61",
46
+ "@types/react": "18.2.64",
47
47
  "@types/react-datepicker": "4.19.6",
48
- "@types/react-dom": "18.2.19",
48
+ "@types/react-dom": "18.2.21",
49
49
  "react": "18.2.0",
50
50
  "react-dom": "18.2.0"
51
51
  },
@@ -56,18 +56,16 @@
56
56
  "@nivo/line": "0.80.0",
57
57
  "@nivo/pie": "0.80.0",
58
58
  "@nivo/scales": "0.80.0",
59
- "@nivo/tooltip": "0.80.0",
60
- "@scaleway/random-name": "4.0.3",
59
+ "@scaleway/random-name": "5.0.0",
61
60
  "@scaleway/use-media": "2.0.1",
62
61
  "deepmerge": "4.3.1",
63
62
  "react-datepicker": "4.25.0",
64
- "react-flatten-children": "1.1.2",
65
63
  "react-select": "5.8.0",
66
64
  "react-toastify": "10.0.5",
67
65
  "react-use-clipboard": "1.0.9",
68
66
  "reakit": "1.3.11",
69
67
  "@ultraviolet/themes": "1.9.0",
70
- "@ultraviolet/icons": "2.10.1"
68
+ "@ultraviolet/icons": "2.11.1"
71
69
  },
72
70
  "scripts": {
73
71
  "build": "rollup -c ../../rollup.config.mjs",