@factorialco/f0-react-native 0.25.0 → 0.27.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 (126) hide show
  1. package/lib/module/components/Activity/ActivityItem/index.js +1 -1
  2. package/lib/module/components/Avatars/BaseAvatar/index.js +1 -1
  3. package/lib/module/components/Avatars/DateAvatar/index.js +1 -1
  4. package/lib/module/components/Avatars/EmojiAvatar/index.js +1 -1
  5. package/lib/module/components/Avatars/FileAvatar/index.js +1 -1
  6. package/lib/module/components/Avatars/FileAvatar/utils.js +1 -1
  7. package/lib/module/components/Avatars/IconAvatar/index.js +1 -1
  8. package/lib/module/components/Avatars/ModuleAvatar/index.js +1 -1
  9. package/lib/module/components/Badge/index.js +1 -1
  10. package/lib/module/components/Button/index.js +1 -1
  11. package/lib/module/components/Counter/index.js +1 -1
  12. package/lib/module/components/ExampleComponent.js +1 -1
  13. package/lib/module/components/Icon/README.md +1 -1
  14. package/lib/module/components/Navigation/PageHeader/index.js +1 -1
  15. package/lib/module/components/OneChip/index.js +1 -1
  16. package/lib/module/components/OnePreset/index.js +1 -1
  17. package/lib/module/components/Tags/AlertTab/index.js +1 -1
  18. package/lib/module/components/Tags/BaseTag/index.js +1 -1
  19. package/lib/module/components/Tags/DotTag/index.js +1 -1
  20. package/lib/module/components/Tags/RawTag/index.js +1 -1
  21. package/lib/module/components/experimental/Lists/DataList/ItemContainer.js +1 -1
  22. package/lib/module/components/experimental/Lists/DataList/actions/CopyAction.js +1 -1
  23. package/lib/module/components/experimental/Lists/DataList/actions/GenericAction.js +1 -1
  24. package/lib/module/components/experimental/Lists/DataList/index.js +1 -1
  25. package/lib/module/components/experimental/Lists/DetailsItemsList/index.js +1 -1
  26. package/lib/module/components/exports.js +1 -1
  27. package/lib/module/components/exports.js.map +1 -1
  28. package/lib/module/components/primitives/F0Text/F0Text.js +2 -0
  29. package/lib/module/components/primitives/F0Text/F0Text.js.map +1 -0
  30. package/lib/module/components/primitives/F0Text/F0Text.md +297 -0
  31. package/lib/module/components/primitives/F0Text/F0Text.styles.js +2 -0
  32. package/lib/module/components/primitives/F0Text/F0Text.styles.js.map +1 -0
  33. package/lib/module/components/primitives/F0Text/F0Text.types.js +2 -0
  34. package/lib/module/components/primitives/F0Text/F0Text.types.js.map +1 -0
  35. package/lib/module/components/primitives/F0Text/index.js +2 -0
  36. package/lib/module/components/primitives/F0Text/index.js.map +1 -0
  37. package/lib/module/icons/app/QuestionCircle.js +1 -1
  38. package/lib/module/icons/app/QuestionCircle.js.map +1 -1
  39. package/lib/module/icons/app/index.js +1 -1
  40. package/lib/module/icons/app/index.js.map +1 -1
  41. package/lib/module/index.js +1 -1
  42. package/lib/module/index.js.map +1 -1
  43. package/lib/module/lib/utils.js +1 -1
  44. package/lib/module/lib/utils.js.map +1 -1
  45. package/lib/module/styles/theme.css +308 -237
  46. package/lib/module/styles/tokens/colors.js +1 -1
  47. package/lib/module/styles/tokens/colors.js.map +1 -1
  48. package/lib/module/ui/avatar.js +1 -1
  49. package/lib/typescript/components/OneChip/index.d.ts +2 -2
  50. package/lib/typescript/components/exports.d.ts +1 -0
  51. package/lib/typescript/components/exports.d.ts.map +1 -1
  52. package/lib/typescript/components/primitives/F0Text/F0Text.d.ts +8 -0
  53. package/lib/typescript/components/primitives/F0Text/F0Text.d.ts.map +1 -0
  54. package/lib/typescript/components/primitives/F0Text/F0Text.styles.d.ts +141 -0
  55. package/lib/typescript/components/primitives/F0Text/F0Text.styles.d.ts.map +1 -0
  56. package/lib/typescript/components/primitives/F0Text/F0Text.types.d.ts +86 -0
  57. package/lib/typescript/components/primitives/F0Text/F0Text.types.d.ts.map +1 -0
  58. package/lib/typescript/components/primitives/F0Text/index.d.ts +9 -0
  59. package/lib/typescript/components/primitives/F0Text/index.d.ts.map +1 -0
  60. package/lib/typescript/icons/app/index.d.ts +1 -1
  61. package/lib/typescript/icons/app/index.d.ts.map +1 -1
  62. package/lib/typescript/index.d.ts +1 -1
  63. package/lib/typescript/index.d.ts.map +1 -1
  64. package/lib/typescript/lib/utils.d.ts +9 -0
  65. package/lib/typescript/lib/utils.d.ts.map +1 -1
  66. package/lib/typescript/styles/tokens/colors.d.ts +2 -2
  67. package/package.json +2 -2
  68. package/src/components/Activity/ActivityItem/__snapshots__/index.spec.tsx.snap +3 -3
  69. package/src/components/Activity/ActivityItem/index.tsx +10 -10
  70. package/src/components/Avatars/BaseAvatar/index.tsx +1 -1
  71. package/src/components/Avatars/CompanyAvatar/__snapshots__/index.spec.tsx.snap +1 -1
  72. package/src/components/Avatars/DateAvatar/__snapshots__/index.spec.tsx.snap +3 -3
  73. package/src/components/Avatars/DateAvatar/index.tsx +3 -3
  74. package/src/components/Avatars/EmojiAvatar/__snapshots__/index.spec.tsx.snap +3 -3
  75. package/src/components/Avatars/EmojiAvatar/index.tsx +1 -1
  76. package/src/components/Avatars/FileAvatar/__snapshots__/index.spec.tsx.snap +26 -26
  77. package/src/components/Avatars/FileAvatar/index.tsx +2 -2
  78. package/src/components/Avatars/FileAvatar/utils.ts +13 -13
  79. package/src/components/Avatars/IconAvatar/__snapshots__/index.spec.tsx.snap +6 -6
  80. package/src/components/Avatars/IconAvatar/index.tsx +2 -2
  81. package/src/components/Avatars/ModuleAvatar/index.tsx +1 -1
  82. package/src/components/Avatars/PersonAvatar/__snapshots__/index.spec.tsx.snap +1 -1
  83. package/src/components/Avatars/TeamAvatar/__snapshots__/index.spec.tsx.snap +1 -1
  84. package/src/components/Badge/index.tsx +5 -5
  85. package/src/components/Button/__snapshots__/index.spec.tsx.snap +22 -22
  86. package/src/components/Button/index.tsx +22 -22
  87. package/src/components/Counter/__snapshots__/index.spec.tsx.snap +14 -14
  88. package/src/components/Counter/index.tsx +6 -6
  89. package/src/components/ExampleComponent.tsx +2 -2
  90. package/src/components/Icon/README.md +1 -1
  91. package/src/components/Navigation/PageHeader/__snapshots__/index.spec.tsx.snap +4 -4
  92. package/src/components/Navigation/PageHeader/index.tsx +1 -1
  93. package/src/components/OneChip/__snapshots__/index.spec.tsx.snap +11 -11
  94. package/src/components/OneChip/index.tsx +5 -5
  95. package/src/components/OnePreset/__snapshots__/index.spec.tsx.snap +8 -8
  96. package/src/components/OnePreset/index.tsx +3 -3
  97. package/src/components/Tags/AlertTab/__snapshots__/index.spec.tsx.snap +9 -9
  98. package/src/components/Tags/AlertTab/index.tsx +9 -9
  99. package/src/components/Tags/BaseTag/index.tsx +2 -2
  100. package/src/components/Tags/DotTag/__snapshots__/index.spec.tsx.snap +38 -38
  101. package/src/components/Tags/DotTag/index.tsx +1 -1
  102. package/src/components/Tags/RawTag/__snapshots__/index.spec.tsx.snap +6 -6
  103. package/src/components/Tags/RawTag/index.tsx +3 -3
  104. package/src/components/experimental/Lists/DataList/ItemContainer.tsx +2 -2
  105. package/src/components/experimental/Lists/DataList/actions/CopyAction.tsx +4 -4
  106. package/src/components/experimental/Lists/DataList/actions/GenericAction.tsx +3 -3
  107. package/src/components/experimental/Lists/DataList/index.tsx +1 -1
  108. package/src/components/experimental/Lists/DetailsItem/__snapshots__/index.spec.tsx.snap +26 -26
  109. package/src/components/experimental/Lists/DetailsItemsList/__snapshots__/index.spec.tsx.snap +26 -26
  110. package/src/components/experimental/Lists/DetailsItemsList/index.tsx +3 -3
  111. package/src/components/exports.ts +3 -0
  112. package/src/components/primitives/F0Text/F0Text.md +297 -0
  113. package/src/components/primitives/F0Text/F0Text.styles.ts +69 -0
  114. package/src/components/primitives/F0Text/F0Text.tsx +76 -0
  115. package/src/components/primitives/F0Text/F0Text.types.ts +133 -0
  116. package/src/components/primitives/F0Text/__tests__/__snapshots__/index.spec.tsx.snap +316 -0
  117. package/src/components/primitives/F0Text/__tests__/index.spec.tsx +227 -0
  118. package/src/components/primitives/F0Text/index.ts +22 -0
  119. package/src/icons/app/QuestionCircle.tsx +1 -1
  120. package/src/icons/app/index.ts +1 -1
  121. package/src/index.ts +1 -1
  122. package/src/lib/__tests__/utils.spec.ts +48 -0
  123. package/src/lib/utils.ts +19 -0
  124. package/src/styles/theme.css +308 -237
  125. package/src/styles/tokens/colors.ts +2 -2
  126. package/src/ui/avatar.tsx +1 -1
@@ -0,0 +1,297 @@
1
+ # F0Text
2
+
3
+ Primitive text component for React Native with semantic typography variants and optimized performance.
4
+
5
+ ## Features
6
+
7
+ - Semantic typography variants (heading and body styles)
8
+ - F0 semantic color system integration
9
+ - Inter font family support
10
+ - Type-safe TypeScript API
11
+ - Uniwind (Tailwind) styling
12
+ - Performance optimized with React.memo and useMemo
13
+ - Full accessibility support
14
+
15
+ ## Installation
16
+
17
+ ```tsx
18
+ import { F0Text } from "@factorialco/f0-react-native"
19
+ ```
20
+
21
+ ## Usage
22
+
23
+ ```tsx
24
+ <>
25
+ <F0Text variant="heading-lg">Welcome</F0Text>
26
+ <F0Text variant="body-sm-default" color="secondary">
27
+ Secondary text
28
+ </F0Text>
29
+ <F0Text variant="body-md-medium" align="center">
30
+ Centered text
31
+ </F0Text>
32
+ <F0Text variant="body-sm-default" numberOfLines={2}>
33
+ Truncated text...
34
+ </F0Text>
35
+ </>
36
+ ```
37
+
38
+ ## API Reference
39
+
40
+ ### Props
41
+
42
+ | Prop | Type | Default | Description |
43
+ | --------------- | ------------------- | ------------------- | ------------------------------------------------------- |
44
+ | `variant` | `TypographyVariant` | `'body-sm-default'` | Typography variant with weight included |
45
+ | `color` | `TextColor` | `'default'` | Text color from F0 semantic color system |
46
+ | `align` | `TextAlign` | `'left'` | Text alignment (left, center, right, justify) |
47
+ | `decoration` | `TextDecoration` | `'none'` | Text decoration (none, underline, line-through) |
48
+ | `transform` | `TextTransform` | `'none'` | Text transform (none, uppercase, lowercase, capitalize) |
49
+ | `numberOfLines` | `number` | `undefined` | Max lines before truncation with ellipsis |
50
+
51
+ All React Native `TextProps` are also supported (onPress, testID, etc.).
52
+
53
+ **Note**: `className` and `style` props are **not available**. Use semantic props for typography. For spacing/layout, wrap F0Text in a View. Both props are filtered at runtime to prevent override via spread.
54
+
55
+ ### Typography Variants
56
+
57
+ All variants use **Inter** font family with the weight included in the variant name.
58
+
59
+ #### Heading Variants
60
+
61
+ | Variant | Size | Line Height | Weight | Letter Spacing |
62
+ | ------------ | ---- | ----------- | -------------- | -------------- |
63
+ | `heading-lg` | 24px | 32px | Semibold (600) | -0.2px |
64
+ | `heading-md` | 20px | 28px | Semibold (600) | -0.2px |
65
+ | `heading-sm` | 16px | 24px | Semibold (600) | - |
66
+
67
+ #### Body Variants
68
+
69
+ | Variant | Size | Line Height | Weight | Letter Spacing |
70
+ | ------------------ | ---- | ----------- | -------------- | -------------- |
71
+ | `body-md-default` | 16px | 24px | Regular (400) | - |
72
+ | `body-md-medium` | 16px | 24px | Medium (500) | - |
73
+ | `body-md-semibold` | 16px | 24px | Semibold (600) | - |
74
+ | `body-sm-default` | 14px | 20px | Regular (400) | - |
75
+ | `body-sm-medium` | 14px | 20px | Medium (500) | - |
76
+ | `body-sm-semibold` | 14px | 20px | Semibold (600) | - |
77
+ | `body-xs-medium` | 12px | 16px | Medium (500) | - |
78
+
79
+ ### Color Variants
80
+
81
+ | Color | Usage |
82
+ | ------------------- | ---------------------------------- |
83
+ | `default` | Primary text |
84
+ | `secondary` | Secondary information |
85
+ | `tertiary` | Tertiary/subtle text |
86
+ | `inverse` | Text on dark backgrounds |
87
+ | `inverse-secondary` | Secondary text on dark backgrounds |
88
+ | `disabled` | Disabled state text |
89
+ | `accent` | Highlighted/accent text |
90
+ | `critical` | Error messages |
91
+ | `info` | Informational text |
92
+ | `warning` | Warning messages |
93
+ | `positive` | Success messages |
94
+ | `selected` | Selected state text |
95
+
96
+ ## Examples
97
+
98
+ ### Typography Variants
99
+
100
+ ```tsx
101
+ <>
102
+ {/* Headings */}
103
+ <F0Text variant="heading-lg">Large Heading</F0Text>
104
+ <F0Text variant="heading-md">Medium Heading</F0Text>
105
+ <F0Text variant="heading-sm">Small Heading</F0Text>
106
+
107
+ {/* Body with different weights */}
108
+ <F0Text variant="body-md-default">Regular body text</F0Text>
109
+ <F0Text variant="body-md-medium">Medium body text</F0Text>
110
+ <F0Text variant="body-md-semibold">Semibold body text</F0Text>
111
+
112
+ {/* Smaller sizes */}
113
+ <F0Text variant="body-sm-default">Small regular text</F0Text>
114
+ <F0Text variant="body-xs-medium">Extra small medium text</F0Text>
115
+ </>
116
+ ```
117
+
118
+ ### Colors
119
+
120
+ ```tsx
121
+ <>
122
+ <F0Text variant="body-sm-default" color="default">
123
+ Primary text
124
+ </F0Text>
125
+ <F0Text variant="body-sm-default" color="secondary">
126
+ Secondary information
127
+ </F0Text>
128
+ <F0Text variant="body-sm-default" color="critical">
129
+ Error message
130
+ </F0Text>
131
+ <F0Text variant="body-sm-default" color="positive">
132
+ Success message
133
+ </F0Text>
134
+ <F0Text variant="body-sm-default" color="accent">
135
+ Highlighted text
136
+ </F0Text>
137
+ </>
138
+ ```
139
+
140
+ ### Text Decorations & Transforms
141
+
142
+ ```tsx
143
+ <>
144
+ <F0Text variant="body-sm-default" decoration="underline">
145
+ Underlined text
146
+ </F0Text>
147
+ <F0Text variant="body-sm-default" decoration="line-through">
148
+ Strikethrough text
149
+ </F0Text>
150
+ <F0Text variant="body-sm-default" transform="uppercase">
151
+ uppercase text
152
+ </F0Text>
153
+ <F0Text variant="body-sm-default" transform="capitalize">
154
+ capitalize words
155
+ </F0Text>
156
+ </>
157
+ ```
158
+
159
+ ### Truncation
160
+
161
+ ```tsx
162
+ <>
163
+ <F0Text variant="body-sm-default" numberOfLines={1}>
164
+ This long text will be truncated after one line with an ellipsis...
165
+ </F0Text>
166
+
167
+ <F0Text variant="body-md-default" numberOfLines={3}>
168
+ This text can span up to three lines before being truncated with an ellipsis
169
+ at the end. Perfect for card descriptions or preview text.
170
+ </F0Text>
171
+ </>
172
+ ```
173
+
174
+ ### Spacing & Layout
175
+
176
+ F0Text doesn't accept `className` to prevent typography override. Use a View wrapper for spacing:
177
+
178
+ ```tsx
179
+ <>
180
+ {/* Spacing with View wrapper */}
181
+ <View className="mt-4 mb-2">
182
+ <F0Text variant="body-sm-default">Text with margin</F0Text>
183
+ </View>
184
+
185
+ {/* Layout with View wrapper */}
186
+ <View className="flex-1">
187
+ <F0Text variant="body-sm-default">Flexible text</F0Text>
188
+ </View>
189
+
190
+ {/* Icon + Text pattern */}
191
+ <View className="flex-row items-center gap-2">
192
+ <F0Icon icon={Check} size="sm" />
193
+ <F0Text variant="body-sm-default">Success message</F0Text>
194
+ </View>
195
+ </>
196
+ ```
197
+
198
+ ### Combined Props
199
+
200
+ ```tsx
201
+ <F0Text
202
+ variant="heading-md"
203
+ color="accent"
204
+ align="center"
205
+ decoration="underline"
206
+ transform="uppercase"
207
+ >
208
+ Featured Title
209
+ </F0Text>
210
+ ```
211
+
212
+ ### Nested Text
213
+
214
+ ```tsx
215
+ <F0Text variant="body-sm-default">
216
+ This is regular text with{" "}
217
+ <F0Text variant="body-sm-semibold" color="accent">
218
+ bold accent nested text
219
+ </F0Text>{" "}
220
+ inside.
221
+ </F0Text>
222
+ ```
223
+
224
+ ### Real-world Card Example
225
+
226
+ ```tsx
227
+ <View className="rounded-lg bg-f0-background-secondary p-4">
228
+ <View className="mb-2">
229
+ <F0Text variant="heading-sm">Card Title</F0Text>
230
+ </View>
231
+ <F0Text variant="body-sm-default" color="secondary" numberOfLines={2}>
232
+ This is a description that will be truncated after two lines if it's too
233
+ long to fit in the available space.
234
+ </F0Text>
235
+ <View className="mt-2">
236
+ <F0Text variant="body-xs-medium" color="tertiary">
237
+ Last updated 2 hours ago
238
+ </F0Text>
239
+ </View>
240
+ </View>
241
+ ```
242
+
243
+ ## Architecture
244
+
245
+ ```
246
+ F0Text/
247
+ ├── F0Text.tsx # Main component
248
+ ├── F0Text.md # Documentation
249
+ ├── F0Text.types.ts # TypeScript types
250
+ ├── F0Text.styles.ts # Tailwind variants config
251
+ ├── index.ts # Public exports
252
+ └── __tests__/
253
+ ├── index.spec.tsx
254
+ └── __snapshots__/
255
+ ```
256
+
257
+ ### Font Family
258
+
259
+ F0Text uses **Inter** font family through Tailwind/Uniwind font weight classes:
260
+
261
+ | Tailwind Class | React Native Font Family | Font Weight |
262
+ | --------------- | ------------------------ | ----------- |
263
+ | `font-normal` | Inter-Regular | 400 |
264
+ | `font-medium` | Inter-Medium | 500 |
265
+ | `font-semibold` | Inter-SemiBold | 600 |
266
+ | `font-bold` | Inter-Bold | 700 |
267
+
268
+ ## Accessibility
269
+
270
+ - Fully supports React Native `Text` accessibility props
271
+ - Supports `accessibilityRole`, `accessibilityLabel`, `accessibilityHint`, `accessibilityState`, and `accessible`
272
+ - Proper ellipsis and truncation with `numberOfLines`
273
+ - F0 color system helps ensure sufficient contrast; verify with platform accessibility tools
274
+
275
+ ## Performance
276
+
277
+ - **React.memo**: Prevents re-renders when props unchanged
278
+ - **useMemo**: Memoizes className computation
279
+
280
+ ### Best Practices
281
+
282
+ ```tsx
283
+ // ✅ Good: Use appropriate variant
284
+ <F0Text variant="body-md-semibold">Bold text</F0Text>
285
+
286
+ // ❌ Bad: Don't try to override with className (not supported)
287
+ // <F0Text className="font-bold">Text</F0Text>
288
+ ```
289
+
290
+ ```tsx
291
+ // ✅ Good: Memoized handler
292
+ const handlePress = useCallback(() => {}, [])
293
+ ;<F0Text onPress={handlePress}>Click</F0Text>
294
+
295
+ // ❌ Bad: Inline function
296
+ ;<F0Text onPress={() => {}}>Click</F0Text>
297
+ ```
@@ -0,0 +1,69 @@
1
+ import { tv, type VariantProps } from "tailwind-variants"
2
+
3
+ /**
4
+ * Text component variants using tailwind-variants
5
+ * Font weights (font-normal, font-medium, font-semibold) map to
6
+ * Inter font families (Inter-Regular, Inter-Medium, Inter-SemiBold)
7
+ */
8
+ export const textVariants = tv({
9
+ base: "",
10
+ variants: {
11
+ variant: {
12
+ // Heading variants
13
+ "heading-lg":
14
+ "text-[24px] leading-[32px] tracking-[-0.2px] font-semibold",
15
+ "heading-md":
16
+ "text-[20px] leading-[28px] tracking-[-0.2px] font-semibold",
17
+ "heading-sm": "text-[16px] leading-[24px] font-semibold",
18
+
19
+ // Body variants with weight included in variant name
20
+ "body-md-default": "text-[16px] leading-[24px] font-normal",
21
+ "body-md-medium": "text-[16px] leading-[24px] font-medium",
22
+ "body-md-semibold": "text-[16px] leading-[24px] font-semibold",
23
+ "body-sm-default": "text-[14px] leading-[20px] font-normal",
24
+ "body-sm-medium": "text-[14px] leading-[20px] font-medium",
25
+ "body-sm-semibold": "text-[14px] leading-[20px] font-semibold",
26
+ "body-xs-medium": "text-[12px] leading-[16px] font-medium",
27
+ },
28
+ color: {
29
+ default: "text-f0-foreground",
30
+ secondary: "text-f0-foreground-secondary",
31
+ tertiary: "text-f0-foreground-tertiary",
32
+ inverse: "text-f0-foreground-inverse",
33
+ "inverse-secondary": "text-f0-foreground-inverse-secondary",
34
+ disabled: "text-f0-foreground-disabled",
35
+ accent: "text-f0-foreground-accent",
36
+ critical: "text-f0-foreground-critical",
37
+ info: "text-f0-foreground-info",
38
+ warning: "text-f0-foreground-warning",
39
+ positive: "text-f0-foreground-positive",
40
+ selected: "text-f0-foreground-selected",
41
+ },
42
+ align: {
43
+ left: "text-left",
44
+ center: "text-center",
45
+ right: "text-right",
46
+ justify: "text-justify",
47
+ },
48
+ decoration: {
49
+ none: "",
50
+ underline: "underline",
51
+ "line-through": "line-through",
52
+ },
53
+ transform: {
54
+ none: "",
55
+ uppercase: "uppercase",
56
+ lowercase: "lowercase",
57
+ capitalize: "capitalize",
58
+ },
59
+ },
60
+ defaultVariants: {
61
+ variant: "body-sm-default",
62
+ color: "default",
63
+ align: "left",
64
+ decoration: "none",
65
+ transform: "none",
66
+ },
67
+ })
68
+
69
+ export type TextVariants = VariantProps<typeof textVariants>
@@ -0,0 +1,76 @@
1
+ import React from "react"
2
+ import { Text as RNText } from "react-native"
3
+
4
+ import { omitProps } from "../../../lib/utils"
5
+
6
+ import { textVariants } from "./F0Text.styles"
7
+ import { F0_TEXT_BANNED_PROPS, type F0TextProps } from "./F0Text.types"
8
+
9
+ /**
10
+ * F0Text - Primitive Text component with semantic typography variants
11
+ *
12
+ * @example
13
+ * <F0Text variant="heading-lg">Large Heading</F0Text>
14
+ * <F0Text variant="body-sm-default" color="secondary">Secondary text</F0Text>
15
+ * <F0Text variant="body-md-medium" numberOfLines={2}>Truncated text...</F0Text>
16
+ */
17
+ const F0TextComponent = React.forwardRef<RNText, F0TextProps>(
18
+ (
19
+ {
20
+ variant = "body-sm-default",
21
+ color = "default",
22
+ align = "left",
23
+ decoration = "none",
24
+ transform = "none",
25
+ children,
26
+ numberOfLines,
27
+ ...rest
28
+ },
29
+ ref
30
+ ) => {
31
+ const textClassName = React.useMemo(
32
+ () =>
33
+ textVariants({
34
+ variant,
35
+ color,
36
+ align,
37
+ decoration,
38
+ transform,
39
+ }),
40
+ [variant, color, align, decoration, transform]
41
+ )
42
+
43
+ return (
44
+ <RNText
45
+ ref={ref}
46
+ {...omitProps(rest, F0_TEXT_BANNED_PROPS)}
47
+ className={textClassName}
48
+ numberOfLines={numberOfLines}
49
+ ellipsizeMode={numberOfLines ? "tail" : undefined}
50
+ >
51
+ {children}
52
+ </RNText>
53
+ )
54
+ }
55
+ )
56
+
57
+ F0TextComponent.displayName = "F0Text"
58
+
59
+ export const F0Text = React.memo(F0TextComponent)
60
+
61
+ // Export types
62
+ export type { F0TextProps }
63
+ export {
64
+ TYPOGRAPHY_VARIANTS,
65
+ TEXT_COLORS,
66
+ TEXT_ALIGN,
67
+ TEXT_DECORATIONS,
68
+ TEXT_TRANSFORMS,
69
+ } from "./F0Text.types"
70
+ export type {
71
+ TypographyVariant,
72
+ TextColor,
73
+ TextAlign,
74
+ TextDecoration,
75
+ TextTransform,
76
+ } from "./F0Text.types"
@@ -0,0 +1,133 @@
1
+ import type { TextProps as RNTextProps } from "react-native"
2
+
3
+ /**
4
+ * Props that must not be passed through to the underlying RN Text
5
+ * (`style` and `className` are handled by F0 instead).
6
+ * Used with omitProps for runtime safety.
7
+ */
8
+ export const F0_TEXT_BANNED_PROPS = ["style", "className"] as const
9
+
10
+ /**
11
+ * Typography variant types based on semantic design tokens
12
+ */
13
+ export const TYPOGRAPHY_VARIANTS = [
14
+ "heading-lg",
15
+ "heading-md",
16
+ "heading-sm",
17
+ "body-md-default",
18
+ "body-md-medium",
19
+ "body-md-semibold",
20
+ "body-sm-default",
21
+ "body-sm-medium",
22
+ "body-sm-semibold",
23
+ "body-xs-medium",
24
+ ] as const
25
+
26
+ export type TypographyVariant = (typeof TYPOGRAPHY_VARIANTS)[number]
27
+
28
+ /**
29
+ * Text color variants aligned with F0 semantic color system
30
+ */
31
+ export const TEXT_COLORS = [
32
+ "default",
33
+ "secondary",
34
+ "tertiary",
35
+ "inverse",
36
+ "inverse-secondary",
37
+ "disabled",
38
+ "accent",
39
+ "critical",
40
+ "info",
41
+ "warning",
42
+ "positive",
43
+ "selected",
44
+ ] as const
45
+
46
+ export type TextColor = (typeof TEXT_COLORS)[number]
47
+
48
+ /**
49
+ * Text alignment options
50
+ */
51
+ export const TEXT_ALIGN = ["left", "center", "right", "justify"] as const
52
+
53
+ export type TextAlign = (typeof TEXT_ALIGN)[number]
54
+
55
+ /**
56
+ * Text decoration options
57
+ */
58
+ export const TEXT_DECORATIONS = ["none", "underline", "line-through"] as const
59
+
60
+ export type TextDecoration = (typeof TEXT_DECORATIONS)[number]
61
+
62
+ /**
63
+ * Text transform options
64
+ */
65
+ export const TEXT_TRANSFORMS = [
66
+ "none",
67
+ "uppercase",
68
+ "lowercase",
69
+ "capitalize",
70
+ ] as const
71
+
72
+ export type TextTransform = (typeof TEXT_TRANSFORMS)[number]
73
+
74
+ /**
75
+ * Internal props for the F0Text component.
76
+ * @private
77
+ */
78
+ interface F0TextPropsInternal extends Omit<RNTextProps, "style"> {
79
+ /**
80
+ * Semantic typography variant
81
+ * @default "body-sm-default"
82
+ */
83
+ variant?: TypographyVariant
84
+
85
+ /**
86
+ * Text color from F0 semantic color system
87
+ * @default "default"
88
+ */
89
+ color?: TextColor
90
+
91
+ /**
92
+ * Text alignment
93
+ * @default "left"
94
+ */
95
+ align?: TextAlign
96
+
97
+ /**
98
+ * Text decoration
99
+ * @default "none"
100
+ */
101
+ decoration?: TextDecoration
102
+
103
+ /**
104
+ * Text transform
105
+ * @default "none"
106
+ */
107
+ transform?: TextTransform
108
+
109
+ /**
110
+ * Maximum number of lines before truncating with ellipsis
111
+ */
112
+ numberOfLines?: number
113
+
114
+ /**
115
+ * Children content
116
+ */
117
+ children?: React.ReactNode
118
+
119
+ /**
120
+ * Excluded from public API via Omit<F0TextPropsInternal, "className">.
121
+ * @private
122
+ */
123
+ className?: string
124
+ }
125
+
126
+ /**
127
+ * Public props for the F0Text component
128
+ *
129
+ * Note: `className` and `style` props are NOT available.
130
+ * Use semantic props (variant, color, align, etc.) for typography.
131
+ * For spacing/layout, wrap F0Text in a View with className.
132
+ */
133
+ export type F0TextProps = Omit<F0TextPropsInternal, "className">