-
Notifications
You must be signed in to change notification settings - Fork 6
/
cssinjs-inlclude-media.ts
99 lines (82 loc) · 2.52 KB
/
cssinjs-inlclude-media.ts
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
interface BreakPoints {
smallPhone: number;
phone: number;
tablet: number;
desktop: number;
largeDesktop: number;
}
let breakpoints = {
smallPhone: 320,
phone: 375,
tablet: 768,
desktop: 1024,
largeDesktop: 1440,
};
const signRegex = /^[<=>]+/;
function throwError(): never {
throw "invalid media-query :(";
}
function throwBreakPointError(): never {
throw "invalid breakpoint :(";
}
/**
* get breakpoint list of css-in-js-media
*/
function getBreakPoints(): BreakPoints {
return breakpoints;
}
function checkValidBreakpoint(customizedBreakPoints): boolean {
const keysOfOrigin = Object.keys(breakpoints);
const keysOfCustomized = Object.keys(customizedBreakPoints);
return keysOfCustomized.every((key) => keysOfOrigin.includes(key));
}
/**
* set break points of css-in-js-media library with custom param
* @param customizedBreakPoints customized breakpoint param
*/
function setBreakPoints(customizedBreakPoints: BreakPoints): never | void {
const isValidBreakPoints = checkValidBreakpoint(customizedBreakPoints);
if (!isValidBreakPoints) {
return throwBreakPointError();
}
breakpoints = { ...breakpoints, ...customizedBreakPoints };
}
/**
* use css in js media (ex: includeMedia(">=phone", "<tablet"))
* @param query
* @param betweenQuery
*/
function cssinjsMedia(query: string, betweenQuery?: string): string | never {
const queries = betweenQuery ? [query, betweenQuery] : [query];
return queries.every(checkValid)
? `@media ${queries.map(convertToQuery).join(" and ")}`
: throwError();
}
function checkValid(param) {
const [sign, screenSize] = parseParam(param);
const checkResult = Boolean(sign) && Boolean(breakpoints[screenSize]);
return checkResult;
}
function parseParam(param: string) {
const sign = param.match(signRegex) ? param.match(signRegex)[0].trim() : "";
const screenSize = param.replace(signRegex, "").trim();
return [sign, screenSize];
}
function calculateSize(sign: string, screenSize: string) {
if (sign.includes("=")) {
return breakpoints[screenSize];
}
if (sign.includes(">")) {
return breakpoints[screenSize] + 1;
}
return breakpoints[screenSize] - 1;
}
function convertToQuery(param: string) {
const [sign, screenSize] = parseParam(param);
const size = calculateSize(sign, screenSize);
const unit = typeof size === "number" ? "px" : "";
const widthCondition = sign.includes(">") ? "min-width" : "max-width";
return `(${widthCondition}: ${size}${unit})`;
}
export default cssinjsMedia;
export { getBreakPoints, setBreakPoints };