@@ -29,6 +29,43 @@ import * as ValueParser from './value-parser'
2929const  IS_VALID_STATIC_UTILITY_NAME  =  / ^ - ? [ a - z ] [ a - z A - Z 0 - 9 / % . _ - ] * $ / 
3030const  IS_VALID_FUNCTIONAL_UTILITY_NAME  =  / ^ - ? [ a - z ] [ a - z A - Z 0 - 9 / % . _ - ] * - \* $ / 
3131
32+ const  DEFAULT_SPACING_SUGGESTIONS  =  [ 
33+   '0' , 
34+   '0.5' , 
35+   '1' , 
36+   '1.5' , 
37+   '2' , 
38+   '2.5' , 
39+   '3' , 
40+   '3.5' , 
41+   '4' , 
42+   '5' , 
43+   '6' , 
44+   '7' , 
45+   '8' , 
46+   '9' , 
47+   '10' , 
48+   '11' , 
49+   '12' , 
50+   '14' , 
51+   '16' , 
52+   '20' , 
53+   '24' , 
54+   '28' , 
55+   '32' , 
56+   '36' , 
57+   '40' , 
58+   '44' , 
59+   '48' , 
60+   '52' , 
61+   '56' , 
62+   '60' , 
63+   '64' , 
64+   '72' , 
65+   '80' , 
66+   '96' , 
67+ ] 
68+ 
3269type  CompileFn < T  extends  Candidate [ 'kind' ] >  =  ( 
3370  value : Extract < Candidate ,  {  kind : T  } > , 
3471)  =>  AstNode [ ]  |  undefined  |  null 
@@ -476,44 +513,7 @@ export function createUtilities(theme: Theme) {
476513
477514    suggest ( name ,  ( )  =>  [ 
478515      { 
479-         values : theme . get ( [ '--spacing' ] ) 
480-           ? [ 
481-               '0' , 
482-               '0.5' , 
483-               '1' , 
484-               '1.5' , 
485-               '2' , 
486-               '2.5' , 
487-               '3' , 
488-               '3.5' , 
489-               '4' , 
490-               '5' , 
491-               '6' , 
492-               '7' , 
493-               '8' , 
494-               '9' , 
495-               '10' , 
496-               '11' , 
497-               '12' , 
498-               '14' , 
499-               '16' , 
500-               '20' , 
501-               '24' , 
502-               '28' , 
503-               '32' , 
504-               '36' , 
505-               '40' , 
506-               '44' , 
507-               '48' , 
508-               '52' , 
509-               '56' , 
510-               '60' , 
511-               '64' , 
512-               '72' , 
513-               '80' , 
514-               '96' , 
515-             ] 
516-           : [ ] , 
516+         values : theme . get ( [ '--spacing' ] )  ? DEFAULT_SPACING_SUGGESTIONS  : [ ] , 
517517        supportsNegative, 
518518        supportsFractions, 
519519        valueThemeKeys : themeKeys , 
@@ -4731,11 +4731,20 @@ export function createCssUtility(node: AtRule) {
47314731    //   If you then use `foo-1/2`, this is invalid, because the modifier is not used. 
47324732
47334733    return  ( designSystem : DesignSystem )  =>  { 
4734-       let  valueThemeKeys  =  new  Set < `--${string } `> ( ) 
4735-       let  valueLiterals  =  new  Set < string > ( ) 
4736- 
4737-       let  modifierThemeKeys  =  new  Set < `--${string } `> ( ) 
4738-       let  modifierLiterals  =  new  Set < string > ( ) 
4734+       let  storage  =  { 
4735+         '--value' : { 
4736+           usedSpacingInteger : false , 
4737+           usedSpacingNumber : false , 
4738+           themeKeys : new  Set < `--${string } `> ( ) , 
4739+           literals : new  Set < string > ( ) , 
4740+         } , 
4741+         '--modifier' : { 
4742+           usedSpacingInteger : false , 
4743+           usedSpacingNumber : false , 
4744+           themeKeys : new  Set < `--${string } `> ( ) , 
4745+           literals : new  Set < string > ( ) , 
4746+         } , 
4747+       } 
47394748
47404749      // Pre-process the AST to make it easier to work with. 
47414750      // 
@@ -4762,6 +4771,41 @@ export function createCssUtility(node: AtRule) {
47624771        // `\\*` or not inserting whitespace) then most of these can go away. 
47634772        ValueParser . walk ( declarationValueAst ,  ( fn )  =>  { 
47644773          if  ( fn . kind  !==  'function' )  return 
4774+ 
4775+           // Track usage of `--spacing(…)` 
4776+           if  ( 
4777+             fn . value  ===  '--spacing'  && 
4778+             // Quick bail check if we already know that `--value` and `--modifier` are 
4779+             // using the full `--spacing` theme scale. 
4780+             ! ( storage [ '--modifier' ] . usedSpacingNumber  &&  storage [ '--value' ] . usedSpacingNumber ) 
4781+           )  { 
4782+             ValueParser . walk ( fn . nodes ,  ( node )  =>  { 
4783+               if  ( node . kind  !==  'function' )  return 
4784+               if  ( node . value  !==  '--value'  &&  node . value  !==  '--modifier' )  return 
4785+               const  key  =  node . value 
4786+ 
4787+               for  ( let  arg  of  node . nodes )  { 
4788+                 if  ( arg . kind  !==  'word' )  continue 
4789+ 
4790+                 if  ( arg . value  ===  'integer' )  { 
4791+                   storage [ key ] . usedSpacingInteger  ||=  true 
4792+                 }  else  if  ( arg . value  ===  'number' )  { 
4793+                   storage [ key ] . usedSpacingNumber  ||=  true 
4794+ 
4795+                   // Once both `--value` and `--modifier` are using the full 
4796+                   // `number` spacing scale, then there's no need to continue 
4797+                   if  ( 
4798+                     storage [ '--modifier' ] . usedSpacingNumber  && 
4799+                     storage [ '--value' ] . usedSpacingNumber 
4800+                   )  { 
4801+                     return  ValueParser . ValueWalkAction . Stop 
4802+                   } 
4803+                 } 
4804+               } 
4805+             } ) 
4806+             return  ValueParser . ValueWalkAction . Continue 
4807+           } 
4808+ 
47654809          if  ( fn . value  !==  '--value'  &&  fn . value  !==  '--modifier' )  return 
47664810
47674811          let  args  =  segment ( ValueParser . toCss ( fn . nodes ) ,  ',' ) 
@@ -4796,23 +4840,13 @@ export function createCssUtility(node: AtRule) {
47964840              node . value [ 0 ]  ===  node . value [ node . value . length  -  1 ] 
47974841            )  { 
47984842              let  value  =  node . value . slice ( 1 ,  - 1 ) 
4799- 
4800-               if  ( fn . value  ===  '--value' )  { 
4801-                 valueLiterals . add ( value ) 
4802-               }  else  if  ( fn . value  ===  '--modifier' )  { 
4803-                 modifierLiterals . add ( value ) 
4804-               } 
4843+               storage [ fn . value ] . literals . add ( value ) 
48054844            } 
48064845
48074846            // Track theme keys 
48084847            else  if  ( node . kind  ===  'word'  &&  node . value [ 0 ]  ===  '-'  &&  node . value [ 1 ]  ===  '-' )  { 
48094848              let  value  =  node . value . replace ( / - \* .* $ / g,  '' )  as  `--${string } `
4810- 
4811-               if  ( fn . value  ===  '--value' )  { 
4812-                 valueThemeKeys . add ( value ) 
4813-               }  else  if  ( fn . value  ===  '--modifier' )  { 
4814-                 modifierThemeKeys . add ( value ) 
4815-               } 
4849+               storage [ fn . value ] . themeKeys . add ( value ) 
48164850            } 
48174851          } 
48184852        } ) 
@@ -4949,20 +4983,33 @@ export function createCssUtility(node: AtRule) {
49494983      } ) 
49504984
49514985      designSystem . utilities . suggest ( name . slice ( 0 ,  - 2 ) ,  ( )  =>  { 
4952-         let  values  =  [ ] 
4953-         for  ( let  value  of  valueLiterals )  { 
4954-           values . push ( value ) 
4955-         } 
4956-         for  ( let  value  of  designSystem . theme . keysInNamespaces ( valueThemeKeys ) )  { 
4957-           values . push ( value ) 
4958-         } 
4986+         let  values : string [ ]  =  [ ] 
4987+         let  modifiers : string [ ]  =  [ ] 
4988+ 
4989+         for  ( let  [ target ,  {  literals,  usedSpacingNumber,  usedSpacingInteger,  themeKeys } ]  of  [ 
4990+           [ values ,  storage [ '--value' ] ] , 
4991+           [ modifiers ,  storage [ '--modifier' ] ] , 
4992+         ]  as  const )  { 
4993+           // Suggest literal values. E.g.: `--value('literal')` 
4994+           for  ( let  value  of  literals )  { 
4995+             target . push ( value ) 
4996+           } 
49594997
4960-         let  modifiers  =  [ ] 
4961-         for  ( let  modifier  of  modifierLiterals )  { 
4962-           modifiers . push ( modifier ) 
4963-         } 
4964-         for  ( let  value  of  designSystem . theme . keysInNamespaces ( modifierThemeKeys ) )  { 
4965-           modifiers . push ( value ) 
4998+           // Suggest `--spacing(…)` values. E.g.: `--spacing(--value(integer))` 
4999+           if  ( usedSpacingNumber )  { 
5000+             target . push ( ...DEFAULT_SPACING_SUGGESTIONS ) 
5001+           }  else  if  ( usedSpacingInteger )  { 
5002+             for  ( let  value  of  DEFAULT_SPACING_SUGGESTIONS )  { 
5003+               if  ( isPositiveInteger ( value ) )  { 
5004+                 target . push ( value ) 
5005+               } 
5006+             } 
5007+           } 
5008+ 
5009+           // Suggest theme values. E.g.: `--value(--color-*)` 
5010+           for  ( let  value  of  designSystem . theme . keysInNamespaces ( themeKeys ) )  { 
5011+             target . push ( value ) 
5012+           } 
49665013        } 
49675014
49685015        return  [ {  values,  modifiers } ]  satisfies  SuggestionGroup [ ] 
0 commit comments