-
-
Notifications
You must be signed in to change notification settings - Fork 779
/
breakpoints.ts
82 lines (71 loc) · 2.76 KB
/
breakpoints.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
import type { VariantObject } from '@unocss/core'
import { resolveBreakpoints } from '../utils'
export function calcMaxWidthBySize(size: string) {
const value = size.match(/^-?[0-9]+\.?[0-9]*/)?.[0] || ''
const unit = size.slice(value.length)
if (unit === 'px') {
const maxWidth = (Number.parseFloat(value) - 0.1)
return Number.isNaN(maxWidth) ? size : `${maxWidth}${unit}`
}
return `calc(${size} - 0.1px)`
}
export function variantBreakpoints(): VariantObject {
const regexCache: Record<string, RegExp> = {}
return {
name: 'breakpoints',
match(matcher, context) {
const variantEntries: Array<[string, string, number]>
= Object.entries(resolveBreakpoints(context) ?? {}).map(([point, size], idx) => [point, size, idx])
for (const [point, size, idx] of variantEntries) {
if (!regexCache[point])
regexCache[point] = new RegExp(`^((?:([al]t-|[<~]|max-))?${point}(?:${context.generator.config.separators.join('|')}))`)
const match = matcher.match(regexCache[point])
if (!match)
continue
const [, pre] = match
const m = matcher.slice(pre.length)
// container rule is responsive, but also is breakpoint aware
// it is handled on its own module (container.ts) and so we
// exclude it from here
if (m === 'container')
continue
const isLtPrefix = pre.startsWith('lt-') || pre.startsWith('<') || pre.startsWith('max-')
const isAtPrefix = pre.startsWith('at-') || pre.startsWith('~')
let order = 1000 // parseInt(size)
if (isLtPrefix) {
order -= (idx + 1)
return {
matcher: m,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (max-width: ${calcMaxWidthBySize(size)})`,
parentOrder: order,
}),
}
}
order += (idx + 1)
// support for windicss @<breakpoint> => last breakpoint will not have the upper bound
if (isAtPrefix && idx < variantEntries.length - 1) {
return {
matcher: m,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (min-width: ${size}) and (max-width: ${calcMaxWidthBySize(variantEntries[idx + 1][1])})`,
parentOrder: order,
}),
}
}
return {
matcher: m,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$ ` : ''}@media (min-width: ${size})`,
parentOrder: order,
}),
}
}
},
multiPass: true,
autocomplete: '(at-|lt-|max-|)$breakpoints:',
}
}