@medway-ui/native 1.6.1 → 1.7.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 (223) hide show
  1. package/README.md +27 -2
  2. package/lib/commonjs/components/Alert.js +3 -1
  3. package/lib/commonjs/components/Alert.js.map +1 -1
  4. package/lib/commonjs/components/AlertDialog.js +5 -2
  5. package/lib/commonjs/components/AlertDialog.js.map +1 -1
  6. package/lib/commonjs/components/Badge.js +37 -2
  7. package/lib/commonjs/components/Badge.js.map +1 -1
  8. package/lib/commonjs/components/Button.js +32 -1
  9. package/lib/commonjs/components/Button.js.map +1 -1
  10. package/lib/commonjs/components/Carousel.js +12 -2
  11. package/lib/commonjs/components/Carousel.js.map +1 -1
  12. package/lib/commonjs/components/Checkbox.js +2 -0
  13. package/lib/commonjs/components/Checkbox.js.map +1 -1
  14. package/lib/commonjs/components/Chip.js +208 -0
  15. package/lib/commonjs/components/Chip.js.map +1 -0
  16. package/lib/commonjs/components/Choice.js +116 -0
  17. package/lib/commonjs/components/Choice.js.map +1 -0
  18. package/lib/commonjs/components/Dialog.js +27 -16
  19. package/lib/commonjs/components/Dialog.js.map +1 -1
  20. package/lib/commonjs/components/DropdownMenu.js +73 -57
  21. package/lib/commonjs/components/DropdownMenu.js.map +1 -1
  22. package/lib/commonjs/components/EmptyState.js +9 -2
  23. package/lib/commonjs/components/EmptyState.js.map +1 -1
  24. package/lib/commonjs/components/Feed.js +7 -3
  25. package/lib/commonjs/components/Feed.js.map +1 -1
  26. package/lib/commonjs/components/Feedback.js +77 -0
  27. package/lib/commonjs/components/Feedback.js.map +1 -0
  28. package/lib/commonjs/components/Filter.js +93 -0
  29. package/lib/commonjs/components/Filter.js.map +1 -0
  30. package/lib/commonjs/components/IndexLevel.js +4 -3
  31. package/lib/commonjs/components/IndexLevel.js.map +1 -1
  32. package/lib/commonjs/components/Input.js +149 -45
  33. package/lib/commonjs/components/Input.js.map +1 -1
  34. package/lib/commonjs/components/InvitePopover.js +4 -1
  35. package/lib/commonjs/components/InvitePopover.js.map +1 -1
  36. package/lib/commonjs/components/MemberRow.js +3 -4
  37. package/lib/commonjs/components/MemberRow.js.map +1 -1
  38. package/lib/commonjs/components/PostForm.js +18 -8
  39. package/lib/commonjs/components/PostForm.js.map +1 -1
  40. package/lib/commonjs/components/PrizeCollection.js +1 -1
  41. package/lib/commonjs/components/RadioGroup.js +7 -0
  42. package/lib/commonjs/components/RadioGroup.js.map +1 -1
  43. package/lib/commonjs/components/Select.js +1 -1
  44. package/lib/commonjs/components/Sheet.js +4 -1
  45. package/lib/commonjs/components/Sheet.js.map +1 -1
  46. package/lib/commonjs/components/Skeleton.js +55 -4
  47. package/lib/commonjs/components/Skeleton.js.map +1 -1
  48. package/lib/commonjs/components/Switch.js +2 -0
  49. package/lib/commonjs/components/Switch.js.map +1 -1
  50. package/lib/commonjs/components/Tabs.js +2 -0
  51. package/lib/commonjs/components/Tabs.js.map +1 -1
  52. package/lib/commonjs/components/Toast.js +355 -79
  53. package/lib/commonjs/components/Toast.js.map +1 -1
  54. package/lib/commonjs/editor/NoteEditor.js +36 -11
  55. package/lib/commonjs/editor/NoteEditor.js.map +1 -1
  56. package/lib/commonjs/editor/editorHtml.generated.js +1 -1
  57. package/lib/commonjs/editor/editorHtml.generated.js.map +1 -1
  58. package/lib/commonjs/hooks/useThemeColor.js +693 -65
  59. package/lib/commonjs/hooks/useThemeColor.js.map +1 -1
  60. package/lib/commonjs/hooks/useTrackedText.js +21 -0
  61. package/lib/commonjs/hooks/useTrackedText.js.map +1 -0
  62. package/lib/commonjs/index.js +46 -0
  63. package/lib/commonjs/index.js.map +1 -1
  64. package/lib/commonjs/lib/optional-deps.js +20 -0
  65. package/lib/commonjs/lib/optional-deps.js.map +1 -0
  66. package/lib/commonjs/lib/touch-target.js +19 -0
  67. package/lib/commonjs/lib/touch-target.js.map +1 -0
  68. package/lib/module/components/Alert.js +3 -1
  69. package/lib/module/components/Alert.js.map +1 -1
  70. package/lib/module/components/AlertDialog.js +5 -2
  71. package/lib/module/components/AlertDialog.js.map +1 -1
  72. package/lib/module/components/Badge.js +36 -2
  73. package/lib/module/components/Badge.js.map +1 -1
  74. package/lib/module/components/Button.js +32 -1
  75. package/lib/module/components/Button.js.map +1 -1
  76. package/lib/module/components/Carousel.js +12 -2
  77. package/lib/module/components/Carousel.js.map +1 -1
  78. package/lib/module/components/Checkbox.js +2 -0
  79. package/lib/module/components/Checkbox.js.map +1 -1
  80. package/lib/module/components/Chip.js +204 -0
  81. package/lib/module/components/Chip.js.map +1 -0
  82. package/lib/module/components/Choice.js +112 -0
  83. package/lib/module/components/Choice.js.map +1 -0
  84. package/lib/module/components/Dialog.js +28 -17
  85. package/lib/module/components/Dialog.js.map +1 -1
  86. package/lib/module/components/DropdownMenu.js +74 -58
  87. package/lib/module/components/DropdownMenu.js.map +1 -1
  88. package/lib/module/components/EmptyState.js +9 -2
  89. package/lib/module/components/EmptyState.js.map +1 -1
  90. package/lib/module/components/Feed.js +7 -3
  91. package/lib/module/components/Feed.js.map +1 -1
  92. package/lib/module/components/Feedback.js +74 -0
  93. package/lib/module/components/Feedback.js.map +1 -0
  94. package/lib/module/components/Filter.js +89 -0
  95. package/lib/module/components/Filter.js.map +1 -0
  96. package/lib/module/components/IndexLevel.js +4 -3
  97. package/lib/module/components/IndexLevel.js.map +1 -1
  98. package/lib/module/components/Input.js +149 -45
  99. package/lib/module/components/Input.js.map +1 -1
  100. package/lib/module/components/InvitePopover.js +4 -1
  101. package/lib/module/components/InvitePopover.js.map +1 -1
  102. package/lib/module/components/MemberRow.js +3 -4
  103. package/lib/module/components/MemberRow.js.map +1 -1
  104. package/lib/module/components/PostForm.js +18 -8
  105. package/lib/module/components/PostForm.js.map +1 -1
  106. package/lib/module/components/PrizeCollection.js +1 -1
  107. package/lib/module/components/RadioGroup.js +7 -0
  108. package/lib/module/components/RadioGroup.js.map +1 -1
  109. package/lib/module/components/Select.js +1 -1
  110. package/lib/module/components/Sheet.js +4 -1
  111. package/lib/module/components/Sheet.js.map +1 -1
  112. package/lib/module/components/Skeleton.js +56 -5
  113. package/lib/module/components/Skeleton.js.map +1 -1
  114. package/lib/module/components/Switch.js +2 -0
  115. package/lib/module/components/Switch.js.map +1 -1
  116. package/lib/module/components/Tabs.js +2 -0
  117. package/lib/module/components/Tabs.js.map +1 -1
  118. package/lib/module/components/Toast.js +360 -84
  119. package/lib/module/components/Toast.js.map +1 -1
  120. package/lib/module/editor/NoteEditor.js +36 -11
  121. package/lib/module/editor/NoteEditor.js.map +1 -1
  122. package/lib/module/editor/editorHtml.generated.js +1 -1
  123. package/lib/module/editor/editorHtml.generated.js.map +1 -1
  124. package/lib/module/hooks/useThemeColor.js +693 -65
  125. package/lib/module/hooks/useThemeColor.js.map +1 -1
  126. package/lib/module/hooks/useTrackedText.js +18 -0
  127. package/lib/module/hooks/useTrackedText.js.map +1 -0
  128. package/lib/module/index.js +8 -0
  129. package/lib/module/index.js.map +1 -1
  130. package/lib/module/lib/optional-deps.js +16 -0
  131. package/lib/module/lib/optional-deps.js.map +1 -0
  132. package/lib/module/lib/touch-target.js +15 -0
  133. package/lib/module/lib/touch-target.js.map +1 -0
  134. package/lib/typescript/components/Alert.d.ts.map +1 -1
  135. package/lib/typescript/components/AlertDialog.d.ts.map +1 -1
  136. package/lib/typescript/components/Badge.d.ts +1 -1
  137. package/lib/typescript/components/Badge.d.ts.map +1 -1
  138. package/lib/typescript/components/Button.d.ts.map +1 -1
  139. package/lib/typescript/components/Carousel.d.ts +1 -1
  140. package/lib/typescript/components/Carousel.d.ts.map +1 -1
  141. package/lib/typescript/components/Checkbox.d.ts.map +1 -1
  142. package/lib/typescript/components/Chip.d.ts +30 -0
  143. package/lib/typescript/components/Chip.d.ts.map +1 -0
  144. package/lib/typescript/components/Choice.d.ts +17 -0
  145. package/lib/typescript/components/Choice.d.ts.map +1 -0
  146. package/lib/typescript/components/Dialog.d.ts.map +1 -1
  147. package/lib/typescript/components/DropdownMenu.d.ts +0 -7
  148. package/lib/typescript/components/DropdownMenu.d.ts.map +1 -1
  149. package/lib/typescript/components/EmptyState.d.ts +3 -2
  150. package/lib/typescript/components/EmptyState.d.ts.map +1 -1
  151. package/lib/typescript/components/Feed.d.ts.map +1 -1
  152. package/lib/typescript/components/Feedback.d.ts +17 -0
  153. package/lib/typescript/components/Feedback.d.ts.map +1 -0
  154. package/lib/typescript/components/Filter.d.ts +17 -0
  155. package/lib/typescript/components/Filter.d.ts.map +1 -0
  156. package/lib/typescript/components/IndexLevel.d.ts.map +1 -1
  157. package/lib/typescript/components/Input.d.ts +3 -3
  158. package/lib/typescript/components/Input.d.ts.map +1 -1
  159. package/lib/typescript/components/InvitePopover.d.ts.map +1 -1
  160. package/lib/typescript/components/MemberRow.d.ts.map +1 -1
  161. package/lib/typescript/components/PostForm.d.ts.map +1 -1
  162. package/lib/typescript/components/RadioGroup.d.ts.map +1 -1
  163. package/lib/typescript/components/Sheet.d.ts.map +1 -1
  164. package/lib/typescript/components/Skeleton.d.ts +1 -1
  165. package/lib/typescript/components/Skeleton.d.ts.map +1 -1
  166. package/lib/typescript/components/Switch.d.ts.map +1 -1
  167. package/lib/typescript/components/Tabs.d.ts.map +1 -1
  168. package/lib/typescript/components/Tag.d.ts +2 -2
  169. package/lib/typescript/components/ThemedIcon.d.ts +1 -1
  170. package/lib/typescript/components/ThemedIcon.d.ts.map +1 -1
  171. package/lib/typescript/components/Toast.d.ts +24 -13
  172. package/lib/typescript/components/Toast.d.ts.map +1 -1
  173. package/lib/typescript/editor/NoteEditor.d.ts.map +1 -1
  174. package/lib/typescript/editor/editorHtml.generated.d.ts.map +1 -1
  175. package/lib/typescript/hooks/useThemeColor.d.ts +0 -10
  176. package/lib/typescript/hooks/useThemeColor.d.ts.map +1 -1
  177. package/lib/typescript/hooks/useTrackedText.d.ts +6 -0
  178. package/lib/typescript/hooks/useTrackedText.d.ts.map +1 -0
  179. package/lib/typescript/index.d.ts +9 -1
  180. package/lib/typescript/index.d.ts.map +1 -1
  181. package/lib/typescript/lib/optional-deps.d.ts +23 -0
  182. package/lib/typescript/lib/optional-deps.d.ts.map +1 -0
  183. package/lib/typescript/lib/touch-target.d.ts +5 -0
  184. package/lib/typescript/lib/touch-target.d.ts.map +1 -0
  185. package/package.json +6 -1
  186. package/setup/createMedwayUiNavigator.tsx +4 -7
  187. package/setup/metro.js +12 -3
  188. package/src/components/Alert.tsx +3 -1
  189. package/src/components/AlertDialog.tsx +8 -3
  190. package/src/components/Badge.tsx +51 -3
  191. package/src/components/Button.tsx +39 -1
  192. package/src/components/Carousel.tsx +17 -3
  193. package/src/components/Checkbox.tsx +2 -0
  194. package/src/components/Chip.tsx +227 -0
  195. package/src/components/Choice.tsx +139 -0
  196. package/src/components/Dialog.tsx +39 -23
  197. package/src/components/DropdownMenu.tsx +99 -87
  198. package/src/components/EmptyState.tsx +18 -3
  199. package/src/components/Feed.tsx +4 -3
  200. package/src/components/Feedback.tsx +111 -0
  201. package/src/components/Filter.tsx +106 -0
  202. package/src/components/IndexLevel.tsx +8 -10
  203. package/src/components/Input.tsx +142 -54
  204. package/src/components/InvitePopover.tsx +5 -1
  205. package/src/components/MemberRow.tsx +3 -5
  206. package/src/components/PostForm.tsx +16 -9
  207. package/src/components/PrizeCollection.tsx +1 -1
  208. package/src/components/RadioGroup.tsx +8 -0
  209. package/src/components/Select.tsx +1 -1
  210. package/src/components/Sheet.tsx +4 -1
  211. package/src/components/Skeleton.tsx +47 -6
  212. package/src/components/Switch.tsx +2 -0
  213. package/src/components/Tabs.tsx +2 -0
  214. package/src/components/ThemedIcon.tsx +1 -1
  215. package/src/components/Toast.tsx +489 -87
  216. package/src/editor/NoteEditor.tsx +47 -10
  217. package/src/editor/editorHtml.generated.ts +1 -1
  218. package/src/hooks/useThemeColor.ts +757 -64
  219. package/src/hooks/useTrackedText.ts +20 -0
  220. package/src/index.ts +36 -1
  221. package/src/lib/optional-deps.ts +27 -0
  222. package/src/lib/touch-target.ts +12 -0
  223. package/setup/index.tsx +0 -42
@@ -0,0 +1,227 @@
1
+ import { type ReactNode } from "react";
2
+ import { Pressable, View } from "react-native";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+ import { CloseSm } from "@medway-ui/icons/native";
5
+
6
+ import { Text } from "@/components/Text";
7
+ import { ThemedIcon } from "@/components/ThemedIcon";
8
+ import { cn } from "@/lib/utils";
9
+
10
+ const chipVariants = cva(
11
+ "flex-row shrink-0 items-center justify-center rounded-sm",
12
+ {
13
+ variants: {
14
+ size: {
15
+ sm: "gap-2 px-3 py-2",
16
+ md: "gap-2.5 px-3.5 py-2.5",
17
+ lg: "gap-3 px-4 py-3",
18
+ },
19
+ disabled: { true: "", false: "" },
20
+ },
21
+ defaultVariants: { size: "lg", disabled: false },
22
+ }
23
+ );
24
+
25
+ const chipBackgroundVariants = cva("", {
26
+ variants: {
27
+ variant: {
28
+ regular: "bg-primary-background-fill",
29
+ "regular-soft": "bg-primary-background-soft",
30
+ emphasis: "bg-secondary-background-fill",
31
+ "emphasis-soft": "bg-secondary-background-soft",
32
+ gray: "bg-gray-background-fill",
33
+ "gray-soft": "bg-gray-background-soft",
34
+ success: "bg-green-background-fill",
35
+ "success-soft": "bg-green-background-soft",
36
+ error: "bg-red-background-fill",
37
+ "error-soft": "bg-red-background-soft",
38
+ warning: "bg-yellow-background-fill",
39
+ "warning-soft": "bg-yellow-background-soft",
40
+ go: "bg-go-background-fill",
41
+ "go-soft": "bg-go-background-soft",
42
+ cm: "bg-cm-background-fill",
43
+ "cm-soft": "bg-cm-background-soft",
44
+ cir: "bg-cir-background-fill",
45
+ "cir-soft": "bg-cir-background-soft",
46
+ ped: "bg-ped-background-fill",
47
+ "ped-soft": "bg-ped-background-soft",
48
+ prev: "bg-prev-background-fill",
49
+ "prev-soft": "bg-prev-background-soft",
50
+ ia: "bg-secondary-background-fill",
51
+ "ia-soft": "bg-secondary-background-soft",
52
+ },
53
+ disabled: {
54
+ true: "bg-gray-background-soft-muted",
55
+ false: "",
56
+ },
57
+ },
58
+ compoundVariants: [
59
+ {
60
+ variant: undefined,
61
+ disabled: false,
62
+ className: "bg-surface-elevated shadow-sm",
63
+ },
64
+ ],
65
+ defaultVariants: { disabled: false },
66
+ });
67
+
68
+ const chipTextVariants = cva("text-center font-semibold", {
69
+ variants: {
70
+ size: {
71
+ sm: "text-xs",
72
+ md: "text-sm",
73
+ lg: "text-md",
74
+ },
75
+ variant: {
76
+ regular: "text-primary-foreground-onfill",
77
+ "regular-soft": "text-primary-foreground",
78
+ emphasis: "text-secondary-foreground-onfill",
79
+ "emphasis-soft": "text-secondary-foreground",
80
+ gray: "text-gray-foreground-onfill",
81
+ "gray-soft": "text-gray-foreground",
82
+ success: "text-green-foreground-onfill",
83
+ "success-soft": "text-green-foreground",
84
+ error: "text-red-foreground-onfill",
85
+ "error-soft": "text-red-foreground",
86
+ warning: "text-yellow-foreground-onfill",
87
+ "warning-soft": "text-yellow-foreground",
88
+ go: "text-go-foreground-onfill",
89
+ "go-soft": "text-go-foreground",
90
+ cm: "text-cm-foreground-onfill",
91
+ "cm-soft": "text-cm-foreground",
92
+ cir: "text-cir-foreground-onfill",
93
+ "cir-soft": "text-cir-foreground",
94
+ ped: "text-ped-foreground-onfill",
95
+ "ped-soft": "text-ped-foreground",
96
+ prev: "text-prev-foreground-onfill",
97
+ "prev-soft": "text-prev-foreground",
98
+ ia: "text-primary-foreground-onfill",
99
+ "ia-soft": "text-secondary-foreground",
100
+ },
101
+ disabled: {
102
+ true: "font-medium text-gray-foreground-muted",
103
+ false: "",
104
+ },
105
+ },
106
+ compoundVariants: [
107
+ {
108
+ variant: undefined,
109
+ disabled: false,
110
+ className: "text-primary-foreground",
111
+ },
112
+ ],
113
+ defaultVariants: { size: "lg", disabled: false },
114
+ });
115
+
116
+ type ChipSize = NonNullable<VariantProps<typeof chipVariants>["size"]>;
117
+ type ChipVariant = NonNullable<
118
+ VariantProps<typeof chipBackgroundVariants>["variant"]
119
+ >;
120
+
121
+ const CHIP_ICON_SIZE: Record<ChipSize, number> = {
122
+ sm: 16,
123
+ md: 20,
124
+ lg: 24,
125
+ };
126
+
127
+ const CHIP_ICON_COLOR_TOKEN: Record<ChipVariant, string> = {
128
+ regular: "primary-foreground-onfill",
129
+ "regular-soft": "primary-foreground",
130
+ emphasis: "secondary-foreground-onfill",
131
+ "emphasis-soft": "secondary-foreground",
132
+ gray: "gray-foreground-onfill",
133
+ "gray-soft": "gray-foreground",
134
+ success: "green-foreground-onfill",
135
+ "success-soft": "green-foreground",
136
+ error: "red-foreground-onfill",
137
+ "error-soft": "red-foreground",
138
+ warning: "yellow-foreground-onfill",
139
+ "warning-soft": "yellow-foreground",
140
+ go: "go-foreground-onfill",
141
+ "go-soft": "go-foreground",
142
+ cm: "cm-foreground-onfill",
143
+ "cm-soft": "cm-foreground",
144
+ cir: "cir-foreground-onfill",
145
+ "cir-soft": "cir-foreground",
146
+ ped: "ped-foreground-onfill",
147
+ "ped-soft": "ped-foreground",
148
+ prev: "prev-foreground-onfill",
149
+ "prev-soft": "prev-foreground",
150
+ ia: "primary-foreground-onfill",
151
+ "ia-soft": "secondary-foreground",
152
+ };
153
+
154
+ interface ChipProps
155
+ extends Omit<VariantProps<typeof chipVariants>, "disabled"> {
156
+ children: ReactNode;
157
+ variant?: ChipVariant;
158
+ disabled?: boolean;
159
+ onPress?: () => void;
160
+ onDismiss?: () => void;
161
+ dismissAccessibilityLabel?: string;
162
+ className?: string;
163
+ }
164
+
165
+ function Chip({
166
+ children,
167
+ size = "lg",
168
+ variant,
169
+ disabled = false,
170
+ onPress,
171
+ onDismiss,
172
+ dismissAccessibilityLabel,
173
+ className,
174
+ }: ChipProps) {
175
+ const iconSize = CHIP_ICON_SIZE[size ?? "lg"];
176
+ const variantIconColor = variant
177
+ ? CHIP_ICON_COLOR_TOKEN[variant]
178
+ : "primary-foreground";
179
+ const iconColor = disabled ? "gray-foreground-muted" : variantIconColor;
180
+
181
+ const containerClass = cn(
182
+ chipVariants({ size, disabled }),
183
+ chipBackgroundVariants({ variant, disabled }),
184
+ className
185
+ );
186
+
187
+ const content = (
188
+ <>
189
+ <Text className={cn(chipTextVariants({ size, variant, disabled }))}>
190
+ {children}
191
+ </Text>
192
+ {onDismiss ? (
193
+ <Pressable
194
+ onPress={onDismiss}
195
+ disabled={disabled}
196
+ accessibilityRole="button"
197
+ accessibilityLabel={dismissAccessibilityLabel ?? "Remover"}
198
+ hitSlop={6}
199
+ >
200
+ <ThemedIcon
201
+ icon={CloseSm as never}
202
+ size={iconSize}
203
+ colorToken={iconColor}
204
+ />
205
+ </Pressable>
206
+ ) : null}
207
+ </>
208
+ );
209
+
210
+ if (onPress) {
211
+ return (
212
+ <Pressable
213
+ onPress={onPress}
214
+ disabled={disabled}
215
+ accessibilityRole="button"
216
+ className={containerClass}
217
+ >
218
+ {content}
219
+ </Pressable>
220
+ );
221
+ }
222
+
223
+ return <View className={containerClass}>{content}</View>;
224
+ }
225
+
226
+ export { Chip, chipVariants, chipBackgroundVariants, chipTextVariants };
227
+ export type { ChipProps, ChipSize, ChipVariant };
@@ -0,0 +1,139 @@
1
+ import type { ReactNode } from "react";
2
+ import { Pressable, View } from "react-native";
3
+ import * as MedwayIcons from "@medway-ui/icons/native";
4
+
5
+ import { Text } from "@/components/Text";
6
+ import { ThemedIcon } from "@/components/ThemedIcon";
7
+ import { useThemeColor } from "@/hooks/useThemeColor";
8
+ import { cn } from "@/lib/utils";
9
+
10
+ type ChoiceSize = "sm" | "md" | "lg";
11
+
12
+ type ChoiceTheme =
13
+ | "gray"
14
+ | "primary"
15
+ | "secondary"
16
+ | "green"
17
+ | "red"
18
+ | "yellow"
19
+ | "cm"
20
+ | "go"
21
+ | "cir"
22
+ | "ped"
23
+ | "prev";
24
+
25
+ interface ChoiceProps {
26
+ label: string;
27
+ selected?: boolean;
28
+ disabled?: boolean;
29
+ size?: ChoiceSize;
30
+ theme?: ChoiceTheme;
31
+ icon?: ReactNode;
32
+ onPress?: () => void;
33
+ className?: string;
34
+ }
35
+
36
+ const SIZE_MAP: Record<
37
+ ChoiceSize,
38
+ { container: string; text: string; icon: number }
39
+ > = {
40
+ sm: { container: "gap-2 px-3 py-2", text: "text-xs", icon: 16 },
41
+ md: { container: "gap-2.5 px-3.5 py-2.5", text: "text-sm", icon: 20 },
42
+ lg: { container: "gap-3 px-4 py-3", text: "text-base", icon: 24 },
43
+ };
44
+
45
+ const THEME_SELECTED_OUTER_BG: Record<ChoiceTheme, string> = {
46
+ gray: "bg-gray-background-soft",
47
+ primary: "bg-primary-background-fill",
48
+ secondary: "bg-secondary-background-fill",
49
+ green: "bg-green-background-fill",
50
+ red: "bg-red-background-fill",
51
+ yellow: "bg-yellow-background-fill",
52
+ cm: "bg-cm-background-fill",
53
+ go: "bg-go-background-fill",
54
+ cir: "bg-cir-background-fill-emphasis",
55
+ ped: "bg-ped-background-fill-emphasis",
56
+ prev: "bg-prev-background-fill",
57
+ };
58
+
59
+ const THEME_CHECK_COLOR_TOKEN: Record<ChoiceTheme, string> = {
60
+ gray: "secondary-foreground",
61
+ primary: "primary-foreground",
62
+ secondary: "secondary-foreground",
63
+ green: "green-foreground",
64
+ red: "red-foreground",
65
+ yellow: "yellow-foreground",
66
+ cm: "cm-foreground",
67
+ go: "go-foreground",
68
+ cir: "cir-foreground",
69
+ ped: "ped-foreground",
70
+ prev: "prev-foreground",
71
+ };
72
+
73
+ const SHADOW_STYLE = {
74
+ shadowOffset: { width: 0, height: 2 },
75
+ shadowOpacity: 0.08,
76
+ shadowRadius: 4,
77
+ elevation: 2,
78
+ };
79
+
80
+ function Choice({
81
+ label,
82
+ selected = false,
83
+ disabled = false,
84
+ size = "md",
85
+ theme = "gray",
86
+ icon,
87
+ onPress,
88
+ className,
89
+ }: ChoiceProps) {
90
+ const sz = SIZE_MAP[size] ?? SIZE_MAP.md;
91
+ const shadowColor = useThemeColor("gray-700");
92
+
93
+ const outerBg = disabled
94
+ ? "bg-gray-background-soft-muted"
95
+ : selected
96
+ ? THEME_SELECTED_OUTER_BG[theme]
97
+ : "bg-gray-background-soft";
98
+
99
+ const textClass = disabled
100
+ ? "font-medium text-gray-foreground-muted"
101
+ : selected
102
+ ? "font-semibold text-primary-foreground"
103
+ : "font-medium text-gray-foreground";
104
+
105
+ return (
106
+ <Pressable
107
+ onPress={disabled ? undefined : onPress}
108
+ disabled={disabled}
109
+ accessibilityRole="button"
110
+ accessibilityState={{ selected, disabled }}
111
+ className={cn("rounded-md", outerBg, className)}
112
+ style={{ padding: 2 }}
113
+ >
114
+ <View
115
+ className={cn(
116
+ "flex-row items-center justify-center rounded-md",
117
+ sz.container,
118
+ selected ? "bg-surface-card" : "bg-transparent",
119
+ )}
120
+ style={selected ? { ...SHADOW_STYLE, shadowColor } : undefined}
121
+ >
122
+ {icon ? <View className="shrink-0">{icon}</View> : null}
123
+ <Text className={cn("text-center", sz.text, textClass)}>{label}</Text>
124
+ {selected ? (
125
+ <View className="shrink-0">
126
+ <ThemedIcon
127
+ icon={MedwayIcons.Check}
128
+ size={sz.icon}
129
+ colorToken={THEME_CHECK_COLOR_TOKEN[theme]}
130
+ />
131
+ </View>
132
+ ) : null}
133
+ </View>
134
+ </Pressable>
135
+ );
136
+ }
137
+
138
+ export { Choice };
139
+ export type { ChoiceProps, ChoiceTheme };
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode, isValidElement, cloneElement, type ReactElement } from "react";
2
- import { View, Text, ScrollView, type ViewProps } from "react-native";
2
+ import { View, ScrollView, type ViewProps } from "react-native";
3
3
  import * as DialogPrimitive from "@rn-primitives/dialog";
4
4
  import { CloseMd } from "@medway-ui/icons/native";
5
5
  import { useThemeColor } from "@/hooks/useThemeColor";
@@ -43,7 +43,7 @@ function DialogClose({ ...props }: DialogPrimitive.CloseProps) {
43
43
  function DialogOverlay({ className, ...props }: DialogPrimitive.OverlayProps) {
44
44
  return (
45
45
  <DialogPrimitive.Overlay
46
- className={cn("absolute inset-0 bg-black/50", className)}
46
+ className={cn("absolute inset-0 bg-black-48", className)}
47
47
  {...props}
48
48
  />
49
49
  );
@@ -61,7 +61,7 @@ function DialogContainer({
61
61
  return (
62
62
  <DialogPrimitive.Portal>
63
63
  <DialogPrimitive.Overlay
64
- className={cn("absolute inset-0 bg-black/50", overlayClassName)}
64
+ className={cn("absolute inset-0 bg-black-48", overlayClassName)}
65
65
  />
66
66
  <DialogPrimitive.Content
67
67
  className="absolute inset-0 items-center justify-center px-4"
@@ -75,7 +75,12 @@ function DialogContainer({
75
75
  >
76
76
  {children}
77
77
  {showCloseButton && (
78
- <DialogPrimitive.Close className="absolute right-3 top-3 rounded-pill p-1.5 active:bg-gray-background-soft">
78
+ <DialogPrimitive.Close
79
+ accessibilityRole="button"
80
+ accessibilityLabel="Fechar"
81
+ hitSlop={8}
82
+ className="absolute right-3 top-3 rounded-pill p-1.5 active:bg-gray-background-soft"
83
+ >
79
84
  {closeIconColor && <CloseMd width={16} height={16} color={closeIconColor} />}
80
85
  </DialogPrimitive.Close>
81
86
  )}
@@ -131,28 +136,39 @@ function DialogFooter({ className, separator = false, children, ...props }: Dial
131
136
  );
132
137
  }
133
138
 
134
- function DialogTitle({ className, iconLeft, iconRight, children, ...props }: DialogTitleProps) {
135
- const renderIcon = (icon: ReactNode) => {
136
- if (isValidElement(icon)) {
137
- return cloneElement(icon as ReactElement<{ size?: number; strokeWidth?: number }>, {
138
- size: 32,
139
- strokeWidth: 2.2,
140
- });
139
+ const DIALOG_TITLE_ICON_SIZE = 32;
140
+ const DIALOG_TITLE_CLASS_NAME = "text-title-md font-semibold leading-title-md text-content-title";
141
+
142
+ function renderTitleIcon(icon: ReactNode) {
143
+ if (!isValidElement(icon)) return icon;
144
+
145
+ return cloneElement(
146
+ icon as ReactElement<{ width?: number; height?: number; strokeWidth?: number }>,
147
+ {
148
+ width: DIALOG_TITLE_ICON_SIZE,
149
+ height: DIALOG_TITLE_ICON_SIZE,
150
+ strokeWidth: 2.2,
141
151
  }
142
- return icon;
143
- };
152
+ );
153
+ }
154
+
155
+ function DialogTitle({ className, iconLeft, iconRight, children, ...props }: DialogTitleProps) {
156
+ if (!iconLeft && !iconRight) {
157
+ return (
158
+ <DialogPrimitive.Title className={cn(DIALOG_TITLE_CLASS_NAME, className)} {...props}>
159
+ {children}
160
+ </DialogPrimitive.Title>
161
+ );
162
+ }
144
163
 
145
164
  return (
146
- <DialogPrimitive.Title
147
- className={cn("flex-row items-center gap-3", className)}
148
- {...props}
149
- >
150
- {iconLeft && renderIcon(iconLeft)}
151
- <Text className="text-title-md font-semibold leading-title-md text-content-title flex-1">
152
- {children as string}
153
- </Text>
154
- {iconRight && renderIcon(iconRight)}
155
- </DialogPrimitive.Title>
165
+ <View className={cn("flex-row items-center gap-3", className)}>
166
+ {iconLeft ? renderTitleIcon(iconLeft) : null}
167
+ <DialogPrimitive.Title className={cn(DIALOG_TITLE_CLASS_NAME, "flex-1")} {...props}>
168
+ {children}
169
+ </DialogPrimitive.Title>
170
+ {iconRight ? renderTitleIcon(iconRight) : null}
171
+ </View>
156
172
  );
157
173
  }
158
174