-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathutils.ts
More file actions
129 lines (107 loc) · 3.72 KB
/
utils.ts
File metadata and controls
129 lines (107 loc) · 3.72 KB
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
import { getLuminance } from 'polished';
const RGB_HEX = /^#?(?:([\da-f]{3})[\da-f]?|([\da-f]{6})(?:[\da-f]{2})?)$/i;
/** Ensure the consistency of colors between old and new colors */
const variantMapping = {
healthy: 'statusHealthy',
success: 'statusHealthy',
warning: 'statusWarning',
danger: 'statusCritical',
selected: 'selectedActive',
base: 'infoPrimary',
};
/** Translates the old colors into new colors while keeping the same name.
* New names are also supported. */
export const getThemePropSelector = (key) => (props) => {
const key_ = variantMapping[key] ?? key;
return props.theme[key_];
};
/** Translates the old colors into new colors while keeping same name.
* New names are also supported. */
export const getThemeVariantSelector = () => (props) => {
const theme = props.theme;
const key = variantMapping[props.variant] ?? props.variant;
return theme[key];
};
/** Returns the theme color key for a given variant (e.g. for use with Icon color prop). */
export const getVariantThemeKey = (variant: string): string =>
variantMapping[variant] ?? variant;
export const hex2RGB = (str: string): [number, number, number] => {
const [, short, long] = String(str).match(RGB_HEX) || [];
if (long) {
const value = Number.parseInt(long, 16);
return [value >> 16, (value >> 8) & 0xff, value & 0xff];
} else if (short) {
const [r, g, b] = Array.from(short, (s) => Number.parseInt(s, 16)).map(
(n) => (n << 4) | n,
);
return [r, g, b];
}
throw new Error('Invalid hex string provided');
};
const wcagContrastRatio = (l1: number, l2: number): number =>
(Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
// Minimum WCAG contrast ratio to consider a text color readable on a background.
// 3.0 corresponds to WCAG AA for large text — same threshold used by MUI.
const CONTRAST_THRESHOLD = 3;
export const getContrastText = (
bgColor: string,
textPrimary: string,
textReverse: string,
): string | null => {
try {
const bgLum = getLuminance(bgColor);
const primaryLum = getLuminance(textPrimary);
const reverseLum = getLuminance(textReverse);
const lighterText = primaryLum >= reverseLum ? textPrimary : textReverse;
const darkerText = primaryLum >= reverseLum ? textReverse : textPrimary;
const lighterContrast = wcagContrastRatio(primaryLum >= reverseLum ? primaryLum : reverseLum, bgLum);
return lighterContrast >= CONTRAST_THRESHOLD ? lighterText : darkerText;
} catch {
return null;
}
};
export const convertRemToPixels = (rem: number): number => {
if (
document.documentElement &&
rem &&
Number.isFinite(rem) &&
!Number.isNaN(rem)
) {
return (
rem * parseFloat(getComputedStyle(document.documentElement).fontSize) || 0
);
}
return 0;
};
type FormatISONumberOptions = {
decimals?: number;
compact?: boolean;
fixedDecimals?: boolean;
};
/**
* Formats a number to ISO 80000-1 format:
* - Space as thousands separator
* - Dot as decimal separator
* - Optional compact notation (10K, 1M, etc.)
* - Very small values (< 0.001): scientific notation
*/
export const formatISONumber = (
value: number,
options: FormatISONumberOptions = {},
): string => {
const { decimals = 2, compact = false, fixedDecimals = false } = options;
if (value === 0) return '0';
const absValue = Math.abs(value);
if (absValue < 0.001) {
return value.toExponential();
}
// ISO format: space as thousands separator, dot as decimal separator
// With optional compact notation (10K, 1M, etc.)
return new Intl.NumberFormat('fr-FR', {
minimumFractionDigits: fixedDecimals ? decimals : undefined,
maximumFractionDigits: decimals,
notation: compact ? 'compact' : 'standard',
})
.format(value)
.replace(',', '.');
};