@factorialco/f0-react-native 0.28.1 → 0.30.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.
- package/lib/module/components/Avatars/IconAvatar/index.js +1 -1
- package/lib/module/components/Avatars/IconAvatar/index.js.map +1 -1
- package/lib/module/components/Avatars/ModuleAvatar/index.js +1 -1
- package/lib/module/components/Avatars/ModuleAvatar/index.js.map +1 -1
- package/lib/module/components/Badge/index.js +1 -1
- package/lib/module/components/Badge/index.js.map +1 -1
- package/lib/module/components/Button/index.js +1 -1
- package/lib/module/components/Button/index.js.map +1 -1
- package/lib/module/components/Button/index.spec.js +1 -1
- package/lib/module/components/Button/index.spec.js.map +1 -1
- package/lib/module/components/Icon/index.js +1 -1
- package/lib/module/components/Icon/index.js.map +1 -1
- package/lib/module/components/OneChip/index.js +1 -1
- package/lib/module/components/OneChip/index.js.map +1 -1
- package/lib/module/components/Tags/AlertTab/index.js +1 -1
- package/lib/module/components/Tags/AlertTab/index.js.map +1 -1
- package/lib/module/components/Tags/RawTag/index.js +1 -1
- package/lib/module/components/Tags/RawTag/index.js.map +1 -1
- package/lib/module/components/experimental/Lists/DataList/ItemContainer.js +1 -1
- package/lib/module/components/experimental/Lists/DataList/ItemContainer.js.map +1 -1
- package/lib/module/components/experimental/Lists/DataList/actions/CopyAction.js +1 -1
- package/lib/module/components/experimental/Lists/DataList/actions/CopyAction.js.map +1 -1
- package/lib/module/components/experimental/Lists/DataList/actions/GenericAction.js +1 -1
- package/lib/module/components/experimental/Lists/DataList/actions/GenericAction.js.map +1 -1
- package/lib/module/components/exports.js +1 -1
- package/lib/module/components/exports.js.map +1 -1
- package/lib/module/components/primitives/F0Icon/F0Icon.js +2 -0
- package/lib/module/components/primitives/F0Icon/F0Icon.js.map +1 -0
- package/lib/module/components/primitives/F0Icon/F0Icon.md +187 -0
- package/lib/module/components/primitives/F0Icon/F0Icon.styles.js +2 -0
- package/lib/module/components/primitives/F0Icon/F0Icon.styles.js.map +1 -0
- package/lib/module/components/primitives/F0Icon/F0Icon.types.js +2 -0
- package/lib/module/components/primitives/F0Icon/F0Icon.types.js.map +1 -0
- package/lib/module/components/primitives/F0Icon/index.js +2 -0
- package/lib/module/components/primitives/F0Icon/index.js.map +1 -0
- package/lib/module/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.js +1 -1
- package/lib/module/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.js.map +1 -1
- package/lib/module/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.md +45 -8
- package/lib/module/components/primitives/F0Text/F0Text/F0Text.js +1 -1
- package/lib/module/components/primitives/F0Text/F0Text/F0Text.js.map +1 -1
- package/lib/module/components/primitives/F0Text/F0Text/F0Text.md +42 -31
- package/lib/module/components/primitives/F0Text/F0Text/F0Text.styles.js +1 -1
- package/lib/module/components/primitives/F0Text/F0Text/F0Text.styles.js.map +1 -1
- package/lib/module/components/primitives/F0Text/F0Text/F0Text.types.js +1 -1
- package/lib/module/components/primitives/F0Text/F0Text/F0Text.types.js.map +1 -1
- package/lib/module/icons/index.js +1 -1
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/lib/utils.js.map +1 -1
- package/lib/typescript/components/Activity/ActivityItem/index.d.ts +1 -1
- package/lib/typescript/components/Activity/ActivityItem/index.d.ts.map +1 -1
- package/lib/typescript/components/Avatars/IconAvatar/index.d.ts +1 -1
- package/lib/typescript/components/Avatars/IconAvatar/index.d.ts.map +1 -1
- package/lib/typescript/components/Avatars/ModuleAvatar/index.d.ts +1 -1
- package/lib/typescript/components/Avatars/ModuleAvatar/index.d.ts.map +1 -1
- package/lib/typescript/components/Badge/index.d.ts +1 -1
- package/lib/typescript/components/Badge/index.d.ts.map +1 -1
- package/lib/typescript/components/Button/index.d.ts +1 -1
- package/lib/typescript/components/Button/index.d.ts.map +1 -1
- package/lib/typescript/components/Icon/index.d.ts +7 -14
- package/lib/typescript/components/Icon/index.d.ts.map +1 -1
- package/lib/typescript/components/OneChip/index.d.ts +1 -1
- package/lib/typescript/components/OneChip/index.d.ts.map +1 -1
- package/lib/typescript/components/Tags/RawTag/index.d.ts +1 -1
- package/lib/typescript/components/Tags/RawTag/index.d.ts.map +1 -1
- package/lib/typescript/components/experimental/Lists/DataList/ItemContainer.d.ts +1 -1
- package/lib/typescript/components/experimental/Lists/DataList/ItemContainer.d.ts.map +1 -1
- package/lib/typescript/components/experimental/Lists/DataList/actions/CopyAction.d.ts.map +1 -1
- package/lib/typescript/components/experimental/Lists/DataList/index.d.ts +1 -1
- package/lib/typescript/components/experimental/Lists/DataList/index.d.ts.map +1 -1
- package/lib/typescript/components/exports.d.ts +2 -1
- package/lib/typescript/components/exports.d.ts.map +1 -1
- package/lib/typescript/components/primitives/F0Icon/F0Icon.d.ts +25 -0
- package/lib/typescript/components/primitives/F0Icon/F0Icon.d.ts.map +1 -0
- package/lib/typescript/components/primitives/F0Icon/F0Icon.styles.d.ts +90 -0
- package/lib/typescript/components/primitives/F0Icon/F0Icon.styles.d.ts.map +1 -0
- package/lib/typescript/components/primitives/F0Icon/F0Icon.types.d.ts +47 -0
- package/lib/typescript/components/primitives/F0Icon/F0Icon.types.d.ts.map +1 -0
- package/lib/typescript/components/primitives/F0Icon/index.d.ts +10 -0
- package/lib/typescript/components/primitives/F0Icon/index.d.ts.map +1 -0
- package/lib/typescript/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.d.ts.map +1 -1
- package/lib/typescript/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.types.d.ts +14 -0
- package/lib/typescript/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.types.d.ts.map +1 -1
- package/lib/typescript/components/primitives/F0Text/F0Text/F0Text.d.ts.map +1 -1
- package/lib/typescript/components/primitives/F0Text/F0Text/F0Text.styles.d.ts +2 -2
- package/lib/typescript/components/primitives/F0Text/F0Text/F0Text.styles.d.ts.map +1 -1
- package/lib/typescript/components/primitives/F0Text/F0Text/F0Text.types.d.ts +22 -18
- package/lib/typescript/components/primitives/F0Text/F0Text/F0Text.types.d.ts.map +1 -1
- package/lib/typescript/icons/index.d.ts +0 -1
- package/lib/typescript/icons/index.d.ts.map +1 -1
- package/lib/typescript/lib/utils.d.ts +1 -2
- package/lib/typescript/lib/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Activity/ActivityItem/index.spec.tsx +1 -1
- package/src/components/Activity/ActivityItem/index.tsx +1 -1
- package/src/components/Avatars/IconAvatar/index.tsx +6 -2
- package/src/components/Avatars/ModuleAvatar/index.tsx +1 -1
- package/src/components/Badge/index.tsx +2 -2
- package/src/components/Button/index.spec.tsx +3 -4
- package/src/components/Button/index.tsx +19 -13
- package/src/components/Icon/__tests__/Icon.spec.tsx +0 -4
- package/src/components/Icon/index.tsx +7 -26
- package/src/components/OneChip/index.tsx +3 -3
- package/src/components/Tags/AlertTab/index.tsx +2 -2
- package/src/components/Tags/RawTag/index.tsx +2 -2
- package/src/components/experimental/Lists/DataList/ItemContainer.tsx +2 -2
- package/src/components/experimental/Lists/DataList/actions/CopyAction.tsx +7 -10
- package/src/components/experimental/Lists/DataList/actions/GenericAction.tsx +2 -2
- package/src/components/experimental/Lists/DataList/index.tsx +1 -1
- package/src/components/experimental/Lists/DetailsItem/__snapshots__/index.spec.tsx.snap +4 -4
- package/src/components/experimental/Lists/DetailsItemsList/__snapshots__/index.spec.tsx.snap +1 -1
- package/src/components/exports.ts +2 -1
- package/src/components/primitives/F0Icon/F0Icon.md +187 -0
- package/src/components/primitives/F0Icon/F0Icon.styles.ts +43 -0
- package/src/components/primitives/F0Icon/F0Icon.tsx +73 -0
- package/src/components/primitives/F0Icon/F0Icon.types.ts +77 -0
- package/src/components/primitives/F0Icon/__tests__/F0Icon.spec.tsx +131 -0
- package/src/components/primitives/F0Icon/__tests__/F0Icon.tokens.spec.ts +39 -0
- package/src/components/primitives/F0Icon/index.ts +10 -0
- package/src/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.md +45 -8
- package/src/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.tsx +20 -8
- package/src/components/primitives/F0Text/AnimatedF0Text/AnimatedF0Text.types.ts +15 -0
- package/src/components/primitives/F0Text/AnimatedF0Text/__tests__/AnimatedF0Text.spec.tsx +220 -0
- package/src/components/primitives/F0Text/AnimatedF0Text/__tests__/__snapshots__/AnimatedF0Text.spec.tsx.snap +16 -16
- package/src/components/primitives/F0Text/F0Text/F0Text.md +42 -31
- package/src/components/primitives/F0Text/F0Text/F0Text.styles.ts +1 -1
- package/src/components/primitives/F0Text/F0Text/F0Text.tsx +17 -10
- package/src/components/primitives/F0Text/F0Text/F0Text.types.ts +22 -18
- package/src/components/primitives/F0Text/F0Text/__tests__/F0Text.spec.tsx +340 -16
- package/src/components/primitives/F0Text/F0Text/__tests__/__snapshots__/F0Text.spec.tsx.snap +36 -36
- package/src/icons/index.ts +0 -1
- package/src/lib/utils.ts +1 -2
- package/lib/module/components/Icon/README.md +0 -63
- package/src/components/Icon/README.md +0 -63
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// @ts-ignore - Node built-ins are available in Jest runtime
|
|
2
|
+
import fs from "fs"
|
|
3
|
+
// @ts-ignore - Node built-ins are available in Jest runtime
|
|
4
|
+
import path from "path"
|
|
5
|
+
|
|
6
|
+
import { ICON_COLORS } from "../F0Icon.types"
|
|
7
|
+
|
|
8
|
+
describe("F0Icon token sync", () => {
|
|
9
|
+
it("ICON_COLORS matches f0-icon-* tokens in theme.css", () => {
|
|
10
|
+
const css = fs.readFileSync(
|
|
11
|
+
// @ts-ignore - __dirname is available in Jest runtime
|
|
12
|
+
path.resolve(__dirname, "../../../../styles/theme.css"),
|
|
13
|
+
"utf-8"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// Extract all --color-f0-icon-<name> tokens, excluding sub-tokens
|
|
17
|
+
// that are already captured (e.g. --color-f0-icon-mood-positive
|
|
18
|
+
// but not --color-f0-icon which maps to "default")
|
|
19
|
+
const tokenRegex = /--color-f0-icon-([a-z0-9][a-z0-9-]*):/g
|
|
20
|
+
const tokensFromCSS = new Set<string>()
|
|
21
|
+
let match: RegExpExecArray | null
|
|
22
|
+
while ((match = tokenRegex.exec(css)) !== null) {
|
|
23
|
+
tokensFromCSS.add(match[1])
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// "default" in ICON_COLORS maps to the base --color-f0-icon token
|
|
27
|
+
const colorsFromType = new Set<string>(
|
|
28
|
+
ICON_COLORS.filter((c) => c !== "default")
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
const missingInType = [...tokensFromCSS].filter(
|
|
32
|
+
(t) => !colorsFromType.has(t)
|
|
33
|
+
)
|
|
34
|
+
const extraInType = [...colorsFromType].filter((t) => !tokensFromCSS.has(t))
|
|
35
|
+
|
|
36
|
+
expect(missingInType).toEqual([])
|
|
37
|
+
expect(extraInType).toEqual([])
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F0Icon - Icon primitive component
|
|
3
|
+
*
|
|
4
|
+
* @see F0Icon.md for documentation
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { default as F0Icon } from "./F0Icon"
|
|
8
|
+
export type { F0IconProps, IconType, IconColor } from "./F0Icon.types"
|
|
9
|
+
export { ICON_COLORS } from "./F0Icon.types"
|
|
10
|
+
export { applyIconInterop } from "./F0Icon"
|
|
@@ -5,6 +5,7 @@ Animated text primitive for React Native with semantic typography variants and R
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- All F0Text semantic typography variants and colors
|
|
8
|
+
- `className` for layout/positioning (margin, padding, flex, etc.) — typography always wins via twMerge
|
|
8
9
|
- Reanimated `entering`/`exiting` layout animations
|
|
9
10
|
- Animated `style` prop for custom animations via `useAnimatedStyle`
|
|
10
11
|
- Layout transition animations
|
|
@@ -90,6 +91,41 @@ import { LinearTransition } from "react-native-reanimated"
|
|
|
90
91
|
</>
|
|
91
92
|
```
|
|
92
93
|
|
|
94
|
+
### className for Layout/Positioning
|
|
95
|
+
|
|
96
|
+
`className` accepts Tailwind classes for layout and positioning. Typography classes
|
|
97
|
+
in `className` are ignored — semantic props always take precedence via twMerge.
|
|
98
|
+
|
|
99
|
+
<!-- prettier-ignore -->
|
|
100
|
+
```tsx
|
|
101
|
+
import { AnimatedF0Text } from "@factorialco/f0-react-native"
|
|
102
|
+
import { FadeIn } from "react-native-reanimated"
|
|
103
|
+
import { useAnimatedStyle, useSharedValue } from "react-native-reanimated"
|
|
104
|
+
|
|
105
|
+
const opacity = useSharedValue(1)
|
|
106
|
+
const animatedStyle = useAnimatedStyle(() => ({ opacity: opacity.value }))
|
|
107
|
+
|
|
108
|
+
<>
|
|
109
|
+
{/* className for static layout, style for animated values */}
|
|
110
|
+
<AnimatedF0Text
|
|
111
|
+
variant="heading-sm"
|
|
112
|
+
className="mt-4 flex-1"
|
|
113
|
+
style={animatedStyle}
|
|
114
|
+
>
|
|
115
|
+
Positioned animated heading
|
|
116
|
+
</AnimatedF0Text>
|
|
117
|
+
|
|
118
|
+
{/* className for layout + entering animation */}
|
|
119
|
+
<AnimatedF0Text
|
|
120
|
+
variant="body-sm-default"
|
|
121
|
+
className="mb-2 self-center"
|
|
122
|
+
entering={FadeIn.duration(300)}
|
|
123
|
+
>
|
|
124
|
+
Centered fade-in text
|
|
125
|
+
</AnimatedF0Text>
|
|
126
|
+
</>
|
|
127
|
+
```
|
|
128
|
+
|
|
93
129
|
## API Reference
|
|
94
130
|
|
|
95
131
|
### Props
|
|
@@ -98,14 +134,15 @@ AnimatedF0Text accepts all F0Text semantic props plus Reanimated animation props
|
|
|
98
134
|
|
|
99
135
|
#### Typography Props (shared with F0Text)
|
|
100
136
|
|
|
101
|
-
| Prop | Type | Default | Description
|
|
102
|
-
| --------------- | ------------------- | ------------------- |
|
|
103
|
-
| `variant` | `TypographyVariant` | `'body-sm-default'` | Typography variant
|
|
104
|
-
| `color` | `TextColor` | `'default'` | Text color from F0 semantic color system
|
|
105
|
-
| `align` | `TextAlign` | `'left'` | Text alignment
|
|
106
|
-
| `decoration` | `TextDecoration` | `'none'` | Text decoration
|
|
107
|
-
| `transform` | `TextTransform` | `'none'` | Text transform
|
|
108
|
-
| `numberOfLines` | `number` | `undefined` | Max lines before truncation
|
|
137
|
+
| Prop | Type | Default | Description |
|
|
138
|
+
| --------------- | ------------------- | ------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
139
|
+
| `variant` | `TypographyVariant` | `'body-sm-default'` | Typography variant |
|
|
140
|
+
| `color` | `TextColor` | `'default'` | Text color from F0 semantic color system |
|
|
141
|
+
| `align` | `TextAlign` | `'left'` | Text alignment |
|
|
142
|
+
| `decoration` | `TextDecoration` | `'none'` | Text decoration |
|
|
143
|
+
| `transform` | `TextTransform` | `'none'` | Text transform |
|
|
144
|
+
| `numberOfLines` | `number` | `undefined` | Max lines before truncation |
|
|
145
|
+
| `className` | `string` | `undefined` | Tailwind classes for layout/positioning. Typography classes are overridden by semantic props via twMerge. |
|
|
109
146
|
|
|
110
147
|
#### Animation Props
|
|
111
148
|
|
|
@@ -2,6 +2,7 @@ import React from "react"
|
|
|
2
2
|
import { Text as RNText } from "react-native"
|
|
3
3
|
import Animated from "react-native-reanimated"
|
|
4
4
|
|
|
5
|
+
import { cn } from "../../../../lib/utils"
|
|
5
6
|
import { textVariants } from "../F0Text/F0Text.styles"
|
|
6
7
|
|
|
7
8
|
import type { AnimatedF0TextProps } from "./AnimatedF0Text.types"
|
|
@@ -15,10 +16,17 @@ const AnimatedText = Animated.createAnimatedComponent(RNText)
|
|
|
15
16
|
* typography system as F0Text. Supports `entering`, `exiting`, `layout`
|
|
16
17
|
* animations and animated `style` props.
|
|
17
18
|
*
|
|
19
|
+
* Typography is controlled by semantic props and always takes precedence.
|
|
20
|
+
* `className` is accepted for layout/positioning (margin, padding, flex, etc.).
|
|
21
|
+
* `style` is accepted for Reanimated animated values.
|
|
22
|
+
*
|
|
18
23
|
* @example
|
|
19
24
|
* <AnimatedF0Text variant="heading-xl" entering={FadeIn.duration(300)}>
|
|
20
25
|
* Welcome back
|
|
21
26
|
* </AnimatedF0Text>
|
|
27
|
+
* <AnimatedF0Text variant="body-sm-default" className="mt-4 flex-1" style={animatedStyle}>
|
|
28
|
+
* Positioned animated text
|
|
29
|
+
* </AnimatedF0Text>
|
|
22
30
|
*/
|
|
23
31
|
const AnimatedF0TextComponent = React.forwardRef<
|
|
24
32
|
React.ComponentRef<typeof AnimatedText>,
|
|
@@ -31,6 +39,7 @@ const AnimatedF0TextComponent = React.forwardRef<
|
|
|
31
39
|
align = "left",
|
|
32
40
|
decoration = "none",
|
|
33
41
|
transform = "none",
|
|
42
|
+
className,
|
|
34
43
|
children,
|
|
35
44
|
numberOfLines,
|
|
36
45
|
style,
|
|
@@ -40,14 +49,17 @@ const AnimatedF0TextComponent = React.forwardRef<
|
|
|
40
49
|
) => {
|
|
41
50
|
const textClassName = React.useMemo(
|
|
42
51
|
() =>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
cn(
|
|
53
|
+
className,
|
|
54
|
+
textVariants({
|
|
55
|
+
variant,
|
|
56
|
+
color,
|
|
57
|
+
align,
|
|
58
|
+
decoration,
|
|
59
|
+
transform,
|
|
60
|
+
})
|
|
61
|
+
),
|
|
62
|
+
[variant, color, align, decoration, transform, className]
|
|
51
63
|
)
|
|
52
64
|
|
|
53
65
|
return (
|
|
@@ -58,4 +58,19 @@ export interface AnimatedF0TextProps extends Omit<
|
|
|
58
58
|
* Children content
|
|
59
59
|
*/
|
|
60
60
|
children?: React.ReactNode
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Tailwind classes for layout and positioning.
|
|
64
|
+
*
|
|
65
|
+
* Allowed: margin, padding, flex, position, width, height, opacity, z-index, etc.
|
|
66
|
+
* Ignored: font-size, font-weight, line-height, letter-spacing, color, text-align,
|
|
67
|
+
* text-decoration, text-transform — these are controlled by semantic props and
|
|
68
|
+
* always take precedence via twMerge.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* className="mt-4 flex-1"
|
|
72
|
+
* className="mb-2 self-center"
|
|
73
|
+
* className="absolute top-0 left-0"
|
|
74
|
+
*/
|
|
75
|
+
className?: string
|
|
61
76
|
}
|
|
@@ -128,4 +128,224 @@ describe("AnimatedF0Text", () => {
|
|
|
128
128
|
expect(element.props.testID).toBe("test-animated-text")
|
|
129
129
|
})
|
|
130
130
|
})
|
|
131
|
+
|
|
132
|
+
describe("className — layout classes pass through", () => {
|
|
133
|
+
it("applies margin classes", () => {
|
|
134
|
+
const { getByText } = render(
|
|
135
|
+
<AnimatedF0Text className="mx-3 mt-4 mb-2">Margin text</AnimatedF0Text>
|
|
136
|
+
)
|
|
137
|
+
const element = getByText("Margin text")
|
|
138
|
+
expect(element.props.className).toContain("mt-4")
|
|
139
|
+
expect(element.props.className).toContain("mb-2")
|
|
140
|
+
expect(element.props.className).toContain("mx-3")
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
it("applies padding classes", () => {
|
|
144
|
+
const { getByText } = render(
|
|
145
|
+
<AnimatedF0Text className="p-4 px-2 py-1">Padded text</AnimatedF0Text>
|
|
146
|
+
)
|
|
147
|
+
const element = getByText("Padded text")
|
|
148
|
+
expect(element.props.className).toContain("p-4")
|
|
149
|
+
expect(element.props.className).toContain("px-2")
|
|
150
|
+
expect(element.props.className).toContain("py-1")
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it("applies flex classes", () => {
|
|
154
|
+
const { getByText } = render(
|
|
155
|
+
<AnimatedF0Text className="flex-1 flex-shrink-0">
|
|
156
|
+
Flex text
|
|
157
|
+
</AnimatedF0Text>
|
|
158
|
+
)
|
|
159
|
+
const element = getByText("Flex text")
|
|
160
|
+
expect(element.props.className).toContain("flex-1")
|
|
161
|
+
expect(element.props.className).toContain("flex-shrink-0")
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it("applies position classes", () => {
|
|
165
|
+
const { getByText } = render(
|
|
166
|
+
<AnimatedF0Text className="absolute top-0 left-0">
|
|
167
|
+
Positioned text
|
|
168
|
+
</AnimatedF0Text>
|
|
169
|
+
)
|
|
170
|
+
const element = getByText("Positioned text")
|
|
171
|
+
expect(element.props.className).toContain("absolute")
|
|
172
|
+
expect(element.props.className).toContain("top-0")
|
|
173
|
+
expect(element.props.className).toContain("left-0")
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it("applies opacity classes", () => {
|
|
177
|
+
const { getByText } = render(
|
|
178
|
+
<AnimatedF0Text className="opacity-50">Faded text</AnimatedF0Text>
|
|
179
|
+
)
|
|
180
|
+
const element = getByText("Faded text")
|
|
181
|
+
expect(element.props.className).toContain("opacity-50")
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
it("preserves layout classes with all variant combinations", () => {
|
|
185
|
+
const { getByText } = render(
|
|
186
|
+
<AnimatedF0Text
|
|
187
|
+
variant="heading-lg"
|
|
188
|
+
color="critical"
|
|
189
|
+
align="center"
|
|
190
|
+
decoration="underline"
|
|
191
|
+
transform="uppercase"
|
|
192
|
+
className="mt-4 flex-1 self-end"
|
|
193
|
+
>
|
|
194
|
+
Full combo
|
|
195
|
+
</AnimatedF0Text>
|
|
196
|
+
)
|
|
197
|
+
const element = getByText("Full combo")
|
|
198
|
+
expect(element.props.className).toContain("mt-4")
|
|
199
|
+
expect(element.props.className).toContain("flex-1")
|
|
200
|
+
expect(element.props.className).toContain("self-end")
|
|
201
|
+
expect(element.props.className).toContain("text-[24px]")
|
|
202
|
+
expect(element.props.className).toContain("font-semibold")
|
|
203
|
+
expect(element.props.className).toContain("text-f0-foreground-critical")
|
|
204
|
+
expect(element.props.className).toContain("text-center")
|
|
205
|
+
expect(element.props.className).toContain("underline")
|
|
206
|
+
expect(element.props.className).toContain("uppercase")
|
|
207
|
+
})
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
describe("className — typography overrides are rejected", () => {
|
|
211
|
+
it("rejects font-size override", () => {
|
|
212
|
+
const { getByText } = render(
|
|
213
|
+
<AnimatedF0Text variant="body-sm-default" className="text-xs">
|
|
214
|
+
Size override attempt
|
|
215
|
+
</AnimatedF0Text>
|
|
216
|
+
)
|
|
217
|
+
const element = getByText("Size override attempt")
|
|
218
|
+
expect(element.props.className).toContain("text-[14px]")
|
|
219
|
+
expect(element.props.className).not.toContain("text-xs")
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it("rejects font-weight override", () => {
|
|
223
|
+
const { getByText } = render(
|
|
224
|
+
<AnimatedF0Text variant="body-sm-default" className="font-bold">
|
|
225
|
+
Weight override attempt
|
|
226
|
+
</AnimatedF0Text>
|
|
227
|
+
)
|
|
228
|
+
const element = getByText("Weight override attempt")
|
|
229
|
+
expect(element.props.className).toContain("font-normal")
|
|
230
|
+
expect(element.props.className).not.toContain("font-bold")
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
it("rejects line-height override", () => {
|
|
234
|
+
const { getByText } = render(
|
|
235
|
+
<AnimatedF0Text variant="body-sm-default" className="leading-10">
|
|
236
|
+
Leading override attempt
|
|
237
|
+
</AnimatedF0Text>
|
|
238
|
+
)
|
|
239
|
+
const element = getByText("Leading override attempt")
|
|
240
|
+
expect(element.props.className).toContain("leading-[20px]")
|
|
241
|
+
expect(element.props.className).not.toContain("leading-10")
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
it("rejects text-color override", () => {
|
|
245
|
+
const { getByText } = render(
|
|
246
|
+
<AnimatedF0Text color="default" className="text-red-500">
|
|
247
|
+
Color override attempt
|
|
248
|
+
</AnimatedF0Text>
|
|
249
|
+
)
|
|
250
|
+
const element = getByText("Color override attempt")
|
|
251
|
+
expect(element.props.className).toContain("text-f0-foreground")
|
|
252
|
+
expect(element.props.className).not.toContain("text-red-500")
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
it("rejects multiple typography overrides simultaneously", () => {
|
|
256
|
+
const { getByText } = render(
|
|
257
|
+
<AnimatedF0Text
|
|
258
|
+
variant="body-sm-default"
|
|
259
|
+
color="default"
|
|
260
|
+
className="text-xl leading-loose font-bold tracking-wider text-blue-500"
|
|
261
|
+
>
|
|
262
|
+
Multi override attempt
|
|
263
|
+
</AnimatedF0Text>
|
|
264
|
+
)
|
|
265
|
+
const element = getByText("Multi override attempt")
|
|
266
|
+
expect(element.props.className).toContain("text-[14px]")
|
|
267
|
+
expect(element.props.className).toContain("font-normal")
|
|
268
|
+
expect(element.props.className).toContain("leading-[20px]")
|
|
269
|
+
expect(element.props.className).toContain("text-f0-foreground")
|
|
270
|
+
expect(element.props.className).not.toContain("text-xl")
|
|
271
|
+
expect(element.props.className).not.toContain("font-bold")
|
|
272
|
+
expect(element.props.className).not.toContain("leading-loose")
|
|
273
|
+
expect(element.props.className).not.toContain("text-blue-500")
|
|
274
|
+
expect(element.props.className).not.toContain("tracking-wider")
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
describe("className — mixed layout + typography attempts", () => {
|
|
279
|
+
it("keeps layout classes, rejects typography overrides", () => {
|
|
280
|
+
const { getByText } = render(
|
|
281
|
+
<AnimatedF0Text
|
|
282
|
+
variant="heading-md"
|
|
283
|
+
className="mt-4 flex-1 p-2 text-xl font-bold text-red-500"
|
|
284
|
+
>
|
|
285
|
+
Mixed attempt
|
|
286
|
+
</AnimatedF0Text>
|
|
287
|
+
)
|
|
288
|
+
const element = getByText("Mixed attempt")
|
|
289
|
+
expect(element.props.className).toContain("mt-4")
|
|
290
|
+
expect(element.props.className).toContain("p-2")
|
|
291
|
+
expect(element.props.className).toContain("flex-1")
|
|
292
|
+
expect(element.props.className).toContain("text-[20px]")
|
|
293
|
+
expect(element.props.className).toContain("font-semibold")
|
|
294
|
+
expect(element.props.className).toContain("text-f0-foreground")
|
|
295
|
+
expect(element.props.className).not.toContain("font-bold")
|
|
296
|
+
expect(element.props.className).not.toContain("text-red-500")
|
|
297
|
+
expect(element.props.className).not.toContain("text-xl")
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
it("works with both className and style simultaneously", () => {
|
|
301
|
+
const animatedStyle = { opacity: 0.5 }
|
|
302
|
+
const { getByText } = render(
|
|
303
|
+
<AnimatedF0Text
|
|
304
|
+
variant="heading-sm"
|
|
305
|
+
className="mb-2 flex-1"
|
|
306
|
+
style={animatedStyle}
|
|
307
|
+
>
|
|
308
|
+
className + style
|
|
309
|
+
</AnimatedF0Text>
|
|
310
|
+
)
|
|
311
|
+
const element = getByText("className + style")
|
|
312
|
+
expect(element.props.className).toContain("mb-2")
|
|
313
|
+
expect(element.props.className).toContain("flex-1")
|
|
314
|
+
expect(element.props.className).toContain("text-[16px]")
|
|
315
|
+
expect(element.props.className).toContain("font-semibold")
|
|
316
|
+
expect(element.props.style).toEqual(animatedStyle)
|
|
317
|
+
})
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
describe("className — edge cases", () => {
|
|
321
|
+
it("works correctly when className is undefined", () => {
|
|
322
|
+
const { getByText } = render(
|
|
323
|
+
<AnimatedF0Text>No className</AnimatedF0Text>
|
|
324
|
+
)
|
|
325
|
+
const element = getByText("No className")
|
|
326
|
+
expect(element.props.className).toContain("text-[14px]")
|
|
327
|
+
expect(element.props.className).toContain("font-normal")
|
|
328
|
+
expect(element.props.className).toContain("text-f0-foreground")
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
it("works correctly when className is empty string", () => {
|
|
332
|
+
const { getByText } = render(
|
|
333
|
+
<AnimatedF0Text className="">Empty className</AnimatedF0Text>
|
|
334
|
+
)
|
|
335
|
+
const element = getByText("Empty className")
|
|
336
|
+
expect(element.props.className).toContain("text-[14px]")
|
|
337
|
+
expect(element.props.className).toContain("font-normal")
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
it("handles className with extra whitespace", () => {
|
|
341
|
+
const { getByText } = render(
|
|
342
|
+
<AnimatedF0Text className=" mt-4 mb-2 ">
|
|
343
|
+
Whitespace className
|
|
344
|
+
</AnimatedF0Text>
|
|
345
|
+
)
|
|
346
|
+
const element = getByText("Whitespace className")
|
|
347
|
+
expect(element.props.className).toContain("mt-4")
|
|
348
|
+
expect(element.props.className).toContain("mb-2")
|
|
349
|
+
})
|
|
350
|
+
})
|
|
131
351
|
})
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-md-default 1`] = `
|
|
4
4
|
<Text
|
|
5
|
-
className="text-[16px] leading-[24px] font-normal text-f0-foreground text-left"
|
|
5
|
+
className="no-underline normal-case tracking-normal text-[16px] leading-[24px] font-normal text-f0-foreground text-left"
|
|
6
6
|
>
|
|
7
7
|
body-md-default
|
|
8
8
|
text
|
|
@@ -11,7 +11,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-
|
|
|
11
11
|
|
|
12
12
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-md-medium 1`] = `
|
|
13
13
|
<Text
|
|
14
|
-
className="text-[16px] leading-[24px] font-medium text-f0-foreground text-left"
|
|
14
|
+
className="no-underline normal-case tracking-normal text-[16px] leading-[24px] font-medium text-f0-foreground text-left"
|
|
15
15
|
>
|
|
16
16
|
body-md-medium
|
|
17
17
|
text
|
|
@@ -20,7 +20,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-
|
|
|
20
20
|
|
|
21
21
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-md-semibold 1`] = `
|
|
22
22
|
<Text
|
|
23
|
-
className="text-[16px] leading-[24px] font-semibold text-f0-foreground text-left"
|
|
23
|
+
className="no-underline normal-case tracking-normal text-[16px] leading-[24px] font-semibold text-f0-foreground text-left"
|
|
24
24
|
>
|
|
25
25
|
body-md-semibold
|
|
26
26
|
text
|
|
@@ -29,7 +29,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-
|
|
|
29
29
|
|
|
30
30
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-sm-default 1`] = `
|
|
31
31
|
<Text
|
|
32
|
-
className="text-[14px] leading-[20px] font-normal text-f0-foreground text-left"
|
|
32
|
+
className="no-underline normal-case tracking-normal text-[14px] leading-[20px] font-normal text-f0-foreground text-left"
|
|
33
33
|
>
|
|
34
34
|
body-sm-default
|
|
35
35
|
text
|
|
@@ -38,7 +38,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-
|
|
|
38
38
|
|
|
39
39
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-sm-medium 1`] = `
|
|
40
40
|
<Text
|
|
41
|
-
className="text-[14px] leading-[20px] font-medium text-f0-foreground text-left"
|
|
41
|
+
className="no-underline normal-case tracking-normal text-[14px] leading-[20px] font-medium text-f0-foreground text-left"
|
|
42
42
|
>
|
|
43
43
|
body-sm-medium
|
|
44
44
|
text
|
|
@@ -47,7 +47,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-
|
|
|
47
47
|
|
|
48
48
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-sm-semibold 1`] = `
|
|
49
49
|
<Text
|
|
50
|
-
className="text-[14px] leading-[20px] font-semibold text-f0-foreground text-left"
|
|
50
|
+
className="no-underline normal-case tracking-normal text-[14px] leading-[20px] font-semibold text-f0-foreground text-left"
|
|
51
51
|
>
|
|
52
52
|
body-sm-semibold
|
|
53
53
|
text
|
|
@@ -56,7 +56,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-
|
|
|
56
56
|
|
|
57
57
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-xs-medium 1`] = `
|
|
58
58
|
<Text
|
|
59
|
-
className="text-[12px] leading-[16px] font-medium text-f0-foreground text-left"
|
|
59
|
+
className="no-underline normal-case tracking-normal text-[12px] leading-[16px] font-medium text-f0-foreground text-left"
|
|
60
60
|
>
|
|
61
61
|
body-xs-medium
|
|
62
62
|
text
|
|
@@ -65,7 +65,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-body-
|
|
|
65
65
|
|
|
66
66
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-heading-lg 1`] = `
|
|
67
67
|
<Text
|
|
68
|
-
className="text-[24px] leading-[32px] tracking-[-0.2px] font-semibold text-f0-foreground text-left"
|
|
68
|
+
className="no-underline normal-case text-[24px] leading-[32px] tracking-[-0.2px] font-semibold text-f0-foreground text-left"
|
|
69
69
|
>
|
|
70
70
|
heading-lg
|
|
71
71
|
text
|
|
@@ -74,7 +74,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-headi
|
|
|
74
74
|
|
|
75
75
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-heading-md 1`] = `
|
|
76
76
|
<Text
|
|
77
|
-
className="text-[20px] leading-[28px] tracking-[-0.2px] font-semibold text-f0-foreground text-left"
|
|
77
|
+
className="no-underline normal-case text-[20px] leading-[28px] tracking-[-0.2px] font-semibold text-f0-foreground text-left"
|
|
78
78
|
>
|
|
79
79
|
heading-md
|
|
80
80
|
text
|
|
@@ -83,7 +83,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-headi
|
|
|
83
83
|
|
|
84
84
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-heading-sm 1`] = `
|
|
85
85
|
<Text
|
|
86
|
-
className="text-[16px] leading-[24px] font-semibold text-f0-foreground text-left"
|
|
86
|
+
className="no-underline normal-case tracking-normal text-[16px] leading-[24px] font-semibold text-f0-foreground text-left"
|
|
87
87
|
>
|
|
88
88
|
heading-sm
|
|
89
89
|
text
|
|
@@ -92,7 +92,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-headi
|
|
|
92
92
|
|
|
93
93
|
exports[`AnimatedF0Text Snapshots renders all typography variants: variant-heading-xl 1`] = `
|
|
94
94
|
<Text
|
|
95
|
-
className="text-[36px] leading-[40px] tracking-[-0.2px] font-semibold text-f0-foreground text-left"
|
|
95
|
+
className="no-underline normal-case text-[36px] leading-[40px] tracking-[-0.2px] font-semibold text-f0-foreground text-left"
|
|
96
96
|
>
|
|
97
97
|
heading-xl
|
|
98
98
|
text
|
|
@@ -101,7 +101,7 @@ exports[`AnimatedF0Text Snapshots renders all typography variants: variant-headi
|
|
|
101
101
|
|
|
102
102
|
exports[`AnimatedF0Text Snapshots renders with color variants: color-accent 1`] = `
|
|
103
103
|
<Text
|
|
104
|
-
className="text-[14px] leading-[20px] font-normal text-f0-foreground-accent text-left"
|
|
104
|
+
className="no-underline normal-case tracking-normal text-[14px] leading-[20px] font-normal text-f0-foreground-accent text-left"
|
|
105
105
|
>
|
|
106
106
|
accent
|
|
107
107
|
text
|
|
@@ -110,7 +110,7 @@ exports[`AnimatedF0Text Snapshots renders with color variants: color-accent 1`]
|
|
|
110
110
|
|
|
111
111
|
exports[`AnimatedF0Text Snapshots renders with color variants: color-critical 1`] = `
|
|
112
112
|
<Text
|
|
113
|
-
className="text-[14px] leading-[20px] font-normal text-f0-foreground-critical text-left"
|
|
113
|
+
className="no-underline normal-case tracking-normal text-[14px] leading-[20px] font-normal text-f0-foreground-critical text-left"
|
|
114
114
|
>
|
|
115
115
|
critical
|
|
116
116
|
text
|
|
@@ -119,7 +119,7 @@ exports[`AnimatedF0Text Snapshots renders with color variants: color-critical 1`
|
|
|
119
119
|
|
|
120
120
|
exports[`AnimatedF0Text Snapshots renders with color variants: color-default 1`] = `
|
|
121
121
|
<Text
|
|
122
|
-
className="text-[14px] leading-[20px] font-normal text-f0-foreground text-left"
|
|
122
|
+
className="no-underline normal-case tracking-normal text-[14px] leading-[20px] font-normal text-f0-foreground text-left"
|
|
123
123
|
>
|
|
124
124
|
default
|
|
125
125
|
text
|
|
@@ -128,7 +128,7 @@ exports[`AnimatedF0Text Snapshots renders with color variants: color-default 1`]
|
|
|
128
128
|
|
|
129
129
|
exports[`AnimatedF0Text Snapshots renders with color variants: color-secondary 1`] = `
|
|
130
130
|
<Text
|
|
131
|
-
className="text-[14px] leading-[20px] font-normal text-f0-foreground-secondary text-left"
|
|
131
|
+
className="no-underline normal-case tracking-normal text-[14px] leading-[20px] font-normal text-f0-foreground-secondary text-left"
|
|
132
132
|
>
|
|
133
133
|
secondary
|
|
134
134
|
text
|
|
@@ -137,7 +137,7 @@ exports[`AnimatedF0Text Snapshots renders with color variants: color-secondary 1
|
|
|
137
137
|
|
|
138
138
|
exports[`AnimatedF0Text Snapshots renders with default variant (body-sm-default) 1`] = `
|
|
139
139
|
<Text
|
|
140
|
-
className="text-[14px] leading-[20px] font-normal text-f0-foreground text-left"
|
|
140
|
+
className="no-underline normal-case tracking-normal text-[14px] leading-[20px] font-normal text-f0-foreground text-left"
|
|
141
141
|
>
|
|
142
142
|
Default text
|
|
143
143
|
</Text>
|