@@ -49,19 +49,24 @@ function getKeywordColor(value: unknown): KeywordColor | null {
4949 return null
5050}
5151
52- function getColorsInString ( state : State , str : string ) : ParsedColor [ ] {
52+ function getColorsInString (
53+ state : State ,
54+ str : string ,
55+ colorScheme : 'light' | 'dark' = 'light' ,
56+ ) : ParsedColor [ ] {
5357 if ( / (?: b o x | d r o p ) - s h a d o w / . test ( str ) && ! / - - t w - d r o p - s h a d o w / . test ( str ) ) return [ ]
5458
5559 str = replaceCssVarsWithFallbacks ( state , str )
5660 str = removeColorMixWherePossible ( str )
57- str = resolveLightDark ( str )
61+ str = resolveLightDark ( str , colorScheme )
5862
5963 return parseColors ( str )
6064}
6165
6266function getColorFromDecls (
6367 state : State ,
6468 decls : Record < string , string | string [ ] > ,
69+ colorScheme : 'light' | 'dark' = 'light' ,
6570) : ParsedColor | null {
6671 let props = Object . keys ( decls ) . filter ( ( prop ) => {
6772 // ignore content: "";
@@ -104,7 +109,7 @@ function getColorFromDecls(
104109 const propsToCheck = areAllCustom ? props : nonCustomProps
105110
106111 const colors = propsToCheck . flatMap ( ( prop ) =>
107- ensureArray ( decls [ prop ] ) . flatMap ( ( str ) => getColorsInString ( state , str ) ) ,
112+ ensureArray ( decls [ prop ] ) . flatMap ( ( str ) => getColorsInString ( state , str , colorScheme ) ) ,
108113 )
109114
110115 // check that all of the values are the same color, ignoring alpha
@@ -137,7 +142,11 @@ function getColorFromDecls(
137142 return null
138143}
139144
140- function getColorFromRoot ( state : State , css : AstNode [ ] ) : ParsedColor | null {
145+ function getColorFromRoot (
146+ state : State ,
147+ css : AstNode [ ] ,
148+ colorScheme : 'light' | 'dark' = 'light' ,
149+ ) : ParsedColor | null {
141150 let decls : Record < string , string [ ] > = { }
142151
143152 walk ( css , ( node ) => {
@@ -171,7 +180,7 @@ function getColorFromRoot(state: State, css: AstNode[]): ParsedColor | null {
171180 return WalkAction . Continue
172181 } )
173182
174- return getColorFromDecls ( state , decls )
183+ return getColorFromDecls ( state , decls , colorScheme )
175184}
176185
177186let isNegative = / ^ - /
@@ -190,13 +199,17 @@ function isLikelyColorless(className: string) {
190199 return false
191200}
192201
193- export function getColor ( state : State , className : string ) : ParsedColor | null {
202+ export function getColor (
203+ state : State ,
204+ className : string ,
205+ colorScheme : 'light' | 'dark' = 'light' ,
206+ ) : ParsedColor | null {
194207 if ( state . v4 ) {
195208 // FIXME: This is a performance optimization and not strictly correct
196209 if ( isLikelyColorless ( className ) ) return null
197210
198211 let css = state . designSystem . compile ( [ className ] ) [ 0 ]
199- let color = getColorFromRoot ( state , css )
212+ let color = getColorFromRoot ( state , css , colorScheme )
200213
201214 let prefix = state . designSystem . theme . prefix ?? ''
202215
@@ -205,7 +218,7 @@ export function getColor(state: State, className: string): ParsedColor | null {
205218 if ( prefix && ! color && ! className . startsWith ( prefix + ':' ) ) {
206219 className = `${ prefix } :${ className } `
207220 css = state . designSystem . compile ( [ className ] ) [ 0 ]
208- color = getColorFromRoot ( state , css )
221+ color = getColorFromRoot ( state , css , colorScheme )
209222 }
210223
211224 return color
@@ -215,7 +228,7 @@ export function getColor(state: State, className: string): ParsedColor | null {
215228 if ( state . classNames ) {
216229 const item = dlv ( state . classNames . classNames , [ className , '__info' ] )
217230 if ( item && item . __rule ) {
218- return getColorFromDecls ( state , removeMeta ( item ) )
231+ return getColorFromDecls ( state , removeMeta ( item ) , colorScheme )
219232 }
220233 }
221234
@@ -244,7 +257,7 @@ export function getColor(state: State, className: string): ParsedColor | null {
244257 decls [ decl . prop ] = decl . value
245258 }
246259 } )
247- return getColorFromDecls ( state , decls )
260+ return getColorFromDecls ( state , decls , colorScheme )
248261 }
249262
250263 let parts = getClassNameParts ( state , className )
@@ -253,7 +266,7 @@ export function getColor(state: State, className: string): ParsedColor | null {
253266 const item = dlv ( state . classNames . classNames , [ ...parts , '__info' ] )
254267 if ( ! item . __rule ) return null
255268
256- return getColorFromDecls ( state , removeMeta ( item ) )
269+ return getColorFromDecls ( state , removeMeta ( item ) , colorScheme )
257270}
258271
259272export function getColorFromValue ( value : unknown ) : ParsedColor | null {
@@ -315,10 +328,56 @@ function removeColorMixWherePossible(str: string) {
315328 } )
316329}
317330
318- const LIGHT_DARK_REGEX = / l i g h t - d a r k \( \s * ( .* ?) \s * , \s * .* ?\s * \) / g
331+ const LIGHT_DARK_START = / l i g h t - d a r k \( \s * / g
332+
333+ export function resolveLightDark (
334+ str : string ,
335+ colorScheme : 'light' | 'dark' = 'light' ,
336+ ) : string {
337+ let result = ''
338+ let lastIndex = 0
339+ let match : RegExpExecArray | null
340+
341+ LIGHT_DARK_START . lastIndex = 0
342+
343+ while ( ( match = LIGHT_DARK_START . exec ( str ) ) !== null ) {
344+ result += str . slice ( lastIndex , match . index )
345+
346+ let start = match . index + match [ 0 ] . length
347+ let depth = 1
348+ let commaIndex = - 1
349+ let i = start
350+
351+ // Find the comma separating light and dark values, handling nested parentheses
352+ while ( i < str . length && depth > 0 ) {
353+ let char = str [ i ]
354+ if ( char === '(' ) {
355+ depth ++
356+ } else if ( char === ')' ) {
357+ depth --
358+ } else if ( char === ',' && depth === 1 && commaIndex === - 1 ) {
359+ commaIndex = i
360+ }
361+ i ++
362+ }
363+
364+ if ( commaIndex === - 1 || depth !== 0 ) {
365+ // Invalid light-dark() syntax, keep original
366+ result += match [ 0 ]
367+ lastIndex = start
368+ continue
369+ }
370+
371+ let lightColor = str . slice ( start , commaIndex ) . trim ( )
372+ let darkColor = str . slice ( commaIndex + 1 , i - 1 ) . trim ( )
373+
374+ result += colorScheme === 'light' ? lightColor : darkColor
375+ lastIndex = i
376+ LIGHT_DARK_START . lastIndex = i
377+ }
319378
320- function resolveLightDark ( str : string ) {
321- return str . replace ( LIGHT_DARK_REGEX , ( _ , lightColor ) => lightColor )
379+ result += str . slice ( lastIndex )
380+ return result
322381}
323382
324383const COLOR_FNS = new Set ( [
0 commit comments