├── .eslintrc.json ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── dist ├── index.cjs ├── index.cjs.map ├── index.modern.js ├── index.modern.js.map ├── index.module.js ├── index.module.js.map ├── index.umd.js ├── index.umd.js.map └── types │ └── index.d.ts ├── index.ts ├── package-lock.json ├── package.json └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"], 8 | "overrides": [], 9 | "parser": "@typescript-eslint/parser", 10 | "parserOptions": { 11 | "ecmaVersion": "latest", 12 | "sourceType": "module" 13 | }, 14 | "plugins": ["@typescript-eslint", "prettier"], 15 | "rules": { 16 | "prettier/prettier": 1, 17 | "@typescript-eslint/no-explicit-any": "off" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | README.md 2 | dist 3 | tsconfig.json -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5", 4 | "arrowParens": "always", 5 | "bracketSameLine": false, 6 | "printWidth": 120, 7 | "tabWidth": 2, 8 | "semi": true 9 | } 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Brandon McConnell 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Multi for Tailwind CSS

2 | 3 |
4 | 5 | [![minified size](https://img.shields.io/bundlephobia/min/tailwindcss-multi)](https://bundlephobia.com/package/tailwindcss-multi) 6 | [![license](https://img.shields.io/github/license/brandonmcconnell/tailwindcss-multi?label=license)](https://github.com/brandonmcconnell/tailwindcss-multi/blob/main/LICENSE) 7 | [![version](https://img.shields.io/npm/v/tailwindcss-multi)](https://www.npmjs.com/package/tailwindcss-multi) 8 | [![twitter](https://img.shields.io/twitter/follow/branmcconnell)](https://twitter.com/branmcconnell) 9 | 10 |
11 | 12 | `tailwindcss-multi` is a plugin for Tailwind CSS that introduces the `multi` directive, a utility that allows you to group utility classes together. This simplifies your HTML and improves readability of your Tailwind CSS code. 13 | 14 | ### Table of Contents 15 | - [Installation](#installation) 16 | - [Usage](#usage) 17 | - [Nested variants (quoted values)](#nested-variants-quoted-values) 18 | - [Quotes](#quotes) 19 | - [Why use `tailwindcss-multi`](#why-use-tailwindcss-multi) 20 | - [Quoted values explanation](#quoted-values-explanation) 21 | - [What's next?](#whats-next) 22 | 23 | > [!IMPORTANT] 24 | > Update to `@latest` to ensure compatibility with newer versions of Tailwind CSS. 25 | > 26 | > **Syntax change:** If you use a value inside `multi-[...]` that includes a colon `:`, the value between the brackets must be quoted, due to a breaking change introduced in Tailwind CSS v3.3.6. 27 | > ``` 28 | > ✅ hover:multi-[bg-red-500;text-white] // no `:`, so quotes are NOT NEEDED 29 | > 30 | > ❌ hover:multi-[hover:bg-red-500;text-white] // using `:`, so quotes are NEEDED 🚨 31 | > ✅ hover:multi-['hover:bg-red-500;text-white'] 32 | > ^ ^ 33 | > ``` 34 | > See the [Quoted values explanation](#quoted-values-explanation) section for more information. 35 | 36 | ## Installation 37 | 38 | You can install the plugin via npm: 39 | 40 | ```bash 41 | npm install tailwindcss-multi 42 | ``` 43 | 44 | Then, include it in your `tailwind.config.js`: 45 | 46 | ```js 47 | module.exports = { 48 | plugins: [ 49 | require('tailwindcss-multi'), 50 | ] 51 | } 52 | ``` 53 | 54 | ## Usage 55 | 56 | The plugin provides a `multi` directive, allowing you to group multiple utility classes: 57 | 58 | ```html 59 |
60 | When hovered, this text is white and the background is red. 61 |
62 | ``` 63 | [View this example on Tailwind Play](https://play.tailwindcss.com/En0nuy58kq) 64 | 65 | The directive accepts a semicolon-delimited list of utility classes and applies them to the selected element. A key feature of `tailwindcss-multi` is its support for arbitrary values, which are not limited to predefined classes in Tailwind CSS. 66 | 67 | ### Nested variants (quoted values) 68 | 69 | When a value includes a colon `:`, the value must be quoted to ensure compatibility with newer versions of Tailwind CSS. This is due to a breaking change introduced in Tailwind CSS v3.3.6 ([explanation](#quoted-values-explanation)). 70 | 71 | > [!NOTE] 72 | > One exception to this `:` rule is if the colon is used for a CSS property-value pair, like `multi-[[font-family:times]]`. In this case, quotes are not needed, as this is the expected case for using a colon `:`, which is actually what warranted the breaking change in the first place. 73 | > 74 | > So this is valid: 75 | > ```html 76 | >
...
77 | > ``` 78 | 79 | #### Quotes 80 | 81 | Valid quotes include single `'`, double `"`, and backticks `` ` ``. The choice of quote is up to you, per usage. Quotes chosen must be kept consistent within the same value. 82 | 83 | ```html 84 | 85 |
...
86 |
...
87 |
...
88 | 89 | 90 |
...
91 |
...
92 | 93 | ``` 94 | 95 | ## Why use `tailwindcss-multi` 96 | 97 | In some cases, you may need to apply several utilities to a long or convoluted variant or even chain of variants, which can start to look like this: 98 | 99 | ```html 100 |
101 | When hovered, this text will appear bold, red, and in `times` font. 102 |
103 | ``` 104 | [View this example on Tailwind Play](https://play.tailwindcss.com/A3EoS45R14) 105 | 106 | This can be difficult to read and understand, especially when the number of utilities increases. 107 | 108 | By employing the `multi` directive, you can group related utility classes by variant, providing clearer insights into your code's function. Below is an example that demonstrates the flexibility of the `multi` directive, demonstrating its ability to support not only multiple utilities, but partially and fully arbitrary values: 109 | 110 | ```html 111 |
112 | When hovered, this text will appear bold, red, and in `times` font. 113 |
114 | ``` 115 | [View this example on Tailwind Play](https://play.tailwindcss.com/NLgm3mPUkf) 116 | 117 | This is… 118 | 119 | ✨ GREAT for consolidating utilities under long & ideally unique variants 👏🏼 120 | 121 | 😬 NOT great for keeping the compile size small if you use it with commonly used variants 👀 122 | 123 | ## Quoted values explanation 124 | 125 | ```html 126 | ⚫️ `:` not present -> quotes OPTIONAL 127 | ✅
...
128 | 129 | ⚫️ `:` used in property-value pair -> quotes OPTIONAL 130 | ✅
...
131 | 132 | ⚫️ `:` used in nested variant -> quotes REQUIRED 🚨 133 | ❌
...
134 | ✅
...
135 | ``` 136 | [View a similar example on Tailwind Play](https://play.tailwindcss.com/yuNA3wIvuH) 137 | 138 | The release of [Tailwind CSS v3.3.6](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.3.6) (on Dec 4, 2023) introduced breaking changes that made the original syntax of Multi for Tailwind CSS incompatible with newer versions of Tailwind CSS. 139 | 140 | See [tailwindlabs/tailwindcss#13473](https://github.com/tailwindlabs/tailwindcss/issues/13473) for the discussion that led to this new syntax. 141 | 142 | This change required a slight tweak to the syntax of the `multi` directive. When using a value that includes a colon `:`, instead of using `multi-[...]`, use `multi-['...']` (with a quoted value between the brackets) to pass the grouped utilities together as a string. 143 | 144 | > [!NOTE] 145 | > One exception to this `:` rule is if the colon is used for a CSS property-value pair, like `multi-[[font-family:times]]`. In this case, quotes are not needed, as this is the expected case for using a colon `:`, which is actually what warranted the breaking change in the first place. 146 | > 147 | > So this is valid: 148 | > ```html 149 | >
...
150 | > ``` 151 | 152 | Versions of Tailwind CSS thereafter (v3.3.6+) are now incompatible with versions of the original unquoted syntax for this plugin (pre-v0.2.0) for values that contain a colon `:`. Update to `@latest` to ensure compatibility. This new version syntax is reverse-compatible with versions of Tailwind CSS prior to v3.3.6 as well. 153 | 154 | Passing the joined strings together as a string allows the Tailwind CSS parser (again, in Tailwind CSS v3.3.6+) to see the value as a valid CSS value and process it as expected. 155 | 156 | ## What's next? 157 | 158 | I think the next natural step in the evolution of Multi for Tailwind CSS is to refactor the plugin as a vite/postcss plugin, as either a supplementary or alternate version of the current Tailwind plugin. 159 | 160 | This would allow the plugin to… 161 | * once again use a custom syntax, without ever needing quotes 162 | * split any joined utilities into separate classes before the Tailwind CSS parser processes them 163 | 164 | If such a plugin could effectively split classes used with the `multi` directive, it would radically reduce the compile size of the CSS output, as the Tailwind CSS parser would only process the classes used within the `multi`, not the `multi` itself. 165 | 166 | For example, consider the following markup: 167 | 168 | ```html 169 |
...
170 |
...
171 |
...
172 | ``` 173 | 174 | This generates all of these rules: 175 | ```scss 176 | @media (min-width: 640px) { 177 | .sm\:hover\:bg-red-500:hover { /* 2 lines */ } 178 | .sm\:hover\:text-white:hover { /* 2 lines */ } 179 | .sm\:hover\:multi-\[bg-red-500\;text-white\]:hover { /* 4 lines */ } 180 | .sm\:hover\:multi-\[text-white\;bg-red-500\]:hover { /* 4 lines */ } 181 | } 182 | ``` 183 | 184 | As a vite plugin, that markup would be split into individual utilities like this: 185 | 186 | ```html 187 |
...
188 |
...
189 |
...
190 | ``` 191 | 192 | This post-split example would only generates these rules: 193 | 194 | ```scss 195 | @media (min-width: 640px) { 196 | .sm\:hover\:bg-red-500:hover { /* 2 lines */ } 197 | .sm\:hover\:text-white:hover { /* 2 lines */ } 198 | } 199 | ``` 200 | 201 | That's down from 22 lines of output CSS to 10 lines of code, and the same minimal output that would be generated without using the `multi` directive at all. 202 | 203 | The strongest argument against using `multi` is output CSS bloat. This is I caution strongly against throughout this README and provide tips for avoiding. 204 | 205 | It's also something [**@adamwathan**](https://github.com/adamwathan), the creator of Tailwind CSS, discussed at length in [this legendary thread](https://x.com/adamwathan/status/1461519820411789314) when he and his team explored the same problem space from a different angle. 206 | 207 | Notice the nicer syntax in that linked thread. Something like that _**might**_ be possible with a vite/postcss plugin. 208 | 209 | This… 210 | ```html 211 |
...
212 | ``` 213 | 214 | …could become something like this: 215 | ```html 216 |
...
217 | ``` 218 | 219 | --- 220 | 221 | I hope you find `tailwindcss-multi` a valuable addition to your projects. If you have any issues or suggestions, don't hesitate to open an issue or pull request. 222 | 223 | If you liked this, you might also like my other Tailwind CSS plugins: 224 | * [tailwindcss-signals](https://github.com/brandonmcconnell/tailwindcss-signals): Apply styles based on parent or ancestor state, a state-driven alterative to groups 225 | * [tailwindcss-members](https://github.com/brandonmcconnell/tailwindcss-members): Apply styles based on child or descendant state, the inverse of groups 226 | * [tailwindcss-mixins](https://github.com/brandonmcconnell/tailwindcss-mixins): Construct reusable & aliased sets of utilities inline 227 | * [tailwindcss-selector-patterns](https://github.com/brandonmcconnell/tailwindcss-selector-patterns): Dynamic CSS selector patterns 228 | * [tailwindcss-js](https://github.com/brandonmcconnell/tailwindcss-js): Effortless build-time JS script injection 229 | * [tailwindcss-directional-shadows](https://github.com/brandonmcconnell/tailwindcss-directional-shadows): Supercharge your shadow utilities with added directional support (includes directional `shadow-border` utilities too ✨) 230 | * [tailwindcss-default-shades](https://github.com/brandonmcconnell/tailwindcss-default-shades): Default shades for simpler color utility classes 231 | * [tailwind-lerp-colors](https://github.com/brandonmcconnell/tailwind-lerp-colors): Expand your color horizons and take the fuss out of generating new—or expanding existing—color palettes 232 | -------------------------------------------------------------------------------- /dist/index.cjs: -------------------------------------------------------------------------------- 1 | function e(e){var t={exports:{}};return e(t,t.exports),t.exports}var t=e(function(e,t){function n(e,t){return{handler:e,config:t}}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return r}}),n.withOptions=function(e,t=(()=>({}))){const n=function(n){return{__options:n,handler:e(n),config:t(n)}};return n.__isOptionsFunction=!0,n.__pluginFunction=e,n.__configFunction=t,n};const r=n}),n=e(function(e,n){function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"default",{enumerable:!0,get:function(){return u}});const u=/*#__PURE__*/r(t).default}),r=(0,(n.__esModule?n:{default:n}).default)(function(e){(0,e.matchUtilities)({multi:function(e){var t;if(!e[0])return{};var n=[e[0],e.slice(-1)[0]],r=["'",'"',"`"].includes(e[0]);if(r&&(e.length<3||n[0]!==n[1]))throw new Error("Invalid multi value: `"+e+"`. Quoted values must use matching quotes (e.g. ['...'], [\"...\"], or [`...`]).");var u=e.slice.apply(e,r?[1,-1]:[]).split(/;(?![^[]*\])/).filter(function(e){return e.trim().length}).map(function(e){return e.replace(/_/g,"\\_").replace(/ /g,"_")}).join(" ");return u.trim()?((t={})["@apply "+u]={},t):{}}})});module.exports=r; 2 | //# sourceMappingURL=index.cjs.map 3 | -------------------------------------------------------------------------------- /dist/index.cjs.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.cjs","sources":["../node_modules/tailwindcss/lib/util/createPlugin.js","../node_modules/tailwindcss/lib/public/create-plugin.js","../index.ts","../node_modules/tailwindcss/plugin.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"default\", {\n enumerable: true,\n get: function() {\n return _default;\n }\n});\nfunction createPlugin(plugin, config) {\n return {\n handler: plugin,\n config\n };\n}\ncreatePlugin.withOptions = function(pluginFunction, configFunction = ()=>({})) {\n const optionsFunction = function(options) {\n return {\n __options: options,\n handler: pluginFunction(options),\n config: configFunction(options)\n };\n };\n optionsFunction.__isOptionsFunction = true;\n // Expose plugin dependencies so that `object-hash` returns a different\n // value if anything here changes, to ensure a rebuild is triggered.\n optionsFunction.__pluginFunction = pluginFunction;\n optionsFunction.__configFunction = configFunction;\n return optionsFunction;\n};\nconst _default = createPlugin;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"default\", {\n enumerable: true,\n get: function() {\n return _default;\n }\n});\nconst _createPlugin = /*#__PURE__*/ _interop_require_default(require(\"../util/createPlugin\"));\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : {\n default: obj\n };\n}\nconst _default = _createPlugin.default;\n","import plugin from 'tailwindcss/plugin.js';\n\nexport default plugin(({ matchUtilities }) => {\n matchUtilities({\n multi: (value) => {\n if (!value[0]) return {};\n const validQuotes = [`'`, `\"`, `\\``];\n const ends = [value[0], value.slice(-1)[0]];\n const valueIsQuoted = validQuotes.includes(value[0]);\n if (valueIsQuoted && (value.length < 3 || ends[0] !== ends[1])) {\n throw new Error(\n `Invalid multi value: \\`${value}\\`. Quoted values must use matching quotes (e.g. ['...'], [\"...\"], or [\\`...\\`]).`\n );\n }\n const escape = (str: string) => str.replace(/_/g, '\\\\_').replace(/ /g, '_');\n const delimiter = /;(?![^[]*\\])/;\n const utilities = value\n .slice(...(valueIsQuoted ? [1, -1] : []))\n .split(delimiter)\n .filter((str) => str.trim().length)\n .map(escape)\n .join(' ');\n return !utilities.trim()\n ? {}\n : {\n [`@apply ${utilities}`]: {},\n };\n },\n });\n});\n","let createPlugin = require('./lib/public/create-plugin')\nmodule.exports = (createPlugin.__esModule ? createPlugin : { default: createPlugin }).default\n"],"names":["createPlugin","plugin","config","handler","Object","defineProperty","exports","value","enumerable","get","_default","withOptions","pluginFunction","configFunction","optionsFunction","options","__options","__isOptionsFunction","__pluginFunction","__configFunction","_interop_require_default","obj","__esModule","default","require$$0","_ref","matchUtilities","multi","_ref2","ends","slice","valueIsQuoted","includes","length","Error","utilities","apply","split","filter","str","trim","map","replace","join"],"mappings":"uFAUA,SAASA,EAAaC,EAAQC,GAC1B,MAAO,CACHC,QAASF,EACTC,SAER,CAdAE,OAAOC,eAAwBC,EAAA,aAAc,CACzCC,OAAO,IAEXH,OAAOC,eAAeC,EAAS,UAAW,CACtCE,YAAY,EACZC,IAAK,WACD,OAAOC,CACV,IAQLV,EAAaW,YAAc,SAASC,EAAgBC,EAAiB,MAAA,CAAO,KACxE,MAAMC,EAAkB,SAASC,GAC7B,MAAO,CACHC,UAAWD,EACXZ,QAASS,EAAeG,GACxBb,OAAQW,EAAeE,GAEnC,EAMI,OALAD,EAAgBG,qBAAsB,EAGtCH,EAAgBI,iBAAmBN,EACnCE,EAAgBK,iBAAmBN,EAC5BC,CACX,EACA,MAAMJ,EAAWV,sBCpBjB,SAASoB,EAAyBC,GAC9B,OAAOA,GAAOA,EAAIC,WAAaD,EAAM,CACjCE,QAASF,EAEjB,CAdAjB,OAAOC,eAAwBC,EAAA,aAAc,CACzCC,OAAO,IAEXH,OAAOC,eAAeC,EAAS,UAAW,CACtCE,YAAY,EACZC,IAAK,WACD,OAAOC,CACV,IAQL,MAAMA,eAN8BU,EAAyBI,GAM9BD,UCdhBtB,GAAAA,GCDGD,EAAasB,WAAatB,EAAe,CAAEuB,QAASvB,IAAgBuB,SDChE,SAAAE,IACpBC,EADqCD,EAAdC,gBACR,CACbC,MAAO,SAACpB,GAAS,IAAAqB,EACf,IAAKrB,EAAM,GAAI,MAAO,CAAE,EACxB,IACMsB,EAAO,CAACtB,EAAM,GAAIA,EAAMuB,OAAO,GAAG,IAClCC,EAFc,CAAA,IAAA,IAAA,KAEcC,SAASzB,EAAM,IACjD,GAAIwB,IAAkBxB,EAAM0B,OAAS,GAAKJ,EAAK,KAAOA,EAAK,IACzD,MAAM,IAAIK,MACkB3B,yBAAAA,EAAwF,oFAGtH,IAEM4B,EAAY5B,EACfuB,MAAKM,MADU7B,EACLwB,EAAgB,CAAC,GAAI,GAAK,IACpCM,MAHe,gBAIfC,OAAO,SAACC,GAAG,OAAKA,EAAIC,OAAOP,MAAM,GACjCQ,IANY,SAACF,GAAgB,OAAAA,EAAIG,QAAQ,KAAM,OAAOA,QAAQ,KAAM,IAAI,GAOxEC,KAAK,KACR,OAAQR,EAAUK,SACZZ,EAAA,CAAA,GAEWO,UAAAA,GAAc,CAAE,EAAAP,GAF7B,CAAA,CAIN,GAEJ"} -------------------------------------------------------------------------------- /dist/index.modern.js: -------------------------------------------------------------------------------- 1 | function e(e){var t={exports:{}};return e(t,t.exports),t.exports}var t=e(function(e,t){function n(e,t){return{handler:e,config:t}}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return r}}),n.withOptions=function(e,t=(()=>({}))){const n=function(n){return{__options:n,handler:e(n),config:t(n)}};return n.__isOptionsFunction=!0,n.__pluginFunction=e,n.__configFunction=t,n};const r=n}),n=e(function(e,n){function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"default",{enumerable:!0,get:function(){return u}});const u=/*#__PURE__*/r(t).default}),r=(0,(n.__esModule?n:{default:n}).default)(({matchUtilities:e})=>{e({multi:e=>{if(!e[0])return{};const t=[e[0],e.slice(-1)[0]],n=["'",'"',"`"].includes(e[0]);if(n&&(e.length<3||t[0]!==t[1]))throw new Error(`Invalid multi value: \`${e}\`. Quoted values must use matching quotes (e.g. ['...'], ["..."], or [\`...\`]).`);const r=e.slice(...n?[1,-1]:[]).split(/;(?![^[]*\])/).filter(e=>e.trim().length).map(e=>e.replace(/_/g,"\\_").replace(/ /g,"_")).join(" ");return r.trim()?{[`@apply ${r}`]:{}}:{}}})});export{r as default}; 2 | //# sourceMappingURL=index.modern.js.map 3 | -------------------------------------------------------------------------------- /dist/index.modern.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.modern.js","sources":["../node_modules/tailwindcss/lib/util/createPlugin.js","../node_modules/tailwindcss/lib/public/create-plugin.js","../index.ts","../node_modules/tailwindcss/plugin.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"default\", {\n enumerable: true,\n get: function() {\n return _default;\n }\n});\nfunction createPlugin(plugin, config) {\n return {\n handler: plugin,\n config\n };\n}\ncreatePlugin.withOptions = function(pluginFunction, configFunction = ()=>({})) {\n const optionsFunction = function(options) {\n return {\n __options: options,\n handler: pluginFunction(options),\n config: configFunction(options)\n };\n };\n optionsFunction.__isOptionsFunction = true;\n // Expose plugin dependencies so that `object-hash` returns a different\n // value if anything here changes, to ensure a rebuild is triggered.\n optionsFunction.__pluginFunction = pluginFunction;\n optionsFunction.__configFunction = configFunction;\n return optionsFunction;\n};\nconst _default = createPlugin;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"default\", {\n enumerable: true,\n get: function() {\n return _default;\n }\n});\nconst _createPlugin = /*#__PURE__*/ _interop_require_default(require(\"../util/createPlugin\"));\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : {\n default: obj\n };\n}\nconst _default = _createPlugin.default;\n","import plugin from 'tailwindcss/plugin.js';\n\nexport default plugin(({ matchUtilities }) => {\n matchUtilities({\n multi: (value) => {\n if (!value[0]) return {};\n const validQuotes = [`'`, `\"`, `\\``];\n const ends = [value[0], value.slice(-1)[0]];\n const valueIsQuoted = validQuotes.includes(value[0]);\n if (valueIsQuoted && (value.length < 3 || ends[0] !== ends[1])) {\n throw new Error(\n `Invalid multi value: \\`${value}\\`. Quoted values must use matching quotes (e.g. ['...'], [\"...\"], or [\\`...\\`]).`\n );\n }\n const escape = (str: string) => str.replace(/_/g, '\\\\_').replace(/ /g, '_');\n const delimiter = /;(?![^[]*\\])/;\n const utilities = value\n .slice(...(valueIsQuoted ? [1, -1] : []))\n .split(delimiter)\n .filter((str) => str.trim().length)\n .map(escape)\n .join(' ');\n return !utilities.trim()\n ? {}\n : {\n [`@apply ${utilities}`]: {},\n };\n },\n });\n});\n","let createPlugin = require('./lib/public/create-plugin')\nmodule.exports = (createPlugin.__esModule ? createPlugin : { default: createPlugin }).default\n"],"names":["createPlugin","plugin","config","handler","Object","defineProperty","exports","value","enumerable","get","_default","withOptions","pluginFunction","configFunction","optionsFunction","options","__options","__isOptionsFunction","__pluginFunction","__configFunction","_interop_require_default","obj","__esModule","default","require$$0","matchUtilities","multi","ends","slice","valueIsQuoted","includes","length","Error","utilities","split","filter","str","trim","map","replace","join"],"mappings":"uFAUA,SAASA,EAAaC,EAAQC,GAC1B,MAAO,CACHC,QAASF,EACTC,SAER,CAdAE,OAAOC,eAAwBC,EAAA,aAAc,CACzCC,OAAO,IAEXH,OAAOC,eAAeC,EAAS,UAAW,CACtCE,YAAY,EACZC,IAAK,WACD,OAAOC,CACV,IAQLV,EAAaW,YAAc,SAASC,EAAgBC,EAAiB,MAAA,CAAO,KACxE,MAAMC,EAAkB,SAASC,GAC7B,MAAO,CACHC,UAAWD,EACXZ,QAASS,EAAeG,GACxBb,OAAQW,EAAeE,GAEnC,EAMI,OALAD,EAAgBG,qBAAsB,EAGtCH,EAAgBI,iBAAmBN,EACnCE,EAAgBK,iBAAmBN,EAC5BC,CACX,EACA,MAAMJ,EAAWV,sBCpBjB,SAASoB,EAAyBC,GAC9B,OAAOA,GAAOA,EAAIC,WAAaD,EAAM,CACjCE,QAASF,EAEjB,CAdAjB,OAAOC,eAAwBC,EAAA,aAAc,CACzCC,OAAO,IAEXH,OAAOC,eAAeC,EAAS,UAAW,CACtCE,YAAY,EACZC,IAAK,WACD,OAAOC,CACV,IAQL,MAAMA,eAN8BU,EAAyBI,GAM9BD,UCdhBtB,GAAAA,GCDGD,EAAasB,WAAatB,EAAe,CAAEuB,QAASvB,IAAgBuB,SDChE,EAAGE,qBACvBA,EAAe,CACbC,MAAQnB,IACN,IAAKA,EAAM,GAAI,MAAO,GACtB,MACMoB,EAAO,CAACpB,EAAM,GAAIA,EAAMqB,OAAO,GAAG,IAClCC,EAFc,CAAC,IAAQ,IAAM,KAEDC,SAASvB,EAAM,IACjD,GAAIsB,IAAkBtB,EAAMwB,OAAS,GAAKJ,EAAK,KAAOA,EAAK,IACzD,MAAM,IAAIK,gCACkBzB,sFAG9B,MAEM0B,EAAY1B,EACfqB,SAAUC,EAAgB,CAAC,GAAI,GAAK,IACpCK,MAHe,gBAIfC,OAAQC,GAAQA,EAAIC,OAAON,QAC3BO,IANaF,GAAgBA,EAAIG,QAAQ,KAAM,OAAOA,QAAQ,KAAM,MAOpEC,KAAK,KACR,OAAQP,EAAUI,OAEd,CACE,CAAW,UAAAJ,KAAc,CAAA,GAF3B,CAAA,IAMV"} -------------------------------------------------------------------------------- /dist/index.module.js: -------------------------------------------------------------------------------- 1 | function e(e){var t={exports:{}};return e(t,t.exports),t.exports}var t=e(function(e,t){function n(e,t){return{handler:e,config:t}}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return r}}),n.withOptions=function(e,t=(()=>({}))){const n=function(n){return{__options:n,handler:e(n),config:t(n)}};return n.__isOptionsFunction=!0,n.__pluginFunction=e,n.__configFunction=t,n};const r=n}),n=e(function(e,n){function r(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"default",{enumerable:!0,get:function(){return u}});const u=/*#__PURE__*/r(t).default}),r=(0,(n.__esModule?n:{default:n}).default)(function(e){(0,e.matchUtilities)({multi:function(e){var t;if(!e[0])return{};var n=[e[0],e.slice(-1)[0]],r=["'",'"',"`"].includes(e[0]);if(r&&(e.length<3||n[0]!==n[1]))throw new Error("Invalid multi value: `"+e+"`. Quoted values must use matching quotes (e.g. ['...'], [\"...\"], or [`...`]).");var u=e.slice.apply(e,r?[1,-1]:[]).split(/;(?![^[]*\])/).filter(function(e){return e.trim().length}).map(function(e){return e.replace(/_/g,"\\_").replace(/ /g,"_")}).join(" ");return u.trim()?((t={})["@apply "+u]={},t):{}}})});export{r as default}; 2 | //# sourceMappingURL=index.module.js.map 3 | -------------------------------------------------------------------------------- /dist/index.module.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.module.js","sources":["../node_modules/tailwindcss/lib/util/createPlugin.js","../node_modules/tailwindcss/lib/public/create-plugin.js","../index.ts","../node_modules/tailwindcss/plugin.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"default\", {\n enumerable: true,\n get: function() {\n return _default;\n }\n});\nfunction createPlugin(plugin, config) {\n return {\n handler: plugin,\n config\n };\n}\ncreatePlugin.withOptions = function(pluginFunction, configFunction = ()=>({})) {\n const optionsFunction = function(options) {\n return {\n __options: options,\n handler: pluginFunction(options),\n config: configFunction(options)\n };\n };\n optionsFunction.__isOptionsFunction = true;\n // Expose plugin dependencies so that `object-hash` returns a different\n // value if anything here changes, to ensure a rebuild is triggered.\n optionsFunction.__pluginFunction = pluginFunction;\n optionsFunction.__configFunction = configFunction;\n return optionsFunction;\n};\nconst _default = createPlugin;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"default\", {\n enumerable: true,\n get: function() {\n return _default;\n }\n});\nconst _createPlugin = /*#__PURE__*/ _interop_require_default(require(\"../util/createPlugin\"));\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : {\n default: obj\n };\n}\nconst _default = _createPlugin.default;\n","import plugin from 'tailwindcss/plugin.js';\n\nexport default plugin(({ matchUtilities }) => {\n matchUtilities({\n multi: (value) => {\n if (!value[0]) return {};\n const validQuotes = [`'`, `\"`, `\\``];\n const ends = [value[0], value.slice(-1)[0]];\n const valueIsQuoted = validQuotes.includes(value[0]);\n if (valueIsQuoted && (value.length < 3 || ends[0] !== ends[1])) {\n throw new Error(\n `Invalid multi value: \\`${value}\\`. Quoted values must use matching quotes (e.g. ['...'], [\"...\"], or [\\`...\\`]).`\n );\n }\n const escape = (str: string) => str.replace(/_/g, '\\\\_').replace(/ /g, '_');\n const delimiter = /;(?![^[]*\\])/;\n const utilities = value\n .slice(...(valueIsQuoted ? [1, -1] : []))\n .split(delimiter)\n .filter((str) => str.trim().length)\n .map(escape)\n .join(' ');\n return !utilities.trim()\n ? {}\n : {\n [`@apply ${utilities}`]: {},\n };\n },\n });\n});\n","let createPlugin = require('./lib/public/create-plugin')\nmodule.exports = (createPlugin.__esModule ? createPlugin : { default: createPlugin }).default\n"],"names":["createPlugin","plugin","config","handler","Object","defineProperty","exports","value","enumerable","get","_default","withOptions","pluginFunction","configFunction","optionsFunction","options","__options","__isOptionsFunction","__pluginFunction","__configFunction","_interop_require_default","obj","__esModule","default","require$$0","_ref","matchUtilities","multi","_ref2","ends","slice","valueIsQuoted","includes","length","Error","utilities","apply","split","filter","str","trim","map","replace","join"],"mappings":"uFAUA,SAASA,EAAaC,EAAQC,GAC1B,MAAO,CACHC,QAASF,EACTC,SAER,CAdAE,OAAOC,eAAwBC,EAAA,aAAc,CACzCC,OAAO,IAEXH,OAAOC,eAAeC,EAAS,UAAW,CACtCE,YAAY,EACZC,IAAK,WACD,OAAOC,CACV,IAQLV,EAAaW,YAAc,SAASC,EAAgBC,EAAiB,MAAA,CAAO,KACxE,MAAMC,EAAkB,SAASC,GAC7B,MAAO,CACHC,UAAWD,EACXZ,QAASS,EAAeG,GACxBb,OAAQW,EAAeE,GAEnC,EAMI,OALAD,EAAgBG,qBAAsB,EAGtCH,EAAgBI,iBAAmBN,EACnCE,EAAgBK,iBAAmBN,EAC5BC,CACX,EACA,MAAMJ,EAAWV,sBCpBjB,SAASoB,EAAyBC,GAC9B,OAAOA,GAAOA,EAAIC,WAAaD,EAAM,CACjCE,QAASF,EAEjB,CAdAjB,OAAOC,eAAwBC,EAAA,aAAc,CACzCC,OAAO,IAEXH,OAAOC,eAAeC,EAAS,UAAW,CACtCE,YAAY,EACZC,IAAK,WACD,OAAOC,CACV,IAQL,MAAMA,eAN8BU,EAAyBI,GAM9BD,UCdhBtB,GAAAA,GCDGD,EAAasB,WAAatB,EAAe,CAAEuB,QAASvB,IAAgBuB,SDChE,SAAAE,IACpBC,EADqCD,EAAdC,gBACR,CACbC,MAAO,SAACpB,GAAS,IAAAqB,EACf,IAAKrB,EAAM,GAAI,MAAO,CAAE,EACxB,IACMsB,EAAO,CAACtB,EAAM,GAAIA,EAAMuB,OAAO,GAAG,IAClCC,EAFc,CAAA,IAAA,IAAA,KAEcC,SAASzB,EAAM,IACjD,GAAIwB,IAAkBxB,EAAM0B,OAAS,GAAKJ,EAAK,KAAOA,EAAK,IACzD,MAAM,IAAIK,MACkB3B,yBAAAA,EAAwF,oFAGtH,IAEM4B,EAAY5B,EACfuB,MAAKM,MADU7B,EACLwB,EAAgB,CAAC,GAAI,GAAK,IACpCM,MAHe,gBAIfC,OAAO,SAACC,GAAG,OAAKA,EAAIC,OAAOP,MAAM,GACjCQ,IANY,SAACF,GAAgB,OAAAA,EAAIG,QAAQ,KAAM,OAAOA,QAAQ,KAAM,IAAI,GAOxEC,KAAK,KACR,OAAQR,EAAUK,SACZZ,EAAA,CAAA,GAEWO,UAAAA,GAAc,CAAE,EAAAP,GAF7B,CAAA,CAIN,GAEJ"} -------------------------------------------------------------------------------- /dist/index.umd.js: -------------------------------------------------------------------------------- 1 | !function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e||self).tailwindcssMulti=n()}(this,function(){function e(e){var n={exports:{}};return e(n,n.exports),n.exports}var n=e(function(e,n){function t(e,n){return{handler:e,config:n}}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"default",{enumerable:!0,get:function(){return i}}),t.withOptions=function(e,n=(()=>({}))){const t=function(t){return{__options:t,handler:e(t),config:n(t)}};return t.__isOptionsFunction=!0,t.__pluginFunction=e,t.__configFunction=n,t};const i=t}),t=e(function(e,t){function i(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});const u=/*#__PURE__*/i(n).default});return(0,(t.__esModule?t:{default:t}).default)(function(e){(0,e.matchUtilities)({multi:function(e){var n;if(!e[0])return{};var t=[e[0],e.slice(-1)[0]],i=["'",'"',"`"].includes(e[0]);if(i&&(e.length<3||t[0]!==t[1]))throw new Error("Invalid multi value: `"+e+"`. Quoted values must use matching quotes (e.g. ['...'], [\"...\"], or [`...`]).");var u=e.slice.apply(e,i?[1,-1]:[]).split(/;(?![^[]*\])/).filter(function(e){return e.trim().length}).map(function(e){return e.replace(/_/g,"\\_").replace(/ /g,"_")}).join(" ");return u.trim()?((n={})["@apply "+u]={},n):{}}})})}); 2 | //# sourceMappingURL=index.umd.js.map 3 | -------------------------------------------------------------------------------- /dist/index.umd.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.umd.js","sources":["../node_modules/tailwindcss/lib/util/createPlugin.js","../node_modules/tailwindcss/lib/public/create-plugin.js","../index.ts","../node_modules/tailwindcss/plugin.js"],"sourcesContent":["\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"default\", {\n enumerable: true,\n get: function() {\n return _default;\n }\n});\nfunction createPlugin(plugin, config) {\n return {\n handler: plugin,\n config\n };\n}\ncreatePlugin.withOptions = function(pluginFunction, configFunction = ()=>({})) {\n const optionsFunction = function(options) {\n return {\n __options: options,\n handler: pluginFunction(options),\n config: configFunction(options)\n };\n };\n optionsFunction.__isOptionsFunction = true;\n // Expose plugin dependencies so that `object-hash` returns a different\n // value if anything here changes, to ensure a rebuild is triggered.\n optionsFunction.__pluginFunction = pluginFunction;\n optionsFunction.__configFunction = configFunction;\n return optionsFunction;\n};\nconst _default = createPlugin;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nObject.defineProperty(exports, \"default\", {\n enumerable: true,\n get: function() {\n return _default;\n }\n});\nconst _createPlugin = /*#__PURE__*/ _interop_require_default(require(\"../util/createPlugin\"));\nfunction _interop_require_default(obj) {\n return obj && obj.__esModule ? obj : {\n default: obj\n };\n}\nconst _default = _createPlugin.default;\n","import plugin from 'tailwindcss/plugin.js';\n\nexport default plugin(({ matchUtilities }) => {\n matchUtilities({\n multi: (value) => {\n if (!value[0]) return {};\n const validQuotes = [`'`, `\"`, `\\``];\n const ends = [value[0], value.slice(-1)[0]];\n const valueIsQuoted = validQuotes.includes(value[0]);\n if (valueIsQuoted && (value.length < 3 || ends[0] !== ends[1])) {\n throw new Error(\n `Invalid multi value: \\`${value}\\`. Quoted values must use matching quotes (e.g. ['...'], [\"...\"], or [\\`...\\`]).`\n );\n }\n const escape = (str: string) => str.replace(/_/g, '\\\\_').replace(/ /g, '_');\n const delimiter = /;(?![^[]*\\])/;\n const utilities = value\n .slice(...(valueIsQuoted ? [1, -1] : []))\n .split(delimiter)\n .filter((str) => str.trim().length)\n .map(escape)\n .join(' ');\n return !utilities.trim()\n ? {}\n : {\n [`@apply ${utilities}`]: {},\n };\n },\n });\n});\n","let createPlugin = require('./lib/public/create-plugin')\nmodule.exports = (createPlugin.__esModule ? createPlugin : { default: createPlugin }).default\n"],"names":["createPlugin","plugin","config","handler","Object","defineProperty","exports","value","enumerable","get","_default","withOptions","pluginFunction","configFunction","optionsFunction","options","__options","__isOptionsFunction","__pluginFunction","__configFunction","_interop_require_default","obj","__esModule","default","require$$0","_ref","matchUtilities","multi","_ref2","ends","slice","valueIsQuoted","includes","length","Error","utilities","apply","split","filter","str","trim","map","replace","join"],"mappings":"0TAUA,SAASA,EAAaC,EAAQC,GAC1B,MAAO,CACHC,QAASF,EACTC,SAER,CAdAE,OAAOC,eAAwBC,EAAA,aAAc,CACzCC,OAAO,IAEXH,OAAOC,eAAeC,EAAS,UAAW,CACtCE,YAAY,EACZC,IAAK,WACD,OAAOC,CACV,IAQLV,EAAaW,YAAc,SAASC,EAAgBC,EAAiB,MAAA,CAAO,KACxE,MAAMC,EAAkB,SAASC,GAC7B,MAAO,CACHC,UAAWD,EACXZ,QAASS,EAAeG,GACxBb,OAAQW,EAAeE,GAEnC,EAMI,OALAD,EAAgBG,qBAAsB,EAGtCH,EAAgBI,iBAAmBN,EACnCE,EAAgBK,iBAAmBN,EAC5BC,CACX,EACA,MAAMJ,EAAWV,sBCpBjB,SAASoB,EAAyBC,GAC9B,OAAOA,GAAOA,EAAIC,WAAaD,EAAM,CACjCE,QAASF,EAEjB,CAdAjB,OAAOC,eAAwBC,EAAA,aAAc,CACzCC,OAAO,IAEXH,OAAOC,eAAeC,EAAS,UAAW,CACtCE,YAAY,EACZC,IAAK,WACD,OAAOC,CACV,IAQL,MAAMA,eAN8BU,EAAyBI,GAM9BD,iBCdhBtB,GCDGD,EAAasB,WAAatB,EAAe,CAAEuB,QAASvB,IAAgBuB,SDChE,SAAAE,IACpBC,EADqCD,EAAdC,gBACR,CACbC,MAAO,SAACpB,GAAS,IAAAqB,EACf,IAAKrB,EAAM,GAAI,MAAO,CAAE,EACxB,IACMsB,EAAO,CAACtB,EAAM,GAAIA,EAAMuB,OAAO,GAAG,IAClCC,EAFc,CAAA,IAAA,IAAA,KAEcC,SAASzB,EAAM,IACjD,GAAIwB,IAAkBxB,EAAM0B,OAAS,GAAKJ,EAAK,KAAOA,EAAK,IACzD,MAAM,IAAIK,MACkB3B,yBAAAA,EAAwF,oFAGtH,IAEM4B,EAAY5B,EACfuB,MAAKM,MADU7B,EACLwB,EAAgB,CAAC,GAAI,GAAK,IACpCM,MAHe,gBAIfC,OAAO,SAACC,GAAG,OAAKA,EAAIC,OAAOP,MAAM,GACjCQ,IANY,SAACF,GAAgB,OAAAA,EAAIG,QAAQ,KAAM,OAAOA,QAAQ,KAAM,IAAI,GAOxEC,KAAK,KACR,OAAQR,EAAUK,SACZZ,EAAA,CAAA,GAEWO,UAAAA,GAAc,CAAE,EAAAP,GAF7B,CAAA,CAIN,GAEJ"} -------------------------------------------------------------------------------- /dist/types/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const _default: { 2 | handler: import("tailwindcss/types/config").PluginCreator; 3 | config?: Partial | undefined; 4 | }; 5 | export default _default; 6 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import plugin from 'tailwindcss/plugin.js'; 2 | 3 | export default plugin(({ matchUtilities }) => { 4 | matchUtilities({ 5 | multi: (value) => { 6 | if (!value[0]) return {}; 7 | const validQuotes = [`'`, `"`, `\``]; 8 | const ends = [value[0], value.slice(-1)[0]]; 9 | const valueIsQuoted = validQuotes.includes(value[0]); 10 | if (valueIsQuoted && (value.length < 3 || ends[0] !== ends[1])) { 11 | throw new Error( 12 | `Invalid multi value: \`${value}\`. Quoted values must use matching quotes (e.g. ['...'], ["..."], or [\`...\`]).` 13 | ); 14 | } 15 | const escape = (str: string) => str.replace(/_/g, '\\_').replace(/ /g, '_'); 16 | const delimiter = /;(?![^[]*\])/; 17 | const utilities = value 18 | .slice(...(valueIsQuoted ? [1, -1] : [])) 19 | .split(delimiter) 20 | .filter((str) => str.trim().length) 21 | .map(escape) 22 | .join(' '); 23 | return !utilities.trim() 24 | ? {} 25 | : { 26 | [`@apply ${utilities}`]: {}, 27 | }; 28 | }, 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tailwindcss-multi", 3 | "version": "0.4.6", 4 | "description": "Grouped utility support for Tailwind CSS", 5 | "type": "module", 6 | "source": "index.ts", 7 | "exports": { 8 | "types": "./dist/types/index.d.ts", 9 | "require": "./dist/index.cjs", 10 | "default": "./dist/index.modern.js" 11 | }, 12 | "types": "dist/types/index.d.ts", 13 | "main": "./dist/index.cjs", 14 | "module": "./dist/index.module.js", 15 | "unpkg": "./dist/index.umd.js", 16 | "scripts": { 17 | "test": "echo \"Error: no test specified\" && exit 1", 18 | "build": "microbundle", 19 | "dev": "microbundle watch" 20 | }, 21 | "publishConfig": { 22 | "access": "public" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "git+https://github.com/brandonmcconnell/tailwindcss-multi.git" 27 | }, 28 | "keywords": [ 29 | "css", 30 | "utility-classes", 31 | "grouping", 32 | "plugin", 33 | "plugins", 34 | "tailwind", 35 | "tailwindcss" 36 | ], 37 | "author": "Brandon McConnell", 38 | "license": "MIT", 39 | "bugs": { 40 | "url": "https://github.com/brandonmcconnell/tailwindcss-multi/issues" 41 | }, 42 | "homepage": "https://github.com/brandonmcconnell/tailwindcss-multi#readme", 43 | "dependencies": { 44 | "@types/node": "^20.4.1" 45 | }, 46 | "devDependencies": { 47 | "@types/tailwindcss": "^3.1.0", 48 | "@typescript-eslint/eslint-plugin": "^5.59.8", 49 | "@typescript-eslint/parser": "^5.59.8", 50 | "eslint": "^8.41.0", 51 | "eslint-config-prettier": "^8.8.0", 52 | "eslint-plugin-prettier": "^5.0.0-alpha.1", 53 | "microbundle": "^0.15.1", 54 | "npm-run-all": "^4.1.5", 55 | "tailwindcss": "^3.4.3", 56 | "typescript": "^5.1.6" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "skipLibCheck": true, 5 | "target": "es2022", 6 | "allowJs": true, 7 | "resolveJsonModule": true, 8 | "moduleDetection": "force", 9 | "isolatedModules": true, 10 | "strict": true, 11 | "noUncheckedIndexedAccess": true, 12 | "module": "NodeNext", 13 | "outDir": "dist", 14 | "sourceMap": true, 15 | "declaration": true, 16 | "lib": ["es2022"] 17 | } 18 | } 19 | --------------------------------------------------------------------------------