@ssa-ui-kit/core 1.0.9 → 1.0.11

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 (39) hide show
  1. package/dist/components/PieChart/PieChart.d.ts +1 -1
  2. package/dist/components/PieChart/PieChartLegend.d.ts +1 -1
  3. package/dist/components/PieChart/PieChartLegendMarker.d.ts +2 -0
  4. package/dist/components/PieChart/types.d.ts +2 -1
  5. package/dist/components/SegmentedPieChart/SegmentedPieChart.d.ts +2 -0
  6. package/dist/components/SegmentedPieChart/colorPalettes.d.ts +2 -0
  7. package/dist/components/SegmentedPieChart/index.d.ts +1 -0
  8. package/dist/components/SegmentedPieChart/stories/fixtures.d.ts +3 -0
  9. package/dist/components/SegmentedPieChart/types.d.ts +37 -0
  10. package/dist/components/Typeahead/Typeahead.context.d.ts +0 -1
  11. package/dist/components/Typeahead/Typeahead.d.ts +1 -1
  12. package/dist/components/Typeahead/types.d.ts +2 -2
  13. package/dist/components/Typeahead/useTypeahead.d.ts +1 -2
  14. package/dist/components/index.d.ts +1 -0
  15. package/dist/index.js +1 -1
  16. package/dist/index.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/components/LinksTabBar/LinksTabBar.spec.tsx +0 -1
  19. package/src/components/PieChart/PieChart.tsx +1 -3
  20. package/src/components/PieChart/PieChartBases.tsx +1 -0
  21. package/src/components/PieChart/PieChartLegend.tsx +7 -1
  22. package/src/components/PieChart/PieChartLegendMarker.tsx +3 -1
  23. package/src/components/PieChart/types.ts +2 -1
  24. package/src/components/SegmentedPieChart/SegmentedPieChart.spec.tsx +29 -0
  25. package/src/components/SegmentedPieChart/SegmentedPieChart.tsx +154 -0
  26. package/src/components/SegmentedPieChart/colorPalettes.ts +13 -0
  27. package/src/components/SegmentedPieChart/index.ts +1 -0
  28. package/src/components/SegmentedPieChart/stories/SegmentedPieChart.stories.tsx +63 -0
  29. package/src/components/SegmentedPieChart/stories/fixtures.ts +147 -0
  30. package/src/components/SegmentedPieChart/types.ts +40 -0
  31. package/src/components/Typeahead/Typeahead.context.ts +0 -3
  32. package/src/components/Typeahead/Typeahead.stories.tsx +4 -4
  33. package/src/components/Typeahead/Typeahead.tsx +2 -2
  34. package/src/components/Typeahead/components/MultipleTrigger.tsx +0 -1
  35. package/src/components/Typeahead/components/SingleTrigger.tsx +0 -1
  36. package/src/components/Typeahead/types.ts +2 -2
  37. package/src/components/Typeahead/useTypeahead.tsx +10 -2
  38. package/src/components/index.ts +1 -0
  39. package/tsbuildcache +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ssa-ui-kit/core",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "private": false,
@@ -2,7 +2,6 @@ import { css } from '@emotion/react';
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import { links } from './stories/mockData';
4
4
  import { MemoryRouterDecorator } from './stories/decorators';
5
-
6
5
  import { LinksTabBar } from './index';
7
6
 
8
7
  function setup(Component: React.ElementType) {
@@ -4,7 +4,6 @@ import { PieChartProps } from './types';
4
4
  import { PieChartBase, PieChartTextBase } from './PieChartBases';
5
5
 
6
6
  export const PieChart = ({
7
- data,
8
7
  as,
9
8
  className,
10
9
  title,
@@ -15,7 +14,6 @@ export const PieChart = ({
15
14
  <PieChartBase as={as} className={className}>
16
15
  <div className="pie-chart-wrapper">
17
16
  <ResponsivePie
18
- data={data}
19
17
  isInteractive={false}
20
18
  innerRadius={0.8}
21
19
  enableArcLinkLabels={false}
@@ -29,7 +27,7 @@ export const PieChart = ({
29
27
  arcLinkLabelsThickness={2}
30
28
  arcLinkLabelsColor={{ from: 'color' }}
31
29
  arcLabelsSkipAngle={10}
32
- layers={['arcs']}
30
+ layers={['arcs', 'arcLinkLabels', 'arcLabels']}
33
31
  {...chartProps}
34
32
  />
35
33
  {title && <PieChartTextBase>{title}</PieChartTextBase>}
@@ -17,6 +17,7 @@ export const PieChartTextBase = styled.div`
17
17
  position: absolute;
18
18
  width: 100%;
19
19
  height: 100%;
20
+ pointer-events: none;
20
21
  top: 0;
21
22
  left: 0;
22
23
  display: flex;
@@ -9,6 +9,7 @@ import { PieChartLegendProps } from './types';
9
9
  export const PieChartLegend = ({
10
10
  data,
11
11
  colors,
12
+ backgroundColors,
12
13
  renderLabel,
13
14
  renderValue,
14
15
  markerStyles,
@@ -27,7 +28,12 @@ export const PieChartLegend = ({
27
28
  return (
28
29
  <li key={`tag-${id}`}>
29
30
  <PieChartLegendMarker
30
- color={colors[index] || 'purple'}
31
+ color={
32
+ backgroundColors ? undefined : colors?.[index] || 'purple'
33
+ }
34
+ background={
35
+ backgroundColors ? backgroundColors[index] : undefined
36
+ }
31
37
  as={'span'}
32
38
  css={markerStyles}
33
39
  />
@@ -1,7 +1,7 @@
1
1
  import styled from '@emotion/styled';
2
2
  import Badge from '@components/Badge';
3
3
 
4
- export const PieChartLegendMarker = styled(Badge)`
4
+ export const PieChartLegendMarker = styled(Badge)<{ background?: string }>`
5
5
  display: inline-block;
6
6
 
7
7
  padding: 0;
@@ -9,4 +9,6 @@ export const PieChartLegendMarker = styled(Badge)`
9
9
 
10
10
  width: 8px;
11
11
  height: 8px;
12
+
13
+ background: ${({ background }) => background};
12
14
  `;
@@ -18,7 +18,8 @@ export type PieChartLegendItem = {
18
18
 
19
19
  export interface PieChartLegendProps {
20
20
  data: Array<PieChartLegendItem>;
21
- colors: Array<keyof MainColors>;
21
+ colors?: Array<keyof MainColors>;
22
+ backgroundColors?: Array<string>;
22
23
  renderValue?: (item: PieChartLegendItem) => NonNullable<React.ReactNode>;
23
24
  renderLabel?: (item: PieChartLegendItem) => NonNullable<React.ReactNode>;
24
25
  className?: string;
@@ -0,0 +1,29 @@
1
+ import { SegmentedPieChart } from './index';
2
+ import { balanceData } from './stories/fixtures';
3
+
4
+ const ResponsivePieMock = () => <div data-testid="responsive-pie"></div>;
5
+
6
+ jest.mock('@nivo/pie', () => ({
7
+ PieCustomLayerProps: {},
8
+ ResponsivePie: ResponsivePieMock,
9
+ }));
10
+
11
+ describe('SegmentedPieChart', () => {
12
+ it('Renders with a Legend', () => {
13
+ const { getByTestId, getByRole, getByText } = render(
14
+ <SegmentedPieChart data={balanceData} />,
15
+ );
16
+
17
+ getByTestId('responsive-pie');
18
+ getByText('17737');
19
+
20
+ for (const { label, value, percentage } of balanceData) {
21
+ getByRole('heading', { name: label });
22
+ if (label === 'Other') {
23
+ getByRole('heading', { name: `${value} USD (${percentage}%)` });
24
+ } else {
25
+ getByRole('heading', { name: `${value} ${label} (${percentage}%)` });
26
+ }
27
+ }
28
+ });
29
+ });
@@ -0,0 +1,154 @@
1
+ import { css, useTheme } from '@emotion/react';
2
+ import { pathOr } from '@ssa-ui-kit/utils';
3
+ import { Typography, Wrapper, PieChart, PieChartLegend } from '@components';
4
+ import {
5
+ defaultLegendBackgrounds,
6
+ defaultPieChartColors,
7
+ } from './colorPalettes';
8
+ import { BalanceDataForGraph, SegmentedPieChartProps } from './types';
9
+
10
+ export const SegmentedPieChart = ({
11
+ data,
12
+ pieChartProps,
13
+ pieChartLegendProps,
14
+ legendBackgrounds = defaultLegendBackgrounds,
15
+ pieChartColors = defaultPieChartColors,
16
+ currency = 'USD',
17
+ otherLabel = 'Other',
18
+ }: SegmentedPieChartProps) => {
19
+ const theme = useTheme();
20
+
21
+ const balanceDataForTheGraph: BalanceDataForGraph[] = [];
22
+ let balanceDataTotal = 0;
23
+ data?.forEach((item, itemIndex) => {
24
+ if (item.parts?.length) {
25
+ item.parts?.forEach((part, partIndex) => {
26
+ balanceDataForTheGraph.push({
27
+ mainLabel: item.label,
28
+ mainPercentage: item.percentage,
29
+ partLabel: part.label,
30
+ partPercentage: part.percentage,
31
+ color: pieChartColors[itemIndex][partIndex],
32
+ id: `${itemIndex}${partIndex}`,
33
+ mainId: item.id,
34
+ value: part.percentage,
35
+ });
36
+ });
37
+ } else {
38
+ balanceDataForTheGraph.push({
39
+ mainLabel: item.label,
40
+ mainPercentage: item.percentage,
41
+ color: pieChartColors[itemIndex][0],
42
+ id: `${itemIndex}${0}`,
43
+ mainId: item.id,
44
+ value: item.percentage,
45
+ });
46
+ }
47
+ balanceDataTotal += item.value;
48
+ });
49
+
50
+ return (
51
+ <PieChart
52
+ data={balanceDataForTheGraph}
53
+ animate={true}
54
+ css={{
55
+ width: 500,
56
+ padding: 50,
57
+ }}
58
+ isInteractive
59
+ activeInnerRadiusOffset={0}
60
+ activeOuterRadiusOffset={0}
61
+ tooltip={(point) => {
62
+ const pointData = pathOr<typeof point, BalanceDataForGraph>({}, [
63
+ 'datum',
64
+ 'data',
65
+ ])(point);
66
+ return (
67
+ <Wrapper
68
+ css={{
69
+ background: theme.colors.greyLighter,
70
+ flexDirection: 'column',
71
+ borderRadius: 8,
72
+ padding: 5,
73
+ fontSize: 12,
74
+ fontWeight: 500,
75
+ }}>
76
+ {['main', 'part'].map((item) => {
77
+ if (item === 'part' && !pointData['partLabel']) {
78
+ return null;
79
+ }
80
+ const currentItem =
81
+ item === 'main'
82
+ ? {
83
+ label: pointData['mainLabel'],
84
+ percentage: pointData['mainPercentage'],
85
+ }
86
+ : {
87
+ label: pointData['partLabel'],
88
+ percentage: pointData['partPercentage'],
89
+ };
90
+ return (
91
+ <Wrapper
92
+ key={item}
93
+ css={{
94
+ justifyContent: 'space-between',
95
+ gap: 10,
96
+ }}>
97
+ <span css={{ fontWeight: 600 }}>{currentItem.label}</span>
98
+ <span>{currentItem['percentage']}%</span>
99
+ </Wrapper>
100
+ );
101
+ })}
102
+ </Wrapper>
103
+ );
104
+ }}
105
+ title={
106
+ <Typography
107
+ variant="body2"
108
+ weight="bold"
109
+ color={theme.colors.greyDarker}
110
+ css={css`
111
+ font-size: 20px;
112
+ line-height: 25px;
113
+ `}>
114
+ {balanceDataTotal} &nbsp;
115
+ <Typography
116
+ variant="body2"
117
+ weight="regular"
118
+ as="span"
119
+ color={theme.colors.greyDarker80}
120
+ css={css`
121
+ font-size: 14px;
122
+ `}>
123
+ {currency}
124
+ </Typography>
125
+ </Typography>
126
+ }
127
+ {...pieChartProps}>
128
+ <PieChartLegend
129
+ data={data}
130
+ backgroundColors={legendBackgrounds}
131
+ renderValue={({ value, label, percentage }) =>
132
+ label === otherLabel
133
+ ? value + ` ${currency}` + ` (${percentage}%)`
134
+ : value + ' ' + label + ` (${percentage}%)`
135
+ }
136
+ markerStyles={css`
137
+ width: 10px;
138
+ height: 10px;
139
+ `}
140
+ labelListStyles={css`
141
+ h6 {
142
+ font-weight: 700;
143
+ }
144
+ `}
145
+ valueListStyles={css`
146
+ h6 {
147
+ color: ${theme.colors.greyDarker80};
148
+ }
149
+ `}
150
+ {...pieChartLegendProps}
151
+ />
152
+ </PieChart>
153
+ );
154
+ };
@@ -0,0 +1,13 @@
1
+ export const defaultLegendBackgrounds = [
2
+ 'linear-gradient(90deg, #ED995D 0%, #EDBA5D 100%)',
3
+ 'linear-gradient(247deg, #7599DE 14.71%, #4178E1 85.29%)',
4
+ 'linear-gradient(296deg, #89D996 16.38%, #52C587 83.62%)',
5
+ 'linear-gradient(68deg, #EB7556 12.3%, #F2888E 88.95%)',
6
+ ];
7
+
8
+ export const defaultPieChartColors = [
9
+ ['#ED995D', '#EDAA5D', '#EDBA5D', '#FFCF78', '#FFDFA5'],
10
+ ['#4178E1', '#7599DE', '#8BB2FD', '#A6C4FF', '#CEDFFF'],
11
+ ['#36AB6C', '#52C587', '#89D996', '#A7F3B3', '#C0FFCA'],
12
+ ['#EB7556', '#FF917E', '#F2888E', '#FFA6A8', '#FFD4CB'],
13
+ ];
@@ -0,0 +1 @@
1
+ export * from './SegmentedPieChart';
@@ -0,0 +1,63 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { balanceData, balanceMissedPartsData } from './fixtures';
3
+ import { SegmentedPieChart } from '../SegmentedPieChart';
4
+
5
+ export default {
6
+ title: 'Widgets/SegmentedPieChart',
7
+ component: SegmentedPieChart,
8
+ } as Meta<typeof SegmentedPieChart>;
9
+
10
+ type Args = StoryObj<Partial<Parameters<typeof SegmentedPieChart>[0]>>;
11
+
12
+ const StoryTemplate: Args = {
13
+ render: ({ ...args }) => <SegmentedPieChart data={balanceData} {...args} />,
14
+ };
15
+
16
+ export const AccountExample = {
17
+ ...StoryTemplate,
18
+ args: {},
19
+ };
20
+
21
+ export const CustomColors = {
22
+ ...StoryTemplate,
23
+ args: {
24
+ legendBackgrounds: [
25
+ 'linear-gradient(90deg, #6A9FDC 0%, #85BCE8 100%)',
26
+ 'linear-gradient(247deg, #A34EC6 14.71%, #D678F8 85.29%)',
27
+ 'linear-gradient(296deg, #5FD1E4 16.38%, #7AE4F5 83.62%)',
28
+ 'linear-gradient(68deg, #D77A61 12.3%, #E89C91 88.95%)',
29
+ ],
30
+ pieChartColors: [
31
+ ['#6A9FDC', '#85BCE8', '#A3D7F2', '#BAE7FF', '#D1F2FF'],
32
+ ['#A34EC6', '#D678F8', '#E597FF', '#F5C0FF', '#FFD9FF'],
33
+ ['#5FD1E4', '#7AE4F5', '#A1F3FF', '#C0FFFF', '#D9FFFF'],
34
+ ['#D77A61', '#E89C91', '#F1B5A4', '#FFC3B5', '#FFDACC'],
35
+ ],
36
+ pieChartProps: {
37
+ tooltip: undefined,
38
+ },
39
+ },
40
+ };
41
+
42
+ export const CustomCurrency = {
43
+ ...StoryTemplate,
44
+ args: {
45
+ currency: 'EUR',
46
+ },
47
+ };
48
+
49
+ export const WithoutTooltip = {
50
+ ...StoryTemplate,
51
+ args: {
52
+ pieChartProps: {
53
+ isInteractive: false,
54
+ },
55
+ },
56
+ };
57
+
58
+ export const MissedPartsData = {
59
+ ...StoryTemplate,
60
+ args: {
61
+ data: balanceMissedPartsData,
62
+ },
63
+ };
@@ -0,0 +1,147 @@
1
+ import { BalanceData } from '../types';
2
+
3
+ export const balanceData: BalanceData = [
4
+ {
5
+ id: 1,
6
+ value: 5843.37,
7
+ label: 'BTC',
8
+ percentage: 33,
9
+ parts: [
10
+ {
11
+ label: 'BTC. Option 1',
12
+ percentage: 13,
13
+ value: 2300,
14
+ },
15
+ {
16
+ label: 'BTC. Option 2',
17
+ percentage: 10,
18
+ value: 1800,
19
+ },
20
+ {
21
+ label: 'BTC. Option 3',
22
+ percentage: 10,
23
+ value: 1743.37,
24
+ },
25
+ ],
26
+ },
27
+ {
28
+ id: 2,
29
+ value: 5249.25,
30
+ label: 'ETH',
31
+ percentage: 30,
32
+ parts: [
33
+ {
34
+ label: 'ETH. Option 1',
35
+ percentage: 17,
36
+ value: 2800,
37
+ },
38
+ {
39
+ label: 'ETH. Option 2',
40
+ percentage: 13,
41
+ value: 2449.25,
42
+ },
43
+ ],
44
+ },
45
+ {
46
+ id: 3,
47
+ value: 3825.55,
48
+ label: 'USDT',
49
+ percentage: 22,
50
+ parts: [
51
+ {
52
+ label: 'USDT. Option 1',
53
+ percentage: 5,
54
+ value: 1000,
55
+ },
56
+ {
57
+ label: 'USDT. Option 2',
58
+ percentage: 12,
59
+ value: 1840,
60
+ },
61
+ {
62
+ label: 'USDT. Option 3',
63
+ percentage: 5,
64
+ value: 985.55,
65
+ },
66
+ ],
67
+ },
68
+ {
69
+ id: 4,
70
+ value: 2818.83,
71
+ label: 'Other',
72
+ percentage: 15,
73
+ parts: [
74
+ {
75
+ label: 'Other. Option 1',
76
+ percentage: 7,
77
+ value: 1400,
78
+ },
79
+ {
80
+ label: 'Other. Option 2',
81
+ percentage: 8,
82
+ value: 1418.83,
83
+ },
84
+ ],
85
+ },
86
+ ];
87
+
88
+ export const balanceMissedPartsData: BalanceData = [
89
+ {
90
+ id: 1,
91
+ value: 5843.37,
92
+ label: 'BTC',
93
+ percentage: 33,
94
+ parts: [
95
+ {
96
+ label: 'BTC. Option 1',
97
+ percentage: 13,
98
+ value: 2300,
99
+ },
100
+ {
101
+ label: 'BTC. Option 2',
102
+ percentage: 10,
103
+ value: 1800,
104
+ },
105
+ {
106
+ label: 'BTC. Option 3',
107
+ percentage: 10,
108
+ value: 1743.37,
109
+ },
110
+ ],
111
+ },
112
+ {
113
+ id: 2,
114
+ value: 5249.25,
115
+ label: 'ETH',
116
+ percentage: 30,
117
+ },
118
+ {
119
+ id: 3,
120
+ value: 3825.55,
121
+ label: 'USDT',
122
+ percentage: 22,
123
+ parts: [
124
+ {
125
+ label: 'USDT. Option 1',
126
+ percentage: 5,
127
+ value: 1000,
128
+ },
129
+ {
130
+ label: 'USDT. Option 2',
131
+ percentage: 12,
132
+ value: 1840,
133
+ },
134
+ {
135
+ label: 'USDT. Option 3',
136
+ percentage: 5,
137
+ value: 985.55,
138
+ },
139
+ ],
140
+ },
141
+ {
142
+ id: 4,
143
+ value: 2818.83,
144
+ label: 'Other',
145
+ percentage: 15,
146
+ },
147
+ ];
@@ -0,0 +1,40 @@
1
+ import { CommonProps } from '@global-types/emotion';
2
+ import { MayHaveLabel } from '@nivo/pie';
3
+ import { PieChartLegend, PieChartProps } from '@components';
4
+
5
+ type BalanceDataPartsItem = {
6
+ label: string;
7
+ percentage: number;
8
+ value: number;
9
+ };
10
+
11
+ type BalanceDataItem = {
12
+ id: number;
13
+ value: number;
14
+ label: string;
15
+ percentage: number;
16
+ parts?: BalanceDataPartsItem[];
17
+ };
18
+
19
+ export type BalanceData = Array<BalanceDataItem>;
20
+
21
+ export interface SegmentedPieChartProps extends CommonProps {
22
+ data: BalanceData;
23
+ pieChartProps?: Partial<PieChartProps>;
24
+ pieChartLegendProps?: Partial<React.ComponentProps<typeof PieChartLegend>>;
25
+ legendBackgrounds?: string[];
26
+ pieChartColors?: string[][];
27
+ currency?: string;
28
+ otherLabel?: string;
29
+ }
30
+
31
+ export interface BalanceDataForGraph extends MayHaveLabel {
32
+ mainLabel: string;
33
+ mainPercentage: number;
34
+ partLabel?: string;
35
+ partPercentage?: number;
36
+ id: number | string;
37
+ mainId: number;
38
+ value: number | string;
39
+ color: string;
40
+ }
@@ -52,9 +52,6 @@ export const TypeaheadContext = React.createContext<UseTypeaheadResult>({
52
52
  handleRemoveSelectedClick: () => () => {
53
53
  /* no-op */
54
54
  },
55
- handleInputBlur: () => {
56
- /* no-op */
57
- },
58
55
  handleSelectedClick: () => {
59
56
  /* no-op */
60
57
  },
@@ -63,8 +63,8 @@ export const Basic: StoryObj = (args: TypeaheadProps) => {
63
63
  <Typeahead
64
64
  initialSelectedItems={[items[2].id]}
65
65
  isDisabled={args.isDisabled}
66
- onBlur={() => {
67
- console.log('>>>onBlur event');
66
+ onEmptyChange={(isEmpty) => {
67
+ console.log('>>>onEmptyChange event', isEmpty);
68
68
  }}
69
69
  name={'typeahead-dropdown'}
70
70
  label="Label"
@@ -127,8 +127,8 @@ export const Multiple: StoryObj = (args: TypeaheadProps) => {
127
127
  initialSelectedItems={[items[2].id, items[1].id]}
128
128
  isMultiple
129
129
  isDisabled={args.isDisabled}
130
- onBlur={() => {
131
- console.log('>>>onBlur event');
130
+ onEmptyChange={(isEmpty) => {
131
+ console.log('>>>onEmptyChange event', isEmpty);
132
132
  }}
133
133
  label="Label"
134
134
  helperText="Helper Text"
@@ -45,7 +45,7 @@ export const Typeahead = ({
45
45
  setValue,
46
46
  register,
47
47
  onChange,
48
- onBlur,
48
+ onEmptyChange,
49
49
  renderOption,
50
50
  }: TypeaheadProps) => {
51
51
  const theme = useTheme();
@@ -68,7 +68,7 @@ export const Typeahead = ({
68
68
  setValue,
69
69
  register,
70
70
  onChange,
71
- onBlur,
71
+ onEmptyChange,
72
72
  renderOption,
73
73
  });
74
74
 
@@ -67,7 +67,6 @@ export const MultipleTrigger = () => {
67
67
  onClick: context.handleInputClick,
68
68
  onKeyDown: context.handleInputKeyDown,
69
69
  onChange: context.handleInputChange,
70
- onBlur: context.handleInputBlur,
71
70
  value: context.inputValue,
72
71
  autoComplete: 'off',
73
72
  className: ['typeahead-input', S.TypeaheadInput(theme)].join(' '),
@@ -26,7 +26,6 @@ export const SingleTrigger = () => {
26
26
  onClick: context.handleInputClick,
27
27
  onKeyDown: context.handleInputKeyDown,
28
28
  onChange: context.handleInputChange,
29
- onBlur: context.handleInputBlur,
30
29
  value: context.inputValue,
31
30
  autoComplete: 'off',
32
31
  className: ['typeahead-input', S.TypeaheadInput(theme)].join(' '),
@@ -34,7 +34,7 @@ export interface TypeaheadProps {
34
34
  setValue?: UseFormSetValue<FieldValues>;
35
35
  register?: UseFormReturn['register'];
36
36
  onChange?: (selectedItem: TypeaheadValue, isSelected: boolean) => void;
37
- onBlur?: React.FocusEventHandler<HTMLInputElement>;
37
+ onEmptyChange?: (isEmpty?: boolean) => void;
38
38
  renderOption?: (data: {
39
39
  value: string | number;
40
40
  input: string;
@@ -49,7 +49,7 @@ export type UseTypeaheadProps = Pick<
49
49
  | 'children'
50
50
  | 'isMultiple'
51
51
  | 'onChange'
52
- | 'onBlur'
52
+ | 'onEmptyChange'
53
53
  | 'renderOption'
54
54
  | 'isOpen'
55
55
  | 'className'
@@ -29,7 +29,7 @@ export const useTypeahead = ({
29
29
  register,
30
30
  setValue,
31
31
  onChange,
32
- onBlur,
32
+ onEmptyChange,
33
33
  renderOption,
34
34
  }: UseTypeaheadProps) => {
35
35
  const inputName = `${name}-text`;
@@ -40,6 +40,7 @@ export const useTypeahead = ({
40
40
  const [optionsWithKey, setOptionsWithKey] = useState<
41
41
  Record<number | string, Record<string, string | number>>
42
42
  >({});
43
+ const [isEmpty, setIsEmpty] = useState<boolean>();
43
44
  const [isFirstRender, setFirstRender] = useState<boolean>(true);
44
45
  const [items, setItems] = useState<Array<React.ReactElement> | undefined>();
45
46
  const [inputValue, setInputValue] = useState<string>('');
@@ -70,8 +71,16 @@ export const useTypeahead = ({
70
71
  shouldDirty: !isFirstRender,
71
72
  });
72
73
  }
74
+
75
+ if (!isFirstRender) {
76
+ setIsEmpty(!selected.length);
77
+ }
73
78
  }, [selected]);
74
79
 
80
+ useEffect(() => {
81
+ onEmptyChange?.(isEmpty);
82
+ }, [isEmpty]);
83
+
75
84
  useEffect(() => {
76
85
  if (isDisabled && isOpen) {
77
86
  setIsOpen(false);
@@ -341,7 +350,6 @@ export const useTypeahead = ({
341
350
  handleInputChange,
342
351
  handleInputClick,
343
352
  handleInputKeyDown,
344
- handleInputBlur: onBlur,
345
353
  handleSelectedClick,
346
354
  handleRemoveSelectedClick,
347
355
  };