cpk-ui 0.0.1

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/README.md +27 -0
  2. package/components/modals/AlertDialog/AlertDialog.js +80 -0
  3. package/components/modals/AlertDialog/AlertDialog.stories.tsx +80 -0
  4. package/components/modals/AlertDialog/AlertDialog.tsx +194 -0
  5. package/components/modals/Snackbar/Snackbar.js +94 -0
  6. package/components/modals/Snackbar/Snackbar.stories.tsx +98 -0
  7. package/components/modals/Snackbar/Snackbar.tsx +174 -0
  8. package/components/modals/Snackbar/const.js +5 -0
  9. package/components/modals/Snackbar/const.ts +4 -0
  10. package/components/uis/Accordion/Accordion.js +11 -0
  11. package/components/uis/Accordion/Accordion.stories.tsx +38 -0
  12. package/components/uis/Accordion/Accordion.test.tsx +128 -0
  13. package/components/uis/Accordion/Accordion.tsx +58 -0
  14. package/components/uis/Accordion/AccordionItem.js +102 -0
  15. package/components/uis/Accordion/AccordionItem.tsx +213 -0
  16. package/components/uis/Button/Button.js +161 -0
  17. package/components/uis/Button/Button.stories.tsx +81 -0
  18. package/components/uis/Button/Button.test.tsx +560 -0
  19. package/components/uis/Button/Button.tsx +335 -0
  20. package/components/uis/Checkbox/Checkbox.js +70 -0
  21. package/components/uis/Checkbox/Checkbox.stories.tsx +46 -0
  22. package/components/uis/Checkbox/Checkbox.test.tsx +139 -0
  23. package/components/uis/Checkbox/Checkbox.tsx +150 -0
  24. package/components/uis/Icon/Icon.js +3780 -0
  25. package/components/uis/Icon/Icon.stories.tsx +45 -0
  26. package/components/uis/Icon/Icon.test.tsx +19 -0
  27. package/components/uis/Icon/Icon.tsx +3800 -0
  28. package/components/uis/Icon/Pretendard-Bold.otf +0 -0
  29. package/components/uis/Icon/Pretendard-Regular.otf +0 -0
  30. package/components/uis/Icon/Pretendard-Thin.otf +0 -0
  31. package/components/uis/Icon/cpk.ttf +0 -0
  32. package/components/uis/Icon/selection.json +1 -0
  33. package/components/uis/IconButton/IconButton.js +120 -0
  34. package/components/uis/IconButton/IconButton.test.tsx +165 -0
  35. package/components/uis/IconButton/IconButton.tsx +252 -0
  36. package/components/uis/LoadingIndicator/LoadingIndicator.js +24 -0
  37. package/components/uis/LoadingIndicator/LoadingIndicator.tsx +79 -0
  38. package/components/uis/Rating/Rating.js +53 -0
  39. package/components/uis/Rating/Rating.test.tsx +72 -0
  40. package/components/uis/Rating/Rating.tsx +155 -0
  41. package/components/uis/StatusbarBrightness/StatusBarBrightness.js +13 -0
  42. package/components/uis/StatusbarBrightness/StatusBarBrightness.test.tsx +41 -0
  43. package/components/uis/StatusbarBrightness/StatusBarBrightness.tsx +17 -0
  44. package/components/uis/Styled/StyledComponents.js +130 -0
  45. package/components/uis/Styled/StyledComponents.tsx +200 -0
  46. package/components/uis/SwitchToggle/SwitchToggle.js +126 -0
  47. package/components/uis/SwitchToggle/SwitchToggle.test.tsx +70 -0
  48. package/components/uis/SwitchToggle/SwitchToggle.tsx +224 -0
  49. package/components/uis/Typography/Typography.js +90 -0
  50. package/components/uis/Typography/Typography.test.tsx +58 -0
  51. package/components/uis/Typography/Typography.tsx +132 -0
  52. package/hooks/useDebouncedColorScheme.js +21 -0
  53. package/hooks/useDebouncedColorScheme.tsx +30 -0
  54. package/index.js +16 -0
  55. package/index.tsx +18 -0
  56. package/package.json +35 -0
  57. package/providers/ThemeProvider.js +106 -0
  58. package/providers/ThemeProvider.tsx +180 -0
  59. package/providers/index.js +62 -0
  60. package/providers/index.tsx +125 -0
  61. package/react-native.config.cjs +5 -0
  62. package/utils/colors.js +124 -0
  63. package/utils/colors.ts +127 -0
  64. package/utils/createCtx.js +15 -0
  65. package/utils/createCtx.tsx +26 -0
  66. package/utils/guards.js +44 -0
  67. package/utils/guards.ts +93 -0
  68. package/utils/theme.js +5 -0
  69. package/utils/theme.ts +33 -0
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # CPK-UI
2
+
3
+ React Native UI components for [Expo](https://expo.dev).
4
+
5
+ [![Npm Version](http://img.shields.io/npm/v/CPK-UI.svg?style=flat-square)](https://npmjs.org/package/CPK-UI)
6
+ [![Downloads](http://img.shields.io/npm/dm/CPK-UI.svg?style=flat-square)](https://npmjs.org/package/CPK-UI)
7
+ [![codecov](https://codecov.io/gh/crossplatformkorea/cpk-ui/graph/badge.svg?token=LWZI4U369L)](https://codecov.io/gh/crossplatformkorea/cpk-ui)
8
+ [![CI](https://github.com/crossplatformkorea/CPK-UI/actions/workflows/ci.yml/badge.svg)](https://github.com/crossplatformkorea/CPK-UI/actions/workflows/ci.yml)
9
+ [![gh-pages](https://github.com/crossplatformkorea/CPK-UI/actions/workflows/gh-pages.yml/badge.svg)](https://crossplatformkorea.github.io/CPK-UI)
10
+ [![Publish](https://github.com/crossplatformkorea/CPK-UI/actions/workflows/publish.yml/badge.svg)](https://github.com/crossplatformkorea/CPK-UI/actions/workflows/publish.yml)
11
+ [![Sponsor](https://opencollective.com/crossplatformkorea/tiers/badge.svg?style=shield)](https://opencollective.com/crossplatformkorea/tiers/badge.svg)
12
+
13
+ <img src="https://private-user-images.githubusercontent.com/27461460/398448953-c31ac1c2-cc0e-4f13-a542-c35045c266cd.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzUwNTk1ODcsIm5iZiI6MTczNTA1OTI4NywicGF0aCI6Ii8yNzQ2MTQ2MC8zOTg0NDg5NTMtYzMxYWMxYzItY2MwZS00ZjEzLWE1NDItYzM1MDQ1YzI2NmNkLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDEyMjQlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQxMjI0VDE2NTQ0N1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTcxN2ExN2YwZTEzZWEzZmVmZmQ4NDQ2OGJhN2E5ODIyZWI4MjJiM2RhNzI3YTRmZDYzNWZjODU5ZmJiZWJhY2MmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.QUUg_5gLMfBXDxQybO9ZA4zTS8no_0ZqXlFXEvuUhmk" width="320"/>
14
+
15
+ ## Documentation
16
+
17
+ Check out [ui.crossplatformkorea.com](https://ui.crossplatformkorea.com)
18
+
19
+ > Not all ui components are written in documents. Currently working :construction_worker:. Please see the [Demo](https://github.com/ui.crossplatformkorea/CPK-UI#demo) to see all components.
20
+
21
+ ## Demo
22
+
23
+ You can see live example at [https://crossplatformkorea.github.io/CPK-UI](https://crossplatformkorea.github.io/CPK-UI).
24
+
25
+ To run the storybook in your local environments. Follow [Contributing Guide](./Contributing).
26
+
27
+ > `Documentation` is not identical to `Demo`. `Demo` is just a playground whereas `documentation` is for the customers. Documentations are missing many features yet.
@@ -0,0 +1,80 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cloneElement, forwardRef, useImperativeHandle, useState, } from 'react';
3
+ import { Modal, Platform, StyleSheet, TouchableWithoutFeedback, } from 'react-native';
4
+ import styled, { css } from '@emotion/native';
5
+ import { useTheme } from '../../../providers/ThemeProvider';
6
+ import { Typography } from '../../uis/Typography/Typography';
7
+ import { Button } from '../../uis/Button/Button';
8
+ import { Icon } from '../../uis/Icon/Icon';
9
+ const Container = styled.View `
10
+ flex: 1;
11
+ justify-content: center;
12
+ align-items: center;
13
+
14
+ flex-direction: row;
15
+ `;
16
+ const AlertDialogContainer = styled.View `
17
+ flex: 0.87;
18
+ background-color: ${({ theme }) => theme.bg.basic};
19
+ padding: 20px 20px 28px 24px;
20
+ border-radius: 8px;
21
+ `;
22
+ const TitleRow = styled.View `
23
+ flex-direction: row;
24
+ justify-content: space-between;
25
+ align-items: center;
26
+ `;
27
+ const BodyRow = styled.View `
28
+ margin-top: 12px;
29
+ margin-bottom: 8px;
30
+ `;
31
+ const ActionRow = styled.View `
32
+ margin-top: 20px;
33
+ padding-right: 4px;
34
+ flex-direction: row;
35
+ `;
36
+ function AlertDialog({ style }, ref) {
37
+ const [options, setOptions] = useState(null);
38
+ const [visible, setVisible] = useState(false);
39
+ const { theme, themeType } = useTheme();
40
+ useImperativeHandle(ref, () => ({
41
+ open: (alertDialogOptions) => {
42
+ setVisible(true);
43
+ if (alertDialogOptions) {
44
+ setOptions(alertDialogOptions);
45
+ }
46
+ },
47
+ close: () => {
48
+ setVisible(false);
49
+ setOptions(null);
50
+ },
51
+ }));
52
+ const { backdropOpacity = 0.2, title, body, styles, actions, closeOnTouchOutside = true, } = options ?? {};
53
+ const AlertDialogContent = (_jsx(Container, { style: css `
54
+ background-color: ${themeType === 'light'
55
+ ? `rgba(0,0,0,${backdropOpacity})`
56
+ : `rgba(255,255,255,${backdropOpacity})`};
57
+ `, children: _jsxs(AlertDialogContainer, { style: StyleSheet.flatten([
58
+ Platform.OS !== 'web' && {
59
+ shadowOffset: { width: 0, height: 4 },
60
+ shadowColor: theme.text.basic,
61
+ },
62
+ styles?.container,
63
+ ]), children: [_jsxs(TitleRow, { style: styles?.titleContainer, children: [typeof title === 'string' ? (_jsx(Typography.Heading3, { style: styles?.title, children: title })) : (title), _jsx(Button, { onPress: () => setVisible(false), borderRadius: 24, text: _jsx(Icon, { color: theme.text.basic, name: "X", size: 18 }), type: "text" })] }), _jsx(BodyRow, { style: styles?.bodyContainer, children: typeof body === 'string' ? (_jsx(Typography.Body3, { style: styles?.body, children: body })) : (body) }), actions ? (_jsx(ActionRow, { style: styles?.actionContainer, children: actions.map((action, index) => cloneElement(action, {
64
+ key: `action-${index}`,
65
+ style: {
66
+ flex: 1,
67
+ marginLeft: index !== 0 ? 12 : 0,
68
+ },
69
+ })) })) : null] }) }));
70
+ return (_jsx(Modal, { animationType: "fade", style: [
71
+ css `
72
+ flex: 1;
73
+ align-self: stretch;
74
+ `,
75
+ style,
76
+ ], transparent: true, visible: visible, children: closeOnTouchOutside ? (_jsx(TouchableWithoutFeedback, { onPress: () => setVisible(false), style: css `
77
+ flex: 1;
78
+ `, children: AlertDialogContent })) : (AlertDialogContent) }));
79
+ }
80
+ export default forwardRef(AlertDialog);
@@ -0,0 +1,80 @@
1
+ import type {ComponentProps} from 'react';
2
+ import styled, {css} from '@emotion/native';
3
+ import type {Meta, StoryObj} from '@storybook/react';
4
+
5
+ import {withThemeProvider} from '../../../../.storybook/decorators';
6
+ import {useCPK} from '../../../providers';
7
+ import {Typography} from '../../uis/Typography/Typography';
8
+ import {Button} from '../../uis/Button/Button';
9
+ import AlertDialog from './AlertDialog';
10
+
11
+ const Container = styled.SafeAreaView`
12
+ background-color: ${({theme}) => theme.bg.basic};
13
+ `;
14
+
15
+ function AlertDialogBasicStory(): JSX.Element {
16
+ const {alertDialog} = useCPK();
17
+
18
+ return (
19
+ <Container
20
+ style={css`
21
+ flex-direction: column;
22
+ padding: 48px 24px;
23
+ align-self: stretch;
24
+ justify-content: center;
25
+ align-items: center;
26
+ `}
27
+ >
28
+ <Typography.Title>AlertDialog</Typography.Title>
29
+ <Button
30
+ color="primary"
31
+ onPress={() =>
32
+ alertDialog.open({
33
+ title: 'Hello there!',
34
+ body: 'This is an alert dialog.',
35
+ })
36
+ }
37
+ style={{marginTop: 60, width: 200}}
38
+ text="Dialog"
39
+ />
40
+ <Button
41
+ color="primary"
42
+ onPress={() =>
43
+ alertDialog.open({
44
+ title: 'Hello there!',
45
+ body: 'This is an alert dialog.',
46
+ actions: [
47
+ <Button
48
+ color="light"
49
+ key="button-cancel"
50
+ onPress={() => alertDialog.close()}
51
+ text="Cancel"
52
+ />,
53
+ <Button
54
+ key="button-ok"
55
+ onPress={() => alertDialog.close()}
56
+ text="OK"
57
+ />,
58
+ ],
59
+ })
60
+ }
61
+ style={{marginTop: 20, width: 200}}
62
+ text="With actions"
63
+ />
64
+ </Container>
65
+ );
66
+ }
67
+
68
+ const meta = {
69
+ title: 'AlertDialog',
70
+ component: AlertDialogBasicStory,
71
+ decorators: [withThemeProvider],
72
+ } satisfies Meta<typeof AlertDialog>;
73
+
74
+ export default meta;
75
+
76
+ type Story = StoryObj<typeof meta>;
77
+
78
+ export const Basic: Story = {
79
+ args: {},
80
+ };
@@ -0,0 +1,194 @@
1
+ import React, {
2
+ cloneElement,
3
+ forwardRef,
4
+ useImperativeHandle,
5
+ useState,
6
+ } from 'react';
7
+ import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
8
+ import {
9
+ Modal,
10
+ Platform,
11
+ StyleSheet,
12
+ TouchableWithoutFeedback,
13
+ } from 'react-native';
14
+ import styled, {css} from '@emotion/native';
15
+ import {useTheme} from '../../../providers/ThemeProvider';
16
+ import {Typography} from '../../uis/Typography/Typography';
17
+ import {Button} from '../../uis/Button/Button';
18
+ import {Icon} from '../../uis/Icon/Icon';
19
+
20
+ const Container = styled.View`
21
+ flex: 1;
22
+ justify-content: center;
23
+ align-items: center;
24
+
25
+ flex-direction: row;
26
+ `;
27
+
28
+ const AlertDialogContainer = styled.View`
29
+ flex: 0.87;
30
+ background-color: ${({theme}) => theme.bg.basic};
31
+ padding: 20px 20px 28px 24px;
32
+ border-radius: 8px;
33
+ `;
34
+
35
+ const TitleRow = styled.View`
36
+ flex-direction: row;
37
+ justify-content: space-between;
38
+ align-items: center;
39
+ `;
40
+
41
+ const BodyRow = styled.View`
42
+ margin-top: 12px;
43
+ margin-bottom: 8px;
44
+ `;
45
+
46
+ const ActionRow = styled.View`
47
+ margin-top: 20px;
48
+ padding-right: 4px;
49
+ flex-direction: row;
50
+ `;
51
+
52
+ export type AlertDialogProps = {
53
+ style?: StyleProp<ViewStyle>;
54
+ };
55
+
56
+ export type AlertDialogStyles = {
57
+ container?: StyleProp<ViewStyle>;
58
+ titleContainer?: StyleProp<ViewStyle>;
59
+ title?: StyleProp<TextStyle>;
60
+ bodyContainer?: StyleProp<ViewStyle>;
61
+ body?: StyleProp<TextStyle>;
62
+ actionContainer?: StyleProp<ViewStyle>;
63
+ };
64
+
65
+ export type AlertDialogOptions = {
66
+ styles?: AlertDialogStyles;
67
+ title?: string | JSX.Element;
68
+ body?: string | JSX.Element;
69
+ backdropOpacity?: number;
70
+ closeOnTouchOutside?: boolean;
71
+ actions?: JSX.Element[];
72
+ };
73
+
74
+ export type AlertDialogContext = {
75
+ open(alertDialogOptions?: AlertDialogOptions): void;
76
+ close(): void;
77
+ };
78
+
79
+ function AlertDialog(
80
+ {style}: AlertDialogProps,
81
+ ref: React.Ref<AlertDialogContext>,
82
+ ): JSX.Element {
83
+ const [options, setOptions] = useState<AlertDialogOptions | null>(null);
84
+ const [visible, setVisible] = useState(false);
85
+ const {theme, themeType} = useTheme();
86
+
87
+ useImperativeHandle(ref, () => ({
88
+ open: (alertDialogOptions) => {
89
+ setVisible(true);
90
+ if (alertDialogOptions) {
91
+ setOptions(alertDialogOptions);
92
+ }
93
+ },
94
+ close: () => {
95
+ setVisible(false);
96
+ setOptions(null);
97
+ },
98
+ }));
99
+
100
+ const {
101
+ backdropOpacity = 0.2,
102
+ title,
103
+ body,
104
+ styles,
105
+ actions,
106
+ closeOnTouchOutside = true,
107
+ } = options ?? {};
108
+
109
+ const AlertDialogContent = (
110
+ <Container
111
+ style={css`
112
+ background-color: ${themeType === 'light'
113
+ ? `rgba(0,0,0,${backdropOpacity})`
114
+ : `rgba(255,255,255,${backdropOpacity})`};
115
+ `}
116
+ >
117
+ <AlertDialogContainer
118
+ style={StyleSheet.flatten([
119
+ Platform.OS !== 'web' && {
120
+ shadowOffset: {width: 0, height: 4},
121
+ shadowColor: theme.text.basic,
122
+ },
123
+ styles?.container,
124
+ ])}
125
+ >
126
+ <TitleRow style={styles?.titleContainer}>
127
+ {typeof title === 'string' ? (
128
+ <Typography.Heading3 style={styles?.title}>
129
+ {title}
130
+ </Typography.Heading3>
131
+ ) : (
132
+ title
133
+ )}
134
+ <Button
135
+ onPress={() => setVisible(false)}
136
+ borderRadius={24}
137
+ text={<Icon color={theme.text.basic} name="X" size={18} />}
138
+ type="text"
139
+ />
140
+ </TitleRow>
141
+ <BodyRow style={styles?.bodyContainer}>
142
+ {typeof body === 'string' ? (
143
+ <Typography.Body3 style={styles?.body}>{body}</Typography.Body3>
144
+ ) : (
145
+ body
146
+ )}
147
+ </BodyRow>
148
+ {actions ? (
149
+ <ActionRow style={styles?.actionContainer}>
150
+ {actions.map((action, index) =>
151
+ cloneElement(action, {
152
+ key: `action-${index}`,
153
+ style: {
154
+ flex: 1,
155
+ marginLeft: index !== 0 ? 12 : 0,
156
+ },
157
+ }),
158
+ )}
159
+ </ActionRow>
160
+ ) : null}
161
+ </AlertDialogContainer>
162
+ </Container>
163
+ );
164
+
165
+ return (
166
+ <Modal
167
+ animationType="fade"
168
+ style={[
169
+ css`
170
+ flex: 1;
171
+ align-self: stretch;
172
+ `,
173
+ style,
174
+ ]}
175
+ transparent={true}
176
+ visible={visible}
177
+ >
178
+ {closeOnTouchOutside ? (
179
+ <TouchableWithoutFeedback
180
+ onPress={() => setVisible(false)}
181
+ style={css`
182
+ flex: 1;
183
+ `}
184
+ >
185
+ {AlertDialogContent}
186
+ </TouchableWithoutFeedback>
187
+ ) : (
188
+ AlertDialogContent
189
+ )}
190
+ </Modal>
191
+ );
192
+ }
193
+
194
+ export default forwardRef<AlertDialogContext, AlertDialogProps>(AlertDialog);
@@ -0,0 +1,94 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useImperativeHandle, useState } from 'react';
3
+ import { Modal, Platform, StyleSheet } from 'react-native';
4
+ import styled, { css } from '@emotion/native';
5
+ import { SnackbarTimer } from './const';
6
+ import { Button } from '../../uis/Button/Button';
7
+ import { useTheme } from '../../../providers/ThemeProvider';
8
+ import { Icon } from '../../uis/Icon/Icon';
9
+ const Container = styled.View `
10
+ flex: 1;
11
+ align-self: stretch;
12
+
13
+ flex-direction: row;
14
+ justify-content: center;
15
+ `;
16
+ const SnackbarContainer = styled.SafeAreaView `
17
+ background-color: ${({ theme, color }) => theme.button[color].bg};
18
+ border-radius: 8px;
19
+ margin-bottom: 52px;
20
+ margin-left: 12px;
21
+ margin-right: 12px;
22
+ align-self: flex-end;
23
+
24
+ flex-direction: row;
25
+ align-items: center;
26
+ `;
27
+ const ActionContainer = styled.View `
28
+ margin-right: 4px;
29
+ `;
30
+ const SnackbarText = styled.Text `
31
+ font-family: Pretendard;
32
+ color: ${({ theme, color }) => theme.button[color].text};
33
+ flex: 1;
34
+ padding: 12px;
35
+ `;
36
+ let timer = null;
37
+ function clearTimer() {
38
+ if (timer) {
39
+ clearTimeout(timer);
40
+ timer = null;
41
+ }
42
+ }
43
+ function Snackbar({ style }, ref) {
44
+ const [options, setOptions] = useState(null);
45
+ const [visible, setVisible] = useState(false);
46
+ const { theme } = useTheme();
47
+ useImperativeHandle(ref, () => ({
48
+ open: (snackbarOptions) => {
49
+ clearTimer();
50
+ setVisible(true);
51
+ if (snackbarOptions) {
52
+ setOptions(snackbarOptions);
53
+ }
54
+ timer = setTimeout(() => {
55
+ setVisible(false);
56
+ clearTimer();
57
+ }, snackbarOptions?.timer ?? SnackbarTimer.SHORT);
58
+ },
59
+ close: () => {
60
+ setVisible(false);
61
+ setOptions(null);
62
+ },
63
+ }));
64
+ const { text, styles, actionText, color = 'primary' } = options ?? {};
65
+ const SnackbarContent = (_jsx(Container, { children: _jsxs(SnackbarContainer, { color: color, style: StyleSheet.flatten([
66
+ Platform.OS !== 'web' && {
67
+ shadowOffset: { width: 0, height: 4 },
68
+ shadowColor: theme.text.basic,
69
+ },
70
+ styles?.container,
71
+ ]), children: [_jsx(SnackbarText, { color: color, style: StyleSheet.flatten([
72
+ css `
73
+ font-family: 'Pretendard';
74
+ color: ${theme.button[color].text};
75
+ `,
76
+ styles?.text,
77
+ ]), children: text }), _jsx(ActionContainer, { style: styles?.actionContainer, children: actionText ? (_jsx(Button, { onPress: () => setVisible(false), styles: {
78
+ text: StyleSheet.flatten([
79
+ css `
80
+ font-family: 'Pretendard';
81
+ color: ${theme.button[color].text};
82
+ `,
83
+ styles?.actionText,
84
+ ]),
85
+ }, text: actionText, type: "text" })) : (_jsx(Button, { onPress: () => setVisible(false), text: _jsx(Icon, { color: theme.button[color].text, name: "X" }), type: "text" })) })] }) }));
86
+ return (_jsx(Modal, { animationType: "fade", style: [
87
+ css `
88
+ flex: 1;
89
+ align-self: stretch;
90
+ `,
91
+ style,
92
+ ], transparent: true, visible: visible, children: SnackbarContent }));
93
+ }
94
+ export default forwardRef(Snackbar);
@@ -0,0 +1,98 @@
1
+ import type {ComponentProps} from 'react';
2
+ import styled, {css} from '@emotion/native';
3
+ import type {Meta, StoryObj} from '@storybook/react';
4
+ import {useCPK} from '../../../providers';
5
+ import {Typography} from '../../uis/Typography/Typography';
6
+ import {Button} from '../../uis/Button/Button';
7
+ import {withThemeProvider} from '../../../../.storybook/decorators';
8
+ import Snackbar from './Snackbar';
9
+
10
+ const Container = styled.SafeAreaView`
11
+ background-color: ${({theme}) => theme.bg.basic};
12
+ `;
13
+
14
+ function SnackbarBasicStory(): JSX.Element {
15
+ const {snackbar} = useCPK();
16
+
17
+ return (
18
+ <Container
19
+ style={css`
20
+ flex-direction: column;
21
+ padding: 48px 24px;
22
+ align-self: stretch;
23
+ justify-content: center;
24
+ align-items: center;
25
+ `}
26
+ >
27
+ <Typography.Title>Snackbar</Typography.Title>
28
+ <Button
29
+ color="primary"
30
+ onPress={() =>
31
+ snackbar.open({
32
+ text: 'Hello there!',
33
+ })
34
+ }
35
+ style={{marginTop: 60, width: 200}}
36
+ text="Snackbar"
37
+ />
38
+ <Button
39
+ color="primary"
40
+ onPress={() =>
41
+ snackbar.open({
42
+ text: 'Hello there!',
43
+ actionText: 'Cancel',
44
+ })
45
+ }
46
+ style={{marginTop: 20, width: 200}}
47
+ text="With action"
48
+ />
49
+ <Button
50
+ color="info"
51
+ onPress={() =>
52
+ snackbar.open({
53
+ text: 'Hello there!',
54
+ color: 'info',
55
+ })
56
+ }
57
+ style={{marginTop: 20, width: 200}}
58
+ text="Color = info"
59
+ />
60
+ <Button
61
+ color="danger"
62
+ onPress={() =>
63
+ snackbar.open({
64
+ text: 'Hello there!',
65
+ color: 'danger',
66
+ })
67
+ }
68
+ style={{marginTop: 20, width: 200}}
69
+ text="Color = danger"
70
+ />
71
+ <Button
72
+ color="light"
73
+ onPress={() =>
74
+ snackbar.open({
75
+ text: 'Hello there!',
76
+ color: 'light',
77
+ })
78
+ }
79
+ style={{marginTop: 20, width: 200}}
80
+ text="Color = light"
81
+ />
82
+ </Container>
83
+ );
84
+ }
85
+
86
+ const meta = {
87
+ title: 'Snackbar',
88
+ component: SnackbarBasicStory,
89
+ decorators: [withThemeProvider],
90
+ } satisfies Meta<typeof Snackbar>;
91
+
92
+ export default meta;
93
+
94
+ type Story = StoryObj<typeof meta>;
95
+
96
+ export const Basic: Story = {
97
+ args: {},
98
+ };