cpk-ui 0.5.5 → 0.7.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/README.md +80 -147
- package/components/modals/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/components/modals/AlertDialog/AlertDialog.js +14 -7
- package/components/modals/Snackbar/Snackbar.d.ts.map +1 -1
- package/components/modals/Snackbar/Snackbar.js +20 -17
- package/components/uis/Accordion/AccordionItem.d.ts.map +1 -1
- package/components/uis/Accordion/AccordionItem.js +41 -17
- package/components/uis/Button/Button.d.ts.map +1 -1
- package/components/uis/Button/Button.js +10 -10
- package/components/uis/Card/Card.d.ts +2 -1
- package/components/uis/Card/Card.d.ts.map +1 -1
- package/components/uis/Card/Card.js +12 -3
- package/components/uis/Checkbox/Checkbox.d.ts.map +1 -1
- package/components/uis/Checkbox/Checkbox.js +1 -1
- package/components/uis/CustomPressable/CustomPressable.d.ts.map +1 -1
- package/components/uis/CustomPressable/CustomPressable.js +6 -6
- package/components/uis/EditText/EditText.d.ts.map +1 -1
- package/components/uis/EditText/EditText.js +17 -12
- package/components/uis/Fab/Fab.d.ts +2 -2
- package/components/uis/Fab/Fab.d.ts.map +1 -1
- package/components/uis/Fab/Fab.js +22 -4
- package/components/uis/Icon/Icon.d.ts.map +1 -1
- package/components/uis/Icon/Icon.js +6 -3
- package/components/uis/IconButton/IconButton.d.ts.map +1 -1
- package/components/uis/IconButton/IconButton.js +43 -41
- package/components/uis/LoadingIndicator/LoadingIndicator.d.ts +2 -1
- package/components/uis/LoadingIndicator/LoadingIndicator.d.ts.map +1 -1
- package/components/uis/LoadingIndicator/LoadingIndicator.js +4 -4
- package/components/uis/RadioGroup/RadioButton.d.ts.map +1 -1
- package/components/uis/RadioGroup/RadioButton.js +1 -1
- package/components/uis/RadioGroup/RadioGroup.d.ts.map +1 -1
- package/components/uis/RadioGroup/RadioGroup.js +16 -3
- package/components/uis/Rating/Rating.d.ts.map +1 -1
- package/components/uis/Rating/Rating.js +23 -19
- package/components/uis/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/components/uis/SegmentedControl/SegmentedControl.js +1 -1
- package/components/uis/StatusbarBrightness/StatusBarBrightness.d.ts +2 -2
- package/components/uis/StatusbarBrightness/StatusBarBrightness.d.ts.map +1 -1
- package/components/uis/StatusbarBrightness/StatusBarBrightness.js +1 -1
- package/components/uis/SwitchToggle/SwitchToggle.d.ts.map +1 -1
- package/components/uis/SwitchToggle/SwitchToggle.js +1 -1
- package/hooks/useHoverState.d.ts +8 -0
- package/hooks/useHoverState.d.ts.map +1 -0
- package/hooks/useHoverState.js +16 -0
- package/package.json +18 -6
- package/providers/ThemeProvider.d.ts.map +1 -1
- package/providers/ThemeProvider.js +0 -1
- package/providers/index.d.ts.map +1 -1
- package/providers/index.js +3 -2
- package/components/uis/Icon/selection.json +0 -1
- package/src/components/common/ErrorBoundary/ErrorBoundary.tsx +0 -75
- package/src/components/modals/AlertDialog/AlertDialog.stories.tsx +0 -216
- package/src/components/modals/AlertDialog/AlertDialog.test.tsx +0 -251
- package/src/components/modals/AlertDialog/AlertDialog.tsx +0 -356
- package/src/components/modals/Snackbar/Snackbar.stories.tsx +0 -182
- package/src/components/modals/Snackbar/Snackbar.test.tsx +0 -319
- package/src/components/modals/Snackbar/Snackbar.tsx +0 -260
- package/src/components/modals/Snackbar/const.ts +0 -4
- package/src/components/uis/Accordion/Accordion.stories.tsx +0 -167
- package/src/components/uis/Accordion/Accordion.test.tsx +0 -272
- package/src/components/uis/Accordion/Accordion.tsx +0 -109
- package/src/components/uis/Accordion/AccordionItem.tsx +0 -306
- package/src/components/uis/Button/Button.stories.tsx +0 -218
- package/src/components/uis/Button/Button.test.tsx +0 -694
- package/src/components/uis/Button/Button.tsx +0 -440
- package/src/components/uis/Card/Card.test.tsx +0 -146
- package/src/components/uis/Card/Card.tsx +0 -102
- package/src/components/uis/Checkbox/Checkbox.stories.tsx +0 -216
- package/src/components/uis/Checkbox/Checkbox.test.tsx +0 -267
- package/src/components/uis/Checkbox/Checkbox.tsx +0 -225
- package/src/components/uis/CustomPressable/CustomPressable.tsx +0 -48
- package/src/components/uis/EditText/EditText.stories.tsx +0 -124
- package/src/components/uis/EditText/EditText.test.tsx +0 -477
- package/src/components/uis/EditText/EditText.tsx +0 -593
- package/src/components/uis/Fab/Fab.stories.tsx +0 -133
- package/src/components/uis/Fab/Fab.test.tsx +0 -110
- package/src/components/uis/Fab/Fab.tsx +0 -168
- package/src/components/uis/Hr/Hr.test.tsx +0 -26
- package/src/components/uis/Hr/Hr.tsx +0 -19
- package/src/components/uis/Icon/Icon.stories.tsx +0 -98
- package/src/components/uis/Icon/Icon.test.tsx +0 -49
- package/src/components/uis/Icon/Icon.tsx +0 -3819
- package/src/components/uis/IconButton/IconButton.test.tsx +0 -204
- package/src/components/uis/IconButton/IconButton.tsx +0 -279
- package/src/components/uis/LoadingIndicator/LoadingIndicator.tsx +0 -126
- package/src/components/uis/LoadingIndicator/LodingIndicator.stories.tsx +0 -81
- package/src/components/uis/PinchZoom/PinchZoom.stories.tsx +0 -266
- package/src/components/uis/PinchZoom/PinchZoom.test.tsx +0 -113
- package/src/components/uis/PinchZoom/PinchZoom.tsx +0 -424
- package/src/components/uis/RadioGroup/RadioButton.tsx +0 -193
- package/src/components/uis/RadioGroup/RadioGroup.stories.tsx +0 -188
- package/src/components/uis/RadioGroup/RadioGroup.test.tsx +0 -354
- package/src/components/uis/RadioGroup/RadioGroup.tsx +0 -109
- package/src/components/uis/Rating/Rating.test.tsx +0 -98
- package/src/components/uis/Rating/Rating.tsx +0 -200
- package/src/components/uis/SegmentedControl/SegmentedControl.stories.tsx +0 -546
- package/src/components/uis/SegmentedControl/SegmentedControl.test.tsx +0 -274
- package/src/components/uis/SegmentedControl/SegmentedControl.tsx +0 -232
- package/src/components/uis/StatusbarBrightness/StatusBarBrightness.test.tsx +0 -41
- package/src/components/uis/StatusbarBrightness/StatusBarBrightness.tsx +0 -26
- package/src/components/uis/Styled/StyledComponents.tsx +0 -217
- package/src/components/uis/SwitchToggle/SwitchToggle.stories.tsx +0 -75
- package/src/components/uis/SwitchToggle/SwitchToggle.test.tsx +0 -149
- package/src/components/uis/SwitchToggle/SwitchToggle.tsx +0 -309
- package/src/components/uis/Typography/Typography.stories.tsx +0 -149
- package/src/components/uis/Typography/Typography.test.tsx +0 -58
- package/src/components/uis/Typography/Typography.tsx +0 -386
- package/src/hooks/index.ts +0 -2
- package/src/hooks/useAnimations.ts +0 -71
- package/src/hooks/useDebouncedColorScheme.tsx +0 -30
- package/src/hooks/useOptimizedStyles.ts +0 -22
- package/src/hooks/usePerformance.ts +0 -93
- package/src/index.tsx +0 -38
- package/src/providers/ThemeProvider.tsx +0 -177
- package/src/providers/index.tsx +0 -130
- package/src/test/testUtils.tsx +0 -101
- package/src/types/common.ts +0 -77
- package/src/types/index.ts +0 -1
- package/src/types/kstyled.d.ts +0 -6
- package/src/utils/accessibility.ts +0 -110
- package/src/utils/colors.ts +0 -151
- package/src/utils/createCtx.tsx +0 -26
- package/src/utils/guards.ts +0 -93
- package/src/utils/index.ts +0 -2
- package/src/utils/performanceTest.ts +0 -174
- package/src/utils/platform.ts +0 -69
- package/src/utils/theme.ts +0 -38
- package/test/testUtils.d.ts +0 -113
- package/test/testUtils.d.ts.map +0 -1
- package/test/testUtils.js +0 -65
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
import '@testing-library/jest-native/extend-expect';
|
|
2
|
-
|
|
3
|
-
import React, {type ReactElement, useRef} from 'react';
|
|
4
|
-
import type {RenderAPI} from '@testing-library/react-native';
|
|
5
|
-
import {render, waitFor} from '@testing-library/react-native';
|
|
6
|
-
|
|
7
|
-
import {createComponent} from '../../../../test/testUtils';
|
|
8
|
-
import Snackbar, {type SnackbarContext} from './Snackbar';
|
|
9
|
-
import {ThemeType} from '../../../providers/ThemeProvider';
|
|
10
|
-
|
|
11
|
-
let testingLib: RenderAPI;
|
|
12
|
-
|
|
13
|
-
const TestComponent = ({
|
|
14
|
-
themeType,
|
|
15
|
-
}: {
|
|
16
|
-
themeType?: ThemeType;
|
|
17
|
-
}): ReactElement => {
|
|
18
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
19
|
-
|
|
20
|
-
return createComponent(<Snackbar ref={snackbarRef} />, themeType);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
describe('[Snackbar]', () => {
|
|
24
|
-
it('should render without crashing', () => {
|
|
25
|
-
testingLib = render(<TestComponent />);
|
|
26
|
-
|
|
27
|
-
const json = testingLib.toJSON();
|
|
28
|
-
expect(json).toBeTruthy();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe('Size prop', () => {
|
|
32
|
-
it('should accept small size', async () => {
|
|
33
|
-
const TestWithSize = (): ReactElement => {
|
|
34
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
35
|
-
|
|
36
|
-
React.useEffect(() => {
|
|
37
|
-
snackbarRef.current?.open({
|
|
38
|
-
text: 'Test message',
|
|
39
|
-
size: 'small',
|
|
40
|
-
timer: 10000,
|
|
41
|
-
});
|
|
42
|
-
}, []);
|
|
43
|
-
|
|
44
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
testingLib = render(<TestWithSize />);
|
|
48
|
-
|
|
49
|
-
await waitFor(() => {
|
|
50
|
-
expect(testingLib.getByText('Test message')).toBeTruthy();
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('should accept medium size', async () => {
|
|
55
|
-
const TestWithSize = (): ReactElement => {
|
|
56
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
57
|
-
|
|
58
|
-
React.useEffect(() => {
|
|
59
|
-
snackbarRef.current?.open({
|
|
60
|
-
text: 'Test message',
|
|
61
|
-
size: 'medium',
|
|
62
|
-
timer: 10000,
|
|
63
|
-
});
|
|
64
|
-
}, []);
|
|
65
|
-
|
|
66
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
testingLib = render(<TestWithSize />);
|
|
70
|
-
|
|
71
|
-
await waitFor(() => {
|
|
72
|
-
expect(testingLib.getByText('Test message')).toBeTruthy();
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should accept large size', async () => {
|
|
77
|
-
const TestWithSize = (): ReactElement => {
|
|
78
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
79
|
-
|
|
80
|
-
React.useEffect(() => {
|
|
81
|
-
snackbarRef.current?.open({
|
|
82
|
-
text: 'Test message',
|
|
83
|
-
size: 'large',
|
|
84
|
-
timer: 10000,
|
|
85
|
-
});
|
|
86
|
-
}, []);
|
|
87
|
-
|
|
88
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
testingLib = render(<TestWithSize />);
|
|
92
|
-
|
|
93
|
-
await waitFor(() => {
|
|
94
|
-
expect(testingLib.getByText('Test message')).toBeTruthy();
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should accept custom numeric size', async () => {
|
|
99
|
-
const TestWithSize = (): ReactElement => {
|
|
100
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
101
|
-
|
|
102
|
-
React.useEffect(() => {
|
|
103
|
-
snackbarRef.current?.open({
|
|
104
|
-
text: 'Test message',
|
|
105
|
-
size: 18,
|
|
106
|
-
timer: 10000,
|
|
107
|
-
});
|
|
108
|
-
}, []);
|
|
109
|
-
|
|
110
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
testingLib = render(<TestWithSize />);
|
|
114
|
-
|
|
115
|
-
await waitFor(() => {
|
|
116
|
-
expect(testingLib.getByText('Test message')).toBeTruthy();
|
|
117
|
-
});
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should default to medium size when size is not specified', async () => {
|
|
121
|
-
const TestWithoutSize = (): ReactElement => {
|
|
122
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
123
|
-
|
|
124
|
-
React.useEffect(() => {
|
|
125
|
-
snackbarRef.current?.open({
|
|
126
|
-
text: 'Test message',
|
|
127
|
-
timer: 10000,
|
|
128
|
-
});
|
|
129
|
-
}, []);
|
|
130
|
-
|
|
131
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
testingLib = render(<TestWithoutSize />);
|
|
135
|
-
|
|
136
|
-
await waitFor(() => {
|
|
137
|
-
expect(testingLib.getByText('Test message')).toBeTruthy();
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
describe('Content rendering', () => {
|
|
143
|
-
it('should render text message', async () => {
|
|
144
|
-
const TestWithText = (): ReactElement => {
|
|
145
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
146
|
-
|
|
147
|
-
React.useEffect(() => {
|
|
148
|
-
snackbarRef.current?.open({
|
|
149
|
-
text: 'Snackbar message content',
|
|
150
|
-
size: 'medium',
|
|
151
|
-
timer: 10000,
|
|
152
|
-
});
|
|
153
|
-
}, []);
|
|
154
|
-
|
|
155
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
testingLib = render(<TestWithText />);
|
|
159
|
-
|
|
160
|
-
await waitFor(() => {
|
|
161
|
-
expect(testingLib.getByText('Snackbar message content')).toBeTruthy();
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('should render with action text', async () => {
|
|
166
|
-
const TestWithAction = (): ReactElement => {
|
|
167
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
168
|
-
|
|
169
|
-
React.useEffect(() => {
|
|
170
|
-
snackbarRef.current?.open({
|
|
171
|
-
text: 'Action test',
|
|
172
|
-
actionText: 'Undo',
|
|
173
|
-
size: 'medium',
|
|
174
|
-
timer: 10000,
|
|
175
|
-
});
|
|
176
|
-
}, []);
|
|
177
|
-
|
|
178
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
testingLib = render(<TestWithAction />);
|
|
182
|
-
|
|
183
|
-
await waitFor(() => {
|
|
184
|
-
expect(testingLib.getByText('Action test')).toBeTruthy();
|
|
185
|
-
expect(testingLib.getByText('Undo')).toBeTruthy();
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
describe('Color variants', () => {
|
|
191
|
-
it('should render with primary color', async () => {
|
|
192
|
-
const TestWithColor = (): ReactElement => {
|
|
193
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
194
|
-
|
|
195
|
-
React.useEffect(() => {
|
|
196
|
-
snackbarRef.current?.open({
|
|
197
|
-
text: 'Primary color',
|
|
198
|
-
color: 'primary',
|
|
199
|
-
size: 'medium',
|
|
200
|
-
timer: 10000,
|
|
201
|
-
});
|
|
202
|
-
}, []);
|
|
203
|
-
|
|
204
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
testingLib = render(<TestWithColor />);
|
|
208
|
-
|
|
209
|
-
await waitFor(() => {
|
|
210
|
-
expect(testingLib.getByText('Primary color')).toBeTruthy();
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('should render with danger color', async () => {
|
|
215
|
-
const TestWithColor = (): ReactElement => {
|
|
216
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
217
|
-
|
|
218
|
-
React.useEffect(() => {
|
|
219
|
-
snackbarRef.current?.open({
|
|
220
|
-
text: 'Danger color',
|
|
221
|
-
color: 'danger',
|
|
222
|
-
size: 'medium',
|
|
223
|
-
timer: 10000,
|
|
224
|
-
});
|
|
225
|
-
}, []);
|
|
226
|
-
|
|
227
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
228
|
-
};
|
|
229
|
-
|
|
230
|
-
testingLib = render(<TestWithColor />);
|
|
231
|
-
|
|
232
|
-
await waitFor(() => {
|
|
233
|
-
expect(testingLib.getByText('Danger color')).toBeTruthy();
|
|
234
|
-
});
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('should render with info color', async () => {
|
|
238
|
-
const TestWithColor = (): ReactElement => {
|
|
239
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
240
|
-
|
|
241
|
-
React.useEffect(() => {
|
|
242
|
-
snackbarRef.current?.open({
|
|
243
|
-
text: 'Info color',
|
|
244
|
-
color: 'info',
|
|
245
|
-
size: 'medium',
|
|
246
|
-
timer: 10000,
|
|
247
|
-
});
|
|
248
|
-
}, []);
|
|
249
|
-
|
|
250
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
testingLib = render(<TestWithColor />);
|
|
254
|
-
|
|
255
|
-
await waitFor(() => {
|
|
256
|
-
expect(testingLib.getByText('Info color')).toBeTruthy();
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
describe('Close functionality', () => {
|
|
262
|
-
it('should close snackbar when close is called', async () => {
|
|
263
|
-
const TestWithClose = (): ReactElement => {
|
|
264
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
265
|
-
|
|
266
|
-
React.useEffect(() => {
|
|
267
|
-
snackbarRef.current?.open({
|
|
268
|
-
text: 'Test message',
|
|
269
|
-
size: 'medium',
|
|
270
|
-
timer: 10000,
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
setTimeout(() => {
|
|
274
|
-
snackbarRef.current?.close();
|
|
275
|
-
}, 100);
|
|
276
|
-
}, []);
|
|
277
|
-
|
|
278
|
-
return createComponent(<Snackbar ref={snackbarRef} />);
|
|
279
|
-
};
|
|
280
|
-
|
|
281
|
-
testingLib = render(<TestWithClose />);
|
|
282
|
-
|
|
283
|
-
await waitFor(() => {
|
|
284
|
-
expect(testingLib.getByText('Test message')).toBeTruthy();
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
await waitFor(
|
|
288
|
-
() => {
|
|
289
|
-
expect(testingLib.queryByText('Test message')).toBeNull();
|
|
290
|
-
},
|
|
291
|
-
{timeout: 500},
|
|
292
|
-
);
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
describe('Dark mode', () => {
|
|
297
|
-
it('should render in dark mode', async () => {
|
|
298
|
-
const TestDarkMode = (): ReactElement => {
|
|
299
|
-
const snackbarRef = useRef<SnackbarContext>(null);
|
|
300
|
-
|
|
301
|
-
React.useEffect(() => {
|
|
302
|
-
snackbarRef.current?.open({
|
|
303
|
-
text: 'Dark mode message',
|
|
304
|
-
size: 'medium',
|
|
305
|
-
timer: 10000,
|
|
306
|
-
});
|
|
307
|
-
}, []);
|
|
308
|
-
|
|
309
|
-
return createComponent(<Snackbar ref={snackbarRef} />, 'dark');
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
testingLib = render(<TestDarkMode />);
|
|
313
|
-
|
|
314
|
-
await waitFor(() => {
|
|
315
|
-
expect(testingLib.getByText('Dark mode message')).toBeTruthy();
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
});
|
|
319
|
-
});
|
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import React, {forwardRef, useImperativeHandle, useState, useCallback, useMemo, type ReactElement} from 'react';
|
|
2
|
-
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
|
|
3
|
-
import {Modal, Platform, SafeAreaView, StyleSheet, View} from 'react-native';
|
|
4
|
-
import {styled, css} from 'kstyled';
|
|
5
|
-
|
|
6
|
-
import {SnackbarTimer} from './const';
|
|
7
|
-
import {Button, ButtonColorType} from '../../uis/Button/Button';
|
|
8
|
-
import {useTheme} from '../../../providers/ThemeProvider';
|
|
9
|
-
import {Icon} from '../../uis/Icon/Icon';
|
|
10
|
-
import {Typography} from '../../uis/Typography/Typography';
|
|
11
|
-
|
|
12
|
-
export type SnackbarSizeType = 'small' | 'medium' | 'large' | number;
|
|
13
|
-
|
|
14
|
-
const calculateSpacing = (size: SnackbarSizeType = 'medium'): number => {
|
|
15
|
-
if (typeof size === 'number') return size * 0.75;
|
|
16
|
-
return size === 'small' ? 10 : size === 'large' ? 14 : 12;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const Container = styled(View)`
|
|
20
|
-
flex: 1;
|
|
21
|
-
align-self: stretch;
|
|
22
|
-
|
|
23
|
-
flex-direction: row;
|
|
24
|
-
justify-content: center;
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
const SnackbarContainer = styled(SafeAreaView)<{$color: ButtonColorType; $size?: SnackbarSizeType}>`
|
|
28
|
-
background-color: ${({theme, $color}) => theme.button[$color].bg};
|
|
29
|
-
border-radius: 8px;
|
|
30
|
-
margin-bottom: 52px;
|
|
31
|
-
margin-left: ${({$size}) => calculateSpacing($size)};
|
|
32
|
-
margin-right: ${({$size}) => calculateSpacing($size)};
|
|
33
|
-
align-self: flex-end;
|
|
34
|
-
|
|
35
|
-
flex-direction: row;
|
|
36
|
-
align-items: center;
|
|
37
|
-
`;
|
|
38
|
-
|
|
39
|
-
const ActionContainer = styled(View)`
|
|
40
|
-
margin-right: 4px;
|
|
41
|
-
`;
|
|
42
|
-
|
|
43
|
-
const SnackbarText = styled(Typography.Body2)<{$color: ButtonColorType; $size?: SnackbarSizeType}>`
|
|
44
|
-
color: ${({theme, $color}) => theme.button[$color].text};
|
|
45
|
-
flex: 1;
|
|
46
|
-
padding: ${({$size}) => calculateSpacing($size)};
|
|
47
|
-
`;
|
|
48
|
-
|
|
49
|
-
export type SnackbarProps = {
|
|
50
|
-
style?: StyleProp<ViewStyle>;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export type SnackbarStyles = {
|
|
54
|
-
container?: StyleProp<ViewStyle>;
|
|
55
|
-
text?: StyleProp<TextStyle>;
|
|
56
|
-
actionContainer?: StyleProp<ViewStyle>;
|
|
57
|
-
actionText?: StyleProp<TextStyle>;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export type SnackbarOptions = {
|
|
61
|
-
color?: ButtonColorType;
|
|
62
|
-
styles?: SnackbarStyles;
|
|
63
|
-
text?: string;
|
|
64
|
-
actionText?: string;
|
|
65
|
-
timer?: SnackbarTimer | number;
|
|
66
|
-
size?: SnackbarSizeType;
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
export type SnackbarContext = {
|
|
70
|
-
open(snackbarOptions?: SnackbarOptions): void;
|
|
71
|
-
close(): void;
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
let timer: NodeJS.Timeout | null = null;
|
|
75
|
-
|
|
76
|
-
function clearTimer(): void {
|
|
77
|
-
if (timer) {
|
|
78
|
-
clearTimeout(timer);
|
|
79
|
-
timer = null;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function Snackbar(
|
|
84
|
-
{style}: SnackbarProps,
|
|
85
|
-
ref: React.Ref<SnackbarContext>,
|
|
86
|
-
): ReactElement {
|
|
87
|
-
const [options, setOptions] = useState<SnackbarOptions | null>(null);
|
|
88
|
-
const [visible, setVisible] = useState(false);
|
|
89
|
-
const {theme} = useTheme();
|
|
90
|
-
|
|
91
|
-
// Memoize the close handler
|
|
92
|
-
const handleClose = useCallback(() => {
|
|
93
|
-
setVisible(false);
|
|
94
|
-
setOptions(null);
|
|
95
|
-
}, []);
|
|
96
|
-
|
|
97
|
-
// Memoize the open handler
|
|
98
|
-
const handleOpen = useCallback((snackbarOptions?: SnackbarOptions) => {
|
|
99
|
-
clearTimer();
|
|
100
|
-
setVisible(true);
|
|
101
|
-
if (snackbarOptions) {
|
|
102
|
-
setOptions(snackbarOptions);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
timer = setTimeout(() => {
|
|
106
|
-
setVisible(false);
|
|
107
|
-
clearTimer();
|
|
108
|
-
}, snackbarOptions?.timer ?? SnackbarTimer.SHORT);
|
|
109
|
-
}, []);
|
|
110
|
-
|
|
111
|
-
useImperativeHandle(ref, () => ({
|
|
112
|
-
open: handleOpen,
|
|
113
|
-
close: handleClose,
|
|
114
|
-
}), [handleOpen, handleClose]);
|
|
115
|
-
|
|
116
|
-
const {text, styles, actionText, color = 'primary', size = 'medium'} = options ?? {};
|
|
117
|
-
|
|
118
|
-
// Calculate sizes based on size prop
|
|
119
|
-
const sizeConfig = useMemo(() => {
|
|
120
|
-
if (typeof size === 'number') {
|
|
121
|
-
return {
|
|
122
|
-
fontSize: size,
|
|
123
|
-
iconSize: size,
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
switch (size) {
|
|
128
|
-
case 'small':
|
|
129
|
-
return {
|
|
130
|
-
fontSize: 12,
|
|
131
|
-
iconSize: 14,
|
|
132
|
-
};
|
|
133
|
-
case 'large':
|
|
134
|
-
return {
|
|
135
|
-
fontSize: 16,
|
|
136
|
-
iconSize: 18,
|
|
137
|
-
};
|
|
138
|
-
default: // 'medium'
|
|
139
|
-
return {
|
|
140
|
-
fontSize: 14,
|
|
141
|
-
iconSize: 16,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}, [size]);
|
|
145
|
-
|
|
146
|
-
// Memoize shadow styles
|
|
147
|
-
const shadowStyles = useMemo(() =>
|
|
148
|
-
Platform.OS !== 'web' ? {
|
|
149
|
-
shadowOffset: {width: 0, height: 4},
|
|
150
|
-
shadowColor: theme.text.basic,
|
|
151
|
-
} : {},
|
|
152
|
-
[theme.text.basic]
|
|
153
|
-
);
|
|
154
|
-
|
|
155
|
-
// Memoize container styles
|
|
156
|
-
const containerStyles = useMemo(() =>
|
|
157
|
-
StyleSheet.flatten([shadowStyles, styles?.container]),
|
|
158
|
-
[shadowStyles, styles?.container]
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
// Memoize text styles
|
|
162
|
-
const textStyles = useMemo(() =>
|
|
163
|
-
StyleSheet.flatten([
|
|
164
|
-
css`
|
|
165
|
-
color: ${theme.button[color].text};
|
|
166
|
-
font-size: ${sizeConfig.fontSize}px;
|
|
167
|
-
`,
|
|
168
|
-
styles?.text,
|
|
169
|
-
]),
|
|
170
|
-
[theme.button, color, sizeConfig.fontSize, styles?.text]
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
// Memoize action text styles
|
|
174
|
-
const actionTextStyles = useMemo(() =>
|
|
175
|
-
StyleSheet.flatten([
|
|
176
|
-
css`
|
|
177
|
-
color: ${theme.button[color].text};
|
|
178
|
-
`,
|
|
179
|
-
styles?.actionText,
|
|
180
|
-
]),
|
|
181
|
-
[theme.button, color, styles?.actionText]
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
// Memoize action button handler
|
|
185
|
-
const handleActionPress = useCallback(() => setVisible(false), []);
|
|
186
|
-
|
|
187
|
-
// Memoize modal styles
|
|
188
|
-
const modalStyles = useMemo(() => [
|
|
189
|
-
css`
|
|
190
|
-
flex: 1;
|
|
191
|
-
align-self: stretch;
|
|
192
|
-
`,
|
|
193
|
-
style,
|
|
194
|
-
], [style]);
|
|
195
|
-
|
|
196
|
-
const SnackbarContent = useMemo(() => (
|
|
197
|
-
<Container>
|
|
198
|
-
<SnackbarContainer
|
|
199
|
-
$color={color}
|
|
200
|
-
$size={size}
|
|
201
|
-
style={containerStyles}
|
|
202
|
-
>
|
|
203
|
-
<SnackbarText
|
|
204
|
-
$color={color}
|
|
205
|
-
$size={size}
|
|
206
|
-
style={textStyles}
|
|
207
|
-
>
|
|
208
|
-
{text}
|
|
209
|
-
</SnackbarText>
|
|
210
|
-
<ActionContainer style={styles?.actionContainer}>
|
|
211
|
-
{actionText ? (
|
|
212
|
-
<Button
|
|
213
|
-
onPress={handleActionPress}
|
|
214
|
-
styles={{
|
|
215
|
-
text: actionTextStyles,
|
|
216
|
-
}}
|
|
217
|
-
text={actionText}
|
|
218
|
-
type="text"
|
|
219
|
-
/>
|
|
220
|
-
) : (
|
|
221
|
-
<Button
|
|
222
|
-
onPress={handleActionPress}
|
|
223
|
-
text={<Icon color={theme.button[color].text} name="X" size={sizeConfig.iconSize} />}
|
|
224
|
-
type="text"
|
|
225
|
-
/>
|
|
226
|
-
)}
|
|
227
|
-
</ActionContainer>
|
|
228
|
-
</SnackbarContainer>
|
|
229
|
-
</Container>
|
|
230
|
-
), [
|
|
231
|
-
color,
|
|
232
|
-
size,
|
|
233
|
-
containerStyles,
|
|
234
|
-
textStyles,
|
|
235
|
-
text,
|
|
236
|
-
styles?.actionContainer,
|
|
237
|
-
actionText,
|
|
238
|
-
actionTextStyles,
|
|
239
|
-
handleActionPress,
|
|
240
|
-
sizeConfig.iconSize,
|
|
241
|
-
theme.button,
|
|
242
|
-
]);
|
|
243
|
-
|
|
244
|
-
return (
|
|
245
|
-
// https://github.com/facebook/react-native/issues/48526#issuecomment-2579478884
|
|
246
|
-
<View>
|
|
247
|
-
<Modal
|
|
248
|
-
animationType="fade"
|
|
249
|
-
style={modalStyles}
|
|
250
|
-
transparent={true}
|
|
251
|
-
visible={visible}
|
|
252
|
-
>
|
|
253
|
-
{SnackbarContent}
|
|
254
|
-
</Modal>
|
|
255
|
-
</View>
|
|
256
|
-
);
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// Export memoized component for better performance
|
|
260
|
-
export default React.memo(forwardRef<SnackbarContext, SnackbarProps>(Snackbar));
|