Skip to content

Commit fd0bd6b

Browse files
committed
feat: make positional adjustment of the list container better
1 parent 424afa7 commit fd0bd6b

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

src/components/Anchor.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ import {
66
View,
77
type TextStyle,
88
Dimensions,
9+
Platform,
910
} from 'react-native';
1011
import useStyles from '../hooks/useStyles';
1112
import ChevronDownIcon from '../icons/ChevronDownIcon';
1213
import type { IconStyle, LayoutRect, Option } from '../types';
1314
import Selections from './Selections';
1415
import CloseIcon from '../icons/CloseIcon';
1516
import { StyleSheet } from 'react-native';
17+
import debounce from 'lodash/debounce';
1618

1719
interface Props extends Omit<PressableProps, 'onLayout'> {
1820
placeholder?: string;
@@ -87,18 +89,31 @@ export default function Anchor({
8789
const onLayoutRef = useRef(onLayout);
8890

8991
useEffect(() => {
90-
const onViewLayout = () => {
92+
const updatePosition = () => {
9193
if (ref.current) {
9294
ref.current.measure((x, y, width, height, pageX, pageY) => {
9395
onLayoutRef.current({ x, y, width, height, left: pageX, top: pageY });
9496
});
9597
}
9698
};
97-
const subscription = Dimensions.addEventListener('change', onViewLayout);
98-
onViewLayout();
99+
100+
const debouncedUpdate = debounce(updatePosition, 16);
101+
102+
const subscription = Dimensions.addEventListener('change', debouncedUpdate);
103+
104+
// Track scroll events on web
105+
if (Platform.OS === 'web' && window) {
106+
window.addEventListener('scroll', debouncedUpdate, true);
107+
}
108+
109+
updatePosition();
99110

100111
return () => {
101112
subscription.remove();
113+
debouncedUpdate.cancel();
114+
if (Platform.OS === 'web') {
115+
window.removeEventListener('scroll', debouncedUpdate, true);
116+
}
102117
};
103118
}, []);
104119

src/components/ListContainer.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ export default function ListContainer({
3737

3838
const top = useMemo(() => {
3939
if (Platform.OS === 'web' && avoidBottom === 'position') {
40-
if (height - (position?.y ?? 0) < listHeight + 80) {
41-
return height - listHeight - 80;
42-
}
40+
const maxTop = height - listHeight - 80;
41+
const preferredTop = position?.y ?? 0;
42+
return Math.min(preferredTop, maxTop);
4343
}
4444
return position?.y ?? 0;
4545
}, [height, listHeight, position?.y, avoidBottom]);
@@ -59,7 +59,7 @@ export default function ListContainer({
5959
left,
6060
right,
6161
maxHeight: 400,
62-
position: 'absolute',
62+
position: 'fixed' as any, // this style is only applied on web
6363
paddingVertical: tokens.size.sm,
6464
marginTop: tokens.size.xl + tokens.size.sm,
6565
gap: tokens.size.sm,

tsconfig.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22
"compilerOptions": {
33
"rootDir": ".",
44
"paths": {
5-
"@devrue/rn-select": ["./src/index"]
5+
"@devrue/rn-select": [
6+
"./src/index"
7+
]
68
},
79
"allowUnreachableCode": false,
810
"allowUnusedLabels": false,
911
"esModuleInterop": true,
1012
"forceConsistentCasingInFileNames": true,
1113
"jsx": "react",
12-
"lib": ["esnext"],
14+
"lib": [
15+
"esnext",
16+
"DOM"
17+
],
1318
"module": "esnext",
1419
"moduleResolution": "node",
1520
"noFallthroughCasesInSwitch": true,
@@ -25,4 +30,4 @@
2530
"target": "esnext",
2631
"verbatimModuleSyntax": true
2732
}
28-
}
33+
}

0 commit comments

Comments
 (0)