All files / src/components/search-bar SearchBar.tsx

93.33% Statements 14/15
89.47% Branches 17/19
100% Functions 5/5
100% Lines 14/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112                                                                          16x 16x   16x 1x 1x 1x 1x     16x 10x                   6x 2x                       4x     4x                               1x                                          
import React, { useRef } from "react";
import { StyleSheet, View, Text, Pressable } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import RouteCard from "./RouteCard";
import NavigationBar from "../navigation-bar/NavigationBar";
import { Step } from "../../api/outdoorDirectionsApi";
import { useTheme } from "../../hooks/useTheme";
 
interface SearchBarProps {
  readonly placeholder: string;
  readonly onPress: () => void;
  readonly isConfiguring?: boolean;
  readonly isNavigating?: boolean;
  readonly isCancellingNavigation?: boolean;
  readonly originLabel?: string;
  readonly destinationLabel?: string;
  readonly onBack?: () => void;
  readonly onSwap?: () => void;
  readonly navigationInfoToggleState?: "maximize" | "minimize";
  readonly navigationHUDToggleState?: "maximize" | "minimize";
  readonly navigationHUDStep?: Step;
}
 
export default function SearchBar({
  placeholder,
  onPress,
  isConfiguring = false,
  isNavigating = false,
  isCancellingNavigation = false,
  originLabel = "Current Location",
  destinationLabel = "Select destination",
  onBack,
  onSwap,
  navigationInfoToggleState,
  navigationHUDToggleState,
  navigationHUDStep,
}: SearchBarProps) {
  const { colors } = useTheme();
  const lastPressTsRef = useRef(0);
 
  const handlePress = () => {
    const now = Date.now();
    Iif (now - lastPressTsRef.current < 400) return;
    lastPressTsRef.current = now;
    onPress();
  };
 
  if (isConfiguring) {
    return (
      <RouteCard
        originLabel={originLabel}
        destinationLabel={destinationLabel}
        onBack={onBack ?? (() => {})}
        onSwap={onSwap ?? (() => {})}
      />
    );
  }
 
  if (isNavigating || isCancellingNavigation) {
    return (
      <NavigationBar
        destination={destinationLabel}
        onPress={onBack}
        navigationInfoToggleState={navigationInfoToggleState}
        navigationHUDToggleState={navigationHUDToggleState}
        isCancellingNavigation={isCancellingNavigation}
        navigationHUDStep={navigationHUDStep}
      />
    );
  }
 
  return (
    <Pressable
      onPress={handlePress}
      style={({ pressed }) => [
        styles.container,
        { backgroundColor: colors.card },
        pressed && { opacity: 0.85 },
      ]}
    >
      <Ionicons name="search" size={18} color={colors.iconDefault} />
      <Text style={[styles.text, { color: colors.textMuted }]}>
        {placeholder}
      </Text>
      <View style={styles.spacer} />
      <Ionicons name="mic" size={18} color={colors.iconDefault} />
    </Pressable>
  );
}
 
const styles = StyleSheet.create({
  container: {
    height: 44,
    borderRadius: 12,
    paddingHorizontal: 12,
    flexDirection: "row",
    alignItems: "center",
    gap: 10,
    shadowColor: "#000",
    shadowOpacity: 0.12,
    shadowRadius: 10,
    shadowOffset: { width: 0, height: 4 },
    elevation: 5,
  },
  text: {
    fontSize: 15,
  },
  spacer: {
    flex: 1,
  },
});