@@ -2,46 +2,89 @@ import type { Theme } from '@clerk/types';
2
2
3
3
import { spaceScaleKeys } from '../foundations/sizes' ;
4
4
import type { fontSizes , fontWeights } from '../foundations/typography' ;
5
- import { colorOptionToHslaAlphaScale , colorOptionToHslaLightnessScale } from '../utils/colorOptionToHslaScale' ;
6
5
import { colors } from '../utils/colors' ;
6
+ import { colorOptionToThemedAlphaScale , colorOptionToThemedLightnessScale } from '../utils/colors/scales' ;
7
+ import { cssSupports } from '../utils/cssSupports' ;
7
8
import { fromEntries } from '../utils/fromEntries' ;
8
9
import { removeUndefinedProps } from '../utils/removeUndefinedProps' ;
9
10
10
11
export const createColorScales = ( theme : Theme ) => {
11
- const variables = theme . variables || { } ;
12
+ const variables = removeInvalidValues ( theme . variables || { } ) ;
12
13
13
- const primaryScale = colorOptionToHslaLightnessScale ( variables . colorPrimary , 'primary' ) ;
14
- const primaryAlphaScale = colorOptionToHslaAlphaScale ( primaryScale ?. primary500 , 'primaryAlpha' ) ;
15
- const dangerScale = colorOptionToHslaLightnessScale ( variables . colorDanger , 'danger' ) ;
16
- const dangerAlphaScale = colorOptionToHslaAlphaScale ( dangerScale ?. danger500 , 'dangerAlpha' ) ;
17
- const successScale = colorOptionToHslaLightnessScale ( variables . colorSuccess , 'success' ) ;
18
- const successAlphaScale = colorOptionToHslaAlphaScale ( successScale ?. success500 , 'successAlpha' ) ;
19
- const warningScale = colorOptionToHslaLightnessScale ( variables . colorWarning , 'warning' ) ;
20
- const warningAlphaScale = colorOptionToHslaAlphaScale ( warningScale ?. warning500 , 'warningAlpha' ) ;
14
+ const dangerScale = colorOptionToThemedLightnessScale ( variables . colorDanger , 'danger' ) ;
15
+ const primaryScale = colorOptionToThemedLightnessScale ( variables . colorPrimary , 'primary' ) ;
16
+ const successScale = colorOptionToThemedLightnessScale ( variables . colorSuccess , 'success' ) ;
17
+ const warningScale = colorOptionToThemedLightnessScale ( variables . colorWarning , 'warning' ) ;
18
+
19
+ const dangerAlphaScale = colorOptionToThemedAlphaScale ( dangerScale ?. danger500 , 'dangerAlpha' ) ;
20
+ const neutralAlphaScale = colorOptionToThemedAlphaScale ( variables . colorNeutral , 'neutralAlpha' ) ;
21
+ const primaryAlphaScale = colorOptionToThemedAlphaScale ( primaryScale ?. primary500 , 'primaryAlpha' ) ;
22
+ const successAlphaScale = colorOptionToThemedAlphaScale ( successScale ?. success500 , 'successAlpha' ) ;
23
+ const warningAlphaScale = colorOptionToThemedAlphaScale ( warningScale ?. warning500 , 'warningAlpha' ) ;
21
24
22
25
return removeUndefinedProps ( {
23
- ...primaryScale ,
24
- ...primaryAlphaScale ,
25
26
...dangerScale ,
26
- ...dangerAlphaScale ,
27
+ ...primaryScale ,
27
28
...successScale ,
28
- ...successAlphaScale ,
29
29
...warningScale ,
30
+ ...dangerAlphaScale ,
31
+ ...neutralAlphaScale ,
32
+ ...primaryAlphaScale ,
33
+ ...successAlphaScale ,
30
34
...warningAlphaScale ,
31
- ...colorOptionToHslaAlphaScale ( variables . colorNeutral , 'neutralAlpha' ) ,
32
35
primaryHover : colors . adjustForLightness ( primaryScale ?. primary500 ) ,
33
- colorTextOnPrimaryBackground : toHSLA ( variables . colorTextOnPrimaryBackground ) ,
34
- colorText : toHSLA ( variables . colorText ) ,
35
- colorTextSecondary : toHSLA ( variables . colorTextSecondary ) || colors . makeTransparent ( variables . colorText , 0.35 ) ,
36
- colorInputText : toHSLA ( variables . colorInputText ) ,
37
- colorBackground : toHSLA ( variables . colorBackground ) ,
38
- colorInputBackground : toHSLA ( variables . colorInputBackground ) ,
39
- colorShimmer : toHSLA ( variables . colorShimmer ) ,
36
+ colorTextOnPrimaryBackground : colors . toHslaString ( variables . colorTextOnPrimaryBackground ) ,
37
+ colorText : colors . toHslaString ( variables . colorText ) ,
38
+ colorTextSecondary :
39
+ colors . toHslaString ( variables . colorTextSecondary ) || colors . makeTransparent ( variables . colorText , 0.35 ) ,
40
+ colorInputText : colors . toHslaString ( variables . colorInputText ) ,
41
+ colorBackground : colors . toHslaString ( variables . colorBackground ) ,
42
+ colorInputBackground : colors . toHslaString ( variables . colorInputBackground ) ,
43
+ colorShimmer : colors . toHslaString ( variables . colorShimmer ) ,
40
44
} ) ;
41
45
} ;
42
46
43
- export const toHSLA = ( str : string | undefined ) => {
44
- return str ? colors . toHslaString ( str ) : undefined ;
47
+ export const removeInvalidValues = ( variables : NonNullable < Theme [ 'variables' ] > ) : NonNullable < Theme [ 'variables' ] > => {
48
+ // Check for modern color support. If present, we can simply return the variables as-is since we support everything
49
+ // CSS supports.
50
+ if ( cssSupports . modernColor ( ) ) {
51
+ return variables ;
52
+ }
53
+
54
+ // If not, we need to remove any values that are specified with CSS variables, as our color scale generation only
55
+ // supports CSS variables using modern CSS functionality.
56
+ const validVariables : Theme [ 'variables' ] = Object . fromEntries (
57
+ Object . entries ( variables ) . filter ( ( [ key , value ] ) => {
58
+ if ( typeof value === 'string' ) {
59
+ const isValid = ! value . startsWith ( 'var(' ) ;
60
+ if ( ! isValid ) {
61
+ console . warn (
62
+ `Invalid color value: ${ value } for key: ${ key } , using default value instead. Using CSS variables is not supported in this browser.` ,
63
+ ) ;
64
+ }
65
+ return isValid ;
66
+ }
67
+
68
+ if ( typeof value === 'object' ) {
69
+ return Object . entries ( value ) . every ( ( [ key , value ] ) => {
70
+ if ( typeof value !== 'string' ) return true ;
71
+
72
+ const isValid = ! value . startsWith ( 'var(' ) ;
73
+ if ( ! isValid ) {
74
+ console . warn (
75
+ `Invalid color value: ${ value } for key: ${ key } , using default value instead. Using CSS variables is not supported in this browser.` ,
76
+ ) ;
77
+ }
78
+
79
+ return isValid ;
80
+ } ) ;
81
+ }
82
+
83
+ return false ;
84
+ } ) ,
85
+ ) ;
86
+
87
+ return validVariables ;
45
88
} ;
46
89
47
90
export const createRadiiUnits = ( theme : Theme ) => {
@@ -51,12 +94,11 @@ export const createRadiiUnits = (theme: Theme) => {
51
94
}
52
95
53
96
const md = borderRadius === 'none' ? '0' : borderRadius ;
54
- const { numericValue, unit = 'rem' } = splitCssUnit ( md ) ;
55
97
return {
56
- sm : ( numericValue * 0.66 ) . toString ( ) + unit ,
98
+ sm : `calc( ${ md } * 0.66)` ,
57
99
md,
58
- lg : ( numericValue * 1.33 ) . toString ( ) + unit ,
59
- xl : ( numericValue * 2 ) . toString ( ) + unit ,
100
+ lg : `calc( ${ md } * 1.33)` ,
101
+ xl : `calc( ${ md } * 2)` ,
60
102
} ;
61
103
} ;
62
104
@@ -65,12 +107,11 @@ export const createSpaceScale = (theme: Theme) => {
65
107
if ( spacingUnit === undefined ) {
66
108
return ;
67
109
}
68
- const { numericValue, unit } = splitCssUnit ( spacingUnit ) ;
69
110
return fromEntries (
70
111
spaceScaleKeys . map ( k => {
71
112
const num = Number . parseFloat ( k . replace ( 'x' , '.' ) ) ;
72
113
const percentage = ( num / 0.5 ) * 0.125 ;
73
- return [ k , `${ numericValue * percentage } ${ unit } ` ] ;
114
+ return [ k , `calc( ${ spacingUnit } * ${ percentage } ) ` ] ;
74
115
} ) ,
75
116
) ;
76
117
} ;
@@ -83,13 +124,12 @@ export const createFontSizeScale = (theme: Theme): Record<keyof typeof fontSizes
83
124
if ( fontSize === undefined ) {
84
125
return ;
85
126
}
86
- const { numericValue, unit = 'rem' } = splitCssUnit ( fontSize ) ;
87
127
return {
88
- xs : ( numericValue * 0.8 ) . toString ( ) + unit ,
89
- sm : ( numericValue * 0.9 ) . toString ( ) + unit ,
128
+ xs : `calc( ${ fontSize } * 0.8)` ,
129
+ sm : `calc( ${ fontSize } * 0.9)` ,
90
130
md : fontSize ,
91
- lg : ( numericValue * 1.3 ) . toString ( ) + unit ,
92
- xl : ( numericValue * 1.85 ) . toString ( ) + unit ,
131
+ lg : `calc( ${ fontSize } * 1.3)` ,
132
+ xl : `calc( ${ fontSize } * 1.85)` ,
93
133
} ;
94
134
} ;
95
135
@@ -102,9 +142,3 @@ export const createFonts = (theme: Theme) => {
102
142
const { fontFamily, fontFamilyButtons } = theme . variables || { } ;
103
143
return removeUndefinedProps ( { main : fontFamily , buttons : fontFamilyButtons } ) ;
104
144
} ;
105
-
106
- const splitCssUnit = ( str : string ) => {
107
- const numericValue = Number . parseFloat ( str ) ;
108
- const unit = str . replace ( numericValue . toString ( ) , '' ) || undefined ;
109
- return { numericValue, unit } ;
110
- } ;
0 commit comments