@sudobility/components-rn 1.0.39 → 1.0.41
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.cjs.js +21 -0
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +21 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/ui/AppVersion/AppVersion.d.ts +24 -0
- package/dist/ui/AppVersion/AppVersion.d.ts.map +1 -0
- package/dist/ui/AppVersion/index.d.ts +3 -0
- package/dist/ui/AppVersion/index.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/__tests__/dialog.test.tsx +30 -1
- package/src/__tests__/sheet.test.tsx +42 -1
- package/src/__tests__/toast.test.tsx +32 -0
- package/src/index.ts +1 -0
- package/src/ui/AppVersion/AppVersion.tsx +42 -0
- package/src/ui/AppVersion/index.ts +2 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
export interface AppVersionProps {
|
|
3
|
+
/** App display name */
|
|
4
|
+
appName: string;
|
|
5
|
+
/** Version string (e.g. from package.json) */
|
|
6
|
+
version: string;
|
|
7
|
+
/** Additional className */
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* AppVersion Component
|
|
12
|
+
*
|
|
13
|
+
* Displays the app name and version in a muted text style.
|
|
14
|
+
* Reads the version from the consuming app's package.json.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* import { version } from '../package.json';
|
|
19
|
+
* <AppVersion appName="MyApp" version={version} />
|
|
20
|
+
* // renders: "MyApp v1.0.0"
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const AppVersion: React.FC<AppVersionProps>;
|
|
24
|
+
//# sourceMappingURL=AppVersion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppVersion.d.ts","sourceRoot":"","sources":["../../../src/ui/AppVersion/AppVersion.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAehD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/AppVersion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen, fireEvent } from '@testing-library/react-native';
|
|
2
|
+
import { render, screen, fireEvent, act } from '@testing-library/react-native';
|
|
3
3
|
import { Text } from 'react-native';
|
|
4
4
|
import { Dialog } from '../ui/Dialog';
|
|
5
5
|
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
jest.useFakeTimers();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
jest.useRealTimers();
|
|
12
|
+
});
|
|
13
|
+
|
|
6
14
|
describe('Dialog', () => {
|
|
7
15
|
const defaultProps = {
|
|
8
16
|
isOpen: true,
|
|
@@ -16,11 +24,17 @@ describe('Dialog', () => {
|
|
|
16
24
|
|
|
17
25
|
it('renders children when open', () => {
|
|
18
26
|
render(<Dialog {...defaultProps} />);
|
|
27
|
+
act(() => {
|
|
28
|
+
jest.runAllTimers();
|
|
29
|
+
});
|
|
19
30
|
expect(screen.getByText('Dialog content')).toBeTruthy();
|
|
20
31
|
});
|
|
21
32
|
|
|
22
33
|
it('renders close button by default when onClose is provided', () => {
|
|
23
34
|
render(<Dialog {...defaultProps} />);
|
|
35
|
+
act(() => {
|
|
36
|
+
jest.runAllTimers();
|
|
37
|
+
});
|
|
24
38
|
const closeButton = screen.getByLabelText('Close dialog');
|
|
25
39
|
expect(closeButton).toBeTruthy();
|
|
26
40
|
});
|
|
@@ -32,12 +46,18 @@ describe('Dialog', () => {
|
|
|
32
46
|
<Text>Content</Text>
|
|
33
47
|
</Dialog>
|
|
34
48
|
);
|
|
49
|
+
act(() => {
|
|
50
|
+
jest.runAllTimers();
|
|
51
|
+
});
|
|
35
52
|
fireEvent.press(screen.getByLabelText('Close dialog'));
|
|
36
53
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
37
54
|
});
|
|
38
55
|
|
|
39
56
|
it('hides close button when showCloseButton is false', () => {
|
|
40
57
|
render(<Dialog {...defaultProps} showCloseButton={false} />);
|
|
58
|
+
act(() => {
|
|
59
|
+
jest.runAllTimers();
|
|
60
|
+
});
|
|
41
61
|
expect(screen.queryByLabelText('Close dialog')).toBeNull();
|
|
42
62
|
});
|
|
43
63
|
|
|
@@ -50,6 +70,9 @@ describe('Dialog', () => {
|
|
|
50
70
|
<Text>{size}</Text>
|
|
51
71
|
</Dialog>
|
|
52
72
|
);
|
|
73
|
+
act(() => {
|
|
74
|
+
jest.runAllTimers();
|
|
75
|
+
});
|
|
53
76
|
expect(screen.getByText(size)).toBeTruthy();
|
|
54
77
|
unmount();
|
|
55
78
|
});
|
|
@@ -61,6 +84,9 @@ describe('Dialog', () => {
|
|
|
61
84
|
<Text>No close</Text>
|
|
62
85
|
</Dialog>
|
|
63
86
|
);
|
|
87
|
+
act(() => {
|
|
88
|
+
jest.runAllTimers();
|
|
89
|
+
});
|
|
64
90
|
expect(screen.queryByLabelText('Close dialog')).toBeNull();
|
|
65
91
|
});
|
|
66
92
|
|
|
@@ -70,6 +96,9 @@ describe('Dialog', () => {
|
|
|
70
96
|
<Text>No X button</Text>
|
|
71
97
|
</Dialog>
|
|
72
98
|
);
|
|
99
|
+
act(() => {
|
|
100
|
+
jest.runAllTimers();
|
|
101
|
+
});
|
|
73
102
|
expect(screen.getByText('No X button')).toBeTruthy();
|
|
74
103
|
expect(screen.queryByLabelText('Close dialog')).toBeNull();
|
|
75
104
|
});
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen, fireEvent } from '@testing-library/react-native';
|
|
2
|
+
import { render, screen, fireEvent, act } from '@testing-library/react-native';
|
|
3
3
|
import { Text } from 'react-native';
|
|
4
4
|
import { Sheet } from '../ui/Sheet';
|
|
5
5
|
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
jest.useFakeTimers();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
jest.useRealTimers();
|
|
12
|
+
});
|
|
13
|
+
|
|
6
14
|
describe('Sheet', () => {
|
|
7
15
|
const defaultProps = {
|
|
8
16
|
isOpen: true,
|
|
@@ -16,11 +24,17 @@ describe('Sheet', () => {
|
|
|
16
24
|
|
|
17
25
|
it('renders children when open', () => {
|
|
18
26
|
render(<Sheet {...defaultProps} />);
|
|
27
|
+
act(() => {
|
|
28
|
+
jest.runAllTimers();
|
|
29
|
+
});
|
|
19
30
|
expect(screen.getByText('Sheet content')).toBeTruthy();
|
|
20
31
|
});
|
|
21
32
|
|
|
22
33
|
it('renders title when provided', () => {
|
|
23
34
|
render(<Sheet {...defaultProps} title='Sheet Title' />);
|
|
35
|
+
act(() => {
|
|
36
|
+
jest.runAllTimers();
|
|
37
|
+
});
|
|
24
38
|
expect(screen.getByText('Sheet Title')).toBeTruthy();
|
|
25
39
|
});
|
|
26
40
|
|
|
@@ -28,11 +42,17 @@ describe('Sheet', () => {
|
|
|
28
42
|
render(
|
|
29
43
|
<Sheet {...defaultProps} title='Title' description='Sheet description' />
|
|
30
44
|
);
|
|
45
|
+
act(() => {
|
|
46
|
+
jest.runAllTimers();
|
|
47
|
+
});
|
|
31
48
|
expect(screen.getByText('Sheet description')).toBeTruthy();
|
|
32
49
|
});
|
|
33
50
|
|
|
34
51
|
it('renders close button by default', () => {
|
|
35
52
|
render(<Sheet {...defaultProps} title='Title' />);
|
|
53
|
+
act(() => {
|
|
54
|
+
jest.runAllTimers();
|
|
55
|
+
});
|
|
36
56
|
const closeButton = screen.getByLabelText('Close sheet');
|
|
37
57
|
expect(closeButton).toBeTruthy();
|
|
38
58
|
});
|
|
@@ -44,17 +64,26 @@ describe('Sheet', () => {
|
|
|
44
64
|
<Text>Content</Text>
|
|
45
65
|
</Sheet>
|
|
46
66
|
);
|
|
67
|
+
act(() => {
|
|
68
|
+
jest.runAllTimers();
|
|
69
|
+
});
|
|
47
70
|
fireEvent.press(screen.getByLabelText('Close sheet'));
|
|
48
71
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
49
72
|
});
|
|
50
73
|
|
|
51
74
|
it('hides close button when showCloseButton is false', () => {
|
|
52
75
|
render(<Sheet {...defaultProps} title='Title' showCloseButton={false} />);
|
|
76
|
+
act(() => {
|
|
77
|
+
jest.runAllTimers();
|
|
78
|
+
});
|
|
53
79
|
expect(screen.queryByLabelText('Close sheet')).toBeNull();
|
|
54
80
|
});
|
|
55
81
|
|
|
56
82
|
it('renders footer when provided', () => {
|
|
57
83
|
render(<Sheet {...defaultProps} footer={<Text>Footer area</Text>} />);
|
|
84
|
+
act(() => {
|
|
85
|
+
jest.runAllTimers();
|
|
86
|
+
});
|
|
58
87
|
expect(screen.getByText('Footer area')).toBeTruthy();
|
|
59
88
|
});
|
|
60
89
|
|
|
@@ -67,6 +96,9 @@ describe('Sheet', () => {
|
|
|
67
96
|
<Text>Size {size}</Text>
|
|
68
97
|
</Sheet>
|
|
69
98
|
);
|
|
99
|
+
act(() => {
|
|
100
|
+
jest.runAllTimers();
|
|
101
|
+
});
|
|
70
102
|
expect(screen.getByText(`Size ${size}`)).toBeTruthy();
|
|
71
103
|
unmount();
|
|
72
104
|
});
|
|
@@ -81,6 +113,9 @@ describe('Sheet', () => {
|
|
|
81
113
|
<Text>Side {side}</Text>
|
|
82
114
|
</Sheet>
|
|
83
115
|
);
|
|
116
|
+
act(() => {
|
|
117
|
+
jest.runAllTimers();
|
|
118
|
+
});
|
|
84
119
|
expect(screen.getByText(`Side ${side}`)).toBeTruthy();
|
|
85
120
|
unmount();
|
|
86
121
|
});
|
|
@@ -88,6 +123,9 @@ describe('Sheet', () => {
|
|
|
88
123
|
|
|
89
124
|
it('renders without drag handle when showHandle is false', () => {
|
|
90
125
|
const { toJSON } = render(<Sheet {...defaultProps} showHandle={false} />);
|
|
126
|
+
act(() => {
|
|
127
|
+
jest.runAllTimers();
|
|
128
|
+
});
|
|
91
129
|
// When showHandle is false, the drag handle View is not rendered
|
|
92
130
|
expect(screen.getByText('Sheet content')).toBeTruthy();
|
|
93
131
|
expect(toJSON()).toBeTruthy();
|
|
@@ -105,6 +143,9 @@ describe('Sheet', () => {
|
|
|
105
143
|
<Text>Main content</Text>
|
|
106
144
|
</Sheet>
|
|
107
145
|
);
|
|
146
|
+
act(() => {
|
|
147
|
+
jest.runAllTimers();
|
|
148
|
+
});
|
|
108
149
|
expect(screen.getByText('Full Sheet')).toBeTruthy();
|
|
109
150
|
expect(screen.getByText('A full sheet example')).toBeTruthy();
|
|
110
151
|
expect(screen.getByText('Main content')).toBeTruthy();
|
|
@@ -4,6 +4,14 @@ import { Text, Pressable } from 'react-native';
|
|
|
4
4
|
import { Toast, ToastProvider, useToast } from '../ui/Toast';
|
|
5
5
|
import type { ToastMessage } from '../ui/Toast';
|
|
6
6
|
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
jest.useFakeTimers();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
jest.useRealTimers();
|
|
13
|
+
});
|
|
14
|
+
|
|
7
15
|
describe('Toast', () => {
|
|
8
16
|
const baseToast: ToastMessage = {
|
|
9
17
|
id: 'test-1',
|
|
@@ -14,16 +22,25 @@ describe('Toast', () => {
|
|
|
14
22
|
|
|
15
23
|
it('renders title', () => {
|
|
16
24
|
render(<Toast toast={baseToast} onRemove={jest.fn()} />);
|
|
25
|
+
act(() => {
|
|
26
|
+
jest.runAllTimers();
|
|
27
|
+
});
|
|
17
28
|
expect(screen.getByText('Test Toast')).toBeTruthy();
|
|
18
29
|
});
|
|
19
30
|
|
|
20
31
|
it('renders description', () => {
|
|
21
32
|
render(<Toast toast={baseToast} onRemove={jest.fn()} />);
|
|
33
|
+
act(() => {
|
|
34
|
+
jest.runAllTimers();
|
|
35
|
+
});
|
|
22
36
|
expect(screen.getByText('This is a test toast')).toBeTruthy();
|
|
23
37
|
});
|
|
24
38
|
|
|
25
39
|
it('renders close button', () => {
|
|
26
40
|
render(<Toast toast={baseToast} onRemove={jest.fn()} />);
|
|
41
|
+
act(() => {
|
|
42
|
+
jest.runAllTimers();
|
|
43
|
+
});
|
|
27
44
|
const closeButton = screen.getByLabelText('Close notification');
|
|
28
45
|
expect(closeButton).toBeTruthy();
|
|
29
46
|
});
|
|
@@ -31,6 +48,9 @@ describe('Toast', () => {
|
|
|
31
48
|
it('calls onRemove when close button is pressed', () => {
|
|
32
49
|
const onRemove = jest.fn();
|
|
33
50
|
render(<Toast toast={baseToast} onRemove={onRemove} />);
|
|
51
|
+
act(() => {
|
|
52
|
+
jest.runAllTimers();
|
|
53
|
+
});
|
|
34
54
|
fireEvent.press(screen.getByLabelText('Close notification'));
|
|
35
55
|
expect(onRemove).toHaveBeenCalledWith('test-1');
|
|
36
56
|
});
|
|
@@ -42,6 +62,9 @@ describe('Toast', () => {
|
|
|
42
62
|
action: { label: 'Undo', onPress: onAction },
|
|
43
63
|
};
|
|
44
64
|
render(<Toast toast={toastWithAction} onRemove={jest.fn()} />);
|
|
65
|
+
act(() => {
|
|
66
|
+
jest.runAllTimers();
|
|
67
|
+
});
|
|
45
68
|
expect(screen.getByText('Undo')).toBeTruthy();
|
|
46
69
|
fireEvent.press(screen.getByText('Undo'));
|
|
47
70
|
expect(onAction).toHaveBeenCalledTimes(1);
|
|
@@ -59,6 +82,9 @@ describe('Toast', () => {
|
|
|
59
82
|
variants.forEach(variant => {
|
|
60
83
|
const toast: ToastMessage = { ...baseToast, variant, id: variant };
|
|
61
84
|
const { unmount } = render(<Toast toast={toast} onRemove={jest.fn()} />);
|
|
85
|
+
act(() => {
|
|
86
|
+
jest.runAllTimers();
|
|
87
|
+
});
|
|
62
88
|
expect(screen.getByText('Test Toast')).toBeTruthy();
|
|
63
89
|
unmount();
|
|
64
90
|
});
|
|
@@ -70,6 +96,9 @@ describe('Toast', () => {
|
|
|
70
96
|
description: 'Description only',
|
|
71
97
|
};
|
|
72
98
|
render(<Toast toast={toast} onRemove={jest.fn()} />);
|
|
99
|
+
act(() => {
|
|
100
|
+
jest.runAllTimers();
|
|
101
|
+
});
|
|
73
102
|
expect(screen.getByText('Description only')).toBeTruthy();
|
|
74
103
|
});
|
|
75
104
|
|
|
@@ -79,6 +108,9 @@ describe('Toast', () => {
|
|
|
79
108
|
title: 'Title only',
|
|
80
109
|
};
|
|
81
110
|
render(<Toast toast={toast} onRemove={jest.fn()} />);
|
|
111
|
+
act(() => {
|
|
112
|
+
jest.runAllTimers();
|
|
113
|
+
});
|
|
82
114
|
expect(screen.getByText('Title only')).toBeTruthy();
|
|
83
115
|
});
|
|
84
116
|
});
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Text } from 'react-native';
|
|
3
|
+
import { cn } from '../../lib/utils';
|
|
4
|
+
|
|
5
|
+
export interface AppVersionProps {
|
|
6
|
+
/** App display name */
|
|
7
|
+
appName: string;
|
|
8
|
+
/** Version string (e.g. from package.json) */
|
|
9
|
+
version: string;
|
|
10
|
+
/** Additional className */
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* AppVersion Component
|
|
16
|
+
*
|
|
17
|
+
* Displays the app name and version in a muted text style.
|
|
18
|
+
* Reads the version from the consuming app's package.json.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* import { version } from '../package.json';
|
|
23
|
+
* <AppVersion appName="MyApp" version={version} />
|
|
24
|
+
* // renders: "MyApp v1.0.0"
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export const AppVersion: React.FC<AppVersionProps> = ({
|
|
28
|
+
appName,
|
|
29
|
+
version,
|
|
30
|
+
className,
|
|
31
|
+
}) => {
|
|
32
|
+
return (
|
|
33
|
+
<Text
|
|
34
|
+
className={cn(
|
|
35
|
+
'text-sm text-gray-500 dark:text-gray-400 text-center',
|
|
36
|
+
className
|
|
37
|
+
)}
|
|
38
|
+
>
|
|
39
|
+
{appName} v{version}
|
|
40
|
+
</Text>
|
|
41
|
+
);
|
|
42
|
+
};
|