@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,229 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import dayjs from "dayjs";
3
+ import { forwardRef, useCallback, useEffect, useMemo, useRef, useState, } from "react";
4
+ import { FlatList, Pressable, StyleSheet, Text, View } from "react-native";
5
+ import { hasDefinedKeys, useForm } from "react-ux-form";
6
+ import { Rifm } from "rifm";
7
+ import { match, P } from "ts-pattern";
8
+ import { colors, shadows, spacings } from "../constants/design";
9
+ import { useDisclosure } from "../hooks/useDisclosure";
10
+ import { useMergeRefs } from "../hooks/useMergeRefs";
11
+ import { usePreviousValue } from "../hooks/usePreviousValue";
12
+ import { isNotNullish } from "../utils/nullish";
13
+ import { Box } from "./Box";
14
+ import { Icon } from "./Icon";
15
+ import { Input } from "./Input";
16
+ import { LakeButton } from "./LakeButton";
17
+ import { LakeCheckbox } from "./LakeCheckbox";
18
+ import { LakeRadio } from "./LakeRadio";
19
+ import { Popover } from "./Popover";
20
+ import { Space } from "./Space";
21
+ import { Stack } from "./Stack";
22
+ import { Tag } from "./Tag";
23
+ const styles = StyleSheet.create({
24
+ container: {
25
+ paddingRight: 12,
26
+ paddingBottom: 8,
27
+ },
28
+ shadowed: {
29
+ position: "absolute",
30
+ opacity: 0,
31
+ width: "100%",
32
+ height: "100%",
33
+ borderRadius: 4,
34
+ boxShadow: shadows.tile,
35
+ transitionDuration: "150ms",
36
+ transitionProperty: "opacity",
37
+ },
38
+ hovered: {
39
+ opacity: 1,
40
+ },
41
+ dropdown: {
42
+ marginTop: 4,
43
+ maxHeight: 400,
44
+ minWidth: 200,
45
+ },
46
+ itemHovered: {
47
+ backgroundColor: colors.gray[50],
48
+ },
49
+ content: {
50
+ paddingVertical: 12,
51
+ },
52
+ inputContent: {
53
+ padding: 24,
54
+ },
55
+ radio: {
56
+ display: "flex",
57
+ flexDirection: "row",
58
+ alignItems: "center",
59
+ height: 32,
60
+ paddingHorizontal: 24,
61
+ },
62
+ dateInput: {
63
+ width: 200,
64
+ },
65
+ value: {
66
+ maxWidth: 130,
67
+ whiteSpace: "nowrap",
68
+ },
69
+ buttonContainer: {
70
+ paddingHorizontal: spacings[24],
71
+ },
72
+ });
73
+ const FilterTag = forwardRef(({ onPress, onPressRemove, label, value = "", isActive }, forwardRef) => {
74
+ const ref = useRef(null);
75
+ const mergedRef = useMergeRefs(ref, forwardRef);
76
+ return (_jsx(Pressable, { ref: mergedRef, onPress: onPress, children: ({ hovered }) => (_jsxs(_Fragment, { children: [_jsx(View, { style: [styles.shadowed, hovered && styles.hovered] }), _jsx(Tag, { label: label, color: "current", onPressRemove: onPressRemove, children: _jsxs(Box, { direction: "row", alignItems: "center", children: [_jsx(Text, { numberOfLines: 1, style: styles.value, children: value }), _jsx(Space, { width: 4 }), _jsx(Icon, { color: colors.current.primary, name: isActive ? "chevron-up-filled" : "chevron-down-filled", size: 16 })] }) })] })) }));
77
+ });
78
+ function FilterRadio({ label, items, value, onValueChange, onPressRemove, autoOpen = false, }) {
79
+ const inputRef = useRef(null);
80
+ const [visible, { close, toggle }] = useDisclosure(autoOpen);
81
+ const currentValue = useMemo(() => items.find(i => i.value === value), [items, value]);
82
+ return (_jsxs(View, { style: styles.container, children: [_jsx(FilterTag, { label: label, onPress: toggle, ref: inputRef, onPressRemove: onPressRemove, isActive: visible, value: currentValue?.label }), _jsx(Popover, { role: "listbox", matchReferenceWidth: false, onDismiss: close, referenceRef: inputRef, returnFocus: false, visible: visible, children: _jsx(View, { style: styles.dropdown, children: _jsx(FlatList, { accessibilityRole: "list", data: items, contentContainerStyle: styles.content, keyExtractor: (_, index) => `filter-item-${index}`, renderItem: ({ item }) => {
83
+ const isSelected = value === item.value;
84
+ return (_jsxs(Pressable, { accessibilityRole: "radio", accessibilityChecked: isSelected, style: ({ hovered }) => [styles.radio, hovered && styles.itemHovered], onPress: () => {
85
+ onValueChange(item.value);
86
+ close();
87
+ }, children: [_jsx(LakeRadio, { value: isSelected }), _jsx(Space, { width: 12 }), _jsx(Text, { children: item.label })] }));
88
+ } }) }) })] }));
89
+ }
90
+ function FilterCheckbox({ label, items, checkAllLabel, value, onValueChange, applyButtonLabel, onPressRemove, autoOpen = false, }) {
91
+ const inputRef = useRef(null);
92
+ const [visible, { close, toggle }] = useDisclosure(autoOpen);
93
+ const [localValue, setLocalValue] = useState(value);
94
+ const values = useMemo(() => new Set(localValue), [localValue]);
95
+ const currentValue = useMemo(() => items.filter(item => values.has(item.value)), [items, values]);
96
+ const allChecked = checkAllLabel != null && values.size === items.length;
97
+ const listItems = useMemo(() => {
98
+ if (checkAllLabel == null) {
99
+ return items;
100
+ }
101
+ const checked = values.size === 0 ? false : values.size === items.length ? true : "mixed";
102
+ const checkAllItem = {
103
+ label: checkAllLabel,
104
+ checked,
105
+ };
106
+ return [checkAllItem, ...items];
107
+ }, [items, checkAllLabel, values]);
108
+ const save = useCallback(() => {
109
+ onValueChange(localValue);
110
+ close();
111
+ }, [onValueChange, localValue, close]);
112
+ useEffect(() => {
113
+ if (!visible) {
114
+ setLocalValue(value);
115
+ }
116
+ }, [visible, value]);
117
+ return (_jsxs(View, { style: styles.container, children: [_jsx(FilterTag, { label: label, onPress: toggle, ref: inputRef, onPressRemove: onPressRemove, isActive: visible, value: allChecked ? checkAllLabel : currentValue.map(item => item.label).join(", ") }), _jsx(Popover, { role: "listbox", matchReferenceWidth: false, onDismiss: close, referenceRef: inputRef, returnFocus: false, visible: visible, children: _jsxs(View, { style: styles.dropdown, children: [_jsx(FlatList, { accessibilityRole: "list", data: listItems, contentContainerStyle: styles.content, keyExtractor: (_, index) => `filter-item-${index}`, renderItem: ({ item }) => {
118
+ const isSelected = match(item)
119
+ .with({ checked: P.any }, ({ checked }) => checked)
120
+ .with({ value: P.any }, ({ value }) => values.has(value))
121
+ .exhaustive();
122
+ const onPress = match(item)
123
+ // Check all item
124
+ .with({ checked: P.any }, ({ checked }) => () => {
125
+ if (checked === true) {
126
+ setLocalValue(undefined);
127
+ }
128
+ else {
129
+ setLocalValue(items.map(item => item.value));
130
+ }
131
+ })
132
+ // Regular item
133
+ .with({ value: P.any }, ({ value }) => () => {
134
+ const nextValues = new Set([...values]);
135
+ if (isSelected === true) {
136
+ nextValues.delete(value);
137
+ }
138
+ else {
139
+ nextValues.add(value);
140
+ }
141
+ if (nextValues.size === 0) {
142
+ setLocalValue(undefined);
143
+ }
144
+ else {
145
+ setLocalValue([...nextValues]);
146
+ }
147
+ })
148
+ .exhaustive();
149
+ return (_jsxs(Pressable, { accessibilityRole: "radio", accessibilityChecked: isSelected, style: ({ hovered }) => [styles.radio, hovered && styles.itemHovered], onPress: onPress, children: [_jsx(LakeCheckbox, { value: isSelected }), _jsx(Space, { width: 12 }), _jsx(Text, { children: item.label })] }));
150
+ } }), _jsx(Space, { height: 8 }), _jsx(View, { style: styles.buttonContainer, children: _jsx(LakeButton, { color: "current", onPress: save, children: applyButtonLabel }) }), _jsx(Space, { height: 24 })] }) })] }));
151
+ }
152
+ function FilterDate({ label, initialValue, noValueText, submitText, dateFormat, rifmProps, validate, onSave, onPressRemove, autoOpen = false, }) {
153
+ const inputRef = useRef(null);
154
+ const [visible, { close, toggle }] = useDisclosure(autoOpen);
155
+ const { Field, submitForm, setFieldValue } = useForm({
156
+ date: {
157
+ initialValue: isNotNullish(initialValue) ? dayjs(initialValue).format(dateFormat) : "",
158
+ validate,
159
+ },
160
+ });
161
+ useEffect(() => {
162
+ setFieldValue("date", isNotNullish(initialValue) ? dayjs(initialValue).format(dateFormat) : "");
163
+ }, [initialValue, dateFormat, setFieldValue]);
164
+ const onSubmit = () => {
165
+ submitForm(values => {
166
+ if (hasDefinedKeys(values, ["date"])) {
167
+ const date = dayjs(values.date, dateFormat, true).toJSON();
168
+ onSave(date);
169
+ close();
170
+ }
171
+ });
172
+ };
173
+ return (_jsxs(View, { style: styles.container, children: [_jsx(FilterTag, { label: label, onPress: toggle, ref: inputRef, onPressRemove: onPressRemove, isActive: visible, value: isNotNullish(initialValue) ? dayjs(initialValue).format(dateFormat) : noValueText }), _jsx(Popover, { role: "listbox", matchReferenceWidth: false, onDismiss: close, referenceRef: inputRef, returnFocus: false, visible: visible, children: _jsxs(View, { style: [styles.dropdown, styles.inputContent], children: [_jsx(Field, { name: "date", children: ({ value, onChange, error }) => (_jsx(Rifm, { value: value, onChange: onChange, ...rifmProps, children: ({ value, onChange }) => (_jsx(Input, { label: label, error: error, size: "small", style: styles.dateInput, placeholder: dateFormat, value: value, onChange: onChange })) })) }), _jsx(LakeButton, { color: "current", onPress: onSubmit, children: submitText })] }) })] }));
174
+ }
175
+ function FilterInput({ label, initialValue = "", noValueText, submitText, autoOpen = false, placeholder, validate, onSave, onPressRemove, }) {
176
+ const inputRef = useRef(null);
177
+ const [visible, { close, toggle }] = useDisclosure(autoOpen);
178
+ const [value, setValue] = useState(initialValue);
179
+ const { Field, submitForm } = useForm({
180
+ input: {
181
+ initialValue,
182
+ validate,
183
+ },
184
+ });
185
+ const onSubmit = () => {
186
+ submitForm(values => {
187
+ if (hasDefinedKeys(values, ["input"])) {
188
+ setValue(values.input);
189
+ onSave(values.input);
190
+ close();
191
+ }
192
+ });
193
+ };
194
+ return (_jsxs(View, { style: styles.container, children: [_jsx(FilterTag, { label: label, onPress: toggle, ref: inputRef, onPressRemove: onPressRemove, isActive: visible, value: value === "" ? noValueText : value }), _jsx(Popover, { role: "listbox", matchReferenceWidth: false, onDismiss: close, referenceRef: inputRef, returnFocus: false, visible: visible, children: _jsxs(View, { style: [styles.dropdown, styles.inputContent], children: [_jsx(Field, { name: "input", children: ({ error, value, onChange }) => (_jsx(Input, { label: label, size: "small", error: error, style: styles.dateInput, placeholder: placeholder, value: value, onValueChange: onChange })) }), _jsx(LakeButton, { size: "small", color: "current", onPress: onSubmit, children: submitText })] }) })] }));
195
+ }
196
+ const getFilterValue = (_type, filters, name) => filters[name];
197
+ export const FiltersStack = ({ filters, openedFilters, definition, onChangeOpened, onChangeFilters, }) => {
198
+ const previousOpened = usePreviousValue(openedFilters);
199
+ const lastOpenedFilter = openedFilters.length > previousOpened.length
200
+ ? openedFilters[openedFilters.length - 1]
201
+ : undefined;
202
+ if (openedFilters.length === 0) {
203
+ return null;
204
+ }
205
+ return (_jsx(Stack, { direction: "row", wrap: true, children: openedFilters.map(filterName => {
206
+ const filterDefinition = definition[filterName];
207
+ if (typeof filterName !== "string" || filterDefinition == null) {
208
+ return null;
209
+ }
210
+ return (_jsx(View, { children: match(filterDefinition)
211
+ .with({ type: "radio" }, ({ type, label, items }) => (_jsx(FilterRadio, { label: label, items: items, autoOpen: lastOpenedFilter === filterName, onPressRemove: () => {
212
+ onChangeFilters({ ...filters, [filterName]: undefined });
213
+ onChangeOpened(openedFilters.filter(f => f !== filterName));
214
+ }, value: getFilterValue(type, filters, filterName), onValueChange: value => onChangeFilters({ ...filters, [filterName]: value }) })))
215
+ .with({ type: "checkbox" }, ({ type, label, items, checkAllLabel, submitText }) => (_jsx(FilterCheckbox, { label: label, items: items, checkAllLabel: checkAllLabel, autoOpen: lastOpenedFilter === filterName, applyButtonLabel: submitText, value: getFilterValue(type, filters, filterName), onValueChange: value => onChangeFilters({ ...filters, [filterName]: value }), onPressRemove: () => {
216
+ onChangeFilters({ ...filters, [filterName]: undefined });
217
+ onChangeOpened(openedFilters.filter(f => f !== filterName));
218
+ } })))
219
+ .with({ type: "date" }, ({ type, label, noValueText, submitText, dateFormat, rifmProps, validate }) => (_jsx(FilterDate, { label: label, noValueText: noValueText, submitText: submitText, autoOpen: lastOpenedFilter === filterName, dateFormat: dateFormat, rifmProps: rifmProps, validate: validate, initialValue: getFilterValue(type, filters, filterName), onSave: value => onChangeFilters({ ...filters, [filterName]: value }), onPressRemove: () => {
220
+ onChangeFilters({ ...filters, [filterName]: undefined });
221
+ onChangeOpened(openedFilters.filter(f => f !== filterName));
222
+ } })))
223
+ .with({ type: "input" }, ({ type, label, placeholder, noValueText, submitText, validate }) => (_jsx(FilterInput, { label: label, placeholder: placeholder, noValueText: noValueText, submitText: submitText, autoOpen: lastOpenedFilter === filterName, validate: validate, initialValue: getFilterValue(type, filters, filterName), onSave: value => onChangeFilters({ ...filters, [filterName]: value }), onPressRemove: () => {
224
+ onChangeFilters({ ...filters, [filterName]: undefined });
225
+ onChangeOpened(openedFilters.filter(f => f !== filterName));
226
+ } })))
227
+ .exhaustive() }, filterName));
228
+ }) }));
229
+ };
@@ -0,0 +1,104 @@
1
+ /**
2
+ * ## FixedListView
3
+ *
4
+ * The FixedListView is a component designed to render big amounts of tabular data.
5
+ *
6
+ * For usability, the data can be display in three types of columns:
7
+ *
8
+ * - Sticked to start columns (usually the main identifier, always visible)
9
+ * - Center columns (scrollable columns, with additional information)
10
+ * - Sticked to end columns (so that some actions are always accesible at the end of each line)
11
+ *
12
+ * ┌────────────────────────────────────────────────────────────────────────────────────────┐
13
+ * │ ┌────────────────┐ ┌────────────────────────────────────────┐ ┌────────────────┐ │
14
+ * │ │ ╔════════════╗ │ │ ╔════════════════════════════════════╗ │ │ ╔════════════╗ │ │
15
+ * │ │ ║ Header ║ │ │ ║ Header ║ │ │ ║ Header ║ │ ▲ │
16
+ * │ │ ║ ║ │ │ ║◀──────────────────────────────────▶║ │ │ ║ ║ │ │ │
17
+ * │ │ ╚════════════╝ │ │ ╚════════════════════════════════════╝ │ │ ╚════════════╝ │ │ │
18
+ * │ │ │ │ │ │ │ │ │
19
+ * │ │ ┌───────────┐ │ │ ┌────────────────────────────────────┐ │ │ ┌────────────┐ │ │ │
20
+ * │ │ │ Cell A1 │──┼─┼▷│ Cell B1 ├─┼─┼─▷ Cell C1 │ │ │ │
21
+ * │ │ └───────────┘ │ │ └────────────────────────────────────┘ │ │ └────────────┘ │ │ │
22
+ * │ │ ┌───────────┐ │ │ ┌────────────────────────────────────┐ │ │ ┌────────────┐ │ │ │
23
+ * │ │ │ Cell A2 │──┼─┼▷│ Cell B2 │─┼─┼─▷ Cell C2 │ │ │ │
24
+ * │ │ └───────────┘ │ │ └────────────────────────────────────┘ │ │ └────────────┘ │ │ │
25
+ * │ │ │ │ │ │ │ │ │
26
+ * │ │ │ │ ◀────────────────────────────────────▶ │ │ │ ▼ │
27
+ * └─┴────────────────┴─┴────────────────────────────────────────┴─┴────────────────┴───────┘
28
+ *
29
+ * ╔════╗
30
+ * ║ ║ Sticky
31
+ * ╚════╝
32
+ * ◀────▶ Scrollable
33
+ * ─────▷ Emulated tab order
34
+ *
35
+ */
36
+ import { ReactElement, ReactNode } from "react";
37
+ import { IconName } from "./Icon";
38
+ export type ColumnTitleConfig<ExtraInfo> = {
39
+ title: string;
40
+ extraInfo: ExtraInfo;
41
+ id: string;
42
+ };
43
+ export type ColumnCellConfig<T, ExtraInfo> = {
44
+ columnId: string;
45
+ item: T;
46
+ index: number;
47
+ extraInfo: ExtraInfo;
48
+ isHovered: boolean;
49
+ };
50
+ export type LinkConfig<T, ExtraInfo> = {
51
+ item: T;
52
+ index: number;
53
+ extraInfo: ExtraInfo;
54
+ };
55
+ export type ColumnConfig<T, ExtraInfo> = {
56
+ id: string;
57
+ width: number;
58
+ title: string;
59
+ renderTitle: (props: ColumnTitleConfig<ExtraInfo>) => ReactNode;
60
+ renderCell: (props: ColumnCellConfig<T, ExtraInfo>) => ReactNode;
61
+ };
62
+ type Mode = "tile" | "plain";
63
+ export type FixedListViewProps<T, ExtraInfo> = {
64
+ mode?: Mode;
65
+ data: T[];
66
+ keyExtractor: (item: T, index: number) => string;
67
+ highlightedRowId?: string;
68
+ headerHeight: number;
69
+ rowHeight: number;
70
+ rowVerticalSpacing: number;
71
+ extraInfo: ExtraInfo;
72
+ stickedToStartColumns?: ColumnConfig<T, ExtraInfo>[];
73
+ columns: ColumnConfig<T, ExtraInfo>[];
74
+ stickedToEndColumns?: ColumnConfig<T, ExtraInfo>[];
75
+ renderThreshold?: number;
76
+ onEndReached?: () => void;
77
+ onEndReachedThresholdPx?: number;
78
+ getRowLink?: (config: LinkConfig<T, ExtraInfo>) => ReactElement | undefined;
79
+ renderEmptyList?: () => ReactNode;
80
+ loading?: {
81
+ isLoading: boolean;
82
+ count: number;
83
+ };
84
+ };
85
+ export declare const FixedListView: <T, ExtraInfo>({ data: originalData, mode, keyExtractor, highlightedRowId, rowHeight, rowVerticalSpacing, headerHeight, renderThreshold, stickedToStartColumns: initialStickedToStartColumns, columns: initialColumns, stickedToEndColumns: initialStickedToEndColumns, extraInfo, onEndReached, onEndReachedThresholdPx, getRowLink, renderEmptyList, loading, }: FixedListViewProps<T, ExtraInfo>) => JSX.Element;
86
+ type PlaceholderProps = {
87
+ count: number;
88
+ rowHeight: number;
89
+ rowVerticalSpacing: number;
90
+ groupHeaderHeight?: number;
91
+ headerHeight?: number;
92
+ paddingHorizontal?: number;
93
+ };
94
+ export declare const FixedListViewPlaceholder: ({ count, rowHeight, rowVerticalSpacing, groupHeaderHeight, headerHeight, paddingHorizontal, }: PlaceholderProps) => JSX.Element;
95
+ export declare const PlainListViewPlaceholder: ({ count, rowHeight, rowVerticalSpacing, groupHeaderHeight, headerHeight, paddingHorizontal, }: PlaceholderProps) => JSX.Element;
96
+ type EmptyProps = {
97
+ icon: IconName;
98
+ borderedIcon?: boolean;
99
+ title?: string;
100
+ subtitle?: ReactNode;
101
+ children?: ReactNode;
102
+ };
103
+ export declare const FixedListViewEmpty: ({ icon, borderedIcon, title, subtitle, children, }: EmptyProps) => JSX.Element;
104
+ export {};