Refactor box-shadow and ring to not use universal selector in JIT

This commit is contained in:
Adam Wathan 2021-06-25 11:34:57 -04:00
parent d782a7869a
commit 92d1664d2f
4 changed files with 220 additions and 24 deletions

View file

@ -1,11 +1,28 @@
import transformThemeValue from '../util/transformThemeValue'
import postcss from 'postcss'
import parseObjectStyles from '../util/parseObjectStyles'
let baseRulesKey = Symbol()
export function addBaseSelector(memory, selector) {
let baseRoot = memory.get(baseRulesKey)
if (baseRoot.nodes.length === 0) {
baseRoot.append(
parseObjectStyles({
[selector]: {
'--tw-ring-offset-shadow': '0 0 #0000',
'--tw-ring-shadow': '0 0 #0000',
'--tw-shadow': '0 0 #0000',
},
})
)
} else {
baseRoot.nodes[0].selectors = [...baseRoot.nodes[0].selectors, selector]
}
}
let transformValue = transformThemeValue('boxShadow')
let shadowReset = {
'*, ::before, ::after': {
'--tw-shadow': '0 0 #0000',
},
}
let defaultBoxShadow = [
`var(--tw-ring-offset-shadow, 0 0 #0000)`,
`var(--tw-ring-shadow, 0 0 #0000)`,
@ -13,16 +30,29 @@ let defaultBoxShadow = [
].join(', ')
export default function () {
return function ({ config, matchUtilities, addBase, addUtilities, theme, variants }) {
return function ({ config, matchUtilities, addBase, addUtilities, theme, variants, memory }) {
if (config('mode') === 'jit') {
addBase(shadowReset)
let baseRoot = postcss.root()
memory.set(baseRulesKey, baseRoot)
addBase(baseRoot)
} else {
addUtilities(shadowReset, { respectImportant: false })
addUtilities(
{
'*, ::before, ::after': {
'--tw-shadow': '0 0 #0000',
},
},
{ respectImportant: false }
)
}
matchUtilities(
{
shadow: (value) => {
shadow: (value, { selector }) => {
if (config('mode') === 'jit') {
addBaseSelector(memory, selector)
}
value = transformValue(value)
return {

View file

@ -1,7 +1,13 @@
import { withAlphaValue } from '../util/withAlphaVariable'
import postcss from 'postcss'
import parseObjectStyles from '../util/parseObjectStyles'
export default function () {
return function ({ config, matchUtilities, addBase, addUtilities, theme, variants }) {
let baseRulesKey = Symbol()
export function addBaseSelector(memory, theme, selector) {
let baseRoot = memory.get(baseRulesKey)
if (baseRoot.nodes.length === 0) {
let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
let ringColorDefault = withAlphaValue(
theme('ringColor.DEFAULT'),
@ -9,26 +15,58 @@ export default function () {
`rgba(147, 197, 253, ${ringOpacityDefault})`
)
let ringReset = {
'*, ::before, ::after': {
'--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-ring-offset-width': theme('ringOffsetWidth.DEFAULT', '0px'),
'--tw-ring-offset-color': theme('ringOffsetColor.DEFAULT', '#fff'),
'--tw-ring-color': ringColorDefault,
'--tw-ring-offset-shadow': '0 0 #0000',
'--tw-ring-shadow': '0 0 #0000',
},
}
baseRoot.append(
parseObjectStyles({
[selector]: {
'--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-ring-offset-width': theme('ringOffsetWidth.DEFAULT', '0px'),
'--tw-ring-offset-color': theme('ringOffsetColor.DEFAULT', '#fff'),
'--tw-ring-color': ringColorDefault,
'--tw-ring-offset-shadow': '0 0 #0000',
'--tw-ring-shadow': '0 0 #0000',
'--tw-shadow': '0 0 #0000',
},
})
)
} else {
baseRoot.nodes[0].selectors = [...baseRoot.nodes[0].selectors, selector]
}
}
if (config('mode') === 'jit') {
addBase(ringReset)
export default function () {
return function ({ config, matchUtilities, addBase, addUtilities, theme, variants, memory }) {
if (config('mode') == 'jit') {
let baseRoot = postcss.root()
memory.set(baseRulesKey, baseRoot)
addBase(baseRoot)
} else {
let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
let ringColorDefault = withAlphaValue(
theme('ringColor.DEFAULT'),
ringOpacityDefault,
`rgba(147, 197, 253, ${ringOpacityDefault})`
)
let ringReset = {
'*, ::before, ::after': {
'--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-ring-offset-width': theme('ringOffsetWidth.DEFAULT', '0px'),
'--tw-ring-offset-color': theme('ringOffsetColor.DEFAULT', '#fff'),
'--tw-ring-color': ringColorDefault,
'--tw-ring-offset-shadow': '0 0 #0000',
'--tw-ring-shadow': '0 0 #0000',
},
}
addUtilities(ringReset, { respectImportant: false })
}
matchUtilities(
{
ring: (value) => {
ring: (value, { selector }) => {
if (config('mode') === 'jit') {
addBaseSelector(memory, theme, selector)
}
return {
'--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`,
'--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(${value} + var(--tw-ring-offset-width)) var(--tw-ring-color)`,

View file

@ -0,0 +1,57 @@
import postcss from 'postcss'
import path from 'path'
import tailwind from '../../src/jit/index.js'
function run(input, config = {}) {
const { currentTestName } = expect.getState()
return postcss(tailwind(config)).process(input, {
from: `${path.resolve(__filename)}?test=${currentTestName}`,
})
}
test('basic ring width', async () => {
let config = {
mode: 'jit',
purge: [
{
raw: '<div class="shadow shadow-md shadow-lg"></div>',
},
],
corePlugins: ['boxShadow'],
theme: {},
plugins: [],
}
let css = `
@tailwind base;
@tailwind utilities
`
return run(css, config).then((result) => {
expect(result.css).toMatchFormattedCss(`
.shadow,
.shadow-md,
.shadow-lg {
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
}
.shadow {
--tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
var(--tw-shadow);
}
.shadow-md {
--tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
var(--tw-shadow);
}
.shadow-lg {
--tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
var(--tw-shadow);
}
`)
})
})

View file

@ -0,0 +1,71 @@
import postcss from 'postcss'
import path from 'path'
import tailwind from '../../src/jit/index.js'
function run(input, config = {}) {
const { currentTestName } = expect.getState()
return postcss(tailwind(config)).process(input, {
from: `${path.resolve(__filename)}?test=${currentTestName}`,
})
}
test('basic ring width', async () => {
let config = {
mode: 'jit',
purge: [
{
raw: '<div class="ring ring-2 ring-4 ring-blue-500 ring-offset-2 ring-offset-blue-100"></div>',
},
],
corePlugins: ['ringColor', 'ringOffsetColor', 'ringOffsetWidth', 'ringOpacity', 'ringWidth'],
theme: {},
plugins: [],
}
let css = `
@tailwind base;
@tailwind utilities
`
return run(css, config).then((result) => {
expect(result.css).toMatchFormattedCss(`
.ring,
.ring-2,
.ring-4 {
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgba(59, 130, 246, 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
}
.ring {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)
}
.ring-2 {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)
}
.ring-4 {
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color);
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)
}
.ring-blue-500 {
--tw-ring-opacity: 1;
--tw-ring-color: rgba(59, 130, 246, var(--tw-ring-opacity));
}
.ring-offset-2 {
--tw-ring-offset-width: 2px;
}
.ring-offset-blue-100 {
--tw-ring-offset-color: #dbeafe;
}
`)
})
})