2021-07-12 17:06:27 +02:00
|
|
|
import { FC } from "react";
|
2022-06-15 23:37:15 +02:00
|
|
|
import {
|
|
|
|
|
VStack,
|
|
|
|
|
HStack,
|
|
|
|
|
Text,
|
|
|
|
|
Textarea,
|
|
|
|
|
IconButton,
|
|
|
|
|
Tooltip,
|
|
|
|
|
Spinner,
|
|
|
|
|
TextareaProps,
|
|
|
|
|
useBreakpointValue,
|
|
|
|
|
useColorModeValue,
|
|
|
|
|
useClipboard
|
|
|
|
|
} from "@chakra-ui/react";
|
2021-03-25 16:48:46 +01:00
|
|
|
import { FaCopy, FaCheck, FaPlay, FaStop } from "react-icons/fa";
|
2021-06-12 22:44:56 +02:00
|
|
|
import { useAudioFromBuffer } from "@hooks";
|
2021-03-16 01:33:19 +01:00
|
|
|
|
|
|
|
|
type Props = {
|
|
|
|
|
value: string,
|
2021-07-12 17:06:27 +02:00
|
|
|
onChange?: TextareaProps["onChange"],
|
|
|
|
|
onSubmit?: () => void,
|
2021-03-25 16:48:46 +01:00
|
|
|
readOnly?: true,
|
|
|
|
|
audio?: number[],
|
|
|
|
|
canCopy?: boolean,
|
2021-04-01 15:40:25 +02:00
|
|
|
isLoading?: boolean,
|
2021-03-16 01:33:19 +01:00
|
|
|
[key: string]: any
|
|
|
|
|
};
|
|
|
|
|
|
2022-06-15 23:37:15 +02:00
|
|
|
const TranslationArea: FC<Props> = ({ value, onChange, onSubmit, readOnly, audio, canCopy, isLoading, pronunciation, ...props }) => {
|
2021-03-25 16:48:46 +01:00
|
|
|
const { hasCopied, onCopy } = useClipboard(value);
|
|
|
|
|
const { audioExists, isAudioPlaying, onAudioClick } = useAudioFromBuffer(audio);
|
2021-04-01 15:40:25 +02:00
|
|
|
const spinnerProps = {
|
2022-06-15 23:37:15 +02:00
|
|
|
size: useBreakpointValue(["lg", null, "xl"]) ?? "lg",
|
2021-04-01 15:40:25 +02:00
|
|
|
color: useColorModeValue("lingva.500", "lingva.200"),
|
|
|
|
|
emptyColor: useColorModeValue("gray.300", "gray.600")
|
|
|
|
|
};
|
|
|
|
|
|
2021-03-25 16:48:46 +01:00
|
|
|
return (
|
2022-06-15 23:37:15 +02:00
|
|
|
<VStack
|
2021-03-25 16:48:46 +01:00
|
|
|
w="full"
|
2022-06-15 23:37:15 +02:00
|
|
|
h={useBreakpointValue([44, null, 80]) ?? 44}
|
|
|
|
|
align="stretch"
|
|
|
|
|
spacing={0}
|
|
|
|
|
position="relative"
|
2022-05-04 20:28:59 +02:00
|
|
|
isolation="isolate"
|
2022-06-15 23:37:15 +02:00
|
|
|
border="1px solid"
|
|
|
|
|
borderColor={useColorModeValue("lingva.500", "lingva.200")}
|
|
|
|
|
borderRadius="md"
|
|
|
|
|
_hover={{
|
|
|
|
|
borderColor: useColorModeValue("lingva.800", "lingva.400"),
|
|
|
|
|
}}
|
|
|
|
|
_readOnly={{
|
|
|
|
|
userSelect: "auto"
|
|
|
|
|
}}
|
2021-03-25 16:48:46 +01:00
|
|
|
>
|
|
|
|
|
<Textarea
|
|
|
|
|
value={value}
|
|
|
|
|
onChange={onChange}
|
|
|
|
|
readOnly={readOnly}
|
|
|
|
|
dir="auto"
|
|
|
|
|
resize="none"
|
|
|
|
|
size="lg"
|
2022-06-15 23:37:15 +02:00
|
|
|
variant="ghost"
|
|
|
|
|
boxShadow={`inset 0 0 1px ${useColorModeValue("hsl(146 100% 17% / 25%)", "hsl(142 40% 82% / 25%)")}`}
|
2021-06-17 22:51:10 +02:00
|
|
|
data-gramm_editor={false}
|
2021-07-12 17:06:27 +02:00
|
|
|
onKeyPress={e => (e.ctrlKey || e.metaKey) && e.key === "Enter" && onSubmit?.()}
|
2022-06-15 23:37:15 +02:00
|
|
|
flex={1}
|
|
|
|
|
bgColor="transparent"
|
|
|
|
|
_focus={{
|
|
|
|
|
bgColor: useColorModeValue("hsl(0deg 0% 0% / 2.5%)", "hsl(0deg 0% 100% / 2.5%)")
|
|
|
|
|
}}
|
2021-03-25 16:48:46 +01:00
|
|
|
{...props}
|
|
|
|
|
/>
|
|
|
|
|
<HStack
|
2022-06-15 23:37:15 +02:00
|
|
|
position={!pronunciation ? "absolute" : undefined}
|
|
|
|
|
pointerEvents={!pronunciation ? "none" : undefined}
|
|
|
|
|
bottom={0}
|
|
|
|
|
left={0}
|
|
|
|
|
right={0}
|
2021-03-25 16:48:46 +01:00
|
|
|
>
|
2022-06-15 23:37:15 +02:00
|
|
|
<HStack justify="space-between" px={5} h={useBreakpointValue([12, null, 14]) ?? 12} w="0px" flex={1}>
|
|
|
|
|
<Tooltip label={pronunciation}>
|
|
|
|
|
<Text aria-label="Pronunciation" opacity={0.75} whiteSpace="nowrap" overflow="hidden" textOverflow="ellipsis">
|
|
|
|
|
{pronunciation}
|
|
|
|
|
</Text>
|
2021-03-25 16:48:46 +01:00
|
|
|
</Tooltip>
|
2022-06-15 23:37:15 +02:00
|
|
|
<HStack pointerEvents="auto">
|
|
|
|
|
{canCopy && (
|
|
|
|
|
<Tooltip label={hasCopied ? "Copied!" : "Copy to clipboard"}>
|
|
|
|
|
<IconButton
|
|
|
|
|
aria-label="Copy to clipboard"
|
|
|
|
|
icon={hasCopied ? <FaCheck /> : <FaCopy />}
|
|
|
|
|
onClick={onCopy}
|
|
|
|
|
colorScheme="lingva"
|
|
|
|
|
variant="ghost"
|
|
|
|
|
disabled={!value}
|
|
|
|
|
/>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
)}
|
|
|
|
|
<Tooltip label={isAudioPlaying ? "Stop audio" : "Play audio"}>
|
|
|
|
|
<IconButton
|
|
|
|
|
aria-label={isAudioPlaying ? "Stop audio" : "Play audio"}
|
|
|
|
|
icon={isAudioPlaying ? <FaStop /> : <FaPlay />}
|
|
|
|
|
onClick={onAudioClick}
|
|
|
|
|
colorScheme="lingva"
|
|
|
|
|
variant="ghost"
|
|
|
|
|
disabled={!audioExists}
|
|
|
|
|
/>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
</HStack>
|
|
|
|
|
</HStack>
|
2021-03-25 16:48:46 +01:00
|
|
|
</HStack>
|
2021-04-01 15:40:25 +02:00
|
|
|
{isLoading && <Spinner
|
|
|
|
|
position="absolute"
|
2022-06-15 23:37:15 +02:00
|
|
|
inset={0}
|
|
|
|
|
m="auto !important"
|
2021-04-01 15:40:25 +02:00
|
|
|
thickness="3px"
|
|
|
|
|
label="Loading translation"
|
|
|
|
|
{...spinnerProps}
|
|
|
|
|
/>}
|
2022-06-15 23:37:15 +02:00
|
|
|
</VStack>
|
2021-03-25 16:48:46 +01:00
|
|
|
);
|
|
|
|
|
};
|
2021-03-16 01:33:19 +01:00
|
|
|
|
|
|
|
|
export default TranslationArea;
|