UEA-PRODEM
This commit is contained in:
+15
-1
@@ -2,7 +2,7 @@ import { createClassGroupUtils } from './class-group-utils'
|
||||
import { createLruCache } from './lru-cache'
|
||||
import { createParseClassName } from './parse-class-name'
|
||||
import { createSortModifiers } from './sort-modifiers'
|
||||
import { AnyConfig } from './types'
|
||||
import { AnyClassGroupIds, AnyConfig } from './types'
|
||||
|
||||
export type ConfigUtils = ReturnType<typeof createConfigUtils>
|
||||
|
||||
@@ -10,5 +10,19 @@ export const createConfigUtils = (config: AnyConfig) => ({
|
||||
cache: createLruCache<string, string>(config.cacheSize),
|
||||
parseClassName: createParseClassName(config),
|
||||
sortModifiers: createSortModifiers(config),
|
||||
postfixLookupClassGroupIds: createPostfixLookupClassGroupIds(config),
|
||||
...createClassGroupUtils(config),
|
||||
})
|
||||
|
||||
const createPostfixLookupClassGroupIds = (config: AnyConfig) => {
|
||||
const lookup: Partial<Record<AnyClassGroupIds, true>> = Object.create(null)
|
||||
const classGroupIds = config.postfixLookupClassGroups
|
||||
|
||||
if (classGroupIds) {
|
||||
for (let i = 0; i < classGroupIds.length; i++) {
|
||||
lookup[classGroupIds[i]!] = true
|
||||
}
|
||||
}
|
||||
|
||||
return lookup
|
||||
}
|
||||
|
||||
+261
-36
@@ -3,6 +3,7 @@ import { Config, DefaultClassGroupIds, DefaultThemeGroupIds } from './types'
|
||||
import {
|
||||
isAny,
|
||||
isAnyNonArbitrary,
|
||||
isArbitraryFamilyName,
|
||||
isArbitraryImage,
|
||||
isArbitraryLength,
|
||||
isArbitraryNumber,
|
||||
@@ -17,8 +18,11 @@ import {
|
||||
isArbitraryVariablePosition,
|
||||
isArbitraryVariableShadow,
|
||||
isArbitraryVariableSize,
|
||||
isArbitraryVariableWeight,
|
||||
isArbitraryWeight,
|
||||
isFraction,
|
||||
isInteger,
|
||||
isNamedContainerQuery,
|
||||
isNumber,
|
||||
isPercent,
|
||||
isTshirtSize,
|
||||
@@ -134,6 +138,33 @@ export const getDefaultConfig = () => {
|
||||
'fit',
|
||||
...scaleUnambiguousSpacing(),
|
||||
] as const
|
||||
const scaleSizingInline = () =>
|
||||
[
|
||||
isFraction,
|
||||
'screen',
|
||||
'full',
|
||||
'dvw',
|
||||
'lvw',
|
||||
'svw',
|
||||
'min',
|
||||
'max',
|
||||
'fit',
|
||||
...scaleUnambiguousSpacing(),
|
||||
] as const
|
||||
const scaleSizingBlock = () =>
|
||||
[
|
||||
isFraction,
|
||||
'screen',
|
||||
'full',
|
||||
'lh',
|
||||
'dvh',
|
||||
'lvh',
|
||||
'svh',
|
||||
'min',
|
||||
'max',
|
||||
'fit',
|
||||
...scaleUnambiguousSpacing(),
|
||||
] as const
|
||||
const scaleColor = () => [themeColor, isArbitraryVariable, isArbitraryValue] as const
|
||||
const scaleBgPosition = () =>
|
||||
[
|
||||
@@ -262,6 +293,18 @@ export const getDefaultConfig = () => {
|
||||
* @deprecated since Tailwind CSS v4.0.0
|
||||
*/
|
||||
container: ['container'],
|
||||
/**
|
||||
* Container Type
|
||||
* @see https://tailwindcss.com/docs/responsive-design#container-queries
|
||||
*/
|
||||
'container-type': [
|
||||
{ '@container': ['', 'normal', 'size', isArbitraryVariable, isArbitraryValue] },
|
||||
],
|
||||
/**
|
||||
* Container Name
|
||||
* @see https://tailwindcss.com/docs/responsive-design#named-containers
|
||||
*/
|
||||
'container-named': [isNamedContainerQuery],
|
||||
/**
|
||||
* Columns
|
||||
* @see https://tailwindcss.com/docs/columns
|
||||
@@ -387,30 +430,60 @@ export const getDefaultConfig = () => {
|
||||
*/
|
||||
position: ['static', 'fixed', 'absolute', 'relative', 'sticky'],
|
||||
/**
|
||||
* Top / Right / Bottom / Left
|
||||
* Inset
|
||||
* @see https://tailwindcss.com/docs/top-right-bottom-left
|
||||
*/
|
||||
inset: [{ inset: scaleInset() }],
|
||||
/**
|
||||
* Right / Left
|
||||
* Inset Inline
|
||||
* @see https://tailwindcss.com/docs/top-right-bottom-left
|
||||
*/
|
||||
'inset-x': [{ 'inset-x': scaleInset() }],
|
||||
/**
|
||||
* Top / Bottom
|
||||
* Inset Block
|
||||
* @see https://tailwindcss.com/docs/top-right-bottom-left
|
||||
*/
|
||||
'inset-y': [{ 'inset-y': scaleInset() }],
|
||||
/**
|
||||
* Start
|
||||
* Inset Inline Start
|
||||
* @see https://tailwindcss.com/docs/top-right-bottom-left
|
||||
* @todo class group will be renamed to `inset-s` in next major release
|
||||
*/
|
||||
start: [{ start: scaleInset() }],
|
||||
start: [
|
||||
{
|
||||
'inset-s': scaleInset(),
|
||||
/**
|
||||
* @deprecated since Tailwind CSS v4.2.0 in favor of `inset-s-*` utilities.
|
||||
* @see https://github.com/tailwindlabs/tailwindcss/pull/19613
|
||||
*/
|
||||
start: scaleInset(),
|
||||
},
|
||||
],
|
||||
/**
|
||||
* End
|
||||
* Inset Inline End
|
||||
* @see https://tailwindcss.com/docs/top-right-bottom-left
|
||||
* @todo class group will be renamed to `inset-e` in next major release
|
||||
*/
|
||||
end: [
|
||||
{
|
||||
'inset-e': scaleInset(),
|
||||
/**
|
||||
* @deprecated since Tailwind CSS v4.2.0 in favor of `inset-e-*` utilities.
|
||||
* @see https://github.com/tailwindlabs/tailwindcss/pull/19613
|
||||
*/
|
||||
end: scaleInset(),
|
||||
},
|
||||
],
|
||||
/**
|
||||
* Inset Block Start
|
||||
* @see https://tailwindcss.com/docs/top-right-bottom-left
|
||||
*/
|
||||
end: [{ end: scaleInset() }],
|
||||
'inset-bs': [{ 'inset-bs': scaleInset() }],
|
||||
/**
|
||||
* Inset Block End
|
||||
* @see https://tailwindcss.com/docs/top-right-bottom-left
|
||||
*/
|
||||
'inset-be': [{ 'inset-be': scaleInset() }],
|
||||
/**
|
||||
* Top
|
||||
* @see https://tailwindcss.com/docs/top-right-bottom-left
|
||||
@@ -626,25 +699,35 @@ export const getDefaultConfig = () => {
|
||||
*/
|
||||
p: [{ p: scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Padding X
|
||||
* Padding Inline
|
||||
* @see https://tailwindcss.com/docs/padding
|
||||
*/
|
||||
px: [{ px: scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Padding Y
|
||||
* Padding Block
|
||||
* @see https://tailwindcss.com/docs/padding
|
||||
*/
|
||||
py: [{ py: scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Padding Start
|
||||
* Padding Inline Start
|
||||
* @see https://tailwindcss.com/docs/padding
|
||||
*/
|
||||
ps: [{ ps: scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Padding End
|
||||
* Padding Inline End
|
||||
* @see https://tailwindcss.com/docs/padding
|
||||
*/
|
||||
pe: [{ pe: scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Padding Block Start
|
||||
* @see https://tailwindcss.com/docs/padding
|
||||
*/
|
||||
pbs: [{ pbs: scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Padding Block End
|
||||
* @see https://tailwindcss.com/docs/padding
|
||||
*/
|
||||
pbe: [{ pbe: scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Padding Top
|
||||
* @see https://tailwindcss.com/docs/padding
|
||||
@@ -671,25 +754,35 @@ export const getDefaultConfig = () => {
|
||||
*/
|
||||
m: [{ m: scaleMargin() }],
|
||||
/**
|
||||
* Margin X
|
||||
* Margin Inline
|
||||
* @see https://tailwindcss.com/docs/margin
|
||||
*/
|
||||
mx: [{ mx: scaleMargin() }],
|
||||
/**
|
||||
* Margin Y
|
||||
* Margin Block
|
||||
* @see https://tailwindcss.com/docs/margin
|
||||
*/
|
||||
my: [{ my: scaleMargin() }],
|
||||
/**
|
||||
* Margin Start
|
||||
* Margin Inline Start
|
||||
* @see https://tailwindcss.com/docs/margin
|
||||
*/
|
||||
ms: [{ ms: scaleMargin() }],
|
||||
/**
|
||||
* Margin End
|
||||
* Margin Inline End
|
||||
* @see https://tailwindcss.com/docs/margin
|
||||
*/
|
||||
me: [{ me: scaleMargin() }],
|
||||
/**
|
||||
* Margin Block Start
|
||||
* @see https://tailwindcss.com/docs/margin
|
||||
*/
|
||||
mbs: [{ mbs: scaleMargin() }],
|
||||
/**
|
||||
* Margin Block End
|
||||
* @see https://tailwindcss.com/docs/margin
|
||||
*/
|
||||
mbe: [{ mbe: scaleMargin() }],
|
||||
/**
|
||||
* Margin Top
|
||||
* @see https://tailwindcss.com/docs/margin
|
||||
@@ -740,6 +833,36 @@ export const getDefaultConfig = () => {
|
||||
* @see https://tailwindcss.com/docs/width#setting-both-width-and-height
|
||||
*/
|
||||
size: [{ size: scaleSizing() }],
|
||||
/**
|
||||
* Inline Size
|
||||
* @see https://tailwindcss.com/docs/width
|
||||
*/
|
||||
'inline-size': [{ inline: ['auto', ...scaleSizingInline()] }],
|
||||
/**
|
||||
* Min-Inline Size
|
||||
* @see https://tailwindcss.com/docs/min-width
|
||||
*/
|
||||
'min-inline-size': [{ 'min-inline': ['auto', ...scaleSizingInline()] }],
|
||||
/**
|
||||
* Max-Inline Size
|
||||
* @see https://tailwindcss.com/docs/max-width
|
||||
*/
|
||||
'max-inline-size': [{ 'max-inline': ['none', ...scaleSizingInline()] }],
|
||||
/**
|
||||
* Block Size
|
||||
* @see https://tailwindcss.com/docs/height
|
||||
*/
|
||||
'block-size': [{ block: ['auto', ...scaleSizingBlock()] }],
|
||||
/**
|
||||
* Min-Block Size
|
||||
* @see https://tailwindcss.com/docs/min-height
|
||||
*/
|
||||
'min-block-size': [{ 'min-block': ['auto', ...scaleSizingBlock()] }],
|
||||
/**
|
||||
* Max-Block Size
|
||||
* @see https://tailwindcss.com/docs/max-height
|
||||
*/
|
||||
'max-block-size': [{ 'max-block': ['none', ...scaleSizingBlock()] }],
|
||||
/**
|
||||
* Width
|
||||
* @see https://tailwindcss.com/docs/width
|
||||
@@ -819,7 +942,11 @@ export const getDefaultConfig = () => {
|
||||
* Font Weight
|
||||
* @see https://tailwindcss.com/docs/font-weight
|
||||
*/
|
||||
'font-weight': [{ font: [themeFontWeight, isArbitraryVariable, isArbitraryNumber] }],
|
||||
'font-weight': [
|
||||
{
|
||||
font: [themeFontWeight, isArbitraryVariableWeight, isArbitraryWeight],
|
||||
},
|
||||
],
|
||||
/**
|
||||
* Font Stretch
|
||||
* @see https://tailwindcss.com/docs/font-stretch
|
||||
@@ -845,7 +972,14 @@ export const getDefaultConfig = () => {
|
||||
* Font Family
|
||||
* @see https://tailwindcss.com/docs/font-family
|
||||
*/
|
||||
'font-family': [{ font: [isArbitraryVariableFamilyName, isArbitraryValue, themeFont] }],
|
||||
'font-family': [
|
||||
{ font: [isArbitraryVariableFamilyName, isArbitraryFamilyName, themeFont] },
|
||||
],
|
||||
/**
|
||||
* Font Feature Settings
|
||||
* @see https://tailwindcss.com/docs/font-feature-settings
|
||||
*/
|
||||
'font-features': [{ 'font-features': [isArbitraryValue] }],
|
||||
/**
|
||||
* Font Variant Numeric
|
||||
* @see https://tailwindcss.com/docs/font-variant-numeric
|
||||
@@ -991,6 +1125,11 @@ export const getDefaultConfig = () => {
|
||||
* @see https://tailwindcss.com/docs/text-indent
|
||||
*/
|
||||
indent: [{ indent: scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Tab Size
|
||||
* @see https://tailwindcss.com/docs/tab-size
|
||||
*/
|
||||
'tab-size': [{ tab: [isInteger, isArbitraryVariable, isArbitraryValue] }],
|
||||
/**
|
||||
* Vertical Alignment
|
||||
* @see https://tailwindcss.com/docs/vertical-align
|
||||
@@ -1217,25 +1356,35 @@ export const getDefaultConfig = () => {
|
||||
*/
|
||||
'border-w': [{ border: scaleBorderWidth() }],
|
||||
/**
|
||||
* Border Width X
|
||||
* Border Width Inline
|
||||
* @see https://tailwindcss.com/docs/border-width
|
||||
*/
|
||||
'border-w-x': [{ 'border-x': scaleBorderWidth() }],
|
||||
/**
|
||||
* Border Width Y
|
||||
* Border Width Block
|
||||
* @see https://tailwindcss.com/docs/border-width
|
||||
*/
|
||||
'border-w-y': [{ 'border-y': scaleBorderWidth() }],
|
||||
/**
|
||||
* Border Width Start
|
||||
* Border Width Inline Start
|
||||
* @see https://tailwindcss.com/docs/border-width
|
||||
*/
|
||||
'border-w-s': [{ 'border-s': scaleBorderWidth() }],
|
||||
/**
|
||||
* Border Width End
|
||||
* Border Width Inline End
|
||||
* @see https://tailwindcss.com/docs/border-width
|
||||
*/
|
||||
'border-w-e': [{ 'border-e': scaleBorderWidth() }],
|
||||
/**
|
||||
* Border Width Block Start
|
||||
* @see https://tailwindcss.com/docs/border-width
|
||||
*/
|
||||
'border-w-bs': [{ 'border-bs': scaleBorderWidth() }],
|
||||
/**
|
||||
* Border Width Block End
|
||||
* @see https://tailwindcss.com/docs/border-width
|
||||
*/
|
||||
'border-w-be': [{ 'border-be': scaleBorderWidth() }],
|
||||
/**
|
||||
* Border Width Top
|
||||
* @see https://tailwindcss.com/docs/border-width
|
||||
@@ -1292,25 +1441,35 @@ export const getDefaultConfig = () => {
|
||||
*/
|
||||
'border-color': [{ border: scaleColor() }],
|
||||
/**
|
||||
* Border Color X
|
||||
* Border Color Inline
|
||||
* @see https://tailwindcss.com/docs/border-color
|
||||
*/
|
||||
'border-color-x': [{ 'border-x': scaleColor() }],
|
||||
/**
|
||||
* Border Color Y
|
||||
* Border Color Block
|
||||
* @see https://tailwindcss.com/docs/border-color
|
||||
*/
|
||||
'border-color-y': [{ 'border-y': scaleColor() }],
|
||||
/**
|
||||
* Border Color S
|
||||
* Border Color Inline Start
|
||||
* @see https://tailwindcss.com/docs/border-color
|
||||
*/
|
||||
'border-color-s': [{ 'border-s': scaleColor() }],
|
||||
/**
|
||||
* Border Color E
|
||||
* Border Color Inline End
|
||||
* @see https://tailwindcss.com/docs/border-color
|
||||
*/
|
||||
'border-color-e': [{ 'border-e': scaleColor() }],
|
||||
/**
|
||||
* Border Color Block Start
|
||||
* @see https://tailwindcss.com/docs/border-color
|
||||
*/
|
||||
'border-color-bs': [{ 'border-bs': scaleColor() }],
|
||||
/**
|
||||
* Border Color Block End
|
||||
* @see https://tailwindcss.com/docs/border-color
|
||||
*/
|
||||
'border-color-be': [{ 'border-be': scaleColor() }],
|
||||
/**
|
||||
* Border Color Top
|
||||
* @see https://tailwindcss.com/docs/border-color
|
||||
@@ -1945,6 +2104,11 @@ export const getDefaultConfig = () => {
|
||||
* @see https://tailwindcss.com/docs/translate
|
||||
*/
|
||||
'translate-none': ['translate-none'],
|
||||
/**
|
||||
* Zoom
|
||||
* @see https://tailwindcss.com/docs/zoom
|
||||
*/
|
||||
zoom: [{ zoom: [isInteger, isArbitraryVariable, isArbitraryValue] }],
|
||||
|
||||
// ---------------------
|
||||
// --- Interactivity ---
|
||||
@@ -2040,31 +2204,61 @@ export const getDefaultConfig = () => {
|
||||
* @see https://tailwindcss.com/docs/scroll-behavior
|
||||
*/
|
||||
'scroll-behavior': [{ scroll: ['auto', 'smooth'] }],
|
||||
/**
|
||||
* Scrollbar Thumb Color
|
||||
* @see https://tailwindcss.com/docs/scrollbar-color
|
||||
*/
|
||||
'scrollbar-thumb-color': [{ 'scrollbar-thumb': scaleColor() }],
|
||||
/**
|
||||
* Scrollbar Track Color
|
||||
* @see https://tailwindcss.com/docs/scrollbar-color
|
||||
*/
|
||||
'scrollbar-track-color': [{ 'scrollbar-track': scaleColor() }],
|
||||
/**
|
||||
* Scrollbar Gutter
|
||||
* @see https://tailwindcss.com/docs/scrollbar-gutter
|
||||
*/
|
||||
'scrollbar-gutter': [{ 'scrollbar-gutter': ['auto', 'stable', 'both'] }],
|
||||
/**
|
||||
* Scrollbar Width
|
||||
* @see https://tailwindcss.com/docs/scrollbar-width
|
||||
*/
|
||||
'scrollbar-w': [{ scrollbar: ['auto', 'thin', 'none'] }],
|
||||
/**
|
||||
* Scroll Margin
|
||||
* @see https://tailwindcss.com/docs/scroll-margin
|
||||
*/
|
||||
'scroll-m': [{ 'scroll-m': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Margin X
|
||||
* Scroll Margin Inline
|
||||
* @see https://tailwindcss.com/docs/scroll-margin
|
||||
*/
|
||||
'scroll-mx': [{ 'scroll-mx': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Margin Y
|
||||
* Scroll Margin Block
|
||||
* @see https://tailwindcss.com/docs/scroll-margin
|
||||
*/
|
||||
'scroll-my': [{ 'scroll-my': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Margin Start
|
||||
* Scroll Margin Inline Start
|
||||
* @see https://tailwindcss.com/docs/scroll-margin
|
||||
*/
|
||||
'scroll-ms': [{ 'scroll-ms': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Margin End
|
||||
* Scroll Margin Inline End
|
||||
* @see https://tailwindcss.com/docs/scroll-margin
|
||||
*/
|
||||
'scroll-me': [{ 'scroll-me': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Margin Block Start
|
||||
* @see https://tailwindcss.com/docs/scroll-margin
|
||||
*/
|
||||
'scroll-mbs': [{ 'scroll-mbs': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Margin Block End
|
||||
* @see https://tailwindcss.com/docs/scroll-margin
|
||||
*/
|
||||
'scroll-mbe': [{ 'scroll-mbe': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Margin Top
|
||||
* @see https://tailwindcss.com/docs/scroll-margin
|
||||
@@ -2091,25 +2285,35 @@ export const getDefaultConfig = () => {
|
||||
*/
|
||||
'scroll-p': [{ 'scroll-p': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Padding X
|
||||
* Scroll Padding Inline
|
||||
* @see https://tailwindcss.com/docs/scroll-padding
|
||||
*/
|
||||
'scroll-px': [{ 'scroll-px': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Padding Y
|
||||
* Scroll Padding Block
|
||||
* @see https://tailwindcss.com/docs/scroll-padding
|
||||
*/
|
||||
'scroll-py': [{ 'scroll-py': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Padding Start
|
||||
* Scroll Padding Inline Start
|
||||
* @see https://tailwindcss.com/docs/scroll-padding
|
||||
*/
|
||||
'scroll-ps': [{ 'scroll-ps': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Padding End
|
||||
* Scroll Padding Inline End
|
||||
* @see https://tailwindcss.com/docs/scroll-padding
|
||||
*/
|
||||
'scroll-pe': [{ 'scroll-pe': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Padding Block Start
|
||||
* @see https://tailwindcss.com/docs/scroll-padding
|
||||
*/
|
||||
'scroll-pbs': [{ 'scroll-pbs': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Padding Block End
|
||||
* @see https://tailwindcss.com/docs/scroll-padding
|
||||
*/
|
||||
'scroll-pbe': [{ 'scroll-pbe': scaleUnambiguousSpacing() }],
|
||||
/**
|
||||
* Scroll Padding Top
|
||||
* @see https://tailwindcss.com/docs/scroll-padding
|
||||
@@ -2232,17 +2436,29 @@ export const getDefaultConfig = () => {
|
||||
'forced-color-adjust': [{ 'forced-color-adjust': ['auto', 'none'] }],
|
||||
},
|
||||
conflictingClassGroups: {
|
||||
'container-named': ['container-type'],
|
||||
overflow: ['overflow-x', 'overflow-y'],
|
||||
overscroll: ['overscroll-x', 'overscroll-y'],
|
||||
inset: ['inset-x', 'inset-y', 'start', 'end', 'top', 'right', 'bottom', 'left'],
|
||||
inset: [
|
||||
'inset-x',
|
||||
'inset-y',
|
||||
'inset-bs',
|
||||
'inset-be',
|
||||
'start',
|
||||
'end',
|
||||
'top',
|
||||
'right',
|
||||
'bottom',
|
||||
'left',
|
||||
],
|
||||
'inset-x': ['right', 'left'],
|
||||
'inset-y': ['top', 'bottom'],
|
||||
flex: ['basis', 'grow', 'shrink'],
|
||||
gap: ['gap-x', 'gap-y'],
|
||||
p: ['px', 'py', 'ps', 'pe', 'pt', 'pr', 'pb', 'pl'],
|
||||
p: ['px', 'py', 'ps', 'pe', 'pbs', 'pbe', 'pt', 'pr', 'pb', 'pl'],
|
||||
px: ['pr', 'pl'],
|
||||
py: ['pt', 'pb'],
|
||||
m: ['mx', 'my', 'ms', 'me', 'mt', 'mr', 'mb', 'ml'],
|
||||
m: ['mx', 'my', 'ms', 'me', 'mbs', 'mbe', 'mt', 'mr', 'mb', 'ml'],
|
||||
mx: ['mr', 'ml'],
|
||||
my: ['mt', 'mb'],
|
||||
size: ['w', 'h'],
|
||||
@@ -2288,6 +2504,8 @@ export const getDefaultConfig = () => {
|
||||
'border-w-y',
|
||||
'border-w-s',
|
||||
'border-w-e',
|
||||
'border-w-bs',
|
||||
'border-w-be',
|
||||
'border-w-t',
|
||||
'border-w-r',
|
||||
'border-w-b',
|
||||
@@ -2300,6 +2518,8 @@ export const getDefaultConfig = () => {
|
||||
'border-color-y',
|
||||
'border-color-s',
|
||||
'border-color-e',
|
||||
'border-color-bs',
|
||||
'border-color-be',
|
||||
'border-color-t',
|
||||
'border-color-r',
|
||||
'border-color-b',
|
||||
@@ -2314,6 +2534,8 @@ export const getDefaultConfig = () => {
|
||||
'scroll-my',
|
||||
'scroll-ms',
|
||||
'scroll-me',
|
||||
'scroll-mbs',
|
||||
'scroll-mbe',
|
||||
'scroll-mt',
|
||||
'scroll-mr',
|
||||
'scroll-mb',
|
||||
@@ -2326,6 +2548,8 @@ export const getDefaultConfig = () => {
|
||||
'scroll-py',
|
||||
'scroll-ps',
|
||||
'scroll-pe',
|
||||
'scroll-pbs',
|
||||
'scroll-pbe',
|
||||
'scroll-pt',
|
||||
'scroll-pr',
|
||||
'scroll-pb',
|
||||
@@ -2341,6 +2565,7 @@ export const getDefaultConfig = () => {
|
||||
conflictingClassGroupModifiers: {
|
||||
'font-size': ['leading'],
|
||||
},
|
||||
postfixLookupClassGroups: ['container-type'],
|
||||
orderSensitiveModifiers: [
|
||||
'*',
|
||||
'**',
|
||||
|
||||
+27
-7
@@ -4,8 +4,13 @@ import { IMPORTANT_MODIFIER } from './parse-class-name'
|
||||
const SPLIT_CLASSES_REGEX = /\s+/
|
||||
|
||||
export const mergeClassList = (classList: string, configUtils: ConfigUtils) => {
|
||||
const { parseClassName, getClassGroupId, getConflictingClassGroupIds, sortModifiers } =
|
||||
configUtils
|
||||
const {
|
||||
parseClassName,
|
||||
getClassGroupId,
|
||||
getConflictingClassGroupIds,
|
||||
sortModifiers,
|
||||
postfixLookupClassGroupIds,
|
||||
} = configUtils
|
||||
|
||||
/**
|
||||
* Set of classGroupIds in following format:
|
||||
@@ -36,11 +41,26 @@ export const mergeClassList = (classList: string, configUtils: ConfigUtils) => {
|
||||
}
|
||||
|
||||
let hasPostfixModifier = !!maybePostfixModifierPosition
|
||||
let classGroupId = getClassGroupId(
|
||||
hasPostfixModifier
|
||||
? baseClassName.substring(0, maybePostfixModifierPosition)
|
||||
: baseClassName,
|
||||
)
|
||||
let classGroupId: ReturnType<typeof getClassGroupId>
|
||||
|
||||
if (hasPostfixModifier) {
|
||||
const baseClassNameWithoutPostfix = baseClassName.substring(
|
||||
0,
|
||||
maybePostfixModifierPosition,
|
||||
)
|
||||
classGroupId = getClassGroupId(baseClassNameWithoutPostfix)
|
||||
|
||||
const classGroupIdWithPostfix =
|
||||
classGroupId && postfixLookupClassGroupIds[classGroupId]
|
||||
? getClassGroupId(baseClassName)
|
||||
: undefined
|
||||
if (classGroupIdWithPostfix && classGroupIdWithPostfix !== classGroupId) {
|
||||
classGroupId = classGroupIdWithPostfix
|
||||
hasPostfixModifier = false
|
||||
}
|
||||
} else {
|
||||
classGroupId = getClassGroupId(baseClassName)
|
||||
}
|
||||
|
||||
if (!classGroupId) {
|
||||
if (!hasPostfixModifier) {
|
||||
|
||||
+2
@@ -25,6 +25,7 @@ export const mergeConfigs = <ClassGroupIds extends string, ThemeGroupIds extends
|
||||
baseConfig.conflictingClassGroupModifiers,
|
||||
override.conflictingClassGroupModifiers,
|
||||
)
|
||||
overrideProperty(baseConfig, 'postfixLookupClassGroups', override.postfixLookupClassGroups)
|
||||
overrideProperty(baseConfig, 'orderSensitiveModifiers', override.orderSensitiveModifiers)
|
||||
|
||||
mergeConfigProperties(baseConfig.theme, extend.theme)
|
||||
@@ -34,6 +35,7 @@ export const mergeConfigs = <ClassGroupIds extends string, ThemeGroupIds extends
|
||||
baseConfig.conflictingClassGroupModifiers,
|
||||
extend.conflictingClassGroupModifiers,
|
||||
)
|
||||
mergeArrayProperties(baseConfig, extend, 'postfixLookupClassGroups')
|
||||
mergeArrayProperties(baseConfig, extend, 'orderSensitiveModifiers')
|
||||
|
||||
return baseConfig
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
export type ClassNameValue = ClassNameArray | string | null | undefined | 0 | 0n | false
|
||||
type ClassNameArray = ClassNameValue[]
|
||||
type ClassNameArray = readonly ClassNameValue[]
|
||||
|
||||
export const twJoin = (...classLists: ClassNameValue[]): string => {
|
||||
let index = 0
|
||||
|
||||
+61
-9
@@ -2,8 +2,7 @@
|
||||
* Type the tailwind-merge configuration adheres to.
|
||||
*/
|
||||
export interface Config<ClassGroupIds extends string, ThemeGroupIds extends string>
|
||||
extends ConfigStaticPart,
|
||||
ConfigGroupsPart<ClassGroupIds, ThemeGroupIds> {}
|
||||
extends ConfigStaticPart, ConfigGroupsPart<ClassGroupIds, ThemeGroupIds> {}
|
||||
|
||||
/**
|
||||
* The static part of the tailwind-merge configuration. When merging multiple configurations, the properties of this interface are always overridden.
|
||||
@@ -75,7 +74,7 @@ export interface ParsedClassName {
|
||||
*
|
||||
* This property is prefixed with "maybe" because tailwind-merge does not know whether something is a postfix modifier or part of the base class since it's possible to configure Tailwind CSS classes which include a `/` in the base class name.
|
||||
*
|
||||
* If a `maybePostfixModifierPosition` is present, tailwind-merge first tries to match the `baseClassName` without the possible postfix modifier to a class group. If that fails, it tries again with the possible postfix modifier.
|
||||
* If a `maybePostfixModifierPosition` is present, tailwind-merge first tries to match the `baseClassName` without the possible postfix modifier to a class group. If that fails or the matched class group is configured in `postfixLookupClassGroups`, it tries again with the possible postfix modifier.
|
||||
*
|
||||
* @example 11 // for `bg-gray-100/50`
|
||||
*/
|
||||
@@ -124,6 +123,14 @@ interface ConfigGroupsPart<ClassGroupIds extends string, ThemeGroupIds extends s
|
||||
conflictingClassGroupModifiers: NoInfer<
|
||||
Partial<Record<ClassGroupIds, readonly ClassGroupIds[]>>
|
||||
>
|
||||
/**
|
||||
* Class group IDs which should be resolved again with their postfix modifier attached.
|
||||
*
|
||||
* This is needed when a slash can make the full class name belong to a different class group than the part before the slash.
|
||||
*
|
||||
* @example ['container-type'] // `@container-size/sidebar` should resolve differently from `@container-size`
|
||||
*/
|
||||
postfixLookupClassGroups?: readonly NoInferString<ClassGroupIds>[]
|
||||
/**
|
||||
* Modifiers whose order among multiple modifiers should be preserved because their order changes which element gets targeted.
|
||||
*
|
||||
@@ -135,14 +142,23 @@ interface ConfigGroupsPart<ClassGroupIds extends string, ThemeGroupIds extends s
|
||||
/**
|
||||
* Type of the configuration object that can be passed to `extendTailwindMerge`.
|
||||
*/
|
||||
export interface ConfigExtension<ClassGroupIds extends string, ThemeGroupIds extends string>
|
||||
extends Partial<ConfigStaticPart> {
|
||||
override?: PartialPartial<ConfigGroupsPart<ClassGroupIds, ThemeGroupIds>>
|
||||
extend?: PartialPartial<ConfigGroupsPart<ClassGroupIds, ThemeGroupIds>>
|
||||
export interface ConfigExtension<
|
||||
ClassGroupIds extends string,
|
||||
ThemeGroupIds extends string,
|
||||
> extends Partial<ConfigStaticPart> {
|
||||
override?: PartialConfigGroupsPart<ClassGroupIds, ThemeGroupIds>
|
||||
extend?: PartialConfigGroupsPart<ClassGroupIds, ThemeGroupIds>
|
||||
}
|
||||
|
||||
type PartialPartial<T> = {
|
||||
[P in keyof T]?: T[P] extends any[] ? T[P] : Partial<T[P]>
|
||||
interface PartialConfigGroupsPart<ClassGroupIds extends string, ThemeGroupIds extends string> {
|
||||
theme?: NoInfer<Partial<ThemeObject<ThemeGroupIds>>>
|
||||
classGroups?: NoInfer<Partial<Record<ClassGroupIds, ClassGroup<ThemeGroupIds>>>>
|
||||
conflictingClassGroups?: NoInfer<Partial<Record<ClassGroupIds, readonly ClassGroupIds[]>>>
|
||||
conflictingClassGroupModifiers?: NoInfer<
|
||||
Partial<Record<ClassGroupIds, readonly ClassGroupIds[]>>
|
||||
>
|
||||
postfixLookupClassGroups?: readonly NoInferString<ClassGroupIds>[]
|
||||
orderSensitiveModifiers?: string[]
|
||||
}
|
||||
|
||||
export type ThemeObject<ThemeGroupIds extends string> = Record<
|
||||
@@ -172,6 +188,13 @@ type ClassObject<ThemeGroupIds extends string> = Record<
|
||||
*/
|
||||
export type NoInfer<T> = [T][T extends any ? 0 : never]
|
||||
|
||||
/**
|
||||
* Special-purpose NoInfer variant for string unions used in array item positions.
|
||||
*
|
||||
* The NoInfer helper above doesn't prevent inference from array items in all cases, so this keeps config arrays like `postfixLookupClassGroups` from defining or narrowing class group IDs. Once tailwind-merge only supports TypeScript 5.4 and newer, this can be replaced with TypeScript's built-in NoInfer utility type.
|
||||
*/
|
||||
type NoInferString<T extends string> = T extends infer S ? S & string : never
|
||||
|
||||
/**
|
||||
* Theme group IDs included in the default configuration of tailwind-merge.
|
||||
*
|
||||
@@ -236,9 +259,12 @@ export type DefaultClassGroupIds =
|
||||
| 'bg-position'
|
||||
| 'bg-repeat'
|
||||
| 'bg-size'
|
||||
| 'block-size'
|
||||
| 'blur'
|
||||
| 'border-collapse'
|
||||
| 'border-color-b'
|
||||
| 'border-color-be'
|
||||
| 'border-color-bs'
|
||||
| 'border-color-e'
|
||||
| 'border-color-l'
|
||||
| 'border-color-r'
|
||||
@@ -252,6 +278,8 @@ export type DefaultClassGroupIds =
|
||||
| 'border-spacing'
|
||||
| 'border-style'
|
||||
| 'border-w-b'
|
||||
| 'border-w-be'
|
||||
| 'border-w-bs'
|
||||
| 'border-w-e'
|
||||
| 'border-w-l'
|
||||
| 'border-w-r'
|
||||
@@ -277,6 +305,8 @@ export type DefaultClassGroupIds =
|
||||
| 'color-scheme'
|
||||
| 'columns'
|
||||
| 'container'
|
||||
| 'container-named'
|
||||
| 'container-type'
|
||||
| 'content'
|
||||
| 'contrast'
|
||||
| 'cursor'
|
||||
@@ -301,6 +331,7 @@ export type DefaultClassGroupIds =
|
||||
| 'flex'
|
||||
| 'float'
|
||||
| 'font-family'
|
||||
| 'font-features'
|
||||
| 'font-size'
|
||||
| 'font-smoothing'
|
||||
| 'font-stretch'
|
||||
@@ -331,10 +362,13 @@ export type DefaultClassGroupIds =
|
||||
| 'hue-rotate'
|
||||
| 'hyphens'
|
||||
| 'indent'
|
||||
| 'inline-size'
|
||||
| 'inset-ring-color'
|
||||
| 'inset-ring-w'
|
||||
| 'inset-shadow-color'
|
||||
| 'inset-shadow'
|
||||
| 'inset-be'
|
||||
| 'inset-bs'
|
||||
| 'inset-x'
|
||||
| 'inset-y'
|
||||
| 'inset'
|
||||
@@ -401,11 +435,17 @@ export type DefaultClassGroupIds =
|
||||
| 'mask-repeat'
|
||||
| 'mask-size'
|
||||
| 'mask-type'
|
||||
| 'max-block-size'
|
||||
| 'max-h'
|
||||
| 'max-inline-size'
|
||||
| 'max-w'
|
||||
| 'mb'
|
||||
| 'mbe'
|
||||
| 'mbs'
|
||||
| 'me'
|
||||
| 'min-block-size'
|
||||
| 'min-h'
|
||||
| 'min-inline-size'
|
||||
| 'min-w'
|
||||
| 'mix-blend'
|
||||
| 'ml'
|
||||
@@ -430,6 +470,7 @@ export type DefaultClassGroupIds =
|
||||
| 'overscroll'
|
||||
| 'p'
|
||||
| 'pb'
|
||||
| 'pbe'
|
||||
| 'pe'
|
||||
| 'perspective-origin'
|
||||
| 'perspective'
|
||||
@@ -442,6 +483,7 @@ export type DefaultClassGroupIds =
|
||||
| 'position'
|
||||
| 'pr'
|
||||
| 'ps'
|
||||
| 'pbs'
|
||||
| 'pt'
|
||||
| 'px'
|
||||
| 'py'
|
||||
@@ -480,21 +522,29 @@ export type DefaultClassGroupIds =
|
||||
| 'scale-y'
|
||||
| 'scale-z'
|
||||
| 'scale'
|
||||
| 'scrollbar-gutter'
|
||||
| 'scrollbar-thumb-color'
|
||||
| 'scrollbar-track-color'
|
||||
| 'scrollbar-w'
|
||||
| 'scroll-behavior'
|
||||
| 'scroll-m'
|
||||
| 'scroll-mb'
|
||||
| 'scroll-mbe'
|
||||
| 'scroll-me'
|
||||
| 'scroll-ml'
|
||||
| 'scroll-mr'
|
||||
| 'scroll-mbs'
|
||||
| 'scroll-ms'
|
||||
| 'scroll-mt'
|
||||
| 'scroll-mx'
|
||||
| 'scroll-my'
|
||||
| 'scroll-p'
|
||||
| 'scroll-pb'
|
||||
| 'scroll-pbe'
|
||||
| 'scroll-pe'
|
||||
| 'scroll-pl'
|
||||
| 'scroll-pr'
|
||||
| 'scroll-pbs'
|
||||
| 'scroll-ps'
|
||||
| 'scroll-pt'
|
||||
| 'scroll-px'
|
||||
@@ -521,6 +571,7 @@ export type DefaultClassGroupIds =
|
||||
| 'stroke-w'
|
||||
| 'stroke'
|
||||
| 'table-layout'
|
||||
| 'tab-size'
|
||||
| 'text-alignment'
|
||||
| 'text-color'
|
||||
| 'text-decoration-color'
|
||||
@@ -555,6 +606,7 @@ export type DefaultClassGroupIds =
|
||||
| 'whitespace'
|
||||
| 'will-change'
|
||||
| 'wrap'
|
||||
| 'zoom'
|
||||
| 'z'
|
||||
|
||||
export type AnyClassGroupIds = string
|
||||
|
||||
+17
-1
@@ -1,6 +1,6 @@
|
||||
const arbitraryValueRegex = /^\[(?:(\w[\w-]*):)?(.+)\]$/i
|
||||
const arbitraryVariableRegex = /^\((?:(\w[\w-]*):)?(.+)\)$/i
|
||||
const fractionRegex = /^\d+\/\d+$/
|
||||
const fractionRegex = /^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/
|
||||
const tshirtUnitRegex = /^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/
|
||||
const lengthUnitRegex =
|
||||
/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/
|
||||
@@ -37,6 +37,12 @@ const isImage = (value: string) => imageRegex.test(value)
|
||||
export const isAnyNonArbitrary = (value: string) =>
|
||||
!isArbitraryValue(value) && !isArbitraryVariable(value)
|
||||
|
||||
export const isNamedContainerQuery = (value: string) =>
|
||||
value.startsWith('@container') &&
|
||||
((value[10] === '/' && value[11] !== undefined) ||
|
||||
(value[11] === 's' && value[16] !== undefined && value.startsWith('-size/', 10)) ||
|
||||
(value[11] === 'n' && value[18] !== undefined && value.startsWith('-normal/', 10)))
|
||||
|
||||
export const isArbitrarySize = (value: string) => getIsArbitraryValue(value, isLabelSize, isNever)
|
||||
|
||||
export const isArbitraryValue = (value: string) => arbitraryValueRegex.test(value)
|
||||
@@ -47,6 +53,11 @@ export const isArbitraryLength = (value: string) =>
|
||||
export const isArbitraryNumber = (value: string) =>
|
||||
getIsArbitraryValue(value, isLabelNumber, isNumber)
|
||||
|
||||
export const isArbitraryWeight = (value: string) => getIsArbitraryValue(value, isLabelWeight, isAny)
|
||||
|
||||
export const isArbitraryFamilyName = (value: string) =>
|
||||
getIsArbitraryValue(value, isLabelFamilyName, isNever)
|
||||
|
||||
export const isArbitraryPosition = (value: string) =>
|
||||
getIsArbitraryValue(value, isLabelPosition, isNever)
|
||||
|
||||
@@ -74,6 +85,9 @@ export const isArbitraryVariableImage = (value: string) =>
|
||||
export const isArbitraryVariableShadow = (value: string) =>
|
||||
getIsArbitraryVariable(value, isLabelShadow, true)
|
||||
|
||||
export const isArbitraryVariableWeight = (value: string) =>
|
||||
getIsArbitraryVariable(value, isLabelWeight, true)
|
||||
|
||||
// Helpers
|
||||
|
||||
const getIsArbitraryValue = (
|
||||
@@ -125,4 +139,6 @@ const isLabelNumber = (label: string) => label === 'number'
|
||||
|
||||
const isLabelFamilyName = (label: string) => label === 'family-name'
|
||||
|
||||
const isLabelWeight = (label: string) => label === 'number' || label === 'weight'
|
||||
|
||||
const isLabelShadow = (label: string) => label === 'shadow'
|
||||
|
||||
Reference in New Issue
Block a user