@primer/components
Version:
Primer react components
121 lines (114 loc) • 4.79 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import React, { forwardRef } from 'react';
import styled, { css } from 'styled-components';
import TokenBase, { isTokenInteractive } from './TokenBase';
import RemoveTokenButton from './_RemoveTokenButton';
import tinycolor from 'tinycolor2';
import { useTheme } from '../ThemeProvider';
const colorModeConfigs = {
dark: {
bgOpacity: 0.18,
borderThreshold: 0,
borderOpacity: 0.3,
lightnessThreshold: 0.6
},
light: {
bgOpacity: 1,
borderThreshold: 0.96,
borderOpacity: 1,
lightnessThreshold: 0.453
}
};
const tokenBorderWidthPx = 1;
const StyledTokenLabel = styled(TokenBase).withConfig({
displayName: "TokenLabel__StyledTokenLabel",
componentId: "sc-1bdmgzv-0"
})(["background-color:", ";border-width:", "px;border-style:solid;border-color:", ";color:", ";padding-right:", ";position:relative;", ""], props => props.bgColor, tokenBorderWidthPx, props => props.borderColor, props => props.textColor, props => !props.hideRemoveButton ? 0 : undefined, props => {
if (props.isSelected) {
return css(["&:after{content:'';position:absolute;z-index:1;top:-2px;right:-2px;bottom:-2px;left:-2px;display:block;pointer-events:none;box-shadow:0 0 0 2px ", ";border-radius:999px;}"], props.bgColor);
}
});
const TokenTextContainer = styled('span').withConfig({
displayName: "TokenLabel__TokenTextContainer",
componentId: "sc-1bdmgzv-1"
})(["flex-grow:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"]);
const TokenLabel = /*#__PURE__*/forwardRef((props, forwardedRef) => {
const {
as,
fillColor,
handleRemove,
id,
isSelected,
ref,
text,
variant,
hideRemoveButton,
...rest
} = props;
const {
colorScheme
} = useTheme();
const {
bgOpacity,
borderOpacity,
borderThreshold,
lightnessThreshold
} = colorModeConfigs[colorScheme || 'light'];
let bgColor = fillColor;
let borderColor = fillColor;
let textColor = '#FFF';
const perceivedLightness = tinycolor(fillColor).getLuminance();
const isFillColorLight = perceivedLightness >= lightnessThreshold;
if (colorScheme === 'dark') {
const lightenBy = (perceivedLightness - lightnessThreshold) * 100 * (isFillColorLight ? 1 : 0);
bgColor = isSelected ? tinycolor(fillColor).setAlpha(bgOpacity * 1.2).toRgbString() : tinycolor(fillColor).setAlpha(bgOpacity).toRgbString();
textColor = isSelected ? tinycolor(fillColor).lighten(lightenBy + 10).toString() : tinycolor(fillColor).lighten(lightenBy).toString();
borderColor = isSelected ? tinycolor(fillColor).lighten(lightenBy + 5).toRgbString() : tinycolor(fillColor).lighten(lightenBy).setAlpha(borderOpacity).toRgbString();
} else {
const isFillColorDark = perceivedLightness < 0.1;
borderColor = perceivedLightness >= borderThreshold ? tinycolor(fillColor).darken(25).toString() : 'transparent';
if (isFillColorLight) {
textColor = '#000';
}
if (isSelected) {
bgColor = isFillColorDark ? tinycolor(fillColor).lighten(10).toString() // TODO: darken more than 10 if the fillColor is really bright and doesn't darken well
// Examples of colors that don't darken well:
// - #a2eeef
// - #ffd78e
// - #a4f287
: tinycolor(fillColor).darken(10).toString();
}
}
const hasMultipleActionTargets = isTokenInteractive(props) && Boolean(handleRemove) && !hideRemoveButton;
const handleRemoveClick = e => {
e.stopPropagation();
handleRemove && handleRemove();
};
return /*#__PURE__*/React.createElement(StyledTokenLabel // specific to labels
, _extends({
fillColor: fillColor,
bgColor: bgColor,
borderColor: borderColor,
textColor: textColor // common token props
,
as: as,
hideRemoveButton: hideRemoveButton || !handleRemove,
handleRemove: handleRemove,
id: id === null || id === void 0 ? void 0 : id.toString(),
isSelected: isSelected,
ref: forwardedRef,
text: text,
variant: variant
}, rest), /*#__PURE__*/React.createElement(TokenTextContainer, null, text), !hideRemoveButton && handleRemove ? /*#__PURE__*/React.createElement(RemoveTokenButton, {
borderOffset: tokenBorderWidthPx,
parentTokenTag: as || 'span',
tabIndex: -1,
onClick: handleRemoveClick,
variant: variant,
"aria-hidden": hasMultipleActionTargets ? "true" : "false"
}) : null);
});
TokenLabel.defaultProps = {
fillColor: '#999'
};
export default TokenLabel;