mirror of
https://github.com/roleypoly/roleypoly.git
synced 2025-04-25 11:59:11 +00:00
82 lines
2.7 KiB
TypeScript
82 lines
2.7 KiB
TypeScript
import * as React from 'react';
|
|
import { Role as RPCRole, RoleSafety } from 'roleypoly/common/types';
|
|
import * as styled from './Role.styled';
|
|
import { FaCheck, FaTimes } from 'react-icons/fa';
|
|
import { numberToChroma } from 'roleypoly/design-system/atoms/colors';
|
|
import chroma from 'chroma-js';
|
|
|
|
type Props = {
|
|
role: RPCRole;
|
|
selected: boolean;
|
|
disabled?: boolean;
|
|
onClick?: (newState: boolean) => void;
|
|
tooltipId?: string;
|
|
type?: 'delete';
|
|
};
|
|
|
|
export const Role = (props: Props) => {
|
|
const colorVars = {
|
|
'--role-color': 'white',
|
|
'--role-contrast': 'hsl(0,0,0%)',
|
|
'--role-accent': 'hsl(0,0,70%)',
|
|
};
|
|
|
|
if (props.role.color !== 0) {
|
|
const baseColor = numberToChroma(props.role.color);
|
|
const contrastColorUp = baseColor.brighten(5);
|
|
const contrastColorDown = baseColor.darken(5);
|
|
const ratio = chroma.contrast(contrastColorDown, baseColor);
|
|
const contrastColor = ratio > 2 ? contrastColorDown : contrastColorUp;
|
|
const accentColor = ratio > 2 ? baseColor.darken(2) : baseColor.brighten(2);
|
|
colorVars['--role-color'] = baseColor.css();
|
|
colorVars['--role-accent'] = accentColor.css();
|
|
colorVars['--role-contrast'] = contrastColor.css();
|
|
}
|
|
|
|
const styledProps: styled.StyledProps = {
|
|
selected: props.selected,
|
|
defaultColor: props.role.color === 0,
|
|
disabled: !!props.disabled,
|
|
type: props.type,
|
|
};
|
|
|
|
const extra = !props.disabled
|
|
? {}
|
|
: {
|
|
'data-tip': disabledReason(props.role),
|
|
'data-for': props.tooltipId,
|
|
};
|
|
|
|
return (
|
|
<styled.Outer
|
|
{...styledProps}
|
|
style={colorVars as any}
|
|
onClick={() => !props.disabled && props.onClick?.(!props.selected)}
|
|
{...extra}
|
|
>
|
|
<styled.Circle {...styledProps}>
|
|
{!props.disabled && props.type !== 'delete' ? <FaCheck /> : <FaTimes />}
|
|
</styled.Circle>
|
|
<styled.Text>{props.role.name}</styled.Text>
|
|
</styled.Outer>
|
|
);
|
|
};
|
|
|
|
const disabledReason = (role: RPCRole) => {
|
|
switch (role.safety) {
|
|
case RoleSafety.HIGHERTHANBOT:
|
|
return `This role is above Roleypoly's own role.`;
|
|
case RoleSafety.DANGEROUSPERMISSIONS:
|
|
const { permissions } = role;
|
|
let permissionHits: string[] = [];
|
|
|
|
(permissions & 0x00000008) === 0x00000008 &&
|
|
permissionHits.push('Administrator');
|
|
(permissions & 0x10000000) === 0x10000000 &&
|
|
permissionHits.push('Manage Roles');
|
|
|
|
return `This role has unsafe permissions: ${permissionHits.join(', ')}`;
|
|
default:
|
|
return `This role is disabled.`;
|
|
}
|
|
};
|