@urbint/cl 1.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.
- package/.cursor/rules +313 -0
- package/.rnstorybook/index.ts +11 -0
- package/.rnstorybook/main.ts +8 -0
- package/.rnstorybook/preview.tsx +14 -0
- package/.rnstorybook/storybook.requires.ts +49 -0
- package/.storybook/main.ts +16 -0
- package/.storybook/preview.ts +32 -0
- package/.storybook/vitest.setup.ts +7 -0
- package/App.tsx +422 -0
- package/README.md +229 -0
- package/app.json +33 -0
- package/assets/adaptive-icon.png +0 -0
- package/assets/favicon.png +0 -0
- package/assets/icon.png +0 -0
- package/assets/splash-icon.png +0 -0
- package/babel.config.js +16 -0
- package/docs/components/CodeBlock.tsx +80 -0
- package/docs/components/PropTable.tsx +93 -0
- package/docs/components/Sidebar.tsx +199 -0
- package/docs/components/index.ts +8 -0
- package/docs/data/colorTokens.ts +70 -0
- package/docs/data/componentData.tsx +1685 -0
- package/docs/data/index.ts +7 -0
- package/docs/index.ts +19 -0
- package/docs/navigation.ts +94 -0
- package/docs/pages/ColorsPage.tsx +226 -0
- package/docs/pages/ComponentPage.tsx +235 -0
- package/docs/pages/InstallationPage.tsx +232 -0
- package/docs/pages/IntroductionPage.tsx +163 -0
- package/docs/pages/ThemingPage.tsx +251 -0
- package/docs/pages/index.ts +10 -0
- package/docs/theme.ts +64 -0
- package/docs/types.ts +54 -0
- package/index.ts +8 -0
- package/llms.txt +1893 -0
- package/mcp-config.example.json +10 -0
- package/mcp-server/README.md +192 -0
- package/mcp-server/package-lock.json +1707 -0
- package/mcp-server/package.json +38 -0
- package/mcp-server/src/index.ts +1136 -0
- package/mcp-server/src/registry/components.ts +1446 -0
- package/mcp-server/src/registry/index.ts +3 -0
- package/mcp-server/src/registry/tokens.ts +256 -0
- package/mcp-server/tsconfig.json +19 -0
- package/package.json +92 -0
- package/src/components/Accordion/Accordion.stories.tsx +226 -0
- package/src/components/Accordion/Accordion.tsx +255 -0
- package/src/components/Accordion/index.ts +12 -0
- package/src/components/ActionSheet/ActionSheet.stories.tsx +393 -0
- package/src/components/ActionSheet/ActionSheet.tsx +258 -0
- package/src/components/ActionSheet/index.ts +2 -0
- package/src/components/Alert/Alert.stories.tsx +165 -0
- package/src/components/Alert/Alert.tsx +164 -0
- package/src/components/Alert/index.ts +2 -0
- package/src/components/AlertDialog/AlertDialog.stories.tsx +330 -0
- package/src/components/AlertDialog/AlertDialog.tsx +234 -0
- package/src/components/AlertDialog/index.ts +2 -0
- package/src/components/Avatar/Avatar.stories.tsx +154 -0
- package/src/components/Avatar/Avatar.tsx +219 -0
- package/src/components/Avatar/index.ts +2 -0
- package/src/components/Badge/Badge.stories.tsx +146 -0
- package/src/components/Badge/Badge.tsx +125 -0
- package/src/components/Badge/index.ts +2 -0
- package/src/components/Box/Box.stories.tsx +192 -0
- package/src/components/Box/Box.tsx +184 -0
- package/src/components/Box/index.ts +2 -0
- package/src/components/Button/Button.stories.tsx +157 -0
- package/src/components/Button/Button.tsx +180 -0
- package/src/components/Button/index.ts +2 -0
- package/src/components/Card/Card.stories.tsx +145 -0
- package/src/components/Card/Card.tsx +169 -0
- package/src/components/Card/index.ts +11 -0
- package/src/components/Center/Center.stories.tsx +215 -0
- package/src/components/Center/Center.tsx +29 -0
- package/src/components/Center/index.ts +2 -0
- package/src/components/Checkbox/Checkbox.stories.tsx +94 -0
- package/src/components/Checkbox/Checkbox.tsx +242 -0
- package/src/components/Checkbox/index.ts +2 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +623 -0
- package/src/components/DatePicker/DatePicker.tsx +1228 -0
- package/src/components/DatePicker/index.ts +8 -0
- package/src/components/Divider/Divider.stories.tsx +224 -0
- package/src/components/Divider/Divider.tsx +73 -0
- package/src/components/Divider/index.ts +2 -0
- package/src/components/Drawer/Drawer.stories.tsx +414 -0
- package/src/components/Drawer/Drawer.tsx +342 -0
- package/src/components/Drawer/index.ts +11 -0
- package/src/components/Fab/Fab.stories.tsx +360 -0
- package/src/components/Fab/Fab.tsx +185 -0
- package/src/components/Fab/index.ts +2 -0
- package/src/components/FormControl/FormControl.stories.tsx +276 -0
- package/src/components/FormControl/FormControl.tsx +185 -0
- package/src/components/FormControl/index.ts +12 -0
- package/src/components/Grid/Grid.stories.tsx +244 -0
- package/src/components/Grid/Grid.tsx +93 -0
- package/src/components/Grid/index.ts +2 -0
- package/src/components/HStack/HStack.stories.tsx +230 -0
- package/src/components/HStack/HStack.tsx +80 -0
- package/src/components/HStack/index.ts +2 -0
- package/src/components/Heading/Heading.stories.tsx +111 -0
- package/src/components/Heading/Heading.tsx +85 -0
- package/src/components/Heading/index.ts +2 -0
- package/src/components/Icon/Icon.stories.tsx +320 -0
- package/src/components/Icon/Icon.tsx +117 -0
- package/src/components/Icon/index.ts +2 -0
- package/src/components/Image/Image.stories.tsx +357 -0
- package/src/components/Image/Image.tsx +168 -0
- package/src/components/Image/index.ts +2 -0
- package/src/components/Input/Input.stories.tsx +164 -0
- package/src/components/Input/Input.tsx +274 -0
- package/src/components/Input/index.ts +2 -0
- package/src/components/Link/Link.stories.tsx +187 -0
- package/src/components/Link/Link.tsx +104 -0
- package/src/components/Link/index.ts +2 -0
- package/src/components/Menu/Menu.stories.tsx +363 -0
- package/src/components/Menu/Menu.tsx +238 -0
- package/src/components/Menu/index.ts +2 -0
- package/src/components/Modal/Modal.stories.tsx +156 -0
- package/src/components/Modal/Modal.tsx +280 -0
- package/src/components/Modal/index.ts +11 -0
- package/src/components/Popover/Popover.stories.tsx +330 -0
- package/src/components/Popover/Popover.tsx +315 -0
- package/src/components/Popover/index.ts +11 -0
- package/src/components/Portal/Portal.stories.tsx +376 -0
- package/src/components/Portal/Portal.tsx +100 -0
- package/src/components/Portal/index.ts +2 -0
- package/src/components/Pressable/Pressable.stories.tsx +338 -0
- package/src/components/Pressable/Pressable.tsx +71 -0
- package/src/components/Pressable/index.ts +2 -0
- package/src/components/Progress/Progress.stories.tsx +131 -0
- package/src/components/Progress/Progress.tsx +219 -0
- package/src/components/Progress/index.ts +2 -0
- package/src/components/Radio/Radio.stories.tsx +101 -0
- package/src/components/Radio/Radio.tsx +234 -0
- package/src/components/Radio/index.ts +2 -0
- package/src/components/Select/Select.stories.tsx +908 -0
- package/src/components/Select/Select.tsx +659 -0
- package/src/components/Select/index.ts +8 -0
- package/src/components/Skeleton/Skeleton.stories.tsx +154 -0
- package/src/components/Skeleton/Skeleton.tsx +192 -0
- package/src/components/Skeleton/index.ts +8 -0
- package/src/components/Slider/Slider.stories.tsx +363 -0
- package/src/components/Slider/Slider.tsx +209 -0
- package/src/components/Slider/index.ts +2 -0
- package/src/components/Spinner/Spinner.stories.tsx +108 -0
- package/src/components/Spinner/Spinner.tsx +121 -0
- package/src/components/Spinner/index.ts +2 -0
- package/src/components/Switch/Switch.stories.tsx +116 -0
- package/src/components/Switch/Switch.tsx +172 -0
- package/src/components/Switch/index.ts +2 -0
- package/src/components/Table/Table.stories.tsx +417 -0
- package/src/components/Table/Table.tsx +233 -0
- package/src/components/Table/index.ts +2 -0
- package/src/components/Text/Text.stories.tsx +93 -0
- package/src/components/Text/Text.tsx +119 -0
- package/src/components/Text/index.ts +2 -0
- package/src/components/Textarea/Textarea.stories.tsx +280 -0
- package/src/components/Textarea/Textarea.tsx +212 -0
- package/src/components/Textarea/index.ts +2 -0
- package/src/components/Toast/Toast.stories.tsx +446 -0
- package/src/components/Toast/Toast.tsx +221 -0
- package/src/components/Toast/index.ts +2 -0
- package/src/components/Tooltip/Tooltip.stories.tsx +354 -0
- package/src/components/Tooltip/Tooltip.tsx +261 -0
- package/src/components/Tooltip/index.ts +2 -0
- package/src/components/VStack/VStack.stories.tsx +183 -0
- package/src/components/VStack/VStack.tsx +76 -0
- package/src/components/VStack/index.ts +2 -0
- package/src/components/index.ts +62 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/useControllableState.ts +41 -0
- package/src/hooks/useDisclosure.ts +51 -0
- package/src/index.ts +22 -0
- package/src/stories/Button.stories.tsx +53 -0
- package/src/stories/Button.tsx +101 -0
- package/src/stories/Configure.mdx +364 -0
- package/src/stories/Header.stories.tsx +33 -0
- package/src/stories/Header.tsx +75 -0
- package/src/stories/Page.stories.tsx +25 -0
- package/src/stories/Page.tsx +154 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/styles/index.ts +7 -0
- package/src/styles/tokens.ts +318 -0
- package/src/styles/unistyles.ts +254 -0
- package/src/utils/createContext.tsx +25 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/mergeRefs.ts +21 -0
- package/tsconfig.json +26 -0
- package/urbint-cl-1.0.0.tgz +0 -0
- package/vitest.config.ts +37 -0
- package/vitest.shims.d.ts +1 -0
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Table Component
|
|
3
|
+
* Data table with sorting and styling
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { forwardRef } from 'react';
|
|
7
|
+
import { View, ViewProps, Text, ScrollView, Pressable, StyleSheet } from 'react-native';
|
|
8
|
+
import Svg, { Path } from 'react-native-svg';
|
|
9
|
+
import { colors, spacing, borderRadius, typography } from '../../styles/tokens';
|
|
10
|
+
|
|
11
|
+
export interface TableColumn<T> {
|
|
12
|
+
key: keyof T | string;
|
|
13
|
+
header: string;
|
|
14
|
+
width?: number | string;
|
|
15
|
+
render?: (item: T, index: number) => React.ReactNode;
|
|
16
|
+
sortable?: boolean;
|
|
17
|
+
align?: 'left' | 'center' | 'right';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface TableProps<T> extends ViewProps {
|
|
21
|
+
/** Table data */
|
|
22
|
+
data: T[];
|
|
23
|
+
/** Table columns */
|
|
24
|
+
columns: TableColumn<T>[];
|
|
25
|
+
/** Is striped */
|
|
26
|
+
isStriped?: boolean;
|
|
27
|
+
/** Show borders */
|
|
28
|
+
showBorders?: boolean;
|
|
29
|
+
/** Table variant */
|
|
30
|
+
variant?: 'simple' | 'striped' | 'unstyled';
|
|
31
|
+
/** Table size */
|
|
32
|
+
size?: 'sm' | 'md' | 'lg';
|
|
33
|
+
/** On row press */
|
|
34
|
+
onRowPress?: (item: T, index: number) => void;
|
|
35
|
+
/** Key extractor */
|
|
36
|
+
keyExtractor?: (item: T, index: number) => string;
|
|
37
|
+
/** Sort column */
|
|
38
|
+
sortColumn?: string;
|
|
39
|
+
/** Sort direction */
|
|
40
|
+
sortDirection?: 'asc' | 'desc';
|
|
41
|
+
/** On sort change */
|
|
42
|
+
onSortChange?: (column: string, direction: 'asc' | 'desc') => void;
|
|
43
|
+
/** Empty state */
|
|
44
|
+
emptyState?: React.ReactNode;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function TableComponent<T extends Record<string, any>>(
|
|
48
|
+
{
|
|
49
|
+
style,
|
|
50
|
+
data,
|
|
51
|
+
columns,
|
|
52
|
+
variant = 'simple',
|
|
53
|
+
size = 'md',
|
|
54
|
+
onRowPress,
|
|
55
|
+
keyExtractor,
|
|
56
|
+
sortColumn,
|
|
57
|
+
sortDirection = 'asc',
|
|
58
|
+
onSortChange,
|
|
59
|
+
emptyState,
|
|
60
|
+
...props
|
|
61
|
+
}: TableProps<T>,
|
|
62
|
+
ref: React.Ref<View>
|
|
63
|
+
) {
|
|
64
|
+
const handleSort = (column: TableColumn<T>) => {
|
|
65
|
+
if (!column.sortable || !onSortChange) return;
|
|
66
|
+
const newDirection =
|
|
67
|
+
sortColumn === column.key && sortDirection === 'asc' ? 'desc' : 'asc';
|
|
68
|
+
onSortChange(column.key as string, newDirection);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const getCellValue = (item: T, column: TableColumn<T>, index: number) => {
|
|
72
|
+
if (column.render) {
|
|
73
|
+
return column.render(item, index);
|
|
74
|
+
}
|
|
75
|
+
const value = item[column.key as keyof T];
|
|
76
|
+
return value !== undefined && value !== null ? String(value) : '-';
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const isStriped = variant === 'striped';
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
|
|
83
|
+
<View ref={ref} style={[styles.table, style]} {...props}>
|
|
84
|
+
<View style={styles.header}>
|
|
85
|
+
{columns.map((column) => (
|
|
86
|
+
<Pressable
|
|
87
|
+
key={column.key as string}
|
|
88
|
+
onPress={() => handleSort(column)}
|
|
89
|
+
disabled={!column.sortable}
|
|
90
|
+
style={[
|
|
91
|
+
styles.headerCell,
|
|
92
|
+
styles[`${size}Cell` as keyof typeof styles],
|
|
93
|
+
column.width ? { width: column.width } : styles.flexCell,
|
|
94
|
+
column.align && styles[`align${column.align.charAt(0).toUpperCase() + column.align.slice(1)}` as keyof typeof styles],
|
|
95
|
+
]}
|
|
96
|
+
>
|
|
97
|
+
<Text style={styles.headerText}>{column.header}</Text>
|
|
98
|
+
{column.sortable && sortColumn === column.key && (
|
|
99
|
+
<View style={styles.sortIcon}>
|
|
100
|
+
<Svg width={12} height={12} viewBox="0 0 24 24" fill="none">
|
|
101
|
+
<Path
|
|
102
|
+
d={sortDirection === 'asc' ? 'M18 15l-6-6-6 6' : 'M6 9l6 6 6-6'}
|
|
103
|
+
stroke={colors.text.secondary}
|
|
104
|
+
strokeWidth={2}
|
|
105
|
+
strokeLinecap="round"
|
|
106
|
+
strokeLinejoin="round"
|
|
107
|
+
/>
|
|
108
|
+
</Svg>
|
|
109
|
+
</View>
|
|
110
|
+
)}
|
|
111
|
+
</Pressable>
|
|
112
|
+
))}
|
|
113
|
+
</View>
|
|
114
|
+
|
|
115
|
+
{data.length === 0 ? (
|
|
116
|
+
<View style={styles.emptyState}>
|
|
117
|
+
{emptyState || <Text style={styles.emptyText}>No data available</Text>}
|
|
118
|
+
</View>
|
|
119
|
+
) : (
|
|
120
|
+
data.map((item, rowIndex) => (
|
|
121
|
+
<Pressable
|
|
122
|
+
key={keyExtractor ? keyExtractor(item, rowIndex) : rowIndex}
|
|
123
|
+
onPress={onRowPress ? () => onRowPress(item, rowIndex) : undefined}
|
|
124
|
+
style={[
|
|
125
|
+
styles.row,
|
|
126
|
+
isStriped && rowIndex % 2 === 1 && styles.stripedRow,
|
|
127
|
+
]}
|
|
128
|
+
>
|
|
129
|
+
{columns.map((column) => (
|
|
130
|
+
<View
|
|
131
|
+
key={`${rowIndex}-${column.key as string}`}
|
|
132
|
+
style={[
|
|
133
|
+
styles.cell,
|
|
134
|
+
styles[`${size}Cell` as keyof typeof styles],
|
|
135
|
+
column.width ? { width: column.width } : styles.flexCell,
|
|
136
|
+
column.align && styles[`align${column.align.charAt(0).toUpperCase() + column.align.slice(1)}` as keyof typeof styles],
|
|
137
|
+
]}
|
|
138
|
+
>
|
|
139
|
+
{typeof getCellValue(item, column, rowIndex) === 'string' ? (
|
|
140
|
+
<Text style={styles.cellText}>
|
|
141
|
+
{getCellValue(item, column, rowIndex)}
|
|
142
|
+
</Text>
|
|
143
|
+
) : (
|
|
144
|
+
getCellValue(item, column, rowIndex)
|
|
145
|
+
)}
|
|
146
|
+
</View>
|
|
147
|
+
))}
|
|
148
|
+
</Pressable>
|
|
149
|
+
))
|
|
150
|
+
)}
|
|
151
|
+
</View>
|
|
152
|
+
</ScrollView>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export const Table = forwardRef(TableComponent) as <T extends Record<string, any>>(
|
|
157
|
+
props: TableProps<T> & { ref?: React.Ref<View> }
|
|
158
|
+
) => React.ReactElement;
|
|
159
|
+
|
|
160
|
+
const styles = StyleSheet.create({
|
|
161
|
+
table: {
|
|
162
|
+
borderWidth: 1,
|
|
163
|
+
borderColor: colors.border.disabled,
|
|
164
|
+
borderRadius: borderRadius.md,
|
|
165
|
+
overflow: 'hidden',
|
|
166
|
+
minWidth: '100%',
|
|
167
|
+
},
|
|
168
|
+
header: {
|
|
169
|
+
flexDirection: 'row',
|
|
170
|
+
backgroundColor: colors.background.secondary,
|
|
171
|
+
borderBottomWidth: 1,
|
|
172
|
+
borderBottomColor: colors.border.disabled,
|
|
173
|
+
},
|
|
174
|
+
headerCell: {
|
|
175
|
+
flexDirection: 'row',
|
|
176
|
+
alignItems: 'center',
|
|
177
|
+
},
|
|
178
|
+
headerText: {
|
|
179
|
+
fontSize: typography.fontSize.componentLabel,
|
|
180
|
+
fontWeight: typography.fontWeight.semiBold,
|
|
181
|
+
color: colors.text.default,
|
|
182
|
+
},
|
|
183
|
+
row: {
|
|
184
|
+
flexDirection: 'row',
|
|
185
|
+
borderBottomWidth: 1,
|
|
186
|
+
borderBottomColor: colors.border.disabled,
|
|
187
|
+
},
|
|
188
|
+
stripedRow: {
|
|
189
|
+
backgroundColor: colors.background.secondary,
|
|
190
|
+
},
|
|
191
|
+
cell: {},
|
|
192
|
+
cellText: {
|
|
193
|
+
fontSize: typography.fontSize.body,
|
|
194
|
+
color: colors.text.default,
|
|
195
|
+
},
|
|
196
|
+
flexCell: {
|
|
197
|
+
flex: 1,
|
|
198
|
+
minWidth: 100,
|
|
199
|
+
},
|
|
200
|
+
smCell: {
|
|
201
|
+
paddingVertical: spacing['2x'],
|
|
202
|
+
paddingHorizontal: spacing['3x'],
|
|
203
|
+
},
|
|
204
|
+
mdCell: {
|
|
205
|
+
paddingVertical: spacing['3x'],
|
|
206
|
+
paddingHorizontal: spacing['4x'],
|
|
207
|
+
},
|
|
208
|
+
lgCell: {
|
|
209
|
+
paddingVertical: spacing['4x'],
|
|
210
|
+
paddingHorizontal: spacing['6x'],
|
|
211
|
+
},
|
|
212
|
+
alignLeft: {
|
|
213
|
+
justifyContent: 'flex-start',
|
|
214
|
+
},
|
|
215
|
+
alignCenter: {
|
|
216
|
+
justifyContent: 'center',
|
|
217
|
+
},
|
|
218
|
+
alignRight: {
|
|
219
|
+
justifyContent: 'flex-end',
|
|
220
|
+
},
|
|
221
|
+
sortIcon: {
|
|
222
|
+
marginLeft: spacing.base,
|
|
223
|
+
},
|
|
224
|
+
emptyState: {
|
|
225
|
+
padding: spacing['8x'],
|
|
226
|
+
alignItems: 'center',
|
|
227
|
+
justifyContent: 'center',
|
|
228
|
+
},
|
|
229
|
+
emptyText: {
|
|
230
|
+
fontSize: typography.fontSize.body,
|
|
231
|
+
color: colors.text.secondary,
|
|
232
|
+
},
|
|
233
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Text } from './Text';
|
|
3
|
+
import { VStack } from '../VStack';
|
|
4
|
+
import { colors, spacing } from '../../styles/tokens';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof Text> = {
|
|
7
|
+
title: 'Components/Text',
|
|
8
|
+
component: Text,
|
|
9
|
+
argTypes: {
|
|
10
|
+
variant: {
|
|
11
|
+
control: 'select',
|
|
12
|
+
options: ['body', 'caption', 'label', 'small'],
|
|
13
|
+
},
|
|
14
|
+
weight: {
|
|
15
|
+
control: 'select',
|
|
16
|
+
options: ['regular', 'medium', 'semiBold', 'bold'],
|
|
17
|
+
},
|
|
18
|
+
align: {
|
|
19
|
+
control: 'select',
|
|
20
|
+
options: ['left', 'center', 'right'],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
args: {
|
|
24
|
+
children: 'The quick brown fox jumps over the lazy dog.',
|
|
25
|
+
variant: 'body',
|
|
26
|
+
weight: 'regular',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default meta;
|
|
31
|
+
|
|
32
|
+
type Story = StoryObj<typeof Text>;
|
|
33
|
+
|
|
34
|
+
export const Default: Story = {};
|
|
35
|
+
|
|
36
|
+
export const Variants: Story = {
|
|
37
|
+
render: () => (
|
|
38
|
+
<VStack space={spacing.md}>
|
|
39
|
+
<Text variant="body">Body Text (16px) - Used for longer sections of text</Text>
|
|
40
|
+
<Text variant="caption">Caption Text (13px) - Used in limited real estate</Text>
|
|
41
|
+
<Text variant="label">Label Text (14px) - Used for form labels, badges</Text>
|
|
42
|
+
<Text variant="small">Small Text (12px) - Used for small annotations</Text>
|
|
43
|
+
</VStack>
|
|
44
|
+
),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const Weights: Story = {
|
|
48
|
+
render: () => (
|
|
49
|
+
<VStack space={spacing.sm}>
|
|
50
|
+
<Text weight="regular">Regular (400) - Normal text weight</Text>
|
|
51
|
+
<Text weight="medium">Medium (500) - Slightly emphasized</Text>
|
|
52
|
+
<Text weight="semiBold">Semi Bold (600) - Strong emphasis</Text>
|
|
53
|
+
<Text weight="bold">Bold (700) - Maximum emphasis</Text>
|
|
54
|
+
</VStack>
|
|
55
|
+
),
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const Styling: Story = {
|
|
59
|
+
render: () => (
|
|
60
|
+
<VStack space={spacing.sm}>
|
|
61
|
+
<Text color="#00A0CC">Custom Color Text</Text>
|
|
62
|
+
<Text strikethrough>Strikethrough Text</Text>
|
|
63
|
+
<Text underline>Underlined Text</Text>
|
|
64
|
+
<Text italic>Italic Text</Text>
|
|
65
|
+
<Text transform="uppercase">Uppercase Text</Text>
|
|
66
|
+
</VStack>
|
|
67
|
+
),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const Truncation: Story = {
|
|
71
|
+
render: () => (
|
|
72
|
+
<VStack space={spacing.md} style={{ width: 250 }}>
|
|
73
|
+
<Text truncate>
|
|
74
|
+
This is a very long text that will be truncated to a single line with ellipsis.
|
|
75
|
+
</Text>
|
|
76
|
+
<Text noOfLines={2}>
|
|
77
|
+
This is a very long text that will be truncated after two lines. It continues with
|
|
78
|
+
more content that should be cut off and show an ellipsis at the end.
|
|
79
|
+
</Text>
|
|
80
|
+
</VStack>
|
|
81
|
+
),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const Alignment: Story = {
|
|
85
|
+
render: () => (
|
|
86
|
+
<VStack space={spacing.sm}>
|
|
87
|
+
<Text align="left">Left aligned text</Text>
|
|
88
|
+
<Text align="center">Center aligned text</Text>
|
|
89
|
+
<Text align="right">Right aligned text</Text>
|
|
90
|
+
</VStack>
|
|
91
|
+
),
|
|
92
|
+
};
|
|
93
|
+
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text Component
|
|
3
|
+
* Core typography component with variants and styling
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { forwardRef } from 'react';
|
|
7
|
+
import { Text as RNText, TextProps as RNTextProps, TextStyle, StyleSheet } from 'react-native';
|
|
8
|
+
import { colors, typography } from '../../styles/tokens';
|
|
9
|
+
|
|
10
|
+
export interface TextProps extends RNTextProps {
|
|
11
|
+
/** Text variant */
|
|
12
|
+
variant?: 'body' | 'caption' | 'label' | 'small';
|
|
13
|
+
/** Font weight */
|
|
14
|
+
weight?: 'regular' | 'medium' | 'semiBold' | 'bold';
|
|
15
|
+
/** Text color */
|
|
16
|
+
color?: string;
|
|
17
|
+
/** Text alignment */
|
|
18
|
+
align?: TextStyle['textAlign'];
|
|
19
|
+
/** Transform text */
|
|
20
|
+
transform?: TextStyle['textTransform'];
|
|
21
|
+
/** Strikethrough */
|
|
22
|
+
strikethrough?: boolean;
|
|
23
|
+
/** Underline */
|
|
24
|
+
underline?: boolean;
|
|
25
|
+
/** Italic */
|
|
26
|
+
italic?: boolean;
|
|
27
|
+
/** Truncate with ellipsis */
|
|
28
|
+
truncate?: boolean;
|
|
29
|
+
/** Number of lines before truncating */
|
|
30
|
+
noOfLines?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const Text = forwardRef<RNText, TextProps>(
|
|
34
|
+
(
|
|
35
|
+
{
|
|
36
|
+
style,
|
|
37
|
+
variant = 'body',
|
|
38
|
+
weight = 'regular',
|
|
39
|
+
color,
|
|
40
|
+
align,
|
|
41
|
+
transform,
|
|
42
|
+
strikethrough,
|
|
43
|
+
underline,
|
|
44
|
+
italic,
|
|
45
|
+
truncate,
|
|
46
|
+
noOfLines,
|
|
47
|
+
children,
|
|
48
|
+
...props
|
|
49
|
+
},
|
|
50
|
+
ref
|
|
51
|
+
) => {
|
|
52
|
+
const textDecorationLine = [
|
|
53
|
+
strikethrough && 'line-through',
|
|
54
|
+
underline && 'underline',
|
|
55
|
+
]
|
|
56
|
+
.filter(Boolean)
|
|
57
|
+
.join(' ') as TextStyle['textDecorationLine'];
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<RNText
|
|
61
|
+
ref={ref}
|
|
62
|
+
numberOfLines={truncate ? 1 : noOfLines}
|
|
63
|
+
ellipsizeMode={truncate || noOfLines ? 'tail' : undefined}
|
|
64
|
+
style={[
|
|
65
|
+
styles.base,
|
|
66
|
+
styles[variant],
|
|
67
|
+
styles[`weight${weight.charAt(0).toUpperCase() + weight.slice(1)}` as keyof typeof styles],
|
|
68
|
+
color && { color },
|
|
69
|
+
align && { textAlign: align },
|
|
70
|
+
transform && { textTransform: transform },
|
|
71
|
+
textDecorationLine && { textDecorationLine },
|
|
72
|
+
italic && { fontStyle: 'italic' },
|
|
73
|
+
style,
|
|
74
|
+
]}
|
|
75
|
+
{...props}
|
|
76
|
+
>
|
|
77
|
+
{children}
|
|
78
|
+
</RNText>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
Text.displayName = 'Text';
|
|
84
|
+
|
|
85
|
+
const styles = StyleSheet.create({
|
|
86
|
+
base: {
|
|
87
|
+
color: colors.text.default,
|
|
88
|
+
},
|
|
89
|
+
body: {
|
|
90
|
+
fontSize: typography.fontSize.body,
|
|
91
|
+
lineHeight: typography.fontSize.body * typography.lineHeight.tight,
|
|
92
|
+
},
|
|
93
|
+
caption: {
|
|
94
|
+
fontSize: typography.fontSize.caption,
|
|
95
|
+
lineHeight: typography.fontSize.caption * typography.lineHeight.normal,
|
|
96
|
+
color: colors.text.secondary,
|
|
97
|
+
},
|
|
98
|
+
label: {
|
|
99
|
+
fontSize: typography.fontSize.componentLabel,
|
|
100
|
+
lineHeight: typography.fontSize.componentLabel * typography.lineHeight.normal,
|
|
101
|
+
},
|
|
102
|
+
small: {
|
|
103
|
+
fontSize: typography.fontSize.small,
|
|
104
|
+
lineHeight: typography.fontSize.small * typography.lineHeight.normal,
|
|
105
|
+
},
|
|
106
|
+
weightRegular: {
|
|
107
|
+
fontWeight: typography.fontWeight.regular,
|
|
108
|
+
},
|
|
109
|
+
weightMedium: {
|
|
110
|
+
fontWeight: typography.fontWeight.medium,
|
|
111
|
+
},
|
|
112
|
+
weightSemiBold: {
|
|
113
|
+
fontWeight: typography.fontWeight.semiBold,
|
|
114
|
+
},
|
|
115
|
+
weightBold: {
|
|
116
|
+
fontWeight: typography.fontWeight.bold,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|