|
1 | 1 | import type { Context } from '@pandacss/core' |
2 | 2 | import { walkObject } from '@pandacss/shared' |
3 | 3 | import type { Token } from '@pandacss/token-dictionary' |
4 | | -import type { SemanticTokenSpec, SemanticTokenSpecDefinition, TokenSpec, TokenSpecDefinition } from '@pandacss/types' |
| 4 | +import type { |
| 5 | + SemanticTokenSpec, |
| 6 | + SemanticTokenGroupDefinition, |
| 7 | + SemanticTokenValue, |
| 8 | + TokenSpec, |
| 9 | + TokenGroupDefinition, |
| 10 | + TokenValue, |
| 11 | +} from '@pandacss/types' |
5 | 12 |
|
6 | 13 | const CATEGORY_PROPERTY_MAP: Record<string, string> = { |
7 | 14 | colors: 'color', |
@@ -56,62 +63,96 @@ const generateTokenExamples = (token: Token, jsxStyleProps: 'all' | 'minimal' | |
56 | 63 |
|
57 | 64 | export const generateTokensSpec = (ctx: Context): TokenSpec => { |
58 | 65 | const jsxStyleProps = ctx.config.jsxStyleProps ?? 'all' |
59 | | - const tokens = ctx.tokens.allTokens |
60 | | - .filter( |
61 | | - (token) => |
62 | | - !token.extensions.isSemantic && |
63 | | - !token.extensions.isVirtual && |
64 | | - !token.extensions.conditions && |
65 | | - !token.extensions.isNegative, |
66 | | - ) |
67 | | - .map((token): TokenSpecDefinition => { |
68 | | - const { functionExamples, tokenFunctionExamples, jsxExamples } = generateTokenExamples(token, jsxStyleProps) |
69 | | - return { |
70 | | - name: token.name, |
| 66 | + |
| 67 | + // Create grouped data structure using tokens.view.categoryMap |
| 68 | + const groupedData: TokenGroupDefinition[] = Array.from(ctx.tokens.view.categoryMap.entries()) |
| 69 | + .map(([category, tokenMap]) => { |
| 70 | + // Convert Map values to array and filter |
| 71 | + const typeTokens = Array.from(tokenMap.values()).filter( |
| 72 | + (token) => |
| 73 | + !token.extensions.isSemantic && |
| 74 | + !token.extensions.isVirtual && |
| 75 | + !token.extensions.conditions && |
| 76 | + !token.extensions.isNegative, |
| 77 | + ) |
| 78 | + |
| 79 | + // Skip if no tokens after filtering |
| 80 | + if (!typeTokens.length) return null |
| 81 | + |
| 82 | + // Get examples from first token of this type (they'll be the same for all) |
| 83 | + const firstToken = typeTokens[0] |
| 84 | + const { functionExamples, tokenFunctionExamples, jsxExamples } = generateTokenExamples(firstToken, jsxStyleProps) |
| 85 | + |
| 86 | + const values: TokenValue[] = typeTokens.map((token) => ({ |
| 87 | + name: token.extensions.prop || token.name, |
71 | 88 | value: token.value, |
72 | | - type: token.extensions.category, |
73 | 89 | description: token.description, |
74 | 90 | deprecated: token.deprecated, |
75 | 91 | cssVar: token.extensions.varRef, |
| 92 | + })) |
| 93 | + |
| 94 | + return { |
| 95 | + type: category, |
| 96 | + values, |
76 | 97 | tokenFunctionExamples, |
77 | 98 | functionExamples, |
78 | 99 | jsxExamples, |
79 | 100 | } |
80 | 101 | }) |
| 102 | + .filter(Boolean) as TokenGroupDefinition[] |
81 | 103 |
|
82 | 104 | return { |
83 | 105 | type: 'tokens', |
84 | | - data: tokens, |
| 106 | + data: groupedData, |
85 | 107 | } |
86 | 108 | } |
87 | 109 |
|
88 | 110 | export const generateSemanticTokensSpec = (ctx: Context): SemanticTokenSpec => { |
89 | 111 | const jsxStyleProps = ctx.config.jsxStyleProps ?? 'all' |
90 | | - const semanticTokens = ctx.tokens.allTokens |
91 | | - .filter((token) => (token.extensions.isSemantic || token.extensions.conditions) && !token.extensions.isVirtual) |
92 | | - .map((token): SemanticTokenSpecDefinition => { |
93 | | - const { functionExamples, tokenFunctionExamples, jsxExamples } = generateTokenExamples(token, jsxStyleProps) |
94 | | - const values: Array<{ value: string; condition?: string }> = [] |
95 | | - |
96 | | - walkObject(token.extensions.rawValue, (value, path) => { |
97 | | - values.push({ value, condition: path.map((p) => p.replace(/^_/, '')).join('.') }) |
| 112 | + |
| 113 | + // Create grouped data structure using tokens.view.categoryMap |
| 114 | + const groupedData: SemanticTokenGroupDefinition[] = Array.from(ctx.tokens.view.categoryMap.entries()) |
| 115 | + .map(([category, tokenMap]) => { |
| 116 | + // Convert Map values to array and filter for semantic tokens |
| 117 | + const typeTokens = Array.from(tokenMap.values()).filter( |
| 118 | + (token) => (token.extensions.isSemantic || token.extensions.conditions) && !token.extensions.isVirtual, |
| 119 | + ) |
| 120 | + |
| 121 | + // Skip if no tokens after filtering |
| 122 | + if (!typeTokens.length) return null |
| 123 | + |
| 124 | + // Get examples from first token of this type |
| 125 | + const firstToken = typeTokens[0] |
| 126 | + const { functionExamples, tokenFunctionExamples, jsxExamples } = generateTokenExamples(firstToken, jsxStyleProps) |
| 127 | + |
| 128 | + const values: SemanticTokenValue[] = typeTokens.map((token) => { |
| 129 | + const conditions: Array<{ value: string; condition?: string }> = [] |
| 130 | + |
| 131 | + walkObject(token.extensions.rawValue, (value, path) => { |
| 132 | + conditions.push({ value, condition: path.map((p) => p.replace(/^_/, '')).join('.') }) |
| 133 | + }) |
| 134 | + |
| 135 | + return { |
| 136 | + name: token.extensions.prop || token.name, |
| 137 | + values: conditions, |
| 138 | + description: token.description, |
| 139 | + deprecated: token.deprecated, |
| 140 | + cssVar: token.extensions.varRef, |
| 141 | + } |
98 | 142 | }) |
99 | 143 |
|
100 | 144 | return { |
101 | | - name: token.name, |
| 145 | + type: category, |
102 | 146 | values, |
103 | | - type: token.extensions.category, |
104 | | - description: token.description, |
105 | | - deprecated: token.deprecated, |
106 | | - cssVar: token.extensions.varRef, |
107 | 147 | tokenFunctionExamples, |
108 | 148 | functionExamples, |
109 | 149 | jsxExamples, |
110 | 150 | } |
111 | 151 | }) |
| 152 | + .filter(Boolean) as SemanticTokenGroupDefinition[] |
112 | 153 |
|
113 | 154 | return { |
114 | 155 | type: 'semantic-tokens', |
115 | | - data: semanticTokens, |
| 156 | + data: groupedData, |
116 | 157 | } |
117 | 158 | } |
0 commit comments