Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 46x 46x 46x 1x 1x 1x 1x 45x 46x 1x 1x 45x 45x 45x 45x 46x 46x 1x 1x 1x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 31x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 31x 1x | /** @internal */
import SvgIcon, { type SvgIconProps } from '@mui/material/SvgIcon';
import { FC } from 'react';
/** Props for {@link CustomFileIcon}: a colored document with a labeled band and optional language badge. */
export interface CustomFileIconProps extends SvgIconProps {
/** Text shown on the document's label band (e.g. "SDS", "SPECS"). */
label: string;
/** Font size of the label text, in user units. Defaults to 15. */
labelFontSize?: number;
/** Letter spacing of the label text. Defaults to ".08em". */
labelLetterSpacing?: string;
/** Fill color of the document body. Defaults to white. */
documentColor?: string;
/** Fill color of the label band. Defaults to red. */
labelColor?: string;
/** Color of the label/badge text. Defaults to black or white, auto-chosen for contrast. */
textColor?: string;
/** Color of the document/label outlines. Defaults to the inherited text color. */
outlineColor?: string;
/** Optional language code (e.g. "EN") shown as a corner badge. Omit to hide the badge. */
language?: string;
/** Fill color of the language badge. Defaults to green. */
languageColor?: string;
}
/** Closed outline of the document body, a rounded sheet with a folded top-right corner. */
const DOCUMENT_PATH =
'M7.24,6.42 C7.24,5.55,7.95,4.85,8.83,4.85 H30.06 L41.46,16.25 V43.58 ' +
'C41.46,44.45,40.7,45.15,39.76,45.15 H8.94 C8,45.15,7.24,44.45,7.24,43.58 Z';
/**
* Picks a readable text color (black or white) for a given background color.
* Uses the perceptual YIQ brightness of the parsed RGB; falls back to black when the
* background can't be parsed as a hex color (e.g. "currentColor" or a named color).
*
* @param background - A CSS hex color string, 3- or 6-digit (e.g. "#e8302a", "#fff").
* @returns "#000000" for light backgrounds, "#ffffff" for dark ones.
* @example
* getContrastTextColor("#e8302a"); // "#ffffff" (red → white)
* getContrastTextColor("#f2dd2e"); // "#000000" (yellow → black)
* @source
*/
const getContrastTextColor = (background: string): string => {
const hex = background.replace('#', '');
const normalized =
hex.length === 3
? hex
.split('')
.map((char) => char + char)
.join('')
: hex;
if (!/^[0-9a-fA-F]{6}$/.test(normalized)) {
return '#000000';
}
const r = Number.parseInt(normalized.slice(0, 2), 16);
const g = Number.parseInt(normalized.slice(2, 4), 16);
const b = Number.parseInt(normalized.slice(4, 6), 16);
const yiq = (r * 299 + g * 587 + b * 114) / 1000;
return yiq >= 128 ? '#000000' : '#ffffff';
};
/**
* A Material-UI icon that renders a colored document with a labeled band and an optional
* language badge. Used as the shared base for document-type icons such as SDS and spec sheets.
* The label and badge text default to black or white, whichever contrasts with their
* background; pass `textColor` to override both.
*
* @component
* @param props - SvgIcon props plus the label text and optional color/language overrides
* @returns A React component that renders the labeled document icon
* @example
* // A red "SDS" document with an English badge
* <CustomFileIcon label="SDS" language="EN" fontSize="small" />
* @source
*/
const CustomFileIcon: FC<CustomFileIconProps> = ({
label,
labelFontSize = 15,
labelLetterSpacing = '.04em',
documentColor = '#ffffff',
labelColor = '#000000',
textColor,
outlineColor = 'currentColor',
language,
languageColor = '#000000',
...props
}) => {
const labelTextColor = textColor ?? getContrastTextColor(labelColor);
const badgeTextColor = textColor ?? getContrastTextColor(languageColor);
return (
<SvgIcon {...props} viewBox="0 0 48 48">
<g stroke={outlineColor} strokeWidth={2} strokeLinecap="round" strokeLinejoin="round">
<path d={DOCUMENT_PATH} fill={documentColor} />
<rect
x="3.52"
y="17.04"
width="41.48"
height="17.12"
rx="1.57"
ry="1.57"
fill={labelColor}
/>
</g>
<text
x="24"
y="30.5"
textAnchor="middle"
fill={labelTextColor}
fontFamily="EMprint-Bold, EMprint, sans-serif"
fontSize={labelFontSize}
fontWeight={900}
letterSpacing={labelLetterSpacing}
>
{label}
</text>
{language ? (
<>
<rect
x="22.5"
y="34"
width="19"
height="11"
rx="1.5"
ry="1.5"
fill={languageColor}
stroke={outlineColor}
strokeWidth={2}
strokeLinejoin="round"
/>
<text
x="32"
y="42.3"
textAnchor="middle"
fill={badgeTextColor}
fontFamily="EMprint-Bold, EMprint, sans-serif"
fontSize="8"
fontWeight={700}
>
{language.toUpperCase()}
</text>
</>
) : null}
</SvgIcon>
);
};
export default CustomFileIcon;
|