@swan-io/lake 1.0.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 (288) hide show
  1. package/HISTORY.md +3 -0
  2. package/LICENSE +21 -0
  3. package/README.md +49 -0
  4. package/package.json +60 -0
  5. package/src/components/Alert.d.ts +10 -0
  6. package/src/components/Alert.js +36 -0
  7. package/src/components/AppOpeningAnimation.d.ts +10 -0
  8. package/src/components/AppOpeningAnimation.js +50 -0
  9. package/src/components/AutoWidthImage.d.ts +8 -0
  10. package/src/components/AutoWidthImage.js +26 -0
  11. package/src/components/Avatar.d.ts +7 -0
  12. package/src/components/Avatar.js +42 -0
  13. package/src/components/BorderedButton.d.ts +16 -0
  14. package/src/components/BorderedButton.js +98 -0
  15. package/src/components/BorderedIcon.d.ts +12 -0
  16. package/src/components/BorderedIcon.js +25 -0
  17. package/src/components/BottomPanel.d.ts +9 -0
  18. package/src/components/BottomPanel.js +94 -0
  19. package/src/components/Box.d.ts +65 -0
  20. package/src/components/Box.js +31 -0
  21. package/src/components/Breadcrumbs.d.ts +18 -0
  22. package/src/components/Breadcrumbs.js +362 -0
  23. package/src/components/Button.d.ts +15 -0
  24. package/src/components/Button.js +83 -0
  25. package/src/components/Caption.d.ts +6 -0
  26. package/src/components/Caption.js +11 -0
  27. package/src/components/Checkbox.d.ts +12 -0
  28. package/src/components/Checkbox.js +83 -0
  29. package/src/components/ChoicePicker.d.ts +11 -0
  30. package/src/components/ChoicePicker.js +99 -0
  31. package/src/components/Combobox.d.ts +29 -0
  32. package/src/components/Combobox.js +182 -0
  33. package/src/components/FailureIcon.d.ts +8 -0
  34. package/src/components/FailureIcon.js +4 -0
  35. package/src/components/FileTile.d.ts +11 -0
  36. package/src/components/FileTile.js +37 -0
  37. package/src/components/Fill.d.ts +8 -0
  38. package/src/components/Fill.js +24 -0
  39. package/src/components/FilterChooser.d.ts +15 -0
  40. package/src/components/FilterChooser.js +52 -0
  41. package/src/components/Filters.d.ts +57 -0
  42. package/src/components/Filters.js +229 -0
  43. package/src/components/FixedListView.d.ts +104 -0
  44. package/src/components/FixedListView.js +821 -0
  45. package/src/components/FixedListViewCells.d.ts +55 -0
  46. package/src/components/FixedListViewCells.js +157 -0
  47. package/src/components/Flag.d.ts +8 -0
  48. package/src/components/Flag.js +36 -0
  49. package/src/components/FlowPresentation.d.ts +12 -0
  50. package/src/components/FlowPresentation.js +70 -0
  51. package/src/components/FocusTrap.d.ts +16 -0
  52. package/src/components/FocusTrap.js +90 -0
  53. package/src/components/Form.d.ts +8 -0
  54. package/src/components/Form.js +17 -0
  55. package/src/components/FullViewportLayer.d.ts +7 -0
  56. package/src/components/FullViewportLayer.js +91 -0
  57. package/src/components/Grid.d.ts +13 -0
  58. package/src/components/Grid.js +33 -0
  59. package/src/components/Heading.d.ts +61 -0
  60. package/src/components/Heading.js +27 -0
  61. package/src/components/Icon.d.ts +191 -0
  62. package/src/components/Icon.js +11 -0
  63. package/src/components/Input.d.ts +34 -0
  64. package/src/components/Input.js +115 -0
  65. package/src/components/InputError.d.ts +8 -0
  66. package/src/components/InputError.js +16 -0
  67. package/src/components/Label.d.ts +10 -0
  68. package/src/components/Label.js +19 -0
  69. package/src/components/LakeAlert.d.ts +14 -0
  70. package/src/components/LakeAlert.js +75 -0
  71. package/src/components/LakeButton.d.ts +36 -0
  72. package/src/components/LakeButton.js +171 -0
  73. package/src/components/LakeCheckbox.d.ts +16 -0
  74. package/src/components/LakeCheckbox.js +54 -0
  75. package/src/components/LakeCombobox.d.ts +28 -0
  76. package/src/components/LakeCombobox.js +166 -0
  77. package/src/components/LakeCopyButton.d.ts +10 -0
  78. package/src/components/LakeCopyButton.js +16 -0
  79. package/src/components/LakeDownloadButton.d.ts +8 -0
  80. package/src/components/LakeDownloadButton.js +6 -0
  81. package/src/components/LakeHeading.d.ts +10 -0
  82. package/src/components/LakeHeading.js +19 -0
  83. package/src/components/LakeLabel.d.ts +19 -0
  84. package/src/components/LakeLabel.js +43 -0
  85. package/src/components/LakeModal.d.ts +14 -0
  86. package/src/components/LakeModal.js +132 -0
  87. package/src/components/LakeRadio.d.ts +9 -0
  88. package/src/components/LakeRadio.js +44 -0
  89. package/src/components/LakeScrollView.d.ts +10 -0
  90. package/src/components/LakeScrollView.js +35 -0
  91. package/src/components/LakeSearchField.d.ts +10 -0
  92. package/src/components/LakeSearchField.js +111 -0
  93. package/src/components/LakeSelect.d.ts +30 -0
  94. package/src/components/LakeSelect.js +183 -0
  95. package/src/components/LakeSlider.d.ts +12 -0
  96. package/src/components/LakeSlider.js +31 -0
  97. package/src/components/LakeStepper.d.ts +21 -0
  98. package/src/components/LakeStepper.js +134 -0
  99. package/src/components/LakeText.d.ts +19 -0
  100. package/src/components/LakeText.js +20 -0
  101. package/src/components/LakeTextInput.d.ts +36 -0
  102. package/src/components/LakeTextInput.js +154 -0
  103. package/src/components/LakeTooltip.d.ts +24 -0
  104. package/src/components/LakeTooltip.js +188 -0
  105. package/src/components/Link.d.ts +138 -0
  106. package/src/components/Link.js +23 -0
  107. package/src/components/ListRightPanel.d.ts +17 -0
  108. package/src/components/ListRightPanel.js +79 -0
  109. package/src/components/LoadingView.d.ts +9 -0
  110. package/src/components/LoadingView.js +24 -0
  111. package/src/components/Modal.d.ts +12 -0
  112. package/src/components/Modal.js +80 -0
  113. package/src/components/MultiSelect.d.ts +27 -0
  114. package/src/components/MultiSelect.js +223 -0
  115. package/src/components/MultilineInput.d.ts +15 -0
  116. package/src/components/MultilineInput.js +55 -0
  117. package/src/components/Picker.d.ts +26 -0
  118. package/src/components/Picker.js +116 -0
  119. package/src/components/PlainListView.d.ts +36 -0
  120. package/src/components/PlainListView.js +208 -0
  121. package/src/components/Popover.d.ts +23 -0
  122. package/src/components/Popover.js +147 -0
  123. package/src/components/PopoverContent.d.ts +8 -0
  124. package/src/components/PopoverContent.js +9 -0
  125. package/src/components/Portal.d.ts +7 -0
  126. package/src/components/Portal.js +9 -0
  127. package/src/components/Pressable.d.ts +348 -0
  128. package/src/components/Pressable.js +91 -0
  129. package/src/components/ProgressBar.d.ts +11 -0
  130. package/src/components/ProgressBar.js +46 -0
  131. package/src/components/ProjectEnvTag.d.ts +7 -0
  132. package/src/components/ProjectEnvTag.js +12 -0
  133. package/src/components/QuickActions.d.ts +15 -0
  134. package/src/components/QuickActions.js +38 -0
  135. package/src/components/RadioGroup.d.ts +16 -0
  136. package/src/components/RadioGroup.js +34 -0
  137. package/src/components/ReadOnlyFieldList.d.ts +6 -0
  138. package/src/components/ReadOnlyFieldList.js +8 -0
  139. package/src/components/ResponsiveContainer.d.ts +13 -0
  140. package/src/components/ResponsiveContainer.js +23 -0
  141. package/src/components/RightPanel.d.ts +10 -0
  142. package/src/components/RightPanel.js +102 -0
  143. package/src/components/SegmentedControl.d.ts +19 -0
  144. package/src/components/SegmentedControl.js +74 -0
  145. package/src/components/Separator.d.ts +10 -0
  146. package/src/components/Separator.js +19 -0
  147. package/src/components/SidebarNavigationTracker.d.ts +13 -0
  148. package/src/components/SidebarNavigationTracker.js +93 -0
  149. package/src/components/Slider.d.ts +11 -0
  150. package/src/components/Slider.js +119 -0
  151. package/src/components/SmsOpeningAnimation.d.ts +8 -0
  152. package/src/components/SmsOpeningAnimation.js +52 -0
  153. package/src/components/Space.d.ts +10 -0
  154. package/src/components/Space.js +23 -0
  155. package/src/components/Stack.d.ts +12 -0
  156. package/src/components/Stack.js +23 -0
  157. package/src/components/StepDots.d.ts +7 -0
  158. package/src/components/StepDots.js +24 -0
  159. package/src/components/Stepper.d.ts +9 -0
  160. package/src/components/Stepper.js +67 -0
  161. package/src/components/SuccessIcon.d.ts +8 -0
  162. package/src/components/SuccessIcon.js +4 -0
  163. package/src/components/Svg.d.ts +145 -0
  164. package/src/components/Svg.js +24 -0
  165. package/src/components/SwanLogo.d.ts +8 -0
  166. package/src/components/SwanLogo.js +11 -0
  167. package/src/components/Switch.d.ts +9 -0
  168. package/src/components/Switch.js +74 -0
  169. package/src/components/TabView.d.ts +16 -0
  170. package/src/components/TabView.js +398 -0
  171. package/src/components/Table.d.ts +34 -0
  172. package/src/components/Table.js +79 -0
  173. package/src/components/Tag.d.ts +17 -0
  174. package/src/components/Tag.js +76 -0
  175. package/src/components/Tile.d.ts +34 -0
  176. package/src/components/Tile.js +130 -0
  177. package/src/components/TilePlaceholder.d.ts +6 -0
  178. package/src/components/TilePlaceholder.js +51 -0
  179. package/src/components/ToastStack.d.ts +2 -0
  180. package/src/components/ToastStack.js +96 -0
  181. package/src/components/Tooltip.d.ts +18 -0
  182. package/src/components/Tooltip.js +162 -0
  183. package/src/components/TransitionGroupView.d.ts +12 -0
  184. package/src/components/TransitionGroupView.js +43 -0
  185. package/src/components/TransitionView.d.ts +12 -0
  186. package/src/components/TransitionView.js +43 -0
  187. package/src/components/WithCurrentColor.d.ts +12 -0
  188. package/src/components/WithCurrentColor.js +65 -0
  189. package/src/components/WithPartnerAccentColor.d.ts +7 -0
  190. package/src/components/WithPartnerAccentColor.js +91 -0
  191. package/src/constants/colors.d.ts +42 -0
  192. package/src/constants/colors.js +42 -0
  193. package/src/constants/commonStyles.d.ts +66 -0
  194. package/src/constants/commonStyles.js +45 -0
  195. package/src/constants/design.d.ts +168 -0
  196. package/src/constants/design.js +564 -0
  197. package/src/constants/insets.d.ts +10 -0
  198. package/src/constants/insets.js +22 -0
  199. package/src/constants/typography.d.ts +26 -0
  200. package/src/constants/typography.js +54 -0
  201. package/src/hooks/useAnimatedValue.d.ts +2 -0
  202. package/src/hooks/useAnimatedValue.js +3 -0
  203. package/src/hooks/useBodyClassName.d.ts +3 -0
  204. package/src/hooks/useBodyClassName.js +14 -0
  205. package/src/hooks/useBoolean.d.ts +8 -0
  206. package/src/hooks/useBoolean.js +12 -0
  207. package/src/hooks/useComputedColors.d.ts +10 -0
  208. package/src/hooks/useComputedColors.js +42 -0
  209. package/src/hooks/useDebounce.d.ts +1 -0
  210. package/src/hooks/useDebounce.js +12 -0
  211. package/src/hooks/useDisclosure.d.ts +8 -0
  212. package/src/hooks/useDisclosure.js +12 -0
  213. package/src/hooks/useFirstMountState.d.ts +1 -0
  214. package/src/hooks/useFirstMountState.js +9 -0
  215. package/src/hooks/useForceableState.d.ts +1 -0
  216. package/src/hooks/useForceableState.js +6 -0
  217. package/src/hooks/useHover.d.ts +11 -0
  218. package/src/hooks/useHover.js +4 -0
  219. package/src/hooks/useInterval.d.ts +1 -0
  220. package/src/hooks/useInterval.js +11 -0
  221. package/src/hooks/useLazyRef.d.ts +2 -0
  222. package/src/hooks/useLazyRef.js +9 -0
  223. package/src/hooks/useMergeRefs.d.ts +2 -0
  224. package/src/hooks/useMergeRefs.js +5 -0
  225. package/src/hooks/useNativeProp.d.ts +2 -0
  226. package/src/hooks/useNativeProp.js +9 -0
  227. package/src/hooks/useOutsideClick.d.ts +8 -0
  228. package/src/hooks/useOutsideClick.js +54 -0
  229. package/src/hooks/usePersistedState.d.ts +1 -0
  230. package/src/hooks/usePersistedState.js +21 -0
  231. package/src/hooks/usePressEvents.d.ts +31 -0
  232. package/src/hooks/usePressEvents.js +4 -0
  233. package/src/hooks/usePreviousValue.d.ts +1 -0
  234. package/src/hooks/usePreviousValue.js +8 -0
  235. package/src/hooks/useResponsive.d.ts +7 -0
  236. package/src/hooks/useResponsive.js +20 -0
  237. package/src/hooks/useUpdateEffect.d.ts +2 -0
  238. package/src/hooks/useUpdateEffect.js +10 -0
  239. package/src/hooks/useUrqlMutation.d.ts +4 -0
  240. package/src/hooks/useUrqlMutation.js +30 -0
  241. package/src/hooks/useUrqlQuery.d.ts +19 -0
  242. package/src/hooks/useUrqlQuery.js +73 -0
  243. package/src/state/toasts.d.ts +21 -0
  244. package/src/state/toasts.js +61 -0
  245. package/src/utils/__tests__/array.test.d.ts +1 -0
  246. package/src/utils/__tests__/array.test.js +127 -0
  247. package/src/utils/__tests__/base64.test.d.ts +1 -0
  248. package/src/utils/__tests__/base64.test.js +27 -0
  249. package/src/utils/__tests__/function.test.d.ts +1 -0
  250. package/src/utils/__tests__/function.test.js +36 -0
  251. package/src/utils/__tests__/object.test.d.ts +1 -0
  252. package/src/utils/__tests__/object.test.js +17 -0
  253. package/src/utils/__tests__/rifm.test.d.ts +1 -0
  254. package/src/utils/__tests__/rifm.test.js +124 -0
  255. package/src/utils/__tests__/string.test.d.ts +1 -0
  256. package/src/utils/__tests__/string.test.js +16 -0
  257. package/src/utils/a11y.d.ts +1 -0
  258. package/src/utils/a11y.js +18 -0
  259. package/src/utils/array.d.ts +6 -0
  260. package/src/utils/array.js +71 -0
  261. package/src/utils/base64.d.ts +2 -0
  262. package/src/utils/base64.js +20 -0
  263. package/src/utils/file.d.ts +2 -0
  264. package/src/utils/file.js +10 -0
  265. package/src/utils/flagCountry.d.ts +1 -0
  266. package/src/utils/flagCountry.js +1 -0
  267. package/src/utils/function.d.ts +4 -0
  268. package/src/utils/function.js +19 -0
  269. package/src/utils/math.d.ts +16 -0
  270. package/src/utils/math.js +47 -0
  271. package/src/utils/nullish.d.ts +10 -0
  272. package/src/utils/nullish.js +8 -0
  273. package/src/utils/object.d.ts +2 -0
  274. package/src/utils/object.js +7 -0
  275. package/src/utils/popper.d.ts +3 -0
  276. package/src/utils/popper.js +30 -0
  277. package/src/utils/rifm.d.ts +14 -0
  278. package/src/utils/rifm.js +53 -0
  279. package/src/utils/string.d.ts +4 -0
  280. package/src/utils/string.js +233 -0
  281. package/src/utils/timer.d.ts +11 -0
  282. package/src/utils/timer.js +46 -0
  283. package/src/utils/types.d.ts +8 -0
  284. package/src/utils/types.js +1 -0
  285. package/src/utils/userAgent.d.ts +4 -0
  286. package/src/utils/userAgent.js +9 -0
  287. package/src/utils/viewport.d.ts +1 -0
  288. package/src/utils/viewport.js +12 -0
@@ -0,0 +1,55 @@
1
+ import { ReactNode } from "react";
2
+ import { ColorVariants } from "../constants/design";
3
+ import { TextVariant } from "./LakeText";
4
+ type Justify = "flex-start" | "center" | "flex-end";
5
+ type SortDirection = "Desc" | "Asc";
6
+ export declare const SimpleHeaderCell: ({ text, sort, justifyContent, onPress, }: {
7
+ text: string;
8
+ justifyContent?: Justify | undefined;
9
+ sort?: SortDirection | undefined;
10
+ onPress?: ((direction: SortDirection) => void) | undefined;
11
+ }) => JSX.Element;
12
+ export declare const ColorPatchCell: ({ isHovered, alternativeText, color, }: {
13
+ isHovered: boolean;
14
+ alternativeText?: string | undefined;
15
+ color: ColorVariants;
16
+ }) => JSX.Element | null;
17
+ export declare const SimpleTitleCell: ({ isHighlighted, text, }: {
18
+ isHighlighted?: boolean | undefined;
19
+ text: string;
20
+ }) => JSX.Element;
21
+ export declare const SimpleRegularTextCell: ({ variant, text, textAlign, }: {
22
+ variant?: "semibold" | "medium" | "regular" | "light" | "smallSemibold" | "smallMedium" | "smallRegular" | undefined;
23
+ text: string;
24
+ textAlign?: "center" | "left" | "right" | undefined;
25
+ }) => JSX.Element;
26
+ export declare const CopyableRegularTextCell: ({ variant, text, copyWording, copiedWording, }: {
27
+ variant?: "semibold" | "medium" | "regular" | "light" | "smallSemibold" | "smallMedium" | "smallRegular" | undefined;
28
+ text: string;
29
+ copyWording: string;
30
+ copiedWording: string;
31
+ }) => JSX.Element;
32
+ export declare const BalanceCell: ({ value, currency, formatCurrency, textAlign, }: {
33
+ value: number;
34
+ currency: string;
35
+ formatCurrency: (value: number, currency: string) => string;
36
+ textAlign?: "center" | "left" | "right" | undefined;
37
+ }) => JSX.Element;
38
+ export declare const LinkCell: ({ children, external, onPress, }: {
39
+ children: ReactNode;
40
+ onPress: () => void;
41
+ external?: boolean | undefined;
42
+ }) => JSX.Element;
43
+ export declare const StartAlignedCell: ({ children }: {
44
+ children: ReactNode;
45
+ }) => JSX.Element;
46
+ export declare const CenteredCell: ({ children }: {
47
+ children: ReactNode;
48
+ }) => JSX.Element;
49
+ export declare const EndAlignedCell: ({ children }: {
50
+ children: ReactNode;
51
+ }) => JSX.Element;
52
+ export declare const CellAction: ({ children }: {
53
+ children: ReactNode;
54
+ }) => JSX.Element;
55
+ export {};
@@ -0,0 +1,157 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useState } from "react";
3
+ import { Clipboard, StyleSheet, View } from "react-native";
4
+ import { match } from "ts-pattern";
5
+ import { visuallyHiddenStyle } from "../constants/commonStyles";
6
+ import { colors, spacings } from "../constants/design";
7
+ import { isNotNullish, isNullish } from "../utils/nullish";
8
+ import { Box } from "./Box";
9
+ import { Icon } from "./Icon";
10
+ import { LakeText } from "./LakeText";
11
+ import { LakeTooltip } from "./LakeTooltip";
12
+ import { Pressable } from "./Pressable";
13
+ import { Space } from "./Space";
14
+ const styles = StyleSheet.create({
15
+ cellContainer: {
16
+ display: "flex",
17
+ flexGrow: 1,
18
+ flexDirection: "row",
19
+ alignItems: "center",
20
+ },
21
+ cell: {
22
+ display: "flex",
23
+ paddingHorizontal: spacings[16],
24
+ flexGrow: 1,
25
+ flexDirection: "row",
26
+ alignItems: "center",
27
+ width: 1,
28
+ alignSelf: "stretch",
29
+ },
30
+ icon: {
31
+ alignSelf: "stretch",
32
+ alignItems: "center",
33
+ justifyContent: "center",
34
+ paddingHorizontal: spacings[4],
35
+ },
36
+ iconContainer: {
37
+ flexDirection: "row",
38
+ alignSelf: "stretch",
39
+ alignItems: "stretch",
40
+ justifyContent: "center",
41
+ },
42
+ centeredCell: {
43
+ justifyContent: "center",
44
+ },
45
+ endAlignedCell: {
46
+ justifyContent: "flex-end",
47
+ },
48
+ regularText: {
49
+ overflow: "hidden",
50
+ textOverflow: "ellipsis",
51
+ width: 1,
52
+ flexGrow: 1,
53
+ whiteSpace: "nowrap",
54
+ },
55
+ mediumText: {
56
+ overflow: "hidden",
57
+ textOverflow: "ellipsis",
58
+ width: 1,
59
+ flexGrow: 1,
60
+ whiteSpace: "nowrap",
61
+ flexDirection: "row",
62
+ alignItems: "center",
63
+ },
64
+ colorPatch: {
65
+ flexGrow: 1,
66
+ },
67
+ alternativeText: visuallyHiddenStyle,
68
+ sortIcon: {
69
+ transitionProperty: "transform",
70
+ transitionDuration: "300ms",
71
+ transitionTimingFunction: "ease-in-out",
72
+ },
73
+ sortIconReversed: {
74
+ transform: [{ rotate: "-180deg" }],
75
+ },
76
+ cellAction: {
77
+ paddingVertical: spacings[16],
78
+ paddingHorizontal: spacings[8],
79
+ },
80
+ underline: {
81
+ boxShadow: "inset 0 -2px currentColor",
82
+ },
83
+ sortHorizontalBar: {
84
+ position: "absolute",
85
+ width: "100%",
86
+ height: 2,
87
+ bottom: -10,
88
+ backgroundColor: colors.current[500],
89
+ borderBottomColor: colors.current[500],
90
+ },
91
+ });
92
+ export const SimpleHeaderCell = ({ text, sort, justifyContent = "flex-start", onPress, }) => {
93
+ const sortActive = isNotNullish(sort) && isNotNullish(onPress);
94
+ return (_jsx(Pressable, { onPress: () => {
95
+ onPress?.(match(sort)
96
+ .with("Desc", () => "Asc")
97
+ .with("Asc", () => "Desc")
98
+ .otherwise(() => "Desc"));
99
+ }, disabled: isNullish(onPress), style: styles.cellContainer, children: ({ hovered }) => (_jsx(View, { style: [styles.cell, { justifyContent }], children: _jsxs(View, { children: [_jsxs(Box, { direction: "row", alignItems: "center", children: [_jsx(LakeText, { numberOfLines: 1, variant: "medium", color: sortActive ? colors.current[500] : colors.gray[900], style: {
100
+ textAlign: match(justifyContent)
101
+ .with("flex-start", () => "left")
102
+ .with("center", () => "center")
103
+ .with("flex-end", () => "right")
104
+ .exhaustive(),
105
+ }, children: text }), isNotNullish(onPress) ? (_jsxs(_Fragment, { children: [_jsx(Space, { width: 8 }), _jsx(Box, { style: [styles.sortIcon, sort === "Asc" && styles.sortIconReversed], children: _jsx(Icon, { size: 15, color: sortActive ? colors.current[500] : colors.gray[500], name: sortActive ? "arrow-down-filled" : "chevron-up-down-regular" }) })] })) : null] }), sortActive ? (_jsx(View, { style: styles.sortHorizontalBar })) : hovered ? (_jsx(View, { style: [styles.sortHorizontalBar, { backgroundColor: colors.gray[900] }] })) : null] }) })) }));
106
+ };
107
+ export const ColorPatchCell = ({ isHovered, alternativeText, color, }) => {
108
+ return isHovered ? (_jsx(View, { style: [styles.colorPatch, { backgroundColor: colors[color].primary }], children: isNotNullish(alternativeText) ? (_jsx(LakeText, { style: styles.alternativeText, children: alternativeText })) : null })) : null;
109
+ };
110
+ export const SimpleTitleCell = ({ isHighlighted = false, text, }) => (_jsx(View, { style: styles.cell, children: _jsx(LakeText, { numberOfLines: 1, color: colors.gray[900], variant: "medium", ...(isHighlighted && {
111
+ color: colors.current.primary,
112
+ }), children: text }) }));
113
+ export const SimpleRegularTextCell = ({ variant = "regular", text, textAlign = "left", }) => {
114
+ return (_jsx(View, { style: styles.cell, children: _jsx(LakeText, { align: textAlign, color: colors.gray[900], style: styles.regularText, variant: variant, children: text }) }));
115
+ };
116
+ export const CopyableRegularTextCell = ({ variant = "regular", text, copyWording, copiedWording, }) => {
117
+ const [visibleState, setVisibleState] = useState("copy");
118
+ const onPress = useCallback((event) => {
119
+ event.preventDefault();
120
+ Clipboard.setString(text);
121
+ setVisibleState("copied");
122
+ }, [text]);
123
+ return (_jsxs(View, { style: styles.cell, children: [_jsx(LakeTooltip, { placement: "top", onHide: () => setVisibleState("copy"), togglableOnFocus: true, content: visibleState === "copy" ? copyWording : copiedWording, containerStyle: styles.iconContainer, children: _jsx(Pressable, { accessibilityRole: "button", accessibilityLabel: copyWording, onPress: onPress, style: ({ hovered }) => [styles.icon, hovered && styles.underline], children: ({ hovered }) => (_jsx(Icon, { name: hovered ? "copy-filled" : "copy-regular", color: "currentColor", size: 14 })) }) }), _jsx(Space, { width: 4 }), _jsx(LakeText, { color: colors.gray[900], style: styles.regularText, variant: variant, children: text })] }));
124
+ };
125
+ // TODO: handle `+` sign properly
126
+ export const BalanceCell = ({ value, currency, formatCurrency, textAlign = "right", }) => {
127
+ return (_jsx(View, { style: styles.cell, children: _jsxs(LakeText, { align: textAlign, color: colors.gray[900], variant: "medium", style: [
128
+ styles.mediumText,
129
+ {
130
+ justifyContent: match(textAlign)
131
+ .with("left", () => "flex-start")
132
+ .with("center", () => "center")
133
+ .with("right", () => "flex-end")
134
+ .exhaustive(),
135
+ },
136
+ value > 0 && { color: colors.positive.primary },
137
+ value < 0 && { color: colors.negative.primary },
138
+ ], children: [value > 0 && "+", formatCurrency(value, currency)] }) }));
139
+ };
140
+ export const LinkCell = ({ children, external = false, onPress, }) => {
141
+ return (_jsxs(View, { style: styles.cell, children: [_jsx(Pressable, { style: ({ hovered }) => [styles.icon, hovered && styles.underline], onPress: event => {
142
+ event.preventDefault();
143
+ onPress();
144
+ }, children: _jsx(Icon, { size: 14, name: external ? "open-regular" : "arrow-right-filled" }) }), _jsx(Space, { width: 8 }), _jsx(LakeText, { color: colors.gray[900], variant: "medium", style: styles.mediumText, children: children })] }));
145
+ };
146
+ export const StartAlignedCell = ({ children }) => {
147
+ return _jsx(View, { style: styles.cell, children: children });
148
+ };
149
+ export const CenteredCell = ({ children }) => {
150
+ return _jsx(View, { style: [styles.cell, styles.centeredCell], children: children });
151
+ };
152
+ export const EndAlignedCell = ({ children }) => {
153
+ return _jsx(View, { style: [styles.cell, styles.endAlignedCell], children: children });
154
+ };
155
+ export const CellAction = ({ children }) => {
156
+ return _jsx(View, { style: styles.cellAction, children: children });
157
+ };
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { CountryCCA3 } from "@swan-io/shared-business/src/constants/countries";
3
+ type Props = {
4
+ icon: CountryCCA3;
5
+ width: number;
6
+ };
7
+ export declare const Flag: ({ icon, width }: Props) => JSX.Element;
8
+ export {};
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Lazy } from "@swan-io/boxed";
3
+ import { countries } from "@swan-io/shared-business/src/constants/countries";
4
+ import { useEffect, useMemo, useState } from "react";
5
+ import { Svg, Use } from "./Svg";
6
+ let loadedUrl;
7
+ const importFlags = Lazy(async () => {
8
+ const { default: value } = await import("../assets/images/flags.svg");
9
+ loadedUrl = value;
10
+ return value;
11
+ });
12
+ const UNICODE_OFFSET = 127462 - 65;
13
+ export const Flag = ({ icon, width }) => {
14
+ const [url, setUrl] = useState(loadedUrl);
15
+ useEffect(() => {
16
+ if (loadedUrl == undefined) {
17
+ void importFlags.get().then(setUrl);
18
+ }
19
+ }, []);
20
+ const flag = useMemo(() => {
21
+ const cca2 = countries.find(item => item.cca3 === icon)?.cca2;
22
+ if (cca2 == null) {
23
+ return null;
24
+ }
25
+ return ((UNICODE_OFFSET + cca2.charCodeAt(0)).toString(16) +
26
+ "-" +
27
+ (UNICODE_OFFSET + cca2.charCodeAt(1)).toString(16));
28
+ }, [icon]);
29
+ return (_jsx(Svg, { viewBox: "0 0 18 18",
30
+ // eslint-disable-next-line react-native/no-inline-styles
31
+ style: {
32
+ borderRadius: 2,
33
+ width,
34
+ height: width,
35
+ }, children: url != null && flag != null ? _jsx(Use, { xlinkHref: `${url}#${flag}` }) : null }));
36
+ };
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ import { IconName } from "./Icon";
3
+ export type FlowStep = {
4
+ label: string;
5
+ icon: IconName;
6
+ };
7
+ type Props = {
8
+ steps: FlowStep[];
9
+ mode: "desktop" | "mobile";
10
+ };
11
+ export declare const FlowPresentation: ({ steps, mode }: Props) => JSX.Element;
12
+ export {};
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Fragment } from "react";
3
+ import { StyleSheet, View } from "react-native";
4
+ import { match } from "ts-pattern";
5
+ import { colors } from "../constants/design";
6
+ import { BorderedIcon } from "./BorderedIcon";
7
+ import { Box } from "./Box";
8
+ import { LakeText } from "./LakeText";
9
+ import { Space } from "./Space";
10
+ const desktopIconSize = 100;
11
+ const borderHeight = 2;
12
+ const desktopPadding = 40;
13
+ const mobileNumberSize = 24;
14
+ const mobileBorderWidth = 4;
15
+ const styles = StyleSheet.create({
16
+ container: {
17
+ width: "100%",
18
+ },
19
+ textContainer: {
20
+ width: desktopIconSize + desktopPadding,
21
+ },
22
+ lastTextContainer: {
23
+ width: desktopIconSize,
24
+ },
25
+ desktopBarContainer: {
26
+ flex: 1,
27
+ paddingRight: 40,
28
+ height: desktopIconSize,
29
+ },
30
+ desktopBar: {
31
+ width: "100%",
32
+ height: borderHeight,
33
+ borderRadius: borderHeight / 2,
34
+ backgroundColor: colors.gray[100],
35
+ },
36
+ mobileNumber: {
37
+ width: 24,
38
+ height: 24,
39
+ borderRadius: 12,
40
+ borderColor: colors.current[100],
41
+ borderWidth: 1,
42
+ backgroundColor: colors.current[50],
43
+ },
44
+ mobileNumberText: {
45
+ position: "relative",
46
+ top: 1,
47
+ },
48
+ mobileBarContainer: {
49
+ width: mobileNumberSize,
50
+ paddingVertical: 4,
51
+ },
52
+ mobileBar: {
53
+ width: mobileBorderWidth,
54
+ height: 12,
55
+ borderRadius: mobileBorderWidth / 2,
56
+ backgroundColor: colors.gray[100],
57
+ },
58
+ });
59
+ export const FlowPresentation = ({ steps, mode }) => {
60
+ return match(mode)
61
+ .with("desktop", () => (_jsx(Box, { direction: "row", style: styles.container, children: steps.map(({ label, icon }, index) => {
62
+ const isLast = index === steps.length - 1;
63
+ return (_jsxs(Fragment, { children: [_jsxs(Box, { children: [_jsx(BorderedIcon, { name: icon, size: 100, padding: 16 }), _jsx(Space, { height: 32 }), _jsx(View, { style: isLast ? styles.lastTextContainer : styles.textContainer, children: _jsxs(LakeText, { color: colors.gray[900], variant: "medium", children: [index + 1, ". ", label] }) })] }), !isLast && (_jsx(Box, { direction: "row", alignItems: "center", style: styles.desktopBarContainer, children: _jsx(View, { style: styles.desktopBar }) }))] }, index));
64
+ }) })))
65
+ .with("mobile", () => (_jsx(Box, { direction: "column", children: steps.map(({ label }, index) => {
66
+ const isLast = index === steps.length - 1;
67
+ return (_jsxs(Fragment, { children: [_jsxs(Box, { direction: "row", children: [_jsx(Box, { alignItems: "center", justifyContent: "center", style: styles.mobileNumber, children: _jsx(LakeText, { color: colors.current.primary, variant: "medium", style: styles.mobileNumberText, children: index + 1 }) }), _jsx(Space, { width: 12 }), _jsx(LakeText, { color: colors.gray[400], variant: "smallRegular", children: label })] }), !isLast && (_jsx(Box, { alignItems: "center", style: styles.mobileBarContainer, children: _jsx(View, { style: styles.mobileBar }) }))] }, index));
68
+ }) })))
69
+ .exhaustive();
70
+ };
@@ -0,0 +1,16 @@
1
+ import { ReactNode } from "react";
2
+ import { StyleProp, ViewStyle } from "react-native";
3
+ type Props = {
4
+ autoFocus: boolean;
5
+ children: ReactNode;
6
+ focusLock: boolean;
7
+ onClickOutside?: (event: TouchEvent | MouseEvent) => void;
8
+ onEscapeKey?: () => void;
9
+ returnFocus: boolean;
10
+ style?: StyleProp<ViewStyle>;
11
+ };
12
+ export type FocusTrapRef = {
13
+ setInitiallyFocusedElement: (element: HTMLElement) => void;
14
+ };
15
+ export declare const FocusTrap: import("react").ForwardRefExoticComponent<Props & import("react").RefAttributes<FocusTrapRef>>;
16
+ export {};
@@ -0,0 +1,90 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState, } from "react";
3
+ import { View } from "react-native";
4
+ import { match } from "ts-pattern";
5
+ import { useInterval } from "../hooks/useInterval";
6
+ import { useOutsideClick } from "../hooks/useOutsideClick";
7
+ import { getFocusableElements } from "../utils/a11y";
8
+ import { first, last } from "../utils/array";
9
+ import { isNotNullish } from "../utils/nullish";
10
+ let escapeListenerCount = 0;
11
+ export const FocusTrap = forwardRef(({ children, focusLock, onClickOutside, onEscapeKey, returnFocus, style, autoFocus }, ref) => {
12
+ const containerRef = useRef(null);
13
+ const previouslyFocusedRef = useRef(null);
14
+ const hasFocusedOutside = useRef(false);
15
+ useImperativeHandle(ref, () => ({
16
+ setInitiallyFocusedElement: element => (previouslyFocusedRef.current = element),
17
+ }));
18
+ const [initialEscapeListenerCount] = useState(escapeListenerCount);
19
+ useEffect(() => {
20
+ ++escapeListenerCount;
21
+ return () => {
22
+ --escapeListenerCount;
23
+ };
24
+ });
25
+ // The reason we're listening to the capturing phase instead of the bubbling one is that React Native Web
26
+ // uses a static preventDefault in its TextInput implementation, which we cannot control.
27
+ // Listening to the bubbling phase catches the event before RNW has the opportunity to block.
28
+ const onKeyDownCapture = useCallback(({ nativeEvent }) => {
29
+ match(nativeEvent.key)
30
+ .with("Escape", () => {
31
+ if (escapeListenerCount === initialEscapeListenerCount + 1) {
32
+ onEscapeKey?.();
33
+ }
34
+ })
35
+ .with("Tab", () => {
36
+ if (!focusLock) {
37
+ return;
38
+ }
39
+ const trapElement = containerRef.current;
40
+ if (isNotNullish(trapElement)) {
41
+ const target = nativeEvent.target;
42
+ const focusableElements = getFocusableElements(trapElement);
43
+ const firstFocusableElement = first(focusableElements);
44
+ const lastFocusableElement = last(focusableElements);
45
+ if (target === firstFocusableElement && nativeEvent.shiftKey) {
46
+ nativeEvent.preventDefault();
47
+ lastFocusableElement?.focus();
48
+ }
49
+ if (target === lastFocusableElement && !nativeEvent.shiftKey) {
50
+ nativeEvent.preventDefault();
51
+ firstFocusableElement?.focus();
52
+ }
53
+ }
54
+ })
55
+ .otherwise(() => { });
56
+ }, [focusLock, onEscapeKey, initialEscapeListenerCount]);
57
+ useEffect(() => {
58
+ if (returnFocus) {
59
+ previouslyFocusedRef.current = document.activeElement;
60
+ return () => {
61
+ if (!hasFocusedOutside.current) {
62
+ previouslyFocusedRef.current?.focus();
63
+ }
64
+ };
65
+ }
66
+ }, [returnFocus]);
67
+ useInterval(id => {
68
+ if (autoFocus) {
69
+ const trapElement = containerRef.current;
70
+ if (isNotNullish(trapElement)) {
71
+ if (trapElement.offsetWidth === 0) {
72
+ return;
73
+ }
74
+ const focusableElements = getFocusableElements(trapElement);
75
+ const firstFocusableElement = first(focusableElements);
76
+ firstFocusableElement?.focus();
77
+ window.clearInterval(id);
78
+ }
79
+ }
80
+ }, 16);
81
+ const onFocusOutside = useCallback(() => {
82
+ hasFocusedOutside.current = true;
83
+ }, []);
84
+ useOutsideClick({
85
+ containerRef,
86
+ onClickOutside,
87
+ onFocusOutside,
88
+ });
89
+ return (_jsx(View, { ref: containerRef, onKeyDownCapture: onKeyDownCapture, style: style, children: children }));
90
+ });
@@ -0,0 +1,8 @@
1
+ import { ReactNode } from "react";
2
+ import { View, ViewProps } from "react-native";
3
+ import { Except } from "type-fest";
4
+ export declare const Form: import("react").MemoExoticComponent<import("react").ForwardRefExoticComponent<Except<ViewProps, "accessibilityRole"> & {
5
+ children?: ReactNode;
6
+ onReset?: ((event: React.FormEvent<HTMLElement>) => void) | undefined;
7
+ onSubmit?: ((event: React.FormEvent<HTMLElement>) => void) | undefined;
8
+ } & import("react").RefAttributes<View>>>;
@@ -0,0 +1,17 @@
1
+ import { forwardRef, memo } from "react";
2
+ import { unstable_createElement as createElement } from "react-native";
3
+ import { commonStyles } from "../constants/commonStyles";
4
+ export const Form = memo(forwardRef(({ style, onReset, onSubmit, ...props }, forwardedRef) => createElement("form", {
5
+ ...props,
6
+ ref: forwardedRef,
7
+ onReset: (event) => {
8
+ event.preventDefault();
9
+ onReset?.(event);
10
+ },
11
+ onSubmit: (event) => {
12
+ event.preventDefault();
13
+ onSubmit?.(event);
14
+ },
15
+ style: [commonStyles.view, style],
16
+ })));
17
+ Form.displayName = "Form";
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from "react";
2
+ type Props = {
3
+ visible: boolean;
4
+ children: ReactNode;
5
+ };
6
+ export declare const FullViewportLayer: ({ visible, children }: Props) => JSX.Element;
7
+ export {};
@@ -0,0 +1,91 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FocusTrap } from "@swan-io/lake/src/components/FocusTrap";
3
+ import { TransitionView } from "@swan-io/lake/src/components/TransitionView";
4
+ import { backgroundColor } from "@swan-io/lake/src/constants/design";
5
+ import { Suspense, useEffect, useState } from "react";
6
+ import { StyleSheet, View } from "react-native";
7
+ import { LoadingView } from "./LoadingView";
8
+ import { Portal } from "./Portal";
9
+ const BACKGROUND_COLOR = "rgba(0, 0, 0, 0.6)";
10
+ const styles = StyleSheet.create({
11
+ root: {
12
+ ...StyleSheet.absoluteFillObject,
13
+ overflow: "hidden",
14
+ },
15
+ fill: {
16
+ ...StyleSheet.absoluteFillObject,
17
+ animationFillMode: "forwards",
18
+ overflow: "hidden",
19
+ },
20
+ overlayEnter: {
21
+ animationKeyframes: {
22
+ "0%": { opacity: 0 },
23
+ },
24
+ animationDuration: "200ms",
25
+ animationTimingFunction: "ease-in-out",
26
+ },
27
+ overlayLeave: {
28
+ animationKeyframes: {
29
+ "100%": { opacity: 0 },
30
+ },
31
+ animationDuration: "200ms",
32
+ animationTimingFunction: "ease-in-out",
33
+ },
34
+ containerEnter: {
35
+ animationKeyframes: {
36
+ "0%": { opacity: 0, transform: [{ translateZ: 0 }, { translateX: 200 }] },
37
+ },
38
+ animationDuration: "500ms",
39
+ animationTimingFunction: "ease-in-out",
40
+ },
41
+ containerLeave: {
42
+ animationKeyframes: {
43
+ "100%": { opacity: 0, transform: [{ translateZ: 0 }, { translateX: 200 }] },
44
+ },
45
+ animationDuration: "500ms",
46
+ animationTimingFunction: "ease-in-out",
47
+ },
48
+ overlay: {
49
+ ...StyleSheet.absoluteFillObject,
50
+ backgroundColor: BACKGROUND_COLOR,
51
+ },
52
+ container: {
53
+ ...StyleSheet.absoluteFillObject,
54
+ transform: [{ translateZ: 0 }],
55
+ flexDirection: "row",
56
+ alignItems: "stretch",
57
+ backgroundColor: backgroundColor.default,
58
+ },
59
+ contentsEnter: {
60
+ animationKeyframes: {
61
+ "0%": { transform: [{ translateZ: 0 }, { translateX: 50 }] },
62
+ },
63
+ animationDuration: "500ms",
64
+ animationTimingFunction: "ease-in-out",
65
+ },
66
+ contentsLeave: {
67
+ animationKeyframes: {
68
+ "100%": { transform: [{ translateZ: 0 }, { translateX: 50 }] },
69
+ },
70
+ animationDuration: "500ms",
71
+ animationTimingFunction: "ease-in-out",
72
+ },
73
+ contentsContainer: {
74
+ ...StyleSheet.absoluteFillObject,
75
+ zIndex: 2,
76
+ transform: [{ translateZ: 0 }],
77
+ maxWidth: "100%",
78
+ },
79
+ contents: {
80
+ ...StyleSheet.absoluteFillObject,
81
+ maxWidth: "100%",
82
+ },
83
+ });
84
+ const rootNode = document.querySelector("#full-page-layer-root");
85
+ export const FullViewportLayer = ({ visible, children }) => {
86
+ const [delayedVisible, setDelayedVisible] = useState(visible);
87
+ useEffect(() => {
88
+ setDelayedVisible(visible);
89
+ }, [visible]);
90
+ return (_jsx(Portal, { container: rootNode, children: _jsxs(View, { style: styles.root, pointerEvents: visible ? "auto" : "none", children: [_jsx(TransitionView, { style: styles.fill, enter: styles.overlayEnter, leave: styles.overlayLeave, children: visible ? _jsx(View, { style: styles.overlay }) : null }), _jsx(Suspense, { fallback: _jsx(LoadingView, { color: backgroundColor.accented, delay: 0 }), children: _jsx(TransitionView, { style: styles.fill, enter: styles.containerEnter, leave: styles.containerLeave, children: delayedVisible ? (_jsx(FocusTrap, { focusLock: true, autoFocus: true, returnFocus: true, style: styles.container, children: _jsx(TransitionView, { style: styles.contentsContainer, enter: styles.contentsEnter, leave: styles.contentsLeave, children: _jsx(View, { style: styles.contents, children: _jsx(View, { style: styles.contentsContainer, children: children }) }) }) })) : null }) })] }) }));
91
+ };
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from "react";
2
+ import { StyleProp, ViewStyle } from "react-native";
3
+ import { SpacingValue } from "./Space";
4
+ type Props = {
5
+ children: ReactNode;
6
+ horizontalSpace?: SpacingValue;
7
+ itemWrapperStyle?: StyleProp<ViewStyle>;
8
+ numColumns?: number;
9
+ style?: StyleProp<ViewStyle>;
10
+ verticalSpace?: SpacingValue;
11
+ };
12
+ export declare const Grid: ({ children, horizontalSpace, itemWrapperStyle, numColumns, style, verticalSpace, }: Props) => JSX.Element;
13
+ export {};
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Children } from "react";
3
+ import { StyleSheet, View } from "react-native";
4
+ import { isNullish } from "../utils/nullish";
5
+ const styles = StyleSheet.create({
6
+ base: {
7
+ flexDirection: "row",
8
+ flexWrap: "wrap",
9
+ },
10
+ item: {
11
+ flexShrink: 1,
12
+ width: "100%",
13
+ },
14
+ });
15
+ export const Grid = ({ children, horizontalSpace, itemWrapperStyle, numColumns = 1, style, verticalSpace, }) => (_jsx(View, { style: [
16
+ styles.base,
17
+ style,
18
+ numColumns > 1 && horizontalSpace && { marginHorizontal: -(horizontalSpace / 2) },
19
+ verticalSpace && { marginVertical: -(verticalSpace / 2) },
20
+ ], children: Children.map(children, child => {
21
+ if (isNullish(child)) {
22
+ return child;
23
+ }
24
+ return (_jsx(View, { style: [
25
+ styles.item,
26
+ itemWrapperStyle,
27
+ verticalSpace && { paddingVertical: verticalSpace / 2 },
28
+ numColumns > 1 && [
29
+ { width: `${100 / numColumns}%` },
30
+ horizontalSpace && { paddingHorizontal: horizontalSpace / 2 },
31
+ ],
32
+ ], children: child }));
33
+ }) }));