1
0
mirror of https://github.com/checktheroads/hyperglass synced 2024-05-11 05:55:08 +00:00
2020-12-20 01:21:24 -07:00

241 lines
7.6 KiB
TypeScript

import { useCallback, useMemo } from 'react';
import { useToken } from '@chakra-ui/react';
import { mergeWith } from '@chakra-ui/utils';
import { useOpposingColor } from '~/hooks';
import { useColorValue, useMobile } from '~/context';
import { useSelectContext } from './select';
import type {
TControl,
TIndicator,
TMenu,
TMenuList,
TMultiValueState,
TOption,
TPlaceholder,
TStyles,
TRSTheme,
TMultiValue,
} from './types';
export const useControlStyle = (base: TStyles, state: TControl): TStyles => {
const { isFocused } = state;
const { colorMode, isError } = useSelectContext();
const borderHover = useColorValue(
useToken('colors', 'gray.300'),
useToken('colors', 'whiteAlpha.400'),
);
const focusBorder = useColorValue(useToken('colors', 'blue.500'), useToken('colors', 'blue.300'));
const invalidBorder = useColorValue(useToken('colors', 'red.500'), useToken('colors', 'red.300'));
const borderColor = useColorValue('inherit', useToken('colors', 'whiteAlpha.50'));
const borderRadius = useToken('radii', 'md');
const minHeight = useToken('space', 12);
const color = useColorValue(useToken('colors', 'black'), useToken('colors', 'whiteAlpha.800'));
const backgroundColor = useColorValue(
useToken('colors', 'white'),
useToken('colors', 'whiteAlpha.100'),
);
const styles = {
backgroundColor,
borderRadius,
color,
minHeight,
transition: 'all 0.2s',
borderColor: isError ? invalidBorder : isFocused ? focusBorder : borderColor,
boxShadow: isError
? `0 0 0 1px ${invalidBorder}`
: isFocused
? `0 0 0 1px ${focusBorder}`
: undefined,
'&:hover': { borderColor: isFocused ? focusBorder : borderHover },
'&:hover > div > span': { backgroundColor: borderHover },
'&:focus': { borderColor: isError ? invalidBorder : focusBorder },
'&.invalid': { borderColor: invalidBorder, boxShadow: `0 0 0 1px ${invalidBorder}` },
};
return useMemo(() => mergeWith({}, base, styles), [colorMode, isFocused, isError]);
};
export const useMenuStyle = (base: TStyles, state: TMenu): TStyles => {
const { colorMode, isOpen } = useSelectContext();
const backgroundColor = useColorValue(
useToken('colors', 'white'),
useToken('colors', 'blackFaded.800'),
);
const borderRadius = useToken('radii', 'md');
const styles = { borderRadius, backgroundColor };
return useMemo(() => mergeWith({}, base, styles), [colorMode, isOpen]);
};
export const useMenuListStyle = (base: TStyles, state: TMenuList): TStyles => {
const { colorMode, isOpen } = useSelectContext();
const scrollbarTrack = useColorValue(
useToken('colors', 'blackAlpha.50'),
useToken('colors', 'whiteAlpha.50'),
);
const scrollbarThumb = useColorValue(
useToken('colors', 'blackAlpha.300'),
useToken('colors', 'whiteAlpha.300'),
);
const scrollbarThumbHover = useColorValue(
useToken('colors', 'blackAlpha.400'),
useToken('colors', 'whiteAlpha.400'),
);
const styles = {
'&::-webkit-scrollbar': { width: '5px' },
'&::-webkit-scrollbar-track': { backgroundColor: scrollbarTrack },
'&::-webkit-scrollbar-thumb': { backgroundColor: scrollbarThumb },
'&::-webkit-scrollbar-thumb:hover': { backgroundColor: scrollbarThumbHover },
'-ms-overflow-style': { display: 'none' },
};
return useMemo(() => mergeWith({}, base, styles), [colorMode, isOpen]);
};
export const useOptionStyle = (base: TStyles, state: TOption): TStyles => {
const { isFocused, isSelected, isDisabled } = state;
const { colorMode, isOpen } = useSelectContext();
const fontSize = useToken('fontSizes', 'lg');
const disabled = useToken('colors', 'whiteAlpha.400');
const selected = useColorValue(
useToken('colors', 'blackAlpha.400'),
useToken('colors', 'whiteAlpha.400'),
);
const focused = useColorValue(
useToken('colors', 'primary.500'),
useToken('colors', 'primary.300'),
);
const active = useColorValue(
useToken('colors', 'primary.600'),
useToken('colors', 'primary.400'),
);
const activeColor = useOpposingColor(active);
const backgroundColor = useMemo(() => {
let bg = 'transparent';
switch (true) {
case isDisabled:
bg = disabled;
break;
case isSelected:
bg = selected;
break;
case isFocused:
bg = focused;
break;
}
return bg;
}, [isDisabled, isFocused, isSelected]);
const color = useOpposingColor(backgroundColor);
const styles = {
backgroundColor,
color,
fontSize,
'&:focus': { backgroundColor: active, color: activeColor },
'&:active': { backgroundColor: active, color: activeColor },
};
return useMemo(() => mergeWith({}, base, styles), [
isOpen,
colorMode,
isFocused,
isDisabled,
isSelected,
]);
};
export const useIndicatorSeparatorStyle = (base: TStyles, state: TIndicator): TStyles => {
const { colorMode } = useSelectContext();
const backgroundColor = useColorValue(
useToken('colors', 'whiteAlpha.700'),
useToken('colors', 'gray.600'),
);
const styles = { backgroundColor };
return useMemo(() => mergeWith({}, base, styles), [colorMode]);
};
export const usePlaceholderStyle = (base: TStyles, state: TPlaceholder): TStyles => {
const { colorMode } = useSelectContext();
const color = useColorValue(useToken('colors', 'gray.600'), useToken('colors', 'whiteAlpha.700'));
const fontSize = useToken('fontSizes', 'lg');
return useMemo(() => mergeWith({}, base, { color, fontSize }), [colorMode]);
};
export const useSingleValueStyle = (props: TStyles) => {
const { colorMode } = useSelectContext();
const color = useColorValue('black', 'whiteAlpha.800');
const fontSize = useToken('fontSizes', 'lg');
const styles = { color, fontSize };
return useCallback((base: TStyles, state: TMultiValueState) => mergeWith({}, base, styles), [
color,
colorMode,
]);
};
export const useMultiValueStyle = (props: TMultiValue) => {
const { colorMode } = props;
const backgroundColor = useColorValue(
useToken('colors', 'primary.500'),
useToken('colors', 'primary.300'),
);
const color = useOpposingColor(backgroundColor);
const styles = { backgroundColor, color };
return useCallback((base: TStyles, state: TMultiValueState) => mergeWith({}, base, styles), [
backgroundColor,
colorMode,
]);
};
export const useMultiValueLabelStyle = (props: TMultiValue) => {
const { colorMode } = props;
const backgroundColor = useColorValue(
useToken('colors', 'primary.500'),
useToken('colors', 'primary.300'),
);
const color = useOpposingColor(backgroundColor);
const styles = { color };
return useCallback((base: TStyles, state: TMultiValueState) => mergeWith({}, base, styles), [
colorMode,
]);
};
export const useMultiValueRemoveStyle = (props: TMultiValue) => {
const { colorMode } = props;
const backgroundColor = useColorValue(
useToken('colors', 'primary.500'),
useToken('colors', 'primary.300'),
);
const color = useOpposingColor(backgroundColor);
const styles = {
color,
'&:hover': { backgroundColor: 'inherit', color, opacity: 0.7 },
};
return useCallback((base: TStyles, state: TMultiValueState) => mergeWith({}, base, styles), [
colorMode,
]);
};
export const useRSTheme = (props: TMultiValue) => {
const borderRadius = useToken('radii', 'md');
return useCallback((t: TRSTheme): TRSTheme => ({ ...t, borderRadius }), []);
};
export const useMenuPortal = (props: TMultiValue) => {
const isMobile = useMobile();
const styles = {
zIndex: isMobile ? 1500 : 1,
};
return useCallback((base: TStyles, state: TMultiValueState) => mergeWith({}, base, styles), [
isMobile,
]);
};