Skip to content

Commit eb358a6

Browse files
committed
fix: moved code to the same file
1 parent 0be385f commit eb358a6

File tree

4 files changed

+245
-264
lines changed

4 files changed

+245
-264
lines changed

packages/jacaranda/src/index.test.ts

+156-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, it, expect } from 'vitest';
2-
import { styles } from './';
2+
import { styles, createTokens } from './';
33

44
describe('createVariantStyle', () => {
55
it('should return base styles when no variants are provided', () => {
@@ -120,3 +120,158 @@ describe('createVariantStyle', () => {
120120
});
121121
});
122122
});
123+
124+
describe('createTokens', () => {
125+
it('should create styles function', () => {
126+
const { styles } = createTokens({
127+
colors: {
128+
primary: '#000000',
129+
secondary: '#ffffff',
130+
},
131+
spacing: {
132+
sm: 8,
133+
md: 16,
134+
},
135+
});
136+
137+
expect(typeof styles).toBe('function');
138+
});
139+
140+
it('should resolve token references in styles', () => {
141+
const { styles } = createTokens({
142+
colors: {
143+
primary: '#000000',
144+
},
145+
spacing: {
146+
sm: 8,
147+
},
148+
});
149+
150+
const result = styles({
151+
base: {
152+
backgroundColor: '$colors.primary',
153+
padding: '$spacing.sm',
154+
},
155+
variants: {},
156+
});
157+
158+
expect(result()).toEqual({
159+
backgroundColor: '#000000',
160+
padding: 8,
161+
});
162+
});
163+
164+
it('should resolve token references in variants', () => {
165+
const { styles } = createTokens({
166+
colors: {
167+
primary: '#000000',
168+
},
169+
borderStyles: {
170+
default: 'solid',
171+
},
172+
});
173+
174+
const result = styles({
175+
base: {},
176+
variants: {
177+
type: {
178+
primary: {
179+
backgroundColor: '$colors.primary',
180+
borderStyle: '$borderStyles.default',
181+
},
182+
},
183+
},
184+
});
185+
186+
expect(result({ type: 'primary' })).toEqual({
187+
backgroundColor: '#000000',
188+
borderStyle: 'solid',
189+
});
190+
});
191+
192+
it('should handle compound variants', () => {
193+
const { styles } = createTokens({
194+
colors: {
195+
primary: '#000000',
196+
},
197+
spacing: {
198+
sm: 8,
199+
},
200+
});
201+
202+
const result = styles({
203+
base: {},
204+
variants: {
205+
size: { small: {} },
206+
type: { primary: {} },
207+
},
208+
compoundVariants: [{
209+
variants: { size: 'small' as const, type: 'primary' as const },
210+
style: {
211+
backgroundColor: '$colors.primary',
212+
padding: '$spacing.sm',
213+
},
214+
}],
215+
});
216+
217+
expect(result({ size: 'small', type: 'primary' })).toEqual({
218+
backgroundColor: '#000000',
219+
padding: 8,
220+
});
221+
});
222+
223+
it('should ignore missing token references', () => {
224+
const { styles } = createTokens({
225+
colors: {
226+
primary: '#000000',
227+
},
228+
});
229+
230+
const result = styles({
231+
base: {
232+
backgroundColor: '$colors.nonexistent',
233+
color: '$colors.primary',
234+
},
235+
variants: {},
236+
});
237+
238+
expect(result()).toEqual({
239+
color: '#000000',
240+
});
241+
});
242+
243+
it('should support all allowed token categories', () => {
244+
const { styles } = createTokens({
245+
colors: { primary: '#000000' },
246+
spacing: { sm: 8 },
247+
fontSizes: { base: 16 },
248+
fonts: { body: 'Arial' },
249+
lineHeight: { normal: 1.5 },
250+
borderWidth: { thin: 1 },
251+
borderStyles: { default: 'solid' },
252+
});
253+
254+
const result = styles({
255+
base: {
256+
color: '$colors.primary',
257+
padding: '$spacing.sm',
258+
fontSize: '$fontSizes.base',
259+
fontFamily: '$fonts.body',
260+
lineHeight: '$lineHeight.normal',
261+
borderWidth: '$borderWidth.thin',
262+
borderStyle: '$borderStyles.default',
263+
},
264+
variants: {},
265+
});
266+
267+
expect(result()).toEqual({
268+
color: '#000000',
269+
padding: 8,
270+
fontSize: 16,
271+
fontFamily: 'Arial',
272+
lineHeight: 1.5,
273+
borderWidth: 1,
274+
borderStyle: 'solid',
275+
});
276+
});
277+
});

packages/jacaranda/src/index.ts

+89-2
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,93 @@ export function styles<V extends VariantOptions<V>>(config: VariantStyleConfig<V
144144
};
145145
}
146146

147-
// Add these types above the existing types
148147

149-
export { createTokens } from './tokens';
148+
/**** Tokens definition */
149+
150+
// Define allowed token categories and their value types
151+
interface AllowedTokenCategories {
152+
colors: string;
153+
spacing: number;
154+
fontSizes: number;
155+
fonts: string;
156+
lineHeight: number;
157+
borderWidth: number;
158+
borderStyles: 'solid' | 'dashed' | 'dotted' | 'none';
159+
}
160+
161+
// Update TokenConfig to only allow specific categories
162+
type TokenConfig = {
163+
[K in keyof AllowedTokenCategories]?: Record<string, AllowedTokenCategories[K]>;
164+
};
165+
166+
interface CreateTokensReturn {
167+
styles: typeof styles;
168+
}
169+
170+
// Helper to resolve token references in style objects
171+
function resolveTokens(style: StyleObject, tokens: TokenConfig): StyleObject {
172+
return Object.entries(style).reduce<Record<string, any>>((acc, [key, value]) => {
173+
if (typeof value !== 'string' || !value.startsWith('$')) {
174+
acc[key] = value;
175+
return acc;
176+
}
177+
178+
const tokenPath = value.slice(1).split('.');
179+
const [category, token] = tokenPath;
180+
181+
const tokenValue = tokens[category as keyof TokenConfig]?.[token];
182+
if (tokenValue !== undefined) {
183+
acc[key] = tokenValue;
184+
}
185+
186+
return acc;
187+
}, {}) as StyleObject;
188+
}
189+
190+
/**
191+
* Creates a token system and returns the styles function
192+
*/
193+
export function createTokens<T extends TokenConfig>(tokenConfig: T): CreateTokensReturn {
194+
// Create the tokens object
195+
const tokens = Object.entries(tokenConfig).reduce((acc, [category, values]) => {
196+
return {
197+
...acc,
198+
[category]: values,
199+
};
200+
}, {} as any);
201+
202+
// Create a wrapped styles function that resolves token references
203+
const wrappedStyles: typeof styles = (config: any) => {
204+
// Resolve tokens in base styles
205+
const resolvedBase = config.base ? resolveTokens(config.base, tokens) : config.base;
206+
207+
// Resolve tokens in variants
208+
const resolvedVariants = config.variants ? Object.entries(config.variants).reduce((acc, [key, variantGroup]: [string, any]) => {
209+
const resolvedGroup = Object.entries(variantGroup).reduce((groupAcc, [variantKey, styles]: [string, any]) => {
210+
return {
211+
...groupAcc,
212+
[variantKey]: resolveTokens(styles, tokens),
213+
};
214+
}, {});
215+
return { ...acc, [key]: resolvedGroup };
216+
}, {}) : {};
217+
218+
// Resolve tokens in compound variants
219+
const resolvedCompoundVariants = config.compoundVariants?.map((compound: any) => ({
220+
...compound,
221+
style: resolveTokens(compound.style, tokens),
222+
}));
223+
224+
// Return the styles function with resolved tokens
225+
return styles({
226+
...config,
227+
base: resolvedBase,
228+
variants: resolvedVariants,
229+
compoundVariants: resolvedCompoundVariants,
230+
});
231+
};
232+
233+
return {
234+
styles: wrappedStyles,
235+
};
236+
}

0 commit comments

Comments
 (0)