@true-engineering/true-react-common-ui-kit 3.25.1 → 3.26.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.
Files changed (93) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +11 -0
  3. package/dist/components/Button/Button.d.ts +2 -2
  4. package/dist/components/WithPopup/WithPopup.d.ts +13 -14
  5. package/dist/components/WithPopup/WithPopup.styles.d.ts +1 -1
  6. package/dist/components/WithPopup/types.d.ts +11 -0
  7. package/dist/true-react-common-ui-kit.js +156 -105
  8. package/dist/true-react-common-ui-kit.js.map +1 -1
  9. package/dist/true-react-common-ui-kit.umd.cjs +154 -103
  10. package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
  11. package/dist/types.d.ts +20 -0
  12. package/package.json +1 -1
  13. package/src/components/AccountInfo/AccountInfo.stories.tsx +32 -32
  14. package/src/components/AccountInfo/AccountInfo.tsx +80 -80
  15. package/src/components/AddButton/AddButton.stories.tsx +21 -21
  16. package/src/components/AddButton/AddButton.tsx +52 -52
  17. package/src/components/Button/Button.tsx +129 -129
  18. package/src/components/Colors/Colors.stories.tsx +7 -7
  19. package/src/components/DateInput/DateInput.tsx +90 -90
  20. package/src/components/DateInput/constants.ts +2 -2
  21. package/src/components/Description/Description.stories.tsx +27 -27
  22. package/src/components/Description/Description.tsx +61 -61
  23. package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +166 -166
  24. package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.tsx +210 -210
  25. package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +177 -177
  26. package/src/components/Flag/Flag.stories.tsx +29 -29
  27. package/src/components/Flag/Flag.tsx +26 -26
  28. package/src/components/Flag/augment.d.ts +1 -1
  29. package/src/components/FlexibleTable/components/FlexibleTableCell/FlexibleTableCell.styles.ts +38 -38
  30. package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.styles.ts +25 -25
  31. package/src/components/FlexibleTable/helpers.ts +13 -13
  32. package/src/components/Icon/Icon.stories.tsx +86 -86
  33. package/src/components/Icon/complexIcons/augment.d.ts +1 -1
  34. package/src/components/Icon/complexIcons/avatarGreen.svg +57 -57
  35. package/src/components/Icon/complexIcons/index.ts +1 -1
  36. package/src/components/IncrementInput/IncrementInput.tsx +105 -105
  37. package/src/components/Input/Input.tsx +297 -297
  38. package/src/components/Input/types.ts +32 -32
  39. package/src/components/List/List.stories.tsx +70 -70
  40. package/src/components/List/List.tsx +33 -33
  41. package/src/components/List/components/ListItem/ListItem.tsx +57 -57
  42. package/src/components/Modal/Modal.stories.tsx +105 -105
  43. package/src/components/MultiSelect/MultiSelect.stories.tsx +46 -46
  44. package/src/components/MultiSelect/MultiSelect.tsx +106 -106
  45. package/src/components/MultiSelect/components/MultiSelectInput/MultiSelectInput.tsx +53 -53
  46. package/src/components/NewMoreMenu/NewMoreMenu.tsx +8 -9
  47. package/src/components/Notification/Notification.stories.tsx +46 -46
  48. package/src/components/Notification/Notification.tsx +69 -69
  49. package/src/components/NumberInput/NumberInput.tsx +137 -137
  50. package/src/components/NumberInput/index.ts +1 -1
  51. package/src/components/PhoneInput/PhoneInput.tsx +214 -214
  52. package/src/components/PhoneInput/components/PhoneInputCountryList/PhoneInputCountryList.tsx +155 -155
  53. package/src/components/PhoneInput/types.ts +16 -16
  54. package/src/components/RadioButton/RadioButton.stories.tsx +46 -46
  55. package/src/components/RadioButton/RadioButton.tsx +57 -57
  56. package/src/components/ScrollIntoViewIfNeeded/index.ts +1 -1
  57. package/src/components/Select/Select.stories.tsx +235 -235
  58. package/src/components/Select/constants.ts +2 -2
  59. package/src/components/Select/types.ts +1 -1
  60. package/src/components/Selector/Selector.stories.tsx +62 -62
  61. package/src/components/Selector/Selector.tsx +115 -115
  62. package/src/components/Selector/index.ts +2 -2
  63. package/src/components/Selector/types.ts +12 -12
  64. package/src/components/Skeleton/Skeleton.stories.tsx +19 -19
  65. package/src/components/SmartInput/SmartInput.tsx +134 -134
  66. package/src/components/Status/Status.stories.tsx +73 -73
  67. package/src/components/Status/Status.styles.ts +143 -143
  68. package/src/components/Status/Status.tsx +49 -49
  69. package/src/components/Status/constants.ts +11 -11
  70. package/src/components/Status/index.ts +3 -3
  71. package/src/components/Status/types.ts +5 -5
  72. package/src/components/Switch/Switch.stories.tsx +40 -40
  73. package/src/components/Switch/Switch.tsx +75 -75
  74. package/src/components/TextWithInfo/TextWithInfo.stories.tsx +53 -53
  75. package/src/components/TextWithInfo/TextWithInfo.tsx +62 -62
  76. package/src/components/TextWithTooltip/TextWithTooltip.stories.tsx +58 -58
  77. package/src/components/ThemedPreloader/ThemedPreloader.stories.tsx +41 -41
  78. package/src/components/ThemedPreloader/ThemedPreloader.tsx +54 -54
  79. package/src/components/ThemedPreloader/components/DefaultPreloader/index.ts +1 -1
  80. package/src/components/Toaster/Toaster.stories.tsx +30 -30
  81. package/src/components/Tooltip/Tooltip.stories.tsx +19 -19
  82. package/src/components/Tooltip/Tooltip.tsx +35 -35
  83. package/src/components/Tooltip/types.ts +1 -1
  84. package/src/components/WithPopup/WithPopup.stories.tsx +36 -15
  85. package/src/components/WithPopup/WithPopup.styles.ts +6 -8
  86. package/src/components/WithPopup/WithPopup.tsx +64 -35
  87. package/src/components/WithPopup/types.ts +14 -0
  88. package/src/helpers/popper-helpers.ts +17 -17
  89. package/src/hooks/use-dropdown.ts +84 -84
  90. package/src/hooks/use-is-mounted.ts +15 -15
  91. package/src/theme/helpers.ts +76 -76
  92. package/src/types.ts +28 -0
  93. package/src/vite-env.d.ts +1 -1
@@ -1,54 +1,54 @@
1
- import { FC } from 'react';
2
- import clsx from 'clsx';
3
- import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
4
- import { addDataAttributes } from '../../helpers';
5
- import { useTweakStyles } from '../../hooks';
6
- import { ICommonProps } from '../../types';
7
- import { SvgPreloader, DotsPreloader } from './components';
8
- import { IPreloaderSvgType } from './types';
9
- import { useStyles, IThemedPreloaderStyles } from './ThemedPreloader.styles';
10
-
11
- export interface IThemedPreloaderProps extends ICommonProps<IThemedPreloaderStyles> {
12
- /** @default 'default' */
13
- type?: 'dots' | IPreloaderSvgType;
14
- /** @default false */
15
- useCurrentColor?: boolean;
16
- }
17
-
18
- export const ThemedPreloader: FC<IThemedPreloaderProps> = ({
19
- type = 'default',
20
- useCurrentColor = false,
21
- data,
22
- testId,
23
- tweakStyles,
24
- }) => {
25
- const classes = useStyles({ theme: tweakStyles });
26
-
27
- const tweakDotsPreloaderStyles = useTweakStyles({
28
- tweakStyles,
29
- className: 'tweakDotsPreloader',
30
- currentComponentName: 'ThemedPreloader',
31
- });
32
-
33
- const tweakSvgPreloaderStyles = useTweakStyles({
34
- tweakStyles,
35
- className: 'tweakSvgPreloader',
36
- currentComponentName: 'ThemedPreloader',
37
- });
38
-
39
- return (
40
- <div
41
- className={clsx(classes.root, classes[type], {
42
- [classes.currentColor]: useCurrentColor,
43
- })}
44
- {...addDataTestId(testId)}
45
- {...addDataAttributes(data)}
46
- >
47
- {type === 'dots' ? (
48
- <DotsPreloader tweakStyles={tweakDotsPreloaderStyles} />
49
- ) : (
50
- <SvgPreloader type={type} tweakStyles={tweakSvgPreloaderStyles} />
51
- )}
52
- </div>
53
- );
54
- };
1
+ import { FC } from 'react';
2
+ import clsx from 'clsx';
3
+ import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
4
+ import { addDataAttributes } from '../../helpers';
5
+ import { useTweakStyles } from '../../hooks';
6
+ import { ICommonProps } from '../../types';
7
+ import { SvgPreloader, DotsPreloader } from './components';
8
+ import { IPreloaderSvgType } from './types';
9
+ import { useStyles, IThemedPreloaderStyles } from './ThemedPreloader.styles';
10
+
11
+ export interface IThemedPreloaderProps extends ICommonProps<IThemedPreloaderStyles> {
12
+ /** @default 'default' */
13
+ type?: 'dots' | IPreloaderSvgType;
14
+ /** @default false */
15
+ useCurrentColor?: boolean;
16
+ }
17
+
18
+ export const ThemedPreloader: FC<IThemedPreloaderProps> = ({
19
+ type = 'default',
20
+ useCurrentColor = false,
21
+ data,
22
+ testId,
23
+ tweakStyles,
24
+ }) => {
25
+ const classes = useStyles({ theme: tweakStyles });
26
+
27
+ const tweakDotsPreloaderStyles = useTweakStyles({
28
+ tweakStyles,
29
+ className: 'tweakDotsPreloader',
30
+ currentComponentName: 'ThemedPreloader',
31
+ });
32
+
33
+ const tweakSvgPreloaderStyles = useTweakStyles({
34
+ tweakStyles,
35
+ className: 'tweakSvgPreloader',
36
+ currentComponentName: 'ThemedPreloader',
37
+ });
38
+
39
+ return (
40
+ <div
41
+ className={clsx(classes.root, classes[type], {
42
+ [classes.currentColor]: useCurrentColor,
43
+ })}
44
+ {...addDataTestId(testId)}
45
+ {...addDataAttributes(data)}
46
+ >
47
+ {type === 'dots' ? (
48
+ <DotsPreloader tweakStyles={tweakDotsPreloaderStyles} />
49
+ ) : (
50
+ <SvgPreloader type={type} tweakStyles={tweakSvgPreloaderStyles} />
51
+ )}
52
+ </div>
53
+ );
54
+ };
@@ -1 +1 @@
1
- export * from './DefaultPreloader';
1
+ export * from './DefaultPreloader';
@@ -1,30 +1,30 @@
1
- import { ComponentStory, ComponentMeta } from '@storybook/react';
2
- import { Button } from '../Button';
3
- import { Toaster } from './Toaster';
4
-
5
- const types = ['error', 'info', 'warning', 'ok', 'not-ok'];
6
-
7
- export default {
8
- title: 'Feedback/Toaster',
9
- component: Toaster,
10
- args: {
11
- title: 'Произошла очень страшная ошибка',
12
- text: 'Мы даже не знаем, чем вам помочь!',
13
- type: types[0],
14
- timeout: 7000,
15
- hasCloseButton: false,
16
- shouldCloseOnClick: false,
17
- },
18
- argTypes: {
19
- type: { control: 'inline-radio', options: types },
20
- },
21
- parameters: {
22
- controls: { exclude: ['onTimeEnd', 'onClose', 'data', 'tweakStyles'] },
23
- },
24
- } as ComponentMeta<typeof Toaster>;
25
-
26
- export const Default: ComponentStory<typeof Toaster> = (args) => (
27
- <Toaster {...args} onTimeEnd={() => console.log(1)} onClose={() => alert('closed')}>
28
- <Button size="m">Нажмите</Button>
29
- </Toaster>
30
- );
1
+ import { ComponentStory, ComponentMeta } from '@storybook/react';
2
+ import { Button } from '../Button';
3
+ import { Toaster } from './Toaster';
4
+
5
+ const types = ['error', 'info', 'warning', 'ok', 'not-ok'];
6
+
7
+ export default {
8
+ title: 'Feedback/Toaster',
9
+ component: Toaster,
10
+ args: {
11
+ title: 'Произошла очень страшная ошибка',
12
+ text: 'Мы даже не знаем, чем вам помочь!',
13
+ type: types[0],
14
+ timeout: 7000,
15
+ hasCloseButton: false,
16
+ shouldCloseOnClick: false,
17
+ },
18
+ argTypes: {
19
+ type: { control: 'inline-radio', options: types },
20
+ },
21
+ parameters: {
22
+ controls: { exclude: ['onTimeEnd', 'onClose', 'data', 'tweakStyles'] },
23
+ },
24
+ } as ComponentMeta<typeof Toaster>;
25
+
26
+ export const Default: ComponentStory<typeof Toaster> = (args) => (
27
+ <Toaster {...args} onTimeEnd={() => console.log(1)} onClose={() => alert('closed')}>
28
+ <Button size="m">Нажмите</Button>
29
+ </Toaster>
30
+ );
@@ -1,19 +1,19 @@
1
- import { ComponentStory, ComponentMeta } from '@storybook/react';
2
- import { Tooltip } from './Tooltip';
3
-
4
- export default {
5
- title: 'Data Display/Tooltip',
6
- component: Tooltip,
7
- args: {
8
- text: 'Tooltip Text',
9
- view: 'tooltip',
10
- type: 'info',
11
- },
12
- argTypes: {
13
- text: { control: 'text' },
14
- view: { control: 'inline-radio', options: ['tooltip', 'hint'] },
15
- type: { control: 'inline-radio', options: ['info', 'error'] },
16
- },
17
- } as ComponentMeta<typeof Tooltip>;
18
-
19
- export const Default: ComponentStory<typeof Tooltip> = (args) => <Tooltip {...args} />;
1
+ import { ComponentStory, ComponentMeta } from '@storybook/react';
2
+ import { Tooltip } from './Tooltip';
3
+
4
+ export default {
5
+ title: 'Data Display/Tooltip',
6
+ component: Tooltip,
7
+ args: {
8
+ text: 'Tooltip Text',
9
+ view: 'tooltip',
10
+ type: 'info',
11
+ },
12
+ argTypes: {
13
+ text: { control: 'text' },
14
+ view: { control: 'inline-radio', options: ['tooltip', 'hint'] },
15
+ type: { control: 'inline-radio', options: ['info', 'error'] },
16
+ },
17
+ } as ComponentMeta<typeof Tooltip>;
18
+
19
+ export const Default: ComponentStory<typeof Tooltip> = (args) => <Tooltip {...args} />;
@@ -1,35 +1,35 @@
1
- import { FC, ReactNode } from 'react';
2
- import clsx from 'clsx';
3
- import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
4
- import { addDataAttributes } from '../../helpers';
5
- import { ICommonProps } from '../../types';
6
- import { useStyles, ITooltipStyles } from './Tooltip.styles';
7
-
8
- export interface ITooltipProps extends ICommonProps<ITooltipStyles> {
9
- text: ReactNode;
10
- /** @default 'tooltip' */
11
- view?: 'tooltip' | 'hint';
12
- /** @default 'info' */
13
- type?: 'info' | 'error';
14
- }
15
-
16
- export const Tooltip: FC<ITooltipProps> = ({
17
- text,
18
- view = 'tooltip',
19
- type = 'info',
20
- data,
21
- testId,
22
- tweakStyles,
23
- }) => {
24
- const classes = useStyles({ theme: tweakStyles });
25
-
26
- return (
27
- <div
28
- className={clsx(classes.root, classes[view], classes[type])}
29
- {...addDataTestId(testId)}
30
- {...addDataAttributes(data)}
31
- >
32
- {text}
33
- </div>
34
- );
35
- };
1
+ import { FC, ReactNode } from 'react';
2
+ import clsx from 'clsx';
3
+ import { addDataTestId } from '@true-engineering/true-react-platform-helpers';
4
+ import { addDataAttributes } from '../../helpers';
5
+ import { ICommonProps } from '../../types';
6
+ import { useStyles, ITooltipStyles } from './Tooltip.styles';
7
+
8
+ export interface ITooltipProps extends ICommonProps<ITooltipStyles> {
9
+ text: ReactNode;
10
+ /** @default 'tooltip' */
11
+ view?: 'tooltip' | 'hint';
12
+ /** @default 'info' */
13
+ type?: 'info' | 'error';
14
+ }
15
+
16
+ export const Tooltip: FC<ITooltipProps> = ({
17
+ text,
18
+ view = 'tooltip',
19
+ type = 'info',
20
+ data,
21
+ testId,
22
+ tweakStyles,
23
+ }) => {
24
+ const classes = useStyles({ theme: tweakStyles });
25
+
26
+ return (
27
+ <div
28
+ className={clsx(classes.root, classes[view], classes[type])}
29
+ {...addDataTestId(testId)}
30
+ {...addDataAttributes(data)}
31
+ >
32
+ {text}
33
+ </div>
34
+ );
35
+ };
@@ -1 +1 @@
1
- export type ITooltipType = 'info' | 'warning';
1
+ export type ITooltipType = 'info' | 'warning';
@@ -1,6 +1,7 @@
1
+ import { doNothing } from '@true-engineering/true-react-platform-helpers';
1
2
  import { ComponentStory } from '@storybook/react';
2
3
  import { Button } from '../Button';
3
- import { List } from '../List';
4
+ import { IListItem, List } from '../List';
4
5
  import { Tooltip } from '../Tooltip';
5
6
  import { WithPopup } from './WithPopup';
6
7
 
@@ -29,6 +30,21 @@ export default {
29
30
  },
30
31
  };
31
32
 
33
+ const items: IListItem[] = [
34
+ {
35
+ item: 'Copy',
36
+ onClick: doNothing,
37
+ },
38
+ {
39
+ item: 'Paste',
40
+ onClick: doNothing,
41
+ },
42
+ {
43
+ item: 'Remove',
44
+ onClick: doNothing,
45
+ },
46
+ ];
47
+
32
48
  const Template: ComponentStory<typeof WithPopup> = (args) => (
33
49
  <div
34
50
  style={{
@@ -41,23 +57,28 @@ const Template: ComponentStory<typeof WithPopup> = (args) => (
41
57
  height: 400,
42
58
  }}
43
59
  >
60
+ <div onClick={() => console.log('parent onclick')}>
61
+ <WithPopup
62
+ {...args}
63
+ trigger={(props) => (
64
+ <Button icon="plus" isFullWidth {...props}>
65
+ {props.isActive ? 'Click (Active)' : 'Click (Not Active)'}
66
+ </Button>
67
+ )}
68
+ >
69
+ {({ onClose }) => <List items={items} onClick={onClose} />}
70
+ </WithPopup>
71
+ </div>
44
72
  <WithPopup
45
73
  {...args}
46
74
  eventType="hover"
47
- trigger={({ isActive }) => <Button isActive={isActive}>Button</Button>}
75
+ trigger={
76
+ <Button icon="plus" isDisabled={args.isDisabled} isFullWidth>
77
+ Hover
78
+ </Button>
79
+ }
48
80
  >
49
- <Tooltip text="Тултип" view="hint" />
50
- </WithPopup>
51
- <WithPopup {...args} eventType="click" trigger={<Button>Button</Button>}>
52
- {({ onClose }) => (
53
- <List
54
- items={[
55
- { item: 'Create Item', onClick: () => null },
56
- { item: 'Copy Item', onClick: () => null },
57
- ]}
58
- onClick={onClose}
59
- />
60
- )}
81
+ <Tooltip text="Tooltip" />
61
82
  </WithPopup>
62
83
  </div>
63
84
  );
@@ -65,7 +86,7 @@ const Template: ComponentStory<typeof WithPopup> = (args) => (
65
86
  export const Default = Template.bind({});
66
87
 
67
88
  Default.args = {
68
- canBeFlipped: false,
89
+ canBeFlipped: true,
69
90
  isDisabled: false,
70
91
  shouldRenderInBody: true,
71
92
  shouldHideOnScroll: false,
@@ -1,20 +1,18 @@
1
1
  import { createThemedStyles, ITweakStyles } from '../../theme';
2
2
 
3
3
  export const useStyles = createThemedStyles('WithPopup', {
4
- root: {},
5
-
6
- disabled: {
7
- '& > $trigger': {
8
- cursor: 'default',
9
- },
10
- },
11
-
12
4
  trigger: {
5
+ width: 'fit-content',
13
6
  cursor: 'pointer',
14
7
  },
15
8
 
9
+ disabled: {
10
+ cursor: 'default',
11
+ },
12
+
16
13
  popup: {
17
14
  zIndex: 5,
15
+ outline: 'none',
18
16
  },
19
17
 
20
18
  animationEnd: {},
@@ -1,6 +1,10 @@
1
- import { FC, ReactNode, useState, MouseEvent } from 'react';
1
+ import { FC, useState } from 'react';
2
2
  import clsx from 'clsx';
3
- import { addDataTestId, isFunction } from '@true-engineering/true-react-platform-helpers';
3
+ import {
4
+ addDataTestId,
5
+ applyAction,
6
+ isFunction,
7
+ } from '@true-engineering/true-react-platform-helpers';
4
8
  import {
5
9
  autoUpdate,
6
10
  useFloating,
@@ -16,23 +20,26 @@ import {
16
20
  useTransitionStatus,
17
21
  OffsetOptions,
18
22
  UseHoverProps,
23
+ safePolygon,
24
+ useFocus,
19
25
  } from '@floating-ui/react';
20
26
  import { addDataAttributes } from '../../helpers';
21
- import { ICommonProps } from '../../types';
27
+ import { ICommonProps, IRenderNode } from '../../types';
22
28
  import { DEFAULT_OFFSET } from './constants';
23
- import { IPopupEventType } from './types';
29
+ import {
30
+ IPopupEventType,
31
+ IWithPopupChildrenProps,
32
+ IWithPopupToggleEvent,
33
+ IWithPopupTriggerProps,
34
+ } from './types';
24
35
  import { useStyles, IWithPopupStyles } from './WithPopup.styles';
25
36
 
26
37
  export interface IWithPopupProps extends ICommonProps<IWithPopupStyles> {
27
- trigger: ReactNode | FC<{ isActive: boolean }>;
28
- children: ReactNode | FC<{ onClose: () => void }>;
38
+ trigger: IRenderNode<IWithPopupTriggerProps>;
39
+ children: IRenderNode<IWithPopupChildrenProps>;
29
40
  middlewares?: Middleware[];
30
41
  /** @default eventType === 'click' ? 'bottom-end' : 'top' */
31
42
  placement?: Placement;
32
- /** @default false */
33
- shouldHideOnScroll?: boolean;
34
- /** @default false */
35
- shouldRenderInBody?: boolean;
36
43
  /** @default 'click' */
37
44
  eventType?: IPopupEventType;
38
45
  /** @default 0 */
@@ -40,10 +47,17 @@ export interface IWithPopupProps extends ICommonProps<IWithPopupStyles> {
40
47
  /** @default 6 */
41
48
  popupOffset?: OffsetOptions;
42
49
  /** @default false */
50
+ shouldHideOnScroll?: boolean;
51
+ /** @default true */
52
+ shouldRenderInBody?: boolean;
53
+ /** Должен ли WithPopup рендерить свой div-wrapper в качестве триггера
54
+ * @default true, if eventType === hover */
55
+ isTriggerWrapped?: boolean;
56
+ /** @default true */
43
57
  canBeFlipped?: boolean;
44
58
  /** @default false */
45
59
  isDisabled?: boolean;
46
- onToggle?: (isActive: boolean) => void;
60
+ onToggle?: (isActive: boolean, event?: IWithPopupToggleEvent) => void;
47
61
  }
48
62
 
49
63
  export const WithPopup: FC<IWithPopupProps> = ({
@@ -52,11 +66,12 @@ export const WithPopup: FC<IWithPopupProps> = ({
52
66
  middlewares = [],
53
67
  eventType = 'click',
54
68
  placement = eventType === 'click' ? 'bottom-end' : 'top',
55
- shouldHideOnScroll = false,
56
- shouldRenderInBody = false,
57
69
  hoverDelay = 0,
58
70
  popupOffset = DEFAULT_OFFSET,
59
- canBeFlipped = false,
71
+ shouldHideOnScroll = false,
72
+ shouldRenderInBody = true,
73
+ canBeFlipped = true,
74
+ isTriggerWrapped = eventType === 'hover',
60
75
  isDisabled = false,
61
76
  tweakStyles,
62
77
  data,
@@ -67,16 +82,16 @@ export const WithPopup: FC<IWithPopupProps> = ({
67
82
 
68
83
  const [isOpen, setIsOpen] = useState(false);
69
84
 
70
- const handleToggle = (isActive: boolean, event?: MouseEvent | Event) => {
85
+ const handleToggle = (isActive: boolean, event?: IWithPopupToggleEvent) => {
71
86
  event?.stopPropagation();
72
87
  if (!isDisabled) {
73
- onToggle?.(isActive);
88
+ onToggle?.(isActive, event);
74
89
  setIsOpen(isActive);
75
90
  }
76
91
  };
77
92
 
78
- const handleClose = () => {
79
- handleToggle(false);
93
+ const handleClose = (event?: IWithPopupToggleEvent) => {
94
+ handleToggle(false, event);
80
95
  };
81
96
 
82
97
  const { refs, floatingStyles, context } = useFloating({
@@ -90,32 +105,46 @@ export const WithPopup: FC<IWithPopupProps> = ({
90
105
  const hover = useHover(context, {
91
106
  enabled: eventType === 'hover',
92
107
  delay: typeof hoverDelay === 'number' ? { open: hoverDelay, close: 0 } : hoverDelay,
108
+ handleClose: safePolygon(),
93
109
  });
94
- const click = useClick(context, { enabled: eventType === 'click', toggle: false });
110
+
111
+ const focus = useFocus(context, { enabled: eventType === 'hover' });
112
+
113
+ const click = useClick(context, { enabled: eventType === 'click' });
114
+
95
115
  const dismiss = useDismiss(context, {
96
116
  enabled: eventType === 'click',
97
117
  ancestorScroll: shouldHideOnScroll,
98
118
  });
99
119
 
100
- const { getFloatingProps } = useInteractions([hover, click, dismiss]);
120
+ const { getFloatingProps, getReferenceProps } = useInteractions([hover, click, focus, dismiss]);
101
121
 
102
122
  const { isMounted, status } = useTransitionStatus(context, { duration: { close: 500 } });
103
123
 
104
- return (
105
- <div
106
- ref={refs.setReference}
107
- className={clsx(classes.root, { [classes.disabled]: isDisabled })}
108
- {...addDataTestId(testId)}
109
- {...addDataAttributes(data)}
110
- >
111
- <div
112
- className={classes.trigger}
113
- onClick={eventType === 'click' ? (e) => handleToggle(!isOpen, e) : undefined}
114
- {...addDataTestId(testId, 'trigger')}
115
- >
116
- {isFunction(trigger) ? trigger({ isActive: isOpen }) : trigger}
117
- </div>
124
+ const referenceProps: Partial<IWithPopupTriggerProps> = getReferenceProps({
125
+ ref: refs.setReference,
126
+ });
118
127
 
128
+ const triggerElement = applyAction(trigger, {
129
+ isActive: isOpen,
130
+ isDisabled,
131
+ ...(!isTriggerWrapped ? referenceProps : undefined),
132
+ });
133
+
134
+ return (
135
+ <>
136
+ {isTriggerWrapped ? (
137
+ <div
138
+ className={clsx(classes.trigger, { [classes.disabled]: isDisabled })}
139
+ {...referenceProps}
140
+ {...addDataTestId(testId)}
141
+ {...addDataAttributes(data)}
142
+ >
143
+ {triggerElement}
144
+ </div>
145
+ ) : (
146
+ triggerElement
147
+ )}
119
148
  {isMounted && (
120
149
  <FloatingPortal
121
150
  root={!shouldRenderInBody ? (refs.reference.current as HTMLDivElement) : undefined}
@@ -132,6 +161,6 @@ export const WithPopup: FC<IWithPopupProps> = ({
132
161
  </div>
133
162
  </FloatingPortal>
134
163
  )}
135
- </div>
164
+ </>
136
165
  );
137
166
  };
@@ -1,3 +1,17 @@
1
+ import type { MouseEvent, KeyboardEvent } from 'react';
2
+ import type { IDomElementInteractions } from '../../types';
1
3
  import type { POPUP_EVENT_TYPES } from './constants';
2
4
 
3
5
  export type IPopupEventType = (typeof POPUP_EVENT_TYPES)[number];
6
+
7
+ export type IWithPopupToggleEvent = MouseEvent | KeyboardEvent | Event;
8
+
9
+ export interface IWithPopupTriggerProps extends IDomElementInteractions<HTMLElement> {
10
+ isActive: boolean;
11
+ isDisabled?: boolean;
12
+ ref?: (node: Element | null) => void;
13
+ }
14
+
15
+ export interface IWithPopupChildrenProps {
16
+ onClose: (event?: IWithPopupToggleEvent) => void;
17
+ }
@@ -1,17 +1,17 @@
1
- import { Modifier } from 'react-overlays/usePopper';
2
-
3
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
- export const minWidthModifier: Partial<Modifier<any, any>> = {
5
- name: 'minWidth',
6
- enabled: true,
7
- phase: 'beforeWrite',
8
- requires: ['computeStyles'],
9
- fn: ({ state }) => {
10
- state.styles.popper.minWidth = `${state.rects.reference.width}px`;
11
- },
12
- effect: ({ state }) => {
13
- state.elements.popper.style.minWidth = `${
14
- (state.elements.reference as HTMLElement).offsetWidth
15
- }px`;
16
- },
17
- };
1
+ import { Modifier } from 'react-overlays/usePopper';
2
+
3
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
+ export const minWidthModifier: Partial<Modifier<any, any>> = {
5
+ name: 'minWidth',
6
+ enabled: true,
7
+ phase: 'beforeWrite',
8
+ requires: ['computeStyles'],
9
+ fn: ({ state }) => {
10
+ state.styles.popper.minWidth = `${state.rects.reference.width}px`;
11
+ },
12
+ effect: ({ state }) => {
13
+ state.elements.popper.style.minWidth = `${
14
+ (state.elements.reference as HTMLElement).offsetWidth
15
+ }px`;
16
+ },
17
+ };