@coldsurf/ocean-road 1.13.2

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 (195) hide show
  1. package/dist/css/global.css +30 -0
  2. package/dist/index.d.ts +641 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +733 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/native.cjs +94 -0
  7. package/dist/native.cjs.map +1 -0
  8. package/dist/native.d.cts +304 -0
  9. package/dist/native.d.cts.map +1 -0
  10. package/dist/native.d.ts +304 -0
  11. package/dist/native.d.ts.map +1 -0
  12. package/dist/native.js +94 -0
  13. package/dist/native.js.map +1 -0
  14. package/dist/next.cjs +949 -0
  15. package/dist/next.cjs.map +1 -0
  16. package/dist/next.d.cts +270 -0
  17. package/dist/next.d.cts.map +1 -0
  18. package/dist/next.d.ts +270 -0
  19. package/dist/next.d.ts.map +1 -0
  20. package/dist/next.js +949 -0
  21. package/dist/next.js.map +1 -0
  22. package/native/index.d.ts +7 -0
  23. package/next/index.d.ts +7 -0
  24. package/package.json +126 -0
  25. package/src/GlobalStyle.tsx +111 -0
  26. package/src/base/badge/badge.tsx +50 -0
  27. package/src/base/badge/index.ts +1 -0
  28. package/src/base/button/button.styled.tsx +123 -0
  29. package/src/base/button/button.tsx +60 -0
  30. package/src/base/button/button.types.ts +20 -0
  31. package/src/base/button/button.utils.ts +36 -0
  32. package/src/base/button/index.tsx +2 -0
  33. package/src/base/checkbox/checkbox.styled.ts +52 -0
  34. package/src/base/checkbox/checkbox.tsx +26 -0
  35. package/src/base/checkbox/index.ts +1 -0
  36. package/src/base/icon-button/icon-button.styled.ts +8 -0
  37. package/src/base/icon-button/icon-button.tsx +15 -0
  38. package/src/base/icon-button/icon-button.types.ts +3 -0
  39. package/src/base/icon-button/index.ts +2 -0
  40. package/src/base/index.ts +11 -0
  41. package/src/base/label/index.ts +1 -0
  42. package/src/base/label/label.styled.ts +7 -0
  43. package/src/base/label/label.tsx +27 -0
  44. package/src/base/modal/index.ts +1 -0
  45. package/src/base/modal/modal.tsx +59 -0
  46. package/src/base/spinner/index.ts +2 -0
  47. package/src/base/spinner/spinner.styled.ts +25 -0
  48. package/src/base/spinner/spinner.tsx +36 -0
  49. package/src/base/spinner/spinner.types.ts +1 -0
  50. package/src/base/switch/index.ts +1 -0
  51. package/src/base/switch/switch.styled.tsx +49 -0
  52. package/src/base/switch/switch.tsx +29 -0
  53. package/src/base/text/index.ts +1 -0
  54. package/src/base/text/text.styled.ts +17 -0
  55. package/src/base/text/text.tsx +37 -0
  56. package/src/base/text-area/index.ts +2 -0
  57. package/src/base/text-area/text-area.styled.ts +16 -0
  58. package/src/base/text-area/text-area.tsx +29 -0
  59. package/src/base/text-area/text-area.types.ts +11 -0
  60. package/src/base/text-input/index.ts +2 -0
  61. package/src/base/text-input/text-input.styled.ts +40 -0
  62. package/src/base/text-input/text-input.tsx +59 -0
  63. package/src/base/text-input/text-input.types.ts +15 -0
  64. package/src/base/toast/index.ts +2 -0
  65. package/src/base/toast/toast.tsx +60 -0
  66. package/src/base/toast/toast.types.ts +5 -0
  67. package/src/constants.ts +1 -0
  68. package/src/contexts/ColorSchemeProvider.tsx +154 -0
  69. package/src/css/global.css +30 -0
  70. package/src/extensions/accordion/accordion.hooks.ts +11 -0
  71. package/src/extensions/accordion/accordion.tsx +80 -0
  72. package/src/extensions/accordion/index.ts +1 -0
  73. package/src/extensions/app-header/app-header.hooks.ts +94 -0
  74. package/src/extensions/app-header/app-header.tsx +31 -0
  75. package/src/extensions/app-header/app-header.types.ts +1 -0
  76. package/src/extensions/app-header/index.ts +8 -0
  77. package/src/extensions/app-logo/app-logo.tsx +40 -0
  78. package/src/extensions/app-logo/index.ts +1 -0
  79. package/src/extensions/app-store-button/app-store-button.tsx +64 -0
  80. package/src/extensions/app-store-button/index.ts +1 -0
  81. package/src/extensions/brand-icon/brand-icon.android.tsx +11 -0
  82. package/src/extensions/brand-icon/brand-icon.apple.tsx +11 -0
  83. package/src/extensions/brand-icon/brand-icon.google.tsx +11 -0
  84. package/src/extensions/brand-icon/brand-icon.tsx +22 -0
  85. package/src/extensions/brand-icon/index.ts +1 -0
  86. package/src/extensions/color-scheme-toggle/color-scheme-toggle.tsx +76 -0
  87. package/src/extensions/color-scheme-toggle/index.ts +1 -0
  88. package/src/extensions/dropdown/dropdown.menu-item.tsx +237 -0
  89. package/src/extensions/dropdown/dropdown.result-item.tsx +26 -0
  90. package/src/extensions/dropdown/dropdown.styled.tsx +48 -0
  91. package/src/extensions/dropdown/dropdown.trigger.tsx +72 -0
  92. package/src/extensions/dropdown/dropdown.tsx +222 -0
  93. package/src/extensions/dropdown/dropdown.types.ts +3 -0
  94. package/src/extensions/dropdown/dropdown.utils.ts +40 -0
  95. package/src/extensions/dropdown/index.ts +14 -0
  96. package/src/extensions/error-ui/index.ts +7 -0
  97. package/src/extensions/error-ui/network-error/index.ts +1 -0
  98. package/src/extensions/error-ui/network-error/network-error.styled.ts +16 -0
  99. package/src/extensions/error-ui/network-error/network-error.tsx +14 -0
  100. package/src/extensions/error-ui/unknown-error/index.ts +1 -0
  101. package/src/extensions/error-ui/unknown-error/unknown-error.styled.ts +16 -0
  102. package/src/extensions/error-ui/unknown-error/unknown-error.tsx +14 -0
  103. package/src/extensions/full-screen-modal/full-screen-modal.tsx +52 -0
  104. package/src/extensions/full-screen-modal/index.ts +1 -0
  105. package/src/extensions/grid-card-image/grid-card-image.tsx +11 -0
  106. package/src/extensions/grid-card-image/index.ts +1 -0
  107. package/src/extensions/grid-card-image-empty/grid-card-image-empty.tsx +11 -0
  108. package/src/extensions/grid-card-image-empty/index.ts +1 -0
  109. package/src/extensions/grid-card-item/grid-card-item.masonry.styled.tsx +95 -0
  110. package/src/extensions/grid-card-item/grid-card-item.masonry.tsx +63 -0
  111. package/src/extensions/grid-card-item/grid-card-item.styled.tsx +93 -0
  112. package/src/extensions/grid-card-item/grid-card-item.subscribe-btn-layout.tsx +30 -0
  113. package/src/extensions/grid-card-item/grid-card-item.tsx +81 -0
  114. package/src/extensions/grid-card-item/index.ts +2 -0
  115. package/src/extensions/grid-card-list/grid-card-list.masonry.styled.tsx +45 -0
  116. package/src/extensions/grid-card-list/grid-card-list.masonry.tsx +58 -0
  117. package/src/extensions/grid-card-list/grid-card-list.styled.tsx +40 -0
  118. package/src/extensions/grid-card-list/grid-card-list.tsx +59 -0
  119. package/src/extensions/grid-card-list/index.ts +2 -0
  120. package/src/extensions/grid-card-list-empty/grid-card-list-empty.tsx +38 -0
  121. package/src/extensions/grid-card-list-empty/index.ts +1 -0
  122. package/src/extensions/grid-card-list-load-more/grid-card-list-load-more.styled.tsx +15 -0
  123. package/src/extensions/grid-card-list-load-more/grid-card-list-load-more.tsx +43 -0
  124. package/src/extensions/grid-card-list-load-more/index.ts +1 -0
  125. package/src/extensions/index.ts +38 -0
  126. package/src/extensions/menu-item/index.ts +1 -0
  127. package/src/extensions/menu-item/menu-item.tsx +87 -0
  128. package/src/extensions/sns-icon/index.ts +1 -0
  129. package/src/extensions/sns-icon/sns-icon.facebook.tsx +11 -0
  130. package/src/extensions/sns-icon/sns-icon.instagram.tsx +11 -0
  131. package/src/extensions/sns-icon/sns-icon.tsx +24 -0
  132. package/src/extensions/sns-icon/sns-icon.x.tsx +11 -0
  133. package/src/extensions/sns-icon/sns-icon.youtube.tsx +11 -0
  134. package/src/index.ts +8 -0
  135. package/src/native/button/button.styled.tsx +99 -0
  136. package/src/native/button/button.tsx +42 -0
  137. package/src/native/button/index.ts +1 -0
  138. package/src/native/contexts/color-scheme-context/color-scheme-context.tsx +45 -0
  139. package/src/native/contexts/color-scheme-context/index.ts +1 -0
  140. package/src/native/contexts/index.ts +1 -0
  141. package/src/native/icon-button/icon-button.styled.ts +6 -0
  142. package/src/native/icon-button/icon-button.tsx +33 -0
  143. package/src/native/icon-button/icon-button.types.ts +14 -0
  144. package/src/native/icon-button/icon-button.utils.ts +114 -0
  145. package/src/native/icon-button/index.ts +1 -0
  146. package/src/native/index.ts +9 -0
  147. package/src/native/modal/index.ts +2 -0
  148. package/src/native/modal/modal.styled.ts +17 -0
  149. package/src/native/modal/modal.tsx +21 -0
  150. package/src/native/modal/modal.types.ts +8 -0
  151. package/src/native/profile-thumbnail/index.ts +1 -0
  152. package/src/native/profile-thumbnail/profile-thumbnail.tsx +91 -0
  153. package/src/native/spinner/index.ts +1 -0
  154. package/src/native/spinner/spinner.tsx +75 -0
  155. package/src/native/text/index.ts +2 -0
  156. package/src/native/text/text.tsx +51 -0
  157. package/src/native/text/text.types.ts +5 -0
  158. package/src/native/text-input/index.ts +2 -0
  159. package/src/native/text-input/text-input.tsx +72 -0
  160. package/src/native/text-input/text-input.types.ts +3 -0
  161. package/src/native/toast/index.ts +2 -0
  162. package/src/native/toast/toast.styled.ts +40 -0
  163. package/src/native/toast/toast.tsx +23 -0
  164. package/src/native/toast/toast.types.ts +10 -0
  165. package/src/next/app-footer/app-footer.tsx +250 -0
  166. package/src/next/app-footer/index.ts +1 -0
  167. package/src/next/app-header/app-header.fixed-header.tsx +83 -0
  168. package/src/next/app-header/app-header.full-screen-mobile-accordion-drawer.tsx +131 -0
  169. package/src/next/app-header/app-header.logo.tsx +50 -0
  170. package/src/next/app-header/app-header.modal-mobile-accordion-drawer.tsx +69 -0
  171. package/src/next/app-header/app-header.styled.ts +160 -0
  172. package/src/next/app-header/app-header.tsx +91 -0
  173. package/src/next/app-header/index.ts +13 -0
  174. package/src/next/global-link/global-link.store.ts +41 -0
  175. package/src/next/global-link/global-link.tsx +52 -0
  176. package/src/next/global-link/global-link.utils.ts +9 -0
  177. package/src/next/global-link/index.ts +3 -0
  178. package/src/next/grid-card-item/grid-card-item.masonry.tsx +23 -0
  179. package/src/next/grid-card-item/grid-card-item.tsx +23 -0
  180. package/src/next/grid-card-item/index.ts +2 -0
  181. package/src/next/index.ts +16 -0
  182. package/src/next/new-tab-link/index.ts +1 -0
  183. package/src/next/new-tab-link/new-tab-link.tsx +15 -0
  184. package/src/next/route-loading/index.ts +1 -0
  185. package/src/next/route-loading/route-loading.tsx +21 -0
  186. package/src/tokens/index.ts +2 -0
  187. package/src/tokens/tokens.ts +8 -0
  188. package/src/tokens/tokens.types.ts +7 -0
  189. package/src/utils/breakpoints.ts +9 -0
  190. package/src/utils/common-styles.ts +23 -0
  191. package/src/utils/index.ts +2 -0
  192. package/src/utils/media.ts +23 -0
  193. package/src/utils/use-prevent-scroll-effect.ts +19 -0
  194. package/src/utils/with-id.ts +3 -0
  195. package/src/utils/with-stop-propagation.ts +10 -0
@@ -0,0 +1,114 @@
1
+ import color from '@coldsurfers/ocean-road-design-tokens/js/color/variables';
2
+ import { css } from '@emotion/native';
3
+ import type { ButtonTheme } from '../../base/button';
4
+ import type { IconButtonSize } from './icon-button.types';
5
+
6
+ export const sizes = {
7
+ xs: 20,
8
+ sm: 24,
9
+ md: 28,
10
+ lg: 32,
11
+ xl: 36,
12
+ };
13
+
14
+ const sizesStringify = (size: IconButtonSize) => {
15
+ switch (size) {
16
+ case 'xs':
17
+ return `${sizes.xs}px`;
18
+ case 'sm':
19
+ return `${sizes.sm}px`;
20
+ case 'md':
21
+ return `${sizes.md}px`;
22
+ case 'lg':
23
+ return `${sizes.lg}px`;
24
+ case 'xl':
25
+ return `${sizes.xl}px`;
26
+ default:
27
+ return `${sizes.xs}px`;
28
+ }
29
+ };
30
+
31
+ const xsStyles = css`
32
+ width: ${sizesStringify('xs')};
33
+ height: ${sizesStringify('xs')};
34
+ border-radius: 10px;
35
+ `;
36
+
37
+ const smStyles = css`
38
+ width: ${sizesStringify('sm')};
39
+ height: ${sizesStringify('sm')};
40
+ border-radius: 12px;
41
+ `;
42
+
43
+ const mdStyles = css`
44
+ width: ${sizesStringify('md')};
45
+ height: ${sizesStringify('md')};
46
+ border-radius: 14px;
47
+ `;
48
+
49
+ const lgStyles = css`
50
+ width: ${sizesStringify('lg')};
51
+ height: ${sizesStringify('lg')};
52
+ border-radius: 16px;
53
+ `;
54
+
55
+ const xlStyles = css`
56
+ width: ${sizesStringify('xl')};
57
+ height: ${sizesStringify('xl')};
58
+ border-radius: 18px;
59
+ `;
60
+
61
+ export const getIconButtonSizeStyles = (size: IconButtonSize) => {
62
+ switch (size) {
63
+ case 'xs':
64
+ return xsStyles;
65
+ case 'sm':
66
+ return smStyles;
67
+ case 'md':
68
+ return mdStyles;
69
+ case 'lg':
70
+ return lgStyles;
71
+ case 'xl':
72
+ return xlStyles;
73
+ default:
74
+ return xsStyles;
75
+ }
76
+ };
77
+
78
+ const transparentStyles = css`
79
+ background-color: transparent;
80
+ `;
81
+
82
+ const transparentDarkGrayStyles = css`
83
+ background-color: ${color.oc.black.value};
84
+ opacity: 0.5;
85
+ `;
86
+
87
+ const whiteStyles = css`
88
+ background-color: ${color.oc.white.value};
89
+ `;
90
+
91
+ const pinkStyles = css`
92
+ background-color: ${color.oc.pink[9].value};
93
+ `;
94
+
95
+ const indigoStyles = css`
96
+ background-color: ${color.oc.indigo[9].value};
97
+ `;
98
+
99
+ export const getIconButtonBackgroundStyles = (theme: ButtonTheme) => {
100
+ switch (theme) {
101
+ case 'transparent':
102
+ return transparentStyles;
103
+ case 'transparentDarkGray':
104
+ return transparentDarkGrayStyles;
105
+ case 'white':
106
+ return whiteStyles;
107
+ case 'pink':
108
+ return pinkStyles;
109
+ case 'indigo':
110
+ return indigoStyles;
111
+ default:
112
+ return indigoStyles;
113
+ }
114
+ };
@@ -0,0 +1 @@
1
+ export * from './icon-button';
@@ -0,0 +1,9 @@
1
+ export * from './button';
2
+ export * from './contexts';
3
+ export * from './icon-button';
4
+ export * from './modal';
5
+ export * from './profile-thumbnail';
6
+ export * from './spinner';
7
+ export * from './text';
8
+ export * from './text-input';
9
+ export * from './toast';
@@ -0,0 +1,2 @@
1
+ export * from './modal';
2
+ export * from './modal.types';
@@ -0,0 +1,17 @@
1
+ import styled from '@emotion/native';
2
+
3
+ export const StyledModal = styled.Modal`
4
+ flex: 1;
5
+ `;
6
+
7
+ export const StyledModalBackground = styled.Pressable`
8
+ position: absolute;
9
+ z-index: 99;
10
+ top: 0px;
11
+ left: 0px;
12
+ right: 0px;
13
+ bottom: 0px;
14
+ background-color: rgba(0, 0, 0, 0.5);
15
+ align-items: center;
16
+ justify-content: center;
17
+ `;
@@ -0,0 +1,21 @@
1
+ import { TouchableWithoutFeedback } from 'react-native';
2
+ import { StyledModal, StyledModalBackground } from './modal.styled';
3
+ import type { ModalProps } from './modal.types';
4
+
5
+ export const Modal = ({
6
+ children,
7
+ visible = false,
8
+ transparent = true,
9
+ onPressBackground,
10
+ }: ModalProps) => (
11
+ <StyledModal
12
+ supportedOrientations={['landscape', 'portrait']}
13
+ visible={visible}
14
+ transparent={transparent}
15
+ animationType="slide"
16
+ >
17
+ <StyledModalBackground onPress={onPressBackground}>
18
+ <TouchableWithoutFeedback>{children}</TouchableWithoutFeedback>
19
+ </StyledModalBackground>
20
+ </StyledModal>
21
+ );
@@ -0,0 +1,8 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ import type { GestureResponderEvent } from 'react-native';
3
+
4
+ export type ModalProps = PropsWithChildren<{
5
+ visible?: boolean;
6
+ transparent?: boolean;
7
+ onPressBackground?: (event: GestureResponderEvent) => void;
8
+ }>;
@@ -0,0 +1 @@
1
+ export * from './profile-thumbnail';
@@ -0,0 +1,91 @@
1
+ import { useMemo } from 'react';
2
+ import { Image, type StyleProp, StyleSheet, View, type ViewStyle } from 'react-native';
3
+ import { colors } from '../../tokens';
4
+ import { useColorScheme } from '../contexts';
5
+ import { Text } from '../text';
6
+
7
+ const PROFILE_THUMBNAIL_SIZE = {
8
+ md: {
9
+ width: 62,
10
+ height: 62,
11
+ },
12
+ sm: {
13
+ width: 42,
14
+ height: 42,
15
+ },
16
+ lg: {
17
+ width: 92,
18
+ height: 92,
19
+ },
20
+ } as const;
21
+
22
+ type ProfileThumbnailProps = {
23
+ size?: 'md' | 'sm' | 'lg';
24
+ type?: 'square' | 'circle';
25
+ emptyBgText: string;
26
+ imageUrl?: string;
27
+ style?: StyleProp<ViewStyle>;
28
+ };
29
+
30
+ export const ProfileThumbnail = ({
31
+ size = 'md',
32
+ emptyBgText,
33
+ imageUrl,
34
+ type = 'square',
35
+ style,
36
+ }: ProfileThumbnailProps) => {
37
+ const { semantics } = useColorScheme();
38
+ const sizeStyle = useMemo(() => {
39
+ return PROFILE_THUMBNAIL_SIZE[size];
40
+ }, [size]);
41
+ const borderRadiusStyle = useMemo(() => {
42
+ switch (type) {
43
+ case 'circle':
44
+ return {
45
+ borderRadius: sizeStyle.width / 2,
46
+ };
47
+ case 'square':
48
+ return { borderRadius: 4 };
49
+ default:
50
+ return {
51
+ borderRadius: 4,
52
+ };
53
+ }
54
+ }, [sizeStyle.width, type]);
55
+ return (
56
+ <View
57
+ style={[
58
+ styles.wrapper,
59
+ sizeStyle,
60
+ borderRadiusStyle,
61
+ {
62
+ backgroundColor: semantics.background[4],
63
+ },
64
+ style,
65
+ ]}
66
+ >
67
+ {emptyBgText ? (
68
+ <Text weight="bold" style={styles.bgText}>
69
+ {emptyBgText}
70
+ </Text>
71
+ ) : null}
72
+ {imageUrl && <Image source={{ uri: imageUrl }} style={[styles.image, borderRadiusStyle]} />}
73
+ </View>
74
+ );
75
+ };
76
+
77
+ const styles = StyleSheet.create({
78
+ wrapper: {
79
+ alignItems: 'center',
80
+ justifyContent: 'center',
81
+ },
82
+ bgText: {
83
+ color: colors.oc.white.value,
84
+ position: 'absolute',
85
+ fontSize: 14,
86
+ },
87
+ image: {
88
+ width: '100%',
89
+ height: '100%',
90
+ },
91
+ });
@@ -0,0 +1 @@
1
+ export * from './spinner';
@@ -0,0 +1,75 @@
1
+ import styled from '@emotion/native';
2
+ import { LoaderCircle } from 'lucide-react-native';
3
+ import { useEffect, useMemo } from 'react';
4
+ import { type ColorValue, type StyleProp, StyleSheet, View, type ViewStyle } from 'react-native';
5
+ import Reanimated, {
6
+ useAnimatedStyle,
7
+ useSharedValue,
8
+ withRepeat,
9
+ withTiming,
10
+ } from 'react-native-reanimated';
11
+ import { colors } from '../../tokens';
12
+
13
+ const AnimatedLoaderIcon = Reanimated.createAnimatedComponent(LoaderCircle);
14
+
15
+ const LoaderIcon = styled(AnimatedLoaderIcon)`
16
+ color: ${colors.oc.cyan[5].value};
17
+ `;
18
+
19
+ interface Props {
20
+ positionCenter?: boolean;
21
+ size?: number | 'small' | 'large' | 'medium';
22
+ color?: ColorValue;
23
+ style?: StyleProp<ViewStyle>;
24
+ }
25
+
26
+ export const Spinner = ({ positionCenter = false, size = 'large', color, style }: Props) => {
27
+ const rotation = useSharedValue(0); // Shared value for rotation
28
+
29
+ // Animated style for rotation
30
+ const animatedStyle = useAnimatedStyle(() => {
31
+ return {
32
+ transform: [{ rotate: `${rotation.value}deg` }],
33
+ };
34
+ });
35
+
36
+ const sizeNumber = useMemo(() => {
37
+ switch (size) {
38
+ case 'large':
39
+ return 42;
40
+ case 'small':
41
+ return 20;
42
+ case 'medium':
43
+ return 32;
44
+ default:
45
+ return 42;
46
+ }
47
+ }, [size]);
48
+
49
+ useEffect(() => {
50
+ // Start the rotation animation
51
+ rotation.value = withRepeat(
52
+ withTiming(360, { duration: 600 }), // Full rotation in 2000ms
53
+ -1, // Infinite repeat
54
+ false // Reverse the direction after each cycle
55
+ );
56
+ }, [rotation]);
57
+
58
+ return (
59
+ <View style={[positionCenter && styles.positionCenter, style]}>
60
+ <View style={styles.animationWrapper}>
61
+ <LoaderIcon size={sizeNumber} color={color} style={animatedStyle} />
62
+ </View>
63
+ </View>
64
+ );
65
+ };
66
+
67
+ const styles = StyleSheet.create({
68
+ positionCenter: {
69
+ ...StyleSheet.absoluteFillObject,
70
+ backgroundColor: 'transparent',
71
+ justifyContent: 'center',
72
+ alignItems: 'center',
73
+ },
74
+ animationWrapper: { justifyContent: 'center', alignItems: 'center' },
75
+ });
@@ -0,0 +1,2 @@
1
+ export * from './text';
2
+ export * from './text.types';
@@ -0,0 +1,51 @@
1
+ import { Text as RNText, StyleSheet } from 'react-native';
2
+ import { colors } from '../../tokens';
3
+ import type { TextProps } from './text.types';
4
+
5
+ export const Text = ({ children, weight = 'regular', style, ...others }: TextProps) => {
6
+ const fontFamilySet = {
7
+ thin: styles.thin,
8
+ light: styles.light,
9
+ regular: styles.regular,
10
+ medium: styles.medium,
11
+ bold: styles.bold,
12
+ extraBold: styles.extraBold,
13
+ };
14
+ const flattenedStyle = StyleSheet.flatten(style);
15
+ const lineHeight = (flattenedStyle?.fontSize ?? 0) * 1.205;
16
+ return (
17
+ <RNText
18
+ {...others}
19
+ style={[
20
+ fontFamilySet[weight],
21
+ styles.defaultColor,
22
+ { lineHeight: lineHeight, letterSpacing: 0.24, includeFontPadding: false },
23
+ style,
24
+ ]}
25
+ >
26
+ {children}
27
+ </RNText>
28
+ );
29
+ };
30
+
31
+ const styles = StyleSheet.create({
32
+ thin: {
33
+ fontFamily: 'Pretendard-Thin',
34
+ },
35
+ light: {
36
+ fontFamily: 'Pretendard-Light',
37
+ },
38
+ regular: {
39
+ fontFamily: 'Pretendard-Regular',
40
+ },
41
+ medium: {
42
+ fontFamily: 'Pretendard-Medium',
43
+ },
44
+ bold: {
45
+ fontFamily: 'Pretendard-Bold',
46
+ },
47
+ extraBold: {
48
+ fontFamily: 'Pretendard-ExtraBold',
49
+ },
50
+ defaultColor: { color: colors.oc.black.value },
51
+ });
@@ -0,0 +1,5 @@
1
+ import type { TextProps as RNTextProps } from 'react-native';
2
+
3
+ export interface TextProps extends RNTextProps {
4
+ weight?: 'thin' | 'light' | 'regular' | 'medium' | 'bold' | 'extraBold';
5
+ }
@@ -0,0 +1,2 @@
1
+ export * from './text-input';
2
+ export * from './text-input.types';
@@ -0,0 +1,72 @@
1
+ import color from '@coldsurfers/ocean-road-design-tokens/js/color/variables';
2
+ import { forwardRef, memo, useCallback, useState } from 'react';
3
+ import { TextInput as RNTextInput, StyleSheet } from 'react-native';
4
+ import { colors } from '../../tokens';
5
+ import { useColorScheme } from '../contexts';
6
+ import type { TextInputProps } from './text-input.types';
7
+
8
+ const DEFAULT_FONT_SIZE = 12;
9
+
10
+ const _TextInput = forwardRef<RNTextInput, TextInputProps>(({ style, ...otherProps }, ref) => {
11
+ const { semantics, colorScheme } = useColorScheme();
12
+ const [focused, setFocused] = useState<boolean>(false);
13
+ const flattenedStyle = StyleSheet.flatten(style);
14
+ const lineHeight = (flattenedStyle?.fontSize ?? DEFAULT_FONT_SIZE) * 1.275;
15
+ const onFocus = useCallback(() => {
16
+ setFocused(true);
17
+ }, []);
18
+ const onBlur = useCallback(() => {
19
+ setFocused(false);
20
+ }, []);
21
+ return (
22
+ <RNTextInput
23
+ ref={ref}
24
+ placeholderTextColor={'#b0b6b7'}
25
+ onFocus={onFocus}
26
+ onBlur={onBlur}
27
+ {...otherProps}
28
+ style={[
29
+ styles.textInput,
30
+ {
31
+ color: semantics.foreground[1],
32
+ backgroundColor: semantics.background[4],
33
+ borderColor: colorScheme === 'light' ? semantics.border[2] : semantics.border[1],
34
+ },
35
+ focused && {
36
+ borderColor: colorScheme === 'light' ? semantics.border[1] : semantics.border[2],
37
+ },
38
+ typeof otherProps.editable === 'boolean' && !otherProps.editable && styles.disabled,
39
+ {
40
+ lineHeight,
41
+ },
42
+ style,
43
+ ]}
44
+ />
45
+ );
46
+ });
47
+
48
+ export const TextInput = memo(_TextInput);
49
+
50
+ const styles = StyleSheet.create({
51
+ textInput: {
52
+ // borderColor: colors.oc.gray[6].value,
53
+ borderWidth: 2,
54
+ borderRadius: 24,
55
+ paddingLeft: 16,
56
+ paddingRight: 16,
57
+ paddingTop: 16,
58
+ paddingBottom: 16,
59
+ backgroundColor: color.oc.white.value,
60
+ fontFamily: 'Pretendard',
61
+ includeFontPadding: false,
62
+ },
63
+ focused: {
64
+ borderColor: colors.oc.gray[4].value,
65
+ borderWidth: 2,
66
+ },
67
+ disabled: {
68
+ backgroundColor: '#f4eded',
69
+ },
70
+ });
71
+
72
+ _TextInput.displayName = 'TextInput';
@@ -0,0 +1,3 @@
1
+ import type { TextInputProps as RNTextInputProps } from 'react-native';
2
+
3
+ export interface TextInputProps extends RNTextInputProps {}
@@ -0,0 +1,2 @@
1
+ export * from './toast';
2
+ export * from './toast.types';
@@ -0,0 +1,40 @@
1
+ import color from '@coldsurfers/ocean-road-design-tokens/js/color/variables';
2
+ import styled from '@emotion/native';
3
+ import { Text } from '../text';
4
+ import type { ToastType } from './toast.types';
5
+
6
+ export const StyledToastContainer = styled.View`
7
+ align-items: center;
8
+ justify-content: center;
9
+ background-color: transparent;
10
+ position: absolute;
11
+ bottom: 24px;
12
+ left: 0px;
13
+ right: 0px;
14
+ `;
15
+
16
+ export const StyledToastPressable = styled.Pressable<{ type: ToastType }>`
17
+ padding-left: 16px;
18
+ padding-right: 16px;
19
+ padding-top: 16px;
20
+ padding-bottom: 16px;
21
+ border-radius: 24px;
22
+ background-color: ${({ type }) => {
23
+ switch (type) {
24
+ case 'info':
25
+ return color.oc.black.value;
26
+ case 'warning':
27
+ return color.oc.yellow[9].value;
28
+ case 'error':
29
+ return color.oc.pink[9].value;
30
+ default:
31
+ return color.oc.black.value;
32
+ }
33
+ }};
34
+ `;
35
+
36
+ export const StyledToastText = styled(Text)`
37
+ font-weight: 700;
38
+ color: ${color.oc.white.value};
39
+ font-size: 14px;
40
+ `;
@@ -0,0 +1,23 @@
1
+ import { useCallback } from 'react';
2
+ import type { GestureResponderEvent } from 'react-native';
3
+ import { StyledToastContainer, StyledToastPressable, StyledToastText } from './toast.styled';
4
+ import type { ToastProps } from './toast.types';
5
+
6
+ export const Toast = ({ type, message, onPress }: ToastProps) => {
7
+ const handlePress = useCallback(
8
+ (e: GestureResponderEvent) => {
9
+ if (onPress) {
10
+ onPress(e);
11
+ }
12
+ },
13
+ [onPress]
14
+ );
15
+
16
+ return (
17
+ <StyledToastContainer>
18
+ <StyledToastPressable type={type} onPress={handlePress}>
19
+ <StyledToastText>{message}</StyledToastText>
20
+ </StyledToastPressable>
21
+ </StyledToastContainer>
22
+ );
23
+ };
@@ -0,0 +1,10 @@
1
+ import type { GestureResponderEvent } from 'react-native';
2
+
3
+ export interface ToastProps {
4
+ type: ToastType;
5
+ message: string;
6
+ onPress?: (event: GestureResponderEvent) => void;
7
+ autoCloseOnPress?: boolean;
8
+ }
9
+
10
+ export type ToastType = 'info' | 'warning' | 'error';