355b14faef
Enable App Store builds without EAS, iOS 18 App Intents plugins, and signing fixes for distribution export. Add mobile invoice PDF preview, compact line items, and more reliable shortcut deep-link handling. Co-authored-by: Cursor <cursoragent@cursor.com>
93 lines
2.3 KiB
TypeScript
93 lines
2.3 KiB
TypeScript
import { Ionicons } from "@expo/vector-icons";
|
|
import { Pressable, StyleSheet, TextInput, View, type StyleProp, type ViewStyle } from "react-native";
|
|
|
|
import { fonts, radii } from "@/constants/theme";
|
|
import { useAppTheme } from "@/contexts/ThemeContext";
|
|
|
|
type CompactStepperInputProps = {
|
|
value: string;
|
|
onChangeText: (value: string) => void;
|
|
step?: number;
|
|
min?: number;
|
|
style?: StyleProp<ViewStyle>;
|
|
};
|
|
|
|
export function CompactStepperInput({
|
|
value,
|
|
onChangeText,
|
|
step = 0.25,
|
|
min = 0,
|
|
style,
|
|
}: CompactStepperInputProps) {
|
|
const { colors } = useAppTheme();
|
|
|
|
function adjust(delta: number) {
|
|
const current = Number.parseFloat(value) || 0;
|
|
const next = Math.max(min, Math.round((current + delta) * 100) / 100);
|
|
onChangeText(Number.isInteger(next) ? String(next) : String(next));
|
|
}
|
|
|
|
return (
|
|
<View
|
|
style={[
|
|
styles.field,
|
|
{ borderColor: colors.border, backgroundColor: colors.cardGlass },
|
|
style,
|
|
]}
|
|
>
|
|
<Pressable
|
|
accessibilityRole="button"
|
|
accessibilityLabel="Decrease hours"
|
|
hitSlop={4}
|
|
onPress={() => adjust(-step)}
|
|
style={({ pressed }) => [styles.stepButton, pressed && styles.pressed]}
|
|
>
|
|
<Ionicons name="remove" size={14} color={colors.foreground} />
|
|
</Pressable>
|
|
<TextInput
|
|
value={value}
|
|
onChangeText={onChangeText}
|
|
keyboardType="decimal-pad"
|
|
placeholder="0"
|
|
placeholderTextColor={colors.mutedForeground}
|
|
style={[styles.input, { color: colors.foreground }]}
|
|
/>
|
|
<Pressable
|
|
accessibilityRole="button"
|
|
accessibilityLabel="Increase hours"
|
|
hitSlop={4}
|
|
onPress={() => adjust(step)}
|
|
style={({ pressed }) => [styles.stepButton, pressed && styles.pressed]}
|
|
>
|
|
<Ionicons name="add" size={14} color={colors.foreground} />
|
|
</Pressable>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
field: {
|
|
minHeight: 36,
|
|
borderWidth: 1,
|
|
borderRadius: radii.md,
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
},
|
|
stepButton: {
|
|
width: 28,
|
|
height: 36,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
},
|
|
pressed: {
|
|
opacity: 0.65,
|
|
},
|
|
input: {
|
|
flex: 1,
|
|
textAlign: "center",
|
|
fontSize: 13,
|
|
fontFamily: fonts.bodyMedium,
|
|
paddingVertical: 4,
|
|
},
|
|
});
|