From 1eb376533ecee74007ebfcef6887fe7a754aaed3 Mon Sep 17 00:00:00 2001 From: phucbm Date: Wed, 23 Apr 2025 15:02:14 +0700 Subject: [PATCH] feat: Add max-width container query support - Allow configuration of max-width container queries using object syntax - Support both string values (min-width) and object values with max/min properties - Sort max-width queries in descending order - Maintain backward compatibility with original string-based configuration - Add proper TypeScript type definitions --- src/index.ts | 56 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index 84b9869..7f4c18d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,33 @@ import plugin from 'tailwindcss/plugin' +type ContainerValue = string | { min?: string; max?: string } +type QueryType = 'min-width' | 'max-width' + export = plugin( function containerQueries({ matchUtilities, matchVariant, theme }) { - let values: Record = theme('containers') ?? {} + let values: Record = theme('containers') ?? {} + + // Process the container values to support both string and object formats + let processedValues: Record = {} + let queryTypes: Record = {} + + // Transform the theme values into a format we can use + for (const [key, value] of Object.entries(values)) { + if (typeof value === 'string') { + // String value - use as min-width (original behavior) + processedValues[key] = value + queryTypes[key] = 'min-width' + } else if (typeof value === 'object' && value !== null) { + // Object with min/max properties + if (value.min) { + processedValues[key] = value.min + queryTypes[key] = 'min-width' + } else if (value.max) { + processedValues[key] = value.max + queryTypes[key] = 'max-width' + } + } + } function parseValue(value: string) { let numericValue = value.match(/^(\d+\.\d+|\d+|\.\d+)\D+/)?.[1] ?? null @@ -34,18 +59,39 @@ export = plugin( (value = '', { modifier }) => { let parsed = parseValue(value) - return parsed !== null ? `@container ${modifier ?? ''} (min-width: ${value})` : [] + // Find the key for this value to determine query type + const key = Object.keys(processedValues).find(k => processedValues[k] === value) + const queryType = key ? queryTypes[key] : 'min-width' + + return parsed !== null ? `@container ${modifier ?? ''} (${queryType}: ${value})` : [] }, { - values, + values: processedValues, sort(aVariant, zVariant) { let a = parseFloat(aVariant.value) let z = parseFloat(zVariant.value) if (a === null || z === null) return 0 - // Sort values themselves regardless of unit - if (a - z !== 0) return a - z + // Find keys to determine query types + const aKey = Object.keys(processedValues).find(k => processedValues[k] === aVariant.value) + const zKey = Object.keys(processedValues).find(k => processedValues[k] === zVariant.value) + + const aType = aKey ? queryTypes[aKey] : 'min-width' + const zType = zKey ? queryTypes[zKey] : 'min-width' + + // If they have different types, sort max-width first + if (aType !== zType) { + return aType === 'max-width' ? -1 : 1 + } + + // For max-width queries, we want descending order + if (aType === 'max-width') { + if (a - z !== 0) return z - a + } else { + // Original sort logic for min-width + if (a - z !== 0) return a - z + } let aLabel = aVariant.modifier ?? '' let zLabel = zVariant.modifier ?? ''