All files / packages/ui/src/components/QuickSelect index.tsx

100% Statements 12/12
100% Branches 22/22
100% Functions 5/5
100% Lines 11/11

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                2x 107x 87x     20x     2x               29x   29x       109x           109x                   10x                                     29x                                                                                  
import { Pressable, Text, View } from "react-native";
 
import { makeStyles } from "@repo/ui/themes/makeStyles";
import { textStyles } from "@repo/ui/themes/typography";
 
import type { QuickSelectProps, QuickSelectValue } from "./types";
import { isMatchingQuickSelectOption } from "./utils";
 
const isDateQuickSelectValue = (value: unknown): value is QuickSelectValue => {
  if (!value || typeof value !== "object") {
    return false;
  }
 
  return "startDate" in value && "endDate" in value && "timeSlot" in value;
};
 
export const QuickSelect = <TValue = QuickSelectValue,>({
  options,
  value,
  onChange,
  disabled = false,
  testID,
  isOptionActive,
}: QuickSelectProps<TValue>) => {
  const styles = useStyles();
 
  return (
    <View testID={testID}>
      <View style={styles.optionsContainer}>
        {options.map((option) => {
          const isActive = isOptionActive
            ? isOptionActive(value, option.value)
            : isDateQuickSelectValue(value) &&
                isDateQuickSelectValue(option.value)
              ? isMatchingQuickSelectOption(value, option.value)
              : value === option.value;
          return (
            <Pressable
              key={option.testID}
              testID={option.testID}
              disabled={disabled}
              style={[
                styles.optionButton,
                isActive && styles.optionButtonActive,
                disabled && styles.optionButtonDisabled,
              ]}
              onPress={() => onChange(option.value)}
            >
              <Text
                style={[
                  styles.optionText,
                  isActive && styles.optionTextActive,
                  disabled && styles.optionTextDisabled,
                ]}
              >
                {option.label}
              </Text>
            </Pressable>
          );
        })}
      </View>
    </View>
  );
};
 
const useStyles = makeStyles((theme) => ({
  optionsContainer: {
    flexDirection: "row",
    flexWrap: "wrap",
    gap: theme.metrics.spacing[2],
  },
  optionButton: {
    borderRadius: theme.metrics.borderRadius[4],
    minHeight: theme.metrics.spacing[11],
    paddingVertical: theme.metrics.spacing[3.5],
    paddingHorizontal: theme.metrics.spacing[5],
    justifyContent: "center",
    alignItems: "center",
    backgroundColor: theme.colors.background.tertiary,
  },
  optionButtonActive: {
    backgroundColor: theme.colors.background.selectedStrong,
  },
  optionButtonDisabled: {
    backgroundColor: theme.colors.background.disabled,
    opacity: theme.metrics.opacity[60],
  },
  optionText: {
    color: theme.colors.text.primary,
    fontSize: theme.metrics.textSize[16],
    fontWeight: theme.metrics.fontWeight.semiBold,
    ...textStyles.content.semiBold,
  },
  optionTextActive: {
    color: theme.colors.text.white,
  },
  optionTextDisabled: {
    color: theme.colors.text.disabled,
  },
}));
 
export type {
  QuickSelectOption,
  QuickSelectProps,
  QuickSelectValue,
} from "./types";