11#!/usr/bin/env node
2+ import { createRequire } from 'module' ;
23import fg from 'fast-glob' ;
34import { fileURLToPath , pathToFileURL } from 'url' ;
45import fs from 'fs' ;
56import path from 'path' ;
7+ // eslint-disable-next-line rulesdir/imports
8+ import * as ts from 'typescript' ;
69
710const __filename = fileURLToPath ( import . meta. url ) ;
811const __dirname = path . dirname ( __filename ) ;
@@ -13,6 +16,7 @@ const ICONS_DIR = path.resolve(REPO_ROOT, 'packages/@react-spectrum/s2/s2wf-icon
1316const ILLUSTRATIONS_DIR = path . resolve ( REPO_ROOT , 'packages/@react-spectrum/s2/spectrum-illustrations/linear' ) ;
1417const ICON_ALIASES_JS = path . resolve ( REPO_ROOT , 'packages/dev/s2-docs/src/iconAliases.js' ) ;
1518const ILLUSTRATION_ALIASES_JS = path . resolve ( REPO_ROOT , 'packages/dev/s2-docs/src/illustrationAliases.js' ) ;
19+ const STYLE_PROPERTIES_TS = path . resolve ( REPO_ROOT , 'packages/dev/s2-docs/src/styleProperties.ts' ) ;
1620
1721function ensureDir ( p ) {
1822 fs . mkdirSync ( p , { recursive : true } ) ;
@@ -24,6 +28,23 @@ function writeJson(file, data) {
2428 console . log ( 'Wrote' , path . relative ( REPO_ROOT , file ) ) ;
2529}
2630
31+ async function importTsModule ( tsFilePath ) {
32+ if ( ! fs . existsSync ( tsFilePath ) ) {
33+ throw new Error ( `TS module not found: ${ tsFilePath } ` ) ;
34+ }
35+ const sourceText = fs . readFileSync ( tsFilePath , 'utf8' ) ;
36+ const result = ts . transpileModule ( sourceText , {
37+ fileName : tsFilePath ,
38+ compilerOptions : {
39+ target : ts . ScriptTarget . ES2022 ,
40+ module : ts . ModuleKind . ESNext ,
41+ esModuleInterop : true
42+ }
43+ } ) ;
44+ const url = `data:text/javascript;base64,${ Buffer . from ( result . outputText , 'utf8' ) . toString ( 'base64' ) } ` ;
45+ return import ( url ) ;
46+ }
47+
2748function buildIconNames ( ) {
2849 if ( ! fs . existsSync ( ICONS_DIR ) ) {
2950 throw new Error ( `Icons directory not found: ${ ICONS_DIR } ` ) ;
@@ -61,6 +82,107 @@ async function loadAliases(modPath, exportName) {
6182 return mod [ exportName ] ?? { } ;
6283}
6384
85+ function buildBaseColorKeysFromSpectrumTokens ( tokens ) {
86+ const keys = new Set ( ) ;
87+
88+ // Matches spectrum-theme.ts
89+ keys . add ( 'transparent' ) ;
90+ keys . add ( 'black' ) ;
91+ keys . add ( 'white' ) ;
92+
93+ const addScale = ( scale ) => {
94+ const re = new RegExp ( `^${ scale } -\\d+$` ) ;
95+ for ( const tokenName of Object . keys ( tokens ) ) {
96+ if ( re . test ( tokenName ) ) {
97+ // Match @react -spectrum/s2/style/tokens.ts behavior: strip "-color" in the middle.
98+ keys . add ( tokenName . replace ( '-color' , '' ) ) ;
99+ }
100+ }
101+ } ;
102+
103+ // Global color scales
104+ for ( const scale of [
105+ 'gray' , 'blue' , 'red' , 'orange' , 'yellow' , 'chartreuse' , 'celery' , 'green' ,
106+ 'seafoam' , 'cyan' , 'indigo' , 'purple' , 'fuchsia' , 'magenta' , 'pink' ,
107+ 'turquoise' , 'brown' , 'silver' , 'cinnamon'
108+ ] ) {
109+ addScale ( scale ) ;
110+ }
111+
112+ // Semantic color scales
113+ for ( const scale of [ 'accent-color' , 'informative-color' , 'negative-color' , 'notice-color' , 'positive-color' ] ) {
114+ addScale ( scale ) ;
115+ }
116+
117+ // Simple transparent scales (names remain unchanged)
118+ for ( const scale of [ 'transparent-white' , 'transparent-black' ] ) {
119+ const re = new RegExp ( `^${ scale } -\\d+$` ) ;
120+ for ( const tokenName of Object . keys ( tokens ) ) {
121+ if ( re . test ( tokenName ) ) {
122+ keys . add ( tokenName ) ;
123+ }
124+ }
125+ }
126+
127+ // Overlay scale keys (derived in tokens.ts, we only need the names here)
128+ for ( const n of [ 25 , 50 , 75 , 100 , 200 , 300 , 400 , 500 , 600 , 700 , 800 , 900 , 1000 ] ) {
129+ keys . add ( `transparent-overlay-${ n } ` ) ;
130+ }
131+
132+ // High contrast keywords (matches spectrum-theme.ts)
133+ for ( const k of [ 'Background' , 'ButtonBorder' , 'ButtonFace' , 'ButtonText' , 'Field' , 'Highlight' , 'HighlightText' , 'GrayText' , 'Mark' , 'LinkText' ] ) {
134+ keys . add ( k ) ;
135+ }
136+
137+ return Array . from ( keys ) . sort ( ( a , b ) => a . localeCompare ( b ) ) ;
138+ }
139+
140+ function buildExpandedStyleMacroPropertyValues ( styleProperties , spacingTypeValues , baseColorKeys ) {
141+ const out = { } ;
142+
143+ for ( const [ propertyName , def ] of Object . entries ( styleProperties ) ) {
144+ const values = [ ] ;
145+ const seen = new Set ( ) ;
146+
147+ const pushUnique = ( items ) => {
148+ for ( const v of items ) {
149+ const s = String ( v ) ;
150+ if ( ! seen . has ( s ) ) {
151+ seen . add ( s ) ;
152+ values . push ( s ) ;
153+ }
154+ }
155+ } ;
156+
157+ // Expand 'baseColors' placeholder into actual color token names.
158+ const expandedBase = [ ] ;
159+ for ( const v of def . values ?? [ ] ) {
160+ if ( v === 'baseColors' ) {
161+ expandedBase . push ( ...baseColorKeys ) ;
162+ } else {
163+ expandedBase . push ( v ) ;
164+ }
165+ }
166+ pushUnique ( expandedBase ) ;
167+
168+ // Expand spacing type placeholders into the actual numeric values shown in docs.
169+ const additionalTypes = Array . isArray ( def . additionalTypes ) ? def . additionalTypes : [ ] ;
170+ if ( additionalTypes . includes ( 'baseSpacing' ) ) {
171+ pushUnique ( spacingTypeValues ?. baseSpacing ?? [ ] ) ;
172+ }
173+ if ( additionalTypes . includes ( 'negativeSpacing' ) ) {
174+ pushUnique ( spacingTypeValues ?. negativeSpacing ?? [ ] ) ;
175+ }
176+
177+ out [ propertyName ] = {
178+ values,
179+ additionalTypes
180+ } ;
181+ }
182+
183+ return out ;
184+ }
185+
64186async function main ( ) {
65187 const icons = buildIconNames ( ) ;
66188 const illustrations = buildIllustrationNames ( ) ;
@@ -71,6 +193,22 @@ async function main() {
71193 writeJson ( path . join ( OUT_DIR , 'illustrations.json' ) , illustrations ) ;
72194 writeJson ( path . join ( OUT_DIR , 'iconAliases.json' ) , iconAliases ) ;
73195 writeJson ( path . join ( OUT_DIR , 'illustrationAliases.json' ) , illustrationAliases ) ;
196+
197+ // Style macro property definitions
198+ const stylePropsMod = await importTsModule ( STYLE_PROPERTIES_TS ) ;
199+ const propertyCategories = [ 'color' , 'dimensions' , 'text' , 'effects' , 'layout' , 'misc' , 'conditions' ] ;
200+ const styleProperties = { } ;
201+ for ( const category of propertyCategories ) {
202+ Object . assign ( styleProperties , stylePropsMod . getPropertyDefinitions ( category ) ) ;
203+ }
204+ Object . assign ( styleProperties , stylePropsMod . getShorthandDefinitions ( ) ) ;
205+ writeJson ( path . join ( OUT_DIR , 'styleProperties.json' ) , styleProperties ) ;
206+
207+ const require = createRequire ( import . meta. url ) ;
208+ const spectrumTokens = require ( '@adobe/spectrum-tokens/dist/json/variables.json' ) ;
209+ const baseColorKeys = buildBaseColorKeysFromSpectrumTokens ( spectrumTokens ) ;
210+ const expanded = buildExpandedStyleMacroPropertyValues ( styleProperties , stylePropsMod . spacingTypeValues , baseColorKeys ) ;
211+ writeJson ( path . join ( OUT_DIR , 'styleMacroPropertyValues.json' ) , expanded ) ;
74212}
75213
76214main ( ) . catch ( ( err ) => {
0 commit comments