2020-02-24 19:29:11 +00:00

158 lines
3.5 KiB
TypeScript

import { faCaretDown } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useState } from 'react';
import OutsideClickHandler from 'react-outside-click-handler';
import { useDispatch, useSelector } from 'react-redux';
import styled, { css } from 'styled-components';
import { AppState } from '../redux/app';
import { ChangeLanguageAction, EditorState } from '../redux/editor';
import { Language } from '../redux/types';
import { Tooltip } from './tooltip';
const Container = styled.div`
display: flex;
position: relative;
z-index: 2;
min-width: 10em;
`;
const Header = styled.div`
cursor: pointer;
user-select: none;
flex: 1;
display: flex;
height: 2em;
padding: 0 0.5em;
border: 1px solid var(--blue_trans1);
`;
const Label = styled.div`
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
`;
const ArrowIcon = ({ rotate, ...props }: { rotate: boolean }) => (
<FontAwesomeIcon {...props} icon={faCaretDown} size="lg"></FontAwesomeIcon>
);
const Arrow = styled(ArrowIcon)`
margin-left: 0.5em;
pointer-events: none;
color: var(--blue_trans1);
transition: transform 0.15s ease-in;
${(props: { rotate: boolean }) =>
props.rotate &&
css`
transform: rotate(180deg);
`};
`;
const List = styled.ul`
position: absolute;
list-style-type: none;
background-color: white;
width: 100%;
margin: 0;
padding: 0;
box-shadow: 1px 3px 10px 0px rgba(153, 153, 153, 0.4);
border-radius: 3px;
visibility: hidden;
opacity: 0;
transition: opacity 0.15s ease-in;
${(props: { visible: boolean }) =>
props.visible &&
css`
visibility: visible;
opacity: 1;
`}
`;
const Option = styled.li`
cursor: pointer;
user-select: none;
display: flex;
align-items: center;
justify-content: space-between;
height: 2em;
padding: 0 0.5em;
&:first-child {
border-radius: 3px 3px 0 0;
}
&:last-child {
border-radius: 0 0 3px 3px;
}
&:hover {
background-color: var(--blue_trans2);
font-weight: 600;
}
`;
export const SyntaxSelectComponent = () => {
const OPTIONS = {
[Language.PascaLigo]: 'PascaLIGO',
[Language.CameLigo]: 'CameLIGO',
[Language.ReasonLIGO]: 'ReasonLIGO'
};
const moveOptionToTop = (option: Language) => {
return Object.keys(OPTIONS).reduce((list, entry) => {
if (entry === option) {
list.unshift(entry);
} else {
list.push(entry as Language);
}
return list;
}, [] as Language[]);
};
const language = useSelector<AppState, EditorState['language']>(
state => state.editor.language
);
const dispatch = useDispatch();
const [opened, open] = useState(false);
const selectOption = (option: Language) => {
if (language !== option) {
dispatch({ ...new ChangeLanguageAction(option) });
}
open(false);
};
return (
<Container>
<OutsideClickHandler onOutsideClick={() => open(false)}>
<List visible={opened}>
{moveOptionToTop(language).map(option => (
<Option
id={option}
key={option}
onClick={() => selectOption(option)}
>
<span>{OPTIONS[option]}</span>
</Option>
))}
</List>
</OutsideClickHandler>
<Header id="syntax-select" onClick={() => open(true)}>
<Label>
{OPTIONS[language]}
<Arrow rotate={opened}></Arrow>
</Label>
<Tooltip>Select syntax</Tooltip>
</Header>
</Container>
);
};