@ultraviolet/ui 1.16.0 → 1.18.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/README.md CHANGED
@@ -20,13 +20,13 @@ You will also need to import fonts in your project by adding:
20
20
  ### Usage
21
21
 
22
22
  ```js
23
- import { theme, normalize, Button } from '@ultraviolet/ui'
24
- import { Global, css, ThemeProvider } from '@emotion/react'
23
+ import { Global, ThemeProvider, css } from '@emotion/react'
24
+ import { Button, normalize, theme } from '@ultraviolet/ui'
25
25
 
26
26
  const App = () => (
27
27
  <ThemeProvider theme={theme}>
28
28
  <Global styles={css`${normalize()}`} />
29
- <Button variant="primary" onClick={() => console.log('clicked')}>
29
+ <Button onClick={() => console.log('clicked')}>
30
30
  Click Me
31
31
  </Button>
32
32
  </ThemeProvider>
@@ -42,10 +42,10 @@ Example, in a `emotion.d.ts` file:
42
42
 
43
43
  ```ts
44
44
  import '@emotion/react'
45
- import type { SCWUITheme } from '@ultraviolet/ui'
45
+ import type { UltravioletUITheme } from '@ultraviolet/ui'
46
46
 
47
47
  declare module '@emotion/react' {
48
- export interface Theme extends SCWUITheme {}
48
+ export interface Theme extends UltravioletUITheme {}
49
49
  }
50
50
  ```
51
51
 
package/dist/index.d.ts CHANGED
@@ -37,7 +37,11 @@ type ActionBarProps = {
37
37
  declare const ActionBar: ({ children, role, rank, className, "data-testid": dataTestId, }: ActionBarProps) => react.ReactPortal;
38
38
 
39
39
  type ScreenSize = keyof typeof consoleLightTheme.screens;
40
+ /**
41
+ * @deprecated use UltravioletUITheme instead
42
+ */
40
43
  type SCWUITheme = typeof consoleLightTheme;
44
+ type UltravioletUITheme = typeof consoleLightTheme;
41
45
  declare const typography: {
42
46
  body: {
43
47
  fontFamily: string;
@@ -177,10 +181,10 @@ type RecursivePartial<T> = {
177
181
  };
178
182
  /**
179
183
  * Will extend theme with new theme properties
180
- * @param {SCWUITheme} baseTheme the theme you want to extend from, by default it is set to light theme
181
- * @param {RecursivePartial<SCWUITheme>} extendedTheme the properties of a new theme you want to apply from baseTheme
184
+ * @param {UltravioletUITheme} baseTheme the theme you want to extend from, by default it is set to light theme
185
+ * @param {RecursivePartial<UltravioletUITheme>} extendedTheme the properties of a new theme you want to apply from baseTheme
182
186
  */
183
- declare const extendTheme: (extendedTheme: RecursivePartial<SCWUITheme>) => {
187
+ declare const extendTheme: (extendedTheme: RecursivePartial<UltravioletUITheme>) => {
184
188
  colors: {
185
189
  danger: {
186
190
  background: string;
@@ -803,6 +807,9 @@ type CommonProps = {
803
807
  onClick?: MouseEventHandler<HTMLElement>;
804
808
  tooltip?: string;
805
809
  tabIndex?: ButtonHTMLAttributes<HTMLButtonElement>['tabIndex'];
810
+ onMouseDown?: MouseEventHandler<HTMLElement>;
811
+ onMouseUp?: MouseEventHandler<HTMLElement>;
812
+ onMouseOut?: MouseEventHandler<HTMLElement>;
806
813
  };
807
814
  type FinalProps = CommonProps & ({
808
815
  children: ReactNode;
@@ -1762,6 +1769,8 @@ type PopupProps = {
1762
1769
  tabIndex?: number;
1763
1770
  onKeyDown?: KeyboardEventHandler;
1764
1771
  'aria-haspopup'?: HTMLAttributes<HTMLDivElement>['aria-haspopup'];
1772
+ hideOnClickOutside?: boolean;
1773
+ needDebounce?: boolean;
1765
1774
  };
1766
1775
  declare const Popup: react.ForwardRefExoticComponent<PopupProps & react.RefAttributes<HTMLDivElement>>;
1767
1776
 
@@ -1827,7 +1836,7 @@ type RowProps = {
1827
1836
  'data-testid'?: string;
1828
1837
  children: ReactNode;
1829
1838
  templateColumns: string;
1830
- gap?: keyof SCWUITheme['space'] | number;
1839
+ gap?: keyof UltravioletUITheme['space'] | number;
1831
1840
  alignItems?: CSSProperties['alignItems'];
1832
1841
  justifyContent?: CSSProperties['justifyContent'];
1833
1842
  };
@@ -1968,6 +1977,10 @@ declare const variants$1: {
1968
1977
  readonly slider: ({ length }: {
1969
1978
  length?: number | undefined;
1970
1979
  }) => _emotion_react_jsx_runtime.JSX.Element;
1980
+ readonly square: _emotion_styled.StyledComponent<{
1981
+ theme?: _emotion_react.Theme | undefined;
1982
+ as?: react.ElementType<any> | undefined;
1983
+ }, react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
1971
1984
  };
1972
1985
  type SkeletonVariant = keyof typeof variants$1;
1973
1986
  type SkeletonProps = {
@@ -2004,7 +2017,7 @@ type SnippetProps = {
2004
2017
  declare const Snippet: ({ children, copyText, copiedText, showText, hideText, prefix, className, "data-testid": dataTestId, }: SnippetProps) => _emotion_react_jsx_runtime.JSX.Element;
2005
2018
 
2006
2019
  type StackProps = {
2007
- gap?: keyof SCWUITheme['space'] | number;
2020
+ gap?: keyof UltravioletUITheme['space'] | number;
2008
2021
  direction?: 'row' | 'column';
2009
2022
  alignItems?: CSSProperties['alignItems'];
2010
2023
  justifyContent?: CSSProperties['justifyContent'];
@@ -2674,4 +2687,4 @@ declare const down: (size: ScreenSize, rules: string) => string;
2674
2687
 
2675
2688
  declare const normalize: () => string;
2676
2689
 
2677
- export { ActionBar, Alert, Avatar, Badge, Banner, BarChart, BarStack, Breadcrumbs, Breakpoint, Bullet, Button, Card, Carousel, Checkbox, CheckboxGroup, CheckboxGroupCheckbox, CopyButton, DateInput, EmptyState, Expandable, LineChart, Link, List, Loader, Menu, MenuV2, Meter, Modal, Notice, NumberInput, Pagination, PasswordCheck, PasswordStrengthMeter, PieChart, Popover, ProgressBar, Radio, RadioGroup, Row, type SCWUITheme, SelectInput, SelectableCard, Separator, Skeleton, Snippet, Stack, Status, StepList, Stepper, SwitchButton, Table, Tabs, Tag, TagInput, TagList, Text, TextInput, TimeInput, ToastContainer, Toggle, ToggleGroup, Tooltip, VerificationCode, bounce, down, extendTheme, fadeIn, fadeOut, flash, getUUID, normalize, ping, pulse, quickScaleDown, scaleBack, scaleDown, scaleForward, scaleUp, sketchIn, sketchOut, slideDownLarge, slideFromBottom, slideFromLeft, slideFromRight, slideFromTop, slideToBottom, slideToLeft, slideToRight, slideToTop, slideUpLarge, toast, unfoldIn, unfoldOut, up, zoomIn, zoomOut };
2690
+ export { ActionBar, Alert, Avatar, Badge, Banner, BarChart, BarStack, Breadcrumbs, Breakpoint, Bullet, Button, Card, Carousel, Checkbox, CheckboxGroup, CheckboxGroupCheckbox, CopyButton, DateInput, EmptyState, Expandable, LineChart, Link, List, Loader, Menu, MenuV2, Meter, Modal, Notice, NumberInput, Pagination, PasswordCheck, PasswordStrengthMeter, PieChart, Popover, ProgressBar, Radio, RadioGroup, Row, type SCWUITheme, SelectInput, SelectableCard, Separator, Skeleton, Snippet, Stack, Status, StepList, Stepper, SwitchButton, Table, Tabs, Tag, TagInput, TagList, Text, TextInput, TimeInput, ToastContainer, Toggle, ToggleGroup, Tooltip, type UltravioletUITheme, VerificationCode, bounce, down, extendTheme, fadeIn, fadeOut, flash, getUUID, normalize, ping, pulse, quickScaleDown, scaleBack, scaleDown, scaleForward, scaleUp, sketchIn, sketchOut, slideDownLarge, slideFromBottom, slideFromLeft, slideFromRight, slideFromTop, slideToBottom, slideToLeft, slideToRight, slideToTop, slideUpLarge, toast, unfoldIn, unfoldOut, up, zoomIn, zoomOut };
@@ -115,7 +115,7 @@ const Alert = _ref6 => {
115
115
  children: [title ? jsx(Text, {
116
116
  variant: "bodyStronger",
117
117
  as: "span",
118
- color: sentiment,
118
+ sentiment: sentiment,
119
119
  children: title
120
120
  }) : null, typeof children === 'string' ? jsx(Text, {
121
121
  variant: "body",
@@ -135,13 +135,13 @@ const Banner = _ref8 => {
135
135
  children: [jsx(Text, {
136
136
  as: "p",
137
137
  variant: size === 'medium' ? 'headingSmall' : 'bodyStronger',
138
- color: variant === 'promotional' && theme !== 'light' ? 'neutral' : 'primary',
138
+ sentiment: variant === 'promotional' && theme !== 'light' ? 'neutral' : 'primary',
139
139
  prominence: variant === 'intro' ? 'default' : 'strong',
140
140
  children: title
141
141
  }), jsx(Text, {
142
142
  as: "p",
143
143
  variant: "body",
144
- color: "neutral",
144
+ sentiment: "neutral",
145
145
  prominence: variant === 'intro' || variant === 'promotional' && theme !== 'light' ? 'default' : 'stronger',
146
146
  children: children
147
147
  })]
@@ -48,7 +48,7 @@ const BarChartToolTip = _ref5 => {
48
48
  children: [jsx(Text, {
49
49
  variant: "bodyStronger",
50
50
  as: "p",
51
- color: "primary",
51
+ sentiment: "primary",
52
52
  children: formattedValue
53
53
  }), jsx(Text, {
54
54
  variant: "bodySmall",
@@ -231,6 +231,9 @@ const Button = /*#__PURE__*/forwardRef((_ref10, ref) => {
231
231
  isLoading = false,
232
232
  children,
233
233
  onClick,
234
+ onMouseDown,
235
+ onMouseUp,
236
+ onMouseOut,
234
237
  name,
235
238
  'aria-label': ariaLabel,
236
239
  'aria-current': ariaCurrent,
@@ -289,6 +292,9 @@ const Button = /*#__PURE__*/forwardRef((_ref10, ref) => {
289
292
  iconOnly: !!icon && !children,
290
293
  tabIndex: tabIndex,
291
294
  autoFocus: autoFocus,
295
+ onMouseDown: onMouseDown,
296
+ onMouseUp: onMouseUp,
297
+ onMouseOut: onMouseOut,
292
298
  children: content
293
299
  })
294
300
  });
@@ -318,6 +324,9 @@ const Button = /*#__PURE__*/forwardRef((_ref10, ref) => {
318
324
  iconOnly: !!icon && !children,
319
325
  tabIndex: tabIndex,
320
326
  autoFocus: autoFocus,
327
+ onMouseDown: onMouseDown,
328
+ onMouseUp: onMouseUp,
329
+ onMouseOut: onMouseOut,
321
330
  children: content
322
331
  })
323
332
  });
@@ -41,10 +41,10 @@ const CheckboxIconContainer = _ref4 => {
41
41
  const theme = useTheme();
42
42
  return jsxs("g", {
43
43
  children: [jsx(InnerCheckbox, {
44
- x: "2",
45
- y: "2",
46
- width: "20",
47
- height: "20",
44
+ x: "4",
45
+ y: "4",
46
+ width: "16",
47
+ height: "16",
48
48
  rx: theme.radii.small,
49
49
  strokeWidth: "2"
50
50
  }), children]
@@ -129,11 +129,11 @@ const CheckboxInput = /*#__PURE__*/_styled('input', {
129
129
  theme
130
130
  } = _ref18;
131
131
  return theme.colors.danger.background;
132
- }, ";outline:2px solid ", _ref19 => {
132
+ }, ";outline:1px solid ", _ref19 => {
133
133
  let {
134
134
  theme
135
135
  } = _ref19;
136
- return theme.colors.primary.backgroundHover;
136
+ return theme.shadows.focusPrimary;
137
137
  }, ";", InnerCheckbox, "{stroke:", _ref20 => {
138
138
  let {
139
139
  theme
@@ -154,11 +154,11 @@ const CheckboxInput = /*#__PURE__*/_styled('input', {
154
154
  theme
155
155
  } = _ref23;
156
156
  return theme.colors.danger.background;
157
- }, ";outline:2px solid ", _ref24 => {
157
+ }, ";outline:1px solid ", _ref24 => {
158
158
  let {
159
159
  theme
160
160
  } = _ref24;
161
- return theme.colors.danger.backgroundHover;
161
+ return theme.shadows.focusDanger;
162
162
  }, ";", InnerCheckbox, "{stroke:", _ref25 => {
163
163
  let {
164
164
  theme
@@ -445,12 +445,15 @@ const Checkbox = /*#__PURE__*/forwardRef((_ref64, ref) => {
445
445
  }), !progress ? jsx(StyledIcon, {
446
446
  size: size,
447
447
  viewBox: "0 0 24 24",
448
+ fill: "none",
448
449
  children: jsx(CheckboxIconContainer, {
449
450
  children: state !== 'indeterminate' ? jsx("path", {
450
451
  fillRule: "evenodd",
451
452
  clipRule: "evenodd",
452
- width: 14,
453
- height: 14,
453
+ width: 12,
454
+ height: 9,
455
+ x: "5",
456
+ y: "4",
454
457
  d: "M15.6678 5.26709C16.0849 5.6463 16.113 6.28907 15.7307 6.70276L9.29172 13.6705C9.10291 13.8748 8.83818 13.9937 8.55884 13.9998C8.2795 14.0058 8.0098 13.8984 7.81223 13.7024L4.30004 10.2185C3.89999 9.82169 3.89999 9.17831 4.30004 8.78149C4.70009 8.38467 5.34869 8.38467 5.74874 8.78149L8.50441 11.5149L14.2205 5.32951C14.6028 4.91583 15.2508 4.88788 15.6678 5.26709Z",
455
458
  fill: "white"
456
459
  }) : jsx(CheckMixedMark, {
@@ -480,12 +483,12 @@ const Checkbox = /*#__PURE__*/forwardRef((_ref64, ref) => {
480
483
  variant: "bodySmall",
481
484
  as: "p",
482
485
  prominence: "weak",
483
- color: "neutral",
486
+ sentiment: "neutral",
484
487
  children: helper
485
488
  }) : null, error ? jsx(ErrorText, {
486
489
  variant: "bodySmall",
487
490
  as: "p",
488
- color: "danger",
491
+ sentiment: "danger",
489
492
  children: error
490
493
  }) : null]
491
494
  })]
@@ -117,7 +117,7 @@ const CustomLegend = _ref3 => {
117
117
  children: [jsx(Text, {
118
118
  as: "span",
119
119
  variant: "bodySmall",
120
- color: "neutral",
120
+ sentiment: "neutral",
121
121
  children: row?.['label']
122
122
  }), jsx("div", {
123
123
  "data-testid": `label-${id}`,
@@ -40,13 +40,13 @@ const LineChartTooltip = _ref5 => {
40
40
  }), jsxs("div", {
41
41
  children: [jsx(Text, {
42
42
  variant: "bodyStronger",
43
- color: "neutral",
43
+ sentiment: "neutral",
44
44
  prominence: "stronger",
45
45
  as: "div",
46
46
  children: point.data.yFormatted
47
47
  }), jsx(Text, {
48
48
  variant: "bodySmall",
49
- color: "neutral",
49
+ sentiment: "neutral",
50
50
  prominence: "stronger",
51
51
  as: "div",
52
52
  children: point.data.xFormatted
@@ -92,6 +92,8 @@ const FwdMenu = /*#__PURE__*/forwardRef((_ref7, ref) => {
92
92
  ref: disclosureRef
93
93
  });
94
94
  return jsx(StyledPopup, {
95
+ needDebounce: false,
96
+ hideOnClickOutside: true,
95
97
  "aria-label": ariaLabel,
96
98
  className: className,
97
99
  visible: isVisible,
@@ -94,33 +94,12 @@ const Dialog = _ref9 => {
94
94
  onCloseRef.current = onClose;
95
95
  }, [onClose]);
96
96
 
97
- // Handle hide on esc press
97
+ // On open focus the modal
98
98
  useEffect(() => {
99
- const handleEscPress = event => {
100
- if (event.key === 'Escape' && hideOnEsc) {
101
- event.preventDefault();
102
- event.stopPropagation();
103
- onCloseRef.current();
104
- }
105
- };
106
99
  if (open) {
107
100
  dialogRef.current?.focus();
108
- document.body.addEventListener('keyup', handleEscPress, {
109
- capture: true
110
- });
111
- document.body.addEventListener('keydown', handleEscPress, {
112
- capture: true
113
- });
114
101
  }
115
- return () => {
116
- document.body.removeEventListener('keyup', handleEscPress, {
117
- capture: true
118
- });
119
- document.body.removeEventListener('keydown', handleEscPress, {
120
- capture: true
121
- });
122
- };
123
- }, [open, onCloseRef, hideOnEsc]);
102
+ }, [open]);
124
103
 
125
104
  // Handle body scroll
126
105
  useEffect(() => {
@@ -143,10 +122,23 @@ const Dialog = _ref9 => {
143
122
  event.stopPropagation();
144
123
  }, []);
145
124
 
146
- // Stop key up : used when having inputs in modals
147
- const stopKeyUp = useCallback(event => {
125
+ // handle key up : used when having inputs in modals - useful for hideOnEsc
126
+ const handleKeyUp = useCallback(event => {
148
127
  event.stopPropagation();
149
- }, []);
128
+ if (event.key === 'Escape' && hideOnEsc) {
129
+ event.preventDefault();
130
+ onCloseRef.current();
131
+ }
132
+ }, [hideOnEsc]);
133
+ const handleClose = useCallback(event => {
134
+ event.stopPropagation();
135
+ if (hideOnClickOutside) {
136
+ onCloseRef.current();
137
+ } else {
138
+ // Because overlay is not focusable we can't handle hideOnEsc properly
139
+ dialogRef.current?.focus();
140
+ }
141
+ }, [hideOnClickOutside]);
150
142
 
151
143
  // Enable focus trap inside the modal
152
144
  const handleFocusTrap = useCallback(event => {
@@ -185,14 +177,14 @@ const Dialog = _ref9 => {
185
177
  };
186
178
  return /*#__PURE__*/createPortal(jsx(StyledBackdrop, {
187
179
  "data-open": open,
188
- onClick: hideOnClickOutside ? onClose : undefined,
180
+ onClick: handleClose,
189
181
  className: backdropClassName,
190
182
  css: backdropCss,
191
183
  "data-testid": dataTestId ? `${dataTestId}-backdrop` : undefined,
192
184
  onFocus: stopFocus,
193
185
  children: jsx(StyledDialog, {
194
186
  css: dialogCss,
195
- onKeyUp: stopKeyUp,
187
+ onKeyUp: handleKeyUp,
196
188
  onKeyDown: handleFocusTrap,
197
189
  className: className,
198
190
  id: id,
@@ -359,7 +359,7 @@ const NumberInput = _ref21 => {
359
359
  }), typeof error === 'string' ? jsx(Text, {
360
360
  as: "span",
361
361
  variant: "bodySmall",
362
- color: "danger",
362
+ sentiment: "danger",
363
363
  prominence: "weak",
364
364
  children: error
365
365
  }) : null]
@@ -118,17 +118,6 @@ const Popover = _ref6 => {
118
118
  useEffect(() => {
119
119
  setLocalVisible(visible);
120
120
  }, [visible]);
121
- const handleClickOutside = useCallback(event => {
122
- if (ref.current && !ref.current.contains(event.target)) {
123
- onClose?.();
124
- }
125
- }, [onClose]);
126
- useEffect(() => {
127
- document.addEventListener('click', handleClickOutside, true);
128
- return () => {
129
- document.removeEventListener('click', handleClickOutside, true);
130
- };
131
- }, [handleClickOutside]);
132
121
 
133
122
  // When space key is pressed we show the popover
134
123
  const onKeyDownSpace = useCallback(event => {
@@ -146,6 +135,8 @@ const Popover = _ref6 => {
146
135
  innerRef.current?.focus();
147
136
  }, [onClose]);
148
137
  return jsx(StyledPopup, {
138
+ hideOnClickOutside: true,
139
+ needDebounce: false,
149
140
  visible: localVisible,
150
141
  placement: placement,
151
142
  text: jsx(ContentWrapper, {
@@ -0,0 +1,12 @@
1
+ import _styled from '@emotion/styled/base';
2
+
3
+ const Square = /*#__PURE__*/_styled("div", {
4
+ target: "e1uz28830"
5
+ })("height:100%;width:100%;max-width:100%;background-color:", _ref => {
6
+ let {
7
+ theme
8
+ } = _ref;
9
+ return theme.colors.neutral.borderWeak;
10
+ }, ";");
11
+
12
+ export { Square };
@@ -7,6 +7,7 @@ import { Donut } from './Donut.js';
7
7
  import { Line } from './Line.js';
8
8
  import { List } from './List.js';
9
9
  import { Slider } from './Slider.js';
10
+ import { Square } from './Square.js';
10
11
  import { jsxs, jsx } from '@emotion/react/jsx-runtime';
11
12
 
12
13
  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)."; }
@@ -21,11 +22,11 @@ const shineAnimation = keyframes`
21
22
  const StyledContainer = /*#__PURE__*/_styled("div", {
22
23
  target: "e183x2r81"
23
24
  })(process.env.NODE_ENV === "production" ? {
24
- name: "po0r11",
25
- styles: "position:relative;display:block;width:100%;overflow:hidden;cursor:progress"
25
+ name: "158ltsb",
26
+ styles: "position:relative;width:100%;overflow:hidden;cursor:progress;display:flex;flex-flow:column;height:100%"
26
27
  } : {
27
- name: "po0r11",
28
- styles: "position:relative;display:block;width:100%;overflow:hidden;cursor:progress",
28
+ name: "158ltsb",
29
+ styles: "position:relative;width:100%;overflow:hidden;cursor:progress;display:flex;flex-flow:column;height:100%",
29
30
  toString: _EMOTION_STRINGIFIED_CSS_ERROR__
30
31
  });
31
32
  const StyledDiv = /*#__PURE__*/_styled("div", {
@@ -63,7 +64,8 @@ const variants = {
63
64
  donut: Donut,
64
65
  line: Line,
65
66
  list: List,
66
- slider: Slider
67
+ slider: Slider,
68
+ square: Square
67
69
  };
68
70
  /**
69
71
  * Skeleton component is used to indicate that the data is loading.
@@ -3,7 +3,6 @@ import { HeaderCell } from './HeaderCell.js';
3
3
  import { useTableContext } from './TableContext.js';
4
4
  import { jsxs, jsx } from '@emotion/react/jsx-runtime';
5
5
 
6
- const SELECT_CHECKBOX_SIZE = 24;
7
6
  const HeaderRow = _ref => {
8
7
  let {
9
8
  children,
@@ -18,18 +17,17 @@ const HeaderRow = _ref => {
18
17
  const selectableRowCount = Object.keys(selectedRowIds).length;
19
18
  return jsxs("tr", {
20
19
  children: [hasSelectAllColumn ? jsx(HeaderCell, {
21
- width: `${SELECT_CHECKBOX_SIZE}px`,
20
+ width: "24px",
22
21
  children: jsx(Checkbox, {
23
22
  name: "table-select-all-checkbox",
24
23
  value: "all",
25
24
  "aria-label": "select all",
26
25
  checked: allRowSelectValue,
27
26
  onChange: allRowSelectValue === false ? selectAll : unselectAll,
28
- disabled: selectableRowCount === 0,
29
- size: SELECT_CHECKBOX_SIZE
27
+ disabled: selectableRowCount === 0
30
28
  })
31
29
  }) : null, children]
32
30
  });
33
31
  };
34
32
 
35
- export { HeaderRow, SELECT_CHECKBOX_SIZE };
33
+ export { HeaderRow };
@@ -3,7 +3,6 @@ import { useEffect } from 'react';
3
3
  import { Checkbox } from '../Checkbox/index.js';
4
4
  import { Tooltip } from '../Tooltip/index.js';
5
5
  import { Cell } from './Cell.js';
6
- import { SELECT_CHECKBOX_SIZE } from './HeaderRow.js';
7
6
  import { useTableContext } from './TableContext.js';
8
7
  import { jsxs, jsx } from '@emotion/react/jsx-runtime';
9
8
 
@@ -58,8 +57,7 @@ const Row = _ref2 => {
58
57
  selectRow(id);
59
58
  }
60
59
  },
61
- disabled: selectDisabled !== undefined,
62
- size: SELECT_CHECKBOX_SIZE
60
+ disabled: selectDisabled !== undefined
63
61
  })
64
62
  })
65
63
  })
@@ -50,34 +50,34 @@ const CloseButton = _ref3 => {
50
50
  };
51
51
  const Content = _ref4 => {
52
52
  let {
53
- variant,
53
+ sentiment,
54
54
  children
55
55
  } = _ref4;
56
56
  return jsxs(Stack, {
57
57
  gap: 2,
58
58
  direction: "row",
59
59
  children: [jsx(Icon, {
60
- name: TOAST_ICONS[variant],
60
+ name: TOAST_ICONS[sentiment],
61
61
  size: 24
62
62
  }), jsx(Text, {
63
63
  variant: "body",
64
64
  as: "span",
65
- color: variant,
65
+ sentiment: sentiment,
66
66
  children: children
67
67
  })]
68
68
  });
69
69
  };
70
70
  const toast = {
71
71
  error: (children, options) => toast$1.error(jsx(Content, {
72
- variant: "danger",
72
+ sentiment: "danger",
73
73
  children: children
74
74
  }), options),
75
75
  info: (children, options) => toast$1.info(jsx(Content, {
76
- variant: "info",
76
+ sentiment: "info",
77
77
  children: children
78
78
  }), options),
79
79
  success: (children, options) => toast$1.success(jsx(Content, {
80
- variant: "success",
80
+ sentiment: "success",
81
81
  children: children
82
82
  }), options)
83
83
  };
@@ -7,7 +7,7 @@ import { jsx, Fragment, jsxs } from '@emotion/react/jsx-runtime';
7
7
 
8
8
  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)."; }
9
9
  const ANIMATION_DURATION = 230; // in ms
10
-
10
+ const DEBOUNCE_DURATION = 200;
11
11
  function noop() {}
12
12
  const animation = positions => keyframes`
13
13
  0% {
@@ -121,7 +121,9 @@ const Popup = /*#__PURE__*/forwardRef((_ref13, tooltipRef) => {
121
121
  onClose,
122
122
  tabIndex = 0,
123
123
  onKeyDown,
124
- 'aria-haspopup': ariaHasPopup
124
+ 'aria-haspopup': ariaHasPopup,
125
+ hideOnClickOutside = false,
126
+ needDebounce = true
125
127
  } = _ref13;
126
128
  const childrenRef = useRef(null);
127
129
  useImperativeHandle(innerRef, () => childrenRef.current);
@@ -176,8 +178,8 @@ const Popup = /*#__PURE__*/forwardRef((_ref13, tooltipRef) => {
176
178
  unmountTooltip();
177
179
  onClose?.();
178
180
  }, ANIMATION_DURATION);
179
- }, 200);
180
- }, [onClose, unmountTooltip]);
181
+ }, needDebounce ? DEBOUNCE_DURATION : 0);
182
+ }, [needDebounce, onClose, unmountTooltip]);
181
183
 
182
184
  /**
183
185
  * When mouse hover or stop hovering children this function display or hide tooltip. A timeout is set to allow animation
@@ -244,7 +246,7 @@ const Popup = /*#__PURE__*/forwardRef((_ref13, tooltipRef) => {
244
246
  }
245
247
  }, [unmountTooltip]);
246
248
 
247
- // Handle hide on esc press
249
+ // Handle hide on esc press and hide on click outside
248
250
  useEffect(() => {
249
251
  const handleEscPress = event => {
250
252
  if (event.key === 'Escape') {
@@ -253,23 +255,26 @@ const Popup = /*#__PURE__*/forwardRef((_ref13, tooltipRef) => {
253
255
  hideTooltip();
254
256
  }
255
257
  };
258
+ const handleClickOutside = event => {
259
+ const tooltipCurrent = innerTooltipRef.current;
260
+ const childrenCurrent = childrenRef.current;
261
+ if (tooltipCurrent && hideOnClickOutside) {
262
+ if (event.target && event.target !== tooltipCurrent && event.target !== childrenCurrent && !childrenCurrent?.contains(event.target) && !tooltipCurrent.contains(event.target)) {
263
+ event.preventDefault();
264
+ event.stopPropagation();
265
+ hideTooltip();
266
+ }
267
+ }
268
+ };
256
269
  if (visibleInDom) {
257
- document.body.addEventListener('keyup', handleEscPress, {
258
- capture: true
259
- });
260
- document.body.addEventListener('keydown', handleEscPress, {
261
- capture: true
262
- });
270
+ document.body.addEventListener('keyup', handleEscPress);
271
+ document.body.addEventListener('click', handleClickOutside);
263
272
  }
264
273
  return () => {
265
- document.body.removeEventListener('keyup', handleEscPress, {
266
- capture: true
267
- });
268
- document.body.addEventListener('keydown', handleEscPress, {
269
- capture: true
270
- });
274
+ document.body.removeEventListener('keyup', handleEscPress);
275
+ document.body.removeEventListener('click', handleClickOutside);
271
276
  };
272
- }, [hideTooltip, onClose, unmountTooltip, visibleInDom]);
277
+ }, [hideTooltip, visibleInDom, innerTooltipRef, childrenRef, hideOnClickOutside]);
273
278
 
274
279
  /**
275
280
  * Will render children conditionally if children is a function or not.
@@ -2,6 +2,10 @@ import { consoleLightTheme } from '@ultraviolet/themes';
2
2
  export { consoleDarkTheme as darkTheme, consoleLightTheme as default } from '@ultraviolet/themes';
3
3
  import deepmerge from 'deepmerge';
4
4
 
5
+ /**
6
+ * @deprecated use UltravioletUITheme instead
7
+ */
8
+
5
9
  const {
6
10
  colors,
7
11
  shadows,
@@ -12,8 +16,8 @@ const {
12
16
  } = consoleLightTheme;
13
17
  /**
14
18
  * Will extend theme with new theme properties
15
- * @param {SCWUITheme} baseTheme the theme you want to extend from, by default it is set to light theme
16
- * @param {RecursivePartial<SCWUITheme>} extendedTheme the properties of a new theme you want to apply from baseTheme
19
+ * @param {UltravioletUITheme} baseTheme the theme you want to extend from, by default it is set to light theme
20
+ * @param {RecursivePartial<UltravioletUITheme>} extendedTheme the properties of a new theme you want to apply from baseTheme
17
21
  */
18
22
  const extendTheme = extendedTheme => deepmerge(consoleLightTheme, extendedTheme);
19
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraviolet/ui",
3
- "version": "1.16.0",
3
+ "version": "1.18.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.22.19",
42
+ "@babel/core": "7.23.0",
43
43
  "@emotion/babel-plugin": "11.11.0",
44
44
  "@emotion/react": "11.11.1",
45
45
  "@emotion/styled": "11.11.0",
46
- "@types/react": "18.2.21",
47
- "@types/react-datepicker": "4.15.0",
48
- "@types/react-dom": "18.2.7",
46
+ "@types/react": "18.2.25",
47
+ "@types/react-datepicker": "4.15.1",
48
+ "@types/react-dom": "18.2.10",
49
49
  "react": "18.2.0",
50
50
  "react-dom": "18.2.0"
51
51
  },
@@ -62,11 +62,11 @@
62
62
  "deepmerge": "4.3.1",
63
63
  "react-datepicker": "4.18.0",
64
64
  "react-flatten-children": "1.1.2",
65
- "react-select": "5.7.4",
65
+ "react-select": "5.7.7",
66
66
  "react-toastify": "9.1.3",
67
67
  "react-use-clipboard": "1.0.9",
68
68
  "reakit": "1.3.11",
69
69
  "@ultraviolet/themes": "1.2.1",
70
- "@ultraviolet/icons": "2.0.3"
70
+ "@ultraviolet/icons": "2.2.0"
71
71
  }
72
72
  }