@medway-ui/native 1.1.2 → 1.2.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/commonjs/components/Alert.js +5 -4
- package/lib/commonjs/components/Alert.js.map +1 -1
- package/lib/commonjs/components/Avatar.js +2 -1
- package/lib/commonjs/components/Avatar.js.map +1 -1
- package/lib/commonjs/components/Badge.js +2 -1
- package/lib/commonjs/components/Badge.js.map +1 -1
- package/lib/commonjs/components/Button.js +3 -2
- package/lib/commonjs/components/Button.js.map +1 -1
- package/lib/commonjs/components/CardNews.js +7 -6
- package/lib/commonjs/components/CardNews.js.map +1 -1
- package/lib/commonjs/components/Carousel.js +122 -0
- package/lib/commonjs/components/Carousel.js.map +1 -0
- package/lib/commonjs/components/Checkbox.js +11 -2
- package/lib/commonjs/components/Checkbox.js.map +1 -1
- package/lib/commonjs/components/DropdownMenu.js +225 -0
- package/lib/commonjs/components/DropdownMenu.js.map +1 -0
- package/lib/commonjs/components/EmptyState.js +19 -20
- package/lib/commonjs/components/EmptyState.js.map +1 -1
- package/lib/commonjs/components/Feed.js +82 -0
- package/lib/commonjs/components/Feed.js.map +1 -0
- package/lib/commonjs/components/FeedNotice.js +76 -0
- package/lib/commonjs/components/FeedNotice.js.map +1 -0
- package/lib/commonjs/components/Input.js +21 -9
- package/lib/commonjs/components/Input.js.map +1 -1
- package/lib/commonjs/components/InvitePopover.js +196 -0
- package/lib/commonjs/components/InvitePopover.js.map +1 -0
- package/lib/commonjs/components/Label.js +2 -1
- package/lib/commonjs/components/Label.js.map +1 -1
- package/lib/commonjs/components/LeaderboardCard.js +58 -0
- package/lib/commonjs/components/LeaderboardCard.js.map +1 -0
- package/lib/commonjs/components/MemberRow.js +131 -0
- package/lib/commonjs/components/MemberRow.js.map +1 -0
- package/lib/commonjs/components/PageHeader.js +3 -2
- package/lib/commonjs/components/PageHeader.js.map +1 -1
- package/lib/commonjs/components/PostForm.js +182 -0
- package/lib/commonjs/components/PostForm.js.map +1 -0
- package/lib/commonjs/components/PrizeCollection.js +135 -0
- package/lib/commonjs/components/PrizeCollection.js.map +1 -0
- package/lib/commonjs/components/RadioGroup.js +22 -0
- package/lib/commonjs/components/RadioGroup.js.map +1 -1
- package/lib/commonjs/components/SectionHeader.js +36 -0
- package/lib/commonjs/components/SectionHeader.js.map +1 -0
- package/lib/commonjs/components/Switch.js +33 -19
- package/lib/commonjs/components/Switch.js.map +1 -1
- package/lib/commonjs/components/Tabs.js +156 -0
- package/lib/commonjs/components/Tabs.js.map +1 -0
- package/lib/commonjs/components/Tag.js +2 -1
- package/lib/commonjs/components/Tag.js.map +1 -1
- package/lib/commonjs/components/Text.js +60 -0
- package/lib/commonjs/components/Text.js.map +1 -0
- package/lib/commonjs/components/Toast.js +3 -2
- package/lib/commonjs/components/Toast.js.map +1 -1
- package/lib/commonjs/components/Tooltip.js +2 -2
- package/lib/commonjs/components/Tooltip.js.map +1 -1
- package/lib/commonjs/hooks/useThemeColor.js +66 -29
- package/lib/commonjs/hooks/useThemeColor.js.map +1 -1
- package/lib/commonjs/index.js +319 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/lib/overlay-host.js +101 -0
- package/lib/commonjs/lib/overlay-host.js.map +1 -0
- package/lib/commonjs/lib/typography.js +26 -0
- package/lib/commonjs/lib/typography.js.map +1 -0
- package/lib/commonjs/nativewind-env.d.js +0 -1
- package/lib/commonjs/nativewind-env.d.js.map +1 -1
- package/lib/module/components/Alert.js +3 -2
- package/lib/module/components/Alert.js.map +1 -1
- package/lib/module/components/Avatar.js +2 -1
- package/lib/module/components/Avatar.js.map +1 -1
- package/lib/module/components/Badge.js +2 -1
- package/lib/module/components/Badge.js.map +1 -1
- package/lib/module/components/Button.js +2 -1
- package/lib/module/components/Button.js.map +1 -1
- package/lib/module/components/CardNews.js +2 -1
- package/lib/module/components/CardNews.js.map +1 -1
- package/lib/module/components/Carousel.js +117 -0
- package/lib/module/components/Carousel.js.map +1 -0
- package/lib/module/components/Checkbox.js +12 -2
- package/lib/module/components/Checkbox.js.map +1 -1
- package/lib/module/components/DropdownMenu.js +216 -0
- package/lib/module/components/DropdownMenu.js.map +1 -0
- package/lib/module/components/EmptyState.js +19 -20
- package/lib/module/components/EmptyState.js.map +1 -1
- package/lib/module/components/Feed.js +77 -0
- package/lib/module/components/Feed.js.map +1 -0
- package/lib/module/components/FeedNotice.js +73 -0
- package/lib/module/components/FeedNotice.js.map +1 -0
- package/lib/module/components/Input.js +21 -9
- package/lib/module/components/Input.js.map +1 -1
- package/lib/module/components/InvitePopover.js +183 -0
- package/lib/module/components/InvitePopover.js.map +1 -0
- package/lib/module/components/Label.js +2 -1
- package/lib/module/components/Label.js.map +1 -1
- package/lib/module/components/LeaderboardCard.js +53 -0
- package/lib/module/components/LeaderboardCard.js.map +1 -0
- package/lib/module/components/MemberRow.js +127 -0
- package/lib/module/components/MemberRow.js.map +1 -0
- package/lib/module/components/PageHeader.js +2 -1
- package/lib/module/components/PageHeader.js.map +1 -1
- package/lib/module/components/PostForm.js +174 -0
- package/lib/module/components/PostForm.js.map +1 -0
- package/lib/module/components/PrizeCollection.js +127 -0
- package/lib/module/components/PrizeCollection.js.map +1 -0
- package/lib/module/components/RadioGroup.js +21 -1
- package/lib/module/components/RadioGroup.js.map +1 -1
- package/lib/module/components/SectionHeader.js +33 -0
- package/lib/module/components/SectionHeader.js.map +1 -0
- package/lib/module/components/Switch.js +34 -20
- package/lib/module/components/Switch.js.map +1 -1
- package/lib/module/components/Tabs.js +148 -0
- package/lib/module/components/Tabs.js.map +1 -0
- package/lib/module/components/Tag.js +2 -1
- package/lib/module/components/Tag.js.map +1 -1
- package/lib/module/components/Text.js +58 -0
- package/lib/module/components/Text.js.map +1 -0
- package/lib/module/components/Toast.js +2 -1
- package/lib/module/components/Toast.js.map +1 -1
- package/lib/module/components/Tooltip.js +1 -1
- package/lib/module/components/Tooltip.js.map +1 -1
- package/lib/module/hooks/useThemeColor.js +66 -31
- package/lib/module/hooks/useThemeColor.js.map +1 -1
- package/lib/module/index.js +27 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/lib/overlay-host.js +96 -0
- package/lib/module/lib/overlay-host.js.map +1 -0
- package/lib/module/lib/typography.js +22 -0
- package/lib/module/lib/typography.js.map +1 -0
- package/lib/module/nativewind-env.d.js +0 -1
- package/lib/module/nativewind-env.d.js.map +1 -1
- package/lib/typescript/components/Alert.d.ts.map +1 -1
- package/lib/typescript/components/Avatar.d.ts.map +1 -1
- package/lib/typescript/components/Badge.d.ts.map +1 -1
- package/lib/typescript/components/Button.d.ts.map +1 -1
- package/lib/typescript/components/CardNews.d.ts.map +1 -1
- package/lib/typescript/components/Carousel.d.ts +29 -0
- package/lib/typescript/components/Carousel.d.ts.map +1 -0
- package/lib/typescript/components/Checkbox.d.ts.map +1 -1
- package/lib/typescript/components/DropdownMenu.d.ts +39 -0
- package/lib/typescript/components/DropdownMenu.d.ts.map +1 -0
- package/lib/typescript/components/EmptyState.d.ts +1 -1
- package/lib/typescript/components/EmptyState.d.ts.map +1 -1
- package/lib/typescript/components/Feed.d.ts +22 -0
- package/lib/typescript/components/Feed.d.ts.map +1 -0
- package/lib/typescript/components/FeedNotice.d.ts +17 -0
- package/lib/typescript/components/FeedNotice.d.ts.map +1 -0
- package/lib/typescript/components/Input.d.ts +3 -2
- package/lib/typescript/components/Input.d.ts.map +1 -1
- package/lib/typescript/components/InvitePopover.d.ts +46 -0
- package/lib/typescript/components/InvitePopover.d.ts.map +1 -0
- package/lib/typescript/components/Label.d.ts.map +1 -1
- package/lib/typescript/components/LeaderboardCard.d.ts +16 -0
- package/lib/typescript/components/LeaderboardCard.d.ts.map +1 -0
- package/lib/typescript/components/MemberRow.d.ts +40 -0
- package/lib/typescript/components/MemberRow.d.ts.map +1 -0
- package/lib/typescript/components/PageHeader.d.ts.map +1 -1
- package/lib/typescript/components/PostForm.d.ts +50 -0
- package/lib/typescript/components/PostForm.d.ts.map +1 -0
- package/lib/typescript/components/PrizeCollection.d.ts +35 -0
- package/lib/typescript/components/PrizeCollection.d.ts.map +1 -0
- package/lib/typescript/components/RadioGroup.d.ts +10 -2
- package/lib/typescript/components/RadioGroup.d.ts.map +1 -1
- package/lib/typescript/components/SectionHeader.d.ts +12 -0
- package/lib/typescript/components/SectionHeader.d.ts.map +1 -0
- package/lib/typescript/components/Switch.d.ts.map +1 -1
- package/lib/typescript/components/Tabs.d.ts +32 -0
- package/lib/typescript/components/Tabs.d.ts.map +1 -0
- package/lib/typescript/components/Tag.d.ts.map +1 -1
- package/lib/typescript/components/Text.d.ts +23 -0
- package/lib/typescript/components/Text.d.ts.map +1 -0
- package/lib/typescript/components/Toast.d.ts +1 -1
- package/lib/typescript/components/Toast.d.ts.map +1 -1
- package/lib/typescript/components/Tooltip.d.ts.map +1 -1
- package/lib/typescript/hooks/useThemeColor.d.ts +4 -2
- package/lib/typescript/hooks/useThemeColor.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +28 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/lib/overlay-host.d.ts +23 -0
- package/lib/typescript/lib/overlay-host.d.ts.map +1 -0
- package/lib/typescript/lib/typography.d.ts +12 -0
- package/lib/typescript/lib/typography.d.ts.map +1 -0
- package/package.json +13 -3
- package/setup/MedwayUiProvider.tsx +15 -3
- package/setup/tailwind.js +52 -4
- package/setup/tokens.native.css +8 -3
- package/src/components/Alert.tsx +4 -2
- package/src/components/Avatar.tsx +3 -1
- package/src/components/Badge.tsx +3 -1
- package/src/components/Button.tsx +3 -7
- package/src/components/CardNews.tsx +2 -1
- package/src/components/Carousel.tsx +152 -0
- package/src/components/Checkbox.tsx +14 -4
- package/src/components/DropdownMenu.tsx +312 -0
- package/src/components/EmptyState.tsx +21 -23
- package/src/components/Feed.tsx +96 -0
- package/src/components/FeedNotice.tsx +112 -0
- package/src/components/Input.tsx +11 -6
- package/src/components/InvitePopover.tsx +240 -0
- package/src/components/Label.tsx +3 -1
- package/src/components/LeaderboardCard.tsx +70 -0
- package/src/components/MemberRow.tsx +157 -0
- package/src/components/PageHeader.tsx +3 -1
- package/src/components/PostForm.tsx +250 -0
- package/src/components/PrizeCollection.tsx +190 -0
- package/src/components/RadioGroup.tsx +32 -3
- package/src/components/SectionHeader.tsx +45 -0
- package/src/components/Switch.tsx +65 -59
- package/src/components/Tabs.tsx +182 -0
- package/src/components/Tag.tsx +3 -1
- package/src/components/Text.tsx +66 -0
- package/src/components/Toast.tsx +3 -1
- package/src/components/Tooltip.tsx +2 -1
- package/src/hooks/useThemeColor.ts +77 -32
- package/src/index.ts +147 -6
- package/src/lib/overlay-host.tsx +102 -0
- package/src/lib/typography.ts +21 -0
- package/src/nativewind-env.d.ts +2 -0
|
@@ -9,6 +9,7 @@ import Animated, {
|
|
|
9
9
|
} from "react-native-reanimated";
|
|
10
10
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
11
11
|
import { cn } from "@/lib/utils";
|
|
12
|
+
import { useThemeColor } from "@/hooks/useThemeColor";
|
|
12
13
|
|
|
13
14
|
interface SwitchProps
|
|
14
15
|
extends Omit<
|
|
@@ -35,31 +36,28 @@ const THUMB_TRANSLATE: Record<"sm" | "md" | "lg", number> = {
|
|
|
35
36
|
lg: 19,
|
|
36
37
|
};
|
|
37
38
|
|
|
38
|
-
const
|
|
39
|
+
const SWITCH_DIMENSIONS: Record<"sm" | "md" | "lg", { width: number; height: number }> = {
|
|
39
40
|
sm: { width: 24, height: 16 },
|
|
40
41
|
md: { width: 32, height: 20 },
|
|
41
42
|
lg: { width: 40, height: 24 },
|
|
42
43
|
};
|
|
43
44
|
|
|
44
|
-
const switchVariants = cva(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
variant: {
|
|
49
|
-
regular: "",
|
|
50
|
-
},
|
|
51
|
-
size: {
|
|
52
|
-
sm: "h-4 w-6",
|
|
53
|
-
md: "h-5 w-8",
|
|
54
|
-
lg: "h-6 w-10",
|
|
55
|
-
},
|
|
45
|
+
const switchVariants = cva("rounded-full border-2 items-center shrink-0", {
|
|
46
|
+
variants: {
|
|
47
|
+
variant: {
|
|
48
|
+
regular: "",
|
|
56
49
|
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
size: {
|
|
51
|
+
sm: "h-4 w-6",
|
|
52
|
+
md: "h-5 w-8",
|
|
53
|
+
lg: "h-6 w-10",
|
|
60
54
|
},
|
|
61
|
-
}
|
|
62
|
-
|
|
55
|
+
},
|
|
56
|
+
defaultVariants: {
|
|
57
|
+
variant: "regular",
|
|
58
|
+
size: "md",
|
|
59
|
+
},
|
|
60
|
+
});
|
|
63
61
|
|
|
64
62
|
function Switch({
|
|
65
63
|
className,
|
|
@@ -75,25 +73,33 @@ function Switch({
|
|
|
75
73
|
...props
|
|
76
74
|
}: SwitchProps) {
|
|
77
75
|
const resolvedSize = size ?? "md";
|
|
78
|
-
const
|
|
76
|
+
const dimensions = SWITCH_DIMENSIONS[resolvedSize];
|
|
79
77
|
const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);
|
|
80
78
|
const isControlled = checked !== undefined;
|
|
81
79
|
const isChecked = isControlled ? (checked ?? false) : internalChecked;
|
|
82
80
|
|
|
81
|
+
const trackOn = useThemeColor("primary-background-fill");
|
|
82
|
+
const trackOff = useThemeColor("surface-card");
|
|
83
|
+
const trackDisabled = useThemeColor("gray-background-soft-muted");
|
|
84
|
+
const trackBorder = useThemeColor("gray-stroke-muted");
|
|
85
|
+
const thumbOn = useThemeColor("primary-foreground-onfill");
|
|
86
|
+
const thumbOff = useThemeColor("gray-foreground-muted");
|
|
87
|
+
const thumbDisabled = useThemeColor("gray-background-fill-muted");
|
|
88
|
+
|
|
83
89
|
const translateX = useSharedValue(isChecked ? THUMB_TRANSLATE[resolvedSize] : 2);
|
|
84
90
|
|
|
85
91
|
useEffect(() => {
|
|
86
|
-
translateX.value = withTiming(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
);
|
|
92
|
+
translateX.value = withTiming(isChecked ? THUMB_TRANSLATE[resolvedSize] : 2, {
|
|
93
|
+
duration: 180,
|
|
94
|
+
easing: Easing.out(Easing.ease),
|
|
95
|
+
});
|
|
90
96
|
}, [isChecked, resolvedSize, translateX]);
|
|
91
97
|
|
|
92
98
|
const thumbStyle = useAnimatedStyle(() => ({
|
|
93
99
|
transform: [{ translateX: translateX.value }],
|
|
94
100
|
}));
|
|
95
101
|
|
|
96
|
-
const hasIcons = checkedIcon || uncheckedIcon;
|
|
102
|
+
const hasIcons = Boolean(checkedIcon || uncheckedIcon);
|
|
97
103
|
const thumbSize = THUMB_SIZES[resolvedSize];
|
|
98
104
|
|
|
99
105
|
const handleCheckedChange = (nextChecked: boolean) => {
|
|
@@ -101,14 +107,33 @@ function Switch({
|
|
|
101
107
|
onCheckedChange?.(nextChecked);
|
|
102
108
|
};
|
|
103
109
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
const trackBackgroundColor = disabled
|
|
111
|
+
? trackDisabled
|
|
112
|
+
: isChecked
|
|
113
|
+
? trackOn
|
|
114
|
+
: trackOff;
|
|
115
|
+
|
|
116
|
+
const trackBorderColor = disabled || !isChecked ? trackBorder : "transparent";
|
|
117
|
+
|
|
118
|
+
const thumbBackgroundColor = disabled
|
|
119
|
+
? thumbDisabled
|
|
120
|
+
: hasIcons
|
|
121
|
+
? "transparent"
|
|
122
|
+
: isChecked
|
|
123
|
+
? thumbOn
|
|
124
|
+
: thumbOff;
|
|
125
|
+
|
|
126
|
+
const rootStyle: ViewStyle = {
|
|
127
|
+
width: dimensions.width,
|
|
128
|
+
height: dimensions.height,
|
|
129
|
+
minWidth: dimensions.width,
|
|
130
|
+
minHeight: dimensions.height,
|
|
131
|
+
borderRadius: dimensions.height / 2,
|
|
110
132
|
borderWidth: 2,
|
|
133
|
+
alignItems: "flex-start",
|
|
111
134
|
justifyContent: "center",
|
|
135
|
+
backgroundColor: trackBackgroundColor,
|
|
136
|
+
borderColor: trackBorderColor,
|
|
112
137
|
};
|
|
113
138
|
|
|
114
139
|
return (
|
|
@@ -117,18 +142,10 @@ function Switch({
|
|
|
117
142
|
onCheckedChange={handleCheckedChange}
|
|
118
143
|
disabled={disabled}
|
|
119
144
|
style={(state) => [
|
|
120
|
-
|
|
145
|
+
rootStyle,
|
|
121
146
|
typeof style === "function" ? style(state) : style,
|
|
122
147
|
]}
|
|
123
|
-
className={cn(
|
|
124
|
-
switchVariants({ size, variant }),
|
|
125
|
-
disabled
|
|
126
|
-
? "bg-gray-background-soft-muted border-gray-stroke-muted"
|
|
127
|
-
: isChecked
|
|
128
|
-
? "bg-primary-background-fill border-primary-background-fill"
|
|
129
|
-
: "bg-surface-card border-gray-stroke-muted",
|
|
130
|
-
className
|
|
131
|
-
)}
|
|
148
|
+
className={cn(switchVariants({ size, variant }), className)}
|
|
132
149
|
{...props}
|
|
133
150
|
>
|
|
134
151
|
<SwitchPrimitive.Thumb asChild>
|
|
@@ -138,28 +155,17 @@ function Switch({
|
|
|
138
155
|
{
|
|
139
156
|
width: thumbSize,
|
|
140
157
|
height: thumbSize,
|
|
158
|
+
borderRadius: thumbSize / 2,
|
|
159
|
+
backgroundColor: thumbBackgroundColor,
|
|
141
160
|
},
|
|
142
161
|
]}
|
|
143
162
|
>
|
|
144
|
-
|
|
145
|
-
className=
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
? "bg-transparent"
|
|
151
|
-
: isChecked
|
|
152
|
-
? "bg-primary-foreground-onfill"
|
|
153
|
-
: "bg-gray-foreground-muted"
|
|
154
|
-
)}
|
|
155
|
-
>
|
|
156
|
-
{hasIcons ? (
|
|
157
|
-
<>
|
|
158
|
-
{isChecked && checkedIcon}
|
|
159
|
-
{!isChecked && uncheckedIcon}
|
|
160
|
-
</>
|
|
161
|
-
) : null}
|
|
162
|
-
</View>
|
|
163
|
+
{hasIcons ? (
|
|
164
|
+
<View className="flex-1 items-center justify-center">
|
|
165
|
+
{isChecked && checkedIcon}
|
|
166
|
+
{!isChecked && uncheckedIcon}
|
|
167
|
+
</View>
|
|
168
|
+
) : null}
|
|
163
169
|
</Animated.View>
|
|
164
170
|
</SwitchPrimitive.Thumb>
|
|
165
171
|
</SwitchPrimitive.Root>
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { createContext, useContext, type ReactNode } from "react";
|
|
2
|
+
import { Pressable, View } from "react-native";
|
|
3
|
+
|
|
4
|
+
import { Text } from "@/components/Text";
|
|
5
|
+
import * as TabsPrimitive from "@rn-primitives/tabs";
|
|
6
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
7
|
+
|
|
8
|
+
import { cn } from "@/lib/utils";
|
|
9
|
+
|
|
10
|
+
type TabsVariant = "pill" | "filter";
|
|
11
|
+
|
|
12
|
+
const TabsVariantContext = createContext<TabsVariant>("pill");
|
|
13
|
+
|
|
14
|
+
function useTabsVariant() {
|
|
15
|
+
return useContext(TabsVariantContext);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const tabsTriggerVariants = cva(
|
|
19
|
+
"min-h-12 flex-row items-center justify-center rounded-pill px-4",
|
|
20
|
+
{
|
|
21
|
+
variants: {
|
|
22
|
+
active: {
|
|
23
|
+
true: "bg-primary-background-fill",
|
|
24
|
+
false: "bg-transparent",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
defaultVariants: {
|
|
28
|
+
active: false,
|
|
29
|
+
},
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const tabsTriggerTextVariants = cva("text-sm font-semibold", {
|
|
34
|
+
variants: {
|
|
35
|
+
active: {
|
|
36
|
+
true: "text-primary-foreground-onfill",
|
|
37
|
+
false: "text-primary-foreground",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
defaultVariants: {
|
|
41
|
+
active: false,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
interface TabsProps extends TabsPrimitive.RootProps {
|
|
46
|
+
className?: string;
|
|
47
|
+
children?: ReactNode;
|
|
48
|
+
variant?: TabsVariant;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface TabsListProps extends TabsPrimitive.ListProps {
|
|
52
|
+
className?: string;
|
|
53
|
+
children?: ReactNode;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface TabsTriggerProps
|
|
57
|
+
extends TabsPrimitive.TriggerProps,
|
|
58
|
+
VariantProps<typeof tabsTriggerVariants> {
|
|
59
|
+
className?: string;
|
|
60
|
+
children?: ReactNode;
|
|
61
|
+
icon?: ReactNode;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface TabsContentProps extends TabsPrimitive.ContentProps {
|
|
65
|
+
className?: string;
|
|
66
|
+
children?: ReactNode;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function Tabs({ className, children, variant = "pill", ...props }: TabsProps) {
|
|
70
|
+
return (
|
|
71
|
+
<TabsVariantContext.Provider value={variant}>
|
|
72
|
+
<TabsPrimitive.Root asChild {...props}>
|
|
73
|
+
<View
|
|
74
|
+
className={cn(variant === "filter" ? "gap-8" : "gap-2", className)}
|
|
75
|
+
>
|
|
76
|
+
{children}
|
|
77
|
+
</View>
|
|
78
|
+
</TabsPrimitive.Root>
|
|
79
|
+
</TabsVariantContext.Provider>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function TabsList({ className, children, ...props }: TabsListProps) {
|
|
84
|
+
const variant = useTabsVariant();
|
|
85
|
+
|
|
86
|
+
if (variant === "filter") {
|
|
87
|
+
return (
|
|
88
|
+
<View className="rounded-lg border border-gray-stroke-muted bg-surface-section px-6 py-1">
|
|
89
|
+
<TabsPrimitive.List asChild {...props}>
|
|
90
|
+
<View className={cn("w-full flex-row items-center", className)}>
|
|
91
|
+
{children}
|
|
92
|
+
</View>
|
|
93
|
+
</TabsPrimitive.List>
|
|
94
|
+
</View>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<TabsPrimitive.List asChild {...props}>
|
|
100
|
+
<View className={cn("flex-row items-center gap-2", className)}>
|
|
101
|
+
{children}
|
|
102
|
+
</View>
|
|
103
|
+
</TabsPrimitive.List>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function TabsTrigger({
|
|
108
|
+
className,
|
|
109
|
+
children,
|
|
110
|
+
icon,
|
|
111
|
+
value,
|
|
112
|
+
...props
|
|
113
|
+
}: TabsTriggerProps) {
|
|
114
|
+
const variant = useTabsVariant();
|
|
115
|
+
const { value: activeValue } = TabsPrimitive.useRootContext();
|
|
116
|
+
const isActive = activeValue === value;
|
|
117
|
+
|
|
118
|
+
if (variant === "filter") {
|
|
119
|
+
const hasLabel = typeof children === "string" && children.length > 0;
|
|
120
|
+
const showLabel = isActive && hasLabel;
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<TabsPrimitive.Trigger asChild value={value} {...props}>
|
|
124
|
+
<Pressable
|
|
125
|
+
className={cn(
|
|
126
|
+
"relative min-h-12 flex-1 flex-row items-center justify-center gap-3 py-3",
|
|
127
|
+
className
|
|
128
|
+
)}
|
|
129
|
+
>
|
|
130
|
+
{icon ? <View className="size-6 shrink-0">{icon}</View> : null}
|
|
131
|
+
{showLabel ? (
|
|
132
|
+
<Text className="text-md font-semibold text-primary-foreground">
|
|
133
|
+
{children}
|
|
134
|
+
</Text>
|
|
135
|
+
) : !hasLabel ? (
|
|
136
|
+
children
|
|
137
|
+
) : null}
|
|
138
|
+
{isActive ? (
|
|
139
|
+
<View className="absolute -bottom-1 left-0 right-0 h-0.5 rounded-t-pill bg-secondary-stroke-emphasis" />
|
|
140
|
+
) : null}
|
|
141
|
+
</Pressable>
|
|
142
|
+
</TabsPrimitive.Trigger>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<TabsPrimitive.Trigger asChild value={value} {...props}>
|
|
148
|
+
<Pressable
|
|
149
|
+
className={cn(tabsTriggerVariants({ active: isActive }), className)}
|
|
150
|
+
>
|
|
151
|
+
{typeof children === "string" ? (
|
|
152
|
+
<Text className={cn(tabsTriggerTextVariants({ active: isActive }))}>
|
|
153
|
+
{children}
|
|
154
|
+
</Text>
|
|
155
|
+
) : (
|
|
156
|
+
children
|
|
157
|
+
)}
|
|
158
|
+
</Pressable>
|
|
159
|
+
</TabsPrimitive.Trigger>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function TabsContent({ className, children, ...props }: TabsContentProps) {
|
|
164
|
+
const variant = useTabsVariant();
|
|
165
|
+
|
|
166
|
+
return (
|
|
167
|
+
<TabsPrimitive.Content asChild {...props}>
|
|
168
|
+
<View className={cn(variant === "filter" ? "gap-8" : "pt-2", className)}>
|
|
169
|
+
{children}
|
|
170
|
+
</View>
|
|
171
|
+
</TabsPrimitive.Content>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export { Tabs, TabsContent, TabsList, TabsTrigger, tabsTriggerVariants };
|
|
176
|
+
export type {
|
|
177
|
+
TabsContentProps,
|
|
178
|
+
TabsListProps,
|
|
179
|
+
TabsProps,
|
|
180
|
+
TabsTriggerProps,
|
|
181
|
+
TabsVariant,
|
|
182
|
+
};
|
package/src/components/Tag.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ReactNode, type ReactElement } from "react";
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, type ViewProps } from "react-native";
|
|
3
|
+
|
|
4
|
+
import { Text } from "@/components/Text";
|
|
3
5
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
6
|
import { cn } from "@/lib/utils";
|
|
5
7
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { forwardRef, type ComponentProps } from 'react';
|
|
2
|
+
import { Text as RNText, type TextProps as RNTextProps } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Maps Medway UI token weight class names → expo-font family keys.
|
|
8
|
+
* RN cannot pick a weight inside a single "Montserrat" family the way the web does.
|
|
9
|
+
*/
|
|
10
|
+
const FONT_BY_WEIGHT_CLASS: Record<string, string> = {
|
|
11
|
+
'font-thin': 'MontserratLight',
|
|
12
|
+
'font-extralight': 'MontserratLight',
|
|
13
|
+
'font-light': 'MontserratLight',
|
|
14
|
+
'font-normal': 'Montserrat',
|
|
15
|
+
'font-regular': 'Montserrat',
|
|
16
|
+
'font-medium': 'MontserratMedium',
|
|
17
|
+
'font-semibold': 'MontserratSemiBold',
|
|
18
|
+
'font-bold': 'MontserratBold',
|
|
19
|
+
'font-extrabold': 'MontserratExtraBold',
|
|
20
|
+
'font-black': 'MontserratBlack',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
function resolveMontserratFamily(className?: string): string {
|
|
24
|
+
if (!className) {
|
|
25
|
+
return 'Montserrat';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const tokens = className.split(/\s+/);
|
|
29
|
+
for (let i = tokens.length - 1; i >= 0; i -= 1) {
|
|
30
|
+
const family = FONT_BY_WEIGHT_CLASS[tokens[i]];
|
|
31
|
+
if (family) {
|
|
32
|
+
return family;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return 'Montserrat';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type TextProps = RNTextProps & {
|
|
40
|
+
className?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* NativeWind Text that always applies the Montserrat file for the token weight
|
|
45
|
+
* class (font-medium → MontserratMedium, etc.). Last style entry wins over
|
|
46
|
+
* className-derived styles so RN actually loads the correct TTF.
|
|
47
|
+
*/
|
|
48
|
+
const Text = forwardRef<RNText, TextProps>(function Text(
|
|
49
|
+
{ className, style, ...props },
|
|
50
|
+
ref,
|
|
51
|
+
) {
|
|
52
|
+
const fontFamily = resolveMontserratFamily(className);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<RNText
|
|
56
|
+
ref={ref}
|
|
57
|
+
className={cn(className)}
|
|
58
|
+
style={[style, { fontFamily }]}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export { Text, resolveMontserratFamily, FONT_BY_WEIGHT_CLASS };
|
|
65
|
+
export type { TextProps };
|
|
66
|
+
export type TextComponentProps = ComponentProps<typeof Text>;
|
package/src/components/Toast.tsx
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { useState, useEffect, type ReactElement, type ReactNode } from "react";
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, Pressable, type ViewProps } from "react-native";
|
|
3
|
+
|
|
4
|
+
import { Text } from "@/components/Text";
|
|
3
5
|
import { cva } from "class-variance-authority";
|
|
4
6
|
import Animated, {
|
|
5
7
|
useSharedValue,
|
|
@@ -1,46 +1,77 @@
|
|
|
1
|
-
import { useColorScheme, useUnstableNativeVariable } from
|
|
1
|
+
import { useColorScheme, useUnstableNativeVariable } from 'nativewind';
|
|
2
2
|
|
|
3
3
|
/** Token sem prefixo `--color-` (ex.: `gray-foreground`, `primary-background-fill`). */
|
|
4
4
|
type ThemeColorToken = string;
|
|
5
5
|
|
|
6
6
|
/** Fallback quando NativeWind não resolve cadeias `var()` — light mode. */
|
|
7
7
|
const LIGHT_COLOR_ALIAS_MAP: Record<string, string> = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
8
|
+
'content-title': 'primary',
|
|
9
|
+
'content-paragraph': 'gray-600',
|
|
10
|
+
'gray-foreground': 'gray-600',
|
|
11
|
+
'primary-foreground': 'primary',
|
|
12
|
+
'secondary-foreground': 'secondary-darken-3',
|
|
13
|
+
'secondary-stroke-emphasis': 'secondary-darken-1',
|
|
14
|
+
'surface-card': 'white',
|
|
15
|
+
'gray-foreground-muted': 'gray-450',
|
|
16
|
+
'gray-stroke-muted': 'gray-100',
|
|
17
|
+
'gray-background-fill-muted': 'gray-400',
|
|
18
|
+
'gray-background-soft-muted': 'gray-30',
|
|
19
|
+
'primary-foreground-onfill': 'white',
|
|
20
|
+
'primary-background-fill': 'primary',
|
|
21
|
+
'red-foreground': 'red-darken-2',
|
|
22
|
+
'go-foreground': 'go-darken-1',
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
/** Fallback — dark mode (espelha tokens.css `.dark`). */
|
|
23
26
|
const DARK_COLOR_ALIAS_MAP: Record<string, string> = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
'content-title': 'white',
|
|
28
|
+
'content-paragraph': 'gray-150',
|
|
29
|
+
'gray-foreground': 'gray-100',
|
|
30
|
+
'primary-foreground': 'gray-100',
|
|
31
|
+
'secondary-foreground': 'secondary-lighten-1',
|
|
32
|
+
'secondary-stroke-emphasis': 'secondary',
|
|
33
|
+
'surface-card': 'gray-850',
|
|
34
|
+
'gray-foreground-muted': 'gray-150',
|
|
35
|
+
'gray-stroke-muted': 'gray-700',
|
|
36
|
+
'gray-background-fill-muted': 'gray-300',
|
|
37
|
+
'gray-background-soft-muted': 'gray-700',
|
|
38
|
+
'primary-foreground-onfill': 'primary',
|
|
39
|
+
'primary-background-fill': 'gray-70',
|
|
40
|
+
'red-foreground': 'red-lighten-3',
|
|
41
|
+
'go-foreground': 'go-lighten-5',
|
|
36
42
|
};
|
|
37
43
|
|
|
44
|
+
/** Fallback estático quando NativeWind não resolve `var(--color-*)` encadeado. */
|
|
45
|
+
const THEME_COLOR_FALLBACKS: Record<string, string> = {
|
|
46
|
+
white: '#FFFFFF',
|
|
47
|
+
primary: 'rgba(0, 32, 91, 1)',
|
|
48
|
+
'gray-600': 'rgba(49, 57, 73, 1)',
|
|
49
|
+
'gray-450': 'rgba(90, 105, 135, 1)',
|
|
50
|
+
'gray-400': 'rgba(122, 133, 151, 1)',
|
|
51
|
+
'gray-100': 'rgba(231, 233, 239, 1)',
|
|
52
|
+
'gray-30': 'rgba(249, 250, 251, 1)',
|
|
53
|
+
'gray-150': 'rgba(206, 211, 222, 1)',
|
|
54
|
+
'gray-300': 'rgba(133, 146, 173, 1)',
|
|
55
|
+
'gray-700': 'rgba(33, 38, 49, 1)',
|
|
56
|
+
'gray-850': 'rgba(16, 19, 24, 1)',
|
|
57
|
+
'gray-70': 'rgba(240, 241, 245, 1)',
|
|
58
|
+
'red-darken-2': 'rgba(182, 27, 45, 1)',
|
|
59
|
+
'red-lighten-3': 'rgba(231, 131, 142, 1)',
|
|
60
|
+
'go-darken-1': 'rgba(141, 22, 77, 1)',
|
|
61
|
+
'go-lighten-5': 'rgba(237, 187, 192, 1)',
|
|
62
|
+
'secondary-darken-1': 'rgba(7, 171, 149, 1)',
|
|
63
|
+
'secondary-darken-3': 'rgba(13, 104, 92, 1)',
|
|
64
|
+
'secondary-lighten-1': 'rgba(22, 208, 118, 1)',
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const DEFAULT_COLOR = '#3B4958';
|
|
68
|
+
|
|
38
69
|
function toCssVariable(token: ThemeColorToken): string {
|
|
39
|
-
return token.startsWith(
|
|
70
|
+
return token.startsWith('--') ? token : `--color-${token}`;
|
|
40
71
|
}
|
|
41
72
|
|
|
42
73
|
function toTokenName(token: ThemeColorToken): string {
|
|
43
|
-
return token.startsWith(
|
|
74
|
+
return token.startsWith('--color-') ? token.slice('--color-'.length) : token;
|
|
44
75
|
}
|
|
45
76
|
|
|
46
77
|
function toResolvedCssVariable(
|
|
@@ -52,17 +83,31 @@ function toResolvedCssVariable(
|
|
|
52
83
|
}
|
|
53
84
|
|
|
54
85
|
function isResolvedColor(value: unknown): value is string {
|
|
55
|
-
return typeof value ===
|
|
86
|
+
return typeof value === 'string' && !value.startsWith('var(');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function getFallbackColor(
|
|
90
|
+
token: ThemeColorToken,
|
|
91
|
+
aliasMap: Record<string, string>
|
|
92
|
+
): string {
|
|
93
|
+
const tokenName = toTokenName(token);
|
|
94
|
+
const aliasToken = aliasMap[tokenName] ?? tokenName;
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
THEME_COLOR_FALLBACKS[tokenName] ??
|
|
98
|
+
THEME_COLOR_FALLBACKS[aliasToken] ??
|
|
99
|
+
DEFAULT_COLOR
|
|
100
|
+
);
|
|
56
101
|
}
|
|
57
102
|
|
|
58
103
|
/**
|
|
59
104
|
* Resolve uma cor semântica do design system (tokens.native.css) em runtime.
|
|
60
105
|
* Use quando a prop `color` for obrigatória (SVG, stroke Reanimated, etc.).
|
|
61
106
|
*/
|
|
62
|
-
function useThemeColor(token: ThemeColorToken): string
|
|
107
|
+
function useThemeColor(token: ThemeColorToken): string {
|
|
63
108
|
const { colorScheme } = useColorScheme();
|
|
64
109
|
const aliasMap =
|
|
65
|
-
colorScheme ===
|
|
110
|
+
colorScheme === 'dark' ? DARK_COLOR_ALIAS_MAP : LIGHT_COLOR_ALIAS_MAP;
|
|
66
111
|
|
|
67
112
|
const value = useUnstableNativeVariable(toCssVariable(token));
|
|
68
113
|
const resolvedValue = useUnstableNativeVariable(
|
|
@@ -72,8 +117,8 @@ function useThemeColor(token: ThemeColorToken): string | undefined {
|
|
|
72
117
|
if (isResolvedColor(value)) return value;
|
|
73
118
|
if (isResolvedColor(resolvedValue)) return resolvedValue;
|
|
74
119
|
|
|
75
|
-
return
|
|
120
|
+
return getFallbackColor(token, aliasMap);
|
|
76
121
|
}
|
|
77
122
|
|
|
78
|
-
export { useThemeColor, toCssVariable };
|
|
123
|
+
export { useThemeColor, toCssVariable, getFallbackColor, DEFAULT_COLOR };
|
|
79
124
|
export type { ThemeColorToken };
|