@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,99 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { StyleSheet, View } from "react-native";
4
+ import { breakpoints, negativeSpacings, spacings } from "../constants/design";
5
+ import { useResponsive } from "../hooks/useResponsive";
6
+ import { LakeButton } from "./LakeButton";
7
+ import { LakeRadio } from "./LakeRadio";
8
+ import { Pressable } from "./Pressable";
9
+ import { Space } from "./Space";
10
+ import { Tile } from "./Tile";
11
+ const styles = StyleSheet.create({
12
+ root: {
13
+ alignSelf: "stretch",
14
+ alignItems: "stretch",
15
+ flexGrow: 1,
16
+ overflow: "hidden",
17
+ marginHorizontal: negativeSpacings[12],
18
+ },
19
+ container: {
20
+ alignSelf: "stretch",
21
+ flexDirection: "row",
22
+ flexWrap: "wrap",
23
+ alignItems: "stretch",
24
+ justifyContent: "center",
25
+ },
26
+ mobileContainer: {
27
+ flexWrap: "nowrap",
28
+ justifyContent: "flex-start",
29
+ transitionProperty: "transform",
30
+ transitionDuration: "300ms",
31
+ transitionTimingFunction: "ease-in-out",
32
+ },
33
+ item: {
34
+ flexGrow: 0,
35
+ flexBasis: "33.333%",
36
+ maxWidth: 300,
37
+ padding: spacings[12],
38
+ transform: [{ translateZ: 0 }],
39
+ animationKeyframes: {
40
+ from: {
41
+ opacity: 0,
42
+ transform: [{ translateZ: 0 }, { translateX: 50 }],
43
+ },
44
+ to: {
45
+ opacity: 1,
46
+ transform: [{ translateZ: 0 }, { translateX: 0 }],
47
+ },
48
+ },
49
+ animationDuration: "200ms",
50
+ animationFillMode: "backwards",
51
+ animationTimingFunction: "ease-in-out",
52
+ },
53
+ itemLarge: {
54
+ flexBasis: "50%",
55
+ maxWidth: "none",
56
+ },
57
+ itemSmallViewport: {
58
+ width: "100%",
59
+ flexBasis: "auto",
60
+ maxWidth: "none",
61
+ },
62
+ tileContents: {
63
+ alignItems: "center",
64
+ alignSelf: "stretch",
65
+ flexGrow: 1,
66
+ },
67
+ tileRenderedContents: {
68
+ alignItems: "center",
69
+ alignSelf: "stretch",
70
+ flexGrow: 1,
71
+ },
72
+ leftButton: {
73
+ position: "absolute",
74
+ top: "50%",
75
+ left: negativeSpacings[24],
76
+ transform: [{ translateY: "-50%" }],
77
+ },
78
+ rightButton: {
79
+ position: "absolute",
80
+ top: "50%",
81
+ right: negativeSpacings[24],
82
+ transform: [{ translateY: "-50%" }],
83
+ },
84
+ });
85
+ const identity = (x) => x;
86
+ export const ChoicePicker = ({ items, getId = identity, large = false, renderItem, value, onChange, }) => {
87
+ const { desktop } = useResponsive(breakpoints.medium);
88
+ const [index, setIndex] = useState(0);
89
+ return (_jsxs(View, { children: [_jsx(View, { style: styles.root, children: _jsx(View, { style: [
90
+ styles.container,
91
+ !desktop && styles.mobileContainer,
92
+ !desktop && { transform: [{ translateX: `-${100 * index}%` }] },
93
+ ], children: items.map((item, index) => (_jsx(Pressable, { style: [
94
+ styles.item,
95
+ large && styles.itemLarge,
96
+ !desktop && styles.itemSmallViewport,
97
+ { animationDelay: `${200 + 100 * index}ms` },
98
+ ], onPress: () => onChange(item), children: ({ hovered }) => (_jsx(Tile, { hovered: hovered, selected: value != null && getId(item) === getId(value), flexGrow: 1, children: _jsxs(View, { style: styles.tileContents, children: [_jsx(View, { style: styles.tileRenderedContents, children: renderItem(item) }), _jsx(Space, { height: 24 }), _jsx(LakeRadio, { value: value != null && getId(item) === getId(value) })] }) })) }, String(index)))) }) }), !desktop && (_jsx(View, { style: styles.leftButton, children: _jsx(LakeButton, { icon: "chevron-left-filled", mode: "secondary", forceBackground: true, onPress: () => setIndex(Math.max(0, index - 1)), disabled: index === 0 }) })), !desktop && (_jsx(View, { style: styles.rightButton, children: _jsx(LakeButton, { icon: "chevron-right-filled", mode: "secondary", forceBackground: true, onPress: () => setIndex(Math.min(items.length - 1, index + 1)), disabled: index === items.length - 1 }) }))] }));
99
+ };
@@ -0,0 +1,29 @@
1
+ import { ReactNode } from "react";
2
+ import { StyleProp, ViewStyle } from "react-native";
3
+ import { IconName } from "./Icon";
4
+ type Props<I extends {
5
+ value: string;
6
+ disabled?: boolean;
7
+ }> = {
8
+ value: string;
9
+ items: I[];
10
+ ListFooterComponent?: ReactNode;
11
+ onValueChange: (value: string) => void;
12
+ onSelectItem: (value: I) => void;
13
+ renderItem: (item: I) => ReactNode | null;
14
+ size?: "large" | "small";
15
+ icon?: IconName;
16
+ label?: string;
17
+ placeholder?: string;
18
+ loading?: boolean;
19
+ disabled?: boolean;
20
+ error?: string;
21
+ style?: StyleProp<ViewStyle>;
22
+ };
23
+ export declare const Combobox: (<I extends {
24
+ value: string;
25
+ disabled?: boolean | undefined;
26
+ }>(props: Props<I>) => JSX.Element | null) & {
27
+ displayName?: string | undefined;
28
+ };
29
+ export {};
@@ -0,0 +1,182 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { memo as reactMemo, useCallback, useEffect, useId, useRef, useState, } from "react";
3
+ import isEqual from "react-fast-compare";
4
+ import { ActivityIndicator, FlatList, Pressable, StyleSheet, Text, View, } from "react-native";
5
+ import { match } from "ts-pattern";
6
+ import { colors } from "../constants/colors";
7
+ import { spacings } from "../constants/design";
8
+ import { typography } from "../constants/typography";
9
+ import { useDisclosure } from "../hooks/useDisclosure";
10
+ import { useResponsive } from "../hooks/useResponsive";
11
+ import { isNotNullish, isNullish } from "../utils/nullish";
12
+ import { Icon } from "./Icon";
13
+ import { Input } from "./Input";
14
+ import { LakeTextInput } from "./LakeTextInput";
15
+ import { Popover, VIEWPORT_WIDTH_THRESHOLD } from "./Popover";
16
+ const ELEMENT_HEIGHT = 72;
17
+ const NB_SUGGESTION_DISPLAYED = 3.5;
18
+ const styles = StyleSheet.create({
19
+ inputWithLeftIcon: {
20
+ paddingLeft: 48,
21
+ },
22
+ icon: {
23
+ position: "absolute",
24
+ left: 16,
25
+ top: 14,
26
+ },
27
+ iconWithLabel: {
28
+ top: 42,
29
+ },
30
+ list: {
31
+ maxHeight: ELEMENT_HEIGHT * NB_SUGGESTION_DISPLAYED,
32
+ },
33
+ loading: {
34
+ height: ELEMENT_HEIGHT * NB_SUGGESTION_DISPLAYED,
35
+ left: 16,
36
+ alignItems: "center",
37
+ justifyContent: "center",
38
+ },
39
+ item: {
40
+ flexShrink: 1,
41
+ flexGrow: 1,
42
+ height: ELEMENT_HEIGHT,
43
+ justifyContent: "center",
44
+ paddingHorizontal: 16,
45
+ paddingVertical: 0,
46
+ transitionProperty: "background-color",
47
+ transitionDuration: "200ms",
48
+ },
49
+ hoveredItem: {
50
+ backgroundColor: colors.gray[3],
51
+ },
52
+ pressedItem: {
53
+ backgroundColor: colors.gray[10],
54
+ },
55
+ itemText: {
56
+ ...typography.bodyLarge,
57
+ },
58
+ mobileInput: {
59
+ padding: spacings[16],
60
+ },
61
+ });
62
+ const isReactText = (node) => ["string", "number"].includes(typeof node);
63
+ const getItemLayout = (_data, index) => ({
64
+ length: ELEMENT_HEIGHT,
65
+ offset: ELEMENT_HEIGHT * index,
66
+ index,
67
+ });
68
+ const memo = reactMemo;
69
+ export const Combobox = memo(({ value, items, ListFooterComponent, onValueChange, onSelectItem, renderItem, size, icon, label, placeholder, loading = false, disabled = false, error, style, }) => {
70
+ const isFirstRender = useRef(true);
71
+ const ref = useRef(null);
72
+ const mobileInputRef = useRef(null);
73
+ const listRef = useRef(null);
74
+ const [visible, { open, close }] = useDisclosure(false);
75
+ const [focusedIndex, setFocusedIndex] = useState();
76
+ const { desktop } = useResponsive(VIEWPORT_WIDTH_THRESHOLD);
77
+ const suggestionsId = useId();
78
+ const handleFocus = useCallback((event) => {
79
+ if (!desktop) {
80
+ event.preventDefault();
81
+ open();
82
+ }
83
+ else {
84
+ if (items.length > 0) {
85
+ open();
86
+ }
87
+ }
88
+ }, [items, open, desktop]);
89
+ const handleKeyPress = useCallback((event) => {
90
+ match(event.nativeEvent.key)
91
+ .with("ArrowDown", () => {
92
+ event.preventDefault();
93
+ setFocusedIndex(prevIndex => {
94
+ const nextIndex = isNotNullish(prevIndex) ? prevIndex + 1 : 0;
95
+ const maxIndex = items.length - 1;
96
+ return Math.min(nextIndex, maxIndex);
97
+ });
98
+ })
99
+ .with("ArrowUp", () => {
100
+ event.preventDefault();
101
+ setFocusedIndex(prevIndex => {
102
+ const maxIndex = items.length - 1;
103
+ const previousIndex = isNotNullish(prevIndex) ? prevIndex - 1 : maxIndex;
104
+ return Math.max(previousIndex, 0);
105
+ });
106
+ })
107
+ .with("Escape", () => {
108
+ event.preventDefault();
109
+ close();
110
+ })
111
+ .with("Enter", () => {
112
+ event.preventDefault();
113
+ if (isNullish(focusedIndex)) {
114
+ return;
115
+ }
116
+ const item = items[focusedIndex];
117
+ if (item) {
118
+ onSelectItem(item);
119
+ close();
120
+ }
121
+ })
122
+ .otherwise(() => { });
123
+ }, [items, focusedIndex, onSelectItem, close]);
124
+ useEffect(() => {
125
+ isFirstRender.current = false;
126
+ return () => {
127
+ isFirstRender.current = true;
128
+ };
129
+ }, []);
130
+ // Auto open/close popover depending on value on items
131
+ useEffect(() => {
132
+ // avoid to open popover on first render
133
+ if (isFirstRender.current) {
134
+ return;
135
+ }
136
+ if (value.length > 0 && items.length > 0) {
137
+ open();
138
+ }
139
+ // we want to run this effect only when items or value changed
140
+ }, [items.length, value.length]); // eslint-disable-line react-hooks/exhaustive-deps
141
+ // reset focused suggestion when the number of suggestions change
142
+ useEffect(() => {
143
+ setFocusedIndex(prevFocusedIndex => {
144
+ const maxIndex = items.length - 1;
145
+ if (isNotNullish(prevFocusedIndex) && prevFocusedIndex > maxIndex) {
146
+ return maxIndex;
147
+ }
148
+ if (items.length === 0) {
149
+ return undefined;
150
+ }
151
+ return prevFocusedIndex;
152
+ });
153
+ }, [items.length]);
154
+ // scroll automatically in suggestion list if user use keyboard navigation
155
+ useEffect(() => {
156
+ if (isNotNullish(focusedIndex)) {
157
+ const position = focusedIndex + 1 - NB_SUGGESTION_DISPLAYED;
158
+ // avoid negative value for first indexes
159
+ const index = Math.max(0, position);
160
+ listRef.current?.scrollToIndex({
161
+ animated: true,
162
+ index,
163
+ });
164
+ }
165
+ }, [focusedIndex]);
166
+ useEffect(() => {
167
+ if (visible) {
168
+ mobileInputRef.current?.focus();
169
+ }
170
+ }, [visible]);
171
+ return (_jsxs(View, { style: style, children: [_jsx(Input, { ref: ref, accessibilityControls: visible ? suggestionsId : "", accessibilityExpanded: visible, inputStyle: icon || loading ? styles.inputWithLeftIcon : undefined, returnKeyType: "search", role: "combobox", label: label, placeholder: placeholder, value: value, size: size, disabled: disabled, error: error, onValueChange: onValueChange, onFocus: handleFocus, onKeyPress: handleKeyPress }), icon ? (_jsx(Icon, { name: icon, color: colors.gray[50], size: 20, style: [styles.icon, isNotNullish(label) && styles.iconWithLabel] })) : null, _jsxs(Popover, { id: suggestionsId, role: "listbox", matchReferenceWidth: true, onDismiss: close, referenceRef: ref, autoFocus: false, returnFocus: false, visible: visible && (!desktop || loading || items.length > 0), underlay: false, children: [!desktop && (_jsx(View, { style: styles.mobileInput, children: _jsx(LakeTextInput, { ref: mobileInputRef, accessibilityControls: visible ? suggestionsId : "", accessibilityExpanded: visible, returnKeyType: "search", placeholder: placeholder, value: value, disabled: disabled, error: error, onChangeText: onValueChange, onKeyPress: handleKeyPress }) })), _jsxs(View, { style: styles.list, children: [loading ? (_jsx(View, { style: styles.loading, children: _jsx(ActivityIndicator, { color: colors.gray[70], size: 20 }) })) : (_jsx(FlatList, { ref: listRef, keyExtractor: item => item.value, getItemLayout: getItemLayout, accessibilityRole: "list", data: items, extraData: focusedIndex, renderItem: ({ item, index }) => {
172
+ const rendered = renderItem(item);
173
+ return (_jsx(Pressable, { accessibilityRole: "listitem", disabled: item.disabled, style: ({ hovered, pressed, focused }) => [
174
+ styles.item,
175
+ (hovered || focused || index === focusedIndex) && styles.hoveredItem,
176
+ pressed && styles.pressedItem,
177
+ ], onPress: () => {
178
+ onSelectItem(item);
179
+ close();
180
+ }, children: isReactText(rendered) ? (_jsx(Text, { numberOfLines: 1, selectable: false, style: styles.itemText, children: rendered })) : (rendered) }));
181
+ } })), ListFooterComponent] })] })] }));
182
+ }, isEqual);
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { StyleProp, ViewStyle } from "react-native";
3
+ type Props = {
4
+ size: number;
5
+ style?: StyleProp<ViewStyle>;
6
+ };
7
+ export declare const FailureIcon: ({ size, style }: Props) => JSX.Element;
8
+ export {};
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { colors } from "../constants/colors";
3
+ import { Path, Svg } from "./Svg";
4
+ export const FailureIcon = ({ size, style }) => (_jsx(Svg, { viewBox: "0 0 24 24", style: [{ height: size, width: size }, style], children: _jsx(Path, { d: "M12 0a12 12 0 110 24 12 12 0 010-24zM8.9 7.57A.95.95 0 007.58 8.9l3.08 3.1-3.1 3.1a.95.95 0 101.35 1.33L12 13.34l3.1 3.1a.95.95 0 101.33-1.35L13.34 12l3.1-3.1a.95.95 0 10-1.35-1.33L12 10.66z", fill: colors.red[100] }) }));
@@ -0,0 +1,11 @@
1
+ /// <reference types="react" />
2
+ type Props = {
3
+ variant?: "none" | "pending" | "verified" | "refused";
4
+ name: string;
5
+ url?: string;
6
+ onRemove?: () => void;
7
+ title?: string;
8
+ description?: string;
9
+ };
10
+ export declare const FileTile: ({ variant, name, url, onRemove, title, description }: Props) => JSX.Element;
11
+ export {};
@@ -0,0 +1,37 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { StyleSheet } from "react-native";
3
+ import { match } from "ts-pattern";
4
+ import { commonStyles } from "../constants/commonStyles";
5
+ import { backgroundColor, colors, shadows, spacings } from "../constants/design";
6
+ import { getIconNameFromFilename } from "../utils/file";
7
+ import { isNotNullish, isNotNullishOrEmpty } from "../utils/nullish";
8
+ import { Box } from "./Box";
9
+ import { LakeAlert } from "./LakeAlert";
10
+ import { LakeButton } from "./LakeButton";
11
+ import { LakeText } from "./LakeText";
12
+ import { Space } from "./Space";
13
+ import { Tag } from "./Tag";
14
+ const styles = StyleSheet.create({
15
+ base: {
16
+ backgroundColor: backgroundColor.accented,
17
+ borderRadius: 8,
18
+ boxShadow: shadows.tile,
19
+ overflow: "hidden",
20
+ },
21
+ content: {
22
+ height: 56,
23
+ paddingLeft: spacings[20],
24
+ paddingRight: spacings[8],
25
+ },
26
+ });
27
+ export const FileTile = ({ variant = "none", name, url, onRemove, title, description }) => (_jsxs(Box, { style: styles.base, children: [_jsxs(Box, { alignItems: "center", direction: "row", style: styles.content, children: [_jsx(Tag, { icon: getIconNameFromFilename(name), iconSize: 20, color: match(variant)
28
+ .with("none", "pending", () => "shakespear")
29
+ .with("verified", () => "positive")
30
+ .with("refused", () => "negative")
31
+ .exhaustive() }), _jsx(Space, { width: 16 }), _jsx(LakeText, { numberOfLines: 1, color: colors.gray[700], style: commonStyles.fill, children: name }), _jsx(Space, { width: 12 }), isNotNullishOrEmpty(url) && (_jsx(LakeButton, { mode: "tertiary", size: "small", icon: "open-filled", onPress: () => {
32
+ window.open(url, "_blank");
33
+ } })), isNotNullish(onRemove) && (_jsx(LakeButton, { mode: "tertiary", size: "small", icon: "delete-regular", color: "negative", onPress: onRemove }))] }), variant !== "none" && (_jsx(LakeAlert, { anchored: true, title: title, variant: match(variant)
34
+ .with("pending", () => "info")
35
+ .with("verified", () => "success")
36
+ .with("refused", () => "error")
37
+ .exhaustive(), children: description }))] }));
@@ -0,0 +1,8 @@
1
+ /// <reference types="react" />
2
+ import { SpacingValue } from "./Space";
3
+ type Props = {
4
+ minHeight?: SpacingValue;
5
+ minWidth?: SpacingValue;
6
+ };
7
+ export declare const Fill: ({ minHeight, minWidth }: Props) => JSX.Element;
8
+ export {};
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { StyleSheet, View } from "react-native";
3
+ import { isNotNullish } from "../utils/nullish";
4
+ import { spacingValues } from "./Space";
5
+ const baseStyle = {
6
+ flexGrow: 1,
7
+ flexShrink: 1,
8
+ };
9
+ const rawHeightStyles = {};
10
+ const rawWidthStyles = {};
11
+ spacingValues.forEach(value => {
12
+ rawHeightStyles[value] = { ...baseStyle, minHeight: value };
13
+ rawWidthStyles[value] = { ...baseStyle, minWidth: value };
14
+ });
15
+ const styles = StyleSheet.create({
16
+ base: baseStyle,
17
+ });
18
+ const heightStyles = StyleSheet.create(rawHeightStyles);
19
+ const widthStyles = StyleSheet.create(rawWidthStyles);
20
+ export const Fill = ({ minHeight, minWidth }) => (_jsx(View, { focusable: false, pointerEvents: "none", style: [
21
+ styles.base,
22
+ isNotNullish(minHeight) && heightStyles[minHeight],
23
+ isNotNullish(minWidth) && widthStyles[minWidth],
24
+ ] }));
@@ -0,0 +1,15 @@
1
+ /// <reference types="react" />
2
+ export declare function FilterChooser<FilterName extends string>({ filters, openFilters, label, title, availableFilters, large, onAddFilter, }: {
3
+ filters: Partial<{
4
+ [K in FilterName]: string | string[] | undefined;
5
+ }>;
6
+ openFilters: FilterName[];
7
+ label: string;
8
+ title: string;
9
+ availableFilters: {
10
+ label: string;
11
+ name: FilterName;
12
+ }[];
13
+ large?: boolean;
14
+ onAddFilter: (filterName: FilterName) => void;
15
+ }): JSX.Element;
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useRef } from "react";
3
+ import { FlatList, Pressable, StyleSheet, Text, View } from "react-native";
4
+ import { colors } from "../constants/design";
5
+ import { typography } from "../constants/typography";
6
+ import { useDisclosure } from "../hooks/useDisclosure";
7
+ import { Box } from "./Box";
8
+ import { Icon } from "./Icon";
9
+ import { LakeButton } from "./LakeButton";
10
+ import { Popover } from "./Popover";
11
+ import { Space } from "./Space";
12
+ const styles = StyleSheet.create({
13
+ selected: {
14
+ color: colors.gray[500],
15
+ },
16
+ list: {
17
+ paddingVertical: 20,
18
+ marginVertical: 4,
19
+ width: 250,
20
+ overflow: "hidden",
21
+ },
22
+ item: {
23
+ display: "flex",
24
+ paddingHorizontal: 24,
25
+ flexDirection: "row",
26
+ justifyContent: "space-between",
27
+ alignItems: "center",
28
+ paddingVertical: 8,
29
+ },
30
+ itemHovered: {
31
+ backgroundColor: colors.gray[50],
32
+ },
33
+ availableFiltersTitle: {
34
+ ...typography.bodyLarge,
35
+ color: colors.current.primary,
36
+ paddingHorizontal: 24,
37
+ },
38
+ filterName: {
39
+ ...typography.bodySmall,
40
+ },
41
+ });
42
+ export function FilterChooser({ filters, openFilters, label, title, availableFilters, large = true, onAddFilter, }) {
43
+ const inputRef = useRef(null);
44
+ const [visible, { close, toggle }] = useDisclosure(false);
45
+ return (_jsxs(_Fragment, { children: [_jsx(Box, { direction: "row", justifyContent: "start", alignItems: "center", children: _jsx(LakeButton, { size: "small", mode: "secondary", color: "gray", onPress: toggle, ref: inputRef, icon: large ? "chevron-down-filled" : "filter-filled", iconPosition: "end", accessibilityLabel: label, children: large ? label : null }) }), _jsx(Popover, { role: "listbox", matchReferenceMinWidth: true, onDismiss: close, referenceRef: inputRef, returnFocus: false, visible: visible, children: _jsxs(View, { style: styles.list, children: [_jsx(Text, { style: styles.availableFiltersTitle, children: title }), _jsx(Space, { height: 8 }), _jsx(FlatList, { accessibilityRole: "list", data: availableFilters, keyExtractor: (_, index) => `filter-item-${index}`, renderItem: ({ item }) => {
46
+ const isSet = Boolean(filters[item.name]) || openFilters.includes(item.name);
47
+ return (_jsxs(Pressable, { style: ({ hovered }) => [styles.item, hovered && styles.itemHovered], accessibilityRole: "button", disabled: isSet, onPress: () => {
48
+ onAddFilter(item.name);
49
+ close();
50
+ }, children: [_jsx(Text, { style: [styles.filterName, isSet && styles.selected], children: item.label }), isSet && _jsx(Icon, { color: colors.positive[500], name: "checkmark-filled", size: 14 })] }));
51
+ } })] }) })] }));
52
+ }
@@ -0,0 +1,57 @@
1
+ import { ComponentProps } from "react";
2
+ import { ValidatorResult } from "react-ux-form";
3
+ import { Rifm } from "rifm";
4
+ import { Simplify } from "type-fest";
5
+ type Item<T> = {
6
+ label: string;
7
+ value: T;
8
+ };
9
+ type RifmProps = Required<Pick<ComponentProps<typeof Rifm>, "accept" | "append" | "format" | "mask">>;
10
+ export type FilterCheckboxDef<T> = {
11
+ type: "checkbox";
12
+ label: string;
13
+ items: Item<T>[];
14
+ submitText: string;
15
+ checkAllLabel?: string;
16
+ };
17
+ export type FilterRadioDef<T> = {
18
+ type: "radio";
19
+ label: string;
20
+ items: Item<T>[];
21
+ };
22
+ export type FilterDateDef = {
23
+ type: "date";
24
+ label: string;
25
+ submitText: string;
26
+ noValueText: string;
27
+ dateFormat: string;
28
+ rifmProps: RifmProps;
29
+ validate?: (value: string) => ValidatorResult;
30
+ };
31
+ export type FilterInputDef = {
32
+ type: "input";
33
+ label: string;
34
+ submitText: string;
35
+ noValueText: string;
36
+ placeholder?: string;
37
+ validate?: (value: string) => ValidatorResult;
38
+ };
39
+ type Filter<T> = FilterCheckboxDef<T> | FilterRadioDef<T> | FilterDateDef | FilterInputDef;
40
+ type ExtractFilterValue<T extends Filter<unknown>> = T extends {
41
+ type: "checkbox";
42
+ } ? T["items"][number]["value"][] | undefined : T extends {
43
+ type: "radio";
44
+ } ? T["items"][number]["value"] | undefined : string | undefined;
45
+ type FiltersDefinition = Record<string, Filter<unknown>>;
46
+ export type FiltersState<T extends FiltersDefinition> = Simplify<{
47
+ [K in keyof T]: Simplify<ExtractFilterValue<T[K]>>;
48
+ }>;
49
+ type FiltersStackProps<Definition extends FiltersDefinition, State extends FiltersState<Definition> = FiltersState<Definition>> = {
50
+ definition: Definition;
51
+ filters: State;
52
+ openedFilters: (keyof Definition)[];
53
+ onChangeOpened: (value: (keyof Definition)[]) => void;
54
+ onChangeFilters: (value: State) => void;
55
+ };
56
+ export declare const FiltersStack: <T extends FiltersDefinition>({ filters, openedFilters, definition, onChangeOpened, onChangeFilters, }: FiltersStackProps<T, { [K in keyof T]: ExtractFilterValue<T[K]> extends infer T_2 ? { [KeyType_2 in keyof T_2]: ExtractFilterValue<T[K]>[KeyType_2]; } : never; } extends infer T_1 ? { [KeyType_1 in keyof T_1]: { [K in keyof T]: ExtractFilterValue<T[K]> extends infer T_2 ? { [KeyType_2 in keyof T_2]: ExtractFilterValue<T[K]>[KeyType_2]; } : never; }[KeyType_1]; } : never>) => JSX.Element | null;
57
+ export {};