@pisodev/test-component-library 1.1.2 → 2.0.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.
Files changed (54) hide show
  1. package/components/Anchor/Anchor.native.tsx +44 -0
  2. package/components/Anchor/Anchor.types.ts +11 -0
  3. package/components/Anchor/Anchor.web.module.scss +33 -0
  4. package/components/Anchor/Anchor.web.tsx +35 -0
  5. package/components/Anchor/README.md +58 -0
  6. package/components/Anchor/index.ts +2 -0
  7. package/components/README.md +195 -0
  8. package/components/StatusBar/README.md +56 -0
  9. package/components/StatusBar/StatusBar.tsx +17 -0
  10. package/components/StatusBar/StatusBar.types.ts +5 -0
  11. package/components/StatusBar/index.ts +3 -0
  12. package/components/StatusBar/index.web.ts +14 -0
  13. package/components/Tooltip/README.md +45 -0
  14. package/components/Tooltip/Tooltip.module.scss +44 -0
  15. package/components/Tooltip/Tooltip.tsx +26 -0
  16. package/components/Tooltip/Tooltip.types.ts +7 -0
  17. package/components/Tooltip/index.native.ts +15 -0
  18. package/components/Tooltip/index.ts +3 -0
  19. package/components/index.ts +8 -0
  20. package/dist/Anchor/Anchor.native.d.ts +3 -0
  21. package/dist/Anchor/Anchor.native.js +34 -0
  22. package/dist/Anchor/Anchor.types.d.ts +10 -0
  23. package/dist/Anchor/Anchor.types.js +2 -0
  24. package/dist/Anchor/Anchor.web.d.ts +3 -0
  25. package/dist/Anchor/index.d.ts +2 -0
  26. package/dist/StatusBar/StatusBar.d.ts +3 -0
  27. package/dist/StatusBar/StatusBar.types.d.ts +5 -0
  28. package/dist/StatusBar/StatusBar.types.js +2 -0
  29. package/dist/StatusBar/index.d.ts +2 -0
  30. package/dist/StatusBar/index.web.d.ts +3 -0
  31. package/dist/Tooltip/Tooltip.d.ts +3 -0
  32. package/dist/Tooltip/Tooltip.types.d.ts +6 -0
  33. package/dist/Tooltip/Tooltip.types.js +2 -0
  34. package/dist/Tooltip/index.d.ts +2 -0
  35. package/dist/Tooltip/index.native.d.ts +4 -0
  36. package/dist/Tooltip/index.native.js +12 -0
  37. package/dist/index.d.ts +3 -2
  38. package/dist/index.esm.js +23 -143
  39. package/dist/index.esm.js.map +1 -1
  40. package/dist/index.js +23 -146
  41. package/dist/index.js.map +1 -1
  42. package/package.json +22 -9
  43. package/README.md +0 -67
  44. package/dist/components/Anchor/Anchor.d.ts +0 -11
  45. package/dist/components/Anchor/index.d.ts +0 -2
  46. package/dist/components/Button/Button.d.ts +0 -11
  47. package/dist/components/Button/index.d.ts +0 -2
  48. package/dist/components/Card/Card.d.ts +0 -11
  49. package/dist/components/Card/index.d.ts +0 -2
  50. package/dist/components/index.d.ts +0 -6
  51. package/dist/theme/ThemeProvider.d.ts +0 -12
  52. package/dist/theme/defaultTheme.d.ts +0 -2
  53. package/dist/theme/index.d.ts +0 -3
  54. package/dist/theme/types.d.ts +0 -23
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import { Text, Pressable, Linking, StyleSheet } from 'react-native';
3
+ import { AnchorProps } from './Anchor.types';
4
+
5
+ export const Anchor: React.FC<AnchorProps> = ({
6
+ children,
7
+ href,
8
+ title,
9
+ onPress,
10
+ }) => {
11
+ const handlePress = () => {
12
+ if (onPress) {
13
+ onPress();
14
+ } else if (href) {
15
+ Linking.openURL(href);
16
+ }
17
+ };
18
+
19
+ return (
20
+ <Pressable
21
+ onPress={handlePress}
22
+ accessibilityRole="link"
23
+ accessibilityLabel={title}
24
+ accessibilityHint={`Opens ${href}`}
25
+ >
26
+ {({ pressed }: any) => (
27
+ <Text style={[styles.anchor, pressed && styles.anchorPressed]}>
28
+ {children}
29
+ </Text>
30
+ )}
31
+ </Pressable>
32
+ );
33
+ };
34
+
35
+ const styles = StyleSheet.create({
36
+ anchor: {
37
+ color: '#2196f3',
38
+ textDecorationLine: 'none',
39
+ },
40
+ anchorPressed: {
41
+ color: '#1976d2',
42
+ textDecorationLine: 'underline',
43
+ },
44
+ });
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ export interface AnchorProps {
4
+ children: ReactNode;
5
+ href: string;
6
+ rel?: string;
7
+ title?: string;
8
+ target?: '_blank' | '_self' | '_parent' | '_top';
9
+ className?: string;
10
+ onPress?: () => void;
11
+ }
@@ -0,0 +1,33 @@
1
+ $transition: all 0.2s ease;
2
+
3
+ // CSS Variables fallback
4
+ $primary-color: var(--color-primary-600, #2196f3);
5
+ $primary-hover: var(--color-primary-700, #1976d2);
6
+ $primary-visited: var(--color-primary-800, #1565c0);
7
+ $primary-active: var(--color-primary-900, #0d47a1);
8
+
9
+ .anchor {
10
+ color: $primary-color;
11
+ text-decoration: none;
12
+ transition: $transition;
13
+ cursor: pointer;
14
+ position: relative;
15
+
16
+ &:hover {
17
+ color: $primary-hover;
18
+ text-decoration: underline;
19
+ }
20
+
21
+ &:focus {
22
+ outline: 2px solid $primary-color;
23
+ outline-offset: 2px;
24
+ }
25
+
26
+ &:visited {
27
+ color: $primary-visited;
28
+ }
29
+
30
+ &:active {
31
+ color: $primary-active;
32
+ }
33
+ }
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { AnchorProps } from './Anchor.types';
3
+ import styles from './Anchor.web.module.scss';
4
+
5
+ export const Anchor: React.FC<AnchorProps> = ({
6
+ children,
7
+ href,
8
+ rel,
9
+ title,
10
+ target = '_self',
11
+ className = '',
12
+ onPress,
13
+ }) => {
14
+ const anchorClasses = [styles.anchor, className].filter(Boolean).join(' ');
15
+
16
+ const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
17
+ if (onPress) {
18
+ e.preventDefault();
19
+ onPress();
20
+ }
21
+ };
22
+
23
+ return (
24
+ <a
25
+ href={href}
26
+ rel={rel}
27
+ title={title}
28
+ target={target}
29
+ className={anchorClasses}
30
+ onClick={handleClick}
31
+ >
32
+ {children}
33
+ </a>
34
+ );
35
+ };
@@ -0,0 +1,58 @@
1
+ # Anchor
2
+
3
+ 링크 컴포넌트 - 웹과 React Native 모두 지원
4
+
5
+ ## Props
6
+
7
+ | Prop | Type | Required | Platform | Description |
8
+ |------|------|----------|----------|-------------|
9
+ | children | ReactNode | ✓ | All | 링크 텍스트 |
10
+ | href | string | ✓ | All | URL |
11
+ | rel | string | - | Web only | rel 속성 |
12
+ | title | string | - | All | title 속성 / 접근성 레이블 |
13
+ | target | '_blank' \| '_self' \| '_parent' \| '_top' | - | Web only | target 속성 |
14
+ | className | string | - | Web only | CSS 클래스 |
15
+ | onPress | () => void | - | All | 클릭 핸들러 |
16
+
17
+ ## 웹 사용법
18
+
19
+ ```tsx
20
+ import { Anchor } from '@pisodev/test-component-library';
21
+
22
+ <Anchor
23
+ href="https://example.com"
24
+ title="Example"
25
+ rel="noopener"
26
+ target="_blank"
27
+ >
28
+ Click me
29
+ </Anchor>
30
+ ```
31
+
32
+ ## React Native 사용법
33
+
34
+ ```tsx
35
+ import { Anchor } from '@pisodev/test-component-library';
36
+
37
+ <Anchor
38
+ href="https://example.com"
39
+ title="Example"
40
+ >
41
+ Click me
42
+ </Anchor>
43
+ ```
44
+
45
+ ## 구현 차이점
46
+
47
+ ### 웹 (Anchor.web.tsx)
48
+ - `<a>` 태그 사용
49
+ - SCSS 모듈 스타일링
50
+ - :hover, :focus, :visited, :active 가상 선택자
51
+ - target, rel 속성 지원
52
+
53
+ ### React Native (Anchor.native.tsx)
54
+ - Pressable + Text 컴포넌트 사용
55
+ - StyleSheet 기반 스타일링
56
+ - Pressed 상태로 hover 효과 구현
57
+ - Linking API로 URL 열기
58
+ - 접근성 속성 자동 적용
@@ -0,0 +1,2 @@
1
+ export { Anchor } from './Anchor';
2
+ export type { AnchorProps } from './Anchor.types';
@@ -0,0 +1,195 @@
1
+ # 컴포넌트 가이드
2
+
3
+ ## 컴포넌트 타입
4
+
5
+ ### 1. 크로스 플랫폼 컴포넌트 (웹 + RN 모두 지원)
6
+
7
+ ```
8
+ ComponentName/
9
+ ├── ComponentName.types.ts # 공유 타입
10
+ ├── ComponentName.web.tsx # 웹 구현
11
+ ├── ComponentName.native.tsx # RN 구현
12
+ ├── index.ts # export
13
+ └── README.md
14
+ ```
15
+
16
+ **예시**: Anchor, Button, Card
17
+
18
+ **index.ts**:
19
+ ```typescript
20
+ export { ComponentName } from './ComponentName';
21
+ export type { ComponentNameProps } from './ComponentName.types';
22
+ ```
23
+
24
+ ---
25
+
26
+ ### 2. 웹 전용 컴포넌트
27
+
28
+ ```
29
+ WebOnlyComponent/
30
+ ├── WebOnlyComponent.types.ts # 타입
31
+ ├── WebOnlyComponent.tsx # 웹 구현 (.web.tsx 아님!)
32
+ ├── WebOnlyComponent.module.scss # 스타일
33
+ ├── index.ts # export
34
+ └── README.md
35
+ ```
36
+
37
+ **예시**: Table, Tooltip, Dropdown
38
+
39
+ **index.ts**:
40
+ ```typescript
41
+ export { WebOnlyComponent } from './WebOnlyComponent';
42
+ export type { WebOnlyComponentProps } from './WebOnlyComponent.types';
43
+ ```
44
+
45
+ **중요**: RN에서 import 시 에러 방지를 위한 처리
46
+
47
+ **Option 1 - 타입만 제공**:
48
+ ```typescript
49
+ // index.native.ts (별도 파일)
50
+ import { WebOnlyComponentProps } from './WebOnlyComponent.types';
51
+
52
+ export const WebOnlyComponent = () => {
53
+ if (__DEV__) {
54
+ console.warn('WebOnlyComponent is not available on React Native');
55
+ }
56
+ return null;
57
+ };
58
+
59
+ export type { WebOnlyComponentProps };
60
+ ```
61
+
62
+ **Option 2 - 완전히 제외**:
63
+ ```typescript
64
+ // components/index.ts에서
65
+ export * from './Anchor';
66
+ export * from './Button';
67
+
68
+ // 조건부 export (빌드 설정에서 처리)
69
+ if (typeof window !== 'undefined') {
70
+ export * from './WebOnlyComponent';
71
+ }
72
+ ```
73
+
74
+ ---
75
+
76
+ ### 3. React Native 전용 컴포넌트
77
+
78
+ ```
79
+ NativeOnlyComponent/
80
+ ├── NativeOnlyComponent.types.ts # 타입
81
+ ├── NativeOnlyComponent.tsx # RN 구현 (.native.tsx 아님!)
82
+ ├── index.ts # export
83
+ └── README.md
84
+ ```
85
+
86
+ **예시**: MapView, Camera, BiometricAuth
87
+
88
+ **index.ts**:
89
+ ```typescript
90
+ export { NativeOnlyComponent } from './NativeOnlyComponent';
91
+ export type { NativeOnlyComponentProps } from './NativeOnlyComponent.types';
92
+ ```
93
+
94
+ **웹에서 import 시 에러 방지**:
95
+
96
+ **index.web.ts (별도 파일)**:
97
+ ```typescript
98
+ import { NativeOnlyComponentProps } from './NativeOnlyComponent.types';
99
+
100
+ export const NativeOnlyComponent = () => {
101
+ if (process.env.NODE_ENV === 'development') {
102
+ console.warn('NativeOnlyComponent is only available on React Native');
103
+ }
104
+ return null;
105
+ };
106
+
107
+ export type { NativeOnlyComponentProps };
108
+ ```
109
+
110
+ ---
111
+
112
+ ## 실전 예시
113
+
114
+ ### 예시 1: Tooltip (웹 전용)
115
+
116
+ DOM API를 사용하므로 RN에서 불가능
117
+
118
+ ```
119
+ Tooltip/
120
+ ├── Tooltip.types.ts
121
+ ├── Tooltip.tsx # 웹 구현
122
+ ├── Tooltip.module.scss
123
+ ├── index.ts # 웹용 export
124
+ ├── index.native.ts # RN용 - null 반환 또는 대안
125
+ └── README.md
126
+ ```
127
+
128
+ **index.native.ts**:
129
+ ```typescript
130
+ import { TooltipProps } from './Tooltip.types';
131
+
132
+ // RN에서는 React Native의 Tooltip 사용 권장
133
+ export const Tooltip: React.FC<TooltipProps> = ({ children }) => {
134
+ return <>{children}</>; // 툴팁 없이 children만 렌더
135
+ };
136
+
137
+ export type { TooltipProps };
138
+ ```
139
+
140
+ ### 예시 2: DatePicker (플랫폼별 구현 차이가 큼)
141
+
142
+ 웹과 RN에서 완전히 다른 API 사용
143
+
144
+ ```
145
+ DatePicker/
146
+ ├── DatePicker.types.ts # 공통 props만
147
+ ├── DatePicker.web.tsx # HTML input type="date"
148
+ ├── DatePicker.native.tsx # @react-native-community/datetimepicker
149
+ ├── index.ts
150
+ └── README.md
151
+ ```
152
+
153
+ ### 예시 3: MapView (RN 전용)
154
+
155
+ react-native-maps 사용
156
+
157
+ ```
158
+ MapView/
159
+ ├── MapView.types.ts
160
+ ├── MapView.tsx # RN 구현
161
+ ├── index.ts # RN export
162
+ ├── index.web.ts # 웹에서는 에러 또는 대안
163
+ └── README.md
164
+ ```
165
+
166
+ **index.web.ts**:
167
+ ```typescript
168
+ export const MapView = () => {
169
+ throw new Error(
170
+ 'MapView is only available on React Native. Use a web map library like react-leaflet instead.'
171
+ );
172
+ };
173
+ ```
174
+
175
+ ---
176
+
177
+ ## 권장 사항
178
+
179
+ ### 플랫폼 전용 컴포넌트를 만들기 전에
180
+
181
+ 1. **정말 플랫폼 전용이 필요한가?**
182
+ - 대부분의 UI 컴포넌트는 크로스 플랫폼 가능
183
+ - 로직만 분리하고 렌더링만 다르게 할 수 있는지 검토
184
+
185
+ 2. **대안 제공**
186
+ - 웹 전용: RN에서는 null 반환 + 경고
187
+ - RN 전용: 웹에서는 에러 throw + 대안 라이브러리 제안
188
+
189
+ 3. **문서화**
190
+ - README.md에 플랫폼 제한 명시
191
+ - 대안 라이브러리/방법 제시
192
+
193
+ 4. **TypeScript 타입은 공유**
194
+ - Props 타입은 양쪽에서 사용 가능하도록
195
+ - 개발자 경험(DX) 향상
@@ -0,0 +1,56 @@
1
+ # StatusBar
2
+
3
+ **플랫폼**: React Native 전용
4
+
5
+ 모바일 상단 상태바(시간, 배터리 등)의 스타일을 제어하는 컴포넌트입니다.
6
+
7
+ ## 플랫폼 지원
8
+
9
+ - ⚠️ **Web**: 지원 안 함 (null 반환)
10
+ - ✅ **React Native**: 완전 지원
11
+
12
+ ## Props
13
+
14
+ | Prop | Type | Required | Description |
15
+ |------|------|----------|-------------|
16
+ | barStyle | 'default' \| 'light-content' \| 'dark-content' | - | 상태바 텍스트 색상 |
17
+ | backgroundColor | string | - | 상태바 배경색 (Android) |
18
+ | hidden | boolean | - | 상태바 숨김 여부 |
19
+
20
+ ## React Native 사용법
21
+
22
+ ```tsx
23
+ import { StatusBar } from '@pisodev/test-component-library';
24
+
25
+ function App() {
26
+ return (
27
+ <>
28
+ <StatusBar
29
+ barStyle="dark-content"
30
+ backgroundColor="#ffffff"
31
+ />
32
+ {/* 나머지 앱 내용 */}
33
+ </>
34
+ );
35
+ }
36
+ ```
37
+
38
+ ## 웹 대안
39
+
40
+ 웹에서는 HTML meta 태그로 브라우저 테마 색상을 제어할 수 있습니다:
41
+
42
+ ```html
43
+ <!-- public/index.html -->
44
+ <meta name="theme-color" content="#ffffff">
45
+ ```
46
+
47
+ 또는 JavaScript로 동적 제어:
48
+
49
+ ```tsx
50
+ useEffect(() => {
51
+ const metaThemeColor = document.querySelector('meta[name="theme-color"]');
52
+ if (metaThemeColor) {
53
+ metaThemeColor.setAttribute('content', '#ffffff');
54
+ }
55
+ }, []);
56
+ ```
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { StatusBar as RNStatusBar } from 'react-native';
3
+ import { StatusBarProps } from './StatusBar.types';
4
+
5
+ export const StatusBar: React.FC<StatusBarProps> = ({
6
+ barStyle = 'default',
7
+ backgroundColor,
8
+ hidden = false,
9
+ }) => {
10
+ return (
11
+ <RNStatusBar
12
+ barStyle={barStyle}
13
+ backgroundColor={backgroundColor}
14
+ hidden={hidden}
15
+ />
16
+ );
17
+ };
@@ -0,0 +1,5 @@
1
+ export interface StatusBarProps {
2
+ barStyle?: 'default' | 'light-content' | 'dark-content';
3
+ backgroundColor?: string;
4
+ hidden?: boolean;
5
+ }
@@ -0,0 +1,3 @@
1
+ // React Native에서만 사용 가능
2
+ export { StatusBar } from './StatusBar';
3
+ export type { StatusBarProps } from './StatusBar.types';
@@ -0,0 +1,14 @@
1
+ import { StatusBarProps } from './StatusBar.types';
2
+
3
+ // 웹에서는 StatusBar 개념이 없음
4
+ export const StatusBar = (_props: StatusBarProps) => {
5
+ if (process.env.NODE_ENV === 'development') {
6
+ console.warn(
7
+ 'StatusBar is only available on React Native. ' +
8
+ 'For web, you can use <meta name="theme-color"> in your HTML.'
9
+ );
10
+ }
11
+ return null;
12
+ };
13
+
14
+ export type { StatusBarProps };
@@ -0,0 +1,45 @@
1
+ # Tooltip
2
+
3
+ **플랫폼**: 웹 전용
4
+
5
+ 마우스 호버 시 툴팁을 표시하는 컴포넌트입니다.
6
+
7
+ ## 플랫폼 지원
8
+
9
+ - ✅ **Web**: 완전 지원
10
+ - ⚠️ **React Native**: children만 렌더링 (툴팁 미표시)
11
+
12
+ ## Props
13
+
14
+ | Prop | Type | Required | Description |
15
+ |------|------|----------|-------------|
16
+ | children | ReactNode | ✓ | 툴팁을 표시할 요소 |
17
+ | content | string | ✓ | 툴팁 내용 |
18
+ | position | 'top' \| 'bottom' \| 'left' \| 'right' | - | 툴팁 위치 (기본: 'top') |
19
+
20
+ ## 웹 사용법
21
+
22
+ ```tsx
23
+ import { Tooltip } from '@pisodev/test-component-library';
24
+
25
+ <Tooltip content="This is a tooltip" position="top">
26
+ <button>Hover me</button>
27
+ </Tooltip>
28
+ ```
29
+
30
+ ## React Native 대안
31
+
32
+ React Native에서는 모바일에 hover 개념이 없으므로:
33
+
34
+ 1. **react-native-tooltip** 사용
35
+ 2. **Modal + Pressable** 조합
36
+ 3. **Long press** 제스처로 툴팁 표시
37
+
38
+ ```tsx
39
+ // RN 대안 예시
40
+ import { Tooltip } from 'react-native-elements';
41
+
42
+ <Tooltip popover={<Text>Info here</Text>}>
43
+ <Text>Press me</Text>
44
+ </Tooltip>
45
+ ```
@@ -0,0 +1,44 @@
1
+ .tooltipWrapper {
2
+ position: relative;
3
+ display: inline-block;
4
+ }
5
+
6
+ .tooltip {
7
+ position: absolute;
8
+ background-color: rgba(0, 0, 0, 0.8);
9
+ color: white;
10
+ padding: 8px 12px;
11
+ border-radius: 4px;
12
+ font-size: 14px;
13
+ white-space: nowrap;
14
+ z-index: 1000;
15
+ pointer-events: none;
16
+
17
+ &.top {
18
+ bottom: 100%;
19
+ left: 50%;
20
+ transform: translateX(-50%);
21
+ margin-bottom: 8px;
22
+ }
23
+
24
+ &.bottom {
25
+ top: 100%;
26
+ left: 50%;
27
+ transform: translateX(-50%);
28
+ margin-top: 8px;
29
+ }
30
+
31
+ &.left {
32
+ right: 100%;
33
+ top: 50%;
34
+ transform: translateY(-50%);
35
+ margin-right: 8px;
36
+ }
37
+
38
+ &.right {
39
+ left: 100%;
40
+ top: 50%;
41
+ transform: translateY(-50%);
42
+ margin-left: 8px;
43
+ }
44
+ }
@@ -0,0 +1,26 @@
1
+ import React, { useState } from 'react';
2
+ import { TooltipProps } from './Tooltip.types';
3
+ import styles from './Tooltip.module.scss';
4
+
5
+ export const Tooltip: React.FC<TooltipProps> = ({
6
+ children,
7
+ content,
8
+ position = 'top',
9
+ }) => {
10
+ const [isVisible, setIsVisible] = useState(false);
11
+
12
+ return (
13
+ <div
14
+ className={styles.tooltipWrapper}
15
+ onMouseEnter={() => setIsVisible(true)}
16
+ onMouseLeave={() => setIsVisible(false)}
17
+ >
18
+ {children}
19
+ {isVisible && (
20
+ <div className={`${styles.tooltip} ${styles[position]}`}>
21
+ {content}
22
+ </div>
23
+ )}
24
+ </div>
25
+ );
26
+ };
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ export interface TooltipProps {
4
+ children: ReactNode;
5
+ content: string;
6
+ position?: 'top' | 'bottom' | 'left' | 'right';
7
+ }
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { TooltipProps } from './Tooltip.types';
3
+
4
+ // React Native에서는 Tooltip 미지원
5
+ // children만 렌더링하고 tooltip은 무시
6
+ export const Tooltip: React.FC<TooltipProps> = ({ children }) => {
7
+ if (process.env.NODE_ENV === 'development') {
8
+ console.warn(
9
+ 'Tooltip is web-only. On React Native, consider using a modal or overlay library.'
10
+ );
11
+ }
12
+ return children as React.ReactElement;
13
+ };
14
+
15
+ export type { TooltipProps };
@@ -0,0 +1,3 @@
1
+ // 웹에서만 사용 가능
2
+ export { Tooltip } from './Tooltip';
3
+ export type { TooltipProps } from './Tooltip.types';
@@ -0,0 +1,8 @@
1
+ // 크로스 플랫폼 컴포넌트
2
+ export * from './Anchor';
3
+
4
+ // 웹 전용 컴포넌트 (RN에서는 fallback 제공)
5
+ export * from './Tooltip';
6
+
7
+ // React Native 전용 컴포넌트 (웹에서는 null 반환)
8
+ export * from './StatusBar';
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { AnchorProps } from './Anchor.types';
3
+ export declare const Anchor: React.FC<AnchorProps>;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Anchor = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ const Anchor = ({ children, href, title, onPress, }) => {
10
+ const handlePress = () => {
11
+ if (onPress) {
12
+ onPress();
13
+ }
14
+ else if (href) {
15
+ react_native_1.Linking.openURL(href);
16
+ }
17
+ };
18
+ return (<react_native_1.Pressable onPress={handlePress} accessibilityRole="link" accessibilityLabel={title} accessibilityHint={`Opens ${href}`}>
19
+ {({ pressed }) => (<react_native_1.Text style={[styles.anchor, pressed && styles.anchorPressed]}>
20
+ {children}
21
+ </react_native_1.Text>)}
22
+ </react_native_1.Pressable>);
23
+ };
24
+ exports.Anchor = Anchor;
25
+ const styles = react_native_1.StyleSheet.create({
26
+ anchor: {
27
+ color: '#2196f3',
28
+ textDecorationLine: 'none',
29
+ },
30
+ anchorPressed: {
31
+ color: '#1976d2',
32
+ textDecorationLine: 'underline',
33
+ },
34
+ });
@@ -0,0 +1,10 @@
1
+ import { ReactNode } from 'react';
2
+ export interface AnchorProps {
3
+ children: ReactNode;
4
+ href: string;
5
+ rel?: string;
6
+ title?: string;
7
+ target?: '_blank' | '_self' | '_parent' | '_top';
8
+ className?: string;
9
+ onPress?: () => void;
10
+ }