Add CSS filter support (#3923)

* Implement `filter` helper classes with all methods

* Rename filter plugins/utilities, drop filter opacity, add drop shadow

* Remove non-final default filter values

* Working on default filter values, add basic JIT support

* Working on blur values

* New blur values (these are ~okay)

* Match drop-shadow values to box-shadows by eye as best as possible

* Update tests

* Fix kitchen sink test

* Add filter variants configuration

* Move drop-shadow to end of filters list

Co-Authored-By: Peter Neupauer <peter@neupauer.sk>

* Add invert variants configuration

* Add backdrop-filter utilities

* Update tests

* Transition filters by default

* Alphabetize new config keys

* Optimize filter plugins for JIT + add arbitrary value support

Except for drop-shadow, will add that once we can think it through a bit.

Co-authored-by: Nick Schmidt <nick@kreativgebiet.com>
Co-authored-by: Peter Neupauer <peter@neupauer.sk>
This commit is contained in:
Adam Wathan 2021-04-04 19:09:34 -04:00 • committed by GitHub
parent 38661c3a4f
commit 60a06788fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 11398 additions and 38 deletions

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

@ -292,6 +292,28 @@ module.exports = {
ringOffsetWidth: require('./ringOffsetWidth'),
ringOffsetColor: require('./ringOffsetColor'),
filter: require('../../lib/plugins/filter').default(),
blur: require('../../lib/plugins/blur').default(),
brightness: require('../../lib/plugins/brightness').default(),
contrast: require('../../lib/plugins/contrast').default(),
dropShadow: require('../../lib/plugins/dropShadow').default(),
grayscale: require('../../lib/plugins/grayscale').default(),
hueRotate: require('../../lib/plugins/hueRotate').default(),
invert: require('../../lib/plugins/invert').default(),
saturate: require('../../lib/plugins/saturate').default(),
sepia: require('../../lib/plugins/sepia').default(),
backdropFilter: require('../../lib/plugins/backdropFilter').default(),
backdropBlur: require('../../lib/plugins/backdropBlur').default(),
backdropBrightness: require('../../lib/plugins/backdropBrightness').default(),
backdropContrast: require('../../lib/plugins/backdropContrast').default(),
backdropGrayscale: require('../../lib/plugins/backdropGrayscale').default(),
backdropHueRotate: require('../../lib/plugins/backdropHueRotate').default(),
backdropInvert: require('../../lib/plugins/backdropInvert').default(),
backdropOpacity: require('../../lib/plugins/backdropOpacity').default(),
backdropSaturate: require('../../lib/plugins/backdropSaturate').default(),
backdropSepia: require('../../lib/plugins/backdropSepia').default(),
transitionProperty: require('./transitionProperty'),
transitionDelay: require('./transitionDelay'),
transitionDuration: require('./transitionDuration'),

View file

@ -136,6 +136,57 @@
.text-\[2\.23rem\] {
font-size: 2.23rem;
}
.blur-\[15px\] {
--tw-blur: blur(15px);
}
.brightness-\[300\%\] {
--tw-brightness: brightness(300%);
}
.contrast-\[2\.4\] {
--tw-contrast: contrast(2.4);
}
.grayscale-\[0\.55\] {
--tw-grayscale: grayscale(0.55);
}
.hue-rotate-\[0\.8turn\] {
--tw-hue-rotate: hue-rotate(0.8turn);
}
.invert-\[0\.75\] {
--tw-invert: invert(0.75);
}
.saturate-\[180\%\] {
--tw-saturate: saturate(180%);
}
.sepia-\[0\.2\] {
--tw-sepia: sepia(0.2);
}
.backdrop-blur-\[11px\] {
--tw-backdrop-blur: blur(11px);
}
.backdrop-brightness-\[1\.23\] {
--tw-backdrop-brightness: brightness(1.23);
}
.backdrop-contrast-\[0\.87\] {
--tw-backdrop-contrast: contrast(0.87);
}
.backdrop-grayscale-\[0\.42\] {
--tw-backdrop-grayscale: grayscale(0.42);
}
.backdrop-hue-rotate-\[1\.57rad\] {
--tw-backdrop-hue-rotate: hue-rotate(1.57rad);
}
.backdrop-invert-\[0\.66\] {
--tw-backdrop-invert: invert(0.66);
}
.backdrop-opacity-\[22\%\] {
--tw-backdrop-opacity: opacity(22%);
}
.backdrop-saturate-\[144\%\] {
--tw-backdrop-saturate: saturate(144%);
}
.backdrop-sepia-\[0\.38\] {
--tw-backdrop-sepia: sepia(0.38);
}
.duration-\[2s\] {
transition-duration: 2s;
}

View file

@ -43,5 +43,22 @@
<div class="duration-[var(--app-duration)]"></div>
<div class="p-[var(--app-padding)]"></div>
<div class="inset-[11px]"></div>
<div class="blur-[15px]"></div>
<div class="brightness-[300%]"></div>
<div class="contrast-[2.4]"></div>
<div class="grayscale-[0.55]"></div>
<div class="hue-rotate-[0.8turn]"></div>
<div class="invert-[0.75]"></div>
<div class="saturate-[180%]"></div>
<div class="sepia-[0.2]"></div>
<div class="backdrop-blur-[11px]"></div>
<div class="backdrop-brightness-[1.23]"></div>
<div class="backdrop-contrast-[0.87]"></div>
<div class="backdrop-grayscale-[0.42]"></div>
<div class="backdrop-hue-rotate-[1.57rad]"></div>
<div class="backdrop-invert-[0.66]"></div>
<div class="backdrop-opacity-[22%]"></div>
<div class="backdrop-saturate-[144%]"></div>
<div class="backdrop-sepia-[0.38]"></div>
</body>
</html>

View file

@ -9,6 +9,7 @@ function run(input, config = {}) {
test('arbitrary values', () => {
let config = {
mode: 'jit',
purge: [path.resolve(__dirname, './arbitrary-values.test.html')],
corePlugins: { preflight: false },
theme: {},

View file

@ -633,9 +633,97 @@
.ring-offset-blue-300 {
--tw-ring-offset-color: #93c5fd;
}
.filter {
--tw-blur: var(--tw-empty, /*!*/ /*!*/);
--tw-brightness: var(--tw-empty, /*!*/ /*!*/);
--tw-contrast: var(--tw-empty, /*!*/ /*!*/);
--tw-grayscale: var(--tw-empty, /*!*/ /*!*/);
--tw-hue-rotate: var(--tw-empty, /*!*/ /*!*/);
--tw-invert: var(--tw-empty, /*!*/ /*!*/);
--tw-saturate: var(--tw-empty, /*!*/ /*!*/);
--tw-sepia: var(--tw-empty, /*!*/ /*!*/);
--tw-drop-shadow: var(--tw-empty, /*!*/ /*!*/);
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale)
var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.filter-none {
filter: none;
}
.blur-md {
--tw-blur: blur(12px);
}
.brightness-150 {
--tw-brightness: brightness(1.5);
}
.contrast-50 {
--tw-contrast: contrast(0.5);
}
.drop-shadow-md {
--tw-drop-shadow: drop-shadow(0 4px 3px rgba(0, 0, 0, 0.07))
drop-shadow(0 2px 2px rgba(0, 0, 0, 0.06));
}
.grayscale {
--tw-grayscale: grayscale(100%);
}
.hue-rotate-60 {
--tw-hue-rotate: hue-rotate(60deg);
}
.invert {
--tw-invert: invert(100%);
}
.saturate-200 {
--tw-saturate: saturate(2);
}
.sepia {
--tw-sepia: sepia(100%);
}
.backdrop-filter {
--tw-backdrop-blur: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-brightness: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-contrast: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-grayscale: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-hue-rotate: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-invert: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-opacity: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-saturate: var(--tw-empty, /*!*/ /*!*/);
--tw-backdrop-sepia: var(--tw-empty, /*!*/ /*!*/);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast)
var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert)
var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.backdrop-filter-none {
backdrop-filter: none;
}
.backdrop-blur-lg {
--tw-backdrop-blur: blur(16px);
}
.backdrop-brightness-50 {
--tw-backdrop-brightness: brightness(0.5);
}
.backdrop-contrast-0 {
--tw-backdrop-contrast: contrast(0);
}
.backdrop-grayscale {
--tw-backdrop-grayscale: grayscale(100%);
}
.backdrop-hue-rotate-90 {
--tw-backdrop-hue-rotate: hue-rotate(90deg);
}
.backdrop-invert {
--tw-backdrop-invert: invert(100%);
}
.backdrop-opacity-75 {
--tw-backdrop-opacity: opacity(0.75);
}
.backdrop-saturate-150 {
--tw-backdrop-saturate: saturate(1.5);
}
.backdrop-sepia {
--tw-backdrop-sepia: sepia(100%);
}
.transition {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
transform;
transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}

View file

@ -108,6 +108,12 @@
<div class="ring-offset-2"></div>
<div class="ring-opacity-40"></div>
<div class="ring ring-4"></div>
<div
class="filter filter-none blur-md brightness-150 contrast-50 drop-shadow-md grayscale hue-rotate-60 invert saturate-200 sepia"
></div>
<div
class="backdrop-filter backdrop-filter-none backdrop-blur-lg backdrop-brightness-50 backdrop-contrast-0 backdrop-grayscale backdrop-hue-rotate-90 backdrop-invert backdrop-opacity-75 backdrop-saturate-150 backdrop-sepia"
></div>
<div class="rotate-3"></div>
<div class="scale-95"></div>
<div class="skew-y-12 skew-x-12"></div>

View file

@ -314,11 +314,11 @@ div {
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
var(--tw-shadow);
}
.filter-none {
filter: none;
.magic-none {
magic: none;
}
.filter-grayscale {
filter: grayscale(100%);
.magic-tons {
magic: tons;
}
.custom-util {
background: #abcdef;
@ -410,7 +410,7 @@ div {
@media (prefers-reduced-motion: no-preference) {
.motion-safe\:transition {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
transform;
transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
@ -421,7 +421,7 @@ div {
@media (prefers-reduced-motion: reduce) {
.motion-reduce\:transition {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
transform;
transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
@ -535,7 +535,7 @@ div {
@media (prefers-reduced-motion: no-preference) {
.md\:motion-safe\:hover\:transition:hover {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow,
transform;
transform, filter, backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}

View file

@ -27,7 +27,7 @@
<div class="md:dark:motion-safe:foo:active:custom-util"></div>
<div class="aspect-w-1 aspect-h-2"></div>
<div class="aspect-w-3 aspect-h-4"></div>
<div class="filter-none filter-grayscale"></div>
<div class="magic-none magic-tons"></div>
<div class="focus:font-normal"></div>
<div class="font-medium"></div>
<div class="bg-gradient-to-r from-foo"></div>

View file

@ -55,11 +55,11 @@ test('it works', () => {
})
addUtilities(
{
'.filter-none': {
filter: 'none',
'.magic-none': {
magic: 'none',
},
'.filter-grayscale': {
filter: 'grayscale(100%)',
'.magic-tons': {
magic: 'tons',
},
},
['responsive', 'hover']

View file

@ -122,4 +122,24 @@ export const corePluginList = [
'animation',
'mixBlendMode',
'backgroundBlendMode',
'filter',
'blur',
'brightness',
'contrast',
'dropShadow',
'grayscale',
'hueRotate',
'invert',
'saturate',
'sepia',
'backdropFilter',
'backdropBlur',
'backdropBrightness',
'backdropContrast',
'backdropGrayscale',
'backdropHueRotate',
'backdropInvert',
'backdropOpacity',
'backdropSaturate',
'backdropSepia',
]

View file

@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})` },
}
},
})
} 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'))
}
}
}

View file

@ -0,0 +1,39 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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 {
[nameClass('backdrop-brightness', modifier)]: {
'--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'))
}
}
}

View file

@ -0,0 +1,39 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})`,
},
}
},
})
} 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'))
}
}
}

View file

@ -0,0 +1,32 @@
export default function () {
return function ({ addUtilities, variants }) {
addUtilities(
{
'.backdrop-filter': {
'--tw-backdrop-blur': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-backdrop-brightness': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-backdrop-contrast': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-backdrop-grayscale': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-backdrop-hue-rotate': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-backdrop-invert': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-backdrop-opacity': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-backdrop-saturate': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-backdrop-sepia': 'var(--tw-empty,/*!*/ /*!*/)',
'backdrop-filter': [
'var(--tw-backdrop-blur)',
'var(--tw-backdrop-brightness)',
'var(--tw-backdrop-contrast)',
'var(--tw-backdrop-grayscale)',
'var(--tw-backdrop-hue-rotate)',
'var(--tw-backdrop-invert)',
'var(--tw-backdrop-opacity)',
'var(--tw-backdrop-saturate)',
'var(--tw-backdrop-sepia)',
].join(' '),
},
'.backdrop-filter-none': { 'backdrop-filter': 'none' },
},
variants('backdropFilter')
)
}
}

View file

@ -0,0 +1,39 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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 {
[nameClass('backdrop-grayscale', modifier)]: {
'--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'))
}
}
}

View file

@ -0,0 +1,39 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})`,
},
}
},
})
} 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'))
}
}
}

View file

@ -0,0 +1,39 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})`,
},
}
},
})
} 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'))
}
}
}

View file

@ -0,0 +1,39 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})`,
},
}
},
})
} 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'))
}
}
}

View file

@ -0,0 +1,39 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})`,
},
}
},
})
} 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'))
}
}
}

View file

@ -0,0 +1,39 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})`,
},
}
},
})
} 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'))
}
}
}

35
src/plugins/blur.js Normal file
View file

@ -0,0 +1,35 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})` } }
},
})
} 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'))
}
}
}

37
src/plugins/brightness.js Normal file
View file

@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})` },
}
},
})
} 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'))
}
}
}

37
src/plugins/contrast.js Normal file
View file

@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})` },
}
},
})
} 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'))
}
}
}

21
src/plugins/dropShadow.js Normal file
View file

@ -0,0 +1,21 @@
import _ from 'lodash'
import nameClass from '../util/nameClass'
export default function () {
return function ({ addUtilities, theme, variants }) {
const utilities = _.fromPairs(
_.map(theme('dropShadow'), (value, modifier) => {
return [
nameClass('drop-shadow', modifier),
{
'--tw-drop-shadow': Array.isArray(value)
? value.map((v) => `drop-shadow(${v})`).join(' ')
: `drop-shadow(${value})`,
},
]
})
)
addUtilities(utilities, variants('dropShadow'))
}
}

32
src/plugins/filter.js Normal file
View file

@ -0,0 +1,32 @@
export default function () {
return function ({ addUtilities, variants }) {
addUtilities(
{
'.filter': {
'--tw-blur': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-brightness': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-contrast': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-grayscale': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-hue-rotate': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-invert': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-saturate': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-sepia': 'var(--tw-empty,/*!*/ /*!*/)',
'--tw-drop-shadow': 'var(--tw-empty,/*!*/ /*!*/)',
filter: [
'var(--tw-blur)',
'var(--tw-brightness)',
'var(--tw-contrast)',
'var(--tw-grayscale)',
'var(--tw-hue-rotate)',
'var(--tw-invert)',
'var(--tw-saturate)',
'var(--tw-sepia)',
'var(--tw-drop-shadow)',
].join(' '),
},
'.filter-none': { filter: 'none' },
},
variants('filter')
)
}
}

37
src/plugins/grayscale.js Normal file
View file

@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})` },
}
},
})
} 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'))
}
}
}

37
src/plugins/hueRotate.js Normal file
View file

@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})` },
}
},
})
} 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'))
}
}
}

View file

@ -4,6 +4,16 @@ export { default as alignItems } from './alignItems'
export { default as alignSelf } from './alignSelf'
export { default as animation } from './animation'
export { default as appearance } from './appearance'
export { default as backdropBlur } from './backdropBlur'
export { default as backdropBrightness } from './backdropBrightness'
export { default as backdropContrast } from './backdropContrast'
export { default as backdropFilter } from './backdropFilter'
export { default as backdropGrayscale } from './backdropGrayscale'
export { default as backdropHueRotate } from './backdropHueRotate'
export { default as backdropInvert } from './backdropInvert'
export { default as backdropOpacity } from './backdropOpacity'
export { default as backdropSaturate } from './backdropSaturate'
export { default as backdropSepia } from './backdropSepia'
export { default as backgroundAttachment } from './backgroundAttachment'
export { default as backgroundBlendMode } from './backgroundBlendMode'
export { default as backgroundClip } from './backgroundClip'
@ -13,6 +23,7 @@ export { default as backgroundOpacity } from './backgroundOpacity'
export { default as backgroundPosition } from './backgroundPosition'
export { default as backgroundRepeat } from './backgroundRepeat'
export { default as backgroundSize } from './backgroundSize'
export { default as blur } from './blur'
export { default as borderCollapse } from './borderCollapse'
export { default as borderColor } from './borderColor'
export { default as borderOpacity } from './borderOpacity'
@ -22,15 +33,19 @@ export { default as borderWidth } from './borderWidth'
export { default as boxDecorationBreak } from './boxDecorationBreak'
export { default as boxShadow } from './boxShadow'
export { default as boxSizing } from './boxSizing'
export { default as brightness } from './brightness'
export { default as clear } from './clear'
export { default as container } from './container'
export { default as contrast } from './contrast'
export { default as cursor } from './cursor'
export { default as display } from './display'
export { default as divideColor } from './divideColor'
export { default as divideOpacity } from './divideOpacity'
export { default as divideStyle } from './divideStyle'
export { default as divideWidth } from './divideWidth'
export { default as dropShadow } from './dropShadow'
export { default as fill } from './fill'
export { default as filter } from './filter'
export { default as flex } from './flex'
export { default as flexDirection } from './flexDirection'
export { default as flexGrow } from './flexGrow'
@ -45,6 +60,7 @@ export { default as fontVariantNumeric } from './fontVariantNumeric'
export { default as fontWeight } from './fontWeight'
export { default as gap } from './gap'
export { default as gradientColorStops } from './gradientColorStops'
export { default as grayscale } from './grayscale'
export { default as gridAutoColumns } from './gridAutoColumns'
export { default as gridAutoFlow } from './gridAutoFlow'
export { default as gridAutoRows } from './gridAutoRows'
@ -57,7 +73,9 @@ export { default as gridRowStart } from './gridRowStart'
export { default as gridTemplateColumns } from './gridTemplateColumns'
export { default as gridTemplateRows } from './gridTemplateRows'
export { default as height } from './height'
export { default as hueRotate } from './hueRotate'
export { default as inset } from './inset'
export { default as invert } from './invert'
export { default as isolation } from './isolation'
export { default as justifyContent } from './justifyContent'
export { default as justifyItems } from './justifyItems'
@ -95,7 +113,9 @@ export { default as ringOffsetWidth } from './ringOffsetWidth'
export { default as ringOpacity } from './ringOpacity'
export { default as ringWidth } from './ringWidth'
export { default as rotate } from './rotate'
export { default as saturate } from './saturate'
export { default as scale } from './scale'
export { default as sepia } from './sepia'
export { default as skew } from './skew'
export { default as space } from './space'
export { default as stroke } from './stroke'

37
src/plugins/invert.js Normal file
View file

@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})` },
}
},
})
} 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'))
}
}
}

37
src/plugins/saturate.js Normal file
View file

@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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 {
[nameClass('saturate', modifier)]: { '--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'))
}
}
}

37
src/plugins/sepia.js Normal file
View file

@ -0,0 +1,37 @@
import _ from 'lodash'
const { asValue, nameClass } = require('../../jit/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})` },
}
},
})
} 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'))
}
}
}

View file

@ -71,6 +71,15 @@ module.exports = {
pulse: 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
bounce: 'bounce 1s infinite',
},
backdropBlur: (theme) => theme('blur'),
backdropBrightness: (theme) => theme('brightness'),
backdropContrast: (theme) => theme('contrast'),
backdropGrayscale: (theme) => theme('grayscale'),
backdropHueRotate: (theme) => theme('hueRotate'),
backdropInvert: (theme) => theme('invert'),
backdropOpacity: (theme) => theme('opacity'),
backdropSaturate: (theme) => theme('saturate'),
backdropSepia: (theme) => theme('sepia'),
backgroundColor: (theme) => theme('colors'),
backgroundImage: {
none: 'none',
@ -100,6 +109,29 @@ module.exports = {
cover: 'cover',
contain: 'contain',
},
blur: {
0: '0',
sm: '4px',
DEFAULT: '8px',
md: '12px',
lg: '16px',
xl: '24px',
'2xl': '40px',
'3xl': '64px',
},
brightness: {
0: '0',
50: '.5',
75: '.75',
90: '.9',
95: '.95',
100: '1',
105: '1.05',
110: '1.1',
125: '1.25',
150: '1.5',
200: '2',
},
borderColor: (theme) => ({
...theme('colors'),
DEFAULT: theme('colors.gray.200', 'currentColor'),
@ -133,6 +165,15 @@ module.exports = {
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
none: 'none',
},
contrast: {
0: '0',
50: '.5',
75: '.75',
100: '1',
125: '1.25',
150: '1.5',
200: '2',
},
container: {},
cursor: {
auto: 'auto',
@ -147,7 +188,37 @@ module.exports = {
divideColor: (theme) => theme('borderColor'),
divideOpacity: (theme) => theme('borderOpacity'),
divideWidth: (theme) => theme('borderWidth'),
dropShadow: {
sm: '0 1px 1px rgba(0,0,0,0.05)',
DEFAULT: ['0 1px 2px rgba(0, 0, 0, 0.1)', '0 1px 1px rgba(0, 0, 0, 0.06)'],
md: ['0 4px 3px rgba(0, 0, 0, 0.07)', '0 2px 2px rgba(0, 0, 0, 0.06)'],
lg: ['0 10px 8px rgba(0, 0, 0, 0.04)', '0 4px 3px rgba(0, 0, 0, 0.1)'],
xl: ['0 20px 13px rgba(0, 0, 0, 0.03)', '0 8px 5px rgba(0, 0, 0, 0.08)'],
'2xl': '0 25px 25px rgba(0, 0, 0, 0.15)',
none: '0 0 #0000',
},
fill: { current: 'currentColor' },
grayscale: {
0: '0',
DEFAULT: '100%',
},
hueRotate: {
'-180': '-180deg',
'-90': '-90deg',
'-60': '-60deg',
'-30': '-30deg',
'-15': '-15deg',
0: '0deg',
15: '15deg',
30: '30deg',
60: '60deg',
90: '90deg',
180: '180deg',
},
invert: {
0: '0',
DEFAULT: '100%',
},
flex: {
1: '1 1 0%',
auto: '1 1 auto',
@ -567,6 +638,13 @@ module.exports = {
90: '90deg',
180: '180deg',
},
saturate: {
0: '0',
50: '.5',
100: '1',
150: '1.5',
200: '2',
},
scale: {
0: '0',
50: '.5',
@ -579,6 +657,10 @@ module.exports = {
125: '1.25',
150: '1.5',
},
sepia: {
0: '0',
DEFAULT: '100%',
},
skew: {
'-12': '-12deg',
'-6': '-6deg',
@ -641,7 +723,8 @@ module.exports = {
transitionProperty: {
none: 'none',
all: 'all',
DEFAULT: 'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform',
DEFAULT:
'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter',
colors: 'background-color, border-color, color, fill, stroke',
opacity: 'opacity',
shadow: 'box-shadow',
@ -739,6 +822,16 @@ module.exports = {
alignSelf: ['responsive'],
animation: ['responsive'],
appearance: ['responsive'],
backdropBlur: ['responsive'],
backdropBrightness: ['responsive'],
backdropContrast: ['responsive'],
backdropDropShadow: ['responsive'],
backdropFilter: ['responsive'],
backdropGrayscale: ['responsive'],
backdropHueRotate: ['responsive'],
backdropInvert: ['responsive'],
backdropSaturate: ['responsive'],
backdropSepia: ['responsive'],
backgroundAttachment: ['responsive'],
backgroundBlendMode: ['responsive'],
backgroundClip: ['responsive'],
@ -748,6 +841,7 @@ module.exports = {
backgroundPosition: ['responsive'],
backgroundRepeat: ['responsive'],
backgroundSize: ['responsive'],
blur: ['responsive'],
borderCollapse: ['responsive'],
borderColor: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
borderOpacity: ['responsive', 'dark', 'group-hover', 'focus-within', 'hover', 'focus'],
@ -757,15 +851,19 @@ module.exports = {
boxDecorationBreak: ['responsive'],
boxShadow: ['responsive', 'group-hover', 'focus-within', 'hover', 'focus'],
boxSizing: ['responsive'],
brightness: ['responsive'],
clear: ['responsive'],
container: ['responsive'],
contrast: ['responsive'],
cursor: ['responsive'],
display: ['responsive'],
divideColor: ['responsive', 'dark'],
divideOpacity: ['responsive', 'dark'],
divideStyle: ['responsive'],
divideWidth: ['responsive'],
dropShadow: ['responsive'],
fill: ['responsive'],
filter: ['responsive'],
flex: ['responsive'],
flexDirection: ['responsive'],
flexGrow: ['responsive'],
@ -780,6 +878,7 @@ module.exports = {
fontWeight: ['responsive'],
gap: ['responsive'],
gradientColorStops: ['responsive', 'dark', 'hover', 'focus'],
grayscale: ['responsive'],
gridAutoColumns: ['responsive'],
gridAutoFlow: ['responsive'],
gridAutoRows: ['responsive'],
@ -792,7 +891,9 @@ module.exports = {
gridTemplateColumns: ['responsive'],
gridTemplateRows: ['responsive'],
height: ['responsive'],
hueRotate: ['responsive'],
inset: ['responsive'],
invert: ['responsive'],
isolation: ['responsive'],
justifyContent: ['responsive'],
justifyItems: ['responsive'],
@ -829,7 +930,9 @@ module.exports = {
ringOpacity: ['responsive', 'dark', 'focus-within', 'focus'],
ringWidth: ['responsive', 'focus-within', 'focus'],
rotate: ['responsive', 'hover', 'focus'],
saturate: ['responsive'],
scale: ['responsive', 'hover', 'focus'],
sepia: ['responsive'],
skew: ['responsive', 'hover', 'focus'],
space: ['responsive'],
stroke: ['responsive'],