@@ -12,9 +12,14 @@ export type ResponsivePropObject<T = string> = {
1212
1313export  type  ResponsiveProp < T  =  string >  =  T  |  ResponsivePropObject < T > ; 
1414
15- export  type  ResponsiveValue < T  =  string >  =  undefined  |  ResponsiveProp < T > ; 
15+ export  type  PolarisCSSCustomPropertyName  =  `${`--p-` |  `--pc-`} ${string } `; 
16+ export  type  PolarisCSSVar  =  `var(${PolarisCSSCustomPropertyName } )`; 
1617
17- type  ResponsiveVariables < T >  =  { 
18+ type  ResponsiveCSSCustomProperties  =  { 
19+   [ Breakpoint  in  `${string } -${BreakpointsAlias } `] ?: PolarisCSSVar ; 
20+ } ; 
21+ 
22+ type  ResponsiveValues < T >  =  { 
1823  [ Breakpoint  in  `${string } -${BreakpointsAlias } `] ?: T ; 
1924} ; 
2025
@@ -36,6 +41,41 @@ export function sanitizeCustomProperties(
3641  return  nonNullValues . length  ? Object . fromEntries ( nonNullValues )  : undefined ; 
3742} 
3843
44+ export  function  createPolarisCSSVar < T  extends  string  |  number  =  string > ( 
45+   tokenSubgroup : string , 
46+   tokenValue : T , 
47+ ) : PolarisCSSVar  { 
48+   // For backwards compatibility with `Grid` and `Grid.Cell`, accept already 
49+   // formed var()'s using either polaris or polaris component custom properties. 
50+   if  ( typeof  tokenValue  ===  'string'  &&  tokenValue . startsWith ( 'var(' ) )  { 
51+     if  ( 
52+       ! tokenValue . startsWith ( `var(--p-${ tokenSubgroup }  )  && 
53+       ! tokenValue . startsWith ( `var(--pc-${ tokenSubgroup }  ) 
54+     )  { 
55+       throw  new  Error ( 
56+         `"${ tokenValue } ${ tokenSubgroup }  , 
57+       ) ; 
58+     } 
59+ 
60+     return  tokenValue  as  PolarisCSSVar ; 
61+   } 
62+ 
63+   // NOTE: All our token values today are either strings or numbers, so 
64+   // stringifying them here works. But if we ever have anything more complex 
65+   // (such as an object) this may generate invalid token names. 
66+   return  `var(--p-${ tokenSubgroup } ${ tokenValue }  ; 
67+ } 
68+ 
69+ export  function  createPolarisCSSCustomProperty ( 
70+   componentName : string , 
71+   componentProp : string , 
72+   breakpointAlias ?: BreakpointsAlias , 
73+ ) : PolarisCSSCustomPropertyName  { 
74+   return  `--pc-${ componentName } ${ componentProp } ${  
75+     breakpointAlias  ? `-${ breakpointAlias }   : ''  
76+   }  `; 
77+ } 
78+ 
3979/** 
4080 * Given params like so: 
4181 * ( 
@@ -53,59 +93,88 @@ export function sanitizeCustomProperties(
5393 *   '--pc-button-padding-lg': 'var(--p-spacing-6)' 
5494 * } 
5595 * 
96+  * NOTE: Also supports legacy / deprecated values which are a complete CSS 
97+  * variable declaration (primarily for `Grid`): 
98+  * ( 
99+  *   'grid', 
100+  *   'gap', 
101+  *   'spacing', 
102+  *   { 
103+  *     sm: "var(--p-spacing-4)", 
104+  *     lg: "var(--p-spacing-6)" 
105+  *   } 
106+  * ) 
107+  * 
56108 */ 
57- export  function  getResponsiveProps < T  =  string > ( 
109+ export  function  getResponsiveProps < T  extends   string   |   number   =  string > ( 
58110  componentName : string , 
59111  componentProp : string , 
60112  tokenSubgroup : string , 
61113  responsiveProp ?: ResponsiveProp < T > , 
62- ) : ResponsiveVariables < T >  { 
63-   if  ( ! responsiveProp )  return  { } ; 
64- 
65-   let  result : ResponsivePropConfig ; 
66- 
67-   if  ( ! isObject ( responsiveProp ) )  { 
68-     result  =  { 
69-       [ breakpointsAliases [ 0 ] ] : `var(--p-${ tokenSubgroup } ${ responsiveProp }  , 
70-     } ; 
71-   }  else  { 
72-     result  =  Object . fromEntries ( 
73-       Object . entries ( responsiveProp ) . map ( ( [ breakpointAlias ,  aliasOrScale ] )  =>  [ 
74-         breakpointAlias , 
75-         `var(--p-${ tokenSubgroup } ${ aliasOrScale }  , 
114+ ) : ResponsiveCSSCustomProperties  { 
115+   // "falsey" values are valid except `null` or `undefined` 
116+   if  ( responsiveProp  ==  null )  return  { } ; 
117+ 
118+   if  ( isObject ( responsiveProp ) )  { 
119+     return  Object . fromEntries ( 
120+       ( 
121+         Object . entries ( responsiveProp ) . filter ( 
122+           ( [ ,  aliasOrScale ] )  =>  aliasOrScale  !=  null , 
123+           // Use 'Required' here because .filter() doesn't type narrow 
124+         )  as  Entries < Required < typeof  responsiveProp > > 
125+       ) . map ( ( [ breakpointAlias ,  aliasOrScale ] )  =>  [ 
126+         createPolarisCSSCustomProperty ( 
127+           componentName , 
128+           componentProp , 
129+           breakpointAlias , 
130+         ) , 
131+         createPolarisCSSVar ( tokenSubgroup ,  aliasOrScale ) , 
76132      ] ) , 
77133    ) ; 
78134  } 
79135
80-   // Prefix each responsive key with the correct token name 
81-   return   Object . fromEntries ( 
82-     Object . entries ( result ) . map ( ( [ breakpointAlias ,   value ] )   =>   [ 
83-       `--pc- ${ componentName } - ${ componentProp } - ${ breakpointAlias } ` , 
84-       value , 
85-     ] ) , 
86-   )   as   unknown   as   ResponsiveVariables < T > ; 
136+   return   { 
137+      [ createPolarisCSSCustomProperty ( 
138+        componentName , 
139+       componentProp , 
140+       breakpointsAliases [ 0 ] , 
141+     ) ] :  createPolarisCSSVar ( tokenSubgroup ,   responsiveProp   as   T ) , 
142+   } ; 
87143} 
88144
89- export  function  getResponsiveValue < T  =  string > ( 
145+ export  function  getResponsiveValue < T  extends   string   |   number   =  string > ( 
90146  componentName : string , 
91147  componentProp : string , 
92-   responsiveProp ?: ResponsiveValue < T > , 
93- ) : ResponsiveVariables < T >  { 
94-   if  ( ! responsiveProp )  return  { } ; 
95- 
96-   if  ( ! isObject ( responsiveProp ) )  { 
97-     return  { 
98-       [ `--pc-${ componentName } ${ componentProp } ${ breakpointsAliases [ 0 ] }  ] :
99-         responsiveProp , 
100-     }  as  ResponsiveVariables < T > ; 
148+   responsiveProp ?: ResponsiveProp < T > , 
149+ ) : ResponsiveValues < T >  { 
150+   // "falsey" values are valid except `null` or `undefined` 
151+   if  ( responsiveProp  ==  null )  return  { } ; 
152+ 
153+   if  ( isObject ( responsiveProp ) )  { 
154+     return  Object . fromEntries ( 
155+       ( 
156+         Object . entries ( responsiveProp ) . filter ( 
157+           ( [ ,  responsiveValue ] )  =>  responsiveValue  !=  null , 
158+           // Use 'Required' here because .filter() doesn't type narrow 
159+         )  as  Entries < Required < typeof  responsiveProp > > 
160+       ) . map ( ( [ breakpointAlias ,  responsiveValue ] )  =>  [ 
161+         createPolarisCSSCustomProperty ( 
162+           componentName , 
163+           componentProp , 
164+           breakpointAlias , 
165+         ) , 
166+         responsiveValue , 
167+       ] ) , 
168+     ) ; 
101169  } 
102170
103-   return  Object . fromEntries ( 
104-     Object . entries ( responsiveProp ) . map ( ( [ breakpointAlias ,  responsiveValue ] )  =>  [ 
105-       `--pc-${ componentName } ${ componentProp } ${ breakpointAlias }  , 
106-       responsiveValue , 
107-     ] ) , 
108-   ) ; 
171+   return  { 
172+     [ createPolarisCSSCustomProperty ( 
173+       componentName , 
174+       componentProp , 
175+       breakpointsAliases [ 0 ] , 
176+     ) ] : responsiveProp  as  T , 
177+   } ; 
109178} 
110179
111180export  function  mapResponsivePropValues < Input ,  Output > ( 
0 commit comments