@@ -29,6 +29,43 @@ import * as ValueParser from './value-parser'
29
29
const IS_VALID_STATIC_UTILITY_NAME = / ^ - ? [ a - z ] [ a - z A - Z 0 - 9 / % . _ - ] * $ /
30
30
const IS_VALID_FUNCTIONAL_UTILITY_NAME = / ^ - ? [ a - z ] [ a - z A - Z 0 - 9 / % . _ - ] * - \* $ /
31
31
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
+
32
69
type CompileFn < T extends Candidate [ 'kind' ] > = (
33
70
value : Extract < Candidate , { kind : T } > ,
34
71
) => AstNode [ ] | undefined | null
@@ -476,44 +513,7 @@ export function createUtilities(theme: Theme) {
476
513
477
514
suggest ( name , ( ) => [
478
515
{
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 : [ ] ,
517
517
supportsNegative,
518
518
supportsFractions,
519
519
valueThemeKeys : themeKeys ,
@@ -4731,11 +4731,20 @@ export function createCssUtility(node: AtRule) {
4731
4731
// If you then use `foo-1/2`, this is invalid, because the modifier is not used.
4732
4732
4733
4733
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
+ }
4739
4748
4740
4749
// Pre-process the AST to make it easier to work with.
4741
4750
//
@@ -4762,6 +4771,41 @@ export function createCssUtility(node: AtRule) {
4762
4771
// `\\*` or not inserting whitespace) then most of these can go away.
4763
4772
ValueParser . walk ( declarationValueAst , ( fn ) => {
4764
4773
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
+
4765
4809
if ( fn . value !== '--value' && fn . value !== '--modifier' ) return
4766
4810
4767
4811
let args = segment ( ValueParser . toCss ( fn . nodes ) , ',' )
@@ -4796,23 +4840,13 @@ export function createCssUtility(node: AtRule) {
4796
4840
node . value [ 0 ] === node . value [ node . value . length - 1 ]
4797
4841
) {
4798
4842
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 )
4805
4844
}
4806
4845
4807
4846
// Track theme keys
4808
4847
else if ( node . kind === 'word' && node . value [ 0 ] === '-' && node . value [ 1 ] === '-' ) {
4809
4848
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 )
4816
4850
}
4817
4851
}
4818
4852
} )
@@ -4949,20 +4983,33 @@ export function createCssUtility(node: AtRule) {
4949
4983
} )
4950
4984
4951
4985
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
+ }
4959
4997
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
+ }
4966
5013
}
4967
5014
4968
5015
return [ { values, modifiers } ] satisfies SuggestionGroup [ ]
0 commit comments