@ultraviolet/ui 1.48.1 → 1.49.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
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import react__default, { ReactNode, ComponentProps, ButtonHTMLAttributes, AriaRole, MouseEventHandler, JSX, MouseEvent, InputHTMLAttributes, FocusEvent, HTMLAttributeAnchorTarget, AnchorHTMLAttributes, Dispatch, SetStateAction, ReactElement, Ref, RefObject, KeyboardEventHandler, HTMLAttributes, CSSProperties, ChangeEventHandler, FocusEventHandler, ForwardRefExoticComponent, ForwardedRef, ElementType, DOMAttributes, TextareaHTMLAttributes } from 'react';
2
+ import react__default, { ReactNode, ComponentProps, ButtonHTMLAttributes, AriaRole, MouseEventHandler, JSX, MouseEvent, InputHTMLAttributes, FocusEvent, ReactElement, HTMLAttributeAnchorTarget, AnchorHTMLAttributes, Dispatch, SetStateAction, Ref, RefObject, KeyboardEventHandler, HTMLAttributes, CSSProperties, ChangeEventHandler, FocusEventHandler, ForwardRefExoticComponent, ForwardedRef, ElementType, DOMAttributes, TextareaHTMLAttributes } from 'react';
3
3
  import * as _emotion_react_jsx_runtime from '@emotion/react/jsx-runtime';
4
4
  import * as _emotion_styled from '@emotion/styled';
5
5
  import * as _emotion_react from '@emotion/react';
@@ -1638,6 +1638,157 @@ type DateInputProps = Pick<ReactDatePickerProps<string, boolean>, 'locale' | 'on
1638
1638
  */
1639
1639
  declare const DateInput: ({ autoFocus, disabled, error, format, label, labelDescription, locale, maxDate, minDate, startDate, endDate, name, onBlur, onChange, onFocus, required, excludeDates, value, selectsRange, className, id, success, helper, size, readOnly, tooltip, "data-testid": dataTestId, }: DateInputProps) => _emotion_react_jsx_runtime.JSX.Element;
1640
1640
 
1641
+ type ModalSize = 'large' | 'medium' | 'small' | 'xsmall' | 'xxsmall';
1642
+ type ModalPlacement = 'bottom' | 'bottom-left' | 'bottom-right' | 'center' | 'top' | 'top-left' | 'top-right' | 'right' | 'left';
1643
+ type ModalState = {
1644
+ /**
1645
+ * @deprecated use show
1646
+ */
1647
+ onOpen: () => void;
1648
+ /**
1649
+ * @deprecated use close
1650
+ */
1651
+ onClose: () => void;
1652
+ toggle: () => void;
1653
+ visible: boolean;
1654
+ modalId: string;
1655
+ /**
1656
+ * @deprecated use close
1657
+ */
1658
+ hide: () => void;
1659
+ close: () => void;
1660
+ show: () => void;
1661
+ };
1662
+
1663
+ type ModalProps = {
1664
+ id?: string;
1665
+ hideOnEsc?: boolean;
1666
+ hideOnClickOutside?: boolean;
1667
+ preventBodyScroll?: boolean;
1668
+ ariaLabel?: string;
1669
+ disclosure?: ReactElement | ((state: ModalState) => ReactElement);
1670
+ isClosable?: boolean;
1671
+ onClose?: () => void;
1672
+ onBeforeClose?: () => Promise<void> | void;
1673
+ open?: boolean;
1674
+ /**
1675
+ * @deprecated You should use open prop instead
1676
+ */
1677
+ opened?: boolean;
1678
+ placement?: ModalPlacement;
1679
+ size?: ModalSize;
1680
+ /**
1681
+ * @deprecated You should use size prop instead
1682
+ */
1683
+ width?: ModalSize;
1684
+ children: ReactNode | ((args: ModalState) => ReactNode);
1685
+ className?: string;
1686
+ 'data-testid'?: string;
1687
+ backdropClassName?: string;
1688
+ /**
1689
+ * @deprecated You should use backdropClassName instead
1690
+ */
1691
+ customDialogBackdropStyles?: react__default.JSX.IntrinsicAttributes['css'];
1692
+ /**
1693
+ * @deprecated You should use className instead
1694
+ */
1695
+ customDialogStyles?: react__default.JSX.IntrinsicAttributes['css'];
1696
+ };
1697
+ /**
1698
+ * Modal is a component that allows you to display content on top of other content.
1699
+ * It is often used to display a dialog with additional information or to ask for a confirmation.
1700
+ */
1701
+ declare const Modal: ({ ariaLabel, id, children, disclosure, hideOnClickOutside, hideOnEsc, isClosable, onClose, onBeforeClose, open, opened, placement, preventBodyScroll, size, className, "data-testid": dataTestId, backdropClassName, width, customDialogStyles, customDialogBackdropStyles, }: ModalProps) => _emotion_react_jsx_runtime.JSX.Element;
1702
+
1703
+ declare const DIALOG_SENTIMENTS: ("primary" | "success" | "danger" | "warning")[];
1704
+ type DialogSentiment = (typeof DIALOG_SENTIMENTS)[number];
1705
+
1706
+ type DialogContextType = {
1707
+ sentiment: DialogSentiment;
1708
+ };
1709
+
1710
+ type DialogProps = Pick<ComponentProps<typeof Modal>, 'ariaLabel' | 'children' | 'className' | 'data-testid' | 'disclosure' | 'hideOnClickOutside' | 'hideOnEsc' | 'id' | 'isClosable' | 'onBeforeClose' | 'onClose' | 'open' | 'placement'> & {
1711
+ title: string;
1712
+ sentiment: DialogSentiment;
1713
+ };
1714
+ /**
1715
+ * The Dialog component is used to show content on top of an overlay that requires user interaction.
1716
+ * @experimental This component is experimental and may be subject to breaking changes in the future.
1717
+ */
1718
+ declare const Dialog: (({ ariaLabel, className, children, "data-testid": dataTestId, disclosure, hideOnClickOutside, hideOnEsc, id, isClosable, onBeforeClose, onClose, open, placement, sentiment, title, }: DialogProps) => _emotion_react_jsx_runtime.JSX.Element) & {
1719
+ Buttons: ({ secondaryButton, primaryButton, }: {
1720
+ secondaryButton: react.ReactNode;
1721
+ primaryButton: react.ReactNode;
1722
+ }) => _emotion_react_jsx_runtime.JSX.Element;
1723
+ Button: ({ children, onClick, disabled, tooltip, }: {
1724
+ children: react.ReactNode;
1725
+ } & Pick<({
1726
+ type?: "button" | "reset" | "submit" | undefined;
1727
+ autoFocus?: boolean | undefined;
1728
+ variant?: "filled" | "outlined" | "ghost" | undefined;
1729
+ role?: react.AriaRole | undefined;
1730
+ size?: "large" | "small" | "xsmall" | "medium" | undefined;
1731
+ className?: string | undefined;
1732
+ 'data-testid'?: string | undefined;
1733
+ sentiment?: "primary" | "secondary" | "neutral" | "success" | "danger" | "warning" | "info" | undefined;
1734
+ disabled?: boolean | undefined;
1735
+ iconPosition?: "left" | "right" | undefined;
1736
+ iconVariant?: "filled" | "outlined" | undefined;
1737
+ fullWidth?: boolean | undefined;
1738
+ isLoading?: boolean | undefined;
1739
+ 'aria-label'?: string | undefined;
1740
+ 'aria-current'?: boolean | undefined;
1741
+ 'aria-controls'?: string | undefined;
1742
+ 'aria-expanded'?: boolean | undefined;
1743
+ 'aria-haspopup'?: boolean | undefined;
1744
+ onClick?: react.MouseEventHandler<HTMLElement> | undefined;
1745
+ tooltip?: string | undefined;
1746
+ tabIndex?: number | undefined;
1747
+ onMouseDown?: react.MouseEventHandler<HTMLElement> | undefined;
1748
+ onMouseUp?: react.MouseEventHandler<HTMLElement> | undefined;
1749
+ onMouseOut?: react.MouseEventHandler<HTMLElement> | undefined;
1750
+ } & ({
1751
+ children: react.ReactNode;
1752
+ icon?: "address" | "search" | "filter" | "view" | "id" | "alert" | "x" | "anchor" | "cancel" | "close" | "sort" | "download" | "arrow-down" | "arrow-left-bottom" | "arrow-left-double" | "arrow-left" | "arrow-right-bottom" | "arrow-right-double" | "arrow-right" | "arrow-up" | "asterisk" | "attach" | "burger" | "check" | "close-circle-outline" | "copy-content" | "detach" | "dots-horizontal" | "dots-vertical" | "drag-vertical" | "drag-variant" | "east" | "equal" | "escape" | "expand" | "expand-more" | "github" | "instagram" | "linkedIn" | "logout" | "minus" | "north" | "open-in-new" | "organization" | "plus" | "progress-check" | "ray-end-arrow" | "ray-start-arrow" | "ray-start-end" | "ray-top-arrow" | "reboot" | "restore" | "revoke" | "rss" | "send" | "slack" | "south" | "switch_orga" | "upload" | "west" | "youtube" | "auto-fix" | "book-open-outline" | "bullhorn" | "calculator" | "calendar-range" | "chat" | "checkbox-circle-outline" | "clock-outline" | "console" | "credentials" | "credit-card" | "database" | "delete" | "doc" | "earth" | "email-remove-outline" | "email-outline" | "eye-off" | "eye" | "folder" | "help-circle-outline" | "information-outline" | "lock" | "members" | "moon" | "mosaic" | "pen" | "pencil" | "phone" | "play-circle-outline" | "privacy" | "profile" | "rocket" | "settings" | "sun" | "support" | "unlock" | "weather-night" | "pin" | "unpin" | undefined;
1753
+ name?: string | undefined;
1754
+ href?: undefined;
1755
+ target?: undefined;
1756
+ download?: undefined;
1757
+ } | {
1758
+ children?: undefined;
1759
+ icon: "address" | "search" | "filter" | "view" | "id" | "alert" | "x" | "anchor" | "cancel" | "close" | "sort" | "download" | "arrow-down" | "arrow-left-bottom" | "arrow-left-double" | "arrow-left" | "arrow-right-bottom" | "arrow-right-double" | "arrow-right" | "arrow-up" | "asterisk" | "attach" | "burger" | "check" | "close-circle-outline" | "copy-content" | "detach" | "dots-horizontal" | "dots-vertical" | "drag-vertical" | "drag-variant" | "east" | "equal" | "escape" | "expand" | "expand-more" | "github" | "instagram" | "linkedIn" | "logout" | "minus" | "north" | "open-in-new" | "organization" | "plus" | "progress-check" | "ray-end-arrow" | "ray-start-arrow" | "ray-start-end" | "ray-top-arrow" | "reboot" | "restore" | "revoke" | "rss" | "send" | "slack" | "south" | "switch_orga" | "upload" | "west" | "youtube" | "auto-fix" | "book-open-outline" | "bullhorn" | "calculator" | "calendar-range" | "chat" | "checkbox-circle-outline" | "clock-outline" | "console" | "credentials" | "credit-card" | "database" | "delete" | "doc" | "earth" | "email-remove-outline" | "email-outline" | "eye-off" | "eye" | "folder" | "help-circle-outline" | "information-outline" | "lock" | "members" | "moon" | "mosaic" | "pen" | "pencil" | "phone" | "play-circle-outline" | "privacy" | "profile" | "rocket" | "settings" | "sun" | "support" | "unlock" | "weather-night" | "pin" | "unpin" | undefined;
1760
+ name?: string | undefined;
1761
+ href?: undefined;
1762
+ target?: undefined;
1763
+ download?: undefined;
1764
+ } | {
1765
+ children: react.ReactNode;
1766
+ icon?: "address" | "search" | "filter" | "view" | "id" | "alert" | "x" | "anchor" | "cancel" | "close" | "sort" | "download" | "arrow-down" | "arrow-left-bottom" | "arrow-left-double" | "arrow-left" | "arrow-right-bottom" | "arrow-right-double" | "arrow-right" | "arrow-up" | "asterisk" | "attach" | "burger" | "check" | "close-circle-outline" | "copy-content" | "detach" | "dots-horizontal" | "dots-vertical" | "drag-vertical" | "drag-variant" | "east" | "equal" | "escape" | "expand" | "expand-more" | "github" | "instagram" | "linkedIn" | "logout" | "minus" | "north" | "open-in-new" | "organization" | "plus" | "progress-check" | "ray-end-arrow" | "ray-start-arrow" | "ray-start-end" | "ray-top-arrow" | "reboot" | "restore" | "revoke" | "rss" | "send" | "slack" | "south" | "switch_orga" | "upload" | "west" | "youtube" | "auto-fix" | "book-open-outline" | "bullhorn" | "calculator" | "calendar-range" | "chat" | "checkbox-circle-outline" | "clock-outline" | "console" | "credentials" | "credit-card" | "database" | "delete" | "doc" | "earth" | "email-remove-outline" | "email-outline" | "eye-off" | "eye" | "folder" | "help-circle-outline" | "information-outline" | "lock" | "members" | "moon" | "mosaic" | "pen" | "pencil" | "phone" | "play-circle-outline" | "privacy" | "profile" | "rocket" | "settings" | "sun" | "support" | "unlock" | "weather-night" | "pin" | "unpin" | undefined;
1767
+ name?: undefined;
1768
+ href: string;
1769
+ target?: string | undefined;
1770
+ download?: string | undefined;
1771
+ } | {
1772
+ children?: undefined;
1773
+ icon: "address" | "search" | "filter" | "view" | "id" | "alert" | "x" | "anchor" | "cancel" | "close" | "sort" | "download" | "arrow-down" | "arrow-left-bottom" | "arrow-left-double" | "arrow-left" | "arrow-right-bottom" | "arrow-right-double" | "arrow-right" | "arrow-up" | "asterisk" | "attach" | "burger" | "check" | "close-circle-outline" | "copy-content" | "detach" | "dots-horizontal" | "dots-vertical" | "drag-vertical" | "drag-variant" | "east" | "equal" | "escape" | "expand" | "expand-more" | "github" | "instagram" | "linkedIn" | "logout" | "minus" | "north" | "open-in-new" | "organization" | "plus" | "progress-check" | "ray-end-arrow" | "ray-start-arrow" | "ray-start-end" | "ray-top-arrow" | "reboot" | "restore" | "revoke" | "rss" | "send" | "slack" | "south" | "switch_orga" | "upload" | "west" | "youtube" | "auto-fix" | "book-open-outline" | "bullhorn" | "calculator" | "calendar-range" | "chat" | "checkbox-circle-outline" | "clock-outline" | "console" | "credentials" | "credit-card" | "database" | "delete" | "doc" | "earth" | "email-remove-outline" | "email-outline" | "eye-off" | "eye" | "folder" | "help-circle-outline" | "information-outline" | "lock" | "members" | "moon" | "mosaic" | "pen" | "pencil" | "phone" | "play-circle-outline" | "privacy" | "profile" | "rocket" | "settings" | "sun" | "support" | "unlock" | "weather-night" | "pin" | "unpin" | undefined;
1774
+ name?: undefined;
1775
+ href: string;
1776
+ target?: string | undefined;
1777
+ download?: string | undefined;
1778
+ })) & react.RefAttributes<Element>, "tooltip" | "onClick" | "disabled">) => _emotion_react_jsx_runtime.JSX.Element;
1779
+ CancelButton: ({ children, onClick, }: {
1780
+ children: react.ReactNode;
1781
+ onClick: react.MouseEventHandler<HTMLElement> | undefined;
1782
+ }) => _emotion_react_jsx_runtime.JSX.Element;
1783
+ Stack: ({ children }: {
1784
+ children: react.ReactNode;
1785
+ }) => _emotion_react_jsx_runtime.JSX.Element;
1786
+ Text: ({ children }: {
1787
+ children: react.ReactNode;
1788
+ }) => _emotion_react_jsx_runtime.JSX.Element;
1789
+ useDialogContext: () => DialogContextType;
1790
+ };
1791
+
1641
1792
  declare const CONTAINER_SIZES: {
1642
1793
  readonly small: 720;
1643
1794
  readonly medium: 720;
@@ -1941,64 +2092,6 @@ type PasswordStrengthMeterProps$1 = {
1941
2092
  */
1942
2093
  declare const Meter: ({ strength, title, value, className, "data-testid": dataTestId, id, }: PasswordStrengthMeterProps$1) => _emotion_react_jsx_runtime.JSX.Element;
1943
2094
 
1944
- type ModalSize = 'large' | 'medium' | 'small' | 'xsmall' | 'xxsmall';
1945
- type ModalPlacement = 'bottom' | 'bottom-left' | 'bottom-right' | 'center' | 'top' | 'top-left' | 'top-right' | 'right' | 'left';
1946
- type ModalState = {
1947
- /**
1948
- * @deprecated use show
1949
- */
1950
- onOpen: () => void;
1951
- /**
1952
- * @deprecated use close
1953
- */
1954
- onClose: () => void;
1955
- toggle: () => void;
1956
- visible: boolean;
1957
- modalId: string;
1958
- /**
1959
- * @deprecated use close
1960
- */
1961
- hide: () => void;
1962
- close: () => void;
1963
- show: () => void;
1964
- };
1965
-
1966
- type ModalProps = {
1967
- id?: string;
1968
- hideOnEsc?: boolean;
1969
- hideOnClickOutside?: boolean;
1970
- preventBodyScroll?: boolean;
1971
- ariaLabel?: string;
1972
- disclosure?: ReactElement | ((state: ModalState) => ReactElement);
1973
- isClosable?: boolean;
1974
- onClose?: () => void;
1975
- onBeforeClose?: () => Promise<void> | void;
1976
- opened?: boolean;
1977
- placement?: ModalPlacement;
1978
- size?: ModalSize;
1979
- /**
1980
- * @deprecated You should use size prop instead
1981
- */
1982
- width?: ModalSize;
1983
- children: ReactNode | ((args: ModalState) => ReactNode);
1984
- className?: string;
1985
- 'data-testid'?: string;
1986
- backdropClassName?: string;
1987
- /**
1988
- * @deprecated You should use backdropClassName instead
1989
- */
1990
- customDialogBackdropStyles?: react__default.JSX.IntrinsicAttributes['css'];
1991
- /**
1992
- * @deprecated You should use className instead
1993
- */
1994
- customDialogStyles?: react__default.JSX.IntrinsicAttributes['css'];
1995
- };
1996
- /**
1997
- * Modal is a component that allows you to display content on top of other content.
1998
- * It is often used to display a dialog with additional information or to ask for a confirmation.
1999
- */
2000
- declare const Modal: ({ ariaLabel, id, children, disclosure, hideOnClickOutside, hideOnEsc, isClosable, onClose, onBeforeClose, opened, placement, preventBodyScroll, size, className, "data-testid": dataTestId, backdropClassName, width, customDialogStyles, customDialogBackdropStyles, }: ModalProps) => _emotion_react_jsx_runtime.JSX.Element;
2001
-
2002
2095
  type NoticeProps = {
2003
2096
  children: ReactNode;
2004
2097
  className?: string;
@@ -3446,10 +3539,6 @@ type SelectInputV2Props = {
3446
3539
  * Input name
3447
3540
  */
3448
3541
  name: string;
3449
- /**
3450
- * Default value, must be one of the options
3451
- */
3452
- value?: OptionType;
3453
3542
  /**
3454
3543
  * Place holder when no value defined
3455
3544
  */
@@ -3494,10 +3583,6 @@ type SelectInputV2Props = {
3494
3583
  * Size of the input
3495
3584
  */
3496
3585
  size?: 'small' | 'medium' | 'large';
3497
- /**
3498
- * Whether it is possible to select multiple options
3499
- */
3500
- multiselect?: boolean;
3501
3586
  /**
3502
3587
  * Whether field is required
3503
3588
  */
@@ -3548,7 +3633,25 @@ type SelectInputV2Props = {
3548
3633
  autofocus?: boolean;
3549
3634
  'data-testid'?: string;
3550
3635
  onChange?: (value: string[]) => void;
3551
- } & Pick<HTMLAttributes<HTMLDivElement>, 'id' | 'onBlur' | 'onFocus' | 'aria-label' | 'className'>;
3636
+ } & Pick<HTMLAttributes<HTMLDivElement>, 'id' | 'onBlur' | 'onFocus' | 'aria-label' | 'className'> & ({
3637
+ /**
3638
+ * Whether it is possible to select multiple options
3639
+ */
3640
+ multiselect: true;
3641
+ /**
3642
+ * Default value, must be one of the options
3643
+ */
3644
+ value?: string[];
3645
+ } | {
3646
+ /**
3647
+ * Whether it is possible to select multiple options
3648
+ */
3649
+ multiselect?: false | undefined;
3650
+ /**
3651
+ * Default value, must be one of the options
3652
+ */
3653
+ value?: string;
3654
+ });
3552
3655
  /**
3553
3656
  * SelectInputV2 component is used to select one or many elements from a selection.
3554
3657
  */
@@ -3597,4 +3700,4 @@ declare const down: (size: ScreenSize, rules: string) => string;
3597
3700
 
3598
3701
  declare const normalize: () => string;
3599
3702
 
3600
- export { ActionBar, Alert, Avatar, Badge, Banner, BarChart, BarStack, Breadcrumbs, Breakpoint, Bullet, Button, Card, Carousel, Checkbox, CheckboxGroup, CheckboxGroupCheckbox, CopyButton, DateInput, EmptyState, Expandable, GlobalAlert, LineChart, Link, List, Loader, Menu, MenuV2, Meter, Modal, Notice, NotificationContainer, NumberInput, NumberInputV2, Pagination, PasswordCheck, PasswordStrengthMeter, PieChart, Popover, Popup, ProgressBar, Radio, RadioGroup, Row, type SCWUITheme, SelectInput, SelectInputV2, SelectableCard, SelectableCardGroup, Separator, Skeleton, Snippet, Stack, Status, StepList, Stepper, SwitchButton, Table, Tabs, Tag, TagInput, TagList, Text, TextArea, TextInput, TextInputV2, TimeInput, ToastContainer, Toggle, ToggleGroup, Tooltip, type UltravioletUITheme, VerificationCode, bounce, down, extendTheme, fadeIn, fadeOut, flash, getUUID, normalize, notification, 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 };
3703
+ export { ActionBar, Alert, Avatar, Badge, Banner, BarChart, BarStack, Breadcrumbs, Breakpoint, Bullet, Button, Card, Carousel, Checkbox, CheckboxGroup, CheckboxGroupCheckbox, CopyButton, DateInput, Dialog, EmptyState, Expandable, GlobalAlert, LineChart, Link, List, Loader, Menu, MenuV2, Meter, Modal, Notice, NotificationContainer, NumberInput, NumberInputV2, Pagination, PasswordCheck, PasswordStrengthMeter, PieChart, Popover, Popup, ProgressBar, Radio, RadioGroup, Row, type SCWUITheme, SelectInput, SelectInputV2, SelectableCard, SelectableCardGroup, Separator, Skeleton, Snippet, Stack, Status, StepList, Stepper, SwitchButton, Table, Tabs, Tag, TagInput, TagList, Text, TextArea, TextInput, TextInputV2, TimeInput, ToastContainer, Toggle, ToggleGroup, Tooltip, type UltravioletUITheme, VerificationCode, bounce, down, extendTheme, fadeIn, fadeOut, flash, getUUID, normalize, notification, 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 };
@@ -89,7 +89,7 @@ const Bullet = ({
89
89
  prominence: prominence,
90
90
  children: icon ? jsx(Icon, {
91
91
  name: icon,
92
- size: "50%",
92
+ size: "small",
93
93
  variant: iconVariant
94
94
  }) : text
95
95
  })
@@ -0,0 +1,12 @@
1
+ import { useContext, createContext } from 'react';
2
+
3
+ const DialogContext = /*#__PURE__*/createContext(undefined);
4
+ const useDialogContext = () => {
5
+ const context = useContext(DialogContext);
6
+ if (!context) {
7
+ throw new Error('Dialog context can only be used inside a Dialog component');
8
+ }
9
+ return context;
10
+ };
11
+
12
+ export { DialogContext, useDialogContext };
@@ -0,0 +1,88 @@
1
+ import _styled from '@emotion/styled/base';
2
+ import { useMemo } from 'react';
3
+ import { Bullet } from '../Bullet/index.js';
4
+ import { Modal } from '../Modal/index.js';
5
+ import { Text } from '../Text/index.js';
6
+ import { useDialogContext, DialogContext } from './Context.js';
7
+ import { DialogButton } from './subComponents/Button.js';
8
+ import { DialogButtons } from './subComponents/Buttons.js';
9
+ import { DialogCancelButton } from './subComponents/CancelButton.js';
10
+ import { DialogStack } from './subComponents/Stack.js';
11
+ import { DialogText } from './subComponents/Text.js';
12
+ import { jsxs, Fragment, jsx } from '@emotion/react/jsx-runtime';
13
+
14
+ const StyledTextTitle = /*#__PURE__*/_styled(Text, {
15
+ target: "ehf9m9r0"
16
+ })("margin-top:", ({
17
+ theme
18
+ }) => theme.space['2'], ";margin-bottom:", ({
19
+ theme
20
+ }) => theme.space['1'], ";");
21
+ const BaseDialog = ({
22
+ ariaLabel,
23
+ className,
24
+ children,
25
+ 'data-testid': dataTestId,
26
+ disclosure,
27
+ hideOnClickOutside,
28
+ hideOnEsc,
29
+ id,
30
+ isClosable,
31
+ onBeforeClose,
32
+ onClose,
33
+ open,
34
+ placement,
35
+ sentiment,
36
+ title
37
+ }) => {
38
+ const headerContent = jsxs(Fragment, {
39
+ children: [jsx(Bullet, {
40
+ sentiment: sentiment,
41
+ icon: sentiment === 'warning' || sentiment === 'danger' ? 'information-outline' : 'check'
42
+ }), jsx(StyledTextTitle, {
43
+ as: "h2",
44
+ variant: "headingSmallStronger",
45
+ children: title
46
+ })]
47
+ });
48
+ const contextValue = useMemo(() => ({
49
+ sentiment
50
+ }), [sentiment]);
51
+ return jsx(Modal, {
52
+ ariaLabel: ariaLabel,
53
+ className: className,
54
+ "data-testid": dataTestId,
55
+ disclosure: disclosure,
56
+ hideOnClickOutside: hideOnClickOutside,
57
+ hideOnEsc: hideOnEsc,
58
+ id: id,
59
+ isClosable: isClosable,
60
+ onBeforeClose: onBeforeClose,
61
+ onClose: onClose,
62
+ open: open,
63
+ placement: placement,
64
+ size: "xsmall",
65
+ children: typeof children === 'function' ? modalProps => jsxs(DialogContext.Provider, {
66
+ value: contextValue,
67
+ children: [headerContent, children(modalProps)]
68
+ }) : jsxs(DialogContext.Provider, {
69
+ value: contextValue,
70
+ children: [headerContent, children]
71
+ })
72
+ });
73
+ };
74
+
75
+ /**
76
+ * The Dialog component is used to show content on top of an overlay that requires user interaction.
77
+ * @experimental This component is experimental and may be subject to breaking changes in the future.
78
+ */
79
+ const Dialog = /*#__PURE__*/Object.assign(BaseDialog, {
80
+ Buttons: DialogButtons,
81
+ Button: DialogButton,
82
+ CancelButton: DialogCancelButton,
83
+ Stack: DialogStack,
84
+ Text: DialogText,
85
+ useDialogContext
86
+ });
87
+
88
+ export { BaseDialog, Dialog };
@@ -0,0 +1,21 @@
1
+ import { Button } from '../../Button/index.js';
2
+ import { useDialogContext } from '../Context.js';
3
+ import { jsx } from '@emotion/react/jsx-runtime';
4
+
5
+ const DialogButton = ({
6
+ children,
7
+ onClick,
8
+ disabled,
9
+ tooltip
10
+ }) => {
11
+ const context = useDialogContext();
12
+ return jsx(Button, {
13
+ sentiment: context.sentiment,
14
+ onClick: onClick,
15
+ disabled: disabled,
16
+ tooltip: tooltip,
17
+ children: children
18
+ });
19
+ };
20
+
21
+ export { DialogButton };
@@ -0,0 +1,14 @@
1
+ import { Stack } from '../../Stack/index.js';
2
+ import { jsxs } from '@emotion/react/jsx-runtime';
3
+
4
+ const DialogButtons = ({
5
+ secondaryButton,
6
+ primaryButton
7
+ }) => jsxs(Stack, {
8
+ direction: "row",
9
+ gap: 2,
10
+ justifyContent: "end",
11
+ children: [secondaryButton, primaryButton]
12
+ });
13
+
14
+ export { DialogButtons };
@@ -0,0 +1,14 @@
1
+ import { Button } from '../../Button/index.js';
2
+ import { jsx } from '@emotion/react/jsx-runtime';
3
+
4
+ const DialogCancelButton = ({
5
+ children,
6
+ onClick
7
+ }) => jsx(Button, {
8
+ variant: "outlined",
9
+ sentiment: "neutral",
10
+ onClick: onClick,
11
+ children: children
12
+ });
13
+
14
+ export { DialogCancelButton };
@@ -0,0 +1,11 @@
1
+ import { Stack } from '../../Stack/index.js';
2
+ import { jsx } from '@emotion/react/jsx-runtime';
3
+
4
+ const DialogStack = ({
5
+ children
6
+ }) => jsx(Stack, {
7
+ gap: 3,
8
+ children: children
9
+ });
10
+
11
+ export { DialogStack };
@@ -0,0 +1,12 @@
1
+ import { Text } from '../../Text/index.js';
2
+ import { jsx } from '@emotion/react/jsx-runtime';
3
+
4
+ const DialogText = ({
5
+ children
6
+ }) => jsx(Text, {
7
+ as: "p",
8
+ variant: "body",
9
+ children: children
10
+ });
11
+
12
+ export { DialogText };
@@ -1,5 +1,5 @@
1
1
  import _styled from '@emotion/styled/base';
2
- import { useState, useId, useCallback, useEffect } from 'react';
2
+ import { useState, useId, useCallback } from 'react';
3
3
  import { Button } from '../Button/index.js';
4
4
  import { Dialog } from './Dialog.js';
5
5
  import { Disclosure } from './Disclosure.js';
@@ -27,6 +27,7 @@ const Modal = ({
27
27
  isClosable = true,
28
28
  onClose,
29
29
  onBeforeClose,
30
+ open = false,
30
31
  opened = false,
31
32
  placement = 'center',
32
33
  preventBodyScroll = true,
@@ -38,7 +39,8 @@ const Modal = ({
38
39
  customDialogStyles,
39
40
  customDialogBackdropStyles
40
41
  }) => {
41
- const [visible, setVisible] = useState(opened);
42
+ // Used for disclosure usage only
43
+ const [visible, setVisible] = useState(false);
42
44
  const controlId = useId();
43
45
  const handleOpen = useCallback(() => {
44
46
  setVisible(true);
@@ -59,19 +61,16 @@ const Modal = ({
59
61
  }, []);
60
62
  const finalId = id ?? controlId;
61
63
  const finalSize = size ?? width;
62
- useEffect(() => {
63
- setVisible(opened);
64
- }, [opened]);
65
64
  return jsxs(Fragment, {
66
- children: [jsx(Disclosure, {
65
+ children: [disclosure ? jsx(Disclosure, {
67
66
  id: finalId,
68
67
  handleOpen: handleOpen,
69
68
  disclosure: disclosure,
70
69
  handleClose: handleClose,
71
70
  visible: visible,
72
71
  toggle: handleToggle
73
- }), jsx(Dialog, {
74
- open: visible,
72
+ }) : null, jsx(Dialog, {
73
+ open: visible || open || opened,
75
74
  placement: placement,
76
75
  size: finalSize,
77
76
  ariaLabel: ariaLabel,
@@ -91,7 +91,7 @@ const DropdownItem = /*#__PURE__*/_styled("button", {
91
91
  theme
92
92
  }) => theme.colors.primary.background, ";color:", ({
93
93
  theme
94
- }) => theme.colors.primary.text, ";cursor:'pointer';outline:none;}&[data-selected='true']{background-color:", ({
94
+ }) => theme.colors.primary.text, ";cursor:pointer;outline:none;}&[data-selected='true']{background-color:", ({
95
95
  theme
96
96
  }) => theme.colors.primary.background, ";}&[disabled]{background-color:", ({
97
97
  theme
@@ -118,13 +118,14 @@ const PopupFooter = /*#__PURE__*/_styled("div", {
118
118
  const StyledCheckbox = /*#__PURE__*/_styled(Checkbox, {
119
119
  target: "eeucz6c2"
120
120
  })(process.env.NODE_ENV === "production" ? {
121
- name: "10y07ze",
122
- styles: "width:100%;position:static;text-align:left;align-items:center"
121
+ name: "1l9xw77",
122
+ styles: "width:100%;position:static;text-align:left;align-items:center;pointer-events:none"
123
123
  } : {
124
- name: "10y07ze",
125
- styles: "width:100%;position:static;text-align:left;align-items:center",
124
+ name: "1l9xw77",
125
+ styles: "width:100%;position:static;text-align:left;align-items:center;pointer-events:none",
126
126
  toString: _EMOTION_STRINGIFIED_CSS_ERROR__
127
- });
127
+ }); // pointer-events: none prevents any error when using the checkbox in a form since it is an unnamed input
128
+
128
129
  const EmptyState = /*#__PURE__*/_styled(Stack, {
129
130
  target: "eeucz6c1"
130
131
  })("padding:", ({
@@ -246,10 +247,10 @@ const CreateDropdown = ({
246
247
  group
247
248
  });
248
249
  if (multiselect) {
249
- if (selectedData.selectedValues.includes(clickedOption)) {
250
- onChange?.(selectedData.selectedValues.filter(val => val !== clickedOption).map(val => val?.value));
250
+ if (selectedData.selectedValues.includes(clickedOption.value)) {
251
+ onChange?.(selectedData.selectedValues.filter(val => val !== clickedOption.value));
251
252
  } else {
252
- onChange?.([...selectedData.selectedValues, clickedOption].map(val => val?.value));
253
+ onChange?.([...selectedData.selectedValues, clickedOption.value]);
253
254
  }
254
255
  } else {
255
256
  onChange?.([clickedOption.value]);
@@ -284,12 +285,12 @@ const CreateDropdown = ({
284
285
  });
285
286
  if (!Array.isArray(options)) {
286
287
  if (selectedData.selectedGroups.includes(group)) {
287
- const newSelectedValues = [...selectedData.selectedValues].filter(selectedValue => !options[group].includes(selectedValue));
288
- onChange?.(newSelectedValues.map(value => value.value));
288
+ const newSelectedValues = [...selectedData.selectedValues].filter(selectedValue => !options[group].find(option => option.value === selectedValue));
289
+ onChange?.(newSelectedValues);
289
290
  } else {
290
291
  const newSelectedValues = [...selectedData.selectedValues];
291
- options[group].map(option => newSelectedValues.includes(option) || option.disabled ? null : newSelectedValues.push(option));
292
- onChange?.(newSelectedValues.map(value => value.value));
292
+ options[group].map(option => newSelectedValues.includes(option.value) || option.disabled ? null : newSelectedValues.push(option.value));
293
+ onChange?.(newSelectedValues);
293
294
  }
294
295
  }
295
296
  };
@@ -314,12 +315,12 @@ const CreateDropdown = ({
314
315
  id: "select-all",
315
316
  role: "option",
316
317
  onKeyDown: event => [' ', 'Enter'].includes(event.key) ? selectAllOptions() : null,
318
+ onClick: selectAllOptions,
317
319
  children: jsx(StyledCheckbox, {
318
320
  checked: selectedData.allSelected,
319
321
  disabled: false,
320
322
  value: "select-all",
321
323
  "data-testid": "select-all-checkbox",
322
- onChange: selectAllOptions,
323
324
  tabIndex: -1,
324
325
  children: jsxs(Stack, {
325
326
  direction: "column",
@@ -339,7 +340,7 @@ const CreateDropdown = ({
339
340
  })
340
341
  })
341
342
  })
342
- }) : null, Object.keys(displayedOptions).map(group => jsxs(Stack, {
343
+ }) : null, Object.keys(displayedOptions).map((group, index) => jsxs(Stack, {
343
344
  gap: 0.25,
344
345
  children: [displayedOptions[group].length > 0 ? jsx(DropdownGroupWrapper, {
345
346
  id: selectAllGroup ? 'items' : undefined,
@@ -353,11 +354,12 @@ const CreateDropdown = ({
353
354
  },
354
355
  "data-selectgroup": selectAllGroup,
355
356
  role: "group",
357
+ "data-testid": `group-${index}`,
358
+ onClick: () => selectAllGroup ? handleSelectGroup(group) : null,
356
359
  children: selectAllGroup ? jsx(StyledCheckbox, {
357
360
  checked: selectedData.selectedGroups.includes(group),
358
361
  disabled: false,
359
362
  value: group,
360
- onChange: () => handleSelectGroup(group),
361
363
  "data-testid": "select-group",
362
364
  tabIndex: -1,
363
365
  children: jsx(Text, {
@@ -376,12 +378,12 @@ const CreateDropdown = ({
376
378
  }) : null, jsxs(Stack, {
377
379
  id: "items",
378
380
  gap: "0.25",
379
- children: [displayedOptions[group].map((option, index) => jsx(DropdownItem, {
381
+ children: [displayedOptions[group].map((option, indexOption) => jsx(DropdownItem, {
380
382
  disabled: option.disabled,
381
- "data-selected": selectedData.selectedValues.includes(option) && !option.disabled,
383
+ "data-selected": selectedData.selectedValues.includes(option.value) && !option.disabled,
382
384
  "aria-label": option.value,
383
- "data-testid": `option-${index}`,
384
- id: `option-${index}`,
385
+ "data-testid": `option-${option.value}`,
386
+ id: `option-${indexOption}`,
385
387
  role: "option",
386
388
  onClick: () => {
387
389
  if (!option.disabled) {
@@ -391,19 +393,17 @@ const CreateDropdown = ({
391
393
  onKeyDown: event => [' ', 'Enter'].includes(event.key) ? handleClick(option, group) : null,
392
394
  ref: option.value === defaultSearchValue || option.searchText === defaultSearchValue ? focusedItemRef : null,
393
395
  children: multiselect ? jsx(StyledCheckbox, {
394
- checked: selectedData.selectedValues.includes(option) && !option.disabled,
396
+ checked: selectedData.selectedValues.includes(option.value) && !option.disabled,
395
397
  disabled: option.disabled,
396
398
  value: option.value,
397
399
  tabIndex: -1,
398
400
  children: jsx(DisplayOption, {
399
401
  option: option,
400
- multiselect: multiselect,
401
402
  descriptionDirection: descriptionDirection,
402
403
  optionalInfoPlacement: optionalInfoPlacement
403
404
  })
404
405
  }) : jsx(DisplayOption, {
405
406
  option: option,
406
- multiselect: multiselect,
407
407
  descriptionDirection: descriptionDirection,
408
408
  optionalInfoPlacement: optionalInfoPlacement
409
409
  })
@@ -432,12 +432,12 @@ const CreateDropdown = ({
432
432
  "data-testid": "select-all",
433
433
  role: "option",
434
434
  onKeyDown: event => [' ', 'Enter'].includes(event.key) ? selectAllOptions() : null,
435
+ onClick: selectAllOptions,
435
436
  children: jsx(StyledCheckbox, {
436
437
  checked: selectedData.allSelected,
437
438
  disabled: false,
438
439
  value: "select-all",
439
440
  "data-testid": "select-all-checkbox",
440
- onChange: selectAllOptions,
441
441
  tabIndex: -1,
442
442
  children: jsxs(Stack, {
443
443
  direction: "column",
@@ -464,32 +464,30 @@ const CreateDropdown = ({
464
464
  variant: "block"
465
465
  }) : displayedOptions.map((option, index) => jsx(DropdownItem, {
466
466
  disabled: option.disabled,
467
- "data-selected": selectedData.selectedValues.includes(option) && !option.disabled,
467
+ "data-selected": selectedData.selectedValues.includes(option.value) && !option.disabled,
468
468
  onClick: () => {
469
469
  if (!option.disabled) {
470
470
  handleClick(option);
471
471
  }
472
472
  },
473
473
  "aria-label": option.value,
474
- "data-testid": `option-${index}`,
474
+ "data-testid": `option-${option.value}`,
475
475
  id: `option-${index}`,
476
476
  role: "option",
477
477
  ref: option.value === defaultSearchValue || option.searchText === defaultSearchValue ? focusedItemRef : null,
478
478
  onKeyDown: event => [' ', 'Enter'].includes(event.key) ? handleClick(option) : null,
479
479
  children: multiselect ? jsx(StyledCheckbox, {
480
- checked: selectedData.selectedValues.includes(option) && !option.disabled,
480
+ checked: selectedData.selectedValues.includes(option.value) && !option.disabled,
481
481
  disabled: option.disabled,
482
482
  value: option.value,
483
483
  tabIndex: -1,
484
484
  children: jsx(DisplayOption, {
485
485
  option: option,
486
- multiselect: multiselect,
487
486
  descriptionDirection: descriptionDirection,
488
487
  optionalInfoPlacement: optionalInfoPlacement
489
488
  })
490
489
  }) : jsx(DisplayOption, {
491
490
  option: option,
492
- multiselect: multiselect,
493
491
  descriptionDirection: descriptionDirection,
494
492
  optionalInfoPlacement: optionalInfoPlacement
495
493
  })
@@ -16,7 +16,6 @@ const StyledInfo = /*#__PURE__*/_styled("div", {
16
16
  });
17
17
  const DisplayOption = ({
18
18
  option,
19
- multiselect,
20
19
  optionalInfoPlacement,
21
20
  descriptionDirection
22
21
  }) => {
@@ -25,7 +24,6 @@ const DisplayOption = ({
25
24
  gap: 0.5,
26
25
  direction: "row",
27
26
  justifyContent: "left",
28
- onClick: event => multiselect ? event.stopPropagation() : null,
29
27
  "data-testid": `option-stack-${option.value}`,
30
28
  children: jsxs(Stack, {
31
29
  gap: 0.5,
@@ -52,7 +50,6 @@ const DisplayOption = ({
52
50
  gap: 0.5,
53
51
  direction: "row",
54
52
  justifyContent: "space-between",
55
- onClick: event => multiselect ? event.stopPropagation() : null,
56
53
  alignItems: "baseline",
57
54
  "data-testid": `option-stack-${option.value}`,
58
55
  children: [jsxs(Stack, {
@@ -85,7 +82,6 @@ const DisplayOption = ({
85
82
  children: [option.optionalInfo ?? null, jsxs(Stack, {
86
83
  gap: 0.5,
87
84
  direction: "column",
88
- onClick: event => multiselect ? event.stopPropagation() : null,
89
85
  "data-testid": `option-stack-${option.value}`,
90
86
  children: [jsx(Text, {
91
87
  as: "span",
@@ -107,7 +103,6 @@ const DisplayOption = ({
107
103
  gap: 0.5,
108
104
  direction: "column",
109
105
  alignItems: "normal",
110
- onClick: event => multiselect ? event.stopPropagation() : null,
111
106
  "data-testid": `option-stack-${option.value}`,
112
107
  children: [jsxs(Stack, {
113
108
  gap: 0.5,
@@ -85,14 +85,14 @@ const SearchBarDropdown = ({
85
85
  clickedOption: closestOption,
86
86
  group: !Array.isArray(options) ? Object.keys(options).filter(group => options[group].includes(closestOption))[0] : undefined
87
87
  });
88
- onChange?.(selectedData.selectedValues.includes(closestOption) ? selectedData.selectedValues.map(val => val?.value) : [...selectedData.selectedValues, closestOption].map(val => val?.value));
88
+ onChange?.(selectedData.selectedValues.includes(closestOption.value) ? selectedData.selectedValues : [...selectedData.selectedValues, closestOption.value]);
89
89
  setSearchInput(closestOption.searchText ?? closestOption.value);
90
90
  } else {
91
91
  setSelectedData({
92
92
  type: 'selectOption',
93
93
  clickedOption: closestOption
94
94
  });
95
- onChange?.(selectedData.selectedValues.map(val => val?.value));
95
+ onChange?.(selectedData.selectedValues);
96
96
  }
97
97
  }
98
98
  }
@@ -6,6 +6,7 @@ import { Stack } from '../Stack/index.js';
6
6
  import { Tag } from '../Tag/index.js';
7
7
  import { Text } from '../Text/index.js';
8
8
  import { useSelectInput } from './SelectInputProvider.js';
9
+ import { findOptionInOptions } from './findOptionInOptions.js';
9
10
  import { INPUT_SIZE_HEIGHT, SIZES_TAG } from './types.js';
10
11
  import { jsxs, jsx } from '@emotion/react/jsx-runtime';
11
12
 
@@ -25,9 +26,7 @@ const StyledInputWrapper = /*#__PURE__*/_styled(Stack, {
25
26
  theme
26
27
  }) => theme.colors.neutral.background, ";border-radius:", ({
27
28
  theme
28
- }) => theme.radii.default, ";&:hover,:focus{border-color:", ({
29
- theme
30
- }) => theme.colors.primary.borderHover, ";outline:none;}&[data-readonly='true']{background:", ({
29
+ }) => theme.radii.default, ";&[data-readonly='true']{background:", ({
31
30
  theme
32
31
  }) => theme.colors.neutral.backgroundWeak, ";border-color:", ({
33
32
  theme
@@ -35,7 +34,7 @@ const StyledInputWrapper = /*#__PURE__*/_styled(Stack, {
35
34
  theme
36
35
  }) => theme.colors.neutral.backgroundDisabled, ";border-color:", ({
37
36
  theme
38
- }) => theme.colors.neutral.borderDisabled, ";cursor:not-allowed;}&[data-size='small']{height:", INPUT_SIZE_HEIGHT.small, "px;}&[data-size='medium']{height:", INPUT_SIZE_HEIGHT.medium, "px;}&[data-size='larger']{height:", INPUT_SIZE_HEIGHT.large, "px;}&[data-state='neutral']{border:1px solid ", ({
37
+ }) => theme.colors.neutral.borderDisabled, ";cursor:not-allowed;}&[data-size='small']{height:", INPUT_SIZE_HEIGHT.small, "px;}&[data-size='medium']{height:", INPUT_SIZE_HEIGHT.medium, "px;}&[data-size='large']{height:", INPUT_SIZE_HEIGHT.large, "px;}&[data-state='neutral']{border:1px solid ", ({
39
38
  theme
40
39
  }) => theme.colors.neutral.border, ";}&[data-state='success']{border:1px solid ", ({
41
40
  theme
@@ -45,7 +44,9 @@ const StyledInputWrapper = /*#__PURE__*/_styled(Stack, {
45
44
  theme
46
45
  }) => theme.colors.primary.border, ";}&:not([data-disabled='true']):not([data-readonly]):active{box-shadow:", ({
47
46
  theme
48
- }) => theme.shadows.focusPrimary, ";}&[data-dropdownvisible='true']{box-shadow:", ({
47
+ }) => theme.shadows.focusPrimary, ";}&:hover,:focus{border-color:", ({
48
+ theme
49
+ }) => theme.colors.primary.borderHover, ";outline:none;}&[data-dropdownvisible='true']{box-shadow:", ({
49
50
  theme
50
51
  }) => theme.shadows.focusPrimary, ";border-color:", ({
51
52
  theme
@@ -69,7 +70,7 @@ const StyledPlaceholder = /*#__PURE__*/_styled(Text, {
69
70
  }) => theme.typography.body.fontSize, ";display:flex;flex:1;align-self:center;&[data-disabled='true']{color:", ({
70
71
  theme
71
72
  }) => theme.colors.neutral.textWeakDisabled, ";}");
72
- const isValidSelectedValue = (selectedValue, options) => !Array.isArray(options) ? Object.keys(options).some(group => options[group].some(option => option === selectedValue && !option.disabled)) : options.some(option => option === selectedValue && !option.disabled);
73
+ const isValidSelectedValue = (selectedValue, options) => !Array.isArray(options) ? Object.keys(options).some(group => options[group].some(option => option.value === selectedValue && !option.disabled)) : options.some(option => option.value === selectedValue && !option.disabled);
73
74
  const DisplayValues = ({
74
75
  multiselect,
75
76
  refTag,
@@ -81,7 +82,8 @@ const DisplayValues = ({
81
82
  overflowAmount,
82
83
  setSelectedData,
83
84
  selectedData,
84
- size
85
+ size,
86
+ options
85
87
  }) => multiselect ? jsxs(Stack, {
86
88
  direction: "row",
87
89
  gap: "1",
@@ -98,8 +100,8 @@ const DisplayValues = ({
98
100
  type: 'selectOption',
99
101
  clickedOption: option
100
102
  });
101
- const newSelectedValues = selectedData.selectedValues?.filter(val => val !== option);
102
- onChange?.(newSelectedValues.map(val => val?.value));
103
+ const newSelectedValues = selectedData.selectedValues?.filter(val => val !== option.value);
104
+ onChange?.(newSelectedValues);
103
105
  } : undefined,
104
106
  children: option?.label
105
107
  }, option?.value)), overflowed ? jsxs(Tag, {
@@ -114,7 +116,7 @@ const DisplayValues = ({
114
116
  }) : jsx(Text, {
115
117
  as: "p",
116
118
  variant: size === 'large' ? 'body' : 'bodySmall',
117
- children: selectedData.selectedValues[0]?.label
119
+ children: selectedData.selectedValues[0] ? findOptionInOptions(options, selectedData.selectedValues[0])?.label : null
118
120
  });
119
121
  const SelectBar = ({
120
122
  size,
@@ -141,7 +143,13 @@ const SelectBar = ({
141
143
  const width = innerRef.current?.offsetWidth;
142
144
  const [overflowed, setOverflowed] = useState(false);
143
145
  const [overflowAmount, setOverflowAmount] = useState(0);
144
- const [nonOverflowedValues, setNonOverFlowedValues] = useState(selectedData.selectedValues[0] ? [selectedData.selectedValues[0]] : []);
146
+ const [nonOverflowedValues, setNonOverFlowedValues] = useState(() => {
147
+ if (selectedData.selectedValues[0]) {
148
+ const firstSelectOption = findOptionInOptions(options, selectedData.selectedValues[0]);
149
+ return firstSelectOption ? [firstSelectOption] : [];
150
+ }
151
+ return [];
152
+ });
145
153
  const state = useMemo(() => {
146
154
  if (error) {
147
155
  return 'danger';
@@ -158,14 +166,15 @@ const SelectBar = ({
158
166
  let computedNonOverflowedValues = [];
159
167
  const newSelectedValues = selectedData.selectedValues.filter(selectedValue => isValidSelectedValue(selectedValue, options));
160
168
  for (const selectedValue of newSelectedValues) {
161
- if (selectedValue && selectedValue.label && width && isValidSelectedValue(selectedValue, options)) {
162
- const lengthValue = selectedValue.value.length; // Find a better way to find the number of displayed characters?
169
+ const selectedOption = findOptionInOptions(options, selectedValue);
170
+ if (selectedOption?.label && width && isValidSelectedValue(selectedValue, options)) {
171
+ const lengthValue = selectedOption.value.length; // Find a better way to find the number of displayed characters?
163
172
  const totalTagWidth = SIZES_TAG.tagWidth + SIZES_TAG.letterWidth * lengthValue;
164
173
  if (totalTagWidth + tagsWidth > width - 100) {
165
174
  computedOverflowAmount += 1;
166
175
  setOverflowAmount(computedOverflowAmount);
167
176
  } else {
168
- computedNonOverflowedValues = [...computedNonOverflowedValues, selectedValue];
177
+ computedNonOverflowedValues = [...computedNonOverflowedValues, selectedOption];
169
178
  setNonOverFlowedValues(computedNonOverflowedValues);
170
179
  tagsWidth += totalTagWidth;
171
180
  }
@@ -224,7 +233,8 @@ const SelectBar = ({
224
233
  onChange: onChange,
225
234
  overflowed: overflowed,
226
235
  overflowAmount: overflowAmount,
227
- size: size
236
+ size: size,
237
+ options: options
228
238
  }) : jsx(StyledPlaceholder, {
229
239
  as: "p",
230
240
  variant: size === 'large' ? 'body' : 'bodySmall',
@@ -1,4 +1,4 @@
1
- import { useState, useReducer, useMemo, createContext, useContext } from 'react';
1
+ import { useMemo, useState, useReducer, createContext, useContext } from 'react';
2
2
  import { jsx } from '@emotion/react/jsx-runtime';
3
3
 
4
4
  const SelectInputContext = /*#__PURE__*/createContext({
@@ -32,23 +32,36 @@ const SelectInputProvider = ({
32
32
  numberOfOptions,
33
33
  children
34
34
  }) => {
35
- const defaultValue = value ? [value] : [];
35
+ const currentValue = useMemo(() => {
36
+ if (value) {
37
+ if (Array.isArray(value)) {
38
+ return value;
39
+ }
40
+ return [value];
41
+ }
42
+ return [];
43
+ }, [value]);
44
+ const selectedGroups = useMemo(() => {
45
+ if (Array.isArray(options)) {
46
+ return [];
47
+ }
48
+ return Object.keys(options).filter(group => options[group].every(groupOption => currentValue.includes(groupOption.value)));
49
+ }, [currentValue, options]);
36
50
  const [displayedOptions, setDisplayedOptions] = useState(options);
37
51
  const [isDropdownVisible, setIsDropdownVisible] = useState(false);
38
52
  const [searchInput, setSearchInput] = useState('');
39
- const allValues = [];
40
- const allGroups = [];
41
- if (!Array.isArray(options)) {
42
- Object.keys(options).map(group => options[group].map(option => {
43
- if (!option.disabled) {
44
- allValues.push(option);
45
- }
46
- return null;
47
- }));
48
- Object.keys(options).forEach(group => allGroups.push(group));
49
- } else {
50
- options.map(option => allValues.push(option));
51
- }
53
+ const allValues = useMemo(() => {
54
+ if (!Array.isArray(options)) {
55
+ return Object.keys(options).map(group => options[group].filter(option => !option.disabled)).flat();
56
+ }
57
+ return options;
58
+ }, [options]);
59
+ const allGroups = useMemo(() => {
60
+ if (!Array.isArray(options)) {
61
+ return Object.keys(options);
62
+ }
63
+ return [];
64
+ }, [options]);
52
65
  const reducer = (state, action) => {
53
66
  switch (action.type) {
54
67
  case 'selectAll':
@@ -60,7 +73,7 @@ const SelectInputProvider = ({
60
73
  };
61
74
  }
62
75
  return {
63
- selectedValues: allValues,
76
+ selectedValues: allValues.map(option => option.value),
64
77
  allSelected: true,
65
78
  selectedGroups: allGroups
66
79
  };
@@ -68,13 +81,13 @@ const SelectInputProvider = ({
68
81
  if (!Array.isArray(options)) {
69
82
  if (state.selectedGroups.includes(action.selectedGroup)) {
70
83
  return {
71
- selectedValues: [...state.selectedValues].filter(selectedValue => !options[action.selectedGroup].includes(selectedValue)),
84
+ selectedValues: [...state.selectedValues].filter(selectedValue => !options[action.selectedGroup].find(option => option.value === selectedValue)),
72
85
  allSelected: false,
73
86
  selectedGroups: state.selectedGroups.filter(selectedGroup => selectedGroup !== action.selectedGroup)
74
87
  };
75
88
  }
76
89
  const newSelectedValues = [...state.selectedValues];
77
- options[action.selectedGroup].map(option => newSelectedValues.includes(option) || option.disabled ? null : newSelectedValues.push(option));
90
+ options[action.selectedGroup].map(option => newSelectedValues.find(aValue => aValue === option.value) || option.disabled ? null : newSelectedValues.push(option.value));
78
91
  return {
79
92
  selectedValues: newSelectedValues,
80
93
  allSelected: newSelectedValues.length === numberOfOptions,
@@ -84,21 +97,21 @@ const SelectInputProvider = ({
84
97
  return state;
85
98
  case 'selectOption':
86
99
  if (multiselect) {
87
- if (state.selectedValues.includes(action.clickedOption)) {
100
+ if (state.selectedValues.includes(action.clickedOption.value)) {
88
101
  return {
89
- selectedValues: state.selectedValues.filter(val => val !== action.clickedOption),
102
+ selectedValues: state.selectedValues.filter(val => val !== action.clickedOption.value),
90
103
  allSelected: false,
91
104
  selectedGroups: action.group && state.selectedGroups.includes(action.group) ? state.selectedGroups.filter(selectedGroup => selectedGroup !== action.group) : []
92
105
  };
93
106
  }
94
107
  return {
95
- selectedValues: [...state.selectedValues, action.clickedOption],
108
+ selectedValues: [...state.selectedValues, action.clickedOption.value],
96
109
  allSelected: state.selectedValues.length + 1 === numberOfOptions,
97
- selectedGroups: !Array.isArray(options) && action.group && options[action.group].every(option => [...state.selectedValues, action.clickedOption].includes(option) || option.disabled) ? [...state.selectedGroups, action.group] : state.selectedGroups
110
+ selectedGroups: !Array.isArray(options) && action.group && options[action.group].every(option => [...state.selectedValues, action.clickedOption.value].includes(option.value) || option.disabled) ? [...state.selectedGroups, action.group] : state.selectedGroups
98
111
  };
99
112
  }
100
113
  return {
101
- selectedValues: [action.clickedOption],
114
+ selectedValues: [action.clickedOption.value],
102
115
  allSelected: false,
103
116
  selectedGroups: state.selectedGroups
104
117
  };
@@ -115,9 +128,9 @@ const SelectInputProvider = ({
115
128
  allSelected: state.allSelected,
116
129
  selectedValues: state.selectedValues.filter(selectedValue => {
117
130
  if (!Array.isArray(options)) {
118
- return Object.keys(options).some(group => options[group].some(option => option === selectedValue && !option.disabled));
131
+ return Object.keys(options).some(group => options[group].some(option => option.value === selectedValue && !option.disabled));
119
132
  }
120
- return options.some(option => option === selectedValue && !option.disabled);
133
+ return options.some(option => option.value === selectedValue && !option.disabled);
121
134
  })
122
135
  };
123
136
  default:
@@ -125,9 +138,9 @@ const SelectInputProvider = ({
125
138
  }
126
139
  };
127
140
  const [selectedData, setSelectedData] = useReducer(reducer, {
128
- selectedValues: defaultValue,
141
+ selectedValues: currentValue,
129
142
  allSelected: false,
130
- selectedGroups: []
143
+ selectedGroups
131
144
  });
132
145
  const providerValue = useMemo(() => ({
133
146
  onSearch: setDisplayedOptions,
@@ -0,0 +1,11 @@
1
+ const findOptionInOptions = (options, optionValue) => {
2
+ let flatOptions = [];
3
+ if (!Array.isArray(options)) {
4
+ flatOptions = Object.keys(options).map(group => options[group]).flat();
5
+ } else {
6
+ flatOptions = options;
7
+ }
8
+ return flatOptions.find(option => option.value === optionValue);
9
+ };
10
+
11
+ export { findOptionInOptions };
@@ -100,7 +100,7 @@ const SelectInputV2 = ({
100
100
  as: "label",
101
101
  variant: size === 'large' ? 'bodyStrong' : 'bodySmallStrong',
102
102
  children: label
103
- }) : null, required ? jsx(Icon, {
103
+ }) : null, required && label ? jsx(Icon, {
104
104
  name: "asterisk",
105
105
  sentiment: "danger",
106
106
  size: 8
@@ -117,7 +117,7 @@ const SelectableCardGroup = ({
117
117
  }) : null]
118
118
  }) : null, jsx(Row, {
119
119
  gap: 2,
120
- templateColumns: `repeat(${columns}, auto)`,
120
+ templateColumns: `repeat(${columns}, minmax(0, 1fr))`,
121
121
  children: children
122
122
  })]
123
123
  })
package/dist/src/index.js CHANGED
@@ -20,6 +20,7 @@ export { Carousel } from './components/Carousel/index.js';
20
20
  export { Checkbox } from './components/Checkbox/index.js';
21
21
  export { CopyButton } from './components/CopyButton/index.js';
22
22
  export { DateInput } from './components/DateInput/index.js';
23
+ export { Dialog } from './components/Dialog/index.js';
23
24
  export { EmptyState } from './components/EmptyState/index.js';
24
25
  export { Expandable } from './components/Expandable/index.js';
25
26
  export { LineChart } from './components/LineChart/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultraviolet/ui",
3
- "version": "1.48.1",
3
+ "version": "1.49.0",
4
4
  "description": "Ultraviolet UI",
5
5
  "homepage": "https://github.com/scaleway/ultraviolet#readme",
6
6
  "repository": {
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "engines": {
21
21
  "node": ">=18.x",
22
- "pnpm": ">=8.0.0"
22
+ "pnpm": ">=9.x"
23
23
  },
24
24
  "os": [
25
25
  "darwin",
@@ -56,7 +56,7 @@
56
56
  "@nivo/line": "0.80.0",
57
57
  "@nivo/pie": "0.80.0",
58
58
  "@nivo/scales": "0.80.0",
59
- "@scaleway/random-name": "5.0.1",
59
+ "@scaleway/random-name": "5.0.2",
60
60
  "@scaleway/use-media": "3.0.1",
61
61
  "deepmerge": "4.3.1",
62
62
  "react-datepicker": "4.25.0",