tailwindcss 3.0.24 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +75 -3
  2. package/colors.d.ts +3 -0
  3. package/defaultConfig.d.ts +3 -0
  4. package/defaultTheme.d.ts +3 -0
  5. package/lib/cli-peer-dependencies.js +8 -3
  6. package/lib/cli.js +125 -83
  7. package/lib/corePluginList.js +1 -0
  8. package/lib/corePlugins.js +146 -117
  9. package/lib/css/preflight.css +1 -8
  10. package/lib/featureFlags.js +8 -6
  11. package/lib/index.js +10 -13
  12. package/lib/lib/cacheInvalidation.js +32 -14
  13. package/lib/lib/collapseAdjacentRules.js +5 -3
  14. package/lib/lib/defaultExtractor.js +191 -32
  15. package/lib/lib/evaluateTailwindFunctions.js +22 -13
  16. package/lib/lib/expandApplyAtRules.js +232 -195
  17. package/lib/lib/expandTailwindAtRules.js +40 -26
  18. package/lib/lib/generateRules.js +106 -42
  19. package/lib/lib/regex.js +52 -0
  20. package/lib/lib/resolveDefaultsAtRules.js +56 -45
  21. package/lib/lib/setupContextUtils.js +131 -79
  22. package/lib/lib/setupTrackingContext.js +7 -9
  23. package/lib/lib/sharedState.js +1 -2
  24. package/lib/lib/substituteScreenAtRules.js +1 -2
  25. package/lib/postcss-plugins/nesting/plugin.js +1 -2
  26. package/lib/util/buildMediaQuery.js +1 -2
  27. package/lib/util/cloneDeep.js +2 -4
  28. package/lib/util/color.js +26 -36
  29. package/lib/util/createPlugin.js +1 -2
  30. package/lib/util/createUtilityPlugin.js +1 -2
  31. package/lib/util/dataTypes.js +14 -12
  32. package/lib/util/flattenColorPalette.js +2 -5
  33. package/lib/util/formatVariantSelector.js +64 -57
  34. package/lib/util/getAllConfigs.js +10 -5
  35. package/lib/util/isValidArbitraryValue.js +1 -2
  36. package/lib/util/log.js +2 -3
  37. package/lib/util/negateValue.js +1 -2
  38. package/lib/util/normalizeConfig.js +33 -23
  39. package/lib/util/normalizeScreens.js +1 -2
  40. package/lib/util/parseAnimationValue.js +1 -2
  41. package/lib/util/parseBoxShadowValue.js +2 -43
  42. package/lib/util/pluginUtils.js +11 -3
  43. package/lib/util/resolveConfig.js +57 -34
  44. package/lib/util/splitAtTopLevelOnly.js +90 -0
  45. package/lib/util/transformThemeValue.js +4 -2
  46. package/lib/util/validateConfig.js +21 -0
  47. package/lib/util/withAlphaVariable.js +5 -5
  48. package/package.json +21 -16
  49. package/peers/index.js +3264 -1330
  50. package/plugin.d.ts +11 -0
  51. package/src/cli-peer-dependencies.js +7 -1
  52. package/src/cli.js +104 -34
  53. package/src/corePluginList.js +1 -1
  54. package/src/corePlugins.js +57 -40
  55. package/src/css/preflight.css +1 -8
  56. package/src/featureFlags.js +2 -2
  57. package/src/index.js +0 -2
  58. package/src/lib/collapseAdjacentRules.js +5 -1
  59. package/src/lib/defaultExtractor.js +177 -35
  60. package/src/lib/evaluateTailwindFunctions.js +20 -4
  61. package/src/lib/expandApplyAtRules.js +247 -188
  62. package/src/lib/expandTailwindAtRules.js +4 -4
  63. package/src/lib/generateRules.js +69 -5
  64. package/src/lib/regex.js +74 -0
  65. package/src/lib/resolveDefaultsAtRules.js +53 -36
  66. package/src/lib/setupContextUtils.js +103 -39
  67. package/src/lib/setupTrackingContext.js +4 -0
  68. package/src/util/color.js +20 -18
  69. package/src/util/dataTypes.js +11 -5
  70. package/src/util/formatVariantSelector.js +79 -62
  71. package/src/util/getAllConfigs.js +7 -0
  72. package/src/util/log.js +1 -1
  73. package/src/util/normalizeConfig.js +0 -8
  74. package/src/util/parseBoxShadowValue.js +3 -50
  75. package/src/util/pluginUtils.js +13 -1
  76. package/src/util/resolveConfig.js +66 -54
  77. package/src/util/splitAtTopLevelOnly.js +71 -0
  78. package/src/util/toPath.js +1 -1
  79. package/src/util/transformThemeValue.js +4 -2
  80. package/src/util/validateConfig.js +13 -0
  81. package/src/util/withAlphaVariable.js +1 -1
  82. package/stubs/defaultConfig.stub.js +2 -3
  83. package/stubs/simpleConfig.stub.js +1 -0
  84. package/types/config.d.ts +325 -0
  85. package/types/generated/.gitkeep +0 -0
  86. package/types/generated/colors.d.ts +276 -0
  87. package/types/generated/corePluginList.d.ts +1 -0
  88. package/types/index.d.ts +7 -0
package/plugin.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type { Config, PluginCreator } from './types/config'
2
+ type Plugin = {
3
+ withOptions<T>(
4
+ plugin: (options: T) => PluginCreator,
5
+ config?: (options: T) => Config
6
+ ): { (options: T): { handler: PluginCreator; config?: Config }; __isOptionsFunction: true }
7
+ (plugin: PluginCreator, config?: Config): { handler: PluginCreator; config?: Config }
8
+ }
9
+
10
+ declare const plugin: Plugin
11
+ export = plugin
@@ -1,4 +1,10 @@
1
- export let postcss = require('postcss')
1
+ export function lazyPostcss() {
2
+ return require('postcss')
3
+ }
4
+
5
+ export function lazyPostcssImport() {
6
+ return require('postcss-import')
7
+ }
2
8
 
3
9
  export function lazyAutoprefixer() {
4
10
  return require('autoprefixer')
package/src/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { postcss, lazyCssnano, lazyAutoprefixer } from '../peers/index.js'
3
+ import { lazyPostcss, lazyPostcssImport, lazyCssnano, lazyAutoprefixer } from '../peers/index.js'
4
4
 
5
5
  import chokidar from 'chokidar'
6
6
  import path from 'path'
@@ -9,6 +9,7 @@ import fs from 'fs'
9
9
  import postcssrc from 'postcss-load-config'
10
10
  import { lilconfig } from 'lilconfig'
11
11
  import loadPlugins from 'postcss-load-config/src/plugins' // Little bit scary, looking at private/internal API
12
+ import loadOptions from 'postcss-load-config/src/options' // Little bit scary, looking at private/internal API
12
13
  import tailwind from './processTailwindFeatures'
13
14
  import resolveConfigInternal from '../resolveConfig'
14
15
  import fastGlob from 'fast-glob'
@@ -16,11 +17,33 @@ import getModuleDependencies from './lib/getModuleDependencies'
16
17
  import log from './util/log'
17
18
  import packageJson from '../package.json'
18
19
  import normalizePath from 'normalize-path'
20
+ import { validateConfig } from './util/validateConfig.js'
19
21
 
20
22
  let env = {
21
23
  DEBUG: process.env.DEBUG !== undefined && process.env.DEBUG !== '0',
22
24
  }
23
25
 
26
+ function isESM() {
27
+ const pkgPath = path.resolve('./package.json')
28
+
29
+ try {
30
+ let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
31
+ return pkg.type && pkg.type === 'module'
32
+ } catch (err) {
33
+ return false
34
+ }
35
+ }
36
+
37
+ let configs = isESM()
38
+ ? {
39
+ tailwind: 'tailwind.config.cjs',
40
+ postcss: 'postcss.config.cjs',
41
+ }
42
+ : {
43
+ tailwind: 'tailwind.config.js',
44
+ postcss: 'postcss.config.js',
45
+ }
46
+
24
47
  // ---
25
48
 
26
49
  function indentRecursive(node, indent = 0) {
@@ -145,16 +168,21 @@ function oneOf(...options) {
145
168
  )
146
169
  }
147
170
 
171
+ function loadPostcss() {
172
+ // Try to load a local `postcss` version first
173
+ try {
174
+ return require('postcss')
175
+ } catch {}
176
+
177
+ return lazyPostcss()
178
+ }
179
+
148
180
  let commands = {
149
181
  init: {
150
182
  run: init,
151
183
  args: {
152
- '--full': { type: Boolean, description: 'Initialize a full `tailwind.config.js` file' },
153
- '--postcss': { type: Boolean, description: 'Initialize a `postcss.config.js` file' },
154
- '--types': {
155
- type: Boolean,
156
- description: 'Add TypeScript types for the `tailwind.config.js` file',
157
- },
184
+ '--full': { type: Boolean, description: `Initialize a full \`${configs.tailwind}\` file` },
185
+ '--postcss': { type: Boolean, description: `Initialize a \`${configs.postcss}\` file` },
158
186
  '-f': '--full',
159
187
  '-p': '--postcss',
160
188
  },
@@ -165,12 +193,10 @@ let commands = {
165
193
  '--input': { type: String, description: 'Input file' },
166
194
  '--output': { type: String, description: 'Output file' },
167
195
  '--watch': { type: Boolean, description: 'Watch for changes and rebuild as needed' },
168
- /*
169
196
  '--poll': {
170
197
  type: Boolean,
171
198
  description: 'Use polling instead of filesystem events when watching',
172
199
  },
173
- */
174
200
  '--content': {
175
201
  type: String,
176
202
  description: 'Content paths to use for removing unused classes',
@@ -197,9 +223,7 @@ let commands = {
197
223
  '-o': '--output',
198
224
  '-m': '--minify',
199
225
  '-w': '--watch',
200
- /*
201
226
  '-p': '--poll',
202
- */
203
227
  },
204
228
  },
205
229
  }
@@ -217,7 +241,7 @@ if (
217
241
  help({
218
242
  usage: [
219
243
  'tailwindcss [--input input.css] [--output output.css] [--watch] [options...]',
220
- 'tailwindcss init [--full] [--postcss] [--types] [options...]',
244
+ 'tailwindcss init [--full] [--postcss] [options...]',
221
245
  ],
222
246
  commands: Object.keys(commands)
223
247
  .filter((command) => command !== 'build')
@@ -333,7 +357,7 @@ run()
333
357
  function init() {
334
358
  let messages = []
335
359
 
336
- let tailwindConfigLocation = path.resolve(args['_'][1] ?? './tailwind.config.js')
360
+ let tailwindConfigLocation = path.resolve(args['_'][1] ?? `./${configs.tailwind}`)
337
361
  if (fs.existsSync(tailwindConfigLocation)) {
338
362
  messages.push(`${path.basename(tailwindConfigLocation)} already exists.`)
339
363
  } else {
@@ -344,13 +368,6 @@ function init() {
344
368
  'utf8'
345
369
  )
346
370
 
347
- if (args['--types']) {
348
- let typesHeading = "/** @type {import('tailwindcss/types').Config} */"
349
- stubFile =
350
- stubFile.replace(`module.exports = `, `${typesHeading}\nconst config = `) +
351
- '\nmodule.exports = config'
352
- }
353
-
354
371
  // Change colors import
355
372
  stubFile = stubFile.replace('../colors', 'tailwindcss/colors')
356
373
 
@@ -360,7 +377,7 @@ function init() {
360
377
  }
361
378
 
362
379
  if (args['--postcss']) {
363
- let postcssConfigLocation = path.resolve('./postcss.config.js')
380
+ let postcssConfigLocation = path.resolve(`./${configs.postcss}`)
364
381
  if (fs.existsSync(postcssConfigLocation)) {
365
382
  messages.push(`${path.basename(postcssConfigLocation)} already exists.`)
366
383
  } else {
@@ -387,10 +404,7 @@ async function build() {
387
404
  let input = args['--input']
388
405
  let output = args['--output']
389
406
  let shouldWatch = args['--watch']
390
- let shouldPoll = false
391
- /*
392
407
  let shouldPoll = args['--poll']
393
- */
394
408
  let shouldCoalesceWriteEvents = shouldPoll || process.platform === 'win32'
395
409
  let includePostCss = args['--postcss']
396
410
 
@@ -417,12 +431,12 @@ async function build() {
417
431
  let configPath = args['--config']
418
432
  ? args['--config']
419
433
  : ((defaultPath) => (fs.existsSync(defaultPath) ? defaultPath : null))(
420
- path.resolve('./tailwind.config.js')
434
+ path.resolve(`./${configs.tailwind}`)
421
435
  )
422
436
 
423
437
  async function loadPostCssPlugins() {
424
438
  let customPostCssPath = typeof args['--postcss'] === 'string' ? args['--postcss'] : undefined
425
- let { plugins: configPlugins } = customPostCssPath
439
+ let config = customPostCssPath
426
440
  ? await (async () => {
427
441
  let file = path.resolve(customPostCssPath)
428
442
 
@@ -438,10 +452,16 @@ async function build() {
438
452
  config.plugins = []
439
453
  }
440
454
 
441
- return { plugins: loadPlugins(config, file) }
455
+ return {
456
+ file,
457
+ plugins: loadPlugins(config, file),
458
+ options: loadOptions(config, file),
459
+ }
442
460
  })()
443
461
  : await postcssrc()
444
462
 
463
+ let configPlugins = config.plugins
464
+
445
465
  let configPluginTailwindIdx = configPlugins.findIndex((plugin) => {
446
466
  if (typeof plugin === 'function' && plugin.name === 'tailwindcss') {
447
467
  return true
@@ -461,7 +481,46 @@ async function build() {
461
481
  ? configPlugins
462
482
  : configPlugins.slice(configPluginTailwindIdx + 1)
463
483
 
464
- return [beforePlugins, afterPlugins]
484
+ return [beforePlugins, afterPlugins, config.options]
485
+ }
486
+
487
+ function loadBuiltinPostcssPlugins() {
488
+ let postcss = loadPostcss()
489
+ let IMPORT_COMMENT = '__TAILWIND_RESTORE_IMPORT__: '
490
+ return [
491
+ [
492
+ (root) => {
493
+ root.walkAtRules('import', (rule) => {
494
+ if (rule.params.slice(1).startsWith('tailwindcss/')) {
495
+ rule.after(postcss.comment({ text: IMPORT_COMMENT + rule.params }))
496
+ rule.remove()
497
+ }
498
+ })
499
+ },
500
+ (() => {
501
+ try {
502
+ return require('postcss-import')
503
+ } catch {}
504
+
505
+ return lazyPostcssImport()
506
+ })(),
507
+ (root) => {
508
+ root.walkComments((rule) => {
509
+ if (rule.text.startsWith(IMPORT_COMMENT)) {
510
+ rule.after(
511
+ postcss.atRule({
512
+ name: 'import',
513
+ params: rule.text.replace(IMPORT_COMMENT, ''),
514
+ })
515
+ )
516
+ rule.remove()
517
+ }
518
+ })
519
+ },
520
+ ],
521
+ [],
522
+ {},
523
+ ]
465
524
  }
466
525
 
467
526
  function resolveConfig() {
@@ -481,10 +540,13 @@ async function build() {
481
540
  let files = args['--content'].split(/(?<!{[^}]+),/)
482
541
  let resolvedConfig = resolveConfigInternal(config, { content: { files } })
483
542
  resolvedConfig.content.files = files
543
+ resolvedConfig = validateConfig(resolvedConfig)
484
544
  return resolvedConfig
485
545
  }
486
546
 
487
- return resolveConfigInternal(config)
547
+ let resolvedConfig = resolveConfigInternal(config)
548
+ resolvedConfig = validateConfig(resolvedConfig)
549
+ return resolvedConfig
488
550
  }
489
551
 
490
552
  function extractFileGlobs(config) {
@@ -545,7 +607,9 @@ async function build() {
545
607
 
546
608
  tailwindPlugin.postcss = true
547
609
 
548
- let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [[], []]
610
+ let [beforePlugins, afterPlugins, postcssOptions] = includePostCss
611
+ ? await loadPostCssPlugins()
612
+ : loadBuiltinPostcssPlugins()
549
613
 
550
614
  let plugins = [
551
615
  ...beforePlugins,
@@ -574,13 +638,14 @@ async function build() {
574
638
  })(),
575
639
  ].filter(Boolean)
576
640
 
641
+ let postcss = loadPostcss()
577
642
  let processor = postcss(plugins)
578
643
 
579
644
  function processCSS(css) {
580
645
  let start = process.hrtime.bigint()
581
646
  return Promise.resolve()
582
647
  .then(() => (output ? fs.promises.mkdir(path.dirname(output), { recursive: true }) : null))
583
- .then(() => processor.process(css, { from: input, to: output }))
648
+ .then(() => processor.process(css, { ...postcssOptions, from: input, to: output }))
584
649
  .then((result) => {
585
650
  if (!output) {
586
651
  return process.stdout.write(result.css)
@@ -644,7 +709,9 @@ async function build() {
644
709
  return resolveConfig()
645
710
  }
646
711
 
647
- let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [[], []]
712
+ let [beforePlugins, afterPlugins] = includePostCss
713
+ ? await loadPostCssPlugins()
714
+ : loadBuiltinPostcssPlugins()
648
715
 
649
716
  let plugins = [
650
717
  ...beforePlugins,
@@ -707,6 +774,7 @@ async function build() {
707
774
  let tailwindPluginIdx = plugins.indexOf('__TAILWIND_PLUGIN_POSITION__')
708
775
  let copy = plugins.slice()
709
776
  copy.splice(tailwindPluginIdx, 1, tailwindPlugin)
777
+ let postcss = loadPostcss()
710
778
  let processor = postcss(copy)
711
779
 
712
780
  function processCSS(css) {
@@ -836,8 +904,10 @@ async function build() {
836
904
 
837
905
  if (shouldWatch) {
838
906
  /* Abort the watcher if stdin is closed to avoid zombie processes */
839
- process.stdin.on('end', () => process.exit(0))
840
- process.stdin.resume()
907
+ if (process.stdin.isTTY) {
908
+ process.stdin.on('end', () => process.exit(0))
909
+ process.stdin.resume()
910
+ }
841
911
  startWatcher()
842
912
  } else {
843
913
  buildOnce()
@@ -1 +1 @@
1
- export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","display","aspectRatio","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","borderCollapse","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","whitespace","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","content"]
1
+ export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","display","aspectRatio","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","borderCollapse","borderSpacing","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","whitespace","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","content"]
@@ -14,6 +14,7 @@ import { version as tailwindVersion } from '../package.json'
14
14
  import log from './util/log'
15
15
  import { normalizeScreens } from './util/normalizeScreens'
16
16
  import { formatBoxShadowValue, parseBoxShadowValue } from './util/parseBoxShadowValue'
17
+ import { flagEnabled } from './featureFlags'
17
18
 
18
19
  export let variantPlugins = {
19
20
  pseudoElementVariants: ({ addVariant }) => {
@@ -27,9 +28,7 @@ export let variantPlugins = {
27
28
 
28
29
  addVariant('placeholder', '&::placeholder')
29
30
 
30
- /*
31
31
  addVariant('backdrop', '&::backdrop')
32
- */
33
32
 
34
33
  addVariant('before', ({ container }) => {
35
34
  container.walkRules((rule) => {
@@ -62,14 +61,14 @@ export let variantPlugins = {
62
61
  })
63
62
  },
64
63
 
65
- pseudoClassVariants: ({ addVariant }) => {
64
+ pseudoClassVariants: ({ addVariant, config }) => {
66
65
  let pseudoVariants = [
67
66
  // Positional
68
- ['first', ':first-child'],
69
- ['last', ':last-child'],
70
- ['only', ':only-child'],
71
- ['odd', ':nth-child(odd)'],
72
- ['even', ':nth-child(even)'],
67
+ ['first', '&:first-child'],
68
+ ['last', '&:last-child'],
69
+ ['only', '&:only-child'],
70
+ ['odd', '&:nth-child(odd)'],
71
+ ['even', '&:nth-child(even)'],
73
72
  'first-of-type',
74
73
  'last-of-type',
75
74
  'only-of-type',
@@ -94,11 +93,11 @@ export let variantPlugins = {
94
93
  }
95
94
  })
96
95
 
97
- return ':visited'
96
+ return '&:visited'
98
97
  },
99
98
  ],
100
99
  'target',
101
- ['open', '[open]'],
100
+ ['open', '&[open]'],
102
101
 
103
102
  // Forms
104
103
  'default',
@@ -106,6 +105,7 @@ export let variantPlugins = {
106
105
  'indeterminate',
107
106
  'placeholder-shown',
108
107
  'autofill',
108
+ 'optional',
109
109
  'required',
110
110
  'valid',
111
111
  'invalid',
@@ -118,21 +118,24 @@ export let variantPlugins = {
118
118
 
119
119
  // Interactive
120
120
  'focus-within',
121
- 'hover',
121
+ [
122
+ 'hover',
123
+ !flagEnabled(config(), 'hoverOnlyWhenSupported')
124
+ ? '&:hover'
125
+ : '@media (hover: hover) and (pointer: fine) { &:hover }',
126
+ ],
122
127
  'focus',
123
128
  'focus-visible',
124
129
  'active',
125
- /*
126
130
  'enabled',
127
- */
128
131
  'disabled',
129
- ].map((variant) => (Array.isArray(variant) ? variant : [variant, `:${variant}`]))
132
+ ].map((variant) => (Array.isArray(variant) ? variant : [variant, `&:${variant}`]))
130
133
 
131
134
  for (let [variantName, state] of pseudoVariants) {
132
135
  addVariant(variantName, (ctx) => {
133
136
  let result = typeof state === 'function' ? state(ctx) : state
134
137
 
135
- return `&${result}`
138
+ return result
136
139
  })
137
140
  }
138
141
 
@@ -140,7 +143,7 @@ export let variantPlugins = {
140
143
  addVariant(`group-${variantName}`, (ctx) => {
141
144
  let result = typeof state === 'function' ? state(ctx) : state
142
145
 
143
- return `:merge(.group)${result} &`
146
+ return result.replace(/&(\S+)/, ':merge(.group)$1 &')
144
147
  })
145
148
  }
146
149
 
@@ -148,7 +151,7 @@ export let variantPlugins = {
148
151
  addVariant(`peer-${variantName}`, (ctx) => {
149
152
  let result = typeof state === 'function' ? state(ctx) : state
150
153
 
151
- return `:merge(.peer)${result} ~ &`
154
+ return result.replace(/&(\S+)/, ':merge(.peer)$1 ~ &')
152
155
  })
153
156
  }
154
157
  },
@@ -179,7 +182,7 @@ export let variantPlugins = {
179
182
  },
180
183
 
181
184
  darkVariants: ({ config, addVariant }) => {
182
- let [mode] = [].concat(config('darkMode', 'media'))
185
+ let [mode, className = '.dark'] = [].concat(config('darkMode', 'media'))
183
186
 
184
187
  if (mode === false) {
185
188
  mode = 'media'
@@ -191,10 +194,7 @@ export let variantPlugins = {
191
194
  }
192
195
 
193
196
  if (mode === 'class') {
194
- addVariant('dark', `.dark &`)
195
- /*
196
197
  addVariant('dark', `${className} &`)
197
- */
198
198
  } else if (mode === 'media') {
199
199
  addVariant('dark', '@media (prefers-color-scheme: dark)')
200
200
  }
@@ -216,6 +216,11 @@ export let variantPlugins = {
216
216
  addVariant('portrait', '@media (orientation: portrait)')
217
217
  addVariant('landscape', '@media (orientation: landscape)')
218
218
  },
219
+
220
+ prefersContrastVariants: ({ addVariant }) => {
221
+ addVariant('contrast-more', '@media (prefers-contrast: more)')
222
+ addVariant('contrast-less', '@media (prefers-contrast: less)')
223
+ },
219
224
  }
220
225
 
221
226
  let cssTransformValue = [
@@ -539,7 +544,6 @@ export let corePlugins = {
539
544
  })
540
545
  },
541
546
 
542
- /*
543
547
  borderSpacing: ({ addDefaults, matchUtilities, theme }) => {
544
548
  addDefaults('border-spacing', {
545
549
  '--tw-border-spacing-x': 0,
@@ -574,7 +578,6 @@ export let corePlugins = {
574
578
  { values: theme('borderSpacing') }
575
579
  )
576
580
  },
577
- */
578
581
 
579
582
  transformOrigin: createUtilityPlugin('transformOrigin', [['origin', ['transformOrigin']]]),
580
583
  translate: createUtilityPlugin(
@@ -893,6 +896,7 @@ export let corePlugins = {
893
896
  addUtilities({
894
897
  '.grid-flow-row': { gridAutoFlow: 'row' },
895
898
  '.grid-flow-col': { gridAutoFlow: 'column' },
899
+ '.grid-flow-dense': { gridAutoFlow: 'dense' },
896
900
  '.grid-flow-row-dense': { gridAutoFlow: 'row dense' },
897
901
  '.grid-flow-col-dense': { gridAutoFlow: 'column dense' },
898
902
  })
@@ -1433,7 +1437,8 @@ export let corePlugins = {
1433
1437
 
1434
1438
  return {
1435
1439
  '--tw-gradient-from': toColorValue(value, 'from'),
1436
- '--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to, ${transparentToValue})`,
1440
+ '--tw-gradient-to': transparentToValue,
1441
+ '--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to)`,
1437
1442
  }
1438
1443
  },
1439
1444
  },
@@ -1445,10 +1450,11 @@ export let corePlugins = {
1445
1450
  let transparentToValue = transparentTo(value)
1446
1451
 
1447
1452
  return {
1453
+ '--tw-gradient-to': transparentToValue,
1448
1454
  '--tw-gradient-stops': `var(--tw-gradient-from), ${toColorValue(
1449
1455
  value,
1450
1456
  'via'
1451
- )}, var(--tw-gradient-to, ${transparentToValue})`,
1457
+ )}, var(--tw-gradient-to)`,
1452
1458
  }
1453
1459
  },
1454
1460
  },
@@ -1571,10 +1577,8 @@ export let corePlugins = {
1571
1577
  '.text-center': { 'text-align': 'center' },
1572
1578
  '.text-right': { 'text-align': 'right' },
1573
1579
  '.text-justify': { 'text-align': 'justify' },
1574
- /*
1575
1580
  '.text-start': { 'text-align': 'start' },
1576
1581
  '.text-end': { 'text-align': 'end' },
1577
- */
1578
1582
  })
1579
1583
  },
1580
1584
 
@@ -1881,6 +1885,7 @@ export let corePlugins = {
1881
1885
  '.mix-blend-saturation': { 'mix-blend-mode': 'saturation' },
1882
1886
  '.mix-blend-color': { 'mix-blend-mode': 'color' },
1883
1887
  '.mix-blend-luminosity': { 'mix-blend-mode': 'luminosity' },
1888
+ '.mix-blend-plus-lighter': { 'mix-blend-mode': 'plus-lighter' },
1884
1889
  })
1885
1890
  },
1886
1891
 
@@ -1975,16 +1980,24 @@ export let corePlugins = {
1975
1980
  )
1976
1981
  },
1977
1982
 
1978
- ringWidth: ({ matchUtilities, addDefaults, addUtilities, theme }) => {
1979
- let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
1980
- let ringColorDefault = withAlphaValue(
1981
- /*
1982
- theme('ringColor')?.DEFAULT,
1983
- */
1984
- theme('ringColor.DEFAULT'),
1985
- ringOpacityDefault,
1986
- `rgb(147 197 253 / ${ringOpacityDefault})`
1987
- )
1983
+ ringWidth: ({ matchUtilities, addDefaults, addUtilities, theme, config }) => {
1984
+ let ringColorDefault = (() => {
1985
+ if (flagEnabled(config(), 'respectDefaultRingColorOpacity')) {
1986
+ return theme('ringColor.DEFAULT')
1987
+ }
1988
+
1989
+ let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
1990
+
1991
+ if (!theme('ringColor')?.DEFAULT) {
1992
+ return `rgb(147 197 253 / ${ringOpacityDefault})`
1993
+ }
1994
+
1995
+ return withAlphaValue(
1996
+ theme('ringColor')?.DEFAULT,
1997
+ ringOpacityDefault,
1998
+ `rgb(147 197 253 / ${ringOpacityDefault})`
1999
+ )
2000
+ })()
1988
2001
 
1989
2002
  addDefaults('ring-width', {
1990
2003
  '--tw-ring-inset': ' ',
@@ -2048,9 +2061,13 @@ export let corePlugins = {
2048
2061
  )
2049
2062
  },
2050
2063
 
2051
- ringOpacity: createUtilityPlugin('ringOpacity', [['ring-opacity', ['--tw-ring-opacity']]], {
2052
- filterDefault: true,
2053
- }),
2064
+ ringOpacity: (helpers) => {
2065
+ let { config } = helpers
2066
+
2067
+ return createUtilityPlugin('ringOpacity', [['ring-opacity', ['--tw-ring-opacity']]], {
2068
+ filterDefault: !flagEnabled(config(), 'respectDefaultRingColorOpacity'),
2069
+ })(helpers)
2070
+ },
2054
2071
  ringOffsetWidth: createUtilityPlugin(
2055
2072
  'ringOffsetWidth',
2056
2073
  [['ring-offset', ['--tw-ring-offset-width']]],
@@ -160,6 +160,7 @@ select,
160
160
  textarea {
161
161
  font-family: inherit; /* 1 */
162
162
  font-size: 100%; /* 1 */
163
+ font-weight: inherit; /* 1 */
163
164
  line-height: inherit; /* 1 */
164
165
  color: inherit; /* 1 */
165
166
  margin: 0; /* 2 */
@@ -357,11 +358,3 @@ video {
357
358
  max-width: 100%;
358
359
  height: auto;
359
360
  }
360
-
361
- /*
362
- Ensure the default browser behavior of the `hidden` attribute.
363
- */
364
-
365
- [hidden] {
366
- display: none;
367
- }
@@ -6,8 +6,8 @@ let defaults = {
6
6
  }
7
7
 
8
8
  let featureFlags = {
9
- future: [],
10
- experimental: ['optimizeUniversalDefaults'],
9
+ future: ['hoverOnlyWhenSupported', 'respectDefaultRingColorOpacity'],
10
+ experimental: ['optimizeUniversalDefaults', 'matchVariant' /* , 'variantGrouping' */],
11
11
  }
12
12
 
13
13
  export function flagEnabled(config, flag) {
package/src/index.js CHANGED
@@ -15,7 +15,6 @@ module.exports = function tailwindcss(configOrPath) {
15
15
  function (root, result) {
16
16
  let context = setupTrackingContext(configOrPath)
17
17
 
18
- /*
19
18
  if (root.type === 'document') {
20
19
  let roots = root.nodes.filter((node) => node.type === 'root')
21
20
 
@@ -27,7 +26,6 @@ module.exports = function tailwindcss(configOrPath) {
27
26
 
28
27
  return
29
28
  }
30
- */
31
29
 
32
30
  processTailwindFeatures(context)(root, result)
33
31
  },
@@ -29,7 +29,11 @@ export default function collapseAdjacentRules() {
29
29
  (currentRule[property] ?? '').replace(/\s+/g, ' ')
30
30
  )
31
31
  ) {
32
- currentRule.append(node.nodes)
32
+ // An AtRule may not have children (for example if we encounter duplicate @import url(…) rules)
33
+ if (node.nodes) {
34
+ currentRule.append(node.nodes)
35
+ }
36
+
33
37
  node.remove()
34
38
  } else {
35
39
  currentRule = node