UNPKG

81.5 kBJavaScriptView Raw
1import fs from 'fs'
2import * as path from 'path'
3import postcss from 'postcss'
4import createUtilityPlugin from './util/createUtilityPlugin'
5import buildMediaQuery from './util/buildMediaQuery'
6import escapeClassName from './util/escapeClassName'
7import parseAnimationValue from './util/parseAnimationValue'
8import flattenColorPalette from './util/flattenColorPalette'
9import withAlphaVariable, { withAlphaValue } from './util/withAlphaVariable'
10import toColorValue from './util/toColorValue'
11import isPlainObject from './util/isPlainObject'
12import transformThemeValue from './util/transformThemeValue'
13import { version as tailwindVersion } from '../package.json'
14import log from './util/log'
15import {
16 normalizeScreens,
17 isScreenSortable,
18 compareScreens,
19 toScreen,
20} from './util/normalizeScreens'
21import { formatBoxShadowValue, parseBoxShadowValue } from './util/parseBoxShadowValue'
22import { removeAlphaVariables } from './util/removeAlphaVariables'
23import { flagEnabled } from './featureFlags'
24import { normalize } from './util/dataTypes'
25
26export let variantPlugins = {
27 pseudoElementVariants: ({ addVariant }) => {
28 addVariant('first-letter', '&::first-letter')
29 addVariant('first-line', '&::first-line')
30
31 addVariant('marker', [
32 ({ container }) => {
33 removeAlphaVariables(container, ['--tw-text-opacity'])
34
35 return '& *::marker'
36 },
37 ({ container }) => {
38 removeAlphaVariables(container, ['--tw-text-opacity'])
39
40 return '&::marker'
41 },
42 ])
43
44 addVariant('selection', ['& *::selection', '&::selection'])
45
46 addVariant('file', '&::file-selector-button')
47
48 addVariant('placeholder', '&::placeholder')
49
50 addVariant('backdrop', '&::backdrop')
51
52 addVariant('before', ({ container }) => {
53 container.walkRules((rule) => {
54 let foundContent = false
55 rule.walkDecls('content', () => {
56 foundContent = true
57 })
58
59 if (!foundContent) {
60 rule.prepend(postcss.decl({ prop: 'content', value: 'var(--tw-content)' }))
61 }
62 })
63
64 return '&::before'
65 })
66
67 addVariant('after', ({ container }) => {
68 container.walkRules((rule) => {
69 let foundContent = false
70 rule.walkDecls('content', () => {
71 foundContent = true
72 })
73
74 if (!foundContent) {
75 rule.prepend(postcss.decl({ prop: 'content', value: 'var(--tw-content)' }))
76 }
77 })
78
79 return '&::after'
80 })
81 },
82
83 pseudoClassVariants: ({ addVariant, matchVariant, config }) => {
84 let pseudoVariants = [
85 // Positional
86 ['first', '&:first-child'],
87 ['last', '&:last-child'],
88 ['only', '&:only-child'],
89 ['odd', '&:nth-child(odd)'],
90 ['even', '&:nth-child(even)'],
91 'first-of-type',
92 'last-of-type',
93 'only-of-type',
94
95 // State
96 [
97 'visited',
98 ({ container }) => {
99 removeAlphaVariables(container, [
100 '--tw-text-opacity',
101 '--tw-border-opacity',
102 '--tw-bg-opacity',
103 ])
104
105 return '&:visited'
106 },
107 ],
108 'target',
109 ['open', '&[open]'],
110
111 // Forms
112 'default',
113 'checked',
114 'indeterminate',
115 'placeholder-shown',
116 'autofill',
117 'optional',
118 'required',
119 'valid',
120 'invalid',
121 'in-range',
122 'out-of-range',
123 'read-only',
124
125 // Content
126 'empty',
127
128 // Interactive
129 'focus-within',
130 [
131 'hover',
132 !flagEnabled(config(), 'hoverOnlyWhenSupported')
133 ? '&:hover'
134 : '@media (hover: hover) and (pointer: fine) { &:hover }',
135 ],
136 'focus',
137 'focus-visible',
138 'active',
139 'enabled',
140 'disabled',
141 ].map((variant) => (Array.isArray(variant) ? variant : [variant, `&:${variant}`]))
142
143 for (let [variantName, state] of pseudoVariants) {
144 addVariant(variantName, (ctx) => {
145 let result = typeof state === 'function' ? state(ctx) : state
146
147 return result
148 })
149 }
150
151 let variants = {
152 group: (_, { modifier }) =>
153 modifier ? [`:merge(.group\\/${modifier})`, ' &'] : [`:merge(.group)`, ' &'],
154 peer: (_, { modifier }) =>
155 modifier ? [`:merge(.peer\\/${modifier})`, ' ~ &'] : [`:merge(.peer)`, ' ~ &'],
156 }
157
158 for (let [name, fn] of Object.entries(variants)) {
159 matchVariant(
160 name,
161 (value = '', extra) => {
162 let result = normalize(typeof value === 'function' ? value(extra) : value)
163 if (!result.includes('&')) result = '&' + result
164
165 let [a, b] = fn('', extra)
166 return result.replace(/&(\S+)?/g, (_, pseudo = '') => a + pseudo + b)
167 },
168 { values: Object.fromEntries(pseudoVariants) }
169 )
170 }
171 },
172
173 directionVariants: ({ addVariant }) => {
174 addVariant('ltr', () => {
175 log.warn('rtl-experimental', [
176 'The RTL features in Tailwind CSS are currently in preview.',
177 'Preview features are not covered by semver, and may be improved in breaking ways at any time.',
178 ])
179
180 return '[dir="ltr"] &'
181 })
182
183 addVariant('rtl', () => {
184 log.warn('rtl-experimental', [
185 'The RTL features in Tailwind CSS are currently in preview.',
186 'Preview features are not covered by semver, and may be improved in breaking ways at any time.',
187 ])
188
189 return '[dir="rtl"] &'
190 })
191 },
192
193 reducedMotionVariants: ({ addVariant }) => {
194 addVariant('motion-safe', '@media (prefers-reduced-motion: no-preference)')
195 addVariant('motion-reduce', '@media (prefers-reduced-motion: reduce)')
196 },
197
198 darkVariants: ({ config, addVariant }) => {
199 let [mode, className = '.dark'] = [].concat(config('darkMode', 'media'))
200
201 if (mode === false) {
202 mode = 'media'
203 log.warn('darkmode-false', [
204 'The `darkMode` option in your Tailwind CSS configuration is set to `false`, which now behaves the same as `media`.',
205 'Change `darkMode` to `media` or remove it entirely.',
206 'https://tailwindcss.com/docs/upgrade-guide#remove-dark-mode-configuration',
207 ])
208 }
209
210 if (mode === 'class') {
211 addVariant('dark', `${className} &`)
212 } else if (mode === 'media') {
213 addVariant('dark', '@media (prefers-color-scheme: dark)')
214 }
215 },
216
217 printVariant: ({ addVariant }) => {
218 addVariant('print', '@media print')
219 },
220
221 screenVariants: ({ theme, addVariant, matchVariant }) => {
222 let rawScreens = theme('screens') ?? {}
223 let areSimpleScreens = Object.values(rawScreens).every((v) => typeof v === 'string')
224 let screens = normalizeScreens(theme('screens'))
225
226 /** @type {Set<string>} */
227 let unitCache = new Set([])
228
229 /** @param {string} value */
230 function units(value) {
231 return value.match(/(\D+)$/)?.[1] ?? '(none)'
232 }
233
234 /** @param {string} value */
235 function recordUnits(value) {
236 if (value !== undefined) {
237 unitCache.add(units(value))
238 }
239 }
240
241 /** @param {string} value */
242 function canUseUnits(value) {
243 recordUnits(value)
244
245 // If the cache was empty it'll become 1 because we've just added the current unit
246 // If the cache was not empty and the units are the same the size doesn't change
247 // Otherwise, if the units are different from what is already known the size will always be > 1
248 return unitCache.size === 1
249 }
250
251 for (const screen of screens) {
252 for (const value of screen.values) {
253 recordUnits(value.min)
254 recordUnits(value.max)
255 }
256 }
257
258 let screensUseConsistentUnits = unitCache.size <= 1
259
260 /**
261 * @typedef {import('./util/normalizeScreens').Screen} Screen
262 */
263
264 /**
265 * @param {'min' | 'max'} type
266 * @returns {Record<string, Screen>}
267 */
268 function buildScreenValues(type) {
269 return Object.fromEntries(
270 screens
271 .filter((screen) => isScreenSortable(screen).result)
272 .map((screen) => {
273 let { min, max } = screen.values[0]
274
275 if (type === 'min' && min !== undefined) {
276 return screen
277 } else if (type === 'min' && max !== undefined) {
278 return { ...screen, not: !screen.not }
279 } else if (type === 'max' && max !== undefined) {
280 return screen
281 } else if (type === 'max' && min !== undefined) {
282 return { ...screen, not: !screen.not }
283 }
284 })
285 .map((screen) => [screen.name, screen])
286 )
287 }
288
289 /**
290 * @param {'min' | 'max'} type
291 * @returns {(a: { value: string | Screen }, z: { value: string | Screen }) => number}
292 */
293 function buildSort(type) {
294 return (a, z) => compareScreens(type, a.value, z.value)
295 }
296
297 let maxSort = buildSort('max')
298 let minSort = buildSort('min')
299
300 /** @param {'min'|'max'} type */
301 function buildScreenVariant(type) {
302 return (value) => {
303 if (!areSimpleScreens) {
304 log.warn('complex-screen-config', [
305 'The `min-*` and `max-*` variants are not supported with a `screens` configuration containing objects.',
306 ])
307
308 return []
309 } else if (!screensUseConsistentUnits) {
310 log.warn('mixed-screen-units', [
311 'The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units.',
312 ])
313
314 return []
315 } else if (typeof value === 'string' && !canUseUnits(value)) {
316 log.warn('minmax-have-mixed-units', [
317 'The `min-*` and `max-*` variants are not supported with a `screens` configuration containing mixed units.',
318 ])
319
320 return []
321 }
322
323 return [`@media ${buildMediaQuery(toScreen(value, type))}`]
324 }
325 }
326
327 matchVariant('max', buildScreenVariant('max'), {
328 sort: maxSort,
329 values: areSimpleScreens ? buildScreenValues('max') : {},
330 })
331
332 // screens and min-* are sorted together when they can be
333 let id = 'min-screens'
334 for (let screen of screens) {
335 addVariant(screen.name, `@media ${buildMediaQuery(screen)}`, {
336 id,
337 sort: areSimpleScreens && screensUseConsistentUnits ? minSort : undefined,
338 value: screen,
339 })
340 }
341
342 matchVariant('min', buildScreenVariant('min'), {
343 id,
344 sort: minSort,
345 })
346 },
347
348 supportsVariants: ({ matchVariant, theme }) => {
349 matchVariant(
350 'supports',
351 (value = '') => {
352 let check = normalize(value)
353 let isRaw = /^\w*\s*\(/.test(check)
354
355 // Chrome has a bug where `(condtion1)or(condition2)` is not valid
356 // But `(condition1) or (condition2)` is supported.
357 check = isRaw ? check.replace(/\b(and|or|not)\b/g, ' $1 ') : check
358
359 if (isRaw) {
360 return `@supports ${check}`
361 }
362
363 if (!check.includes(':')) {
364 check = `${check}: var(--tw)`
365 }
366
367 if (!(check.startsWith('(') && check.endsWith(')'))) {
368 check = `(${check})`
369 }
370
371 return `@supports ${check}`
372 },
373 { values: theme('supports') ?? {} }
374 )
375 },
376
377 ariaVariants: ({ matchVariant, theme }) => {
378 matchVariant('aria', (value) => `&[aria-${normalize(value)}]`, { values: theme('aria') ?? {} })
379 matchVariant(
380 'group-aria',
381 (value, { modifier }) =>
382 modifier
383 ? `:merge(.group\\/${modifier})[aria-${normalize(value)}] &`
384 : `:merge(.group)[aria-${normalize(value)}] &`,
385 { values: theme('aria') ?? {} }
386 )
387 matchVariant(
388 'peer-aria',
389 (value, { modifier }) =>
390 modifier
391 ? `:merge(.peer\\/${modifier})[aria-${normalize(value)}] ~ &`
392 : `:merge(.peer)[aria-${normalize(value)}] ~ &`,
393 { values: theme('aria') ?? {} }
394 )
395 },
396
397 dataVariants: ({ matchVariant, theme }) => {
398 matchVariant('data', (value) => `&[data-${normalize(value)}]`, { values: theme('data') ?? {} })
399 matchVariant(
400 'group-data',
401 (value, { modifier }) =>
402 modifier
403 ? `:merge(.group\\/${modifier})[data-${normalize(value)}] &`
404 : `:merge(.group)[data-${normalize(value)}] &`,
405 { values: theme('data') ?? {} }
406 )
407 matchVariant(
408 'peer-data',
409 (value, { modifier }) =>
410 modifier
411 ? `:merge(.peer\\/${modifier})[data-${normalize(value)}] ~ &`
412 : `:merge(.peer)[data-${normalize(value)}] ~ &`,
413 { values: theme('data') ?? {} }
414 )
415 },
416
417 orientationVariants: ({ addVariant }) => {
418 addVariant('portrait', '@media (orientation: portrait)')
419 addVariant('landscape', '@media (orientation: landscape)')
420 },
421
422 prefersContrastVariants: ({ addVariant }) => {
423 addVariant('contrast-more', '@media (prefers-contrast: more)')
424 addVariant('contrast-less', '@media (prefers-contrast: less)')
425 },
426}
427
428let cssTransformValue = [
429 'translate(var(--tw-translate-x), var(--tw-translate-y))',
430 'rotate(var(--tw-rotate))',
431 'skewX(var(--tw-skew-x))',
432 'skewY(var(--tw-skew-y))',
433 'scaleX(var(--tw-scale-x))',
434 'scaleY(var(--tw-scale-y))',
435].join(' ')
436
437let cssFilterValue = [
438 'var(--tw-blur)',
439 'var(--tw-brightness)',
440 'var(--tw-contrast)',
441 'var(--tw-grayscale)',
442 'var(--tw-hue-rotate)',
443 'var(--tw-invert)',
444 'var(--tw-saturate)',
445 'var(--tw-sepia)',
446 'var(--tw-drop-shadow)',
447].join(' ')
448
449let cssBackdropFilterValue = [
450 'var(--tw-backdrop-blur)',
451 'var(--tw-backdrop-brightness)',
452 'var(--tw-backdrop-contrast)',
453 'var(--tw-backdrop-grayscale)',
454 'var(--tw-backdrop-hue-rotate)',
455 'var(--tw-backdrop-invert)',
456 'var(--tw-backdrop-opacity)',
457 'var(--tw-backdrop-saturate)',
458 'var(--tw-backdrop-sepia)',
459].join(' ')
460
461export let corePlugins = {
462 preflight: ({ addBase }) => {
463 let preflightStyles = postcss.parse(
464 fs.readFileSync(path.join(__dirname, './css/preflight.css'), 'utf8')
465 )
466
467 addBase([
468 postcss.comment({
469 text: `! tailwindcss v${tailwindVersion} | MIT License | https://tailwindcss.com`,
470 }),
471 ...preflightStyles.nodes,
472 ])
473 },
474
475 container: (() => {
476 function extractMinWidths(breakpoints = []) {
477 return breakpoints
478 .flatMap((breakpoint) => breakpoint.values.map((breakpoint) => breakpoint.min))
479 .filter((v) => v !== undefined)
480 }
481
482 function mapMinWidthsToPadding(minWidths, screens, paddings) {
483 if (typeof paddings === 'undefined') {
484 return []
485 }
486
487 if (!(typeof paddings === 'object' && paddings !== null)) {
488 return [
489 {
490 screen: 'DEFAULT',
491 minWidth: 0,
492 padding: paddings,
493 },
494 ]
495 }
496
497 let mapping = []
498
499 if (paddings.DEFAULT) {
500 mapping.push({
501 screen: 'DEFAULT',
502 minWidth: 0,
503 padding: paddings.DEFAULT,
504 })
505 }
506
507 for (let minWidth of minWidths) {
508 for (let screen of screens) {
509 for (let { min } of screen.values) {
510 if (min === minWidth) {
511 mapping.push({ minWidth, padding: paddings[screen.name] })
512 }
513 }
514 }
515 }
516
517 return mapping
518 }
519
520 return function ({ addComponents, theme }) {
521 let screens = normalizeScreens(theme('container.screens', theme('screens')))
522 let minWidths = extractMinWidths(screens)
523 let paddings = mapMinWidthsToPadding(minWidths, screens, theme('container.padding'))
524
525 let generatePaddingFor = (minWidth) => {
526 let paddingConfig = paddings.find((padding) => padding.minWidth === minWidth)
527
528 if (!paddingConfig) {
529 return {}
530 }
531
532 return {
533 paddingRight: paddingConfig.padding,
534 paddingLeft: paddingConfig.padding,
535 }
536 }
537
538 let atRules = Array.from(
539 new Set(minWidths.slice().sort((a, z) => parseInt(a) - parseInt(z)))
540 ).map((minWidth) => ({
541 [`@media (min-width: ${minWidth})`]: {
542 '.container': {
543 'max-width': minWidth,
544 ...generatePaddingFor(minWidth),
545 },
546 },
547 }))
548
549 addComponents([
550 {
551 '.container': Object.assign(
552 { width: '100%' },
553 theme('container.center', false) ? { marginRight: 'auto', marginLeft: 'auto' } : {},
554 generatePaddingFor(0)
555 ),
556 },
557 ...atRules,
558 ])
559 }
560 })(),
561
562 accessibility: ({ addUtilities }) => {
563 addUtilities({
564 '.sr-only': {
565 position: 'absolute',
566 width: '1px',
567 height: '1px',
568 padding: '0',
569 margin: '-1px',
570 overflow: 'hidden',
571 clip: 'rect(0, 0, 0, 0)',
572 whiteSpace: 'nowrap',
573 borderWidth: '0',
574 },
575 '.not-sr-only': {
576 position: 'static',
577 width: 'auto',
578 height: 'auto',
579 padding: '0',
580 margin: '0',
581 overflow: 'visible',
582 clip: 'auto',
583 whiteSpace: 'normal',
584 },
585 })
586 },
587
588 pointerEvents: ({ addUtilities }) => {
589 addUtilities({
590 '.pointer-events-none': { 'pointer-events': 'none' },
591 '.pointer-events-auto': { 'pointer-events': 'auto' },
592 })
593 },
594
595 visibility: ({ addUtilities }) => {
596 addUtilities({
597 '.visible': { visibility: 'visible' },
598 '.invisible': { visibility: 'hidden' },
599 '.collapse': { visibility: 'collapse' },
600 })
601 },
602
603 position: ({ addUtilities }) => {
604 addUtilities({
605 '.static': { position: 'static' },
606 '.fixed': { position: 'fixed' },
607 '.absolute': { position: 'absolute' },
608 '.relative': { position: 'relative' },
609 '.sticky': { position: 'sticky' },
610 })
611 },
612
613 inset: createUtilityPlugin(
614 'inset',
615 [
616 ['inset', ['top', 'right', 'bottom', 'left']],
617 [
618 ['inset-x', ['left', 'right']],
619 ['inset-y', ['top', 'bottom']],
620 ],
621 [
622 ['top', ['top']],
623 ['right', ['right']],
624 ['bottom', ['bottom']],
625 ['left', ['left']],
626 ],
627 ],
628 { supportsNegativeValues: true }
629 ),
630
631 isolation: ({ addUtilities }) => {
632 addUtilities({
633 '.isolate': { isolation: 'isolate' },
634 '.isolation-auto': { isolation: 'auto' },
635 })
636 },
637
638 zIndex: createUtilityPlugin('zIndex', [['z', ['zIndex']]], { supportsNegativeValues: true }),
639 order: createUtilityPlugin('order', undefined, { supportsNegativeValues: true }),
640 gridColumn: createUtilityPlugin('gridColumn', [['col', ['gridColumn']]]),
641 gridColumnStart: createUtilityPlugin('gridColumnStart', [['col-start', ['gridColumnStart']]]),
642 gridColumnEnd: createUtilityPlugin('gridColumnEnd', [['col-end', ['gridColumnEnd']]]),
643 gridRow: createUtilityPlugin('gridRow', [['row', ['gridRow']]]),
644 gridRowStart: createUtilityPlugin('gridRowStart', [['row-start', ['gridRowStart']]]),
645 gridRowEnd: createUtilityPlugin('gridRowEnd', [['row-end', ['gridRowEnd']]]),
646
647 float: ({ addUtilities }) => {
648 addUtilities({
649 '.float-right': { float: 'right' },
650 '.float-left': { float: 'left' },
651 '.float-none': { float: 'none' },
652 })
653 },
654
655 clear: ({ addUtilities }) => {
656 addUtilities({
657 '.clear-left': { clear: 'left' },
658 '.clear-right': { clear: 'right' },
659 '.clear-both': { clear: 'both' },
660 '.clear-none': { clear: 'none' },
661 })
662 },
663
664 margin: createUtilityPlugin(
665 'margin',
666 [
667 ['m', ['margin']],
668 [
669 ['mx', ['margin-left', 'margin-right']],
670 ['my', ['margin-top', 'margin-bottom']],
671 ],
672 [
673 ['mt', ['margin-top']],
674 ['mr', ['margin-right']],
675 ['mb', ['margin-bottom']],
676 ['ml', ['margin-left']],
677 ],
678 ],
679 { supportsNegativeValues: true }
680 ),
681
682 boxSizing: ({ addUtilities }) => {
683 addUtilities({
684 '.box-border': { 'box-sizing': 'border-box' },
685 '.box-content': { 'box-sizing': 'content-box' },
686 })
687 },
688
689 display: ({ addUtilities }) => {
690 addUtilities({
691 '.block': { display: 'block' },
692 '.inline-block': { display: 'inline-block' },
693 '.inline': { display: 'inline' },
694 '.flex': { display: 'flex' },
695 '.inline-flex': { display: 'inline-flex' },
696 '.table': { display: 'table' },
697 '.inline-table': { display: 'inline-table' },
698 '.table-caption': { display: 'table-caption' },
699 '.table-cell': { display: 'table-cell' },
700 '.table-column': { display: 'table-column' },
701 '.table-column-group': { display: 'table-column-group' },
702 '.table-footer-group': { display: 'table-footer-group' },
703 '.table-header-group': { display: 'table-header-group' },
704 '.table-row-group': { display: 'table-row-group' },
705 '.table-row': { display: 'table-row' },
706 '.flow-root': { display: 'flow-root' },
707 '.grid': { display: 'grid' },
708 '.inline-grid': { display: 'inline-grid' },
709 '.contents': { display: 'contents' },
710 '.list-item': { display: 'list-item' },
711 '.hidden': { display: 'none' },
712 })
713 },
714
715 aspectRatio: createUtilityPlugin('aspectRatio', [['aspect', ['aspect-ratio']]]),
716
717 height: createUtilityPlugin('height', [['h', ['height']]]),
718 maxHeight: createUtilityPlugin('maxHeight', [['max-h', ['maxHeight']]]),
719 minHeight: createUtilityPlugin('minHeight', [['min-h', ['minHeight']]]),
720
721 width: createUtilityPlugin('width', [['w', ['width']]]),
722 minWidth: createUtilityPlugin('minWidth', [['min-w', ['minWidth']]]),
723 maxWidth: createUtilityPlugin('maxWidth', [['max-w', ['maxWidth']]]),
724
725 flex: createUtilityPlugin('flex'),
726 flexShrink: createUtilityPlugin('flexShrink', [
727 ['flex-shrink', ['flex-shrink']], // Deprecated
728 ['shrink', ['flex-shrink']],
729 ]),
730 flexGrow: createUtilityPlugin('flexGrow', [
731 ['flex-grow', ['flex-grow']], // Deprecated
732 ['grow', ['flex-grow']],
733 ]),
734 flexBasis: createUtilityPlugin('flexBasis', [['basis', ['flex-basis']]]),
735
736 tableLayout: ({ addUtilities }) => {
737 addUtilities({
738 '.table-auto': { 'table-layout': 'auto' },
739 '.table-fixed': { 'table-layout': 'fixed' },
740 })
741 },
742
743 borderCollapse: ({ addUtilities }) => {
744 addUtilities({
745 '.border-collapse': { 'border-collapse': 'collapse' },
746 '.border-separate': { 'border-collapse': 'separate' },
747 })
748 },
749
750 borderSpacing: ({ addDefaults, matchUtilities, theme }) => {
751 addDefaults('border-spacing', {
752 '--tw-border-spacing-x': 0,
753 '--tw-border-spacing-y': 0,
754 })
755
756 matchUtilities(
757 {
758 'border-spacing': (value) => {
759 return {
760 '--tw-border-spacing-x': value,
761 '--tw-border-spacing-y': value,
762 '@defaults border-spacing': {},
763 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
764 }
765 },
766 'border-spacing-x': (value) => {
767 return {
768 '--tw-border-spacing-x': value,
769 '@defaults border-spacing': {},
770 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
771 }
772 },
773 'border-spacing-y': (value) => {
774 return {
775 '--tw-border-spacing-y': value,
776 '@defaults border-spacing': {},
777 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
778 }
779 },
780 },
781 { values: theme('borderSpacing') }
782 )
783 },
784
785 transformOrigin: createUtilityPlugin('transformOrigin', [['origin', ['transformOrigin']]]),
786 translate: createUtilityPlugin(
787 'translate',
788 [
789 [
790 [
791 'translate-x',
792 [['@defaults transform', {}], '--tw-translate-x', ['transform', cssTransformValue]],
793 ],
794 [
795 'translate-y',
796 [['@defaults transform', {}], '--tw-translate-y', ['transform', cssTransformValue]],
797 ],
798 ],
799 ],
800 { supportsNegativeValues: true }
801 ),
802 rotate: createUtilityPlugin(
803 'rotate',
804 [['rotate', [['@defaults transform', {}], '--tw-rotate', ['transform', cssTransformValue]]]],
805 { supportsNegativeValues: true }
806 ),
807 skew: createUtilityPlugin(
808 'skew',
809 [
810 [
811 ['skew-x', [['@defaults transform', {}], '--tw-skew-x', ['transform', cssTransformValue]]],
812 ['skew-y', [['@defaults transform', {}], '--tw-skew-y', ['transform', cssTransformValue]]],
813 ],
814 ],
815 { supportsNegativeValues: true }
816 ),
817 scale: createUtilityPlugin(
818 'scale',
819 [
820 [
821 'scale',
822 [
823 ['@defaults transform', {}],
824 '--tw-scale-x',
825 '--tw-scale-y',
826 ['transform', cssTransformValue],
827 ],
828 ],
829 [
830 [
831 'scale-x',
832 [['@defaults transform', {}], '--tw-scale-x', ['transform', cssTransformValue]],
833 ],
834 [
835 'scale-y',
836 [['@defaults transform', {}], '--tw-scale-y', ['transform', cssTransformValue]],
837 ],
838 ],
839 ],
840 { supportsNegativeValues: true }
841 ),
842
843 transform: ({ addDefaults, addUtilities }) => {
844 addDefaults('transform', {
845 '--tw-translate-x': '0',
846 '--tw-translate-y': '0',
847 '--tw-rotate': '0',
848 '--tw-skew-x': '0',
849 '--tw-skew-y': '0',
850 '--tw-scale-x': '1',
851 '--tw-scale-y': '1',
852 })
853
854 addUtilities({
855 '.transform': { '@defaults transform': {}, transform: cssTransformValue },
856 '.transform-cpu': {
857 transform: cssTransformValue,
858 },
859 '.transform-gpu': {
860 transform: cssTransformValue.replace(
861 'translate(var(--tw-translate-x), var(--tw-translate-y))',
862 'translate3d(var(--tw-translate-x), var(--tw-translate-y), 0)'
863 ),
864 },
865 '.transform-none': { transform: 'none' },
866 })
867 },
868
869 animation: ({ matchUtilities, theme, config }) => {
870 let prefixName = (name) => `${config('prefix')}${escapeClassName(name)}`
871 let keyframes = Object.fromEntries(
872 Object.entries(theme('keyframes') ?? {}).map(([key, value]) => {
873 return [key, { [`@keyframes ${prefixName(key)}`]: value }]
874 })
875 )
876
877 matchUtilities(
878 {
879 animate: (value) => {
880 let animations = parseAnimationValue(value)
881
882 return [
883 ...animations.flatMap((animation) => keyframes[animation.name]),
884 {
885 animation: animations
886 .map(({ name, value }) => {
887 if (name === undefined || keyframes[name] === undefined) {
888 return value
889 }
890 return value.replace(name, prefixName(name))
891 })
892 .join(', '),
893 },
894 ]
895 },
896 },
897 { values: theme('animation') }
898 )
899 },
900
901 cursor: createUtilityPlugin('cursor'),
902
903 touchAction: ({ addDefaults, addUtilities }) => {
904 addDefaults('touch-action', {
905 '--tw-pan-x': ' ',
906 '--tw-pan-y': ' ',
907 '--tw-pinch-zoom': ' ',
908 })
909
910 let cssTouchActionValue = 'var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)'
911
912 addUtilities({
913 '.touch-auto': { 'touch-action': 'auto' },
914 '.touch-none': { 'touch-action': 'none' },
915 '.touch-pan-x': {
916 '@defaults touch-action': {},
917 '--tw-pan-x': 'pan-x',
918 'touch-action': cssTouchActionValue,
919 },
920 '.touch-pan-left': {
921 '@defaults touch-action': {},
922 '--tw-pan-x': 'pan-left',
923 'touch-action': cssTouchActionValue,
924 },
925 '.touch-pan-right': {
926 '@defaults touch-action': {},
927 '--tw-pan-x': 'pan-right',
928 'touch-action': cssTouchActionValue,
929 },
930 '.touch-pan-y': {
931 '@defaults touch-action': {},
932 '--tw-pan-y': 'pan-y',
933 'touch-action': cssTouchActionValue,
934 },
935 '.touch-pan-up': {
936 '@defaults touch-action': {},
937 '--tw-pan-y': 'pan-up',
938 'touch-action': cssTouchActionValue,
939 },
940 '.touch-pan-down': {
941 '@defaults touch-action': {},
942 '--tw-pan-y': 'pan-down',
943 'touch-action': cssTouchActionValue,
944 },
945 '.touch-pinch-zoom': {
946 '@defaults touch-action': {},
947 '--tw-pinch-zoom': 'pinch-zoom',
948 'touch-action': cssTouchActionValue,
949 },
950 '.touch-manipulation': { 'touch-action': 'manipulation' },
951 })
952 },
953
954 userSelect: ({ addUtilities }) => {
955 addUtilities({
956 '.select-none': { 'user-select': 'none' },
957 '.select-text': { 'user-select': 'text' },
958 '.select-all': { 'user-select': 'all' },
959 '.select-auto': { 'user-select': 'auto' },
960 })
961 },
962
963 resize: ({ addUtilities }) => {
964 addUtilities({
965 '.resize-none': { resize: 'none' },
966 '.resize-y': { resize: 'vertical' },
967 '.resize-x': { resize: 'horizontal' },
968 '.resize': { resize: 'both' },
969 })
970 },
971
972 scrollSnapType: ({ addDefaults, addUtilities }) => {
973 addDefaults('scroll-snap-type', {
974 '--tw-scroll-snap-strictness': 'proximity',
975 })
976
977 addUtilities({
978 '.snap-none': { 'scroll-snap-type': 'none' },
979 '.snap-x': {
980 '@defaults scroll-snap-type': {},
981 'scroll-snap-type': 'x var(--tw-scroll-snap-strictness)',
982 },
983 '.snap-y': {
984 '@defaults scroll-snap-type': {},
985 'scroll-snap-type': 'y var(--tw-scroll-snap-strictness)',
986 },
987 '.snap-both': {
988 '@defaults scroll-snap-type': {},
989 'scroll-snap-type': 'both var(--tw-scroll-snap-strictness)',
990 },
991 '.snap-mandatory': { '--tw-scroll-snap-strictness': 'mandatory' },
992 '.snap-proximity': { '--tw-scroll-snap-strictness': 'proximity' },
993 })
994 },
995
996 scrollSnapAlign: ({ addUtilities }) => {
997 addUtilities({
998 '.snap-start': { 'scroll-snap-align': 'start' },
999 '.snap-end': { 'scroll-snap-align': 'end' },
1000 '.snap-center': { 'scroll-snap-align': 'center' },
1001 '.snap-align-none': { 'scroll-snap-align': 'none' },
1002 })
1003 },
1004
1005 scrollSnapStop: ({ addUtilities }) => {
1006 addUtilities({
1007 '.snap-normal': { 'scroll-snap-stop': 'normal' },
1008 '.snap-always': { 'scroll-snap-stop': 'always' },
1009 })
1010 },
1011
1012 scrollMargin: createUtilityPlugin(
1013 'scrollMargin',
1014 [
1015 ['scroll-m', ['scroll-margin']],
1016 [
1017 ['scroll-mx', ['scroll-margin-left', 'scroll-margin-right']],
1018 ['scroll-my', ['scroll-margin-top', 'scroll-margin-bottom']],
1019 ],
1020 [
1021 ['scroll-mt', ['scroll-margin-top']],
1022 ['scroll-mr', ['scroll-margin-right']],
1023 ['scroll-mb', ['scroll-margin-bottom']],
1024 ['scroll-ml', ['scroll-margin-left']],
1025 ],
1026 ],
1027 { supportsNegativeValues: true }
1028 ),
1029
1030 scrollPadding: createUtilityPlugin('scrollPadding', [
1031 ['scroll-p', ['scroll-padding']],
1032 [
1033 ['scroll-px', ['scroll-padding-left', 'scroll-padding-right']],
1034 ['scroll-py', ['scroll-padding-top', 'scroll-padding-bottom']],
1035 ],
1036 [
1037 ['scroll-pt', ['scroll-padding-top']],
1038 ['scroll-pr', ['scroll-padding-right']],
1039 ['scroll-pb', ['scroll-padding-bottom']],
1040 ['scroll-pl', ['scroll-padding-left']],
1041 ],
1042 ]),
1043
1044 listStylePosition: ({ addUtilities }) => {
1045 addUtilities({
1046 '.list-inside': { 'list-style-position': 'inside' },
1047 '.list-outside': { 'list-style-position': 'outside' },
1048 })
1049 },
1050
1051 listStyleType: createUtilityPlugin('listStyleType', [['list', ['listStyleType']]]),
1052
1053 appearance: ({ addUtilities }) => {
1054 addUtilities({
1055 '.appearance-none': { appearance: 'none' },
1056 })
1057 },
1058
1059 columns: createUtilityPlugin('columns', [['columns', ['columns']]]),
1060
1061 breakBefore: ({ addUtilities }) => {
1062 addUtilities({
1063 '.break-before-auto': { 'break-before': 'auto' },
1064 '.break-before-avoid': { 'break-before': 'avoid' },
1065 '.break-before-all': { 'break-before': 'all' },
1066 '.break-before-avoid-page': { 'break-before': 'avoid-page' },
1067 '.break-before-page': { 'break-before': 'page' },
1068 '.break-before-left': { 'break-before': 'left' },
1069 '.break-before-right': { 'break-before': 'right' },
1070 '.break-before-column': { 'break-before': 'column' },
1071 })
1072 },
1073
1074 breakInside: ({ addUtilities }) => {
1075 addUtilities({
1076 '.break-inside-auto': { 'break-inside': 'auto' },
1077 '.break-inside-avoid': { 'break-inside': 'avoid' },
1078 '.break-inside-avoid-page': { 'break-inside': 'avoid-page' },
1079 '.break-inside-avoid-column': { 'break-inside': 'avoid-column' },
1080 })
1081 },
1082
1083 breakAfter: ({ addUtilities }) => {
1084 addUtilities({
1085 '.break-after-auto': { 'break-after': 'auto' },
1086 '.break-after-avoid': { 'break-after': 'avoid' },
1087 '.break-after-all': { 'break-after': 'all' },
1088 '.break-after-avoid-page': { 'break-after': 'avoid-page' },
1089 '.break-after-page': { 'break-after': 'page' },
1090 '.break-after-left': { 'break-after': 'left' },
1091 '.break-after-right': { 'break-after': 'right' },
1092 '.break-after-column': { 'break-after': 'column' },
1093 })
1094 },
1095
1096 gridAutoColumns: createUtilityPlugin('gridAutoColumns', [['auto-cols', ['gridAutoColumns']]]),
1097
1098 gridAutoFlow: ({ addUtilities }) => {
1099 addUtilities({
1100 '.grid-flow-row': { gridAutoFlow: 'row' },
1101 '.grid-flow-col': { gridAutoFlow: 'column' },
1102 '.grid-flow-dense': { gridAutoFlow: 'dense' },
1103 '.grid-flow-row-dense': { gridAutoFlow: 'row dense' },
1104 '.grid-flow-col-dense': { gridAutoFlow: 'column dense' },
1105 })
1106 },
1107
1108 gridAutoRows: createUtilityPlugin('gridAutoRows', [['auto-rows', ['gridAutoRows']]]),
1109 gridTemplateColumns: createUtilityPlugin('gridTemplateColumns', [
1110 ['grid-cols', ['gridTemplateColumns']],
1111 ]),
1112 gridTemplateRows: createUtilityPlugin('gridTemplateRows', [['grid-rows', ['gridTemplateRows']]]),
1113
1114 flexDirection: ({ addUtilities }) => {
1115 addUtilities({
1116 '.flex-row': { 'flex-direction': 'row' },
1117 '.flex-row-reverse': { 'flex-direction': 'row-reverse' },
1118 '.flex-col': { 'flex-direction': 'column' },
1119 '.flex-col-reverse': { 'flex-direction': 'column-reverse' },
1120 })
1121 },
1122
1123 flexWrap: ({ addUtilities }) => {
1124 addUtilities({
1125 '.flex-wrap': { 'flex-wrap': 'wrap' },
1126 '.flex-wrap-reverse': { 'flex-wrap': 'wrap-reverse' },
1127 '.flex-nowrap': { 'flex-wrap': 'nowrap' },
1128 })
1129 },
1130
1131 placeContent: ({ addUtilities }) => {
1132 addUtilities({
1133 '.place-content-center': { 'place-content': 'center' },
1134 '.place-content-start': { 'place-content': 'start' },
1135 '.place-content-end': { 'place-content': 'end' },
1136 '.place-content-between': { 'place-content': 'space-between' },
1137 '.place-content-around': { 'place-content': 'space-around' },
1138 '.place-content-evenly': { 'place-content': 'space-evenly' },
1139 '.place-content-baseline': { 'place-content': 'baseline' },
1140 '.place-content-stretch': { 'place-content': 'stretch' },
1141 })
1142 },
1143
1144 placeItems: ({ addUtilities }) => {
1145 addUtilities({
1146 '.place-items-start': { 'place-items': 'start' },
1147 '.place-items-end': { 'place-items': 'end' },
1148 '.place-items-center': { 'place-items': 'center' },
1149 '.place-items-baseline': { 'place-items': 'baseline' },
1150 '.place-items-stretch': { 'place-items': 'stretch' },
1151 })
1152 },
1153
1154 alignContent: ({ addUtilities }) => {
1155 addUtilities({
1156 '.content-center': { 'align-content': 'center' },
1157 '.content-start': { 'align-content': 'flex-start' },
1158 '.content-end': { 'align-content': 'flex-end' },
1159 '.content-between': { 'align-content': 'space-between' },
1160 '.content-around': { 'align-content': 'space-around' },
1161 '.content-evenly': { 'align-content': 'space-evenly' },
1162 '.content-baseline': { 'align-content': 'baseline' },
1163 })
1164 },
1165
1166 alignItems: ({ addUtilities }) => {
1167 addUtilities({
1168 '.items-start': { 'align-items': 'flex-start' },
1169 '.items-end': { 'align-items': 'flex-end' },
1170 '.items-center': { 'align-items': 'center' },
1171 '.items-baseline': { 'align-items': 'baseline' },
1172 '.items-stretch': { 'align-items': 'stretch' },
1173 })
1174 },
1175
1176 justifyContent: ({ addUtilities }) => {
1177 addUtilities({
1178 '.justify-start': { 'justify-content': 'flex-start' },
1179 '.justify-end': { 'justify-content': 'flex-end' },
1180 '.justify-center': { 'justify-content': 'center' },
1181 '.justify-between': { 'justify-content': 'space-between' },
1182 '.justify-around': { 'justify-content': 'space-around' },
1183 '.justify-evenly': { 'justify-content': 'space-evenly' },
1184 })
1185 },
1186
1187 justifyItems: ({ addUtilities }) => {
1188 addUtilities({
1189 '.justify-items-start': { 'justify-items': 'start' },
1190 '.justify-items-end': { 'justify-items': 'end' },
1191 '.justify-items-center': { 'justify-items': 'center' },
1192 '.justify-items-stretch': { 'justify-items': 'stretch' },
1193 })
1194 },
1195
1196 gap: createUtilityPlugin('gap', [
1197 ['gap', ['gap']],
1198 [
1199 ['gap-x', ['columnGap']],
1200 ['gap-y', ['rowGap']],
1201 ],
1202 ]),
1203
1204 space: ({ matchUtilities, addUtilities, theme }) => {
1205 matchUtilities(
1206 {
1207 'space-x': (value) => {
1208 value = value === '0' ? '0px' : value
1209
1210 return {
1211 '& > :not([hidden]) ~ :not([hidden])': {
1212 '--tw-space-x-reverse': '0',
1213 'margin-right': `calc(${value} * var(--tw-space-x-reverse))`,
1214 'margin-left': `calc(${value} * calc(1 - var(--tw-space-x-reverse)))`,
1215 },
1216 }
1217 },
1218 'space-y': (value) => {
1219 value = value === '0' ? '0px' : value
1220
1221 return {
1222 '& > :not([hidden]) ~ :not([hidden])': {
1223 '--tw-space-y-reverse': '0',
1224 'margin-top': `calc(${value} * calc(1 - var(--tw-space-y-reverse)))`,
1225 'margin-bottom': `calc(${value} * var(--tw-space-y-reverse))`,
1226 },
1227 }
1228 },
1229 },
1230 { values: theme('space'), supportsNegativeValues: true }
1231 )
1232
1233 addUtilities({
1234 '.space-y-reverse > :not([hidden]) ~ :not([hidden])': { '--tw-space-y-reverse': '1' },
1235 '.space-x-reverse > :not([hidden]) ~ :not([hidden])': { '--tw-space-x-reverse': '1' },
1236 })
1237 },
1238
1239 divideWidth: ({ matchUtilities, addUtilities, theme }) => {
1240 matchUtilities(
1241 {
1242 'divide-x': (value) => {
1243 value = value === '0' ? '0px' : value
1244
1245 return {
1246 '& > :not([hidden]) ~ :not([hidden])': {
1247 '@defaults border-width': {},
1248 '--tw-divide-x-reverse': '0',
1249 'border-right-width': `calc(${value} * var(--tw-divide-x-reverse))`,
1250 'border-left-width': `calc(${value} * calc(1 - var(--tw-divide-x-reverse)))`,
1251 },
1252 }
1253 },
1254 'divide-y': (value) => {
1255 value = value === '0' ? '0px' : value
1256
1257 return {
1258 '& > :not([hidden]) ~ :not([hidden])': {
1259 '@defaults border-width': {},
1260 '--tw-divide-y-reverse': '0',
1261 'border-top-width': `calc(${value} * calc(1 - var(--tw-divide-y-reverse)))`,
1262 'border-bottom-width': `calc(${value} * var(--tw-divide-y-reverse))`,
1263 },
1264 }
1265 },
1266 },
1267 { values: theme('divideWidth'), type: ['line-width', 'length', 'any'] }
1268 )
1269
1270 addUtilities({
1271 '.divide-y-reverse > :not([hidden]) ~ :not([hidden])': {
1272 '@defaults border-width': {},
1273 '--tw-divide-y-reverse': '1',
1274 },
1275 '.divide-x-reverse > :not([hidden]) ~ :not([hidden])': {
1276 '@defaults border-width': {},
1277 '--tw-divide-x-reverse': '1',
1278 },
1279 })
1280 },
1281
1282 divideStyle: ({ addUtilities }) => {
1283 addUtilities({
1284 '.divide-solid > :not([hidden]) ~ :not([hidden])': { 'border-style': 'solid' },
1285 '.divide-dashed > :not([hidden]) ~ :not([hidden])': { 'border-style': 'dashed' },
1286 '.divide-dotted > :not([hidden]) ~ :not([hidden])': { 'border-style': 'dotted' },
1287 '.divide-double > :not([hidden]) ~ :not([hidden])': { 'border-style': 'double' },
1288 '.divide-none > :not([hidden]) ~ :not([hidden])': { 'border-style': 'none' },
1289 })
1290 },
1291
1292 divideColor: ({ matchUtilities, theme, corePlugins }) => {
1293 matchUtilities(
1294 {
1295 divide: (value) => {
1296 if (!corePlugins('divideOpacity')) {
1297 return {
1298 ['& > :not([hidden]) ~ :not([hidden])']: {
1299 'border-color': toColorValue(value),
1300 },
1301 }
1302 }
1303
1304 return {
1305 ['& > :not([hidden]) ~ :not([hidden])']: withAlphaVariable({
1306 color: value,
1307 property: 'border-color',
1308 variable: '--tw-divide-opacity',
1309 }),
1310 }
1311 },
1312 },
1313 {
1314 values: (({ DEFAULT: _, ...colors }) => colors)(flattenColorPalette(theme('divideColor'))),
1315 type: ['color', 'any'],
1316 }
1317 )
1318 },
1319
1320 divideOpacity: ({ matchUtilities, theme }) => {
1321 matchUtilities(
1322 {
1323 'divide-opacity': (value) => {
1324 return { [`& > :not([hidden]) ~ :not([hidden])`]: { '--tw-divide-opacity': value } }
1325 },
1326 },
1327 { values: theme('divideOpacity') }
1328 )
1329 },
1330
1331 placeSelf: ({ addUtilities }) => {
1332 addUtilities({
1333 '.place-self-auto': { 'place-self': 'auto' },
1334 '.place-self-start': { 'place-self': 'start' },
1335 '.place-self-end': { 'place-self': 'end' },
1336 '.place-self-center': { 'place-self': 'center' },
1337 '.place-self-stretch': { 'place-self': 'stretch' },
1338 })
1339 },
1340
1341 alignSelf: ({ addUtilities }) => {
1342 addUtilities({
1343 '.self-auto': { 'align-self': 'auto' },
1344 '.self-start': { 'align-self': 'flex-start' },
1345 '.self-end': { 'align-self': 'flex-end' },
1346 '.self-center': { 'align-self': 'center' },
1347 '.self-stretch': { 'align-self': 'stretch' },
1348 '.self-baseline': { 'align-self': 'baseline' },
1349 })
1350 },
1351
1352 justifySelf: ({ addUtilities }) => {
1353 addUtilities({
1354 '.justify-self-auto': { 'justify-self': 'auto' },
1355 '.justify-self-start': { 'justify-self': 'start' },
1356 '.justify-self-end': { 'justify-self': 'end' },
1357 '.justify-self-center': { 'justify-self': 'center' },
1358 '.justify-self-stretch': { 'justify-self': 'stretch' },
1359 })
1360 },
1361
1362 overflow: ({ addUtilities }) => {
1363 addUtilities({
1364 '.overflow-auto': { overflow: 'auto' },
1365 '.overflow-hidden': { overflow: 'hidden' },
1366 '.overflow-clip': { overflow: 'clip' },
1367 '.overflow-visible': { overflow: 'visible' },
1368 '.overflow-scroll': { overflow: 'scroll' },
1369 '.overflow-x-auto': { 'overflow-x': 'auto' },
1370 '.overflow-y-auto': { 'overflow-y': 'auto' },
1371 '.overflow-x-hidden': { 'overflow-x': 'hidden' },
1372 '.overflow-y-hidden': { 'overflow-y': 'hidden' },
1373 '.overflow-x-clip': { 'overflow-x': 'clip' },
1374 '.overflow-y-clip': { 'overflow-y': 'clip' },
1375 '.overflow-x-visible': { 'overflow-x': 'visible' },
1376 '.overflow-y-visible': { 'overflow-y': 'visible' },
1377 '.overflow-x-scroll': { 'overflow-x': 'scroll' },
1378 '.overflow-y-scroll': { 'overflow-y': 'scroll' },
1379 })
1380 },
1381
1382 overscrollBehavior: ({ addUtilities }) => {
1383 addUtilities({
1384 '.overscroll-auto': { 'overscroll-behavior': 'auto' },
1385 '.overscroll-contain': { 'overscroll-behavior': 'contain' },
1386 '.overscroll-none': { 'overscroll-behavior': 'none' },
1387 '.overscroll-y-auto': { 'overscroll-behavior-y': 'auto' },
1388 '.overscroll-y-contain': { 'overscroll-behavior-y': 'contain' },
1389 '.overscroll-y-none': { 'overscroll-behavior-y': 'none' },
1390 '.overscroll-x-auto': { 'overscroll-behavior-x': 'auto' },
1391 '.overscroll-x-contain': { 'overscroll-behavior-x': 'contain' },
1392 '.overscroll-x-none': { 'overscroll-behavior-x': 'none' },
1393 })
1394 },
1395
1396 scrollBehavior: ({ addUtilities }) => {
1397 addUtilities({
1398 '.scroll-auto': { 'scroll-behavior': 'auto' },
1399 '.scroll-smooth': { 'scroll-behavior': 'smooth' },
1400 })
1401 },
1402
1403 textOverflow: ({ addUtilities }) => {
1404 addUtilities({
1405 '.truncate': { overflow: 'hidden', 'text-overflow': 'ellipsis', 'white-space': 'nowrap' },
1406 '.overflow-ellipsis': { 'text-overflow': 'ellipsis' }, // Deprecated
1407 '.text-ellipsis': { 'text-overflow': 'ellipsis' },
1408 '.text-clip': { 'text-overflow': 'clip' },
1409 })
1410 },
1411
1412 whitespace: ({ addUtilities }) => {
1413 addUtilities({
1414 '.whitespace-normal': { 'white-space': 'normal' },
1415 '.whitespace-nowrap': { 'white-space': 'nowrap' },
1416 '.whitespace-pre': { 'white-space': 'pre' },
1417 '.whitespace-pre-line': { 'white-space': 'pre-line' },
1418 '.whitespace-pre-wrap': { 'white-space': 'pre-wrap' },
1419 })
1420 },
1421
1422 wordBreak: ({ addUtilities }) => {
1423 addUtilities({
1424 '.break-normal': { 'overflow-wrap': 'normal', 'word-break': 'normal' },
1425 '.break-words': { 'overflow-wrap': 'break-word' },
1426 '.break-all': { 'word-break': 'break-all' },
1427 '.break-keep': { 'word-break': 'keep-all' },
1428 })
1429 },
1430
1431 borderRadius: createUtilityPlugin('borderRadius', [
1432 ['rounded', ['border-radius']],
1433 [
1434 ['rounded-t', ['border-top-left-radius', 'border-top-right-radius']],
1435 ['rounded-r', ['border-top-right-radius', 'border-bottom-right-radius']],
1436 ['rounded-b', ['border-bottom-right-radius', 'border-bottom-left-radius']],
1437 ['rounded-l', ['border-top-left-radius', 'border-bottom-left-radius']],
1438 ],
1439 [
1440 ['rounded-tl', ['border-top-left-radius']],
1441 ['rounded-tr', ['border-top-right-radius']],
1442 ['rounded-br', ['border-bottom-right-radius']],
1443 ['rounded-bl', ['border-bottom-left-radius']],
1444 ],
1445 ]),
1446
1447 borderWidth: createUtilityPlugin(
1448 'borderWidth',
1449 [
1450 ['border', [['@defaults border-width', {}], 'border-width']],
1451 [
1452 ['border-x', [['@defaults border-width', {}], 'border-left-width', 'border-right-width']],
1453 ['border-y', [['@defaults border-width', {}], 'border-top-width', 'border-bottom-width']],
1454 ],
1455 [
1456 ['border-t', [['@defaults border-width', {}], 'border-top-width']],
1457 ['border-r', [['@defaults border-width', {}], 'border-right-width']],
1458 ['border-b', [['@defaults border-width', {}], 'border-bottom-width']],
1459 ['border-l', [['@defaults border-width', {}], 'border-left-width']],
1460 ],
1461 ],
1462 { type: ['line-width', 'length'] }
1463 ),
1464
1465 borderStyle: ({ addUtilities }) => {
1466 addUtilities({
1467 '.border-solid': { 'border-style': 'solid' },
1468 '.border-dashed': { 'border-style': 'dashed' },
1469 '.border-dotted': { 'border-style': 'dotted' },
1470 '.border-double': { 'border-style': 'double' },
1471 '.border-hidden': { 'border-style': 'hidden' },
1472 '.border-none': { 'border-style': 'none' },
1473 })
1474 },
1475
1476 borderColor: ({ matchUtilities, theme, corePlugins }) => {
1477 matchUtilities(
1478 {
1479 border: (value) => {
1480 if (!corePlugins('borderOpacity')) {
1481 return {
1482 'border-color': toColorValue(value),
1483 }
1484 }
1485
1486 return withAlphaVariable({
1487 color: value,
1488 property: 'border-color',
1489 variable: '--tw-border-opacity',
1490 })
1491 },
1492 },
1493 {
1494 values: (({ DEFAULT: _, ...colors }) => colors)(flattenColorPalette(theme('borderColor'))),
1495 type: ['color', 'any'],
1496 }
1497 )
1498
1499 matchUtilities(
1500 {
1501 'border-x': (value) => {
1502 if (!corePlugins('borderOpacity')) {
1503 return {
1504 'border-left-color': toColorValue(value),
1505 'border-right-color': toColorValue(value),
1506 }
1507 }
1508
1509 return withAlphaVariable({
1510 color: value,
1511 property: ['border-left-color', 'border-right-color'],
1512 variable: '--tw-border-opacity',
1513 })
1514 },
1515 'border-y': (value) => {
1516 if (!corePlugins('borderOpacity')) {
1517 return {
1518 'border-top-color': toColorValue(value),
1519 'border-bottom-color': toColorValue(value),
1520 }
1521 }
1522
1523 return withAlphaVariable({
1524 color: value,
1525 property: ['border-top-color', 'border-bottom-color'],
1526 variable: '--tw-border-opacity',
1527 })
1528 },
1529 },
1530 {
1531 values: (({ DEFAULT: _, ...colors }) => colors)(flattenColorPalette(theme('borderColor'))),
1532 type: ['color', 'any'],
1533 }
1534 )
1535
1536 matchUtilities(
1537 {
1538 'border-t': (value) => {
1539 if (!corePlugins('borderOpacity')) {
1540 return {
1541 'border-top-color': toColorValue(value),
1542 }
1543 }
1544
1545 return withAlphaVariable({
1546 color: value,
1547 property: 'border-top-color',
1548 variable: '--tw-border-opacity',
1549 })
1550 },
1551 'border-r': (value) => {
1552 if (!corePlugins('borderOpacity')) {
1553 return {
1554 'border-right-color': toColorValue(value),
1555 }
1556 }
1557
1558 return withAlphaVariable({
1559 color: value,
1560 property: 'border-right-color',
1561 variable: '--tw-border-opacity',
1562 })
1563 },
1564 'border-b': (value) => {
1565 if (!corePlugins('borderOpacity')) {
1566 return {
1567 'border-bottom-color': toColorValue(value),
1568 }
1569 }
1570
1571 return withAlphaVariable({
1572 color: value,
1573 property: 'border-bottom-color',
1574 variable: '--tw-border-opacity',
1575 })
1576 },
1577 'border-l': (value) => {
1578 if (!corePlugins('borderOpacity')) {
1579 return {
1580 'border-left-color': toColorValue(value),
1581 }
1582 }
1583
1584 return withAlphaVariable({
1585 color: value,
1586 property: 'border-left-color',
1587 variable: '--tw-border-opacity',
1588 })
1589 },
1590 },
1591 {
1592 values: (({ DEFAULT: _, ...colors }) => colors)(flattenColorPalette(theme('borderColor'))),
1593 type: ['color', 'any'],
1594 }
1595 )
1596 },
1597
1598 borderOpacity: createUtilityPlugin('borderOpacity', [
1599 ['border-opacity', ['--tw-border-opacity']],
1600 ]),
1601
1602 backgroundColor: ({ matchUtilities, theme, corePlugins }) => {
1603 matchUtilities(
1604 {
1605 bg: (value) => {
1606 if (!corePlugins('backgroundOpacity')) {
1607 return {
1608 'background-color': toColorValue(value),
1609 }
1610 }
1611
1612 return withAlphaVariable({
1613 color: value,
1614 property: 'background-color',
1615 variable: '--tw-bg-opacity',
1616 })
1617 },
1618 },
1619 { values: flattenColorPalette(theme('backgroundColor')), type: ['color', 'any'] }
1620 )
1621 },
1622
1623 backgroundOpacity: createUtilityPlugin('backgroundOpacity', [
1624 ['bg-opacity', ['--tw-bg-opacity']],
1625 ]),
1626 backgroundImage: createUtilityPlugin('backgroundImage', [['bg', ['background-image']]], {
1627 type: ['lookup', 'image', 'url'],
1628 }),
1629 gradientColorStops: (() => {
1630 function transparentTo(value) {
1631 return withAlphaValue(value, 0, 'rgb(255 255 255 / 0)')
1632 }
1633
1634 return function ({ matchUtilities, theme }) {
1635 let options = {
1636 values: flattenColorPalette(theme('gradientColorStops')),
1637 type: ['color', 'any'],
1638 }
1639
1640 matchUtilities(
1641 {
1642 from: (value) => {
1643 let transparentToValue = transparentTo(value)
1644
1645 return {
1646 '--tw-gradient-from': toColorValue(value, 'from'),
1647 '--tw-gradient-to': transparentToValue,
1648 '--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to)`,
1649 }
1650 },
1651 },
1652 options
1653 )
1654 matchUtilities(
1655 {
1656 via: (value) => {
1657 let transparentToValue = transparentTo(value)
1658
1659 return {
1660 '--tw-gradient-to': transparentToValue,
1661 '--tw-gradient-stops': `var(--tw-gradient-from), ${toColorValue(
1662 value,
1663 'via'
1664 )}, var(--tw-gradient-to)`,
1665 }
1666 },
1667 },
1668 options
1669 )
1670 matchUtilities(
1671 { to: (value) => ({ '--tw-gradient-to': toColorValue(value, 'to') }) },
1672 options
1673 )
1674 }
1675 })(),
1676
1677 boxDecorationBreak: ({ addUtilities }) => {
1678 addUtilities({
1679 '.decoration-slice': { 'box-decoration-break': 'slice' }, // Deprecated
1680 '.decoration-clone': { 'box-decoration-break': 'clone' }, // Deprecated
1681 '.box-decoration-slice': { 'box-decoration-break': 'slice' },
1682 '.box-decoration-clone': { 'box-decoration-break': 'clone' },
1683 })
1684 },
1685
1686 backgroundSize: createUtilityPlugin('backgroundSize', [['bg', ['background-size']]], {
1687 type: ['lookup', 'length', 'percentage', 'size'],
1688 }),
1689
1690 backgroundAttachment: ({ addUtilities }) => {
1691 addUtilities({
1692 '.bg-fixed': { 'background-attachment': 'fixed' },
1693 '.bg-local': { 'background-attachment': 'local' },
1694 '.bg-scroll': { 'background-attachment': 'scroll' },
1695 })
1696 },
1697
1698 backgroundClip: ({ addUtilities }) => {
1699 addUtilities({
1700 '.bg-clip-border': { 'background-clip': 'border-box' },
1701 '.bg-clip-padding': { 'background-clip': 'padding-box' },
1702 '.bg-clip-content': { 'background-clip': 'content-box' },
1703 '.bg-clip-text': { 'background-clip': 'text' },
1704 })
1705 },
1706
1707 backgroundPosition: createUtilityPlugin('backgroundPosition', [['bg', ['background-position']]], {
1708 type: ['lookup', ['position', { preferOnConflict: true }]],
1709 }),
1710
1711 backgroundRepeat: ({ addUtilities }) => {
1712 addUtilities({
1713 '.bg-repeat': { 'background-repeat': 'repeat' },
1714 '.bg-no-repeat': { 'background-repeat': 'no-repeat' },
1715 '.bg-repeat-x': { 'background-repeat': 'repeat-x' },
1716 '.bg-repeat-y': { 'background-repeat': 'repeat-y' },
1717 '.bg-repeat-round': { 'background-repeat': 'round' },
1718 '.bg-repeat-space': { 'background-repeat': 'space' },
1719 })
1720 },
1721
1722 backgroundOrigin: ({ addUtilities }) => {
1723 addUtilities({
1724 '.bg-origin-border': { 'background-origin': 'border-box' },
1725 '.bg-origin-padding': { 'background-origin': 'padding-box' },
1726 '.bg-origin-content': { 'background-origin': 'content-box' },
1727 })
1728 },
1729
1730 fill: ({ matchUtilities, theme }) => {
1731 matchUtilities(
1732 {
1733 fill: (value) => {
1734 return { fill: toColorValue(value) }
1735 },
1736 },
1737 { values: flattenColorPalette(theme('fill')), type: ['color', 'any'] }
1738 )
1739 },
1740
1741 stroke: ({ matchUtilities, theme }) => {
1742 matchUtilities(
1743 {
1744 stroke: (value) => {
1745 return { stroke: toColorValue(value) }
1746 },
1747 },
1748 { values: flattenColorPalette(theme('stroke')), type: ['color', 'url', 'any'] }
1749 )
1750 },
1751
1752 strokeWidth: createUtilityPlugin('strokeWidth', [['stroke', ['stroke-width']]], {
1753 type: ['length', 'number', 'percentage'],
1754 }),
1755
1756 objectFit: ({ addUtilities }) => {
1757 addUtilities({
1758 '.object-contain': { 'object-fit': 'contain' },
1759 '.object-cover': { 'object-fit': 'cover' },
1760 '.object-fill': { 'object-fit': 'fill' },
1761 '.object-none': { 'object-fit': 'none' },
1762 '.object-scale-down': { 'object-fit': 'scale-down' },
1763 })
1764 },
1765 objectPosition: createUtilityPlugin('objectPosition', [['object', ['object-position']]]),
1766
1767 padding: createUtilityPlugin('padding', [
1768 ['p', ['padding']],
1769 [
1770 ['px', ['padding-left', 'padding-right']],
1771 ['py', ['padding-top', 'padding-bottom']],
1772 ],
1773 [
1774 ['pt', ['padding-top']],
1775 ['pr', ['padding-right']],
1776 ['pb', ['padding-bottom']],
1777 ['pl', ['padding-left']],
1778 ],
1779 ]),
1780
1781 textAlign: ({ addUtilities }) => {
1782 addUtilities({
1783 '.text-left': { 'text-align': 'left' },
1784 '.text-center': { 'text-align': 'center' },
1785 '.text-right': { 'text-align': 'right' },
1786 '.text-justify': { 'text-align': 'justify' },
1787 '.text-start': { 'text-align': 'start' },
1788 '.text-end': { 'text-align': 'end' },
1789 })
1790 },
1791
1792 textIndent: createUtilityPlugin('textIndent', [['indent', ['text-indent']]], {
1793 supportsNegativeValues: true,
1794 }),
1795
1796 verticalAlign: ({ addUtilities, matchUtilities }) => {
1797 addUtilities({
1798 '.align-baseline': { 'vertical-align': 'baseline' },
1799 '.align-top': { 'vertical-align': 'top' },
1800 '.align-middle': { 'vertical-align': 'middle' },
1801 '.align-bottom': { 'vertical-align': 'bottom' },
1802 '.align-text-top': { 'vertical-align': 'text-top' },
1803 '.align-text-bottom': { 'vertical-align': 'text-bottom' },
1804 '.align-sub': { 'vertical-align': 'sub' },
1805 '.align-super': { 'vertical-align': 'super' },
1806 })
1807
1808 matchUtilities({ align: (value) => ({ 'vertical-align': value }) })
1809 },
1810
1811 fontFamily: ({ matchUtilities, theme }) => {
1812 matchUtilities(
1813 {
1814 font: (value) => {
1815 let [families, options = {}] =
1816 Array.isArray(value) && isPlainObject(value[1]) ? value : [value]
1817 let { fontFeatureSettings } = options
1818
1819 return {
1820 'font-family': Array.isArray(families) ? families.join(', ') : families,
1821 ...(fontFeatureSettings === undefined
1822 ? {}
1823 : { 'font-feature-settings': fontFeatureSettings }),
1824 }
1825 },
1826 },
1827 {
1828 values: theme('fontFamily'),
1829 type: ['lookup', 'generic-name', 'family-name'],
1830 }
1831 )
1832 },
1833
1834 fontSize: ({ matchUtilities, theme }) => {
1835 matchUtilities(
1836 {
1837 text: (value) => {
1838 let [fontSize, options] = Array.isArray(value) ? value : [value]
1839 let { lineHeight, letterSpacing, fontWeight } = isPlainObject(options)
1840 ? options
1841 : { lineHeight: options }
1842
1843 return {
1844 'font-size': fontSize,
1845 ...(lineHeight === undefined ? {} : { 'line-height': lineHeight }),
1846 ...(letterSpacing === undefined ? {} : { 'letter-spacing': letterSpacing }),
1847 ...(fontWeight === undefined ? {} : { 'font-weight': fontWeight }),
1848 }
1849 },
1850 },
1851 {
1852 values: theme('fontSize'),
1853 type: ['absolute-size', 'relative-size', 'length', 'percentage'],
1854 }
1855 )
1856 },
1857
1858 fontWeight: createUtilityPlugin('fontWeight', [['font', ['fontWeight']]], {
1859 type: ['lookup', 'number', 'any'],
1860 }),
1861
1862 textTransform: ({ addUtilities }) => {
1863 addUtilities({
1864 '.uppercase': { 'text-transform': 'uppercase' },
1865 '.lowercase': { 'text-transform': 'lowercase' },
1866 '.capitalize': { 'text-transform': 'capitalize' },
1867 '.normal-case': { 'text-transform': 'none' },
1868 })
1869 },
1870
1871 fontStyle: ({ addUtilities }) => {
1872 addUtilities({
1873 '.italic': { 'font-style': 'italic' },
1874 '.not-italic': { 'font-style': 'normal' },
1875 })
1876 },
1877
1878 fontVariantNumeric: ({ addDefaults, addUtilities }) => {
1879 let cssFontVariantNumericValue =
1880 'var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)'
1881
1882 addDefaults('font-variant-numeric', {
1883 '--tw-ordinal': ' ',
1884 '--tw-slashed-zero': ' ',
1885 '--tw-numeric-figure': ' ',
1886 '--tw-numeric-spacing': ' ',
1887 '--tw-numeric-fraction': ' ',
1888 })
1889
1890 addUtilities({
1891 '.normal-nums': { 'font-variant-numeric': 'normal' },
1892 '.ordinal': {
1893 '@defaults font-variant-numeric': {},
1894 '--tw-ordinal': 'ordinal',
1895 'font-variant-numeric': cssFontVariantNumericValue,
1896 },
1897 '.slashed-zero': {
1898 '@defaults font-variant-numeric': {},
1899 '--tw-slashed-zero': 'slashed-zero',
1900 'font-variant-numeric': cssFontVariantNumericValue,
1901 },
1902 '.lining-nums': {
1903 '@defaults font-variant-numeric': {},
1904 '--tw-numeric-figure': 'lining-nums',
1905 'font-variant-numeric': cssFontVariantNumericValue,
1906 },
1907 '.oldstyle-nums': {
1908 '@defaults font-variant-numeric': {},
1909 '--tw-numeric-figure': 'oldstyle-nums',
1910 'font-variant-numeric': cssFontVariantNumericValue,
1911 },
1912 '.proportional-nums': {
1913 '@defaults font-variant-numeric': {},
1914 '--tw-numeric-spacing': 'proportional-nums',
1915 'font-variant-numeric': cssFontVariantNumericValue,
1916 },
1917 '.tabular-nums': {
1918 '@defaults font-variant-numeric': {},
1919 '--tw-numeric-spacing': 'tabular-nums',
1920 'font-variant-numeric': cssFontVariantNumericValue,
1921 },
1922 '.diagonal-fractions': {
1923 '@defaults font-variant-numeric': {},
1924 '--tw-numeric-fraction': 'diagonal-fractions',
1925 'font-variant-numeric': cssFontVariantNumericValue,
1926 },
1927 '.stacked-fractions': {
1928 '@defaults font-variant-numeric': {},
1929 '--tw-numeric-fraction': 'stacked-fractions',
1930 'font-variant-numeric': cssFontVariantNumericValue,
1931 },
1932 })
1933 },
1934
1935 lineHeight: createUtilityPlugin('lineHeight', [['leading', ['lineHeight']]]),
1936 letterSpacing: createUtilityPlugin('letterSpacing', [['tracking', ['letterSpacing']]], {
1937 supportsNegativeValues: true,
1938 }),
1939
1940 textColor: ({ matchUtilities, theme, corePlugins }) => {
1941 matchUtilities(
1942 {
1943 text: (value) => {
1944 if (!corePlugins('textOpacity')) {
1945 return { color: toColorValue(value) }
1946 }
1947
1948 return withAlphaVariable({
1949 color: value,
1950 property: 'color',
1951 variable: '--tw-text-opacity',
1952 })
1953 },
1954 },
1955 { values: flattenColorPalette(theme('textColor')), type: ['color', 'any'] }
1956 )
1957 },
1958
1959 textOpacity: createUtilityPlugin('textOpacity', [['text-opacity', ['--tw-text-opacity']]]),
1960
1961 textDecoration: ({ addUtilities }) => {
1962 addUtilities({
1963 '.underline': { 'text-decoration-line': 'underline' },
1964 '.overline': { 'text-decoration-line': 'overline' },
1965 '.line-through': { 'text-decoration-line': 'line-through' },
1966 '.no-underline': { 'text-decoration-line': 'none' },
1967 })
1968 },
1969
1970 textDecorationColor: ({ matchUtilities, theme }) => {
1971 matchUtilities(
1972 {
1973 decoration: (value) => {
1974 return { 'text-decoration-color': toColorValue(value) }
1975 },
1976 },
1977 { values: flattenColorPalette(theme('textDecorationColor')), type: ['color', 'any'] }
1978 )
1979 },
1980
1981 textDecorationStyle: ({ addUtilities }) => {
1982 addUtilities({
1983 '.decoration-solid': { 'text-decoration-style': 'solid' },
1984 '.decoration-double': { 'text-decoration-style': 'double' },
1985 '.decoration-dotted': { 'text-decoration-style': 'dotted' },
1986 '.decoration-dashed': { 'text-decoration-style': 'dashed' },
1987 '.decoration-wavy': { 'text-decoration-style': 'wavy' },
1988 })
1989 },
1990
1991 textDecorationThickness: createUtilityPlugin(
1992 'textDecorationThickness',
1993 [['decoration', ['text-decoration-thickness']]],
1994 { type: ['length', 'percentage'] }
1995 ),
1996
1997 textUnderlineOffset: createUtilityPlugin(
1998 'textUnderlineOffset',
1999 [['underline-offset', ['text-underline-offset']]],
2000 { type: ['length', 'percentage', 'any'] }
2001 ),
2002
2003 fontSmoothing: ({ addUtilities }) => {
2004 addUtilities({
2005 '.antialiased': {
2006 '-webkit-font-smoothing': 'antialiased',
2007 '-moz-osx-font-smoothing': 'grayscale',
2008 },
2009 '.subpixel-antialiased': {
2010 '-webkit-font-smoothing': 'auto',
2011 '-moz-osx-font-smoothing': 'auto',
2012 },
2013 })
2014 },
2015
2016 placeholderColor: ({ matchUtilities, theme, corePlugins }) => {
2017 matchUtilities(
2018 {
2019 placeholder: (value) => {
2020 if (!corePlugins('placeholderOpacity')) {
2021 return {
2022 '&::placeholder': {
2023 color: toColorValue(value),
2024 },
2025 }
2026 }
2027
2028 return {
2029 '&::placeholder': withAlphaVariable({
2030 color: value,
2031 property: 'color',
2032 variable: '--tw-placeholder-opacity',
2033 }),
2034 }
2035 },
2036 },
2037 { values: flattenColorPalette(theme('placeholderColor')), type: ['color', 'any'] }
2038 )
2039 },
2040
2041 placeholderOpacity: ({ matchUtilities, theme }) => {
2042 matchUtilities(
2043 {
2044 'placeholder-opacity': (value) => {
2045 return { ['&::placeholder']: { '--tw-placeholder-opacity': value } }
2046 },
2047 },
2048 { values: theme('placeholderOpacity') }
2049 )
2050 },
2051
2052 caretColor: ({ matchUtilities, theme }) => {
2053 matchUtilities(
2054 {
2055 caret: (value) => {
2056 return { 'caret-color': toColorValue(value) }
2057 },
2058 },
2059 { values: flattenColorPalette(theme('caretColor')), type: ['color', 'any'] }
2060 )
2061 },
2062
2063 accentColor: ({ matchUtilities, theme }) => {
2064 matchUtilities(
2065 {
2066 accent: (value) => {
2067 return { 'accent-color': toColorValue(value) }
2068 },
2069 },
2070 { values: flattenColorPalette(theme('accentColor')), type: ['color', 'any'] }
2071 )
2072 },
2073
2074 opacity: createUtilityPlugin('opacity', [['opacity', ['opacity']]]),
2075
2076 backgroundBlendMode: ({ addUtilities }) => {
2077 addUtilities({
2078 '.bg-blend-normal': { 'background-blend-mode': 'normal' },
2079 '.bg-blend-multiply': { 'background-blend-mode': 'multiply' },
2080 '.bg-blend-screen': { 'background-blend-mode': 'screen' },
2081 '.bg-blend-overlay': { 'background-blend-mode': 'overlay' },
2082 '.bg-blend-darken': { 'background-blend-mode': 'darken' },
2083 '.bg-blend-lighten': { 'background-blend-mode': 'lighten' },
2084 '.bg-blend-color-dodge': { 'background-blend-mode': 'color-dodge' },
2085 '.bg-blend-color-burn': { 'background-blend-mode': 'color-burn' },
2086 '.bg-blend-hard-light': { 'background-blend-mode': 'hard-light' },
2087 '.bg-blend-soft-light': { 'background-blend-mode': 'soft-light' },
2088 '.bg-blend-difference': { 'background-blend-mode': 'difference' },
2089 '.bg-blend-exclusion': { 'background-blend-mode': 'exclusion' },
2090 '.bg-blend-hue': { 'background-blend-mode': 'hue' },
2091 '.bg-blend-saturation': { 'background-blend-mode': 'saturation' },
2092 '.bg-blend-color': { 'background-blend-mode': 'color' },
2093 '.bg-blend-luminosity': { 'background-blend-mode': 'luminosity' },
2094 })
2095 },
2096
2097 mixBlendMode: ({ addUtilities }) => {
2098 addUtilities({
2099 '.mix-blend-normal': { 'mix-blend-mode': 'normal' },
2100 '.mix-blend-multiply': { 'mix-blend-mode': 'multiply' },
2101 '.mix-blend-screen': { 'mix-blend-mode': 'screen' },
2102 '.mix-blend-overlay': { 'mix-blend-mode': 'overlay' },
2103 '.mix-blend-darken': { 'mix-blend-mode': 'darken' },
2104 '.mix-blend-lighten': { 'mix-blend-mode': 'lighten' },
2105 '.mix-blend-color-dodge': { 'mix-blend-mode': 'color-dodge' },
2106 '.mix-blend-color-burn': { 'mix-blend-mode': 'color-burn' },
2107 '.mix-blend-hard-light': { 'mix-blend-mode': 'hard-light' },
2108 '.mix-blend-soft-light': { 'mix-blend-mode': 'soft-light' },
2109 '.mix-blend-difference': { 'mix-blend-mode': 'difference' },
2110 '.mix-blend-exclusion': { 'mix-blend-mode': 'exclusion' },
2111 '.mix-blend-hue': { 'mix-blend-mode': 'hue' },
2112 '.mix-blend-saturation': { 'mix-blend-mode': 'saturation' },
2113 '.mix-blend-color': { 'mix-blend-mode': 'color' },
2114 '.mix-blend-luminosity': { 'mix-blend-mode': 'luminosity' },
2115 '.mix-blend-plus-lighter': { 'mix-blend-mode': 'plus-lighter' },
2116 })
2117 },
2118
2119 boxShadow: (() => {
2120 let transformValue = transformThemeValue('boxShadow')
2121 let defaultBoxShadow = [
2122 `var(--tw-ring-offset-shadow, 0 0 #0000)`,
2123 `var(--tw-ring-shadow, 0 0 #0000)`,
2124 `var(--tw-shadow)`,
2125 ].join(', ')
2126
2127 return function ({ matchUtilities, addDefaults, theme }) {
2128 addDefaults(' box-shadow', {
2129 '--tw-ring-offset-shadow': '0 0 #0000',
2130 '--tw-ring-shadow': '0 0 #0000',
2131 '--tw-shadow': '0 0 #0000',
2132 '--tw-shadow-colored': '0 0 #0000',
2133 })
2134
2135 matchUtilities(
2136 {
2137 shadow: (value) => {
2138 value = transformValue(value)
2139
2140 let ast = parseBoxShadowValue(value)
2141 for (let shadow of ast) {
2142 // Don't override color if the whole shadow is a variable
2143 if (!shadow.valid) {
2144 continue
2145 }
2146
2147 shadow.color = 'var(--tw-shadow-color)'
2148 }
2149
2150 return {
2151 '@defaults box-shadow': {},
2152 '--tw-shadow': value === 'none' ? '0 0 #0000' : value,
2153 '--tw-shadow-colored': value === 'none' ? '0 0 #0000' : formatBoxShadowValue(ast),
2154 'box-shadow': defaultBoxShadow,
2155 }
2156 },
2157 },
2158 { values: theme('boxShadow'), type: ['shadow'] }
2159 )
2160 }
2161 })(),
2162
2163 boxShadowColor: ({ matchUtilities, theme }) => {
2164 matchUtilities(
2165 {
2166 shadow: (value) => {
2167 return {
2168 '--tw-shadow-color': toColorValue(value),
2169 '--tw-shadow': 'var(--tw-shadow-colored)',
2170 }
2171 },
2172 },
2173 { values: flattenColorPalette(theme('boxShadowColor')), type: ['color', 'any'] }
2174 )
2175 },
2176
2177 outlineStyle: ({ addUtilities }) => {
2178 addUtilities({
2179 '.outline-none': {
2180 outline: '2px solid transparent',
2181 'outline-offset': '2px',
2182 },
2183 '.outline': { 'outline-style': 'solid' },
2184 '.outline-dashed': { 'outline-style': 'dashed' },
2185 '.outline-dotted': { 'outline-style': 'dotted' },
2186 '.outline-double': { 'outline-style': 'double' },
2187 })
2188 },
2189
2190 outlineWidth: createUtilityPlugin('outlineWidth', [['outline', ['outline-width']]], {
2191 type: ['length', 'number', 'percentage'],
2192 }),
2193
2194 outlineOffset: createUtilityPlugin('outlineOffset', [['outline-offset', ['outline-offset']]], {
2195 type: ['length', 'number', 'percentage', 'any'],
2196 supportsNegativeValues: true,
2197 }),
2198
2199 outlineColor: ({ matchUtilities, theme }) => {
2200 matchUtilities(
2201 {
2202 outline: (value) => {
2203 return { 'outline-color': toColorValue(value) }
2204 },
2205 },
2206 { values: flattenColorPalette(theme('outlineColor')), type: ['color', 'any'] }
2207 )
2208 },
2209
2210 ringWidth: ({ matchUtilities, addDefaults, addUtilities, theme, config }) => {
2211 let ringColorDefault = (() => {
2212 if (flagEnabled(config(), 'respectDefaultRingColorOpacity')) {
2213 return theme('ringColor.DEFAULT')
2214 }
2215
2216 let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
2217
2218 if (!theme('ringColor')?.DEFAULT) {
2219 return `rgb(147 197 253 / ${ringOpacityDefault})`
2220 }
2221
2222 return withAlphaValue(
2223 theme('ringColor')?.DEFAULT,
2224 ringOpacityDefault,
2225 `rgb(147 197 253 / ${ringOpacityDefault})`
2226 )
2227 })()
2228
2229 addDefaults('ring-width', {
2230 '--tw-ring-inset': ' ',
2231 '--tw-ring-offset-width': theme('ringOffsetWidth.DEFAULT', '0px'),
2232 '--tw-ring-offset-color': theme('ringOffsetColor.DEFAULT', '#fff'),
2233 '--tw-ring-color': ringColorDefault,
2234 '--tw-ring-offset-shadow': '0 0 #0000',
2235 '--tw-ring-shadow': '0 0 #0000',
2236 '--tw-shadow': '0 0 #0000',
2237 '--tw-shadow-colored': '0 0 #0000',
2238 })
2239
2240 matchUtilities(
2241 {
2242 ring: (value) => {
2243 return {
2244 '@defaults ring-width': {},
2245 '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`,
2246 '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(${value} + var(--tw-ring-offset-width)) var(--tw-ring-color)`,
2247 'box-shadow': [
2248 `var(--tw-ring-offset-shadow)`,
2249 `var(--tw-ring-shadow)`,
2250 `var(--tw-shadow, 0 0 #0000)`,
2251 ].join(', '),
2252 }
2253 },
2254 },
2255 { values: theme('ringWidth'), type: 'length' }
2256 )
2257
2258 addUtilities({
2259 '.ring-inset': { '@defaults ring-width': {}, '--tw-ring-inset': 'inset' },
2260 })
2261 },
2262
2263 ringColor: ({ matchUtilities, theme, corePlugins }) => {
2264 matchUtilities(
2265 {
2266 ring: (value) => {
2267 if (!corePlugins('ringOpacity')) {
2268 return {
2269 '--tw-ring-color': toColorValue(value),
2270 }
2271 }
2272
2273 return withAlphaVariable({
2274 color: value,
2275 property: '--tw-ring-color',
2276 variable: '--tw-ring-opacity',
2277 })
2278 },
2279 },
2280 {
2281 values: Object.fromEntries(
2282 Object.entries(flattenColorPalette(theme('ringColor'))).filter(
2283 ([modifier]) => modifier !== 'DEFAULT'
2284 )
2285 ),
2286 type: ['color', 'any'],
2287 }
2288 )
2289 },
2290
2291 ringOpacity: (helpers) => {
2292 let { config } = helpers
2293
2294 return createUtilityPlugin('ringOpacity', [['ring-opacity', ['--tw-ring-opacity']]], {
2295 filterDefault: !flagEnabled(config(), 'respectDefaultRingColorOpacity'),
2296 })(helpers)
2297 },
2298 ringOffsetWidth: createUtilityPlugin(
2299 'ringOffsetWidth',
2300 [['ring-offset', ['--tw-ring-offset-width']]],
2301 { type: 'length' }
2302 ),
2303
2304 ringOffsetColor: ({ matchUtilities, theme }) => {
2305 matchUtilities(
2306 {
2307 'ring-offset': (value) => {
2308 return {
2309 '--tw-ring-offset-color': toColorValue(value),
2310 }
2311 },
2312 },
2313 { values: flattenColorPalette(theme('ringOffsetColor')), type: ['color', 'any'] }
2314 )
2315 },
2316
2317 blur: ({ matchUtilities, theme }) => {
2318 matchUtilities(
2319 {
2320 blur: (value) => {
2321 return {
2322 '--tw-blur': `blur(${value})`,
2323 '@defaults filter': {},
2324 filter: cssFilterValue,
2325 }
2326 },
2327 },
2328 { values: theme('blur') }
2329 )
2330 },
2331
2332 brightness: ({ matchUtilities, theme }) => {
2333 matchUtilities(
2334 {
2335 brightness: (value) => {
2336 return {
2337 '--tw-brightness': `brightness(${value})`,
2338 '@defaults filter': {},
2339 filter: cssFilterValue,
2340 }
2341 },
2342 },
2343 { values: theme('brightness') }
2344 )
2345 },
2346
2347 contrast: ({ matchUtilities, theme }) => {
2348 matchUtilities(
2349 {
2350 contrast: (value) => {
2351 return {
2352 '--tw-contrast': `contrast(${value})`,
2353 '@defaults filter': {},
2354 filter: cssFilterValue,
2355 }
2356 },
2357 },
2358 { values: theme('contrast') }
2359 )
2360 },
2361
2362 dropShadow: ({ matchUtilities, theme }) => {
2363 matchUtilities(
2364 {
2365 'drop-shadow': (value) => {
2366 return {
2367 '--tw-drop-shadow': Array.isArray(value)
2368 ? value.map((v) => `drop-shadow(${v})`).join(' ')
2369 : `drop-shadow(${value})`,
2370 '@defaults filter': {},
2371 filter: cssFilterValue,
2372 }
2373 },
2374 },
2375 { values: theme('dropShadow') }
2376 )
2377 },
2378
2379 grayscale: ({ matchUtilities, theme }) => {
2380 matchUtilities(
2381 {
2382 grayscale: (value) => {
2383 return {
2384 '--tw-grayscale': `grayscale(${value})`,
2385 '@defaults filter': {},
2386 filter: cssFilterValue,
2387 }
2388 },
2389 },
2390 { values: theme('grayscale') }
2391 )
2392 },
2393
2394 hueRotate: ({ matchUtilities, theme }) => {
2395 matchUtilities(
2396 {
2397 'hue-rotate': (value) => {
2398 return {
2399 '--tw-hue-rotate': `hue-rotate(${value})`,
2400 '@defaults filter': {},
2401 filter: cssFilterValue,
2402 }
2403 },
2404 },
2405 { values: theme('hueRotate'), supportsNegativeValues: true }
2406 )
2407 },
2408
2409 invert: ({ matchUtilities, theme }) => {
2410 matchUtilities(
2411 {
2412 invert: (value) => {
2413 return {
2414 '--tw-invert': `invert(${value})`,
2415 '@defaults filter': {},
2416 filter: cssFilterValue,
2417 }
2418 },
2419 },
2420 { values: theme('invert') }
2421 )
2422 },
2423
2424 saturate: ({ matchUtilities, theme }) => {
2425 matchUtilities(
2426 {
2427 saturate: (value) => {
2428 return {
2429 '--tw-saturate': `saturate(${value})`,
2430 '@defaults filter': {},
2431 filter: cssFilterValue,
2432 }
2433 },
2434 },
2435 { values: theme('saturate') }
2436 )
2437 },
2438
2439 sepia: ({ matchUtilities, theme }) => {
2440 matchUtilities(
2441 {
2442 sepia: (value) => {
2443 return {
2444 '--tw-sepia': `sepia(${value})`,
2445 '@defaults filter': {},
2446 filter: cssFilterValue,
2447 }
2448 },
2449 },
2450 { values: theme('sepia') }
2451 )
2452 },
2453
2454 filter: ({ addDefaults, addUtilities }) => {
2455 addDefaults('filter', {
2456 '--tw-blur': ' ',
2457 '--tw-brightness': ' ',
2458 '--tw-contrast': ' ',
2459 '--tw-grayscale': ' ',
2460 '--tw-hue-rotate': ' ',
2461 '--tw-invert': ' ',
2462 '--tw-saturate': ' ',
2463 '--tw-sepia': ' ',
2464 '--tw-drop-shadow': ' ',
2465 })
2466 addUtilities({
2467 '.filter': { '@defaults filter': {}, filter: cssFilterValue },
2468 '.filter-none': { filter: 'none' },
2469 })
2470 },
2471
2472 backdropBlur: ({ matchUtilities, theme }) => {
2473 matchUtilities(
2474 {
2475 'backdrop-blur': (value) => {
2476 return {
2477 '--tw-backdrop-blur': `blur(${value})`,
2478 '@defaults backdrop-filter': {},
2479 'backdrop-filter': cssBackdropFilterValue,
2480 }
2481 },
2482 },
2483 { values: theme('backdropBlur') }
2484 )
2485 },
2486
2487 backdropBrightness: ({ matchUtilities, theme }) => {
2488 matchUtilities(
2489 {
2490 'backdrop-brightness': (value) => {
2491 return {
2492 '--tw-backdrop-brightness': `brightness(${value})`,
2493 '@defaults backdrop-filter': {},
2494 'backdrop-filter': cssBackdropFilterValue,
2495 }
2496 },
2497 },
2498 { values: theme('backdropBrightness') }
2499 )
2500 },
2501
2502 backdropContrast: ({ matchUtilities, theme }) => {
2503 matchUtilities(
2504 {
2505 'backdrop-contrast': (value) => {
2506 return {
2507 '--tw-backdrop-contrast': `contrast(${value})`,
2508 '@defaults backdrop-filter': {},
2509 'backdrop-filter': cssBackdropFilterValue,
2510 }
2511 },
2512 },
2513 { values: theme('backdropContrast') }
2514 )
2515 },
2516
2517 backdropGrayscale: ({ matchUtilities, theme }) => {
2518 matchUtilities(
2519 {
2520 'backdrop-grayscale': (value) => {
2521 return {
2522 '--tw-backdrop-grayscale': `grayscale(${value})`,
2523 '@defaults backdrop-filter': {},
2524 'backdrop-filter': cssBackdropFilterValue,
2525 }
2526 },
2527 },
2528 { values: theme('backdropGrayscale') }
2529 )
2530 },
2531
2532 backdropHueRotate: ({ matchUtilities, theme }) => {
2533 matchUtilities(
2534 {
2535 'backdrop-hue-rotate': (value) => {
2536 return {
2537 '--tw-backdrop-hue-rotate': `hue-rotate(${value})`,
2538 '@defaults backdrop-filter': {},
2539 'backdrop-filter': cssBackdropFilterValue,
2540 }
2541 },
2542 },
2543 { values: theme('backdropHueRotate'), supportsNegativeValues: true }
2544 )
2545 },
2546
2547 backdropInvert: ({ matchUtilities, theme }) => {
2548 matchUtilities(
2549 {
2550 'backdrop-invert': (value) => {
2551 return {
2552 '--tw-backdrop-invert': `invert(${value})`,
2553 '@defaults backdrop-filter': {},
2554 'backdrop-filter': cssBackdropFilterValue,
2555 }
2556 },
2557 },
2558 { values: theme('backdropInvert') }
2559 )
2560 },
2561
2562 backdropOpacity: ({ matchUtilities, theme }) => {
2563 matchUtilities(
2564 {
2565 'backdrop-opacity': (value) => {
2566 return {
2567 '--tw-backdrop-opacity': `opacity(${value})`,
2568 '@defaults backdrop-filter': {},
2569 'backdrop-filter': cssBackdropFilterValue,
2570 }
2571 },
2572 },
2573 { values: theme('backdropOpacity') }
2574 )
2575 },
2576
2577 backdropSaturate: ({ matchUtilities, theme }) => {
2578 matchUtilities(
2579 {
2580 'backdrop-saturate': (value) => {
2581 return {
2582 '--tw-backdrop-saturate': `saturate(${value})`,
2583 '@defaults backdrop-filter': {},
2584 'backdrop-filter': cssBackdropFilterValue,
2585 }
2586 },
2587 },
2588 { values: theme('backdropSaturate') }
2589 )
2590 },
2591
2592 backdropSepia: ({ matchUtilities, theme }) => {
2593 matchUtilities(
2594 {
2595 'backdrop-sepia': (value) => {
2596 return {
2597 '--tw-backdrop-sepia': `sepia(${value})`,
2598 '@defaults backdrop-filter': {},
2599 'backdrop-filter': cssBackdropFilterValue,
2600 }
2601 },
2602 },
2603 { values: theme('backdropSepia') }
2604 )
2605 },
2606
2607 backdropFilter: ({ addDefaults, addUtilities }) => {
2608 addDefaults('backdrop-filter', {
2609 '--tw-backdrop-blur': ' ',
2610 '--tw-backdrop-brightness': ' ',
2611 '--tw-backdrop-contrast': ' ',
2612 '--tw-backdrop-grayscale': ' ',
2613 '--tw-backdrop-hue-rotate': ' ',
2614 '--tw-backdrop-invert': ' ',
2615 '--tw-backdrop-opacity': ' ',
2616 '--tw-backdrop-saturate': ' ',
2617 '--tw-backdrop-sepia': ' ',
2618 })
2619 addUtilities({
2620 '.backdrop-filter': {
2621 '@defaults backdrop-filter': {},
2622 'backdrop-filter': cssBackdropFilterValue,
2623 },
2624 '.backdrop-filter-none': { 'backdrop-filter': 'none' },
2625 })
2626 },
2627
2628 transitionProperty: ({ matchUtilities, theme }) => {
2629 let defaultTimingFunction = theme('transitionTimingFunction.DEFAULT')
2630 let defaultDuration = theme('transitionDuration.DEFAULT')
2631
2632 matchUtilities(
2633 {
2634 transition: (value) => {
2635 return {
2636 'transition-property': value,
2637 ...(value === 'none'
2638 ? {}
2639 : {
2640 'transition-timing-function': defaultTimingFunction,
2641 'transition-duration': defaultDuration,
2642 }),
2643 }
2644 },
2645 },
2646 { values: theme('transitionProperty') }
2647 )
2648 },
2649
2650 transitionDelay: createUtilityPlugin('transitionDelay', [['delay', ['transitionDelay']]]),
2651 transitionDuration: createUtilityPlugin(
2652 'transitionDuration',
2653 [['duration', ['transitionDuration']]],
2654 { filterDefault: true }
2655 ),
2656 transitionTimingFunction: createUtilityPlugin(
2657 'transitionTimingFunction',
2658 [['ease', ['transitionTimingFunction']]],
2659 { filterDefault: true }
2660 ),
2661 willChange: createUtilityPlugin('willChange', [['will-change', ['will-change']]]),
2662 content: createUtilityPlugin('content', [
2663 ['content', ['--tw-content', ['content', 'var(--tw-content)']]],
2664 ]),
2665}