├── .gitignore ├── .release-it.json ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "git": { 3 | "tagName": "v${version}", 4 | "requireCleanWorkingDir": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [3.0.0] - 2020-02-05 9 | 10 | ### Changed 11 | - Changed to use Tailwind 1.2’s new plugin definition syntax 12 | 13 | ## [2.0.0] - 2019-05-13 14 | 15 | ### Changed since 2.0.0-beta.1 16 | - Added support for global variants thanks to Tailwind’s `variants()` helper function 17 | 18 | ### Added since 1.x 19 | - Tailwind 1.0.0 compatibility 20 | 21 | ### Changed since 1.x 22 | - The plugin doesn’t accept a config object anymore; instead it finds what it needs in the `theme` and `variants` keys of your config (see `README` for more info) 23 | - Responsive variants are now generated by default 24 | 25 | ## [2.0.0-beta.1] - 2019-04-07 26 | 27 | ### Added 28 | - Tailwind 1.0.0 compatibility 29 | 30 | ### Changed 31 | - The plugin doesn’t accept a config object anymore; instead it finds what it needs in the `theme` and `variants` keys of your config (see `README` for more info) 32 | - Responsive variants are now generated by default 33 | 34 | ## [1.0.2] - 2018-11-04 35 | 36 | ### Added 37 | - Added proper tests with Jest 38 | 39 | ## [1.0.1] - 2018-08-14 40 | 41 | ### Fixed 42 | - Fixed escaping in selectors generated by the plugin 43 | 44 | ## [1.0.0] - 2018-08-13 45 | 46 | Initial release 47 | 48 | [Unreleased]: https://github.com/benface/tailwindcss-filters/compare/v3.0.0...HEAD 49 | [3.0.0]: https://github.com/benface/tailwindcss-filters/compare/v2.0.0...v3.0.0 50 | [2.0.0]: https://github.com/benface/tailwindcss-filters/compare/v2.0.0-beta.1...v2.0.0 51 | [2.0.0-beta.1]: https://github.com/benface/tailwindcss-filters/compare/v1.0.2...v2.0.0-beta.1 52 | [1.0.2]: https://github.com/benface/tailwindcss-filters/compare/v1.0.1...v1.0.2 53 | [1.0.1]: https://github.com/benface/tailwindcss-filters/compare/v1.0.0...v1.0.1 54 | [1.0.0]: https://github.com/benface/tailwindcss-filters/releases/tag/v1.0.0 55 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # ISC License 2 | 3 | Copyright (c) Benoît Rouleau 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⛔️ DEPRECATED 2 | 3 | Tailwind CSS 2.1+ has built-in `filter` and `backdrop-filter` utilities such as [`blur`](https://tailwindcss.com/docs/blur), [`grayscale`](https://tailwindcss.com/docs/grayscale), [`sepia`](https://tailwindcss.com/docs/sepia), etc. Please use them instead of this plugin. Thank you! 4 | 5 | # Filters Plugin for Tailwind CSS 6 | 7 | ## Requirements 8 | 9 | This plugin requires Tailwind CSS 1.2 or later. If your project uses an older version of Tailwind, you should install the latest 2.x version of this plugin (`npm install tailwindcss-filters@2.x`). 10 | 11 | ## Installation 12 | 13 | ```bash 14 | npm install tailwindcss-filters 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```js 20 | // tailwind.config.js 21 | module.exports = { 22 | theme: { 23 | filter: { // defaults to {} 24 | 'none': 'none', 25 | 'grayscale': 'grayscale(1)', 26 | 'invert': 'invert(1)', 27 | 'sepia': 'sepia(1)', 28 | }, 29 | backdropFilter: { // defaults to {} 30 | 'none': 'none', 31 | 'blur': 'blur(20px)', 32 | }, 33 | }, 34 | variants: { 35 | filter: ['responsive'], // defaults to ['responsive'] 36 | backdropFilter: ['responsive'], // defaults to ['responsive'] 37 | }, 38 | plugins: [ 39 | require('tailwindcss-filters'), 40 | ], 41 | }; 42 | ``` 43 | 44 | This plugin generates the following utilities: 45 | 46 | ```css 47 | /* configurable with the "filter" theme object */ 48 | .filter-[key] { 49 | filter: [value]; 50 | } 51 | 52 | /* configurable with the "backdropFilter" theme object */ 53 | .backdrop-[key] { 54 | backdrop-filter: [value]; 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const plugin = require('tailwindcss/plugin'); 2 | const _ = require('lodash'); 3 | 4 | module.exports = plugin(function({ theme, variants, e, addUtilities }) { 5 | const filterUtilities = _.fromPairs( 6 | _.map(theme('filter'), (value, modifier) => { 7 | return [ 8 | `.${e(`filter-${modifier}`)}`, 9 | { 10 | filter: value, 11 | }, 12 | ]; 13 | }) 14 | ); 15 | 16 | const backdropFilterUtilities = _.fromPairs( 17 | _.map(theme('backdropFilter'), (value, modifier) => { 18 | return [ 19 | `.${e(`backdrop-${modifier}`)}`, 20 | { 21 | backdropFilter: value, 22 | }, 23 | ]; 24 | }) 25 | ); 26 | 27 | addUtilities(filterUtilities, variants('filter')); 28 | addUtilities(backdropFilterUtilities, variants('backdropFilter')); 29 | }, { 30 | theme: { 31 | filter: {}, 32 | backdropFilter: {}, 33 | }, 34 | variants: { 35 | filter: ['responsive'], 36 | backdropFilter: ['responsive'], 37 | }, 38 | }); 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tailwindcss-filters", 3 | "version": "3.0.0", 4 | "description": "Tailwind CSS plugin to generate filter and backdrop filter utilities", 5 | "author": "Benoît Rouleau ", 6 | "license": "ISC", 7 | "repository": "https://github.com/benface/tailwindcss-filters.git", 8 | "bugs": "https://github.com/benface/tailwindcss-filters/issues", 9 | "homepage": "https://github.com/benface/tailwindcss-filters", 10 | "scripts": { 11 | "test": "jest", 12 | "release": "f(){ release-it $1 && github-release-from-changelog ;};f" 13 | }, 14 | "dependencies": { 15 | "lodash": "^4.17.19" 16 | }, 17 | "devDependencies": { 18 | "github-release-from-changelog": "^2.1.1", 19 | "jest": "^26.1.0", 20 | "jest-matcher-css": "^1.1.0", 21 | "postcss": "^7.0.32", 22 | "release-it": "^13.6.5", 23 | "tailwindcss": "^1.5.1" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | const cssMatcher = require('jest-matcher-css'); 3 | const postcss = require('postcss'); 4 | const tailwindcss = require('tailwindcss'); 5 | const filtersPlugin = require('./index.js'); 6 | 7 | const generatePluginCss = (config) => { 8 | return postcss( 9 | tailwindcss( 10 | _.merge({ 11 | theme: { 12 | screens: { 13 | 'sm': '640px', 14 | }, 15 | }, 16 | corePlugins: false, 17 | plugins: [ 18 | filtersPlugin, 19 | ], 20 | }, config) 21 | ) 22 | ) 23 | .process('@tailwind utilities', { 24 | from: undefined, 25 | }) 26 | .then(result => { 27 | return result.css; 28 | }); 29 | }; 30 | 31 | expect.extend({ 32 | toMatchCss: cssMatcher, 33 | }); 34 | 35 | test('there is no output by default', () => { 36 | return generatePluginCss().then(css => { 37 | expect(css).toMatchCss(` 38 | @media (min-width: 640px) { 39 | } 40 | `); 41 | }); 42 | }); 43 | 44 | test('utilities can be customized', () => { 45 | return generatePluginCss({ 46 | theme: { 47 | filter: { 48 | 'none': 'none', 49 | 'grayscale': 'grayscale(1)', 50 | 'invert': 'invert(1)', 51 | 'sepia': 'sepia(1)', 52 | }, 53 | backdropFilter: { 54 | 'none': 'none', 55 | 'blur': 'blur(20px)', 56 | }, 57 | }, 58 | }).then(css => { 59 | expect(css).toMatchCss(` 60 | .filter-none { 61 | filter: none; 62 | } 63 | .filter-grayscale { 64 | filter: grayscale(1); 65 | } 66 | .filter-invert { 67 | filter: invert(1); 68 | } 69 | .filter-sepia { 70 | filter: sepia(1); 71 | } 72 | .backdrop-none { 73 | backdrop-filter: none; 74 | } 75 | .backdrop-blur { 76 | backdrop-filter: blur(20px); 77 | } 78 | @media (min-width: 640px) { 79 | .sm\\:filter-none { 80 | filter: none; 81 | } 82 | .sm\\:filter-grayscale { 83 | filter: grayscale(1); 84 | } 85 | .sm\\:filter-invert { 86 | filter: invert(1); 87 | } 88 | .sm\\:filter-sepia { 89 | filter: sepia(1); 90 | } 91 | .sm\\:backdrop-none { 92 | backdrop-filter: none; 93 | } 94 | .sm\\:backdrop-blur { 95 | backdrop-filter: blur(20px); 96 | } 97 | } 98 | `); 99 | }); 100 | }); 101 | 102 | test('variants can be customized', () => { 103 | return generatePluginCss({ 104 | theme: { 105 | filter: { 106 | 'none': 'none', 107 | 'grayscale': 'grayscale(1)', 108 | }, 109 | backdropFilter: { 110 | 'none': 'none', 111 | 'blur': 'blur(20px)', 112 | }, 113 | }, 114 | variants: { 115 | filter: ['hover'], 116 | backdropFilter: ['active'], 117 | }, 118 | }).then(css => { 119 | expect(css).toMatchCss(` 120 | .filter-none { 121 | filter: none; 122 | } 123 | .filter-grayscale { 124 | filter: grayscale(1); 125 | } 126 | .hover\\:filter-none:hover { 127 | filter: none; 128 | } 129 | .hover\\:filter-grayscale:hover { 130 | filter: grayscale(1); 131 | } 132 | .backdrop-none { 133 | backdrop-filter: none; 134 | } 135 | .backdrop-blur { 136 | backdrop-filter: blur(20px); 137 | } 138 | .active\\:backdrop-none:active { 139 | backdrop-filter: none; 140 | } 141 | .active\\:backdrop-blur:active { 142 | backdrop-filter: blur(20px); 143 | } 144 | `); 145 | }); 146 | }); 147 | --------------------------------------------------------------------------------