@fibery/ui-kit 1.11.0 → 1.11.2-next
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fibery/ui-kit",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.2-next",
|
|
4
4
|
"main": "index.ts",
|
|
5
5
|
"private": false,
|
|
6
6
|
"files": [
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"src/tooltip.tsx",
|
|
24
24
|
"src/BackButton.tsx",
|
|
25
25
|
"src/Button",
|
|
26
|
-
"src/emoji-mart/**/*.ts*"
|
|
26
|
+
"src/emoji-mart/**/*.ts*",
|
|
27
|
+
"src/a11y-color.ts"
|
|
27
28
|
],
|
|
28
29
|
"license": "UNLICENSED",
|
|
29
30
|
"dependencies": {
|
|
@@ -59,6 +60,7 @@
|
|
|
59
60
|
"react-windowed-select": "5.0.0",
|
|
60
61
|
"screenfull": "6.0.1",
|
|
61
62
|
"ua-parser-js": "0.7.24",
|
|
63
|
+
"@fibery/emoji-data": "1.1.1",
|
|
62
64
|
"@fibery/helpers": "1.0.4",
|
|
63
65
|
"@fibery/react": "1.0.2"
|
|
64
66
|
},
|
|
@@ -93,8 +95,8 @@
|
|
|
93
95
|
"svgo": "2.8.0",
|
|
94
96
|
"typescript": "5.0.3",
|
|
95
97
|
"unist-util-reduce": "0.2.2",
|
|
96
|
-
"@fibery/
|
|
97
|
-
"@fibery/
|
|
98
|
+
"@fibery/babel-preset": "7.2.0",
|
|
99
|
+
"@fibery/eslint-config": "8.3.0"
|
|
98
100
|
},
|
|
99
101
|
"jest": {
|
|
100
102
|
"testEnvironment": "jsdom",
|
|
@@ -108,7 +108,7 @@ type StyledProps = {
|
|
|
108
108
|
const StyledButtonBase = styled.button<StyledProps>`
|
|
109
109
|
display: block;
|
|
110
110
|
box-sizing: border-box;
|
|
111
|
-
font-weight: ${fontWeight.
|
|
111
|
+
font-weight: ${fontWeight.medium};
|
|
112
112
|
margin: 0;
|
|
113
113
|
border-radius: ${border.radius6}px;
|
|
114
114
|
border: 0;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// https://github.com/alex-page/a11ycolor
|
|
2
|
+
import chroma from "chroma-js";
|
|
3
|
+
|
|
4
|
+
class LRUCache<TKey, TValue> {
|
|
5
|
+
#capacity: number;
|
|
6
|
+
#cache: Map<TKey, TValue>;
|
|
7
|
+
constructor(capacity: number) {
|
|
8
|
+
this.#cache = new Map();
|
|
9
|
+
this.#capacity = capacity;
|
|
10
|
+
}
|
|
11
|
+
has(key: TKey) {
|
|
12
|
+
return this.#cache.has(key);
|
|
13
|
+
}
|
|
14
|
+
get(key: TKey) {
|
|
15
|
+
if (!this.has(key)) {
|
|
16
|
+
throw new Error('Please check if the key exists using the "has" method');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const val = this.#cache.get(key);
|
|
20
|
+
this.#cache.delete(key);
|
|
21
|
+
this.#cache.set(key, val as unknown as TValue);
|
|
22
|
+
|
|
23
|
+
return val;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
put(key: TKey, value: TValue) {
|
|
27
|
+
this.#cache.delete(key);
|
|
28
|
+
|
|
29
|
+
if (this.#cache.size === this.#capacity) {
|
|
30
|
+
this.#cache.delete(this.#cache.keys().next().value);
|
|
31
|
+
this.#cache.set(key, value);
|
|
32
|
+
} else {
|
|
33
|
+
this.#cache.set(key, value);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const cache = new LRUCache<string, string>(5000);
|
|
39
|
+
|
|
40
|
+
const checkColor = (colorValue: string) => {
|
|
41
|
+
if (colorValue === "transparent") {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
return chroma.valid(colorValue);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Find the nearest accessible color
|
|
54
|
+
*
|
|
55
|
+
* @param {string} toMakeA11y - The color that is to be changed
|
|
56
|
+
* @param {string} background - The background color to for the contrast
|
|
57
|
+
* * @param {string} minimumContrast - The WCAG 2.1 contrast ratio
|
|
58
|
+
*
|
|
59
|
+
* @return {string} - The closest hex color for `toMakeA11y` on `background`
|
|
60
|
+
*/
|
|
61
|
+
export function a11yColor(toMakeA11y: string, background: string, minimumContrast = 3.0) {
|
|
62
|
+
if (!checkColor(toMakeA11y) || !checkColor(background)) {
|
|
63
|
+
return toMakeA11y;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (minimumContrast < 0 && minimumContrast > 21) {
|
|
67
|
+
throw new Error(`Minimum contrast must be a number between 0 and 21. It was ${minimumContrast}`);
|
|
68
|
+
}
|
|
69
|
+
const key = toMakeA11y + background + minimumContrast;
|
|
70
|
+
if (cache.has(key)) {
|
|
71
|
+
return cache.get(key);
|
|
72
|
+
}
|
|
73
|
+
const a11y = chroma(toMakeA11y);
|
|
74
|
+
const bg = chroma(background);
|
|
75
|
+
|
|
76
|
+
// Check the ratio straight away, if it passes return the value as hex
|
|
77
|
+
if (chroma.contrast(background, toMakeA11y) >= minimumContrast) {
|
|
78
|
+
return a11y.hex();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Ratio didn't pass so we need to find the nearest color
|
|
82
|
+
const a11yHSL = a11y.hsl();
|
|
83
|
+
const a11yLightness = a11yHSL[2] * 100;
|
|
84
|
+
const minHexDiff = 100 / 255; // 255 Colors / 100% HSL
|
|
85
|
+
|
|
86
|
+
const isBlackBgContrast = chroma.contrast(background, "#000") >= minimumContrast;
|
|
87
|
+
const isWhiteBgContrast = chroma.contrast(background, "#FFF") >= minimumContrast;
|
|
88
|
+
let minLightness = 0;
|
|
89
|
+
let maxLightness = 100;
|
|
90
|
+
let isDarkColor = false;
|
|
91
|
+
|
|
92
|
+
// If black and white both pass on the background
|
|
93
|
+
if (isBlackBgContrast && isWhiteBgContrast) {
|
|
94
|
+
// Change the min lightness if the color is light
|
|
95
|
+
if (a11yLightness >= 50) {
|
|
96
|
+
minLightness = a11yLightness;
|
|
97
|
+
} else {
|
|
98
|
+
// Change the max lightness if the color is dark
|
|
99
|
+
maxLightness = a11yLightness;
|
|
100
|
+
isDarkColor = true;
|
|
101
|
+
}
|
|
102
|
+
} else if (isBlackBgContrast) {
|
|
103
|
+
// If our colour passes contrast on black
|
|
104
|
+
maxLightness = a11yLightness;
|
|
105
|
+
isDarkColor = true;
|
|
106
|
+
} else {
|
|
107
|
+
// Colour doesn't meet contrast pass on black
|
|
108
|
+
minLightness = a11yLightness;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// The colour to return
|
|
112
|
+
let foundColor;
|
|
113
|
+
|
|
114
|
+
// Binary search until we find the colour that meets contrast
|
|
115
|
+
while (!foundColor) {
|
|
116
|
+
const midLightness = (minLightness + maxLightness) / 2;
|
|
117
|
+
const midA11y = chroma.hsl(a11yHSL[0], a11yHSL[1], midLightness / 100);
|
|
118
|
+
|
|
119
|
+
// Give up if we are stuck
|
|
120
|
+
if (Math.abs(maxLightness - minLightness) < 0.01) {
|
|
121
|
+
foundColor = midA11y.hex();
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// The colour meets contrast
|
|
126
|
+
if (chroma.contrast(midA11y.hex(), bg) >= minimumContrast) {
|
|
127
|
+
// It is the minimal lightness range for one hexadecimal
|
|
128
|
+
if (maxLightness - minLightness <= minHexDiff) {
|
|
129
|
+
foundColor = midA11y.hex();
|
|
130
|
+
} else if (isDarkColor) {
|
|
131
|
+
// If it is going to be a dark color move the min to mid
|
|
132
|
+
minLightness = midLightness;
|
|
133
|
+
} else {
|
|
134
|
+
// If it is going to be a light color move the max to mid
|
|
135
|
+
maxLightness = midLightness;
|
|
136
|
+
}
|
|
137
|
+
} else if (isDarkColor) {
|
|
138
|
+
// We do not meet minimum contrast if it is a dark color move max to mid
|
|
139
|
+
maxLightness = midLightness;
|
|
140
|
+
} else {
|
|
141
|
+
// If it is a light color move min to mid
|
|
142
|
+
minLightness = midLightness;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return foundColor;
|
|
147
|
+
}
|
package/src/designSystem.ts
CHANGED
|
@@ -23,9 +23,11 @@ import {a11yColor} from "./a11y-color";
|
|
|
23
23
|
export const typeSizes = [28, 24, 18, 16, 14, 12, 10, 8] as const;
|
|
24
24
|
|
|
25
25
|
export const fontWeight = {
|
|
26
|
+
light: 300,
|
|
26
27
|
regular: 400,
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
medium: 500,
|
|
29
|
+
semibold: 600,
|
|
30
|
+
bold: 700,
|
|
29
31
|
} as const;
|
|
30
32
|
|
|
31
33
|
const transparent = "rgba(255, 255, 255, 0)";
|
|
@@ -839,7 +841,7 @@ export const textStyles = {
|
|
|
839
841
|
fontSize: typeSizes[0],
|
|
840
842
|
letterSpacing: "-0.003em",
|
|
841
843
|
lineHeight: lineHeight.heading,
|
|
842
|
-
fontWeight: fontWeight.
|
|
844
|
+
fontWeight: fontWeight.medium,
|
|
843
845
|
color: themeVars.textColor,
|
|
844
846
|
},
|
|
845
847
|
heading2: {
|
|
@@ -847,7 +849,7 @@ export const textStyles = {
|
|
|
847
849
|
fontSize: typeSizes[1],
|
|
848
850
|
letterSpacing: "-0.002em",
|
|
849
851
|
lineHeight: lineHeight.heading,
|
|
850
|
-
fontWeight: fontWeight.
|
|
852
|
+
fontWeight: fontWeight.medium,
|
|
851
853
|
color: themeVars.textColor,
|
|
852
854
|
},
|
|
853
855
|
heading3: {
|
|
@@ -855,21 +857,21 @@ export const textStyles = {
|
|
|
855
857
|
fontSize: typeSizes[2],
|
|
856
858
|
letterSpacing: "-0.002em",
|
|
857
859
|
lineHeight: lineHeight.heading,
|
|
858
|
-
fontWeight: fontWeight.
|
|
860
|
+
fontWeight: fontWeight.medium,
|
|
859
861
|
color: themeVars.textColor,
|
|
860
862
|
},
|
|
861
863
|
heading4: {
|
|
862
864
|
fontFamily,
|
|
863
865
|
fontSize: typeSizes[3],
|
|
864
866
|
lineHeight: lineHeight.heading,
|
|
865
|
-
fontWeight: fontWeight.
|
|
867
|
+
fontWeight: fontWeight.medium,
|
|
866
868
|
color: themeVars.textColor,
|
|
867
869
|
},
|
|
868
870
|
heading5: {
|
|
869
871
|
fontFamily,
|
|
870
872
|
fontSize: typeSizes[4],
|
|
871
873
|
lineHeight: lineHeight.heading,
|
|
872
|
-
fontWeight: fontWeight.
|
|
874
|
+
fontWeight: fontWeight.medium,
|
|
873
875
|
color: themeVars.textColor,
|
|
874
876
|
},
|
|
875
877
|
heading6: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {Data} from "emoji-mart";
|
|
2
1
|
import {detectEmojiSupportLevel} from "../emoji-support";
|
|
2
|
+
import type {Data} from "emoji-mart";
|
|
3
3
|
|
|
4
4
|
export type EmojiDataProps = {
|
|
5
5
|
native: boolean;
|
|
@@ -15,12 +15,18 @@ let promise: Promise<EmojiDataProps>;
|
|
|
15
15
|
const backgroundImageFn = (set: string) =>
|
|
16
16
|
`https://fibery-ui-public-assets.s3.eu-central-1.amazonaws.com/images/emoji-datasource-${set}-15_0_1-64.png`;
|
|
17
17
|
|
|
18
|
+
export const loadEmojiData = async () => {
|
|
19
|
+
const data = await import("@fibery/emoji-data/data/all.json");
|
|
20
|
+
return data.default;
|
|
21
|
+
};
|
|
22
|
+
|
|
18
23
|
const getAppleDataProps = async (): Promise<EmojiDataProps> => {
|
|
19
|
-
const [level, data] = await Promise.all([detectEmojiSupportLevel(),
|
|
24
|
+
const [level, data] = await Promise.all([detectEmojiSupportLevel(), loadEmojiData()]);
|
|
20
25
|
|
|
21
26
|
return {
|
|
22
|
-
native: level >= 14,
|
|
23
|
-
data
|
|
27
|
+
native: level >= 14,
|
|
28
|
+
// type declarations between @fibery/emoji-data and emoji-mart conflict a bit but they are compatible
|
|
29
|
+
data: data as unknown as Data,
|
|
24
30
|
backgroundImageFn,
|
|
25
31
|
set: "apple",
|
|
26
32
|
sheetColumns: 61,
|
|
@@ -28,11 +34,12 @@ const getAppleDataProps = async (): Promise<EmojiDataProps> => {
|
|
|
28
34
|
};
|
|
29
35
|
};
|
|
30
36
|
const getTwitterDataProps = async (): Promise<EmojiDataProps> => {
|
|
31
|
-
const data = await
|
|
37
|
+
const data = await loadEmojiData();
|
|
32
38
|
|
|
33
39
|
return {
|
|
34
40
|
native: false,
|
|
35
|
-
data
|
|
41
|
+
// type declarations between @fibery/emoji-data and emoji-mart conflict a bit but they are compatible
|
|
42
|
+
data: data as unknown as Data,
|
|
36
43
|
backgroundImageFn,
|
|
37
44
|
set: "twitter",
|
|
38
45
|
sheetColumns: 61,
|
package/src/tooltip.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {css, cx} from "@linaria/core";
|
|
2
2
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
3
3
|
import type {ReactNode, SyntheticEvent} from "react";
|
|
4
|
-
import {border, lineHeight, space, themeVars, tooltipDelay} from "./designSystem";
|
|
4
|
+
import {border, fontWeight, lineHeight, space, themeVars, tooltipDelay} from "./designSystem";
|
|
5
5
|
|
|
6
6
|
const preventDefaultAndStopPropagation = (e: SyntheticEvent) => {
|
|
7
7
|
e.preventDefault();
|
|
@@ -11,13 +11,13 @@ const preventDefaultAndStopPropagation = (e: SyntheticEvent) => {
|
|
|
11
11
|
const titleStyle = css`
|
|
12
12
|
color: ${themeVars.whiteColor};
|
|
13
13
|
line-height: ${lineHeight.heading};
|
|
14
|
-
font-weight:
|
|
14
|
+
font-weight: ${fontWeight.medium};
|
|
15
15
|
`;
|
|
16
16
|
|
|
17
17
|
const descriptionStyle = css`
|
|
18
18
|
color: ${themeVars.shortcutTextColor};
|
|
19
19
|
line-height: ${lineHeight.heading};
|
|
20
|
-
font-weight:
|
|
20
|
+
font-weight: ${fontWeight.regular};
|
|
21
21
|
`;
|
|
22
22
|
|
|
23
23
|
const tooltipStyle = css`
|
package/src/emoji-mart/data.tsx
DELETED