Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Sort fractions last within a group
  • Loading branch information
thecrypticace committed Feb 11, 2025
commit 5653543c4738deacac1157932968ab1986a98fdb
77 changes: 76 additions & 1 deletion packages/tailwindcss/src/intellisense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,32 @@ import { styleRule, walkDepth } from './ast'
import { applyVariant } from './compile'
import type { DesignSystem } from './design-system'
import { compare } from './utils/compare'
import { DefaultMap } from './utils/default-map'

interface ClassMetadata {
modifiers: string[]
}

export type ClassItem = {
name: string
utility: string
fraction: boolean
modifiers: string[]
}

export type ClassEntry = [string, ClassMetadata]

const IS_FRACTION = /^\d+\/\d+$/

export function getClassList(design: DesignSystem): ClassEntry[] {
let list: ClassItem[] = []

// Static utilities only work as-is
for (let utility of design.utilities.keys('static')) {
list.push({
name: utility,
utility,
fraction: false,
modifiers: [],
})
}
Expand All @@ -37,12 +44,16 @@ export function getClassList(design: DesignSystem): ClassEntry[] {

list.push({
name,
utility,
fraction,
modifiers: group.modifiers,
})

if (group.supportsNegative) {
list.push({
name: `-${name}`,
utility: `-${utility}`,
fraction,
modifiers: group.modifiers,
})
}
Expand All @@ -55,7 +66,71 @@ export function getClassList(design: DesignSystem): ClassEntry[] {
// Sort utilities by their class name
list.sort((a, b) => compare(a.name, b.name))

return list.map((item) => [item.name, { modifiers: item.modifiers }])
let entries = sortFractionsLast(list)

return entries
}

function sortFractionsLast(list: ClassItem[]) {
type Bucket = {
utility: string
items: ClassItem[]
}

// 1. Create "buckets" for each utility group
let buckets: Bucket[] = []
let current: Bucket | null = null

// 2. Determine the last bucket for each utility group
let lastUtilityBucket = new Map<string, Bucket>()

// 3. Collect all fractions in a given utility group
let fractions = new DefaultMap<string, ClassItem[]>(() => [])

for (let item of list) {
let { utility, fraction } = item

if (!current) {
current = { utility, items: [] }
lastUtilityBucket.set(utility, current)
}

if (utility !== current.utility) {
buckets.push(current)

current = { utility, items: [] }
lastUtilityBucket.set(utility, current)
}

if (fraction) {
fractions.get(utility).push(item)
} else {
current.items.push(item)
}
}

if (current && buckets[buckets.length - 1] !== current) {
buckets.push(current)
}

// 4. Add fractions to their respective last utility buckets
for (let [utility, items] of fractions) {
let bucket = lastUtilityBucket.get(utility)
if (!bucket) continue

bucket.items.push(...items)
}

// 5. Flatten the buckets into a single list
let entries: ClassEntry[] = []

for (let bucket of buckets) {
for (let entry of bucket.items) {
entries.push([entry.name, { modifiers: entry.modifiers }])
}
}

return entries
}

interface SelectorOptions {
Expand Down