import React, { useRef } from 'react'; import styled from '@emotion/native'; import { ColorName, ViewStyle } from '@emotion/react'; import { StyleSystemThemedProps, TouchableHighlight } from 'components/layout'; import { TouchableHighlightProps as TouchableHighlightPropsBase } from 'react-native'; import { variant } from 'styled-system'; import { COLOR_VALUES } from 'theme/color'; import { useHover } from 'react-native-web-hooks'; const variants: Record = { outline: { borderWidth: 1, borderColor: 'divider', backgroundColor: 'transparent', }, 'outline-dashed': { borderWidth: 1, borderColor: 'caption', borderStyle: 'dashed', backgroundColor: 'transparent', }, plain: { backgroundColor: 'transparent', }, }; const sizeVariants: Record = { 'extra-small': { height: 25, width: 25, }, small: { height: 30, width: 30, }, medium: { height: 35, width: 35, }, large: { height: 40, width: 40, }, 'extra-large': { height: 50, width: 50, }, }; const colorVariants: Record = { primary: { backgroundColor: 'primary', }, 'primary-hover': { backgroundColor: 'primary-hover', }, base: { backgroundColor: 'base', }, 'base-01': { backgroundColor: 'base-01', }, 'base-02': { backgroundColor: 'base-02', }, 'base-02-hover': { backgroundColor: 'base-02-hover', }, 'base-opacity-05': { backgroundColor: 'base-opacity-05', }, 'base-opacity-06': { backgroundColor: 'base-opacity-06', }, 'base-hover': { backgroundColor: 'base-hover', }, body: { backgroundColor: 'body', }, success: { backgroundColor: 'success', }, 'success-01': { backgroundColor: 'success-01', }, secondary: { backgroundColor: 'secondary', }, 'secondary-01': { backgroundColor: 'secondary-01', }, 'secondary-hover': { backgroundColor: 'secondary-hover', }, transparent: { backgroundColor: 'transparent', }, }; const fabSizeVariants: Record = { 'extra-small': 25, small: 30, medium: 35, large: 40, 'extra-large': 50, }; const fabBorderRadius: Record = { 'extra-small': 5, small: 6, medium: 8, large: 10, 'extra-large': 11, }; const FabLocal = styled(TouchableHighlight)( variant({ variants, }), variant({ prop: 'sizeVariant', variants: sizeVariants, }), variant({ prop: 'colorVariant', variants: colorVariants, }), { alignItems: 'center', justifyContent: 'center', } ); const UnderlayColors: Record = { outline: COLOR_VALUES['underlay-primary'], 'outline-dashed': COLOR_VALUES['underlay-primary'], plain: COLOR_VALUES['underlay-dark'], }; export const Fab: React.FC = ({ centerElement, size = 25, sizeVariant, colorVariant, shapeVariant = 'circle', hoverColorVariant, underlayColor, ...props }) => { const fabRef = useRef(null); const isHovered = useHover(fabRef); const localSize = sizeVariant ? fabSizeVariants[sizeVariant] : size || fabSizeVariants.medium; const localBorderRadius = sizeVariant ? fabBorderRadius[sizeVariant] : size * 0.2; const borderRadius = shapeVariant === 'circle' ? localSize / 2 : localBorderRadius; const localColorVariant = isHovered ? hoverColorVariant || 'primary-hover' : colorVariant; const underlayColorLocal = underlayColor || UnderlayColors[props.variant]; const localSizeOptional = !sizeVariant ? size : undefined; return ( {centerElement} ); }; export type FabVariant = 'outline' | 'outline-dashed' | 'plain'; export type FabSizeVariant = 'extra-small' | 'small' | 'medium' | 'large' | 'extra-large'; export type FabColorVariant = | 'transparent' | 'primary' | 'primary-hover' | 'base' | 'base-hover' | 'base-01' | 'base-02' | 'base-02-hover' | 'base-opacity-05' | 'base-opacity-06' | 'body' | 'success' | 'success-01' | 'secondary' | 'secondary-01' | 'secondary-hover'; export type AvatarShapeVariant = 'round' | 'circle'; type FabType = StyleSystemThemedProps & TouchableHighlightProps & FabProps; export interface TouchableHighlightProps extends TouchableHighlightPropsBase { variant: FabVariant; sizeVariant?: FabSizeVariant; shapeVariant?: AvatarShapeVariant; colorVariant: FabColorVariant; } export interface FabProps { size?: number; centerElement?: JSX.Element; hoverColorVariant?: FabColorVariant; underlayColor?: ColorName; }