Skip to content

Commit 9b3de98

Browse files
committed
chore: address review comments
1 parent 0b031b9 commit 9b3de98

4 files changed

Lines changed: 156 additions & 23 deletions

File tree

apps/computer-vision/components/ModelPicker.tsx

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useEffect, useRef, useState } from 'react';
22
import {
3-
View,
3+
Dimensions,
4+
ScrollView,
45
StyleSheet,
56
Text,
67
TouchableOpacity,
7-
ScrollView,
8+
View,
89
} from 'react-native';
910

1011
export type ModelOption<T> = {
@@ -20,6 +21,8 @@ type Props<T> = {
2021
disabled?: boolean;
2122
};
2223

24+
const DROPDOWN_MAX_HEIGHT = 200;
25+
2326
export function ModelPicker<T>({
2427
models,
2528
selectedModel,
@@ -28,18 +31,44 @@ export function ModelPicker<T>({
2831
disabled,
2932
}: Props<T>) {
3033
const [open, setOpen] = useState(false);
34+
const [triggerHeight, setTriggerHeight] = useState(0);
35+
const [expandUp, setExpandUp] = useState(false);
36+
const triggerRef = useRef<React.ComponentRef<typeof TouchableOpacity>>(null);
3137
const selected = models.find((m) => m.value === selectedModel);
3238

3339
useEffect(() => {
3440
if (disabled) setOpen(false);
3541
}, [disabled]);
3642

43+
const handleLayout = () => {
44+
triggerRef.current?.measure(
45+
(
46+
_x: number,
47+
_y: number,
48+
_width: number,
49+
height: number,
50+
_pageX: number,
51+
pageY: number
52+
) => {
53+
setTriggerHeight(height);
54+
const spaceBelow = Dimensions.get('window').height - (pageY + height);
55+
setExpandUp(spaceBelow < DROPDOWN_MAX_HEIGHT);
56+
}
57+
);
58+
};
59+
60+
const dropdownPosition = expandUp
61+
? { bottom: triggerHeight + 2 }
62+
: { top: triggerHeight + 2 };
63+
3764
return (
3865
<View style={styles.container}>
3966
<TouchableOpacity
67+
ref={triggerRef}
4068
style={[styles.trigger, disabled && styles.triggerDisabled]}
4169
onPress={() => !disabled && setOpen((v) => !v)}
4270
activeOpacity={disabled ? 1 : 0.7}
71+
onLayout={handleLayout}
4372
>
4473
{label && <Text style={styles.label}>{label}</Text>}
4574
<Text style={styles.triggerText}>{selected?.label ?? '—'}</Text>
@@ -48,7 +77,7 @@ export function ModelPicker<T>({
4877

4978
{open && (
5079
<ScrollView
51-
style={styles.dropdown}
80+
style={[styles.dropdown, dropdownPosition]}
5281
nestedScrollEnabled
5382
keyboardShouldPersistTaps="handled"
5483
>
@@ -81,7 +110,12 @@ export function ModelPicker<T>({
81110
}
82111

83112
const styles = StyleSheet.create({
84-
container: { marginHorizontal: 12, marginVertical: 4, alignSelf: 'stretch' },
113+
container: {
114+
marginHorizontal: 12,
115+
marginVertical: 4,
116+
alignSelf: 'stretch',
117+
zIndex: 100,
118+
},
85119
trigger: {
86120
flexDirection: 'row',
87121
alignItems: 'center',
@@ -112,12 +146,20 @@ const styles = StyleSheet.create({
112146
marginLeft: 6,
113147
},
114148
dropdown: {
149+
position: 'absolute',
150+
left: 0,
151+
right: 0,
115152
borderWidth: 1,
116153
borderColor: '#C1C6E5',
117154
borderRadius: 8,
118155
backgroundColor: '#fff',
119-
maxHeight: 200,
120-
marginTop: 2,
156+
maxHeight: DROPDOWN_MAX_HEIGHT,
157+
zIndex: 100,
158+
elevation: 4,
159+
shadowColor: '#000',
160+
shadowOffset: { width: 0, height: 2 },
161+
shadowOpacity: 0.1,
162+
shadowRadius: 4,
121163
},
122164
option: {
123165
paddingHorizontal: 12,

apps/llm/components/ModelPicker.tsx

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import React, { useState } from 'react';
1+
import React, { useEffect, useRef, useState } from 'react';
22
import {
3-
View,
3+
Dimensions,
4+
ScrollView,
45
StyleSheet,
56
Text,
67
TouchableOpacity,
7-
ScrollView,
8+
View,
89
} from 'react-native';
910

1011
export type ModelOption<T> = {
@@ -20,6 +21,8 @@ type Props<T> = {
2021
disabled?: boolean;
2122
};
2223

24+
const DROPDOWN_MAX_HEIGHT = 200;
25+
2326
export function ModelPicker<T>({
2427
models,
2528
selectedModel,
@@ -28,14 +31,44 @@ export function ModelPicker<T>({
2831
disabled,
2932
}: Props<T>) {
3033
const [open, setOpen] = useState(false);
34+
const [triggerHeight, setTriggerHeight] = useState(0);
35+
const [expandUp, setExpandUp] = useState(false);
36+
const triggerRef = useRef<React.ComponentRef<typeof TouchableOpacity>>(null);
3137
const selected = models.find((m) => m.value === selectedModel);
3238

39+
useEffect(() => {
40+
if (disabled) setOpen(false);
41+
}, [disabled]);
42+
43+
const handleLayout = () => {
44+
triggerRef.current?.measure(
45+
(
46+
_x: number,
47+
_y: number,
48+
_width: number,
49+
height: number,
50+
_pageX: number,
51+
pageY: number
52+
) => {
53+
setTriggerHeight(height);
54+
const spaceBelow = Dimensions.get('window').height - (pageY + height);
55+
setExpandUp(spaceBelow < DROPDOWN_MAX_HEIGHT);
56+
}
57+
);
58+
};
59+
60+
const dropdownPosition = expandUp
61+
? { bottom: triggerHeight + 2 }
62+
: { top: triggerHeight + 2 };
63+
3364
return (
3465
<View style={styles.container}>
3566
<TouchableOpacity
67+
ref={triggerRef}
3668
style={[styles.trigger, disabled && styles.triggerDisabled]}
3769
onPress={() => !disabled && setOpen((v) => !v)}
3870
activeOpacity={disabled ? 1 : 0.7}
71+
onLayout={handleLayout}
3972
>
4073
{label && <Text style={styles.label}>{label}</Text>}
4174
<Text style={styles.triggerText}>{selected?.label ?? '—'}</Text>
@@ -44,7 +77,7 @@ export function ModelPicker<T>({
4477

4578
{open && (
4679
<ScrollView
47-
style={styles.dropdown}
80+
style={[styles.dropdown, dropdownPosition]}
4881
nestedScrollEnabled
4982
keyboardShouldPersistTaps="handled"
5083
>
@@ -77,7 +110,12 @@ export function ModelPicker<T>({
77110
}
78111

79112
const styles = StyleSheet.create({
80-
container: { marginHorizontal: 12, marginVertical: 4, alignSelf: 'stretch' },
113+
container: {
114+
marginHorizontal: 12,
115+
marginVertical: 4,
116+
alignSelf: 'stretch',
117+
zIndex: 100,
118+
},
81119
trigger: {
82120
flexDirection: 'row',
83121
alignItems: 'center',
@@ -108,12 +146,20 @@ const styles = StyleSheet.create({
108146
marginLeft: 6,
109147
},
110148
dropdown: {
149+
position: 'absolute',
150+
left: 0,
151+
right: 0,
111152
borderWidth: 1,
112153
borderColor: '#C1C6E5',
113154
borderRadius: 8,
114155
backgroundColor: '#fff',
115-
maxHeight: 200,
116-
marginTop: 2,
156+
maxHeight: DROPDOWN_MAX_HEIGHT,
157+
zIndex: 100,
158+
elevation: 4,
159+
shadowColor: '#000',
160+
shadowOffset: { width: 0, height: 2 },
161+
shadowOpacity: 0.1,
162+
shadowRadius: 4,
117163
},
118164
option: {
119165
paddingHorizontal: 12,

apps/speech/components/ModelPicker.tsx

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import React, { useState } from 'react';
1+
import React, { useEffect, useRef, useState } from 'react';
22
import {
3-
View,
3+
Dimensions,
4+
ScrollView,
45
StyleSheet,
56
Text,
67
TouchableOpacity,
7-
ScrollView,
8+
View,
89
} from 'react-native';
910

1011
export type ModelOption<T> = {
@@ -20,6 +21,8 @@ type Props<T> = {
2021
disabled?: boolean;
2122
};
2223

24+
const DROPDOWN_MAX_HEIGHT = 200;
25+
2326
export function ModelPicker<T>({
2427
models,
2528
selectedModel,
@@ -28,14 +31,44 @@ export function ModelPicker<T>({
2831
disabled,
2932
}: Props<T>) {
3033
const [open, setOpen] = useState(false);
34+
const [triggerHeight, setTriggerHeight] = useState(0);
35+
const [expandUp, setExpandUp] = useState(false);
36+
const triggerRef = useRef<React.ComponentRef<typeof TouchableOpacity>>(null);
3137
const selected = models.find((m) => m.value === selectedModel);
3238

39+
useEffect(() => {
40+
if (disabled) setOpen(false);
41+
}, [disabled]);
42+
43+
const handleLayout = () => {
44+
triggerRef.current?.measure(
45+
(
46+
_x: number,
47+
_y: number,
48+
_width: number,
49+
height: number,
50+
_pageX: number,
51+
pageY: number
52+
) => {
53+
setTriggerHeight(height);
54+
const spaceBelow = Dimensions.get('window').height - (pageY + height);
55+
setExpandUp(spaceBelow < DROPDOWN_MAX_HEIGHT);
56+
}
57+
);
58+
};
59+
60+
const dropdownPosition = expandUp
61+
? { bottom: triggerHeight + 2 }
62+
: { top: triggerHeight + 2 };
63+
3364
return (
3465
<View style={styles.container}>
3566
<TouchableOpacity
67+
ref={triggerRef}
3668
style={[styles.trigger, disabled && styles.triggerDisabled]}
3769
onPress={() => !disabled && setOpen((v) => !v)}
3870
activeOpacity={disabled ? 1 : 0.7}
71+
onLayout={handleLayout}
3972
>
4073
{label && <Text style={styles.label}>{label}</Text>}
4174
<Text style={styles.triggerText}>{selected?.label ?? '—'}</Text>
@@ -44,7 +77,7 @@ export function ModelPicker<T>({
4477

4578
{open && (
4679
<ScrollView
47-
style={styles.dropdown}
80+
style={[styles.dropdown, dropdownPosition]}
4881
nestedScrollEnabled
4982
keyboardShouldPersistTaps="handled"
5083
>
@@ -77,7 +110,12 @@ export function ModelPicker<T>({
77110
}
78111

79112
const styles = StyleSheet.create({
80-
container: { marginHorizontal: 12, marginVertical: 4, alignSelf: 'stretch' },
113+
container: {
114+
marginHorizontal: 12,
115+
marginVertical: 4,
116+
alignSelf: 'stretch',
117+
zIndex: 100,
118+
},
81119
trigger: {
82120
flexDirection: 'row',
83121
alignItems: 'center',
@@ -108,12 +146,20 @@ const styles = StyleSheet.create({
108146
marginLeft: 6,
109147
},
110148
dropdown: {
149+
position: 'absolute',
150+
left: 0,
151+
right: 0,
111152
borderWidth: 1,
112153
borderColor: '#C1C6E5',
113154
borderRadius: 8,
114155
backgroundColor: '#fff',
115-
maxHeight: 200,
116-
marginTop: 2,
156+
maxHeight: DROPDOWN_MAX_HEIGHT,
157+
zIndex: 100,
158+
elevation: 4,
159+
shadowColor: '#000',
160+
shadowOffset: { width: 0, height: 2 },
161+
shadowOpacity: 0.1,
162+
shadowRadius: 4,
117163
},
118164
option: {
119165
paddingHorizontal: 12,

packages/react-native-executorch/src/modules/computer_vision/ObjectDetectionModule.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,7 @@ export class ObjectDetectionModule<
194194
inputSize as (typeof availableInputSizes)[number]
195195
)
196196
) {
197-
throw new RnExecutorchError(
198-
RnExecutorchErrorCode.InvalidArgument,
197+
throw new Error(
199198
`Invalid inputSize: ${inputSize}. Available sizes: ${availableInputSizes.join(', ')}`
200199
);
201200
}

0 commit comments

Comments
 (0)