diff --git a/src/jit/corePlugins.js b/src/jit/corePlugins.js index 1ab4fb978e79..9b2f28cf77a4 100644 --- a/src/jit/corePlugins.js +++ b/src/jit/corePlugins.js @@ -3,6 +3,7 @@ import * as corePlugins from '../plugins' import buildMediaQuery from '../util/buildMediaQuery' import prefixSelector from '../util/prefixSelector' import { + applyPseudoToMarker, updateLastClasses, updateAllClasses, transformAllSelectors, @@ -156,7 +157,7 @@ export default { ) } - let baseGroupSelector = prefixSelector(config('prefix'), '.group') + let groupMarker = prefixSelector(config('prefix'), '.group') for (let variant of pseudoVariants) { let [variantName, state] = Array.isArray(variant) ? variant : [variant, variant] let groupVariantName = `group-${variantName}` @@ -165,7 +166,7 @@ export default { groupVariantName, transformAllSelectors((selector) => { let variantSelector = updateAllClasses(selector, (className) => { - if (`.${className}` === baseGroupSelector) return className + if (`.${className}` === groupMarker) return className return `${groupVariantName}${config('separator')}${className}` }) @@ -173,28 +174,39 @@ export default { return null } - let states = [state] + return applyPseudoToMarker( + variantSelector, + groupMarker, + state, + (marker, selector) => `${marker} ${selector}` + ) + }) + ) + } - // Stack group variants - let baseGroupIdx = variantSelector.indexOf(baseGroupSelector + ':') - if (baseGroupIdx !== -1) { - let groupClassName = variantSelector.slice( - baseGroupIdx, - variantSelector.indexOf(' ', baseGroupIdx) - ) + let peerMarker = prefixSelector(config('prefix'), '.peer') + for (let variant of pseudoVariants) { + let [variantName, state] = Array.isArray(variant) ? variant : [variant, variant] + let peerVariantName = `peer-${variantName}` - // Pick all the states - states = states.concat( - variantSelector - .slice(baseGroupIdx + baseGroupSelector.length + 1, groupClassName.length) - .split(':') - ) + addVariant( + peerVariantName, + transformAllSelectors((selector) => { + let variantSelector = updateAllClasses(selector, (className) => { + if (`.${className}` === peerMarker) return className + return `${peerVariantName}${config('separator')}${className}` + }) - // Remove the base `.group:...` - variantSelector = variantSelector.replace(groupClassName, '') + if (variantSelector === selector) { + return null } - return `${[baseGroupSelector, ...states].join(':')} ${variantSelector}` + return applyPseudoToMarker( + variantSelector, + peerMarker, + state, + (marker, selector) => `${marker} ~ ${selector}` + ) }) ) } diff --git a/src/util/pluginUtils.js b/src/util/pluginUtils.js index 33abffc20c54..9d12a87422a8 100644 --- a/src/util/pluginUtils.js +++ b/src/util/pluginUtils.js @@ -4,6 +4,24 @@ import createColor from 'color' import escapeCommas from './escapeCommas' import { withAlphaValue } from './withAlphaVariable' +export function applyPseudoToMarker(selector, marker, state, join) { + let states = [state] + + let targetIdx = selector.indexOf(marker + ':') + + if (targetIdx !== -1) { + let existingTarget = selector.slice(targetIdx, selector.indexOf(' ', targetIdx)) + + states = states.concat( + selector.slice(targetIdx + marker.length + 1, existingTarget.length).split(':') + ) + + selector = selector.replace(existingTarget, '') + } + + return join(`${[marker, ...states].join(':')}`, selector) +} + export function updateAllClasses(selectors, updateClass) { let parser = selectorParser((selectors) => { selectors.walkClasses((sel) => { diff --git a/tests/jit/variants.test.css b/tests/jit/variants.test.css index cba8caaa841c..9d577306cf5b 100644 --- a/tests/jit/variants.test.css +++ b/tests/jit/variants.test.css @@ -378,6 +378,161 @@ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.peer:first-child ~ .peer-first\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:last-child ~ .peer-last\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:only-child ~ .peer-only\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:nth-child(odd) ~ .peer-odd\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:nth-child(even) ~ .peer-even\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:first-of-type ~ .peer-first-of-type\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:last-of-type ~ .peer-last-of-type\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:only-of-type ~ .peer-only-of-type\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:visited ~ .peer-visited\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:target ~ .peer-target\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:default ~ .peer-default\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:checked ~ .peer-checked\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:indeterminate ~ .peer-indeterminate\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:placeholder-shown ~ .peer-placeholder-shown\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:autofill ~ .peer-autofill\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:required ~ .peer-required\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:valid ~ .peer-valid\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:invalid ~ .peer-invalid\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:in-range ~ .peer-in-range\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:out-of-range ~ .peer-out-of-range\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:read-only ~ .peer-read-only\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:empty ~ .peer-empty\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:focus-within ~ .peer-focus-within\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:hover ~ .peer-hover\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:focus ~ .peer-focus\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:focus:hover ~ .peer-focus\:peer-hover\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:focus-visible ~ .peer-focus-visible\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:active ~ .peer-active\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:disabled ~ .peer-disabled\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:disabled:focus:hover ~ .peer-disabled\:peer-focus\:peer-hover\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} +.peer:disabled:focus:hover ~ .peer-disabled\:peer-focus\:peer-hover\:first\:shadow-md:first-child { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} [dir='ltr'] .ltr\:shadow-md { --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), @@ -412,6 +567,11 @@ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } +.dark .peer:disabled:focus:hover ~ .dark\:peer-disabled\:peer-focus\:peer-hover\:shadow-md { + --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), + var(--tw-shadow); +} @media (min-width: 640px) { .sm\:shadow-md { --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); diff --git a/tests/jit/variants.test.html b/tests/jit/variants.test.html index 3444bc462c69..9fb44452efeb 100644 --- a/tests/jit/variants.test.html +++ b/tests/jit/variants.test.html @@ -78,6 +78,36 @@
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -109,5 +139,11 @@
+ + +
+
+
+