Refactor some screen compatibility code (#14465)
These changes were extracted from our work on a `screen()` function for CSS — we've decided to move those changes to a code mod instead of implementing support for `screen()` in the compiler — but the refactoring around the changes still makes sense to do so I'm landing that here separately. --------- Co-authored-by: Philipp Spiess <hello@philippspiess.com>
This commit is contained in:
parent
ba5b9afc8a
commit
4e129be2b7
4 changed files with 77 additions and 36 deletions
|
|
@ -203,4 +203,19 @@ function mergeTheme(ctx: ResolutionContext) {
|
|||
for (let key in ctx.theme) {
|
||||
ctx.theme[key] = resolveValue(ctx.theme[key])
|
||||
}
|
||||
|
||||
// Turn {min: '123px'} into '123px' in screens
|
||||
if (ctx.theme.screens && typeof ctx.theme.screens === 'object') {
|
||||
for (let key of Object.keys(ctx.theme.screens)) {
|
||||
let screen = ctx.theme.screens[key]
|
||||
if (!screen) continue
|
||||
if (typeof screen !== 'object') continue
|
||||
|
||||
if ('raw' in screen) continue
|
||||
if ('max' in screen) continue
|
||||
if (!('min' in screen)) continue
|
||||
|
||||
ctx.theme.screens[key] = screen.min
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@ describe('complex screen configs', () => {
|
|||
md: [
|
||||
//
|
||||
{ min: '668px', max: '767px' },
|
||||
{ min: '868px' },
|
||||
'868px',
|
||||
],
|
||||
lg: { min: '868px' },
|
||||
xl: { min: '1024px', max: '1279px' },
|
||||
|
|
@ -468,15 +468,14 @@ describe('complex screen configs', () => {
|
|||
}),
|
||||
})
|
||||
|
||||
expect(
|
||||
compiler.build(['min-sm:flex', 'min-md:flex', 'min-lg:flex', 'min-xl:flex', 'min-tall:flex']),
|
||||
).toBe('')
|
||||
expect(compiler.build(['min-sm:flex', 'min-md:flex', 'min-xl:flex', 'min-tall:flex'])).toBe('')
|
||||
|
||||
expect(
|
||||
compiler.build([
|
||||
'sm:flex',
|
||||
'md:flex',
|
||||
'lg:flex',
|
||||
'min-lg:flex',
|
||||
'xl:flex',
|
||||
'tall:flex',
|
||||
|
||||
|
|
@ -485,22 +484,27 @@ describe('complex screen configs', () => {
|
|||
]),
|
||||
).toMatchInlineSnapshot(`
|
||||
".lg\\:flex {
|
||||
@media (min-width: 868px) {
|
||||
@media (width >= 868px) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.min-lg\\:flex {
|
||||
@media (width >= 868px) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.sm\\:flex {
|
||||
@media (max-width: 639px) {
|
||||
@media (639px >= width) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.md\\:flex {
|
||||
@media (min-width: 668px and max-width: 767px), (min-width: 868px) {
|
||||
@media (767px >= width >= 668px), (width >= 868px) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
.xl\\:flex {
|
||||
@media (min-width: 1024px and max-width: 1279px) {
|
||||
@media (1279px >= width >= 1024px) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,24 +31,14 @@ export function registerScreensConfig(userConfig: ResolvedConfig, designSystem:
|
|||
continue
|
||||
}
|
||||
|
||||
let query: string | undefined
|
||||
let deferInsert = true
|
||||
|
||||
if (typeof value === 'string') {
|
||||
query = `(width >= ${value})`
|
||||
deferInsert = false
|
||||
} else if (typeof value === 'object' && value !== null) {
|
||||
if (Array.isArray(value)) {
|
||||
query = value.map(ruleForComplexScreenValue).join(', ')
|
||||
} else {
|
||||
query = ruleForComplexScreenValue(value) ?? ''
|
||||
if ('min' in value && !('max' in value)) {
|
||||
deferInsert = false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
let query = buildMediaQuery(value)
|
||||
|
||||
function insert(order: number) {
|
||||
// `min-*` and `max-*` rules do not need to be reconfigured, as they are
|
||||
// reading the latest values from the theme.
|
||||
|
|
@ -87,19 +77,47 @@ export function registerScreensConfig(userConfig: ResolvedConfig, designSystem:
|
|||
}
|
||||
}
|
||||
|
||||
function ruleForComplexScreenValue(value: object): string | null {
|
||||
let query = null
|
||||
if ('raw' in value && typeof value.raw === 'string') {
|
||||
query = value.raw
|
||||
} else {
|
||||
let rules: string[] = []
|
||||
|
||||
if ('min' in value) rules.push(`min-width: ${value.min}`)
|
||||
if ('max' in value) rules.push(`max-width: ${value.max}`)
|
||||
|
||||
if (rules.length !== 0) {
|
||||
query = `(${rules.join(' and ')})`
|
||||
}
|
||||
export function buildMediaQuery(values: unknown) {
|
||||
type ScreenDescriptor = {
|
||||
min?: string
|
||||
max?: string
|
||||
raw?: string
|
||||
}
|
||||
return query
|
||||
|
||||
let list: unknown[] = Array.isArray(values) ? values : [values]
|
||||
return list
|
||||
.map((value): ScreenDescriptor | null => {
|
||||
if (typeof value === 'string') {
|
||||
return { min: value }
|
||||
}
|
||||
|
||||
if (value && typeof value === 'object') {
|
||||
return value
|
||||
}
|
||||
|
||||
return null
|
||||
})
|
||||
.map((screen) => {
|
||||
if (screen === null) return null
|
||||
|
||||
if ('raw' in screen) {
|
||||
return screen.raw
|
||||
}
|
||||
|
||||
let query = ''
|
||||
|
||||
if (screen.max !== undefined) {
|
||||
query += `${screen.max} >= `
|
||||
}
|
||||
|
||||
query += 'width'
|
||||
|
||||
if (screen.min !== undefined) {
|
||||
query += ` >= ${screen.min}`
|
||||
}
|
||||
|
||||
return `(${query})`
|
||||
})
|
||||
.filter(Boolean)
|
||||
.join(', ')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,9 +19,13 @@ export function substituteFunctions(ast: AstNode[], resolveThemeValue: ResolveTh
|
|||
if (
|
||||
node.selector[0] === '@' &&
|
||||
(node.selector.startsWith('@media ') ||
|
||||
node.selector.startsWith('@media(') ||
|
||||
node.selector.startsWith('@custom-media ') ||
|
||||
node.selector.startsWith('@custom-media(') ||
|
||||
node.selector.startsWith('@container ') ||
|
||||
node.selector.startsWith('@supports ')) &&
|
||||
node.selector.startsWith('@container(') ||
|
||||
node.selector.startsWith('@supports ') ||
|
||||
node.selector.startsWith('@supports(')) &&
|
||||
node.selector.includes(THEME_FUNCTION_INVOCATION)
|
||||
) {
|
||||
node.selector = substituteFunctionsInValue(node.selector, resolveThemeValue)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue