Improve matchUtilities API and make it work with the AOT engine (#4232)

* implement matchUtilities2

* ensure animation names without keyframes are not prefixed

* remove matchBase

* call addUtilities for each group individually

* WIP: Write plugins using matchUtilities2

* MORE

* Fix arbitrary value support for fontSize

* Fixes, update fixtures

* Rebuild fixtures

* Don't generate `divide` class with no modifier

* Fixes, rebuild fixtures

* Rename matchUtilities2 to matchUtilities

* Delete bad tests

* Remove temp files GROSS

* Clean stuff up

* Support no return in matchUtilities

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
This commit is contained in:
Robin Malfait 2021-05-05 15:23:32 +02:00 committed by GitHub
parent d76c55afc6
commit 6628eb00ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 81467 additions and 82678 deletions

View File

@ -215,17 +215,12 @@ function* resolveMatches(candidate, context) {
// }
for (let matchedPlugins of resolveMatchedPlugins(classCandidate, context)) {
let pluginHelpers = {
candidate: classCandidate,
theme: context.tailwindConfig.theme,
}
let matches = []
let [plugins, modifier] = matchedPlugins
for (let [sort, plugin] of plugins) {
if (typeof plugin === 'function') {
for (let ruleSet of [].concat(plugin(modifier, pluginHelpers))) {
for (let ruleSet of [].concat(plugin(modifier))) {
let [rules, options] = parseRules(ruleSet, context.postCssNodeCache)
for (let rule of rules) {
matches.push([{ ...sort, options: { ...sort.options, ...options } }, rule])

View File

@ -22,6 +22,9 @@ import corePlugins from '../corePlugins'
import isPlainObject from '../../util/isPlainObject'
import escapeClassName from '../../util/escapeClassName'
import nameClass from '../../util/nameClass'
import { coerceValue } from '../../util/pluginUtils'
import * as sharedState from './sharedState'
let contextMap = sharedState.contextMap
@ -513,36 +516,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
.push([{ sort: offset, layer: 'utilities', options }, rule])
}
},
matchBase: function (base) {
let offset = offsets.base++
for (let identifier in base) {
let prefixedIdentifier = prefixIdentifier(identifier, options)
let rule = base[identifier]
let withOffsets = [{ sort: offset, layer: 'base' }, rule]
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
context.candidateRuleMap.set(prefixedIdentifier, [])
}
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
}
},
matchUtilities: function (utilities, options) {
// TODO: Redesign this API to work like this so it's more end-user friendly
// matchUtilities({
// animate: (value, { includeRules }) => {
// let { name: animationName } = parseAnimationValue(value)
// if (keyframes[animationName] !== undefined) {
// includeRules(keyframes[animationName])
// }
// return { animation: value }
// },
// }, { values: [...], variants: [lol], ...otherStuff })
let defaultOptions = {
variants: [],
respectPrefix: true,
@ -558,7 +532,32 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
let prefixedIdentifier = prefixIdentifier(identifier, options)
let rule = utilities[identifier]
let withOffsets = [{ sort: offset, layer: 'utilities', options }, rule]
function wrapped(modifier) {
let { type = 'any' } = options
let value = coerceValue(type, modifier, options.values)
if (value === undefined) {
return []
}
let includedRules = []
let ruleSets = []
.concat(
rule(value, {
includeRules(rules) {
includedRules.push(...rules)
},
})
)
.filter(Boolean)
.map((declaration) => ({
[nameClass(identifier, modifier)]: declaration,
}))
return [...includedRules, ...ruleSets]
}
let withOffsets = [{ sort: offset, layer: 'utilities', options }, wrapped]
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
context.candidateRuleMap.set(prefixedIdentifier, [])
@ -567,16 +566,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
}
},
// ---
jit: {
e: escapeClassName,
config: tailwindConfig,
theme: tailwindConfig.theme,
addVariant(variantName, applyVariant, options = {}) {
insertInto(variantList, variantName, options)
variantMap.set(variantName, applyVariant)
},
},
}
}

View File

@ -1,60 +1,41 @@
import _ from 'lodash'
import parseAnimationValue from '../util/parseAnimationValue'
import nameClass from '../util/nameClass'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants, prefix }) {
if (config('mode') === 'jit') {
let keyframes = Object.fromEntries(
Object.entries(theme('keyframes')).map(([key, value]) => {
return [
key,
[
{
[`@keyframes ${key}`]: value,
},
{ respectVariants: false },
],
]
})
)
matchUtilities({
animate: (modifier, { theme }) => {
let value = theme.animation[modifier]
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants, prefix }) {
let prefixName = (name) => prefix(`.${name}`).slice(1)
let keyframes = Object.fromEntries(
Object.entries(theme('keyframes')).map(([key, value]) => {
return [
key,
[
{
[`@keyframes ${prefixName(key)}`]: value,
},
{ respectVariants: false },
],
]
})
)
matchUtilities(
{
animate: (value, { includeRules }) => {
let { name: animationName } = parseAnimationValue(value)
return [
keyframes[animationName],
{ [nameClass('animate', modifier)]: { animation: value } },
].filter(Boolean)
if (keyframes[animationName] !== undefined) {
includeRules(keyframes[animationName], { respectImportant: false })
}
if (animationName === undefined || keyframes[animationName] === undefined) {
return { animation: value }
}
return {
animation: value.replace(animationName, prefixName(animationName)),
}
},
})
} else {
const prefixName = (name) => prefix(`.${name}`).slice(1)
const keyframesConfig = theme('keyframes')
const keyframesStyles = _.mapKeys(
keyframesConfig,
(_keyframes, name) => `@keyframes ${prefixName(name)}`
)
addUtilities(keyframesStyles, { respectImportant: false })
const animationConfig = theme('animation')
const utilities = _.mapValues(
_.mapKeys(animationConfig, (_animation, suffix) => nameClass('animate', suffix)),
(animation) => {
const { name } = parseAnimationValue(animation)
if (name === undefined || keyframesConfig[name] === undefined) return { animation }
return { animation: animation.replace(name, prefixName(name)) }
}
)
addUtilities(utilities, variants('animation'))
}
},
{ values: theme('animation'), variants: variants('animation') }
)
}
}

View File

@ -1,38 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-blur': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropBlur)
if (value === undefined) {
return []
}
return {
[nameClass('backdrop-blur', modifier)]: { '--tw-backdrop-blur': `blur(${value})` },
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-blur': (value) => {
return { '--tw-backdrop-blur': `blur(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropBlur'), (value, modifier) => {
return [
nameClass('backdrop-blur', modifier),
{
'--tw-backdrop-blur': Array.isArray(value)
? value.map((v) => `blur(${v})`).join(' ')
: `blur(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdopBlur'))
}
},
{
values: theme('backdropBlur'),
variants: variants('backdropBlur'),
type: 'any',
}
)
}
}

View File

@ -1,40 +1,18 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-brightness': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropBrightness)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-brightness': (value) => {
return {
[nameClass('backdrop-brightness', modifier)]: {
'--tw-backdrop-brightness': `brightness(${value})`,
},
'--tw-backdrop-brightness': `brightness(${value})`,
}
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropBrightness'), (value, modifier) => {
return [
nameClass('backdrop-brightness', modifier),
{
'--tw-backdrop-brightness': Array.isArray(value)
? value.map((v) => `brightness(${v})`).join(' ')
: `brightness(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdropBrightness'))
}
},
{
values: theme('backdropBrightness'),
variants: variants('backdropBrightness'),
type: 'any',
}
)
}
}

View File

@ -1,40 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-contrast': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropContrast)
if (value === undefined) {
return []
}
return {
[nameClass('backdrop-contrast', modifier)]: {
'--tw-backdrop-contrast': `contrast(${value})`,
},
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-contrast': (value) => {
return { '--tw-backdrop-contrast': `contrast(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropContrast'), (value, modifier) => {
return [
nameClass('backdrop-contrast', modifier),
{
'--tw-backdrop-contrast': Array.isArray(value)
? value.map((v) => `contrast(${v})`).join(' ')
: `contrast(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdropContrast'))
}
},
{
values: theme('backdropContrast'),
variants: variants('backdropContrast'),
type: 'any',
}
)
}
}

View File

@ -1,40 +1,18 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-grayscale': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropGrayscale)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-grayscale': (value) => {
return {
[nameClass('backdrop-grayscale', modifier)]: {
'--tw-backdrop-grayscale': `grayscale(${value})`,
},
'--tw-backdrop-grayscale': `grayscale(${value})`,
}
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropGrayscale'), (value, modifier) => {
return [
nameClass('backdrop-grayscale', modifier),
{
'--tw-backdrop-grayscale': Array.isArray(value)
? value.map((v) => `grayscale(${v})`).join(' ')
: `grayscale(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdropGrayscale'))
}
},
{
values: theme('backdropGrayscale'),
variants: variants('backdropGrayscale'),
type: 'any',
}
)
}
}

View File

@ -1,40 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-hue-rotate': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropHueRotate)
if (value === undefined) {
return []
}
return {
[nameClass('backdrop-hue-rotate', modifier)]: {
'--tw-backdrop-hue-rotate': `hue-rotate(${value})`,
},
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-hue-rotate': (value) => {
return { '--tw-backdrop-hue-rotate': `hue-rotate(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropHueRotate'), (value, modifier) => {
return [
nameClass('backdrop-hue-rotate', modifier),
{
'--tw-backdrop-hue-rotate': Array.isArray(value)
? value.map((v) => `hue-rotate(${v})`).join(' ')
: `hue-rotate(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdropHueRotate'))
}
},
{
values: theme('backdropHueRotate'),
variants: variants('backdropHueRotate'),
type: 'any',
}
)
}
}

View File

@ -1,40 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-invert': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropInvert)
if (value === undefined) {
return []
}
return {
[nameClass('backdrop-invert', modifier)]: {
'--tw-backdrop-invert': `invert(${value})`,
},
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-invert': (value) => {
return { '--tw-backdrop-invert': `invert(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropInvert'), (value, modifier) => {
return [
nameClass('backdrop-invert', modifier),
{
'--tw-backdrop-invert': Array.isArray(value)
? value.map((v) => `invert(${v})`).join(' ')
: `invert(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdropInvert'))
}
},
{
values: theme('backdropInvert'),
variants: variants('backdropInvert'),
type: 'any',
}
)
}
}

View File

@ -1,40 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-opacity': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropOpacity)
if (value === undefined) {
return []
}
return {
[nameClass('backdrop-opacity', modifier)]: {
'--tw-backdrop-opacity': `opacity(${value})`,
},
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-opacity': (value) => {
return { '--tw-backdrop-opacity': `opacity(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropOpacity'), (value, modifier) => {
return [
nameClass('backdrop-opacity', modifier),
{
'--tw-backdrop-opacity': Array.isArray(value)
? value.map((v) => `opacity(${v})`).join(' ')
: `opacity(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdropOpacity'))
}
},
{
values: theme('backdropOpacity'),
variants: variants('backdropOpacity'),
type: 'any',
}
)
}
}

View File

@ -1,40 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-saturate': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropSaturate)
if (value === undefined) {
return []
}
return {
[nameClass('backdrop-saturate', modifier)]: {
'--tw-backdrop-saturate': `saturate(${value})`,
},
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-saturate': (value) => {
return { '--tw-backdrop-saturate': `saturate(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropSaturate'), (value, modifier) => {
return [
nameClass('backdrop-saturate', modifier),
{
'--tw-backdrop-saturate': Array.isArray(value)
? value.map((v) => `saturate(${v})`).join(' ')
: `saturate(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdropSaturate'))
}
},
{
values: theme('backdropSaturate'),
variants: variants('backdropSaturate'),
type: 'any',
}
)
}
}

View File

@ -1,40 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'backdrop-sepia': (modifier, { theme }) => {
let value = asValue(modifier, theme.backdropSepia)
if (value === undefined) {
return []
}
return {
[nameClass('backdrop-sepia', modifier)]: {
'--tw-backdrop-sepia': `sepia(${value})`,
},
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'backdrop-sepia': (value) => {
return { '--tw-backdrop-sepia': `sepia(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('backdropSepia'), (value, modifier) => {
return [
nameClass('backdrop-sepia', modifier),
{
'--tw-backdrop-sepia': Array.isArray(value)
? value.map((v) => `sepia(${v})`).join(' ')
: `sepia(${value})`,
},
]
})
)
addUtilities(utilities, variants('backdropSepia'))
}
},
{
values: theme('backdropSepia'),
variants: variants('backdropSepia'),
type: 'any',
}
)
}
}

View File

@ -1,62 +1,29 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import withAlphaVariable from '../util/withAlphaVariable'
import toColorValue from '../util/toColorValue'
import nameClass from '../util/nameClass'
import { asColor } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants, corePlugins }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('backgroundColor'))
matchUtilities({
bg: (modifier) => {
let value = asColor(modifier, colorPalette)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants, corePlugins }) {
matchUtilities(
{
bg: (value) => {
if (!corePlugins('backgroundOpacity')) {
return {
[nameClass('bg', modifier)]: {
'background-color': value,
},
'background-color': value,
}
}
return {
[nameClass('bg', modifier)]: withAlphaVariable({
color: value,
property: 'background-color',
variable: '--tw-bg-opacity',
}),
}
},
})
} else {
const colors = flattenColorPalette(theme('backgroundColor'))
const getProperties = (value) => {
if (corePlugins('backgroundOpacity')) {
return withAlphaVariable({
color: value,
property: 'background-color',
variable: '--tw-bg-opacity',
})
}
return { 'background-color': toColorValue(value) }
},
},
{
values: flattenColorPalette(theme('backgroundColor')),
variants: variants('backgroundColor'),
type: 'color',
}
const utilities = _.fromPairs(
_.map(colors, (value, modifier) => {
return [nameClass('bg', modifier), getProperties(value)]
})
)
addUtilities(utilities, variants('backgroundColor'))
}
)
}
}

View File

@ -1,36 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
blur: (modifier, { theme }) => {
let value = asValue(modifier, theme.blur)
if (value === undefined) {
return []
}
return { [nameClass('blur', modifier)]: { '--tw-blur': `blur(${value})` } }
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
blur: (value) => {
return { '--tw-blur': `blur(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('blur'), (value, modifier) => {
return [
nameClass('blur', modifier),
{
'--tw-blur': Array.isArray(value)
? value.map((v) => `blur(${v})`).join(' ')
: `blur(${value})`,
},
]
})
)
addUtilities(utilities, variants('blur'))
}
},
{
values: theme('blur'),
variants: variants('blur'),
type: 'any',
}
)
}
}

View File

@ -1,66 +1,29 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import toColorValue from '../util/toColorValue'
import withAlphaVariable from '../util/withAlphaVariable'
import nameClass from '../util/nameClass'
import { asColor } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants, corePlugins }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('borderColor'))
matchUtilities({
border: (modifier) => {
if (modifier === 'DEFAULT') {
return []
}
let value = asColor(modifier, colorPalette)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants, corePlugins }) {
matchUtilities(
{
border: (value) => {
if (!corePlugins('borderOpacity')) {
return {
[nameClass('border', modifier)]: {
'border-color': value,
},
'border-color': value,
}
}
return {
[nameClass('border', modifier)]: withAlphaVariable({
color: value,
property: 'border-color',
variable: '--tw-border-opacity',
}),
}
},
})
} else {
const colors = flattenColorPalette(theme('borderColor'))
const getProperties = (value) => {
if (corePlugins('borderOpacity')) {
return withAlphaVariable({
color: value,
property: 'border-color',
variable: '--tw-border-opacity',
})
}
return { 'border-color': toColorValue(value) }
},
},
{
values: (({ DEFAULT: _, ...colors }) => colors)(flattenColorPalette(theme('borderColor'))),
variants: variants('borderColor'),
type: 'color',
}
const utilities = _.fromPairs(
_.map(_.omit(colors, 'DEFAULT'), (value, modifier) => {
return [nameClass('border', modifier), getProperties(value)]
})
)
addUtilities(utilities, variants('borderColor'))
}
)
}
}

View File

@ -1,6 +1,4 @@
import _ from 'lodash'
import transformThemeValue from '../util/transformThemeValue'
import nameClass from '../util/nameClass'
let transformValue = transformThemeValue('boxShadow')
let shadowReset = {
@ -8,60 +6,36 @@ let shadowReset = {
'--tw-shadow': '0 0 #0000',
},
}
let defaultBoxShadow = [
`var(--tw-ring-offset-shadow, 0 0 #0000)`,
`var(--tw-ring-shadow, 0 0 #0000)`,
`var(--tw-shadow)`,
].join(', ')
export default function () {
return function ({ config, matchUtilities, addBase, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
addBase(shadowReset)
matchUtilities({
shadow: (modifier, { theme }) => {
let value = transformValue(theme.boxShadow[modifier])
if (value === undefined) {
return []
}
return [
{
[nameClass('shadow', modifier)]: {
'--tw-shadow': value === 'none' ? '0 0 #0000' : value,
'box-shadow': [
`var(--tw-ring-offset-shadow, 0 0 #0000)`,
`var(--tw-ring-shadow, 0 0 #0000)`,
`var(--tw-shadow)`,
].join(', '),
},
},
]
},
})
} else {
addUtilities(
{
'*': {
'--tw-shadow': '0 0 #0000',
},
},
{ respectImportant: false }
)
const utilities = _.fromPairs(
_.map(theme('boxShadow'), (value, modifier) => {
return [
nameClass('shadow', modifier),
{
'--tw-shadow': value === 'none' ? '0 0 #0000' : value,
'box-shadow': [
`var(--tw-ring-offset-shadow, 0 0 #0000)`,
`var(--tw-ring-shadow, 0 0 #0000)`,
`var(--tw-shadow)`,
].join(', '),
},
]
})
)
addUtilities(utilities, variants('boxShadow'))
addUtilities(shadowReset, { respectImportant: false })
}
matchUtilities(
{
shadow: (value) => {
value = transformValue(value)
return {
'--tw-shadow': value === 'none' ? '0 0 #0000' : value,
'box-shadow': defaultBoxShadow,
}
},
},
{
values: theme('boxShadow'),
variants: variants('boxShadow'),
type: 'lookup',
}
)
}
}

View File

@ -1,38 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
brightness: (modifier, { theme }) => {
let value = asValue(modifier, theme.brightness)
if (value === undefined) {
return []
}
return {
[nameClass('brightness', modifier)]: { '--tw-brightness': `brightness(${value})` },
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
brightness: (value) => {
return { '--tw-brightness': `brightness(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('brightness'), (value, modifier) => {
return [
nameClass('brightness', modifier),
{
'--tw-brightness': Array.isArray(value)
? value.map((v) => `brightness(${v})`).join(' ')
: `brightness(${value})`,
},
]
})
)
addUtilities(utilities, variants('brightness'))
}
},
{
values: theme('brightness'),
variants: variants('brightness'),
type: 'any',
}
)
}
}

View File

@ -1,38 +1,12 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
contrast: (modifier, { theme }) => {
let value = asValue(modifier, theme.contrast)
if (value === undefined) {
return []
}
return {
[nameClass('contrast', modifier)]: { '--tw-contrast': `contrast(${value})` },
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
contrast: (value) => {
return { '--tw-contrast': `contrast(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('contrast'), (value, modifier) => {
return [
nameClass('contrast', modifier),
{
'--tw-contrast': Array.isArray(value)
? value.map((v) => `contrast(${v})`).join(' ')
: `contrast(${value})`,
},
]
})
)
addUtilities(utilities, variants('contrast'))
}
},
{ values: theme('contrast'), variants: variants('contrast'), type: 'any' }
)
}
}

View File

@ -1,72 +1,33 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import toColorValue from '../util/toColorValue'
import withAlphaVariable from '../util/withAlphaVariable'
import nameClass from '../util/nameClass'
import { asColor } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants, corePlugins }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('divideColor'))
matchUtilities({
divide: (modifier) => {
if (modifier === 'DEFAULT') {
return []
}
let value = asColor(modifier, colorPalette)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants, corePlugins }) {
matchUtilities(
{
divide: (value) => {
if (!corePlugins('divideOpacity')) {
return {
[`${nameClass('divide', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
['& > :not([hidden]) ~ :not([hidden])']: {
'border-color': value,
},
}
}
return {
[`${nameClass(
'divide',
modifier
)} > :not([hidden]) ~ :not([hidden])`]: withAlphaVariable({
color: colorPalette[modifier],
['& > :not([hidden]) ~ :not([hidden])']: withAlphaVariable({
color: value,
property: 'border-color',
variable: '--tw-divide-opacity',
}),
}
},
})
} else {
const colors = flattenColorPalette(theme('divideColor'))
const getProperties = (value) => {
if (corePlugins('divideOpacity')) {
return withAlphaVariable({
color: value,
property: 'border-color',
variable: '--tw-divide-opacity',
})
}
return { 'border-color': toColorValue(value) }
},
{
values: (({ DEFAULT: _, ...colors }) => colors)(flattenColorPalette(theme('divideColor'))),
variants: variants('divideColor'),
type: 'color',
}
const utilities = _.fromPairs(
_.map(_.omit(colors, 'DEFAULT'), (value, modifier) => {
return [
`${nameClass('divide', modifier)} > :not([hidden]) ~ :not([hidden])`,
getProperties(value),
]
})
)
addUtilities(utilities, variants('divideColor'))
}
)
}
}

View File

@ -1,38 +1,20 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'divide-opacity': (modifier, { theme }) => {
let value = asValue(modifier, theme.divideOpacity)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'divide-opacity': (value) => {
return {
[`${nameClass('divide-opacity', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
[`& > :not([hidden]) ~ :not([hidden])`]: {
'--tw-divide-opacity': value,
},
}
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('divideOpacity'), (value, modifier) => {
return [
`${nameClass('divide-opacity', modifier)} > :not([hidden]) ~ :not([hidden])`,
{
'--tw-divide-opacity': value,
},
]
})
)
addUtilities(utilities, variants('divideOpacity'))
}
},
{
values: theme('divideOpacity'),
variants: variants('divideOpacity'),
type: 'any',
}
)
}
}

View File

@ -1,91 +1,47 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asLength } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'divide-x': (modifier, { theme }) => {
let value = asLength(modifier, theme['divideWidth'])
if (value === undefined) {
return []
}
return function ({ matchUtilities, addUtilities, theme, variants }) {
matchUtilities(
{
'divide-x': (value) => {
value = value === '0' ? '0px' : value
return {
[`${nameClass('divide-x', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
'& > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-x-reverse': '0',
'border-right-width': `calc(${value} * var(--tw-divide-x-reverse))`,
'border-left-width': `calc(${value} * calc(1 - var(--tw-divide-x-reverse)))`,
},
}
},
'divide-y': (modifier, { theme }) => {
let value = asLength(modifier, theme['divideWidth'])
if (value === undefined) {
return []
}
'divide-y': (value) => {
value = value === '0' ? '0px' : value
return {
[`${nameClass('divide-y', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
'& > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-y-reverse': '0',
'border-top-width': `calc(${value} * calc(1 - var(--tw-divide-y-reverse)))`,
'border-bottom-width': `calc(${value} * var(--tw-divide-y-reverse))`,
},
}
},
})
},
{
values: theme('divideWidth'),
variants: variants('divideWidth'),
type: 'length',
}
)
addUtilities({
addUtilities(
{
'.divide-y-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-y-reverse': '1',
},
'.divide-x-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-x-reverse': '1',
},
})
} else {
const generators = [
(_size, modifier) => {
const size = _size === '0' ? '0px' : _size
return {
[`${nameClass('divide-y', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
'--tw-divide-y-reverse': '0',
'border-top-width': `calc(${size} * calc(1 - var(--tw-divide-y-reverse)))`,
'border-bottom-width': `calc(${size} * var(--tw-divide-y-reverse))`,
},
[`${nameClass('divide-x', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
'--tw-divide-x-reverse': '0',
'border-right-width': `calc(${size} * var(--tw-divide-x-reverse))`,
'border-left-width': `calc(${size} * calc(1 - var(--tw-divide-x-reverse)))`,
},
}
},
]
const utilities = _.flatMap(generators, (generator) => {
return [
..._.flatMap(theme('divideWidth'), (value, modifier) => {
return generator(value, modifier)
}),
{
'.divide-y-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-y-reverse': '1',
},
'.divide-x-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-x-reverse': '1',
},
},
]
})
addUtilities(utilities, variants('divideWidth'))
}
},
variants('divideWidth')
)
}
}

View File

@ -1,35 +1,19 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import toColorValue from '../util/toColorValue'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('fill'))
matchUtilities({
fill: (modifier) => {
let value = asValue(modifier, colorPalette)
if (value === undefined) {
return []
}
return { [nameClass('fill', modifier)]: { fill: toColorValue(value) } }
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
fill: (value) => {
return { fill: toColorValue(value) }
},
})
} else {
const colors = flattenColorPalette(theme('fill'))
const utilities = _.fromPairs(
_.map(colors, (value, modifier) => {
return [nameClass('fill', modifier), { fill: toColorValue(value) }]
})
)
addUtilities(utilities, variants('fill'))
}
},
{
values: flattenColorPalette(theme('fill')),
variants: variants('fill'),
type: 'any',
}
)
}
}

View File

@ -1,81 +1,27 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asLength } from '../util/pluginUtils'
import isPlainObject from '../util/isPlainObject'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
text: (modifier, { theme }) => {
let value = theme.fontSize[modifier]
if (value === undefined) {
value = asLength(modifier, {})
return value === undefined
? []
: {
[nameClass('text', modifier)]: {
'font-size': value,
},
}
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
text: (value) => {
let [fontSize, options] = Array.isArray(value) ? value : [value]
let { lineHeight, letterSpacing } = isPlainObject(options)
? options
: {
lineHeight: options,
}
: { lineHeight: options }
return {
[nameClass('text', modifier)]: {
'font-size': fontSize,
...(lineHeight === undefined
? {}
: {
'line-height': lineHeight,
}),
...(letterSpacing === undefined
? {}
: {
'letter-spacing': letterSpacing,
}),
},
'font-size': fontSize,
...(lineHeight === undefined ? {} : { 'line-height': lineHeight }),
...(letterSpacing === undefined ? {} : { 'letter-spacing': letterSpacing }),
}
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('fontSize'), (value, modifier) => {
const [fontSize, options] = Array.isArray(value) ? value : [value]
const { lineHeight, letterSpacing } = _.isPlainObject(options)
? options
: {
lineHeight: options,
}
return [
nameClass('text', modifier),
{
'font-size': fontSize,
...(lineHeight === undefined
? {}
: {
'line-height': lineHeight,
}),
...(letterSpacing === undefined
? {}
: {
'letter-spacing': letterSpacing,
}),
},
]
})
)
addUtilities(utilities, variants('fontSize'))
}
},
{
values: theme('fontSize'),
variants: variants('fontSize'),
type: 'length',
}
)
}
}

View File

@ -1,110 +1,54 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import toColorValue from '../util/toColorValue'
import { withAlphaValue } from '../util/withAlphaVariable'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
function transparentTo(value) {
return withAlphaValue(value, 0, 'rgba(255, 255, 255, 0)')
}
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
let colorPalette = flattenColorPalette(theme('gradientColorStops'))
if (config('mode') === 'jit') {
matchUtilities({
from: (modifier) => {
let value = asValue(modifier, colorPalette)
if (value === undefined) {
return []
}
let transparentToValue = transparentTo(value)
return {
[nameClass('from', modifier)]: {
'--tw-gradient-from': toColorValue(value, 'from'),
'--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to, ${transparentToValue})`,
},
}
},
})
matchUtilities({
via: (modifier) => {
let value = asValue(modifier, colorPalette)
if (value === undefined) {
return []
}
let transparentToValue = transparentTo(value)
return {
[nameClass('via', modifier)]: {
'--tw-gradient-stops': `var(--tw-gradient-from), ${toColorValue(
value,
'via'
)}, var(--tw-gradient-to, ${transparentToValue})`,
},
}
},
})
matchUtilities({
to: (modifier) => {
let value = asValue(modifier, colorPalette)
if (value === undefined) {
return []
}
return {
[nameClass('to', modifier)]: {
'--tw-gradient-to': toColorValue(value, 'to'),
},
}
},
})
} else {
const colors = colorPalette
const utilities = _(colors)
.map((value, modifier) => {
const transparentToValue = transparentTo(value)
return [
[
nameClass('from', modifier),
{
'--tw-gradient-from': toColorValue(value, 'from'),
'--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to, ${transparentToValue})`,
},
],
[
nameClass('via', modifier),
{
'--tw-gradient-stops': `var(--tw-gradient-from), ${toColorValue(
value,
'via'
)}, var(--tw-gradient-to, ${transparentToValue})`,
},
],
[
nameClass('to', modifier),
{
'--tw-gradient-to': toColorValue(value, 'to'),
},
],
]
})
.unzip()
.flatten()
.fromPairs()
.value()
addUtilities(utilities, variants('gradientColorStops'))
return function ({ matchUtilities, theme, variants }) {
let options = {
values: flattenColorPalette(theme('gradientColorStops')),
variants: variants('gradientColorStops'),
type: 'any',
}
matchUtilities(
{
from: (value) => {
let transparentToValue = transparentTo(value)
return {
'--tw-gradient-from': toColorValue(value, 'from'),
'--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to, ${transparentToValue})`,
}
},
},
options
)
matchUtilities(
{
via: (value) => {
let transparentToValue = transparentTo(value)
return {
'--tw-gradient-stops': `var(--tw-gradient-from), ${toColorValue(
value,
'via'
)}, var(--tw-gradient-to, ${transparentToValue})`,
}
},
},
options
)
matchUtilities(
{
to: (value) => {
return { '--tw-gradient-to': toColorValue(value, 'to') }
},
},
options
)
}
}

View File

@ -1,38 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
grayscale: (modifier, { theme }) => {
let value = asValue(modifier, theme.grayscale)
if (value === undefined) {
return []
}
return {
[nameClass('grayscale', modifier)]: { '--tw-grayscale': `grayscale(${value})` },
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
grayscale: (value) => {
return { '--tw-grayscale': `grayscale(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('grayscale'), (value, modifier) => {
return [
nameClass('grayscale', modifier),
{
'--tw-grayscale': Array.isArray(value)
? value.map((v) => `grayscale(${v})`).join(' ')
: `grayscale(${value})`,
},
]
})
)
addUtilities(utilities, variants('grayscale'))
}
},
{
values: theme('grayscale'),
variants: variants('grayscale'),
type: 'any',
}
)
}
}

View File

@ -1,38 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'hue-rotate': (modifier, { theme }) => {
let value = asValue(modifier, theme.hueRotate)
if (value === undefined) {
return []
}
return {
[nameClass('hue-rotate', modifier)]: { '--tw-hue-rotate': `hue-rotate(${value})` },
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'hue-rotate': (value) => {
return { '--tw-hue-rotate': `hue-rotate(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('hueRotate'), (value, modifier) => {
return [
nameClass('hue-rotate', modifier),
{
'--tw-hue-rotate': Array.isArray(value)
? value.map((v) => `hue-rotate(${v})`).join(' ')
: `hue-rotate(${value})`,
},
]
})
)
addUtilities(utilities, variants('hueRotate'))
}
},
{
values: theme('hueRotate'),
variants: variants('hueRotate'),
type: 'any',
}
)
}
}

View File

@ -1,123 +1,48 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
inset: (modifier, { theme }) => {
let value = asValue(modifier, theme['inset'])
if (value === undefined) {
return []
}
return {
[nameClass('inset', modifier)]: {
top: value,
right: value,
bottom: value,
left: value,
},
}
},
})
matchUtilities({
'inset-x': (modifier, { theme }) => {
let value = asValue(modifier, theme['inset'])
if (value === undefined) {
return []
}
return {
[nameClass('inset-x', modifier)]: { left: value, right: value },
}
},
'inset-y': (modifier, { theme }) => {
let value = asValue(modifier, theme['inset'])
if (value === undefined) {
return []
}
return {
[nameClass('inset-y', modifier)]: { top: value, bottom: value },
}
},
})
matchUtilities({
top: (modifier, { theme }) => {
let value = asValue(modifier, theme['inset'])
if (value === undefined) {
return []
}
return { [nameClass('top', modifier)]: { top: value } }
},
right: (modifier, { theme }) => {
let value = asValue(modifier, theme['inset'])
if (value === undefined) {
return []
}
return { [nameClass('right', modifier)]: { right: value } }
},
bottom: (modifier, { theme }) => {
let value = asValue(modifier, theme['inset'])
if (value === undefined) {
return []
}
return { [nameClass('bottom', modifier)]: { bottom: value } }
},
left: (modifier, { theme }) => {
let value = asValue(modifier, theme['inset'])
if (value === undefined) {
return []
}
return { [nameClass('left', modifier)]: { left: value } }
},
})
} else {
const generators = [
(size, modifier) => ({
[nameClass('inset', modifier)]: {
top: `${size}`,
right: `${size}`,
bottom: `${size}`,
left: `${size}`,
},
}),
(size, modifier) => ({
[nameClass('inset-y', modifier)]: {
top: `${size}`,
bottom: `${size}`,
},
[nameClass('inset-x', modifier)]: {
right: `${size}`,
left: `${size}`,
},
}),
(size, modifier) => ({
[nameClass('top', modifier)]: { top: `${size}` },
[nameClass('right', modifier)]: { right: `${size}` },
[nameClass('bottom', modifier)]: { bottom: `${size}` },
[nameClass('left', modifier)]: { left: `${size}` },
}),
]
const utilities = _.flatMap(generators, (generator) => {
return _.flatMap(theme('inset'), generator)
})
addUtilities(utilities, variants('inset'))
return function ({ matchUtilities, theme, variants }) {
let options = {
values: theme('inset'),
variants: variants('inset'),
type: 'any',
}
matchUtilities(
{
inset: (value) => {
return { top: value, right: value, bottom: value, left: value }
},
},
options
)
matchUtilities(
{
'inset-x': (value) => {
return { left: value, right: value }
},
'inset-y': (value) => {
return { top: value, bottom: value }
},
},
options
)
matchUtilities(
{
top: (value) => {
return { top: value }
},
right: (value) => {
return { right: value }
},
bottom: (value) => {
return { bottom: value }
},
left: (value) => {
return { left: value }
},
},
options
)
}
}

View File

@ -1,38 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
invert: (modifier, { theme }) => {
let value = asValue(modifier, theme.invert)
if (value === undefined) {
return []
}
return {
[nameClass('invert', modifier)]: { '--tw-invert': `invert(${value})` },
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
invert: (value) => {
return { '--tw-invert': `invert(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('invert'), (value, modifier) => {
return [
nameClass('invert', modifier),
{
'--tw-invert': Array.isArray(value)
? value.map((v) => `invert(${v})`).join(' ')
: `invert(${value})`,
},
]
})
)
addUtilities(utilities, variants('invert'))
}
},
{
values: theme('invert'),
variants: variants('invert'),
type: 'any',
}
)
}
}

View File

@ -1,44 +1,14 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
outline: (modifier, { theme }) => {
let value = asValue(modifier, theme.outline)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
outline: (value) => {
let [outline, outlineOffset = '0'] = Array.isArray(value) ? value : [value]
return {
[nameClass('outline', modifier)]: {
outline,
'outline-offset': outlineOffset,
},
}
return { outline, 'outline-offset': outlineOffset }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('outline'), (value, modifier) => {
const [outline, outlineOffset = '0'] = Array.isArray(value) ? value : [value]
return [
nameClass('outline', modifier),
{
outline,
outlineOffset,
},
]
})
)
addUtilities(utilities, variants('outline'))
}
},
{ values: theme('outline'), variants: variants('outline'), type: 'any' }
)
}
}

View File

@ -1,62 +1,33 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import toColorValue from '../util/toColorValue'
import withAlphaVariable from '../util/withAlphaVariable'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants, corePlugins }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('placeholderColor'))
matchUtilities({
placeholder: (modifier) => {
let value = asValue(modifier, colorPalette)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants, corePlugins }) {
matchUtilities(
{
placeholder: (value) => {
if (!corePlugins('placeholderOpacity')) {
return {
[`${nameClass('placeholder', modifier)}::placeholder`]: {
'&::placeholder': {
color: value,
},
}
}
return {
[`${nameClass('placeholder', modifier)}::placeholder`]: withAlphaVariable({
'&::placeholder': withAlphaVariable({
color: value,
property: 'color',
variable: '--tw-placeholder-opacity',
}),
}
},
})
} else {
const colors = flattenColorPalette(theme('placeholderColor'))
const getProperties = (value) => {
if (corePlugins('placeholderOpacity')) {
return withAlphaVariable({
color: value,
property: 'color',
variable: '--tw-placeholder-opacity',
})
}
return { color: toColorValue(value) }
},
{
values: flattenColorPalette(theme('placeholderColor')),
variants: variants('placeholderColor'),
type: 'any',
}
const utilities = _.fromPairs(
_.map(colors, (value, modifier) => {
return [`${nameClass('placeholder', modifier)}::placeholder`, getProperties(value)]
})
)
addUtilities(utilities, variants('placeholderColor'))
}
)
}
}

View File

@ -1,38 +1,16 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'placeholder-opacity': (modifier, { theme }) => {
let value = asValue(modifier, theme.placeholderOpacity)
if (value === undefined) {
return []
}
return {
[`${nameClass('placeholder-opacity', modifier)}::placeholder`]: {
'--tw-placeholder-opacity': value,
},
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'placeholder-opacity': (value) => {
return { ['&::placeholder']: { '--tw-placeholder-opacity': value } }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('placeholderOpacity'), (value, modifier) => {
return [
`${nameClass('placeholder-opacity', modifier)}::placeholder`,
{
'--tw-placeholder-opacity': value,
},
]
})
)
addUtilities(utilities, variants('placeholderOpacity'))
}
},
{
values: theme('placeholderOpacity'),
variants: variants('placeholderOpacity'),
type: 'any',
}
)
}
}

View File

@ -1,53 +1,27 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import withAlphaVariable from '../util/withAlphaVariable'
import nameClass from '../util/nameClass'
import { asColor } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('ringColor'))
matchUtilities({
ring: (modifier) => {
if (modifier === 'DEFAULT') {
return []
}
let value = asColor(modifier, colorPalette)
if (value === undefined) {
return []
}
return {
[nameClass('ring', modifier)]: withAlphaVariable({
color: value,
property: '--tw-ring-color',
variable: '--tw-ring-opacity',
}),
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
ring: (value) => {
return withAlphaVariable({
color: value,
property: '--tw-ring-color',
variable: '--tw-ring-opacity',
})
},
})
} else {
const colors = flattenColorPalette(theme('ringColor'))
const getProperties = (value) => {
return withAlphaVariable({
color: value,
property: '--tw-ring-color',
variable: '--tw-ring-opacity',
})
},
{
values: Object.fromEntries(
Object.entries(flattenColorPalette(theme('ringColor'))).filter(
([modifier]) => modifier !== 'DEFAULT'
)
),
variants: variants('ringColor'),
type: 'color',
}
const utilities = _.fromPairs(
_.map(_.omit(colors, 'DEFAULT'), (value, modifier) => {
return [nameClass('ring', modifier), getProperties(value)]
})
)
addUtilities(utilities, variants('ringColor'))
}
)
}
}

View File

@ -1,42 +1,21 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import toColorValue from '../util/toColorValue'
import nameClass from '../util/nameClass'
import { asColor } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('ringOffsetColor'))
matchUtilities({
'ring-offset': (modifier) => {
let value = asColor(modifier, colorPalette)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'ring-offset': (value) => {
return {
[nameClass('ring-offset', modifier)]: {
'--tw-ring-offset-color': toColorValue(value),
},
'--tw-ring-offset-color': toColorValue(value),
}
},
})
} else {
const colors = flattenColorPalette(theme('ringOffsetColor'))
const utilities = _.fromPairs(
_.map(_.omit(colors, 'DEFAULT'), (value, modifier) => {
return [
nameClass('ring-offset', modifier),
{
'--tw-ring-offset-color': toColorValue(value),
},
]
})
)
addUtilities(utilities, variants('ringOffsetColor'))
}
},
{
values: flattenColorPalette(theme('ringOffsetColor')),
variants: variants('ringOffsetColor'),
type: 'color',
}
)
}
}

View File

@ -1,102 +1,52 @@
import _ from 'lodash'
import { withAlphaValue } from '../util/withAlphaVariable'
import nameClass from '../util/nameClass'
import { asLength } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addBase, addUtilities, theme, variants }) {
const ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
const ringColorDefault = withAlphaValue(
let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
let ringColorDefault = withAlphaValue(
theme('ringColor.DEFAULT'),
ringOpacityDefault,
`rgba(147, 197, 253, ${ringOpacityDefault})`
)
if (config('mode') === 'jit') {
let ringReset = {
'*': {
'--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',
},
}
addBase(ringReset)
matchUtilities({
ring: (modifier, { theme }) => {
let value = asLength(modifier, theme['ringWidth'])
if (value === undefined) {
return []
}
return [
{
[nameClass('ring', modifier)]: {
'--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)`,
'box-shadow': [
`var(--tw-ring-offset-shadow)`,
`var(--tw-ring-shadow)`,
`var(--tw-shadow, 0 0 #0000)`,
].join(', '),
},
},
]
},
})
addUtilities({
'.ring-inset': {
'--tw-ring-inset': 'inset',
},
})
} else {
addUtilities(
{
'*': {
'--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',
},
},
{ respectImportant: false }
)
const utilities = _.fromPairs(
_.map(theme('ringWidth'), (value, modifier) => {
return [
nameClass('ring', modifier),
{
'--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)`,
'box-shadow': [
`var(--tw-ring-offset-shadow)`,
`var(--tw-ring-shadow)`,
`var(--tw-shadow, 0 0 #0000)`,
].join(', '),
},
]
})
)
addUtilities(
[
utilities,
{
'.ring-inset': {
'--tw-ring-inset': 'inset',
},
},
],
variants('ringWidth')
)
let ringReset = {
'*': {
'--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',
},
}
if (config('mode') === 'jit') {
addBase(ringReset)
} else {
addUtilities(ringReset, { respectImportant: false })
}
matchUtilities(
{
ring: (value) => {
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)`,
'box-shadow': [
`var(--tw-ring-offset-shadow)`,
`var(--tw-ring-shadow)`,
`var(--tw-shadow, 0 0 #0000)`,
].join(', '),
}
},
},
{
values: theme('ringWidth'),
variants: variants('ringWidth'),
type: 'length',
}
)
addUtilities({ '.ring-inset': { '--tw-ring-inset': 'inset' } }, variants('ringWidth'))
}
}

View File

@ -1,38 +1,18 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
saturate: (modifier, { theme }) => {
let value = asValue(modifier, theme.saturate)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
saturate: (value) => {
return {
[nameClass('saturate', modifier)]: { '--tw-saturate': `saturate(${value})` },
'--tw-saturate': `saturate(${value})`,
}
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('saturate'), (value, modifier) => {
return [
nameClass('saturate', modifier),
{
'--tw-saturate': Array.isArray(value)
? value.map((v) => `saturate(${v})`).join(' ')
: `saturate(${value})`,
},
]
})
)
addUtilities(utilities, variants('saturate'))
}
},
{
values: theme('saturate'),
variants: variants('saturate'),
type: 'any',
}
)
}
}

View File

@ -1,38 +1,12 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
sepia: (modifier, { theme }) => {
let value = asValue(modifier, theme.sepia)
if (value === undefined) {
return []
}
return {
[nameClass('sepia', modifier)]: { '--tw-sepia': `sepia(${value})` },
}
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
sepia: (value) => {
return { '--tw-sepia': `sepia(${value})` }
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('sepia'), (value, modifier) => {
return [
nameClass('sepia', modifier),
{
'--tw-sepia': Array.isArray(value)
? value.map((v) => `sepia(${v})`).join(' ')
: `sepia(${value})`,
},
]
})
)
addUtilities(utilities, variants('sepia'))
}
},
{ values: theme('sepia'), variants: variants('sepia'), type: 'any' }
)
}
}

View File

@ -1,89 +1,47 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
matchUtilities({
'space-x': (modifier, { theme }) => {
let value = asValue(modifier, theme['space'])
if (value === undefined) {
return []
}
return function ({ matchUtilities, addUtilities, theme, variants }) {
matchUtilities(
{
'space-x': (value) => {
value = value === '0' ? '0px' : value
return {
[`${nameClass('space-x', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
'& > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '0',
'margin-right': `calc(${value} * var(--tw-space-x-reverse))`,
'margin-left': `calc(${value} * calc(1 - var(--tw-space-x-reverse)))`,
},
}
},
'space-y': (modifier, { theme }) => {
let value = asValue(modifier, theme['space'])
if (value === undefined) {
return []
}
'space-y': (value) => {
value = value === '0' ? '0px' : value
return {
[`${nameClass('space-y', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
'& > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '0',
'margin-top': `calc(${value} * calc(1 - var(--tw-space-y-reverse)))`,
'margin-bottom': `calc(${value} * var(--tw-space-y-reverse))`,
},
}
},
})
},
{
values: theme('space'),
variants: variants('space'),
type: 'any',
}
)
addUtilities({
addUtilities(
{
'.space-y-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '1',
},
'.space-x-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '1',
},
})
} else {
const generators = [
(_size, modifier) => {
const size = _size === '0' ? '0px' : _size
return {
[`${nameClass('space-y', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
'--tw-space-y-reverse': '0',
'margin-top': `calc(${size} * calc(1 - var(--tw-space-y-reverse)))`,
'margin-bottom': `calc(${size} * var(--tw-space-y-reverse))`,
},
[`${nameClass('space-x', modifier)} > :not([hidden]) ~ :not([hidden])`]: {
'--tw-space-x-reverse': '0',
'margin-right': `calc(${size} * var(--tw-space-x-reverse))`,
'margin-left': `calc(${size} * calc(1 - var(--tw-space-x-reverse)))`,
},
}
},
]
const utilities = _.flatMap(generators, (generator) => {
return [
..._.flatMap(theme('space'), generator),
{
'.space-y-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '1',
},
'.space-x-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '1',
},
},
]
})
addUtilities(utilities, variants('space'))
}
},
variants('space')
)
}
}

View File

@ -1,35 +1,21 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import toColorValue from '../util/toColorValue'
import nameClass from '../util/nameClass'
import { asColor } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('stroke'))
matchUtilities({
stroke: (modifier) => {
let value = asColor(modifier, colorPalette)
if (value === undefined) {
return []
return function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
stroke: (value) => {
return {
stroke: toColorValue(value),
}
return { [nameClass('stroke', modifier)]: { stroke: toColorValue(value) } }
},
})
} else {
const colors = flattenColorPalette(theme('stroke'))
const utilities = _.fromPairs(
_.map(colors, (value, modifier) => {
return [nameClass('stroke', modifier), { stroke: toColorValue(value) }]
})
)
addUtilities(utilities, variants('stroke'))
}
},
{
values: flattenColorPalette(theme('stroke')),
variants: variants('stroke'),
type: 'color',
}
)
}
}

View File

@ -1,62 +1,27 @@
import _ from 'lodash'
import flattenColorPalette from '../util/flattenColorPalette'
import toColorValue from '../util/toColorValue'
import withAlphaVariable from '../util/withAlphaVariable'
import nameClass from '../util/nameClass'
import { asColor } from '../util/pluginUtils'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants, corePlugins }) {
if (config('mode') === 'jit') {
let colorPalette = flattenColorPalette(theme('textColor'))
matchUtilities({
text: (modifier) => {
let value = asColor(modifier, colorPalette)
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants, corePlugins }) {
matchUtilities(
{
text: (value) => {
if (!corePlugins('textOpacity')) {
return {
[nameClass('text', modifier)]: {
color: value,
},
}
return { color: value }
}
return {
[nameClass('text', modifier)]: withAlphaVariable({
color: value,
property: 'color',
variable: '--tw-text-opacity',
}),
}
},
})
} else {
const colors = flattenColorPalette(theme('textColor'))
const getProperties = (value) => {
if (corePlugins('textOpacity')) {
return withAlphaVariable({
color: value,
property: 'color',
variable: '--tw-text-opacity',
})
}
return { color: toColorValue(value) }
},
},
{
values: flattenColorPalette(theme('textColor')),
variants: variants('textColor'),
type: 'color',
}
const utilities = _.fromPairs(
_.map(colors, (value, modifier) => {
return [nameClass('text', modifier), getProperties(value)]
})
)
addUtilities(utilities, variants('textColor'))
}
)
}
}

View File

@ -1,52 +1,27 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
export default function () {
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
const defaultTimingFunction = theme('transitionTimingFunction.DEFAULT')
const defaultDuration = theme('transitionDuration.DEFAULT')
if (config('mode') === 'jit') {
matchUtilities({
transition: (modifier, { theme }) => {
let value = theme.transitionProperty[modifier]
if (value === undefined) {
return []
}
return function ({ matchUtilities, theme, variants }) {
let defaultTimingFunction = theme('transitionTimingFunction.DEFAULT')
let defaultDuration = theme('transitionDuration.DEFAULT')
matchUtilities(
{
transition: (value) => {
return {
[nameClass('transition', modifier)]: {
'transition-property': value,
...(value === 'none'
? {}
: {
'transition-timing-function': defaultTimingFunction,
'transition-duration': defaultDuration,
}),
},
'transition-property': value,
...(value === 'none'
? {}
: {
'transition-timing-function': defaultTimingFunction,
'transition-duration': defaultDuration,
}),
}
},
})
} else {
const utilities = _.fromPairs(
_.map(theme('transitionProperty'), (value, modifier) => {
return [
nameClass('transition', modifier),
{
'transition-property': value,
...(value === 'none'
? {}
: {
'transition-timing-function': defaultTimingFunction,
'transition-duration': defaultDuration,
}),
},
]
})
)
addUtilities(utilities, variants('transitionProperty'))
}
},
{
values: theme('transitionProperty'),
variants: variants('transitionProperty'),
type: 'lookup',
}
)
}
}

View File

@ -1,65 +1,46 @@
import fromPairs from 'lodash/fromPairs'
import toPairs from 'lodash/toPairs'
import castArray from 'lodash/castArray'
import transformThemeValue from './transformThemeValue'
import nameClass from '../util/nameClass'
import { asValue } from '../util/pluginUtils'
import { asValue, asList, asColor, asAngle, asLength, asLookupValue } from '../util/pluginUtils'
let asMap = new Map([
[asValue, 'any'],
[asList, 'list'],
[asColor, 'color'],
[asAngle, 'angle'],
[asLength, 'length'],
[asLookupValue, 'lookup'],
])
export default function createUtilityPlugin(
themeKey,
utilityVariations = [[themeKey, [themeKey]]],
{ filterDefault = false, resolveArbitraryValue = asValue } = {}
) {
const transformValue = transformThemeValue(themeKey)
return function ({ config, matchUtilities, addUtilities, variants, theme }) {
if (config('mode') === 'jit') {
for (let utilityVariation of utilityVariations) {
let group = Array.isArray(utilityVariation[0]) ? utilityVariation : [utilityVariation]
let transformValue = transformThemeValue(themeKey)
return function ({ matchUtilities, variants, theme }) {
for (let utilityVariation of utilityVariations) {
let group = Array.isArray(utilityVariation[0]) ? utilityVariation : [utilityVariation]
matchUtilities(
group.reduce((obj, [classPrefix, properties]) => {
return Object.assign(obj, {
[classPrefix]: (modifier, { theme }) => {
let value = resolveArbitraryValue(modifier, theme[themeKey])
if (value === undefined) {
return []
}
return {
[nameClass(classPrefix, modifier)]: properties.reduce(
(obj, name) => Object.assign(obj, { [name]: transformValue(value) }),
{}
),
}
},
})
}, {})
)
}
} else {
const pairs = toPairs(theme(themeKey))
const utilities = utilityVariations.flatMap((utilityVariation) => {
let group = Array.isArray(utilityVariation[0]) ? utilityVariation : [utilityVariation]
return group.map(([classPrefix, properties]) => {
return fromPairs(
pairs
.filter(([key]) => {
return filterDefault ? key !== 'DEFAULT' : true
})
.map(([key, value]) => {
return [
nameClass(classPrefix, key),
fromPairs(
castArray(properties).map((property) => [property, transformValue(value)])
),
]
})
)
})
})
return addUtilities(utilities, variants(themeKey))
matchUtilities(
group.reduce((obj, [classPrefix, properties]) => {
return Object.assign(obj, {
[classPrefix]: (value) => {
return properties.reduce(
(obj, name) => Object.assign(obj, { [name]: transformValue(value) }),
{}
)
},
})
}, {}),
{
values: filterDefault
? Object.fromEntries(
Object.entries(theme(themeKey)).filter(([modifier]) => modifier !== 'DEFAULT')
)
: theme(themeKey),
variants: variants(themeKey),
type: asMap.get(resolveArbitraryValue) ?? 'any',
}
)
}
}
}

View File

@ -137,18 +137,6 @@ export function asUnit(modifier, units, lookup = {}) {
})
}
export function createSimpleStaticUtilityPlugin(styles) {
return function ({ matchUtilities }) {
matchUtilities(
Object.entries(styles).reduce((newStyles, [selector, rules]) => {
let result = { [selector]: rules }
newStyles[selector.slice(1)] = [result]
return newStyles
}, {})
)
}
}
export function asList(modifier, lookup = {}) {
return asValue(modifier, lookup, {
transform: (value) => {
@ -206,3 +194,16 @@ export function asLength(modifier, lookup = {}) {
export function asLookupValue(modifier, lookup = {}) {
return lookup[modifier]
}
let typeMap = {
any: asValue,
list: asList,
color: asColor,
angle: asAngle,
length: asLength,
lookup: asLookupValue,
}
export function coerceValue(type, modifier, values) {
return typeMap[type](modifier, values)
}

View File

@ -9,6 +9,7 @@ import prefixSelector from '../util/prefixSelector'
import wrapWithVariants from '../util/wrapWithVariants'
import cloneNodes from '../util/cloneNodes'
import transformThemeValue from './transformThemeValue'
import nameClass from '../util/nameClass'
function parseStyles(styles) {
if (!Array.isArray(styles)) {
@ -42,7 +43,11 @@ export default function (plugins, config) {
}
function addUtilities(utilities, options) {
const defaultOptions = { variants: [], respectPrefix: true, respectImportant: true }
const defaultOptions = {
variants: [],
respectPrefix: true,
respectImportant: true,
}
options = Array.isArray(options)
? Object.assign({}, defaultOptions, { variants: options })
@ -106,10 +111,24 @@ export default function (plugins, config) {
matchUtilities: (matches, { values, variants, respectPrefix, respectImportant }) => {
let modifierValues = Object.entries(values)
let result = Object.values(matches).flatMap((utilityFunction) => {
return modifierValues.map(([modifier, value]) => {
return utilityFunction(modifier, { value })
})
let result = Object.entries(matches).flatMap(([name, utilityFunction]) => {
return modifierValues
.map(([modifier, value]) => {
let declarations = utilityFunction(value, {
includeRules(rules, options) {
addUtilities(rules, options)
},
})
if (!declarations) {
return null
}
return {
[nameClass(name, modifier)]: declarations,
}
})
.filter(Boolean)
})
addUtilities(result, { variants, respectPrefix, respectImportant })

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -120,6 +120,15 @@
.max-w-\[var\(--width\)\] {
max-width: var(--width);
}
.flex-\[var\(--flex\)\] {
flex: var(--flex);
}
.flex-shrink-\[var\(--shrink\)\] {
flex-shrink: var(--shrink);
}
.flex-grow-\[var\(--grow\)\] {
flex-grow: var(--grow);
}
.rotate-\[23deg\] {
--tw-rotate: 23deg;
}

View File

@ -44,6 +44,9 @@
<div class="col-[7]"></div>
<div class="col-end-[7]"></div>
<div class="col-start-[7]"></div>
<div class="flex-[var(--flex)]"></div>
<div class="flex-grow-[var(--grow)]"></div>
<div class="flex-shrink-[var(--shrink)]"></div>
<div class="row-[7]"></div>
<div class="row-end-[7]"></div>
<div class="row-start-[7]"></div>

View File

@ -50,6 +50,17 @@
.tw--ml-4 {
margin-left: -1rem;
}
.tw-animate-ping {
animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes tw-spin {
to {
transform: rotate(360deg);
}
}
.tw-animate-spin {
animation: tw-spin 1s linear infinite;
}
.tw-font-bold {
font-weight: 700;
}
@ -62,7 +73,7 @@
.tw-group:hover .group-hover\:focus-within\:tw-text-left:focus-within {
text-align: left;
}
[dir='rtl'] .rtl\:active\:tw-text-center:active {
[dir="rtl"] .rtl\:active\:tw-text-center:active {
text-align: center;
}
@media (prefers-reduced-motion: no-preference) {

View File

@ -15,3 +15,5 @@
<div class="dark:focus:tw-text-left"></div>
<div class="group-hover:focus-within:tw-text-left"></div>
<div class="rtl:active:tw-text-center"></div>
<div class="tw-animate-ping"></div>
<div class="tw-animate-spin"></div>

View File

@ -16,7 +16,15 @@ test('prefix', () => {
mode: 'jit',
purge: [path.resolve(__dirname, './prefix.test.html')],
corePlugins: { preflight: false },
theme: {},
theme: {
animation: {
spin: 'spin 1s linear infinite',
ping: 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite',
},
keyframes: {
spin: { to: { transform: 'rotate(360deg)' } },
},
},
plugins: [
function ({ addComponents, addUtilities }) {
addComponents({

View File

@ -32,19 +32,24 @@ test('defining animation and keyframes', () => {
@keyframes spin {
to { transform: rotate(360deg); }
}
}
}
@layer utilities {
@variants {
@keyframes ping {
75%, 100% { transform: scale(2); opacity: 0; }
}
}
}
@layer utilities {
@variants {
.animate-none { animation: none; }
.animate-spin { animation: spin 1s linear infinite; }
.animate-ping { animation: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite; }
}
}
}
`)
})
@ -75,6 +80,11 @@ test('defining animation and keyframes with prefix', () => {
@keyframes tw-spin {
to { transform: rotate(360deg); }
}
}
}
@layer utilities {
@variants {
@keyframes tw-ping {
75%, 100% { transform: scale(2); opacity: 0; }
}

View File

@ -1,28 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/backgroundColor'
test('defining color as a function', () => {
const config = {
theme: {
backgroundColor: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
backgroundColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.bg-black': {
'background-color': 'black',
},
},
[],
],
])
})

View File

@ -1,28 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/borderColor'
test('defining color as a function', () => {
const config = {
theme: {
borderColor: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
borderColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.border-black': {
'border-color': 'black',
},
},
[],
],
])
})

View File

@ -1,79 +0,0 @@
import _ from 'lodash'
import escapeClassName from '../../src/util/escapeClassName'
import plugin from '../../src/plugins/boxShadow'
test('box shadow can use DEFAULT keyword and negative prefix syntax', () => {
const addedUtilities = []
const config = {
theme: {
boxShadow: {
DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
'-': 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
'-md': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
},
},
variants: {
boxShadow: ['responsive'],
},
}
const getConfigValue = (path, defaultValue) => _.get(config, path, defaultValue)
const pluginApi = {
config: getConfigValue,
e: escapeClassName,
theme: (path, defaultValue) => getConfigValue(`theme.${path}`, defaultValue),
variants: (path, defaultValue) => {
if (_.isArray(config.variants)) {
return config.variants
}
return getConfigValue(`variants.${path}`, defaultValue)
},
addUtilities(utilities, options) {
addedUtilities.push({
utilities,
options,
})
},
}
plugin()(pluginApi)
expect(addedUtilities).toEqual([
{
utilities: {
'*': {
'--tw-shadow': '0 0 #0000',
},
},
options: { respectImportant: false },
},
{
utilities: {
'.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': {
'--tw-shadow': 'inset 0 2px 4px 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)',
},
},
options: ['responsive'],
},
])
})

View File

@ -1,28 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/divideColor'
test('defining color as a function', () => {
const config = {
theme: {
divideColor: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
divideColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.divide-black > :not([hidden]) ~ :not([hidden])': {
'border-color': 'black',
},
},
[],
],
])
})

View File

@ -1,74 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/divideWidth'
test('generating divide width utilities', () => {
const config = {
theme: {
divideWidth: {
DEFAULT: '1px',
0: '0',
2: '2px',
4: '4px',
},
},
variants: {
divideWidth: ['responsive'],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.divide-y > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-y-reverse': '0',
'border-top-width': 'calc(1px * calc(1 - var(--tw-divide-y-reverse)))',
'border-bottom-width': 'calc(1px * var(--tw-divide-y-reverse))',
},
'.divide-x > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-x-reverse': '0',
'border-right-width': 'calc(1px * var(--tw-divide-x-reverse))',
'border-left-width': 'calc(1px * calc(1 - var(--tw-divide-x-reverse)))',
},
'.divide-y-0 > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-y-reverse': '0',
'border-top-width': 'calc(0px * calc(1 - var(--tw-divide-y-reverse)))',
'border-bottom-width': 'calc(0px * var(--tw-divide-y-reverse))',
},
'.divide-x-0 > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-x-reverse': '0',
'border-right-width': 'calc(0px * var(--tw-divide-x-reverse))',
'border-left-width': 'calc(0px * calc(1 - var(--tw-divide-x-reverse)))',
},
'.divide-y-2 > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-y-reverse': '0',
'border-top-width': 'calc(2px * calc(1 - var(--tw-divide-y-reverse)))',
'border-bottom-width': 'calc(2px * var(--tw-divide-y-reverse))',
},
'.divide-x-2 > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-x-reverse': '0',
'border-right-width': 'calc(2px * var(--tw-divide-x-reverse))',
'border-left-width': 'calc(2px * calc(1 - var(--tw-divide-x-reverse)))',
},
'.divide-y-4 > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-y-reverse': '0',
'border-top-width': 'calc(4px * calc(1 - var(--tw-divide-y-reverse)))',
'border-bottom-width': 'calc(4px * var(--tw-divide-y-reverse))',
},
'.divide-x-4 > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-x-reverse': '0',
'border-right-width': 'calc(4px * var(--tw-divide-x-reverse))',
'border-left-width': 'calc(4px * calc(1 - var(--tw-divide-x-reverse)))',
},
'.divide-y-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-y-reverse': '1',
},
'.divide-x-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-divide-x-reverse': '1',
},
},
['responsive'],
],
])
})

View File

@ -1,28 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/fill'
test('defining color as a function', () => {
const config = {
theme: {
fill: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
fill: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.fill-black': {
fill: 'black',
},
},
[],
],
])
})

View File

@ -1,5 +1,12 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/fontSize'
import postcss from 'postcss'
import path from 'path'
import tailwind from '../../src/index.js'
function run(input, config = {}) {
return postcss(tailwind(config)).process(input, {
from: path.resolve(__filename),
})
}
test('font-size utilities can include a default line-height', () => {
const config = {
@ -10,23 +17,19 @@ test('font-size utilities can include a default line-height', () => {
lg: ['20px', '28px'],
},
},
corePlugins: ['fontSize'],
variants: {
fontSize: ['responsive'],
fontSize: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.text-sm': { 'font-size': '12px' },
'.text-md': { 'font-size': '16px', 'line-height': '24px' },
'.text-lg': { 'font-size': '20px', 'line-height': '28px' },
},
['responsive'],
],
])
return run('@tailwind utilities', config).then((result) => {
expect(result.css).toMatchCss(`
.text-sm { font-size: 12px }
.text-md { font-size: 16px; line-height: 24px }
.text-lg { font-size: 20px; line-height: 28px }
`)
})
})
test('font-size utilities can include a default letter-spacing', () => {
@ -38,23 +41,19 @@ test('font-size utilities can include a default letter-spacing', () => {
lg: ['20px', { letterSpacing: '-0.02em' }],
},
},
corePlugins: ['fontSize'],
variants: {
fontSize: ['responsive'],
fontSize: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.text-sm': { 'font-size': '12px' },
'.text-md': { 'font-size': '16px', 'letter-spacing': '-0.01em' },
'.text-lg': { 'font-size': '20px', 'letter-spacing': '-0.02em' },
},
['responsive'],
],
])
return run('@tailwind utilities', config).then((result) => {
expect(result.css).toMatchCss(`
.text-sm { font-size: 12px }
.text-md { font-size: 16px; letter-spacing: -0.01em }
.text-lg { font-size: 20px; letter-spacing: -0.02em }
`)
})
})
test('font-size utilities can include a default line-height and letter-spacing', () => {
@ -66,21 +65,17 @@ test('font-size utilities can include a default line-height and letter-spacing',
lg: ['20px', { lineHeight: '28px', letterSpacing: '-0.02em' }],
},
},
corePlugins: ['fontSize'],
variants: {
fontSize: ['responsive'],
fontSize: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.text-sm': { 'font-size': '12px' },
'.text-md': { 'font-size': '16px', 'line-height': '24px', 'letter-spacing': '-0.01em' },
'.text-lg': { 'font-size': '20px', 'line-height': '28px', 'letter-spacing': '-0.02em' },
},
['responsive'],
],
])
return run('@tailwind utilities', config).then((result) => {
expect(result.css).toMatchCss(`
.text-sm { font-size: 12px }
.text-md { font-size: 16px; line-height: 24px; letter-spacing: -0.01em }
.text-lg { font-size: 20px; line-height: 28px; letter-spacing: -0.02em }
`)
})
})

View File

@ -1,53 +0,0 @@
import _ from 'lodash'
import escapeClassName from '../../src/util/escapeClassName'
import plugin from '../../src/plugins/letterSpacing'
test('letter spacing can use negative prefix syntax', () => {
const addedUtilities = []
const config = {
theme: {
letterSpacing: {
'-1': '-0.025em',
1: '0.025em',
},
},
variants: {
letterSpacing: ['responsive'],
},
}
const getConfigValue = (path, defaultValue) => _.get(config, path, defaultValue)
const pluginApi = {
config: getConfigValue,
e: escapeClassName,
theme: (path, defaultValue) => getConfigValue(`theme.${path}`, defaultValue),
variants: (path, defaultValue) => {
if (_.isArray(config.variants)) {
return config.variants
}
return getConfigValue(`variants.${path}`, defaultValue)
},
addUtilities(utilities, variants) {
addedUtilities.push({
utilities,
variants,
})
},
}
plugin()(pluginApi)
expect(addedUtilities).toEqual([
{
utilities: [
{
'.-tracking-1': { letterSpacing: '-0.025em' },
'.tracking-1': { letterSpacing: '0.025em' },
},
],
variants: ['responsive'],
},
])
})

View File

@ -1,28 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/placeholderColor'
test('defining color as a function', () => {
const config = {
theme: {
placeholderColor: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
placeholderColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.placeholder-black::placeholder': {
color: 'black',
},
},
[],
],
])
})

View File

@ -1,29 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/ringColor'
test('defining color as a function', () => {
const config = {
theme: {
ringColor: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
ringColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.ring-black': {
'--tw-ring-opacity': '1',
'--tw-ring-color': 'black',
},
},
[],
],
])
})

View File

@ -1,28 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/ringOffsetColor'
test('defining color as a function', () => {
const config = {
theme: {
ringOffsetColor: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
ringOffsetColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.ring-offset-black': {
'--tw-ring-offset-color': 'black',
},
},
[],
],
])
})

View File

@ -1,149 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/ringWidth'
test('ring widths', () => {
const config = {
theme: {
ringWidth: {
4: '4px',
},
ringOffsetWidth: {
4: '4px',
},
ringColor: {
black: '#000',
},
ringOffsetColor: {
white: '#fff',
},
ringOpacity: {
50: '.5',
},
},
variants: {
ringColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'*': {
'--tw-ring-color': 'rgba(147, 197, 253, 0.5)',
'--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-ring-offset-color': '#fff',
'--tw-ring-offset-shadow': '0 0 #0000',
'--tw-ring-offset-width': '0px',
'--tw-ring-shadow': '0 0 #0000',
},
},
{
respectImportant: false,
},
],
[
{
'.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-inset': {
'--tw-ring-inset': 'inset',
},
},
undefined,
],
])
})
test('ring widths with defaults and hsl value for ringColor', () => {
const config = {
theme: {
ringWidth: {},
ringOffsetWidth: {
DEFAULT: '2px',
},
ringOffsetColor: {
DEFAULT: 'pink',
},
ringColor: {
DEFAULT: 'hsl(10, 50%, 50%)',
},
},
variants: {
ringColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'*': {
'--tw-ring-color': 'hsla(10, 50%, 50%, 0.5)',
'--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-ring-offset-color': 'pink',
'--tw-ring-offset-shadow': '0 0 #0000',
'--tw-ring-offset-width': '2px',
'--tw-ring-shadow': '0 0 #0000',
},
},
{ respectImportant: false },
],
[
{
'.ring-inset': {
'--tw-ring-inset': 'inset',
},
},
undefined,
],
])
})
test('ring widths with defaults', () => {
const config = {
theme: {
ringWidth: {},
ringOffsetWidth: {
DEFAULT: '2px',
},
ringOffsetColor: {
DEFAULT: 'pink',
},
},
variants: {
ringColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'*': {
'--tw-ring-color': 'rgba(147, 197, 253, 0.5)',
'--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-ring-offset-color': 'pink',
'--tw-ring-offset-shadow': '0 0 #0000',
'--tw-ring-offset-width': '2px',
'--tw-ring-shadow': '0 0 #0000',
},
},
{ respectImportant: false },
],
[
{
'.ring-inset': {
'--tw-ring-inset': 'inset',
},
},
undefined,
],
])
})

View File

@ -1,96 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/space'
test('generating space utilities', () => {
const config = {
theme: {
space: {
0: '0',
1: '1px',
2: '2px',
4: '4px',
'-2': '-2px',
'-1': '-1px',
},
},
variants: {
space: ['responsive'],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.space-y-0 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '0',
'margin-top': 'calc(0px * calc(1 - var(--tw-space-y-reverse)))',
'margin-bottom': 'calc(0px * var(--tw-space-y-reverse))',
},
'.space-x-0 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '0',
'margin-right': 'calc(0px * var(--tw-space-x-reverse))',
'margin-left': 'calc(0px * calc(1 - var(--tw-space-x-reverse)))',
},
'.space-y-1 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '0',
'margin-top': 'calc(1px * calc(1 - var(--tw-space-y-reverse)))',
'margin-bottom': 'calc(1px * var(--tw-space-y-reverse))',
},
'.space-x-1 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '0',
'margin-right': 'calc(1px * var(--tw-space-x-reverse))',
'margin-left': 'calc(1px * calc(1 - var(--tw-space-x-reverse)))',
},
'.space-y-2 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '0',
'margin-top': 'calc(2px * calc(1 - var(--tw-space-y-reverse)))',
'margin-bottom': 'calc(2px * var(--tw-space-y-reverse))',
},
'.space-x-2 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '0',
'margin-right': 'calc(2px * var(--tw-space-x-reverse))',
'margin-left': 'calc(2px * calc(1 - var(--tw-space-x-reverse)))',
},
'.space-y-4 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '0',
'margin-top': 'calc(4px * calc(1 - var(--tw-space-y-reverse)))',
'margin-bottom': 'calc(4px * var(--tw-space-y-reverse))',
},
'.space-x-4 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '0',
'margin-right': 'calc(4px * var(--tw-space-x-reverse))',
'margin-left': 'calc(4px * calc(1 - var(--tw-space-x-reverse)))',
},
'.-space-y-2 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '0',
'margin-top': 'calc(-2px * calc(1 - var(--tw-space-y-reverse)))',
'margin-bottom': 'calc(-2px * var(--tw-space-y-reverse))',
},
'.-space-x-2 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '0',
'margin-right': 'calc(-2px * var(--tw-space-x-reverse))',
'margin-left': 'calc(-2px * calc(1 - var(--tw-space-x-reverse)))',
},
'.-space-y-1 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '0',
'margin-top': 'calc(-1px * calc(1 - var(--tw-space-y-reverse)))',
'margin-bottom': 'calc(-1px * var(--tw-space-y-reverse))',
},
'.-space-x-1 > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '0',
'margin-right': 'calc(-1px * var(--tw-space-x-reverse))',
'margin-left': 'calc(-1px * calc(1 - var(--tw-space-x-reverse)))',
},
'.space-y-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-space-y-reverse': '1',
},
'.space-x-reverse > :not([hidden]) ~ :not([hidden])': {
'--tw-space-x-reverse': '1',
},
},
['responsive'],
],
])
})

View File

@ -1,28 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/stroke'
test('defining color as a function', () => {
const config = {
theme: {
stroke: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
stroke: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.stroke-black': {
stroke: 'black',
},
},
[],
],
])
})

View File

@ -1,28 +0,0 @@
import invokePlugin from '../util/invokePlugin'
import plugin from '../../src/plugins/textColor'
test('defining color as a function', () => {
const config = {
theme: {
textColor: {
black: ({ opacityVariable: _ }) => 'black',
},
},
variants: {
textColor: [],
},
}
const { utilities } = invokePlugin(plugin(), config)
expect(utilities).toEqual([
[
{
'.text-black': {
color: 'black',
},
},
[],
],
])
})

View File

@ -1,57 +0,0 @@
import _ from 'lodash'
import escapeClassName from '../../src/util/escapeClassName'
import plugin from '../../src/plugins/zIndex'
test('z index can use negative prefix syntax', () => {
const addedUtilities = []
const config = {
theme: {
zIndex: {
'-20': '-20',
'-10': '-10',
10: '10',
20: '20',
},
},
variants: {
zIndex: ['responsive'],
},
}
const getConfigValue = (path, defaultValue) => _.get(config, path, defaultValue)
const pluginApi = {
config: getConfigValue,
e: escapeClassName,
theme: (path, defaultValue) => getConfigValue(`theme.${path}`, defaultValue),
variants: (path, defaultValue) => {
if (_.isArray(config.variants)) {
return config.variants
}
return getConfigValue(`variants.${path}`, defaultValue)
},
addUtilities(utilities, variants) {
addedUtilities.push({
utilities,
variants,
})
},
}
plugin()(pluginApi)
expect(addedUtilities).toEqual([
{
utilities: [
{
'.-z-20': { zIndex: '-20' },
'.-z-10': { zIndex: '-10' },
'.z-10': { zIndex: '10' },
'.z-20': { zIndex: '20' },
},
],
variants: ['responsive'],
},
])
})

View File

@ -2490,20 +2490,8 @@ test('plugins can add utilities using matchUtilities in AOT mode', () => {
function ({ matchUtilities, theme, variants }) {
matchUtilities(
{
'flex-grow': (modifier, { value }) => {
return {
[`.flex-grow-${modifier}`]: {
'flex-grow': value,
},
}
},
'flex-shrink': (modifier, { value }) => {
return {
[`.flex-shrink-${modifier}`]: {
'flex-shrink': value,
},
}
},
'flex-grow': (value) => ({ 'flex-grow': value }),
'flex-shrink': (value) => ({ 'flex-shrink': value }),
},
{
values: theme('flexyPants'),