@ledgerhq/lumen-ui-rnative 0.1.25 → 0.1.26

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 (69) hide show
  1. package/dist/module/index.js +1 -0
  2. package/dist/module/index.js.map +1 -1
  3. package/dist/module/lib/Components/Avatar/Avatar.js +22 -23
  4. package/dist/module/lib/Components/Avatar/Avatar.js.map +1 -1
  5. package/dist/module/lib/Components/Avatar/Avatar.test.js +17 -23
  6. package/dist/module/lib/Components/Avatar/Avatar.test.js.map +1 -1
  7. package/dist/module/lib/Components/DotCount/DotCount.js +128 -0
  8. package/dist/module/lib/Components/DotCount/DotCount.js.map +1 -0
  9. package/dist/module/lib/Components/DotCount/DotCount.mdx +86 -0
  10. package/dist/module/lib/Components/DotCount/DotCount.stories.js +172 -0
  11. package/dist/module/lib/Components/DotCount/DotCount.stories.js.map +1 -0
  12. package/dist/module/lib/Components/DotCount/DotCount.test.js +174 -0
  13. package/dist/module/lib/Components/DotCount/DotCount.test.js.map +1 -0
  14. package/dist/module/lib/Components/DotCount/index.js +5 -0
  15. package/dist/module/lib/Components/DotCount/index.js.map +1 -0
  16. package/dist/module/lib/Components/DotCount/types.js +4 -0
  17. package/dist/module/lib/Components/DotCount/types.js.map +1 -0
  18. package/dist/module/lib/Components/DotIndicator/DotIndicator.js +89 -0
  19. package/dist/module/lib/Components/DotIndicator/DotIndicator.js.map +1 -0
  20. package/dist/module/lib/Components/DotIndicator/DotIndicator.mdx +82 -0
  21. package/dist/module/lib/Components/DotIndicator/DotIndicator.stories.js +84 -0
  22. package/dist/module/lib/Components/DotIndicator/DotIndicator.stories.js.map +1 -0
  23. package/dist/module/lib/Components/DotIndicator/DotIndicator.test.js +136 -0
  24. package/dist/module/lib/Components/DotIndicator/DotIndicator.test.js.map +1 -0
  25. package/dist/module/lib/Components/DotIndicator/index.js +5 -0
  26. package/dist/module/lib/Components/DotIndicator/index.js.map +1 -0
  27. package/dist/module/lib/Components/DotIndicator/types.js +4 -0
  28. package/dist/module/lib/Components/DotIndicator/types.js.map +1 -0
  29. package/dist/module/lib/Components/TabBar/TabBar.js +16 -13
  30. package/dist/module/lib/Components/TabBar/TabBar.js.map +1 -1
  31. package/dist/module/lib/Components/index.js +2 -0
  32. package/dist/module/lib/Components/index.js.map +1 -1
  33. package/dist/typescript/src/index.d.ts +1 -0
  34. package/dist/typescript/src/index.d.ts.map +1 -1
  35. package/dist/typescript/src/lib/Components/Avatar/Avatar.d.ts +1 -1
  36. package/dist/typescript/src/lib/Components/Avatar/Avatar.d.ts.map +1 -1
  37. package/dist/typescript/src/lib/Components/DotCount/DotCount.d.ts +3 -0
  38. package/dist/typescript/src/lib/Components/DotCount/DotCount.d.ts.map +1 -0
  39. package/dist/typescript/src/lib/Components/DotCount/index.d.ts +3 -0
  40. package/dist/typescript/src/lib/Components/DotCount/index.d.ts.map +1 -0
  41. package/dist/typescript/src/lib/Components/DotCount/types.d.ts +40 -0
  42. package/dist/typescript/src/lib/Components/DotCount/types.d.ts.map +1 -0
  43. package/dist/typescript/src/lib/Components/DotIndicator/DotIndicator.d.ts +3 -0
  44. package/dist/typescript/src/lib/Components/DotIndicator/DotIndicator.d.ts.map +1 -0
  45. package/dist/typescript/src/lib/Components/DotIndicator/index.d.ts +3 -0
  46. package/dist/typescript/src/lib/Components/DotIndicator/index.d.ts.map +1 -0
  47. package/dist/typescript/src/lib/Components/DotIndicator/types.d.ts +25 -0
  48. package/dist/typescript/src/lib/Components/DotIndicator/types.d.ts.map +1 -0
  49. package/dist/typescript/src/lib/Components/TabBar/TabBar.d.ts.map +1 -1
  50. package/dist/typescript/src/lib/Components/index.d.ts +2 -0
  51. package/dist/typescript/src/lib/Components/index.d.ts.map +1 -1
  52. package/package.json +1 -1
  53. package/src/index.ts +1 -0
  54. package/src/lib/Components/Avatar/Avatar.test.tsx +17 -27
  55. package/src/lib/Components/Avatar/Avatar.tsx +24 -21
  56. package/src/lib/Components/DotCount/DotCount.mdx +86 -0
  57. package/src/lib/Components/DotCount/DotCount.stories.tsx +124 -0
  58. package/src/lib/Components/DotCount/DotCount.test.tsx +150 -0
  59. package/src/lib/Components/DotCount/DotCount.tsx +130 -0
  60. package/src/lib/Components/DotCount/index.ts +2 -0
  61. package/src/lib/Components/DotCount/types.ts +40 -0
  62. package/src/lib/Components/DotIndicator/DotIndicator.mdx +82 -0
  63. package/src/lib/Components/DotIndicator/DotIndicator.stories.tsx +67 -0
  64. package/src/lib/Components/DotIndicator/DotIndicator.test.tsx +132 -0
  65. package/src/lib/Components/DotIndicator/DotIndicator.tsx +97 -0
  66. package/src/lib/Components/DotIndicator/index.ts +2 -0
  67. package/src/lib/Components/DotIndicator/types.ts +25 -0
  68. package/src/lib/Components/TabBar/TabBar.tsx +17 -16
  69. package/src/lib/Components/index.ts +2 -0
@@ -0,0 +1,40 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { StyledViewProps } from '../../../styles';
3
+
4
+ export type DotCountProps = {
5
+ /**
6
+ * The size of the dot count.
7
+ * @default md
8
+ */
9
+ size?: 'lg' | 'md';
10
+ /**
11
+ * The amount to be displayed.
12
+ *
13
+ * If higher than `max`, the displayed value will be "[max]+".
14
+ */
15
+ value: number;
16
+ /**
17
+ * The max value shown.
18
+ *
19
+ * If `value` is higher than `max`, the displayed value will be "[max]+".
20
+ *
21
+ * By design, it will ignore values higher than 99.
22
+ * @default 99
23
+ */
24
+ max?: number;
25
+ /**
26
+ * The appearance of the dot count.
27
+ * @default base
28
+ */
29
+ appearance?: 'base' | 'red';
30
+ /**
31
+ * Whether the dot count should show a disabled appearance.
32
+ * @default false
33
+ */
34
+ disabled?: boolean;
35
+ /**
36
+ * Can be used as a wrapper to any component in case you wish to overlay a dot count on top of it.
37
+ * If provided, it'll pin the dot count to the top-right of the child component passed.
38
+ */
39
+ children?: ReactNode;
40
+ } & Omit<StyledViewProps, 'children'>;
@@ -0,0 +1,82 @@
1
+ import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
2
+ import * as DotIndicatorStories from './DotIndicator.stories';
3
+ import { CustomTabs, Tab } from '../../../../.storybook/components';
4
+
5
+ <Meta title='Communication/DotIndicator' of={DotIndicatorStories} />
6
+
7
+ # DotIndicator
8
+
9
+ <CustomTabs>
10
+ <Tab label="Overview">
11
+
12
+ ## Introduction
13
+
14
+ DotIndicator is a small colored dot used to signal status or draw attention without displaying a number. It supports two appearances (`base` and `red`) and can be pinned to the top-right of a child element.
15
+
16
+ > View in [Figma](https://www.figma.com/design/JxaLVMTWirCpU0rsbZ30k7/2.-Components-Library?node-id=16470-25597).
17
+
18
+ ## Properties
19
+
20
+ <Canvas of={DotIndicatorStories.Base} />
21
+ <Controls of={DotIndicatorStories.Base} />
22
+
23
+ ## Sizes
24
+
25
+ DotIndicator comes in three sizes:
26
+
27
+ - **xs** - compact dot for tight layouts.
28
+ - **sm** (default) - standard dot for most use cases.
29
+ - **md** - larger dot for prominent indicators.
30
+
31
+ <Canvas of={DotIndicatorStories.SizeShowcase} />
32
+
33
+ ## Appearances
34
+
35
+ Two color schemes are available:
36
+
37
+ - **base** (default) - neutral dot for general-purpose indicators.
38
+ - **red** - high-visibility dot, typically used for unread or alert states.
39
+
40
+ <Canvas of={DotIndicatorStories.AppearanceShowcase} />
41
+
42
+ ## With Children
43
+
44
+ When wrapping a child element, the dot pins itself to the top-right corner.
45
+
46
+ <Canvas of={DotIndicatorStories.WithChildren} />
47
+
48
+ </Tab>
49
+ <Tab label="Implementation">
50
+
51
+ ## Setup
52
+
53
+ Install and set up the library with our [Setup Guide →](?path=/docs/getting-started-setup--docs).
54
+
55
+ ## Basic Usage
56
+
57
+ ```tsx
58
+ import { DotIndicator } from '@ledgerhq/lumen-ui-rnative';
59
+
60
+ function MyComponent() {
61
+ return <DotIndicator appearance="red" />;
62
+ }
63
+ ```
64
+
65
+ ### Pinned to a child
66
+
67
+ ```tsx
68
+ <DotIndicator appearance="red">
69
+ <Button size="sm">Submit</Button>
70
+ </DotIndicator>
71
+ ```
72
+
73
+ ### Accessibility
74
+
75
+ Pass `accessibilityLabel` to provide screen reader context:
76
+
77
+ ```tsx
78
+ <DotIndicator accessibilityLabel="New notifications" />
79
+ ```
80
+
81
+ </Tab>
82
+ </CustomTabs>
@@ -0,0 +1,67 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native-web-vite';
2
+ import { Button } from '../Button/Button';
3
+ import { Box } from '../Utility/Box';
4
+ import { DotIndicator } from './DotIndicator';
5
+
6
+ const meta = {
7
+ component: DotIndicator,
8
+ title: 'Communication/DotIndicator',
9
+ parameters: {
10
+ docs: {
11
+ source: {
12
+ language: 'tsx',
13
+ format: true,
14
+ type: 'code',
15
+ },
16
+ },
17
+ },
18
+ argTypes: {
19
+ size: {
20
+ control: 'radio',
21
+ options: ['xs', 'sm', 'md'],
22
+ },
23
+ appearance: {
24
+ control: 'radio',
25
+ options: ['base', 'red'],
26
+ },
27
+ },
28
+ } satisfies Meta<typeof DotIndicator>;
29
+
30
+ export default meta;
31
+ type Story = StoryObj<typeof meta>;
32
+
33
+ export const Base: Story = {
34
+ args: {
35
+ appearance: 'base',
36
+ },
37
+ };
38
+
39
+ export const SizeShowcase: Story = {
40
+ render: () => (
41
+ <Box lx={{ flexDirection: 'row', alignItems: 'center', gap: 's12' }}>
42
+ <DotIndicator size='xs' />
43
+ <DotIndicator size='sm' />
44
+ <DotIndicator size='md' />
45
+ </Box>
46
+ ),
47
+ };
48
+
49
+ export const AppearanceShowcase: Story = {
50
+ render: () => (
51
+ <Box lx={{ flexDirection: 'row', alignItems: 'center', gap: 's12' }}>
52
+ <DotIndicator appearance='base' />
53
+ <DotIndicator appearance='red' />
54
+ <DotIndicator disabled />
55
+ </Box>
56
+ ),
57
+ };
58
+
59
+ export const WithChildren: Story = {
60
+ render: () => (
61
+ <Box lx={{ flexDirection: 'row', alignItems: 'center', gap: 's12' }}>
62
+ <DotIndicator appearance='red'>
63
+ <Button size='sm'>Submit</Button>
64
+ </DotIndicator>
65
+ </Box>
66
+ ),
67
+ };
@@ -0,0 +1,132 @@
1
+ import { describe, it, expect } from '@jest/globals';
2
+ import { ledgerLiveThemes } from '@ledgerhq/lumen-design-core';
3
+ import { render } from '@testing-library/react-native';
4
+ import { createRef } from 'react';
5
+ import { Text, type View } from 'react-native';
6
+ import { ThemeProvider } from '../ThemeProvider/ThemeProvider';
7
+ import { DotIndicator } from './DotIndicator';
8
+
9
+ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
10
+ <ThemeProvider themes={ledgerLiveThemes} colorScheme='dark' locale='en'>
11
+ {children}
12
+ </ThemeProvider>
13
+ );
14
+
15
+ describe('DotIndicator', () => {
16
+ it('should render without crashing', () => {
17
+ const { toJSON } = render(
18
+ <TestWrapper>
19
+ <DotIndicator />
20
+ </TestWrapper>,
21
+ );
22
+
23
+ expect(toJSON()).toBeTruthy();
24
+ });
25
+
26
+ it('should render children', () => {
27
+ const { getByText } = render(
28
+ <TestWrapper>
29
+ <DotIndicator>
30
+ <Text>Child</Text>
31
+ </DotIndicator>
32
+ </TestWrapper>,
33
+ );
34
+
35
+ expect(getByText('Child')).toBeTruthy();
36
+ });
37
+
38
+ it('should apply accessibility label', () => {
39
+ const { getByLabelText } = render(
40
+ <TestWrapper>
41
+ <DotIndicator accessibilityLabel='New notifications' />
42
+ </TestWrapper>,
43
+ );
44
+
45
+ expect(getByLabelText('New notifications')).toBeTruthy();
46
+ });
47
+
48
+ it('should forward testID to the outer wrapper', () => {
49
+ const { getByTestId } = render(
50
+ <TestWrapper>
51
+ <DotIndicator testID='dot-indicator' />
52
+ </TestWrapper>,
53
+ );
54
+
55
+ expect(getByTestId('dot-indicator')).toBeTruthy();
56
+ });
57
+
58
+ it('should forward pointerEvents to the outer wrapper', () => {
59
+ const { getByTestId } = render(
60
+ <TestWrapper>
61
+ <DotIndicator testID='dot-indicator' pointerEvents='none' />
62
+ </TestWrapper>,
63
+ );
64
+
65
+ expect(getByTestId('dot-indicator').props.pointerEvents).toBe('none');
66
+ });
67
+
68
+ it('should forward ref to the outer wrapper', () => {
69
+ const ref = createRef<View>();
70
+
71
+ render(
72
+ <TestWrapper>
73
+ <DotIndicator ref={ref} />
74
+ </TestWrapper>,
75
+ );
76
+
77
+ expect(ref.current).toBeTruthy();
78
+ });
79
+
80
+ it('should render in xs size', () => {
81
+ const { toJSON } = render(
82
+ <TestWrapper>
83
+ <DotIndicator size='xs' />
84
+ </TestWrapper>,
85
+ );
86
+
87
+ expect(toJSON()).toBeTruthy();
88
+ });
89
+
90
+ it('should render in md size', () => {
91
+ const { toJSON } = render(
92
+ <TestWrapper>
93
+ <DotIndicator size='md' />
94
+ </TestWrapper>,
95
+ );
96
+
97
+ expect(toJSON()).toBeTruthy();
98
+ });
99
+
100
+ it('should render with red appearance', () => {
101
+ const { toJSON } = render(
102
+ <TestWrapper>
103
+ <DotIndicator appearance='red' />
104
+ </TestWrapper>,
105
+ );
106
+
107
+ expect(toJSON()).toBeTruthy();
108
+ });
109
+
110
+ it('should render with disabled state', () => {
111
+ const { toJSON } = render(
112
+ <TestWrapper>
113
+ <DotIndicator disabled />
114
+ </TestWrapper>,
115
+ );
116
+
117
+ expect(toJSON()).toBeTruthy();
118
+ });
119
+
120
+ it('should render pinned overlay when children provided', () => {
121
+ const { getByTestId, getByText } = render(
122
+ <TestWrapper>
123
+ <DotIndicator testID='dot-indicator'>
124
+ <Text>Content</Text>
125
+ </DotIndicator>
126
+ </TestWrapper>,
127
+ );
128
+
129
+ expect(getByTestId('dot-indicator')).toBeTruthy();
130
+ expect(getByText('Content')).toBeTruthy();
131
+ });
132
+ });
@@ -0,0 +1,97 @@
1
+ import { useDisabledContext } from '@ledgerhq/lumen-utils-shared';
2
+ import { StyleSheet } from 'react-native';
3
+ import { useStyleSheet } from '../../../styles';
4
+ import { Box } from '../Utility';
5
+ import type { DotIndicatorProps } from './types';
6
+
7
+ export function DotIndicator({
8
+ size = 'sm',
9
+ appearance = 'base',
10
+ disabled: disabledProp = false,
11
+ lx = {},
12
+ style,
13
+ children,
14
+ accessibilityLabel,
15
+ ref,
16
+ ...props
17
+ }: DotIndicatorProps) {
18
+ const disabled = useDisabledContext({
19
+ consumerName: 'DotIndicator',
20
+ mergeWith: { disabled: disabledProp },
21
+ });
22
+
23
+ const styles = useStyles({
24
+ size,
25
+ appearance,
26
+ disabled,
27
+ pinned: !!children,
28
+ });
29
+
30
+ return (
31
+ <Box
32
+ ref={ref}
33
+ lx={lx}
34
+ style={StyleSheet.flatten([
35
+ children ? { position: 'relative' } : undefined,
36
+ style,
37
+ ])}
38
+ {...props}
39
+ >
40
+ <Box
41
+ style={styles.container}
42
+ accessibilityRole='image'
43
+ accessibilityLabel={accessibilityLabel}
44
+ accessible={!!accessibilityLabel}
45
+ pointerEvents='none'
46
+ />
47
+ {children}
48
+ </Box>
49
+ );
50
+ }
51
+
52
+ const useStyles = ({
53
+ size,
54
+ appearance,
55
+ disabled,
56
+ pinned,
57
+ }: {
58
+ size: NonNullable<DotIndicatorProps['size']>;
59
+ appearance: NonNullable<DotIndicatorProps['appearance']>;
60
+ disabled: boolean;
61
+ pinned: boolean;
62
+ }) => {
63
+ return useStyleSheet(
64
+ (t) => {
65
+ const sizeMap = {
66
+ xs: t.sizes.s10,
67
+ sm: t.sizes.s12,
68
+ md: t.sizes.s16,
69
+ };
70
+
71
+ const bgColorMap = {
72
+ base: { backgroundColor: t.colors.bg.interactive },
73
+ red: { backgroundColor: t.colors.bg.errorStrong },
74
+ };
75
+
76
+ return {
77
+ container: {
78
+ height: sizeMap[size],
79
+ aspectRatio: 1,
80
+ alignItems: 'center',
81
+ justifyContent: 'center',
82
+ borderRadius: t.borderRadius.full,
83
+ ...(pinned && {
84
+ position: 'absolute',
85
+ top: t.spacings.s0,
86
+ right: t.spacings.s0,
87
+ zIndex: 1,
88
+ }),
89
+ ...(disabled
90
+ ? { backgroundColor: t.colors.bg.disabled }
91
+ : { ...bgColorMap[appearance] }),
92
+ },
93
+ };
94
+ },
95
+ [size, appearance, disabled, pinned],
96
+ );
97
+ };
@@ -0,0 +1,2 @@
1
+ export * from './DotIndicator';
2
+ export * from './types';
@@ -0,0 +1,25 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { StyledViewProps } from '../../../styles';
3
+
4
+ export type DotIndicatorProps = {
5
+ /**
6
+ * The size of the dot indicator.
7
+ * @default sm
8
+ */
9
+ size?: 'xs' | 'sm' | 'md';
10
+ /**
11
+ * The appearance of the dot indicator.
12
+ * @default base
13
+ */
14
+ appearance?: 'base' | 'red';
15
+ /**
16
+ * Whether the dot indicator should show a disabled appearance.
17
+ * @default false
18
+ */
19
+ disabled?: boolean;
20
+ /**
21
+ * Can be used as a wrapper to any component in case you wish to overlay a dot indicator on top of it.
22
+ * If provided, it'll pin the dot indicator to the top-right of the child component passed.
23
+ */
24
+ children?: ReactNode;
25
+ } & Omit<StyledViewProps, 'children'>;
@@ -1,12 +1,6 @@
1
1
  import { BlurView } from '@sbaiahmed1/react-native-blur';
2
2
  import type { ReactNode } from 'react';
3
- import {
4
- Children,
5
- isValidElement,
6
- useCallback,
7
- useEffect,
8
- useRef,
9
- } from 'react';
3
+ import { Children, isValidElement, useEffect, useMemo, useRef } from 'react';
10
4
  import type { LayoutChangeEvent } from 'react-native';
11
5
  import { Platform, StyleSheet, Text, View } from 'react-native';
12
6
  import Animated, {
@@ -19,6 +13,7 @@ import Animated, {
19
13
  } from 'react-native-reanimated';
20
14
  import { useStyleSheet, useTheme } from '../../../styles';
21
15
  import { useTimingConfig } from '../../Animations/useTimingConfig';
16
+ import { triggerHapticFeedback } from '../../Haptics';
22
17
  import { Placeholder } from '../../Symbols';
23
18
  import { Box, Pressable } from '../Utility';
24
19
  import { TabBarContextProvider, useTabBarContext } from './TabBarContext';
@@ -51,14 +46,16 @@ const useTabBarItemAnimations = ({ isActive }: { isActive: boolean }) => {
51
46
  50,
52
47
  withTiming(isActive ? 1 : 0, activeTimingConfig),
53
48
  );
54
- return () => cancelAnimation(activeProgress);
55
49
  }, [isActive, activeProgress, activeTimingConfig]);
56
50
 
51
+ useEffect(() => () => cancelAnimation(activeProgress), [activeProgress]);
52
+
57
53
  const onPressIn = () => {
58
54
  pressProgress.value = withTiming(0.9, pressInTimingConfig);
59
55
  };
60
56
 
61
57
  const onPressOut = () => {
58
+ triggerHapticFeedback('light');
62
59
  pressProgress.value = withSequence(
63
60
  withTiming(0.95, { duration: 0 }),
64
61
  withTiming(1, pressOutTimingConfig),
@@ -112,7 +109,7 @@ const useTabBarPillLayout = ({
112
109
  easing: 'easeInOut',
113
110
  });
114
111
 
115
- const getActiveIndex = useCallback((): number => {
112
+ const activeIndex = useMemo(() => {
116
113
  return Children.toArray(children).findIndex((child) => {
117
114
  if (isValidElement<TabBarItemProps>(child)) {
118
115
  return child.props.value === active;
@@ -121,6 +118,9 @@ const useTabBarPillLayout = ({
121
118
  });
122
119
  }, [active, children]);
123
120
 
121
+ const activeIndexRef = useRef(activeIndex);
122
+ activeIndexRef.current = activeIndex;
123
+
124
124
  const onLayout = (e: LayoutChangeEvent): void => {
125
125
  const { width, height } = e.nativeEvent.layout;
126
126
  const count = Children.count(children);
@@ -131,7 +131,7 @@ const useTabBarPillLayout = ({
131
131
 
132
132
  if (!hasLayoutRef.current) {
133
133
  hasLayoutRef.current = true;
134
- const index = getActiveIndex();
134
+ const index = activeIndexRef.current;
135
135
  if (index >= 0) {
136
136
  pillProgress.value = index * slotWidth;
137
137
  }
@@ -140,14 +140,15 @@ const useTabBarPillLayout = ({
140
140
 
141
141
  useEffect(() => {
142
142
  if (!hasLayoutRef.current) return;
143
- const index = getActiveIndex();
144
-
145
- if (index >= 0 && itemWidth.value > 0) {
146
- pillProgress.value = withTiming(index * itemWidth.value, timingConfig);
143
+ if (activeIndex >= 0 && itemWidth.value > 0) {
144
+ pillProgress.value = withTiming(
145
+ activeIndex * itemWidth.value,
146
+ timingConfig,
147
+ );
147
148
  }
149
+ }, [activeIndex, itemWidth, pillProgress, timingConfig]);
148
150
 
149
- return () => cancelAnimation(pillProgress);
150
- }, [itemWidth, pillProgress, getActiveIndex, timingConfig]);
151
+ useEffect(() => () => cancelAnimation(pillProgress), [pillProgress]);
151
152
 
152
153
  const animatedPillStyle = useAnimatedStyle(
153
154
  () => ({
@@ -4,6 +4,8 @@ export * from './AmountInput';
4
4
  export * from './Avatar';
5
5
  export * from './Banner';
6
6
  export * from './BottomSheet';
7
+ export * from './DotCount';
8
+ export * from './DotIndicator';
7
9
  export * from './Button';
8
10
  export * from './Card';
9
11
  export * from './CardButton';