import React from "react"; import gql from "graphql-tag"; import { useQuery } from "@apollo/client"; import { Box, Flex, Select, Text, useColorModeValue } from "@chakra-ui/core"; import { Delay, useFetch } from "../util"; /** * SpeciesColorPicker lets the user pick the species/color of their pet. * * It preloads all species, colors, and valid species/color pairs; and then * ensures that the outfit is always in a valid state. * * NOTE: This component is memoized with React.memo. It's not the cheapest to * re-render on every outfit change. This contributes to * wearing/unwearing items being noticeably slower on lower-power * devices. */ function SpeciesColorPicker({ speciesId, colorId, idealPose, showPlaceholders = false, colorPlaceholderText = "", speciesPlaceholderText = "", stateMustAlwaysBeValid = false, isDisabled = false, size = "md", onChange, }) { const { loading: loadingMeta, error: errorMeta, data: meta } = useQuery(gql` query SpeciesColorPicker { allSpecies { id name standardBodyId # Used for keeping items on during standard color changes } allColors { id name isStandard # Used for keeping items on during standard color changes } } `); const { loading: loadingValids, error: errorValids, data: validsBuffer, } = useFetch("/api/validPetPoses", { responseType: "arrayBuffer" }); const valids = React.useMemo( () => validsBuffer && new DataView(validsBuffer), [validsBuffer] ); const allColors = (meta && [...meta.allColors]) || []; allColors.sort((a, b) => a.name.localeCompare(b.name)); const allSpecies = (meta && [...meta.allSpecies]) || []; allSpecies.sort((a, b) => a.name.localeCompare(b.name)); const backgroundColor = useColorModeValue("white", "gray.600"); const borderColor = useColorModeValue("green.600", "transparent"); const textColor = useColorModeValue("inherit", "green.50"); const SpeciesColorSelect = ({ isDisabled, isLoading, ...props }) => { const loadingProps = isLoading ? { // Visually the disabled state is the same as the normal state, but // with a wait cursor. We don't expect this to take long, and the flash // of content is rough! opacity: "1 !important", cursor: "wait !important", } : {}; return (