@medway-ui/native 1.1.2 → 1.3.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 (244) hide show
  1. package/lib/commonjs/components/Alert.js +5 -4
  2. package/lib/commonjs/components/Alert.js.map +1 -1
  3. package/lib/commonjs/components/Avatar.js +2 -1
  4. package/lib/commonjs/components/Avatar.js.map +1 -1
  5. package/lib/commonjs/components/Badge.js +2 -1
  6. package/lib/commonjs/components/Badge.js.map +1 -1
  7. package/lib/commonjs/components/Button.js +3 -2
  8. package/lib/commonjs/components/Button.js.map +1 -1
  9. package/lib/commonjs/components/CardNews.js +7 -6
  10. package/lib/commonjs/components/CardNews.js.map +1 -1
  11. package/lib/commonjs/components/Carousel.js +122 -0
  12. package/lib/commonjs/components/Carousel.js.map +1 -0
  13. package/lib/commonjs/components/Checkbox.js +11 -2
  14. package/lib/commonjs/components/Checkbox.js.map +1 -1
  15. package/lib/commonjs/components/DropdownMenu.js +225 -0
  16. package/lib/commonjs/components/DropdownMenu.js.map +1 -0
  17. package/lib/commonjs/components/EmptyState.js +19 -20
  18. package/lib/commonjs/components/EmptyState.js.map +1 -1
  19. package/lib/commonjs/components/Feed.js +82 -0
  20. package/lib/commonjs/components/Feed.js.map +1 -0
  21. package/lib/commonjs/components/FeedNotice.js +76 -0
  22. package/lib/commonjs/components/FeedNotice.js.map +1 -0
  23. package/lib/commonjs/components/Input.js +21 -9
  24. package/lib/commonjs/components/Input.js.map +1 -1
  25. package/lib/commonjs/components/InvitePopover.js +196 -0
  26. package/lib/commonjs/components/InvitePopover.js.map +1 -0
  27. package/lib/commonjs/components/Label.js +2 -1
  28. package/lib/commonjs/components/Label.js.map +1 -1
  29. package/lib/commonjs/components/LeaderboardCard.js +58 -0
  30. package/lib/commonjs/components/LeaderboardCard.js.map +1 -0
  31. package/lib/commonjs/components/MemberRow.js +131 -0
  32. package/lib/commonjs/components/MemberRow.js.map +1 -0
  33. package/lib/commonjs/components/PageHeader.js +3 -2
  34. package/lib/commonjs/components/PageHeader.js.map +1 -1
  35. package/lib/commonjs/components/PostForm.js +182 -0
  36. package/lib/commonjs/components/PostForm.js.map +1 -0
  37. package/lib/commonjs/components/PrizeCollection.js +135 -0
  38. package/lib/commonjs/components/PrizeCollection.js.map +1 -0
  39. package/lib/commonjs/components/RadioGroup.js +22 -0
  40. package/lib/commonjs/components/RadioGroup.js.map +1 -1
  41. package/lib/commonjs/components/SectionHeader.js +36 -0
  42. package/lib/commonjs/components/SectionHeader.js.map +1 -0
  43. package/lib/commonjs/components/Switch.js +33 -19
  44. package/lib/commonjs/components/Switch.js.map +1 -1
  45. package/lib/commonjs/components/Tabs.js +156 -0
  46. package/lib/commonjs/components/Tabs.js.map +1 -0
  47. package/lib/commonjs/components/Tag.js +2 -1
  48. package/lib/commonjs/components/Tag.js.map +1 -1
  49. package/lib/commonjs/components/Text.js +60 -0
  50. package/lib/commonjs/components/Text.js.map +1 -0
  51. package/lib/commonjs/components/Toast.js +3 -2
  52. package/lib/commonjs/components/Toast.js.map +1 -1
  53. package/lib/commonjs/components/Tooltip.js +2 -2
  54. package/lib/commonjs/components/Tooltip.js.map +1 -1
  55. package/lib/commonjs/editor/NoteEditor.js +710 -0
  56. package/lib/commonjs/editor/NoteEditor.js.map +1 -0
  57. package/lib/commonjs/editor/editorHtml.generated.js +21 -0
  58. package/lib/commonjs/editor/editorHtml.generated.js.map +1 -0
  59. package/lib/commonjs/editor/index.js +33 -0
  60. package/lib/commonjs/editor/index.js.map +1 -0
  61. package/lib/commonjs/editor/protocol.js +88 -0
  62. package/lib/commonjs/editor/protocol.js.map +1 -0
  63. package/lib/commonjs/hooks/useThemeColor.js +66 -29
  64. package/lib/commonjs/hooks/useThemeColor.js.map +1 -1
  65. package/lib/commonjs/index.js +319 -1
  66. package/lib/commonjs/index.js.map +1 -1
  67. package/lib/commonjs/lib/overlay-host.js +101 -0
  68. package/lib/commonjs/lib/overlay-host.js.map +1 -0
  69. package/lib/commonjs/lib/typography.js +26 -0
  70. package/lib/commonjs/lib/typography.js.map +1 -0
  71. package/lib/commonjs/nativewind-env.d.js +0 -1
  72. package/lib/commonjs/nativewind-env.d.js.map +1 -1
  73. package/lib/module/components/Alert.js +3 -2
  74. package/lib/module/components/Alert.js.map +1 -1
  75. package/lib/module/components/Avatar.js +2 -1
  76. package/lib/module/components/Avatar.js.map +1 -1
  77. package/lib/module/components/Badge.js +2 -1
  78. package/lib/module/components/Badge.js.map +1 -1
  79. package/lib/module/components/Button.js +2 -1
  80. package/lib/module/components/Button.js.map +1 -1
  81. package/lib/module/components/CardNews.js +2 -1
  82. package/lib/module/components/CardNews.js.map +1 -1
  83. package/lib/module/components/Carousel.js +117 -0
  84. package/lib/module/components/Carousel.js.map +1 -0
  85. package/lib/module/components/Checkbox.js +12 -2
  86. package/lib/module/components/Checkbox.js.map +1 -1
  87. package/lib/module/components/DropdownMenu.js +216 -0
  88. package/lib/module/components/DropdownMenu.js.map +1 -0
  89. package/lib/module/components/EmptyState.js +19 -20
  90. package/lib/module/components/EmptyState.js.map +1 -1
  91. package/lib/module/components/Feed.js +77 -0
  92. package/lib/module/components/Feed.js.map +1 -0
  93. package/lib/module/components/FeedNotice.js +73 -0
  94. package/lib/module/components/FeedNotice.js.map +1 -0
  95. package/lib/module/components/Input.js +21 -9
  96. package/lib/module/components/Input.js.map +1 -1
  97. package/lib/module/components/InvitePopover.js +183 -0
  98. package/lib/module/components/InvitePopover.js.map +1 -0
  99. package/lib/module/components/Label.js +2 -1
  100. package/lib/module/components/Label.js.map +1 -1
  101. package/lib/module/components/LeaderboardCard.js +53 -0
  102. package/lib/module/components/LeaderboardCard.js.map +1 -0
  103. package/lib/module/components/MemberRow.js +127 -0
  104. package/lib/module/components/MemberRow.js.map +1 -0
  105. package/lib/module/components/PageHeader.js +2 -1
  106. package/lib/module/components/PageHeader.js.map +1 -1
  107. package/lib/module/components/PostForm.js +174 -0
  108. package/lib/module/components/PostForm.js.map +1 -0
  109. package/lib/module/components/PrizeCollection.js +127 -0
  110. package/lib/module/components/PrizeCollection.js.map +1 -0
  111. package/lib/module/components/RadioGroup.js +21 -1
  112. package/lib/module/components/RadioGroup.js.map +1 -1
  113. package/lib/module/components/SectionHeader.js +33 -0
  114. package/lib/module/components/SectionHeader.js.map +1 -0
  115. package/lib/module/components/Switch.js +34 -20
  116. package/lib/module/components/Switch.js.map +1 -1
  117. package/lib/module/components/Tabs.js +148 -0
  118. package/lib/module/components/Tabs.js.map +1 -0
  119. package/lib/module/components/Tag.js +2 -1
  120. package/lib/module/components/Tag.js.map +1 -1
  121. package/lib/module/components/Text.js +58 -0
  122. package/lib/module/components/Text.js.map +1 -0
  123. package/lib/module/components/Toast.js +2 -1
  124. package/lib/module/components/Toast.js.map +1 -1
  125. package/lib/module/components/Tooltip.js +1 -1
  126. package/lib/module/components/Tooltip.js.map +1 -1
  127. package/lib/module/editor/NoteEditor.js +705 -0
  128. package/lib/module/editor/NoteEditor.js.map +1 -0
  129. package/lib/module/editor/editorHtml.generated.js +17 -0
  130. package/lib/module/editor/editorHtml.generated.js.map +1 -0
  131. package/lib/module/editor/index.js +5 -0
  132. package/lib/module/editor/index.js.map +1 -0
  133. package/lib/module/editor/protocol.js +83 -0
  134. package/lib/module/editor/protocol.js.map +1 -0
  135. package/lib/module/hooks/useThemeColor.js +66 -31
  136. package/lib/module/hooks/useThemeColor.js.map +1 -1
  137. package/lib/module/index.js +33 -3
  138. package/lib/module/index.js.map +1 -1
  139. package/lib/module/lib/overlay-host.js +96 -0
  140. package/lib/module/lib/overlay-host.js.map +1 -0
  141. package/lib/module/lib/typography.js +22 -0
  142. package/lib/module/lib/typography.js.map +1 -0
  143. package/lib/module/nativewind-env.d.js +0 -1
  144. package/lib/module/nativewind-env.d.js.map +1 -1
  145. package/lib/typescript/components/Alert.d.ts.map +1 -1
  146. package/lib/typescript/components/Avatar.d.ts.map +1 -1
  147. package/lib/typescript/components/Badge.d.ts.map +1 -1
  148. package/lib/typescript/components/Button.d.ts.map +1 -1
  149. package/lib/typescript/components/CardNews.d.ts.map +1 -1
  150. package/lib/typescript/components/Carousel.d.ts +29 -0
  151. package/lib/typescript/components/Carousel.d.ts.map +1 -0
  152. package/lib/typescript/components/Checkbox.d.ts.map +1 -1
  153. package/lib/typescript/components/DropdownMenu.d.ts +39 -0
  154. package/lib/typescript/components/DropdownMenu.d.ts.map +1 -0
  155. package/lib/typescript/components/EmptyState.d.ts +1 -1
  156. package/lib/typescript/components/EmptyState.d.ts.map +1 -1
  157. package/lib/typescript/components/Feed.d.ts +22 -0
  158. package/lib/typescript/components/Feed.d.ts.map +1 -0
  159. package/lib/typescript/components/FeedNotice.d.ts +17 -0
  160. package/lib/typescript/components/FeedNotice.d.ts.map +1 -0
  161. package/lib/typescript/components/Input.d.ts +3 -2
  162. package/lib/typescript/components/Input.d.ts.map +1 -1
  163. package/lib/typescript/components/InvitePopover.d.ts +46 -0
  164. package/lib/typescript/components/InvitePopover.d.ts.map +1 -0
  165. package/lib/typescript/components/Label.d.ts.map +1 -1
  166. package/lib/typescript/components/LeaderboardCard.d.ts +16 -0
  167. package/lib/typescript/components/LeaderboardCard.d.ts.map +1 -0
  168. package/lib/typescript/components/MemberRow.d.ts +40 -0
  169. package/lib/typescript/components/MemberRow.d.ts.map +1 -0
  170. package/lib/typescript/components/PageHeader.d.ts.map +1 -1
  171. package/lib/typescript/components/PostForm.d.ts +50 -0
  172. package/lib/typescript/components/PostForm.d.ts.map +1 -0
  173. package/lib/typescript/components/PrizeCollection.d.ts +35 -0
  174. package/lib/typescript/components/PrizeCollection.d.ts.map +1 -0
  175. package/lib/typescript/components/RadioGroup.d.ts +10 -2
  176. package/lib/typescript/components/RadioGroup.d.ts.map +1 -1
  177. package/lib/typescript/components/SectionHeader.d.ts +12 -0
  178. package/lib/typescript/components/SectionHeader.d.ts.map +1 -0
  179. package/lib/typescript/components/Switch.d.ts.map +1 -1
  180. package/lib/typescript/components/Tabs.d.ts +32 -0
  181. package/lib/typescript/components/Tabs.d.ts.map +1 -0
  182. package/lib/typescript/components/Tag.d.ts.map +1 -1
  183. package/lib/typescript/components/Text.d.ts +23 -0
  184. package/lib/typescript/components/Text.d.ts.map +1 -0
  185. package/lib/typescript/components/Toast.d.ts +1 -1
  186. package/lib/typescript/components/Toast.d.ts.map +1 -1
  187. package/lib/typescript/components/Tooltip.d.ts.map +1 -1
  188. package/lib/typescript/editor/NoteEditor.d.ts +82 -0
  189. package/lib/typescript/editor/NoteEditor.d.ts.map +1 -0
  190. package/lib/typescript/editor/editorHtml.generated.d.ts +13 -0
  191. package/lib/typescript/editor/editorHtml.generated.d.ts.map +1 -0
  192. package/lib/typescript/editor/index.d.ts +6 -0
  193. package/lib/typescript/editor/index.d.ts.map +1 -0
  194. package/lib/typescript/editor/protocol.d.ts +153 -0
  195. package/lib/typescript/editor/protocol.d.ts.map +1 -0
  196. package/lib/typescript/hooks/useThemeColor.d.ts +4 -2
  197. package/lib/typescript/hooks/useThemeColor.d.ts.map +1 -1
  198. package/lib/typescript/index.d.ts +28 -4
  199. package/lib/typescript/index.d.ts.map +1 -1
  200. package/lib/typescript/lib/overlay-host.d.ts +23 -0
  201. package/lib/typescript/lib/overlay-host.d.ts.map +1 -0
  202. package/lib/typescript/lib/typography.d.ts +12 -0
  203. package/lib/typescript/lib/typography.d.ts.map +1 -0
  204. package/package.json +36 -3
  205. package/setup/MedwayUiProvider.tsx +15 -3
  206. package/setup/metro.js +27 -5
  207. package/setup/tailwind.js +52 -4
  208. package/setup/tokens.native.css +8 -3
  209. package/src/components/Alert.tsx +4 -2
  210. package/src/components/Avatar.tsx +3 -1
  211. package/src/components/Badge.tsx +3 -1
  212. package/src/components/Button.tsx +3 -7
  213. package/src/components/CardNews.tsx +2 -1
  214. package/src/components/Carousel.tsx +152 -0
  215. package/src/components/Checkbox.tsx +14 -4
  216. package/src/components/DropdownMenu.tsx +312 -0
  217. package/src/components/EmptyState.tsx +21 -23
  218. package/src/components/Feed.tsx +96 -0
  219. package/src/components/FeedNotice.tsx +112 -0
  220. package/src/components/Input.tsx +11 -6
  221. package/src/components/InvitePopover.tsx +240 -0
  222. package/src/components/Label.tsx +3 -1
  223. package/src/components/LeaderboardCard.tsx +70 -0
  224. package/src/components/MemberRow.tsx +157 -0
  225. package/src/components/PageHeader.tsx +3 -1
  226. package/src/components/PostForm.tsx +250 -0
  227. package/src/components/PrizeCollection.tsx +190 -0
  228. package/src/components/RadioGroup.tsx +32 -3
  229. package/src/components/SectionHeader.tsx +45 -0
  230. package/src/components/Switch.tsx +65 -59
  231. package/src/components/Tabs.tsx +182 -0
  232. package/src/components/Tag.tsx +3 -1
  233. package/src/components/Text.tsx +66 -0
  234. package/src/components/Toast.tsx +3 -1
  235. package/src/components/Tooltip.tsx +2 -1
  236. package/src/editor/NoteEditor.tsx +802 -0
  237. package/src/editor/editorHtml.generated.ts +14 -0
  238. package/src/editor/index.ts +13 -0
  239. package/src/editor/protocol.ts +184 -0
  240. package/src/hooks/useThemeColor.ts +77 -32
  241. package/src/index.ts +153 -6
  242. package/src/lib/overlay-host.tsx +102 -0
  243. package/src/lib/typography.ts +21 -0
  244. package/src/nativewind-env.d.ts +2 -0
@@ -0,0 +1,157 @@
1
+ import { cva, type VariantProps } from "class-variance-authority";
2
+ import { type ReactNode } from "react";
3
+ import { View, type ViewProps } from "react-native";
4
+
5
+ import { Text } from "@/components/Text";
6
+
7
+ import { Avatar, AvatarFallback, AvatarImage } from "@/components/Avatar";
8
+ import { RadioGroupItem } from "@/components/RadioGroup";
9
+ import { cn } from "@/lib/utils";
10
+
11
+ const rankIndicatorVariants = cva("size-[22px] rounded-full", {
12
+ variants: {
13
+ rank: {
14
+ 1: "bg-yellow-background-fill",
15
+ 2: "bg-gray-background-fill",
16
+ 3: "bg-warning-background-fill",
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ rank: 1,
21
+ },
22
+ });
23
+
24
+ const memberRowVariants = cva("w-full flex-row items-center p-2", {
25
+ variants: {
26
+ variant: {
27
+ ranked: "",
28
+ selectable: "px-4 py-4",
29
+ },
30
+ highlighted: {
31
+ true: "rounded-md bg-secondary-background-soft",
32
+ false: "",
33
+ },
34
+ },
35
+ defaultVariants: {
36
+ variant: "ranked",
37
+ highlighted: false,
38
+ },
39
+ });
40
+
41
+ interface MemberRowRankedProps extends ViewProps {
42
+ variant?: "ranked";
43
+ rank: 1 | 2 | 3;
44
+ rankLabel: string;
45
+ name: string;
46
+ subtitle?: string;
47
+ avatarSrc?: string;
48
+ avatarAlt?: string;
49
+ avatarFallback?: string;
50
+ highlighted?: boolean;
51
+ leading?: ReactNode;
52
+ value?: never;
53
+ }
54
+
55
+ interface MemberRowSelectableProps extends ViewProps {
56
+ variant: "selectable";
57
+ value: string;
58
+ name: string;
59
+ avatarSrc?: string;
60
+ avatarAlt?: string;
61
+ avatarFallback?: string;
62
+ highlighted?: boolean;
63
+ rank?: never;
64
+ rankLabel?: never;
65
+ subtitle?: never;
66
+ leading?: never;
67
+ }
68
+
69
+ type MemberRowProps = MemberRowRankedProps | MemberRowSelectableProps;
70
+
71
+ function getInitials(name: string): string {
72
+ return name
73
+ .trim()
74
+ .split(/\s+/)
75
+ .slice(0, 2)
76
+ .map((word) => word[0] ?? "")
77
+ .join("")
78
+ .toUpperCase();
79
+ }
80
+
81
+ function MemberRow({
82
+ className,
83
+ variant = "ranked",
84
+ rank = 1,
85
+ rankLabel,
86
+ name,
87
+ subtitle,
88
+ avatarSrc,
89
+ avatarAlt,
90
+ avatarFallback,
91
+ value,
92
+ highlighted = false,
93
+ leading,
94
+ ...props
95
+ }: MemberRowProps) {
96
+ const initials = avatarFallback ?? getInitials(name);
97
+
98
+ if (variant === "selectable") {
99
+ const selectionValue = (props as MemberRowSelectableProps).value;
100
+
101
+ return (
102
+ <View
103
+ className={cn(memberRowVariants({ variant, highlighted }), className)}
104
+ {...props}
105
+ >
106
+ <View className="min-w-0 flex-1 flex-row items-center gap-4">
107
+ <RadioGroupItem value={selectionValue} size="md" />
108
+ <View className="min-w-0 flex-1 flex-row items-center gap-2">
109
+ <Avatar size="sm" alt={avatarAlt ?? name}>
110
+ {avatarSrc ? <AvatarImage src={avatarSrc} /> : null}
111
+ <AvatarFallback>{initials}</AvatarFallback>
112
+ </Avatar>
113
+ <Text className="text-md font-semibold text-primary-foreground">
114
+ {name}
115
+ </Text>
116
+ </View>
117
+ </View>
118
+ </View>
119
+ );
120
+ }
121
+
122
+ return (
123
+ <View
124
+ className={cn(memberRowVariants({ variant, highlighted }), className)}
125
+ {...props}
126
+ >
127
+ <View className="min-w-0 flex-1 flex-row items-center gap-2">
128
+ {leading}
129
+ <View className={cn(rankIndicatorVariants({ rank }))} />
130
+ <View className="flex-row items-center gap-2">
131
+ {rankLabel ? (
132
+ <Text className="w-7 text-md font-semibold text-primary-foreground">
133
+ {rankLabel}
134
+ </Text>
135
+ ) : null}
136
+ <Avatar size="sm" alt={avatarAlt ?? name}>
137
+ {avatarSrc ? <AvatarImage src={avatarSrc} /> : null}
138
+ <AvatarFallback>{initials}</AvatarFallback>
139
+ </Avatar>
140
+ <View>
141
+ <Text className="text-md font-semibold text-primary-foreground">
142
+ {name}
143
+ </Text>
144
+ {subtitle ? (
145
+ <Text className="text-xs font-medium text-primary-foreground">
146
+ {subtitle}
147
+ </Text>
148
+ ) : null}
149
+ </View>
150
+ </View>
151
+ </View>
152
+ </View>
153
+ );
154
+ }
155
+
156
+ export { MemberRow, memberRowVariants, rankIndicatorVariants };
157
+ export type { MemberRowProps };
@@ -1,5 +1,7 @@
1
1
  import { type ReactNode } from "react";
2
- import { Text, View, type ViewProps } from "react-native";
2
+ import { View, type ViewProps } from "react-native";
3
+
4
+ import { Text } from "@/components/Text";
3
5
 
4
6
  import { cn } from "@/lib/utils";
5
7
 
@@ -0,0 +1,250 @@
1
+ import { type ReactElement, type ReactNode } from "react";
2
+ import { Pressable, TextInput, View, type PressableProps, type TextInputProps, type ViewProps } from "react-native";
3
+
4
+ import { Text } from "@/components/Text";
5
+
6
+ import { Button } from "@/components/Button";
7
+ import { Checkbox } from "@/components/Checkbox";
8
+ import { Input, InputText, inputVariants } from "@/components/Input";
9
+ import { cn } from "@/lib/utils";
10
+
11
+ interface PostFormProps extends ViewProps {
12
+ children?: ReactNode;
13
+ }
14
+
15
+ interface PostFormHeaderProps extends ViewProps {
16
+ title: string;
17
+ submitLabel?: string;
18
+ onSubmitPress?: () => void;
19
+ submitLoading?: boolean;
20
+ submitDisabled?: boolean;
21
+ }
22
+
23
+ interface PostFormMediaPickerProps extends PressableProps {
24
+ icon?: ReactNode;
25
+ accessibilityLabel?: string;
26
+ }
27
+
28
+ interface PostFormDescriptionProps
29
+ extends Omit<TextInputProps, "value" | "defaultValue"> {
30
+ value?: string;
31
+ defaultValue?: string;
32
+ onChangeText?: (value: string) => void;
33
+ maxLength?: number;
34
+ placeholder?: string;
35
+ }
36
+
37
+ interface PostFormDateTimeFieldProps extends ViewProps {
38
+ label?: string;
39
+ value?: string;
40
+ placeholder?: string;
41
+ iconRight?: ReactElement<{ size?: number; strokeWidth?: number }>;
42
+ onPress?: () => void;
43
+ }
44
+
45
+ interface PostFormCheckboxOptionProps extends ViewProps {
46
+ checked?: boolean;
47
+ defaultChecked?: boolean;
48
+ onCheckedChange?: (checked: boolean) => void;
49
+ title: string;
50
+ description?: string;
51
+ disabled?: boolean;
52
+ }
53
+
54
+ function PostForm({ className, children, ...props }: PostFormProps) {
55
+ return (
56
+ <View className={cn("gap-6", className)} {...props}>
57
+ {children}
58
+ </View>
59
+ );
60
+ }
61
+
62
+ function PostFormHeader({
63
+ className,
64
+ title,
65
+ submitLabel = "Publicar",
66
+ onSubmitPress,
67
+ submitLoading,
68
+ submitDisabled,
69
+ ...props
70
+ }: PostFormHeaderProps) {
71
+ return (
72
+ <View
73
+ className={cn("flex-row items-center justify-between", className)}
74
+ {...props}
75
+ >
76
+ <Text className="text-title-xs font-semibold text-primary-foreground">
77
+ {title}
78
+ </Text>
79
+ {onSubmitPress ? (
80
+ <Button
81
+ variant="regular"
82
+ size="md"
83
+ onPress={onSubmitPress}
84
+ loading={submitLoading}
85
+ disabled={submitDisabled}
86
+ >
87
+ {submitLabel}
88
+ </Button>
89
+ ) : null}
90
+ </View>
91
+ );
92
+ }
93
+
94
+ function PostFormMediaPicker({
95
+ className,
96
+ icon,
97
+ accessibilityLabel = "Adicionar mídia",
98
+ ...props
99
+ }: PostFormMediaPickerProps) {
100
+ return (
101
+ <Pressable
102
+ accessibilityRole="button"
103
+ accessibilityLabel={accessibilityLabel}
104
+ className={cn(
105
+ "h-[162px] w-[138px] self-center items-center justify-center rounded-md border border-gray-stroke-muted bg-gray-stroke-muted",
106
+ className
107
+ )}
108
+ {...props}
109
+ >
110
+ <View className="items-center justify-center rounded-full bg-gray-background-soft p-2.5">
111
+ {icon}
112
+ </View>
113
+ </Pressable>
114
+ );
115
+ }
116
+
117
+ function PostFormDescription({
118
+ className,
119
+ value,
120
+ defaultValue,
121
+ onChangeText,
122
+ maxLength = 120,
123
+ placeholder = "Descrição (opcional)",
124
+ editable = true,
125
+ ...props
126
+ }: PostFormDescriptionProps) {
127
+ const currentLength = (value ?? defaultValue ?? "").length;
128
+
129
+ return (
130
+ <View className={cn("gap-1", className)}>
131
+ <TextInput
132
+ multiline
133
+ textAlignVertical="top"
134
+ maxLength={maxLength}
135
+ value={value}
136
+ defaultValue={defaultValue}
137
+ onChangeText={onChangeText}
138
+ placeholder={placeholder}
139
+ editable={editable}
140
+ className={cn(
141
+ inputVariants({
142
+ size: "lg",
143
+ invalid: false,
144
+ focused: false,
145
+ disabled: !editable,
146
+ }),
147
+ "min-h-12 py-3 font-medium"
148
+ )}
149
+ accessibilityLabel={placeholder}
150
+ {...props}
151
+ style={[{ fontFamily: "MontserratMedium" }, props.style]}
152
+ />
153
+ <InputText className="text-right text-xs font-medium text-gray-foreground">
154
+ {currentLength} / {maxLength}
155
+ </InputText>
156
+ </View>
157
+ );
158
+ }
159
+
160
+ function PostFormDateTimeField({
161
+ className,
162
+ label,
163
+ value,
164
+ placeholder,
165
+ iconRight,
166
+ onPress,
167
+ ...props
168
+ }: PostFormDateTimeFieldProps) {
169
+ return (
170
+ <View className={cn("gap-2", className)} {...props}>
171
+ {label ? (
172
+ <Text className="text-sm font-medium text-gray-foreground">{label}</Text>
173
+ ) : null}
174
+ <Pressable accessibilityRole="button" onPress={onPress} disabled={!onPress}>
175
+ <View pointerEvents="none">
176
+ <Input
177
+ size="lg"
178
+ value={value}
179
+ placeholder={placeholder}
180
+ iconRight={iconRight}
181
+ editable={false}
182
+ />
183
+ </View>
184
+ </Pressable>
185
+ </View>
186
+ );
187
+ }
188
+
189
+ function PostFormCheckboxOption({
190
+ className,
191
+ checked,
192
+ defaultChecked,
193
+ onCheckedChange,
194
+ title,
195
+ description,
196
+ disabled,
197
+ ...props
198
+ }: PostFormCheckboxOptionProps) {
199
+ const isChecked = checked ?? defaultChecked ?? false;
200
+
201
+ const toggle = () => {
202
+ if (disabled) return;
203
+ onCheckedChange?.(!isChecked);
204
+ };
205
+
206
+ return (
207
+ <View
208
+ className={cn("flex-row items-start gap-3", disabled ? "opacity-50" : "", className)}
209
+ {...props}
210
+ >
211
+ <Checkbox
212
+ size="lg"
213
+ checked={checked}
214
+ defaultChecked={defaultChecked}
215
+ onCheckedChange={onCheckedChange}
216
+ disabled={disabled}
217
+ />
218
+ <Pressable
219
+ accessibilityRole="button"
220
+ disabled={disabled}
221
+ onPress={toggle}
222
+ className="min-w-0 flex-1 gap-1 pb-2"
223
+ >
224
+ <Text className="text-md font-semibold text-gray-foreground">{title}</Text>
225
+ {description ? (
226
+ <Text className="text-xs font-medium text-gray-foreground">
227
+ {description}
228
+ </Text>
229
+ ) : null}
230
+ </Pressable>
231
+ </View>
232
+ );
233
+ }
234
+
235
+ export {
236
+ PostForm,
237
+ PostFormCheckboxOption,
238
+ PostFormDateTimeField,
239
+ PostFormDescription,
240
+ PostFormHeader,
241
+ PostFormMediaPicker,
242
+ };
243
+ export type {
244
+ PostFormCheckboxOptionProps,
245
+ PostFormDateTimeFieldProps,
246
+ PostFormDescriptionProps,
247
+ PostFormHeaderProps,
248
+ PostFormMediaPickerProps,
249
+ PostFormProps,
250
+ };
@@ -0,0 +1,190 @@
1
+ import { type ReactNode } from "react";
2
+ import { Image, View, type ViewProps } from "react-native";
3
+
4
+ import { Text } from "@/components/Text";
5
+
6
+ import { cn } from "@/lib/utils";
7
+
8
+ interface PrizeCollectionProps extends ViewProps {
9
+ title?: string;
10
+ statsTitle?: string;
11
+ children?: ReactNode;
12
+ footer?: ReactNode;
13
+ }
14
+
15
+ interface PrizeCollectionStatsProps extends ViewProps {
16
+ children?: ReactNode;
17
+ }
18
+
19
+ interface PrizeCollectionStatsItemProps extends ViewProps {
20
+ count: number | string;
21
+ rank: 1 | 2 | 3;
22
+ }
23
+
24
+ interface PrizeShelfProps extends ViewProps {
25
+ title?: string;
26
+ children?: ReactNode;
27
+ }
28
+
29
+ interface PrizeItemProps extends ViewProps {
30
+ imageSrc?: string;
31
+ image?: ReactNode;
32
+ dateLabel?: string;
33
+ isNew?: boolean;
34
+ locked?: boolean;
35
+ }
36
+
37
+ const rankColors: Record<1 | 2 | 3, string> = {
38
+ 1: "bg-yellow-background-fill",
39
+ 2: "bg-gray-background-fill",
40
+ 3: "bg-warning-background-fill",
41
+ };
42
+
43
+ function PrizeCollection({
44
+ className,
45
+ title = "Sua coleção",
46
+ statsTitle = "Contagem de pódios",
47
+ children,
48
+ footer,
49
+ ...props
50
+ }: PrizeCollectionProps) {
51
+ return (
52
+ <View className={cn("gap-3", className)} {...props}>
53
+ <Text className="text-title-xs font-semibold text-primary-foreground">
54
+ {title}
55
+ </Text>
56
+ <View className="gap-8">
57
+ <View className="gap-3 rounded-lg border border-gray-stroke-muted bg-surface-section p-4">
58
+ <Text className="text-center text-lg font-medium text-primary-foreground">
59
+ {statsTitle}
60
+ </Text>
61
+ {children}
62
+ </View>
63
+ {footer}
64
+ </View>
65
+ </View>
66
+ );
67
+ }
68
+
69
+ function PrizeCollectionStats({
70
+ className,
71
+ children,
72
+ ...props
73
+ }: PrizeCollectionStatsProps) {
74
+ return (
75
+ <View
76
+ className={cn("flex-row items-center justify-center gap-4", className)}
77
+ {...props}
78
+ >
79
+ {children}
80
+ </View>
81
+ );
82
+ }
83
+
84
+ function PrizeCollectionStatsItem({
85
+ className,
86
+ count,
87
+ rank,
88
+ ...props
89
+ }: PrizeCollectionStatsItemProps) {
90
+ return (
91
+ <View
92
+ className={cn(
93
+ "flex-row items-center gap-2 rounded-pill bg-gray-background-soft-emphasis py-1 pl-4 pr-1",
94
+ className
95
+ )}
96
+ {...props}
97
+ >
98
+ <Text className="text-title-xs font-semibold text-primary-foreground">
99
+ {count}
100
+ </Text>
101
+ <View className={cn("size-8 rounded-full", rankColors[rank])} />
102
+ </View>
103
+ );
104
+ }
105
+
106
+ function PrizeShelf({
107
+ className,
108
+ title = "Prateleira de Prêmios",
109
+ children,
110
+ ...props
111
+ }: PrizeShelfProps) {
112
+ return (
113
+ <View className={cn("gap-4", className)} {...props}>
114
+ <Text className="text-lg font-medium text-primary-foreground">
115
+ {title}
116
+ </Text>
117
+ <View className="gap-2">{children}</View>
118
+ </View>
119
+ );
120
+ }
121
+
122
+ function PrizeRow({ className, ...props }: ViewProps) {
123
+ return (
124
+ <View
125
+ className={cn("flex-row items-start justify-between", className)}
126
+ {...props}
127
+ />
128
+ );
129
+ }
130
+
131
+ function PrizeItem({
132
+ className,
133
+ imageSrc,
134
+ image,
135
+ dateLabel,
136
+ isNew = false,
137
+ locked = false,
138
+ ...props
139
+ }: PrizeItemProps) {
140
+ return (
141
+ <View
142
+ className={cn(
143
+ "relative w-[116px] items-center gap-1 rounded-lg px-4 py-2 shadow-sm",
144
+ locked ? "opacity-50" : "bg-surface-card",
145
+ className
146
+ )}
147
+ {...props}
148
+ >
149
+ {isNew ? (
150
+ <View className="absolute -right-1 -top-1 rounded-md bg-green-background-fill px-2 py-1">
151
+ <Text className="text-xs font-semibold text-green-foreground-onfill">
152
+ Novo
153
+ </Text>
154
+ </View>
155
+ ) : null}
156
+ {image ??
157
+ (imageSrc ? (
158
+ <Image
159
+ source={{ uri: imageSrc }}
160
+ className="h-[112px] w-[96px]"
161
+ resizeMode="contain"
162
+ accessibilityLabel={dateLabel ?? "Prêmio"}
163
+ />
164
+ ) : (
165
+ <View className="h-[112px] w-[96px] rounded-lg bg-gray-background-soft" />
166
+ ))}
167
+ {dateLabel ? (
168
+ <Text className="text-xs font-semibold text-gray-stroke-emphasis">
169
+ {dateLabel}
170
+ </Text>
171
+ ) : null}
172
+ </View>
173
+ );
174
+ }
175
+
176
+ export {
177
+ PrizeCollection,
178
+ PrizeCollectionStats,
179
+ PrizeCollectionStatsItem,
180
+ PrizeShelf,
181
+ PrizeRow,
182
+ PrizeItem,
183
+ };
184
+ export type {
185
+ PrizeCollectionProps,
186
+ PrizeCollectionStatsItemProps,
187
+ PrizeCollectionStatsProps,
188
+ PrizeItemProps,
189
+ PrizeShelfProps,
190
+ };
@@ -1,6 +1,7 @@
1
- import { View } from "react-native";
1
+ import { View, type ViewProps } from "react-native";
2
2
  import * as RadioGroupPrimitive from "@rn-primitives/radio-group";
3
3
  import { cva, type VariantProps } from "class-variance-authority";
4
+ import { type ReactNode } from "react";
4
5
  import { cn } from "@/lib/utils";
5
6
 
6
7
  interface RadioGroupItemProps
@@ -58,5 +59,33 @@ function RadioGroupItem({ className, size = "md", variant, ...props }: RadioGrou
58
59
  );
59
60
  }
60
61
 
61
- export { RadioGroup, RadioGroupItem, radioGroupVariants };
62
- export type { RadioGroupItemProps };
62
+ interface RadioGroupListProps extends RadioGroupPrimitive.RootProps {
63
+ className?: string;
64
+ children?: ReactNode;
65
+ }
66
+
67
+ function RadioGroupList({ className, children, ...props }: RadioGroupListProps) {
68
+ return (
69
+ <RadioGroupPrimitive.Root className={cn("gap-0", className)} {...props}>
70
+ {children}
71
+ </RadioGroupPrimitive.Root>
72
+ );
73
+ }
74
+
75
+ function RadioGroupListItem({ className, ...props }: ViewProps) {
76
+ return (
77
+ <View
78
+ className={cn("border-b border-gray-stroke-muted py-2", className)}
79
+ {...props}
80
+ />
81
+ );
82
+ }
83
+
84
+ export {
85
+ RadioGroup,
86
+ RadioGroupItem,
87
+ RadioGroupList,
88
+ RadioGroupListItem,
89
+ radioGroupVariants,
90
+ };
91
+ export type { RadioGroupItemProps, RadioGroupListProps };
@@ -0,0 +1,45 @@
1
+ import { type ReactNode } from "react";
2
+ import { View, type ViewProps } from "react-native";
3
+
4
+ import { Text } from "@/components/Text";
5
+
6
+ import { cn } from "@/lib/utils";
7
+
8
+ interface SectionHeaderProps extends ViewProps {
9
+ title: string;
10
+ subtitle?: string | number;
11
+ /** Right-side actions (buttons, menus, etc.). */
12
+ trailing?: ReactNode;
13
+ }
14
+
15
+ function SectionHeader({
16
+ className,
17
+ title,
18
+ subtitle,
19
+ trailing,
20
+ ...props
21
+ }: SectionHeaderProps) {
22
+ return (
23
+ <View
24
+ className={cn("flex-row items-center justify-between px-1", className)}
25
+ {...props}
26
+ >
27
+ <View className="min-w-0 flex-1 gap-0">
28
+ <Text className="text-title-xs font-semibold text-primary-foreground">
29
+ {title}
30
+ </Text>
31
+ {subtitle != null ? (
32
+ <Text className="text-sm font-medium leading-sm text-primary-foreground">
33
+ {subtitle}
34
+ </Text>
35
+ ) : null}
36
+ </View>
37
+ {trailing ? (
38
+ <View className="flex-row items-center gap-4">{trailing}</View>
39
+ ) : null}
40
+ </View>
41
+ );
42
+ }
43
+
44
+ export { SectionHeader };
45
+ export type { SectionHeaderProps };