@swan-io/lake 8.6.0 → 8.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/BottomPanel.js +2 -1
- package/src/components/FixedListView.js +2 -1
- package/src/components/FlatList.d.ts +3 -2
- package/src/components/FlatList.js +10 -5
- package/src/components/Form.d.ts +1 -0
- package/src/components/LakeScrollView.js +2 -1
- package/src/components/PlainListView.js +2 -1
- package/src/components/Popover.js +2 -1
- package/src/components/ScrollView.d.ts +23 -0
- package/src/components/ScrollView.js +99 -0
- package/src/components/SectionList.d.ts +3 -2
- package/src/components/SectionList.js +10 -5
- package/src/components/SidebarNavigationTracker.d.ts +1 -1
- package/src/components/SidebarNavigationTracker.js +2 -1
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from "react";
|
|
3
|
-
import { Pressable,
|
|
3
|
+
import { Pressable, StyleSheet, View } from "react-native";
|
|
4
4
|
import { commonStyles } from "../constants/commonStyles";
|
|
5
5
|
import { backgroundColor, radii, shadows } from "../constants/design";
|
|
6
6
|
import { useBodyClassName } from "../hooks/useBodyClassName";
|
|
7
7
|
import { FocusTrap } from "./FocusTrap";
|
|
8
8
|
import { LoadingView } from "./LoadingView";
|
|
9
9
|
import { Portal } from "./Portal";
|
|
10
|
+
import { ScrollView } from "./ScrollView";
|
|
10
11
|
import { Suspendable } from "./Suspendable";
|
|
11
12
|
import { TransitionView } from "./TransitionView";
|
|
12
13
|
const BACKGROUND_COLOR = "rgba(0, 0, 0, 0.6)";
|
|
@@ -35,7 +35,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
35
35
|
*
|
|
36
36
|
*/
|
|
37
37
|
import { cloneElement, Fragment, memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
38
|
-
import {
|
|
38
|
+
import { StyleSheet, View, } from "react-native";
|
|
39
39
|
import { match } from "ts-pattern";
|
|
40
40
|
import { v4 as uuid } from "uuid";
|
|
41
41
|
import { backgroundColor, colors, invariantColors, radii, shadows, spacings, } from "../constants/design";
|
|
@@ -48,6 +48,7 @@ import { BorderedIcon } from "./BorderedIcon";
|
|
|
48
48
|
import { Icon } from "./Icon";
|
|
49
49
|
import { LakeHeading } from "./LakeHeading";
|
|
50
50
|
import { LakeText } from "./LakeText";
|
|
51
|
+
import { ScrollView } from "./ScrollView";
|
|
51
52
|
import { Space } from "./Space";
|
|
52
53
|
const HORIZONTAL_SAFE_AREA = 10;
|
|
53
54
|
export const SCROLLBAR_RESERVED_SPACE = 20;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ForwardedRef, ReactNode } from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { StyleProp, ViewStyle, WebRole } from "react-native";
|
|
3
|
+
import { ScrollViewProps, ScrollViewRef } from "./ScrollView";
|
|
4
|
+
export type FlatListRef = ScrollViewRef;
|
|
4
5
|
export type ListRenderItemInfo<T> = {
|
|
5
6
|
item: T;
|
|
6
7
|
index: number;
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment, forwardRef, useEffect, useRef } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { StyleSheet, View } from "react-native";
|
|
4
|
+
import { ScrollView } from "./ScrollView";
|
|
4
5
|
const styles = StyleSheet.create({
|
|
5
6
|
scrollTracker: {
|
|
6
7
|
position: "absolute",
|
|
7
8
|
pointerEvents: "none",
|
|
8
|
-
left: 0,
|
|
9
|
-
bottom: 0,
|
|
10
9
|
right: 0,
|
|
10
|
+
bottom: 0,
|
|
11
11
|
},
|
|
12
12
|
});
|
|
13
|
-
const FlatListWithRef = ({ ItemSeparatorComponent, ListEmptyComponent, ListFooterComponent, ListHeaderComponent, contentContainerStyle, data, horizontal = false, keyExtractor, onEndReached, onEndReachedThresholdPx = 200, onKeyDown, onScroll, renderItem, role, scrollEventThrottle =
|
|
13
|
+
const FlatListWithRef = ({ ItemSeparatorComponent, ListEmptyComponent, ListFooterComponent, ListHeaderComponent, contentContainerStyle, data, horizontal = false, keyExtractor, onEndReached, onEndReachedThresholdPx = 200, onKeyDown, onScroll, renderItem, role, scrollEventThrottle = 16, showsScrollIndicators = true, style, }, forwardedRef) => {
|
|
14
14
|
const scrollTrackerRef = useRef(null);
|
|
15
|
+
const scrollTrackerStyle = horizontal
|
|
16
|
+
? { top: 0, width: onEndReachedThresholdPx }
|
|
17
|
+
: { left: 0, height: onEndReachedThresholdPx };
|
|
15
18
|
useEffect(() => {
|
|
16
19
|
const element = scrollTrackerRef.current;
|
|
17
20
|
if (element != null) {
|
|
@@ -29,6 +32,8 @@ const FlatListWithRef = ({ ItemSeparatorComponent, ListEmptyComponent, ListFoote
|
|
|
29
32
|
}
|
|
30
33
|
// re-create an observer only on list length change
|
|
31
34
|
}, [data.length]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
32
|
-
return (_jsxs(ScrollView, { contentContainerStyle: contentContainerStyle, horizontal: horizontal, onKeyDown: onKeyDown, onScroll: onScroll, ref: forwardedRef, role: role, scrollEventThrottle: scrollEventThrottle,
|
|
35
|
+
return (_jsxs(ScrollView, { contentContainerStyle: contentContainerStyle, horizontal: horizontal, onKeyDown: onKeyDown, onScroll: onScroll, ref: forwardedRef, role: role, scrollEventThrottle: scrollEventThrottle, showsScrollIndicators: showsScrollIndicators, style: style, children: [ListHeaderComponent, data.length <= 0
|
|
36
|
+
? ListEmptyComponent
|
|
37
|
+
: data.map((item, index) => (_jsxs(Fragment, { children: [index !== 0 && ItemSeparatorComponent, renderItem({ item, index })] }, keyExtractor(item, index)))), ListFooterComponent, _jsx(View, { role: "none", ref: scrollTrackerRef, style: [styles.scrollTracker, scrollTrackerStyle] })] }));
|
|
33
38
|
};
|
|
34
39
|
export const FlatList = forwardRef(FlatListWithRef);
|
package/src/components/Form.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export declare const Form: import("react").MemoExoticComponent<import("react").F
|
|
|
14
14
|
onKeyDownCapture?: ((event: NativeSyntheticEvent<import("react").KeyboardEvent<Element>>) => void) | undefined;
|
|
15
15
|
onKeyUp?: ((event: NativeSyntheticEvent<import("react").KeyboardEvent<Element>>) => void) | undefined;
|
|
16
16
|
onKeyUpCapture?: ((event: NativeSyntheticEvent<import("react").KeyboardEvent<Element>>) => void) | undefined;
|
|
17
|
+
onScroll?: ((event: NativeSyntheticEvent<import("react").UIEvent<Element, UIEvent>>) => void) | undefined;
|
|
17
18
|
collapsable?: boolean | undefined;
|
|
18
19
|
needsOffscreenAlphaCompositing?: boolean | undefined;
|
|
19
20
|
renderToHardwareTextureAndroid?: boolean | undefined;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useState } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { StyleSheet, View } from "react-native";
|
|
4
4
|
import { backgroundColor } from "../constants/design";
|
|
5
|
+
import { ScrollView } from "./ScrollView";
|
|
5
6
|
const HORIZONTAL_SAFE_AREA = 20;
|
|
6
7
|
const styles = StyleSheet.create({
|
|
7
8
|
root: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { cloneElement, Fragment, useCallback, useEffect, useId, useMemo, useRef, useState, } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { StyleSheet, View } from "react-native";
|
|
4
4
|
import { commonStyles } from "../constants/commonStyles";
|
|
5
5
|
import { backgroundColor, breakpoints, colors, spacings } from "../constants/design";
|
|
6
6
|
import { useHover } from "../hooks/useHover";
|
|
@@ -8,6 +8,7 @@ import { isNotNullish, isNullish } from "../utils/nullish";
|
|
|
8
8
|
import { PlainListViewPlaceholder, } from "./FixedListView";
|
|
9
9
|
import { LakeHeading } from "./LakeHeading";
|
|
10
10
|
import { ResponsiveContainer } from "./ResponsiveContainer";
|
|
11
|
+
import { ScrollView } from "./ScrollView";
|
|
11
12
|
const INHERIT = "inherit";
|
|
12
13
|
const styles = StyleSheet.create({
|
|
13
14
|
root: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
-
import { Pressable,
|
|
3
|
+
import { Pressable, StyleSheet, View, } from "react-native";
|
|
4
4
|
import { match, P } from "ts-pattern";
|
|
5
5
|
import { animations, backgroundColor, radii, shadows, spacings, } from "../constants/design";
|
|
6
6
|
import { useContextualLayer } from "../hooks/useContextualLayer";
|
|
@@ -9,6 +9,7 @@ import { noop } from "../utils/function";
|
|
|
9
9
|
import { BottomPanel } from "./BottomPanel";
|
|
10
10
|
import { FocusTrap } from "./FocusTrap";
|
|
11
11
|
import { Portal } from "./Portal";
|
|
12
|
+
import { ScrollView } from "./ScrollView";
|
|
12
13
|
import { TransitionView } from "./TransitionView";
|
|
13
14
|
const styles = StyleSheet.create({
|
|
14
15
|
container: {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { NativeScrollEvent, NativeSyntheticEvent, StyleProp, ViewProps, ViewStyle } from "react-native";
|
|
3
|
+
export type ScrollViewRef = {
|
|
4
|
+
scrollTo: (event: {
|
|
5
|
+
x?: number;
|
|
6
|
+
y?: number;
|
|
7
|
+
animated?: boolean;
|
|
8
|
+
}) => void;
|
|
9
|
+
};
|
|
10
|
+
export type ScrollViewProps = ViewProps & {
|
|
11
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
12
|
+
horizontal?: boolean;
|
|
13
|
+
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
14
|
+
scrollEventThrottle?: number;
|
|
15
|
+
showsScrollIndicators?: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare const ScrollView: import("react").ForwardRefExoticComponent<ViewProps & {
|
|
18
|
+
contentContainerStyle?: StyleProp<ViewStyle>;
|
|
19
|
+
horizontal?: boolean | undefined;
|
|
20
|
+
onScroll?: ((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined;
|
|
21
|
+
scrollEventThrottle?: number | undefined;
|
|
22
|
+
showsScrollIndicators?: boolean | undefined;
|
|
23
|
+
} & import("react").RefAttributes<ScrollViewRef>>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef, useCallback, useImperativeHandle, useRef, } from "react";
|
|
3
|
+
import { StyleSheet, View, } from "react-native";
|
|
4
|
+
import { useMergeRefs } from "../hooks/useMergeRefs";
|
|
5
|
+
const styles = StyleSheet.create({
|
|
6
|
+
base: {
|
|
7
|
+
WebkitOverflowScrolling: "touch",
|
|
8
|
+
flexDirection: "column",
|
|
9
|
+
flexGrow: 1,
|
|
10
|
+
flexShrink: 1,
|
|
11
|
+
overflowX: "hidden",
|
|
12
|
+
overflowY: "auto",
|
|
13
|
+
transform: "translateZ(0)",
|
|
14
|
+
},
|
|
15
|
+
horizontal: {
|
|
16
|
+
flexDirection: "row",
|
|
17
|
+
overflowX: "auto",
|
|
18
|
+
overflowY: "hidden",
|
|
19
|
+
},
|
|
20
|
+
contentHorizontal: {
|
|
21
|
+
flexDirection: "row",
|
|
22
|
+
},
|
|
23
|
+
hideScrollbars: {
|
|
24
|
+
scrollbarWidth: "none",
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
const normalizeScrollEvent = (event) => {
|
|
28
|
+
const target = event.target;
|
|
29
|
+
const contentOffset = {
|
|
30
|
+
get x() {
|
|
31
|
+
return target.scrollLeft;
|
|
32
|
+
},
|
|
33
|
+
get y() {
|
|
34
|
+
return target.scrollTop;
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
const contentSize = {
|
|
38
|
+
get height() {
|
|
39
|
+
return target.scrollHeight;
|
|
40
|
+
},
|
|
41
|
+
get width() {
|
|
42
|
+
return target.scrollWidth;
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const layoutMeasurement = {
|
|
46
|
+
get height() {
|
|
47
|
+
return target.offsetHeight;
|
|
48
|
+
},
|
|
49
|
+
get width() {
|
|
50
|
+
return target.offsetWidth;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
nativeEvent: { contentOffset, contentSize, layoutMeasurement },
|
|
55
|
+
timeStamp: Date.now(),
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
const shouldEmitScrollEvent = (state, eventThrottle) => !state.scrolling || (eventThrottle > 0 && Date.now() - state.lastTick >= eventThrottle);
|
|
59
|
+
export const ScrollView = forwardRef(({ children, contentContainerStyle, horizontal = false, onScroll, scrollEventThrottle = 16, showsScrollIndicators = true, style, ...viewProps }, forwardedRef) => {
|
|
60
|
+
const innerRef = useRef(null);
|
|
61
|
+
const stateRef = useRef({ lastTick: 0, scrolling: false });
|
|
62
|
+
const timeoutRef = useRef(null);
|
|
63
|
+
const mergedRef = useMergeRefs(innerRef, forwardedRef);
|
|
64
|
+
const handleOnScroll = useCallback((event) => {
|
|
65
|
+
event.stopPropagation();
|
|
66
|
+
// A scroll happened, so the scroll resets the scrollend timeout.
|
|
67
|
+
if (timeoutRef.current != null) {
|
|
68
|
+
clearTimeout(timeoutRef.current);
|
|
69
|
+
}
|
|
70
|
+
timeoutRef.current = setTimeout(() => {
|
|
71
|
+
stateRef.current.scrolling = false;
|
|
72
|
+
onScroll === null || onScroll === void 0 ? void 0 : onScroll(normalizeScrollEvent(event));
|
|
73
|
+
}, 100);
|
|
74
|
+
if (shouldEmitScrollEvent(stateRef.current, scrollEventThrottle)) {
|
|
75
|
+
stateRef.current.scrolling = true;
|
|
76
|
+
stateRef.current.lastTick = Date.now();
|
|
77
|
+
onScroll === null || onScroll === void 0 ? void 0 : onScroll(normalizeScrollEvent(event));
|
|
78
|
+
}
|
|
79
|
+
}, [onScroll, scrollEventThrottle]);
|
|
80
|
+
const scrollTo = useCallback(({ x = 0, y = 0, animated = true }) => {
|
|
81
|
+
const element = innerRef.current;
|
|
82
|
+
if (element != null) {
|
|
83
|
+
if (typeof element.scroll === "function") {
|
|
84
|
+
element.scroll({ top: y, left: x, behavior: !animated ? "auto" : "smooth" });
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
element.scrollTop = y;
|
|
88
|
+
element.scrollLeft = x;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}, []);
|
|
92
|
+
useImperativeHandle(innerRef, () => ({ scrollTo }));
|
|
93
|
+
return (_jsx(View, { ...viewProps, ref: mergedRef, onScroll: handleOnScroll, style: [
|
|
94
|
+
styles.base,
|
|
95
|
+
style,
|
|
96
|
+
horizontal && styles.horizontal,
|
|
97
|
+
!showsScrollIndicators && styles.hideScrollbars,
|
|
98
|
+
], children: _jsx(View, { style: [horizontal && styles.contentHorizontal, contentContainerStyle], children: children }) }));
|
|
99
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ForwardedRef, ReactNode } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { StyleProp, ViewStyle, WebRole } from "react-native";
|
|
3
3
|
import { ListRenderItemInfo } from "./FlatList";
|
|
4
|
-
|
|
4
|
+
import { ScrollViewProps, ScrollViewRef } from "./ScrollView";
|
|
5
|
+
export type SectionListRef = ScrollViewRef;
|
|
5
6
|
type Section<T> = {
|
|
6
7
|
title: string;
|
|
7
8
|
data: T[];
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Fragment, forwardRef, useEffect, useId, useRef } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { StyleSheet, View } from "react-native";
|
|
4
|
+
import { ScrollView } from "./ScrollView";
|
|
4
5
|
const styles = StyleSheet.create({
|
|
5
6
|
scrollTracker: {
|
|
6
7
|
position: "absolute",
|
|
7
8
|
pointerEvents: "none",
|
|
8
|
-
bottom: 0,
|
|
9
|
-
left: 0,
|
|
10
9
|
right: 0,
|
|
10
|
+
bottom: 0,
|
|
11
11
|
},
|
|
12
12
|
});
|
|
13
|
-
const SectionListWithRef = ({ ItemSeparatorComponent, ListEmptyComponent, ListFooterComponent, ListHeaderComponent, contentContainerStyle, horizontal = false, keyExtractor, onEndReached, onEndReachedThresholdPx = 200, onKeyDown, onScroll, renderItem, renderSectionHeader, role, scrollEventThrottle =
|
|
13
|
+
const SectionListWithRef = ({ ItemSeparatorComponent, ListEmptyComponent, ListFooterComponent, ListHeaderComponent, contentContainerStyle, horizontal = false, keyExtractor, onEndReached, onEndReachedThresholdPx = 200, onKeyDown, onScroll, renderItem, renderSectionHeader, role, scrollEventThrottle = 16, sections, showsScrollIndicators = true, style, }, forwardedRef) => {
|
|
14
14
|
const groupId = useId();
|
|
15
15
|
const scrollTrackerRef = useRef(null);
|
|
16
|
+
const scrollTrackerStyle = horizontal
|
|
17
|
+
? { top: 0, width: onEndReachedThresholdPx }
|
|
18
|
+
: { left: 0, height: onEndReachedThresholdPx };
|
|
16
19
|
useEffect(() => {
|
|
17
20
|
const element = scrollTrackerRef.current;
|
|
18
21
|
if (element != null) {
|
|
@@ -30,6 +33,8 @@ const SectionListWithRef = ({ ItemSeparatorComponent, ListEmptyComponent, ListFo
|
|
|
30
33
|
}
|
|
31
34
|
// re-create an observer only on list length change
|
|
32
35
|
}, [sections.length]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
33
|
-
return (_jsxs(ScrollView, { contentContainerStyle: contentContainerStyle, horizontal: horizontal, onKeyDown: onKeyDown, onScroll: onScroll, ref: forwardedRef, role: role, scrollEventThrottle: scrollEventThrottle,
|
|
36
|
+
return (_jsxs(ScrollView, { contentContainerStyle: contentContainerStyle, horizontal: horizontal, onKeyDown: onKeyDown, onScroll: onScroll, ref: forwardedRef, role: role, scrollEventThrottle: scrollEventThrottle, showsScrollIndicators: showsScrollIndicators, style: style, children: [ListHeaderComponent, sections.length <= 0
|
|
37
|
+
? ListEmptyComponent
|
|
38
|
+
: sections.map(section => (_jsxs(Fragment, { children: [renderSectionHeader === null || renderSectionHeader === void 0 ? void 0 : renderSectionHeader(section), section.data.map((item, index) => (_jsxs(Fragment, { children: [index !== 0 && ItemSeparatorComponent, renderItem({ item, index })] }, keyExtractor(item, index))))] }, `group-${groupId}-${section.title}`))), ListFooterComponent, _jsx(View, { role: "none", ref: scrollTrackerRef, style: [styles.scrollTracker, scrollTrackerStyle] })] }));
|
|
34
39
|
};
|
|
35
40
|
export const SectionList = forwardRef(SectionListWithRef);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
3
|
-
import {
|
|
3
|
+
import { StyleSheet, View } from "react-native";
|
|
4
|
+
import { ScrollView } from "./ScrollView";
|
|
4
5
|
const styles = StyleSheet.create({
|
|
5
6
|
track: {
|
|
6
7
|
position: "absolute",
|