@factorialco/f0-react-native 0.19.1

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 (310) hide show
  1. package/README.md +54 -0
  2. package/package.json +84 -0
  3. package/src/components/Activity/ActivityItem/__snapshots__/index.spec.tsx.snap +62 -0
  4. package/src/components/Activity/ActivityItem/index.spec.tsx +103 -0
  5. package/src/components/Activity/ActivityItem/index.tsx +90 -0
  6. package/src/components/Avatars/Avatar.tsx +56 -0
  7. package/src/components/Avatars/BaseAvatar/index.tsx +126 -0
  8. package/src/components/Avatars/BaseAvatar/utils.ts +73 -0
  9. package/src/components/Avatars/CompanyAvatar/__snapshots__/index.spec.tsx.snap +25 -0
  10. package/src/components/Avatars/CompanyAvatar/index.spec.tsx +11 -0
  11. package/src/components/Avatars/CompanyAvatar/index.tsx +36 -0
  12. package/src/components/Avatars/DateAvatar/__snapshots__/index.spec.tsx.snap +18 -0
  13. package/src/components/Avatars/DateAvatar/index.spec.tsx +12 -0
  14. package/src/components/Avatars/DateAvatar/index.tsx +22 -0
  15. package/src/components/Avatars/EmojiAvatar/__snapshots__/index.spec.tsx.snap +37 -0
  16. package/src/components/Avatars/EmojiAvatar/index.spec.tsx +15 -0
  17. package/src/components/Avatars/EmojiAvatar/index.tsx +37 -0
  18. package/src/components/Avatars/FileAvatar/__snapshots__/index.spec.tsx.snap +261 -0
  19. package/src/components/Avatars/FileAvatar/index.spec.tsx +43 -0
  20. package/src/components/Avatars/FileAvatar/index.tsx +117 -0
  21. package/src/components/Avatars/FileAvatar/utils.ts +103 -0
  22. package/src/components/Avatars/IconAvatar/__snapshots__/index.spec.tsx.snap +256 -0
  23. package/src/components/Avatars/IconAvatar/index.spec.tsx +16 -0
  24. package/src/components/Avatars/IconAvatar/index.tsx +31 -0
  25. package/src/components/Avatars/ModuleAvatar/index.tsx +106 -0
  26. package/src/components/Avatars/ModuleAvatar/modules.ts +64 -0
  27. package/src/components/Avatars/PersonAvatar/__snapshots__/index.spec.tsx.snap +25 -0
  28. package/src/components/Avatars/PersonAvatar/index.spec.tsx +13 -0
  29. package/src/components/Avatars/PersonAvatar/index.tsx +38 -0
  30. package/src/components/Avatars/TeamAvatar/__snapshots__/index.spec.tsx.snap +25 -0
  31. package/src/components/Avatars/TeamAvatar/index.spec.tsx +11 -0
  32. package/src/components/Avatars/TeamAvatar/index.tsx +36 -0
  33. package/src/components/Avatars/exports.ts +9 -0
  34. package/src/components/Avatars/types.ts +15 -0
  35. package/src/components/Badge/index.tsx +47 -0
  36. package/src/components/Button/__snapshots__/index.spec.tsx.snap +517 -0
  37. package/src/components/Button/index.spec.tsx +124 -0
  38. package/src/components/Button/index.tsx +233 -0
  39. package/src/components/Counter/__snapshots__/index.spec.tsx.snap +113 -0
  40. package/src/components/Counter/index.spec.tsx +53 -0
  41. package/src/components/Counter/index.tsx +59 -0
  42. package/src/components/ExampleComponent.tsx +22 -0
  43. package/src/components/Icon/README.md +63 -0
  44. package/src/components/Icon/__tests__/Icon.spec.tsx +35 -0
  45. package/src/components/Icon/index.tsx +85 -0
  46. package/src/components/Navigation/PageHeader/__snapshots__/index.spec.tsx.snap +242 -0
  47. package/src/components/Navigation/PageHeader/index.spec.tsx +198 -0
  48. package/src/components/Navigation/PageHeader/index.tsx +53 -0
  49. package/src/components/OneChip/__snapshots__/index.spec.tsx.snap +366 -0
  50. package/src/components/OneChip/index.spec.tsx +69 -0
  51. package/src/components/OneChip/index.tsx +89 -0
  52. package/src/components/OnePreset/__snapshots__/index.spec.tsx.snap +149 -0
  53. package/src/components/OnePreset/index.spec.tsx +46 -0
  54. package/src/components/OnePreset/index.tsx +36 -0
  55. package/src/components/Tags/AlertTab/__snapshots__/index.spec.tsx.snap +292 -0
  56. package/src/components/Tags/AlertTab/index.spec.tsx +18 -0
  57. package/src/components/Tags/AlertTab/index.tsx +61 -0
  58. package/src/components/Tags/BaseTag/index.tsx +64 -0
  59. package/src/components/Tags/DotTag/__snapshots__/index.spec.tsx.snap +1081 -0
  60. package/src/components/Tags/DotTag/index.spec.tsx +14 -0
  61. package/src/components/Tags/DotTag/index.tsx +54 -0
  62. package/src/components/Tags/RawTag/__snapshots__/index.spec.tsx.snap +213 -0
  63. package/src/components/Tags/RawTag/index.spec.tsx +19 -0
  64. package/src/components/Tags/RawTag/index.tsx +41 -0
  65. package/src/components/Tags/Tag.tsx +32 -0
  66. package/src/components/Tags/exports.ts +3 -0
  67. package/src/components/__tests__/ExampleComponent.spec.tsx +16 -0
  68. package/src/components/experimental/Lists/DataList/ItemContainer.tsx +74 -0
  69. package/src/components/experimental/Lists/DataList/actions/CopyAction.tsx +72 -0
  70. package/src/components/experimental/Lists/DataList/actions/GenericAction.tsx +37 -0
  71. package/src/components/experimental/Lists/DataList/index.tsx +186 -0
  72. package/src/components/experimental/Lists/DetailsItem/__snapshots__/index.spec.tsx.snap +759 -0
  73. package/src/components/experimental/Lists/DetailsItem/index.spec.tsx +81 -0
  74. package/src/components/experimental/Lists/DetailsItem/index.tsx +68 -0
  75. package/src/components/experimental/Lists/DetailsItemsList/__snapshots__/index.spec.tsx.snap +671 -0
  76. package/src/components/experimental/Lists/DetailsItemsList/index.spec.tsx +73 -0
  77. package/src/components/experimental/Lists/DetailsItemsList/index.tsx +52 -0
  78. package/src/icons/app/AcademicCap.tsx +31 -0
  79. package/src/icons/app/Add.tsx +21 -0
  80. package/src/icons/app/Ai.tsx +24 -0
  81. package/src/icons/app/Alert.tsx +16 -0
  82. package/src/icons/app/AlertCircle.tsx +19 -0
  83. package/src/icons/app/AlertCircleLine.tsx +17 -0
  84. package/src/icons/app/AlignTextCenter.tsx +21 -0
  85. package/src/icons/app/AlignTextJustify.tsx +21 -0
  86. package/src/icons/app/AlignTextLeft.tsx +21 -0
  87. package/src/icons/app/AlignTextRight.tsx +21 -0
  88. package/src/icons/app/Appearance.tsx +33 -0
  89. package/src/icons/app/Archive.tsx +21 -0
  90. package/src/icons/app/ArchiveOpen.tsx +21 -0
  91. package/src/icons/app/ArrowCycle.tsx +27 -0
  92. package/src/icons/app/ArrowDown.tsx +27 -0
  93. package/src/icons/app/ArrowLeft.tsx +21 -0
  94. package/src/icons/app/ArrowRight.tsx +21 -0
  95. package/src/icons/app/ArrowUp.tsx +21 -0
  96. package/src/icons/app/Bank.tsx +20 -0
  97. package/src/icons/app/BarGraph.tsx +21 -0
  98. package/src/icons/app/Bell.tsx +24 -0
  99. package/src/icons/app/Bold.tsx +23 -0
  100. package/src/icons/app/BookOpen.tsx +21 -0
  101. package/src/icons/app/Briefcase.tsx +18 -0
  102. package/src/icons/app/Bucket.tsx +23 -0
  103. package/src/icons/app/Building.tsx +25 -0
  104. package/src/icons/app/Bullet.tsx +19 -0
  105. package/src/icons/app/Calculator.tsx +17 -0
  106. package/src/icons/app/Calendar.tsx +21 -0
  107. package/src/icons/app/CalendarArrowDown.tsx +21 -0
  108. package/src/icons/app/CalendarArrowLeft.tsx +21 -0
  109. package/src/icons/app/CalendarArrowRight.tsx +21 -0
  110. package/src/icons/app/CameraPlus.tsx +22 -0
  111. package/src/icons/app/ChartLine.tsx +26 -0
  112. package/src/icons/app/ChartPie.tsx +25 -0
  113. package/src/icons/app/Check.tsx +21 -0
  114. package/src/icons/app/CheckCircle.tsx +21 -0
  115. package/src/icons/app/CheckCircleLine.tsx +22 -0
  116. package/src/icons/app/CheckDouble.tsx +21 -0
  117. package/src/icons/app/ChevronDown.tsx +21 -0
  118. package/src/icons/app/ChevronLeft.tsx +21 -0
  119. package/src/icons/app/ChevronRight.tsx +21 -0
  120. package/src/icons/app/ChevronUp.tsx +21 -0
  121. package/src/icons/app/Circle.tsx +16 -0
  122. package/src/icons/app/Clock.tsx +22 -0
  123. package/src/icons/app/Code.tsx +21 -0
  124. package/src/icons/app/Coffee.tsx +24 -0
  125. package/src/icons/app/Comment.tsx +19 -0
  126. package/src/icons/app/Completed.tsx +21 -0
  127. package/src/icons/app/CreditCard.tsx +21 -0
  128. package/src/icons/app/Cross.tsx +21 -0
  129. package/src/icons/app/CrossedCircle.tsx +21 -0
  130. package/src/icons/app/Crown.tsx +21 -0
  131. package/src/icons/app/Delete.tsx +21 -0
  132. package/src/icons/app/Deny.tsx +21 -0
  133. package/src/icons/app/Desktop.tsx +26 -0
  134. package/src/icons/app/DollarBill.tsx +22 -0
  135. package/src/icons/app/DottedCircle.tsx +16 -0
  136. package/src/icons/app/Download.tsx +21 -0
  137. package/src/icons/app/DropdownDefault.tsx +25 -0
  138. package/src/icons/app/DropdownOpen.tsx +25 -0
  139. package/src/icons/app/Ellipsis.tsx +36 -0
  140. package/src/icons/app/EllipsisHorizontal.tsx +18 -0
  141. package/src/icons/app/Envelope.tsx +21 -0
  142. package/src/icons/app/EnvelopeOpen.tsx +23 -0
  143. package/src/icons/app/Exit.tsx +21 -0
  144. package/src/icons/app/ExternalLink.tsx +21 -0
  145. package/src/icons/app/EyeInvisible.tsx +26 -0
  146. package/src/icons/app/EyeVisible.tsx +21 -0
  147. package/src/icons/app/FaceNegative.tsx +21 -0
  148. package/src/icons/app/FaceNeutral.tsx +21 -0
  149. package/src/icons/app/FacePositive.tsx +21 -0
  150. package/src/icons/app/FaceSuperNegative.tsx +21 -0
  151. package/src/icons/app/FaceSuperPositive.tsx +21 -0
  152. package/src/icons/app/Feed.tsx +21 -0
  153. package/src/icons/app/File.tsx +21 -0
  154. package/src/icons/app/FileFilled.tsx +21 -0
  155. package/src/icons/app/Filter.tsx +19 -0
  156. package/src/icons/app/Flag.tsx +21 -0
  157. package/src/icons/app/Folder.tsx +19 -0
  158. package/src/icons/app/Folders.tsx +24 -0
  159. package/src/icons/app/Globe.tsx +26 -0
  160. package/src/icons/app/Graph.tsx +26 -0
  161. package/src/icons/app/Handshake.tsx +29 -0
  162. package/src/icons/app/Heading1.tsx +21 -0
  163. package/src/icons/app/Heading2.tsx +21 -0
  164. package/src/icons/app/Heading3.tsx +21 -0
  165. package/src/icons/app/Heart.tsx +21 -0
  166. package/src/icons/app/HoldHeart.tsx +21 -0
  167. package/src/icons/app/Home.tsx +20 -0
  168. package/src/icons/app/Hub.tsx +51 -0
  169. package/src/icons/app/Image.tsx +21 -0
  170. package/src/icons/app/InProgressTask.tsx +17 -0
  171. package/src/icons/app/Inbox.tsx +26 -0
  172. package/src/icons/app/Info.tsx +21 -0
  173. package/src/icons/app/InfoCircle.tsx +21 -0
  174. package/src/icons/app/InfoCircleLine.tsx +28 -0
  175. package/src/icons/app/Italic.tsx +21 -0
  176. package/src/icons/app/Kanban.tsx +21 -0
  177. package/src/icons/app/Laptop.tsx +20 -0
  178. package/src/icons/app/LayersFront.tsx +26 -0
  179. package/src/icons/app/Lightbulb.tsx +26 -0
  180. package/src/icons/app/Link.tsx +25 -0
  181. package/src/icons/app/LinkRemove.tsx +20 -0
  182. package/src/icons/app/List.tsx +25 -0
  183. package/src/icons/app/LockLocked.tsx +21 -0
  184. package/src/icons/app/LockUnlocked.tsx +21 -0
  185. package/src/icons/app/LogoAvatar.tsx +23 -0
  186. package/src/icons/app/LogoEruditai.tsx +19 -0
  187. package/src/icons/app/LogoTravelperk.tsx +27 -0
  188. package/src/icons/app/Masonry.tsx +19 -0
  189. package/src/icons/app/Maximize.tsx +21 -0
  190. package/src/icons/app/Megaphone.tsx +21 -0
  191. package/src/icons/app/Menu.tsx +21 -0
  192. package/src/icons/app/MessageFrown.tsx +25 -0
  193. package/src/icons/app/MessageHeart.tsx +25 -0
  194. package/src/icons/app/Messages.tsx +21 -0
  195. package/src/icons/app/Microphone.tsx +26 -0
  196. package/src/icons/app/MicrophoneNegative.tsx +26 -0
  197. package/src/icons/app/Minimize.tsx +21 -0
  198. package/src/icons/app/Minus.tsx +21 -0
  199. package/src/icons/app/Mobile.tsx +21 -0
  200. package/src/icons/app/Money.tsx +26 -0
  201. package/src/icons/app/MoneyBag.tsx +24 -0
  202. package/src/icons/app/MoveDown.tsx +44 -0
  203. package/src/icons/app/MoveTop.tsx +34 -0
  204. package/src/icons/app/MoveUp.tsx +42 -0
  205. package/src/icons/app/Office.tsx +31 -0
  206. package/src/icons/app/OlList.tsx +21 -0
  207. package/src/icons/app/PalmTree.tsx +20 -0
  208. package/src/icons/app/Paperclip.tsx +20 -0
  209. package/src/icons/app/PartiallyCompleted.tsx +21 -0
  210. package/src/icons/app/PauseCircle.tsx +21 -0
  211. package/src/icons/app/Pencil.tsx +21 -0
  212. package/src/icons/app/People.tsx +27 -0
  213. package/src/icons/app/Person.tsx +22 -0
  214. package/src/icons/app/Phone.tsx +20 -0
  215. package/src/icons/app/Pin.tsx +22 -0
  216. package/src/icons/app/PixBrazil.tsx +19 -0
  217. package/src/icons/app/Placeholder.tsx +21 -0
  218. package/src/icons/app/Plane.tsx +21 -0
  219. package/src/icons/app/Plus.tsx +21 -0
  220. package/src/icons/app/Present.tsx +31 -0
  221. package/src/icons/app/Printer.tsx +26 -0
  222. package/src/icons/app/Proyector.tsx +22 -0
  223. package/src/icons/app/Question.tsx +22 -0
  224. package/src/icons/app/Quote.tsx +21 -0
  225. package/src/icons/app/Reaction.tsx +32 -0
  226. package/src/icons/app/Receipt.tsx +20 -0
  227. package/src/icons/app/Record.tsx +17 -0
  228. package/src/icons/app/RemoveFavorite.tsx +21 -0
  229. package/src/icons/app/Replace.tsx +21 -0
  230. package/src/icons/app/Reset.tsx +27 -0
  231. package/src/icons/app/Rocket.tsx +26 -0
  232. package/src/icons/app/Salad.tsx +21 -0
  233. package/src/icons/app/Save.tsx +27 -0
  234. package/src/icons/app/Schedule.tsx +32 -0
  235. package/src/icons/app/Search.tsx +17 -0
  236. package/src/icons/app/SearchPerson.tsx +24 -0
  237. package/src/icons/app/Settings.tsx +20 -0
  238. package/src/icons/app/Share.tsx +27 -0
  239. package/src/icons/app/Sliders.tsx +22 -0
  240. package/src/icons/app/SolidPause.tsx +19 -0
  241. package/src/icons/app/SolidPlay.tsx +19 -0
  242. package/src/icons/app/SolidStop.tsx +19 -0
  243. package/src/icons/app/Sort.tsx +21 -0
  244. package/src/icons/app/Sparkles.tsx +25 -0
  245. package/src/icons/app/Spinner.tsx +20 -0
  246. package/src/icons/app/Split.tsx +21 -0
  247. package/src/icons/app/Star.tsx +21 -0
  248. package/src/icons/app/StarFilled.tsx +19 -0
  249. package/src/icons/app/Strikethrough.tsx +21 -0
  250. package/src/icons/app/Suitcase.tsx +22 -0
  251. package/src/icons/app/Table.tsx +21 -0
  252. package/src/icons/app/Target.tsx +31 -0
  253. package/src/icons/app/TextSize.tsx +21 -0
  254. package/src/icons/app/Timer.tsx +27 -0
  255. package/src/icons/app/Underline.tsx +26 -0
  256. package/src/icons/app/Upload.tsx +21 -0
  257. package/src/icons/app/Video.tsx +23 -0
  258. package/src/icons/app/VideoRecorder.tsx +31 -0
  259. package/src/icons/app/VideoRecorderNegative.tsx +22 -0
  260. package/src/icons/app/Wallet.tsx +26 -0
  261. package/src/icons/app/Warning.tsx +21 -0
  262. package/src/icons/app/WhatsappChat.tsx +23 -0
  263. package/src/icons/app/Windows.tsx +21 -0
  264. package/src/icons/app/index.ts +186 -0
  265. package/src/icons/index.ts +5 -0
  266. package/src/icons/modules/Benefits.tsx +25 -0
  267. package/src/icons/modules/Calendar.tsx +21 -0
  268. package/src/icons/modules/Cards.tsx +25 -0
  269. package/src/icons/modules/ClockIn.tsx +21 -0
  270. package/src/icons/modules/Discover.tsx +25 -0
  271. package/src/icons/modules/Documents.tsx +19 -0
  272. package/src/icons/modules/Engagement.tsx +21 -0
  273. package/src/icons/modules/Finance.tsx +21 -0
  274. package/src/icons/modules/Goals.tsx +19 -0
  275. package/src/icons/modules/Home.tsx +19 -0
  276. package/src/icons/modules/Hub.tsx +20 -0
  277. package/src/icons/modules/Inbox.tsx +19 -0
  278. package/src/icons/modules/Kudos.tsx +19 -0
  279. package/src/icons/modules/MyDocuments.tsx +21 -0
  280. package/src/icons/modules/Organization.tsx +19 -0
  281. package/src/icons/modules/Overviews.tsx +23 -0
  282. package/src/icons/modules/Payroll.tsx +25 -0
  283. package/src/icons/modules/Performance.tsx +19 -0
  284. package/src/icons/modules/Profile.tsx +19 -0
  285. package/src/icons/modules/Projects.tsx +21 -0
  286. package/src/icons/modules/Recruitment.tsx +21 -0
  287. package/src/icons/modules/Reports.tsx +21 -0
  288. package/src/icons/modules/Sales.tsx +27 -0
  289. package/src/icons/modules/Settings.tsx +21 -0
  290. package/src/icons/modules/Shifts.tsx +27 -0
  291. package/src/icons/modules/Social.tsx +21 -0
  292. package/src/icons/modules/Software.tsx +19 -0
  293. package/src/icons/modules/Spaces.tsx +21 -0
  294. package/src/icons/modules/Spending.tsx +21 -0
  295. package/src/icons/modules/Tasks.tsx +21 -0
  296. package/src/icons/modules/TimeOff.tsx +21 -0
  297. package/src/icons/modules/TimeTracking.tsx +25 -0
  298. package/src/icons/modules/Trainings.tsx +19 -0
  299. package/src/icons/modules/Treasury.tsx +19 -0
  300. package/src/icons/modules/Workflows.tsx +19 -0
  301. package/src/icons/modules/index.ts +35 -0
  302. package/src/icons/types.ts +9 -0
  303. package/src/index.ts +18 -0
  304. package/src/lib/date.ts +102 -0
  305. package/src/lib/emojis.tsx +47 -0
  306. package/src/lib/iconWithClassName.ts +17 -0
  307. package/src/lib/text.ts +31 -0
  308. package/src/lib/utils.ts +6 -0
  309. package/src/ui/avatar.tsx +113 -0
  310. package/tailwind.config.ts +19 -0
@@ -0,0 +1,85 @@
1
+ import { cva, type VariantProps } from "cva";
2
+ import React, {
3
+ forwardRef,
4
+ ForwardRefExoticComponent,
5
+ RefAttributes,
6
+ } from "react";
7
+ import { SvgProps, Svg } from "react-native-svg";
8
+ import { cn } from "../../lib/utils";
9
+ import { cssInterop } from "nativewind";
10
+
11
+ const iconVariants = cva({
12
+ base: "shrink-0",
13
+ variants: {
14
+ size: {
15
+ xl: "w-8 h-8 stroke-xl",
16
+ lg: "w-6 h-6 stroke-lg",
17
+ md: "w-5 h-5 stroke-md",
18
+ sm: "w-4 h-4 stroke-sm",
19
+ xs: "w-3 h-3 stroke-xs",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ size: "md",
24
+ },
25
+ });
26
+
27
+ export interface IconProps extends SvgProps, VariantProps<typeof iconVariants> {
28
+ icon: IconType;
29
+ testID?: string;
30
+ className?: string;
31
+ variant?:
32
+ | "default"
33
+ | "critical"
34
+ | "neutral"
35
+ | "ghost"
36
+ | "outline"
37
+ | "promote";
38
+ isPressed?: boolean;
39
+ }
40
+
41
+ export type IconType = ForwardRefExoticComponent<
42
+ SvgProps &
43
+ RefAttributes<Svg> & {
44
+ className?: string;
45
+ }
46
+ >;
47
+
48
+ // Keep track of icons that have already had cssInterop applied
49
+ const interopAppliedIcons = new WeakSet();
50
+
51
+ // Function to apply NativeWind interop to an icon component
52
+ export function applyIconInterop(icon: IconType) {
53
+ if (!interopAppliedIcons.has(icon)) {
54
+ cssInterop(icon, {
55
+ className: {
56
+ target: "style",
57
+ nativeStyleToProp: {
58
+ color: true,
59
+ opacity: true,
60
+ },
61
+ },
62
+ });
63
+ interopAppliedIcons.add(icon);
64
+ }
65
+ return icon;
66
+ }
67
+
68
+ export const Icon = forwardRef<Svg, IconProps>(function Icon(
69
+ { size, icon, className, testID, ...props },
70
+ ref,
71
+ ) {
72
+ if (!icon) return null;
73
+
74
+ // Apply NativeWind interop to the icon if not already applied
75
+ const Component = applyIconInterop(icon);
76
+
77
+ return (
78
+ <Component
79
+ ref={ref}
80
+ {...props}
81
+ className={cn(iconVariants({ size }), className)}
82
+ testID={testID}
83
+ />
84
+ );
85
+ });
@@ -0,0 +1,242 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`PageHeader Snapshot - renders correctly with multiple actions 1`] = `
4
+ <View
5
+ className="flex-row items-center justify-between px-5 py-3"
6
+ >
7
+ <Text
8
+ className="text-3xl font-semibold text-f1-foreground"
9
+ >
10
+ Test Page Title
11
+ </Text>
12
+ <View
13
+ className="flex-row gap-2"
14
+ >
15
+ <View
16
+ accessibilityLabel="Notifications"
17
+ accessibilityState={
18
+ {
19
+ "busy": undefined,
20
+ "checked": undefined,
21
+ "disabled": undefined,
22
+ "expanded": undefined,
23
+ "selected": undefined,
24
+ }
25
+ }
26
+ accessibilityValue={
27
+ {
28
+ "max": undefined,
29
+ "min": undefined,
30
+ "now": undefined,
31
+ "text": undefined,
32
+ }
33
+ }
34
+ accessible={true}
35
+ collapsable={false}
36
+ focusable={true}
37
+ onClick={[Function]}
38
+ onResponderGrant={[Function]}
39
+ onResponderMove={[Function]}
40
+ onResponderRelease={[Function]}
41
+ onResponderTerminate={[Function]}
42
+ onResponderTerminationRequest={[Function]}
43
+ onStartShouldSetResponder={[Function]}
44
+ style={
45
+ {
46
+ "opacity": 1,
47
+ }
48
+ }
49
+ >
50
+ <Text>
51
+ Notifications
52
+ </Text>
53
+ <Text>
54
+ Icon:
55
+ Bell
56
+ </Text>
57
+ <Text>
58
+ Badge
59
+ </Text>
60
+ </View>
61
+ <View
62
+ accessibilityLabel="Alerts"
63
+ accessibilityState={
64
+ {
65
+ "busy": undefined,
66
+ "checked": undefined,
67
+ "disabled": undefined,
68
+ "expanded": undefined,
69
+ "selected": undefined,
70
+ }
71
+ }
72
+ accessibilityValue={
73
+ {
74
+ "max": undefined,
75
+ "min": undefined,
76
+ "now": undefined,
77
+ "text": undefined,
78
+ }
79
+ }
80
+ accessible={true}
81
+ collapsable={false}
82
+ focusable={true}
83
+ onClick={[Function]}
84
+ onResponderGrant={[Function]}
85
+ onResponderMove={[Function]}
86
+ onResponderRelease={[Function]}
87
+ onResponderTerminate={[Function]}
88
+ onResponderTerminationRequest={[Function]}
89
+ onStartShouldSetResponder={[Function]}
90
+ style={
91
+ {
92
+ "opacity": 1,
93
+ }
94
+ }
95
+ >
96
+ <Text>
97
+ Alerts
98
+ </Text>
99
+ <Text>
100
+ Icon:
101
+ Bell
102
+ </Text>
103
+ </View>
104
+ </View>
105
+ </View>
106
+ `;
107
+
108
+ exports[`PageHeader Snapshot - renders correctly with one action 1`] = `
109
+ <View
110
+ className="flex-row items-center justify-between px-5 py-3"
111
+ >
112
+ <Text
113
+ className="text-3xl font-semibold text-f1-foreground"
114
+ >
115
+ Test Page Title
116
+ </Text>
117
+ <View
118
+ className="flex-row gap-2"
119
+ >
120
+ <View
121
+ accessibilityLabel="Notifications"
122
+ accessibilityState={
123
+ {
124
+ "busy": undefined,
125
+ "checked": undefined,
126
+ "disabled": undefined,
127
+ "expanded": undefined,
128
+ "selected": undefined,
129
+ }
130
+ }
131
+ accessibilityValue={
132
+ {
133
+ "max": undefined,
134
+ "min": undefined,
135
+ "now": undefined,
136
+ "text": undefined,
137
+ }
138
+ }
139
+ accessible={true}
140
+ collapsable={false}
141
+ focusable={true}
142
+ onClick={[Function]}
143
+ onResponderGrant={[Function]}
144
+ onResponderMove={[Function]}
145
+ onResponderRelease={[Function]}
146
+ onResponderTerminate={[Function]}
147
+ onResponderTerminationRequest={[Function]}
148
+ onStartShouldSetResponder={[Function]}
149
+ style={
150
+ {
151
+ "opacity": 1,
152
+ }
153
+ }
154
+ >
155
+ <Text>
156
+ Notifications
157
+ </Text>
158
+ <Text>
159
+ Icon:
160
+ Bell
161
+ </Text>
162
+ </View>
163
+ </View>
164
+ </View>
165
+ `;
166
+
167
+ exports[`PageHeader Snapshot - renders correctly with one action with a badge 1`] = `
168
+ <View
169
+ className="flex-row items-center justify-between px-5 py-3"
170
+ >
171
+ <Text
172
+ className="text-3xl font-semibold text-f1-foreground"
173
+ >
174
+ Test Page Title
175
+ </Text>
176
+ <View
177
+ className="flex-row gap-2"
178
+ >
179
+ <View
180
+ accessibilityLabel="Notifications"
181
+ accessibilityState={
182
+ {
183
+ "busy": undefined,
184
+ "checked": undefined,
185
+ "disabled": undefined,
186
+ "expanded": undefined,
187
+ "selected": undefined,
188
+ }
189
+ }
190
+ accessibilityValue={
191
+ {
192
+ "max": undefined,
193
+ "min": undefined,
194
+ "now": undefined,
195
+ "text": undefined,
196
+ }
197
+ }
198
+ accessible={true}
199
+ collapsable={false}
200
+ focusable={true}
201
+ onClick={[Function]}
202
+ onResponderGrant={[Function]}
203
+ onResponderMove={[Function]}
204
+ onResponderRelease={[Function]}
205
+ onResponderTerminate={[Function]}
206
+ onResponderTerminationRequest={[Function]}
207
+ onStartShouldSetResponder={[Function]}
208
+ style={
209
+ {
210
+ "opacity": 1,
211
+ }
212
+ }
213
+ >
214
+ <Text>
215
+ Notifications
216
+ </Text>
217
+ <Text>
218
+ Icon:
219
+ Bell
220
+ </Text>
221
+ <Text>
222
+ Badge
223
+ </Text>
224
+ </View>
225
+ </View>
226
+ </View>
227
+ `;
228
+
229
+ exports[`PageHeader Snapshot - renders correctly with only a title 1`] = `
230
+ <View
231
+ className="flex-row items-center justify-between px-5 py-3"
232
+ >
233
+ <Text
234
+ className="text-3xl font-semibold text-f1-foreground"
235
+ >
236
+ Test Page Title
237
+ </Text>
238
+ <View
239
+ className="flex-row gap-2"
240
+ />
241
+ </View>
242
+ `;
@@ -0,0 +1,198 @@
1
+ import {
2
+ render,
3
+ fireEvent,
4
+ screen,
5
+ within,
6
+ } from "@testing-library/react-native";
7
+ import React from "react";
8
+ import { PageHeader } from "./"; // Assuming index.tsx is in the same folder
9
+ import { ButtonProps } from "../../Button"; // Adjust path as necessary
10
+ // import { AppIcons } from "../../../index"; // Adjust path as necessary - Not directly used in mock after change
11
+
12
+ // Define a simple type for the mocked icon
13
+ type MockIconType = { name: string };
14
+
15
+ // Mock the Button component
16
+ jest.mock("../../Button", () => ({
17
+ Button: jest.fn(
18
+ ({
19
+ label,
20
+ onPress,
21
+ icon,
22
+ showBadge,
23
+ ...rest
24
+ }: ButtonProps & { icon?: MockIconType }) => {
25
+ const MockButton = require("react-native").TouchableOpacity;
26
+ const MockText = require("react-native").Text;
27
+ return (
28
+ <MockButton onPress={onPress} accessibilityLabel={label} {...rest}>
29
+ <MockText>{label}</MockText>
30
+ {icon && <MockText>Icon:{icon.name}</MockText>}
31
+ {showBadge && <MockText>Badge</MockText>}
32
+ </MockButton>
33
+ );
34
+ },
35
+ ),
36
+ }));
37
+
38
+ // Mock AppIcons - specifically the Bell icon used by PageHeader's NotificationAction
39
+ jest.mock("../../../index", () => ({
40
+ AppIcons: {
41
+ Bell: { name: "Bell" } as MockIconType, // Ensure the mock matches MockIconType
42
+ },
43
+ }));
44
+
45
+ describe("PageHeader", () => {
46
+ const mockOnPressNotification = jest.fn();
47
+
48
+ const defaultProps = {
49
+ title: "Test Page Title",
50
+ };
51
+
52
+ const propsWithActions = {
53
+ ...defaultProps,
54
+ actions: [
55
+ {
56
+ type: "notifications" as const,
57
+ label: "Notifications",
58
+ onPress: mockOnPressNotification,
59
+ showBadge: false,
60
+ },
61
+ ],
62
+ };
63
+
64
+ const propsWithMultipleActions = {
65
+ ...defaultProps,
66
+ actions: [
67
+ {
68
+ type: "notifications" as const,
69
+ label: "Notifications",
70
+ onPress: mockOnPressNotification,
71
+ showBadge: true,
72
+ },
73
+ {
74
+ type: "notifications" as const, // Assuming another action of the same type for simplicity
75
+ label: "Alerts",
76
+ onPress: jest.fn(),
77
+ },
78
+ ],
79
+ };
80
+
81
+ beforeEach(() => {
82
+ jest.clearAllMocks();
83
+ });
84
+
85
+ // Snapshot tests
86
+ it("Snapshot - renders correctly with only a title", () => {
87
+ const { toJSON } = render(<PageHeader {...defaultProps} />);
88
+ expect(toJSON()).toMatchSnapshot();
89
+ });
90
+
91
+ it("Snapshot - renders correctly with one action", () => {
92
+ const { toJSON } = render(<PageHeader {...propsWithActions} />);
93
+ expect(toJSON()).toMatchSnapshot();
94
+ });
95
+
96
+ it("Snapshot - renders correctly with multiple actions", () => {
97
+ const { toJSON } = render(<PageHeader {...propsWithMultipleActions} />);
98
+ expect(toJSON()).toMatchSnapshot();
99
+ });
100
+
101
+ it("Snapshot - renders correctly with one action with a badge", () => {
102
+ const propsWithBadge = {
103
+ ...defaultProps,
104
+ actions: [
105
+ {
106
+ type: "notifications" as const,
107
+ label: "Notifications",
108
+ onPress: mockOnPressNotification,
109
+ showBadge: true,
110
+ },
111
+ ],
112
+ };
113
+ const { toJSON } = render(<PageHeader {...propsWithBadge} />);
114
+ expect(toJSON()).toMatchSnapshot();
115
+ });
116
+
117
+ // Functional tests
118
+ it("renders the title correctly", () => {
119
+ render(<PageHeader {...defaultProps} />);
120
+ const title = screen.getByText("Test Page Title");
121
+ expect(title).toBeDefined();
122
+ });
123
+
124
+ it("does not render actions if actions prop is not provided", () => {
125
+ render(<PageHeader {...defaultProps} />);
126
+ const notificationButton = screen.queryByText("Notifications");
127
+ expect(notificationButton).toBeNull();
128
+ });
129
+
130
+ it("renders action buttons when actions prop is provided", () => {
131
+ render(<PageHeader {...propsWithActions} />);
132
+ const notificationButton = screen.getByText("Notifications");
133
+ expect(notificationButton).toBeDefined();
134
+ });
135
+
136
+ it("calls the onPress handler of an action button when pressed", () => {
137
+ render(<PageHeader {...propsWithActions} />);
138
+ const notificationButton = screen.getByText("Notifications");
139
+ fireEvent.press(notificationButton);
140
+ expect(mockOnPressNotification).toHaveBeenCalledTimes(1);
141
+ });
142
+
143
+ it("displays a badge on an action button if showBadge is true", () => {
144
+ render(
145
+ <PageHeader
146
+ title="Test Title"
147
+ actions={[
148
+ {
149
+ type: "notifications",
150
+ label: "Notifications",
151
+ onPress: jest.fn(),
152
+ showBadge: true,
153
+ },
154
+ ]}
155
+ />,
156
+ );
157
+ const badge = screen.getByText("Badge");
158
+ expect(badge).toBeDefined();
159
+ });
160
+
161
+ it("does not display a badge if showBadge is false or undefined", () => {
162
+ render(
163
+ <PageHeader
164
+ title="Test Title"
165
+ actions={[
166
+ {
167
+ type: "notifications",
168
+ label: "Notifications",
169
+ onPress: jest.fn(),
170
+ // showBadge is undefined here
171
+ },
172
+ {
173
+ type: "notifications",
174
+ label: "Alerts",
175
+ onPress: jest.fn(),
176
+ showBadge: false,
177
+ },
178
+ ]}
179
+ />,
180
+ );
181
+ const badge = screen.queryByText("Badge");
182
+ expect(badge).toBeNull();
183
+ });
184
+
185
+ it("renders multiple action buttons correctly", () => {
186
+ render(<PageHeader {...propsWithMultipleActions} />);
187
+ const notificationsButton = screen.getByText("Notifications");
188
+ const alertsButton = screen.getByText("Alerts");
189
+
190
+ expect(notificationsButton).toBeDefined();
191
+ expect(alertsButton).toBeDefined();
192
+
193
+ const notificationButtonContainer = screen.getByLabelText("Notifications");
194
+
195
+ const badge = within(notificationButtonContainer).getByText("Badge");
196
+ expect(badge).toBeDefined();
197
+ });
198
+ });
@@ -0,0 +1,53 @@
1
+ import { memo } from "react";
2
+ import { Text, View } from "react-native";
3
+ import { Button } from "../../Button";
4
+ import { AppIcons } from "../../..";
5
+
6
+ type ActionType = "notifications";
7
+
8
+ export type ActionT = {
9
+ type: ActionType;
10
+ label: string;
11
+ onPress: () => void;
12
+ showBadge?: boolean;
13
+ };
14
+
15
+ type Props = {
16
+ title: string;
17
+ actions?: ActionT[];
18
+ };
19
+
20
+ const NotificationsAction = ({ label, onPress, showBadge }: ActionT) => {
21
+ return (
22
+ <Button
23
+ variant="outline"
24
+ icon={AppIcons.Bell}
25
+ label={label}
26
+ hideLabel
27
+ onPress={onPress}
28
+ showBadge={showBadge}
29
+ size="md"
30
+ round
31
+ />
32
+ );
33
+ };
34
+
35
+ export const PageHeader = memo(({ title, actions }: Props) => {
36
+ return (
37
+ <View className="flex-row items-center justify-between px-5 py-3">
38
+ <Text className="text-3xl font-semibold text-f1-foreground">{title}</Text>
39
+ <View className="flex-row gap-2">
40
+ {actions?.map((action) => {
41
+ switch (action.type) {
42
+ case "notifications":
43
+ return <NotificationsAction {...action} key={action.label} />;
44
+ default:
45
+ return null;
46
+ }
47
+ })}
48
+ </View>
49
+ </View>
50
+ );
51
+ });
52
+
53
+ PageHeader.displayName = "PageHeader";