@payfit/unity-themes 2.24.2 → 2.25.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/css/unity.css +1653 -543
  2. package/dist/esm/components/unity-theme-provider.d.ts +25 -0
  3. package/dist/esm/components/unity-theme-provider.js +34 -0
  4. package/dist/esm/components/unity-theme-provider.test.d.ts +1 -0
  5. package/dist/esm/index.d.ts +1 -0
  6. package/dist/esm/index.js +8 -5
  7. package/dist/esm/scripts/actions/compose-multi-theme.d.ts +15 -0
  8. package/dist/esm/scripts/transforms/tailwind-color-token.d.ts +4 -3
  9. package/dist/esm/scripts/transforms/tailwind-grid-token.d.ts +2 -1
  10. package/dist/esm/scripts/transforms/tailwind-spacing-token.d.ts +1 -1
  11. package/dist/esm/scripts/transforms/tailwind-text-token.d.ts +1 -1
  12. package/dist/esm/scripts/transforms/tailwind-typography-token.d.ts +1 -4
  13. package/dist/esm/scripts/utils/prefix-transform.d.ts +4 -0
  14. package/dist/esm/utils/cn.d.ts +4 -3
  15. package/package.json +3 -2
  16. package/src/components/unity-theme-provider.stories.tsx +532 -0
  17. package/src/components/unity-theme-provider.test.tsx +150 -0
  18. package/src/components/unity-theme-provider.tsx +72 -0
  19. package/src/index.ts +8 -0
  20. package/src/scripts/actions/compose-multi-theme.ts +59 -0
  21. package/src/scripts/build.ts +261 -55
  22. package/src/scripts/formats/unity-theme.test.ts +180 -253
  23. package/src/scripts/formats/unity-theme.ts +27 -64
  24. package/src/scripts/transforms/tailwind-color-token.test.ts +18 -0
  25. package/src/scripts/transforms/tailwind-color-token.ts +7 -3
  26. package/src/scripts/transforms/tailwind-grid-token.test.ts +22 -0
  27. package/src/scripts/transforms/tailwind-grid-token.ts +7 -3
  28. package/src/scripts/transforms/tailwind-spacing-token.test.ts +9 -0
  29. package/src/scripts/transforms/tailwind-spacing-token.ts +15 -2
  30. package/src/scripts/transforms/tailwind-text-token.test.ts +18 -0
  31. package/src/scripts/transforms/tailwind-text-token.ts +15 -2
  32. package/src/scripts/transforms/tailwind-typography-token.test.ts +8 -2
  33. package/src/scripts/transforms/tailwind-typography-token.ts +5 -1
  34. package/src/scripts/utils/prefix-transform.test.ts +137 -0
  35. package/src/scripts/utils/prefix-transform.ts +16 -0
  36. package/src/utils/cn.ts +2 -2
  37. package/tokens/common/aspect-ratios.json +11 -0
  38. package/tokens/common/breakpoints.json +18 -0
  39. package/tokens/{text.json → common/font-sizes.json} +0 -28
  40. package/tokens/common/font-weights.json +18 -0
  41. package/tokens/{radii.json → common/radii.json} +0 -15
  42. package/tokens/{spacings.json → common/spacings.json} +0 -25
  43. package/tokens/legacy/radii.json +21 -0
  44. package/tokens/legacy/text.json +14 -0
  45. package/tokens/rebrand/colors.json +1400 -0
  46. package/tokens/rebrand/radii.json +21 -0
  47. package/tokens/rebrand/shadows.json +81 -0
  48. package/tokens/rebrand/text.json +14 -0
  49. package/tokens/rebrand/typography.json +329 -0
  50. package/dist/esm/scripts/formats/generators/header-generator.d.ts +0 -2
  51. package/src/scripts/formats/generators/header-generator.ts +0 -32
  52. /package/tokens/{animations.json → common/animations.json} +0 -0
  53. /package/tokens/{layout.json → common/layout.json} +0 -0
  54. /package/tokens/{sizes.json → common/sizes.json} +0 -0
  55. /package/tokens/{colors.json → legacy/colors.json} +0 -0
  56. /package/tokens/{shadows.json → legacy/shadows.json} +0 -0
  57. /package/tokens/{typography.json → legacy/typography.json} +0 -0
@@ -9,145 +9,152 @@ import { describe, expect, it } from 'vitest'
9
9
 
10
10
  import { unityThemeFormat } from './unity-theme.js'
11
11
 
12
- const transformedTokens = [
13
- {
14
- name: 'color-primary',
15
- $value: '#000000',
16
- $type: 'color',
17
- path: ['color', 'primary'],
18
- original: { $value: '#000000' },
19
- filePath: '',
20
- isSource: false,
21
- },
22
- {
23
- name: 'color-secondary',
24
- $value: '#555555',
25
- $type: 'color',
26
- path: ['color', 'secondary'],
27
- original: { $value: '{color.gray}' },
28
- filePath: '',
29
- isSource: false,
30
- },
31
- {
32
- name: 'color-gray',
33
- $value: '#555555',
34
- $type: 'color',
35
- path: ['color', 'gray'],
36
- original: { $value: '#555555' },
37
- },
38
- {
39
- name: 'spacing-1',
40
- $value: '0.25rem',
41
- $type: 'spacing',
42
- path: ['spacing', '1'],
43
- original: { $value: '0.25rem' },
44
- filePath: '',
45
- isSource: false,
46
- },
47
- {
48
- name: 'spacing-2',
49
- $value: '0.25rem',
50
- $type: 'spacing',
51
- path: ['spacing', '2'],
52
- original: { $value: '{spacing.1}' },
53
- filePath: '',
54
- isSource: false,
55
- },
56
- {
57
- name: 'grid-12-column-columns--default',
58
- $value: '12',
59
- $type: 'number',
60
- path: ['grid', '12-column', 'columns'],
61
- original: { $value: '12' },
62
- filePath: '',
63
- isSource: false,
64
- },
65
- {
66
- name: 'grid-12-column-gutter--default',
67
- $value: '1rem',
68
- $type: 'dimension',
69
- path: ['grid', '12-column', 'gutter'],
70
- original: { $value: '1rem' },
71
- },
72
- {
73
- name: 'grid-12-column-margin--default',
74
- $value: '0.25rem',
75
- $type: 'dimension',
76
- path: ['grid', '12-column', 'margin'],
77
- original: { $value: '{spacing.1}' },
78
- },
79
- {
80
- name: 'breakpoint-tablet',
81
- $value: '768px',
82
- $type: 'breakpoint',
83
- path: ['breakpoint', 'tablet'],
84
- original: { $value: '768px' },
85
- },
86
- {
87
- name: 'breakpoint-desktop',
88
- $value: '1024px',
89
- $type: 'breakpoint',
90
- path: ['breakpoint', 'desktop'],
91
- original: { $value: '1024px' },
92
- },
93
- {
94
- name: 'typography-default-h1',
95
- $value: 'normal 700 32px/1.104 Inter, sans-serif ',
96
- $type: 'typography',
97
- path: ['typography', 'h1', 'default'],
98
- attributes: {
99
- type: 'h1',
100
- category: 'typography',
101
- item: 'default',
12
+ /**
13
+ * Creates mock tokens. When prefix is set, token names include the prefix
14
+ * (matching the behavior of the updated name transforms).
15
+ */
16
+ function createTransformedTokens(prefix?: string) {
17
+ const p = prefix ? `${prefix}-` : ''
18
+ return [
19
+ {
20
+ name: `${p}color-primary`,
21
+ $value: '#000000',
22
+ $type: 'color',
23
+ path: ['color', 'primary'],
24
+ original: { $value: '#000000' },
25
+ filePath: '',
26
+ isSource: false,
102
27
  },
103
- original: {
104
- $value: {
105
- fontFamily: 'Inter, sans-serif',
106
- fontSize: '32px',
107
- fontWeight: 700,
108
- lineHeight: 1.104,
109
- },
28
+ {
29
+ name: `${p}color-secondary`,
30
+ $value: '#555555',
31
+ $type: 'color',
32
+ path: ['color', 'secondary'],
33
+ original: { $value: '{color.gray}' },
34
+ filePath: '',
35
+ isSource: false,
110
36
  },
111
- },
112
- {
113
- name: 'typography-sm-h1',
114
- $value: 'normal 700 36px/1.104 Inter, sans-serif ',
115
- $type: 'typography',
116
- path: ['typography', 'h1', 'sm'],
117
- attributes: {
118
- type: 'h1',
119
- category: 'typography',
120
- item: 'sm',
37
+ {
38
+ name: `${p}color-gray`,
39
+ $value: '#555555',
40
+ $type: 'color',
41
+ path: ['color', 'gray'],
42
+ original: { $value: '#555555' },
121
43
  },
122
- original: {
123
- $value: {
124
- fontFamily: 'Inter, sans-serif',
125
- fontSize: '36px',
126
- fontWeight: 700,
127
- lineHeight: 1.104,
44
+ {
45
+ name: `${p}spacing-1`,
46
+ $value: '0.25rem',
47
+ $type: 'spacing',
48
+ path: ['spacing', '1'],
49
+ original: { $value: '0.25rem' },
50
+ filePath: '',
51
+ isSource: false,
52
+ },
53
+ {
54
+ name: `${p}spacing-2`,
55
+ $value: '0.25rem',
56
+ $type: 'spacing',
57
+ path: ['spacing', '2'],
58
+ original: { $value: '{spacing.1}' },
59
+ filePath: '',
60
+ isSource: false,
61
+ },
62
+ {
63
+ name: `${p}grid-12-column-columns--default`,
64
+ $value: '12',
65
+ $type: 'number',
66
+ path: ['grid', '12-column', 'columns'],
67
+ original: { $value: '12' },
68
+ filePath: '',
69
+ isSource: false,
70
+ },
71
+ {
72
+ name: `${p}grid-12-column-gutter--default`,
73
+ $value: '1rem',
74
+ $type: 'dimension',
75
+ path: ['grid', '12-column', 'gutter'],
76
+ original: { $value: '1rem' },
77
+ },
78
+ {
79
+ name: `${p}grid-12-column-margin--default`,
80
+ $value: '0.25rem',
81
+ $type: 'dimension',
82
+ path: ['grid', '12-column', 'margin'],
83
+ original: { $value: '{spacing.1}' },
84
+ },
85
+ {
86
+ name: `${p}breakpoint-tablet`,
87
+ $value: '768px',
88
+ $type: 'breakpoint',
89
+ path: ['breakpoint', 'tablet'],
90
+ original: { $value: '768px' },
91
+ },
92
+ {
93
+ name: `${p}breakpoint-desktop`,
94
+ $value: '1024px',
95
+ $type: 'breakpoint',
96
+ path: ['breakpoint', 'desktop'],
97
+ original: { $value: '1024px' },
98
+ },
99
+ {
100
+ name: `${p}typography-default-h1`,
101
+ $value: 'normal 700 32px/1.104 Inter, sans-serif ',
102
+ $type: 'typography',
103
+ path: ['typography', 'h1', 'default'],
104
+ attributes: {
105
+ type: 'h1',
106
+ category: 'typography',
107
+ item: 'default',
108
+ },
109
+ original: {
110
+ $value: {
111
+ fontFamily: 'Inter, sans-serif',
112
+ fontSize: '32px',
113
+ fontWeight: 700,
114
+ lineHeight: 1.104,
115
+ },
128
116
  },
129
117
  },
130
- },
131
- {
132
- name: 'typography-md-h2',
133
- $value: 'normal 600 24px/1.2 Inter, sans-serif ',
134
- $type: 'typography',
135
- path: ['typography', 'h2', 'md'],
136
- attributes: {
137
- type: 'h2',
138
- category: 'typography',
139
- item: 'md',
118
+ {
119
+ name: `${p}typography-sm-h1`,
120
+ $value: 'normal 700 36px/1.104 Inter, sans-serif ',
121
+ $type: 'typography',
122
+ path: ['typography', 'h1', 'sm'],
123
+ attributes: {
124
+ type: 'h1',
125
+ category: 'typography',
126
+ item: 'sm',
127
+ },
128
+ original: {
129
+ $value: {
130
+ fontFamily: 'Inter, sans-serif',
131
+ fontSize: '36px',
132
+ fontWeight: 700,
133
+ lineHeight: 1.104,
134
+ },
135
+ },
140
136
  },
141
- original: {
142
- $value: {
143
- fontFamily: 'Inter, sans-serif',
144
- fontSize: '24px',
145
- fontWeight: 600,
146
- lineHeight: 1.2,
137
+ {
138
+ name: `${p}typography-md-h2`,
139
+ $value: 'normal 600 24px/1.2 Inter, sans-serif ',
140
+ $type: 'typography',
141
+ path: ['typography', 'h2', 'md'],
142
+ attributes: {
143
+ type: 'h2',
144
+ category: 'typography',
145
+ item: 'md',
146
+ },
147
+ original: {
148
+ $value: {
149
+ fontFamily: 'Inter, sans-serif',
150
+ fontSize: '24px',
151
+ fontWeight: 600,
152
+ lineHeight: 1.2,
153
+ },
147
154
  },
148
155
  },
149
- },
150
- ] as unknown as TransformedToken[]
156
+ ] as unknown as TransformedToken[]
157
+ }
151
158
 
152
159
  const tokenDef = {
153
160
  color: {
@@ -198,22 +205,19 @@ const tokenDef = {
198
205
  },
199
206
  } as unknown as TransformedTokens
200
207
 
201
- const createMockFormatFnArguments = (
202
- prefix?: string,
203
- outputReferences = false,
204
- ): FormatFnArguments =>
208
+ const createMockFormatFnArguments = (prefix?: string): FormatFnArguments =>
205
209
  ({
206
210
  dictionary: {
207
211
  tokens: tokenDef,
208
212
  unfilteredTokens: tokenDef,
209
- allTokens: transformedTokens,
213
+ allTokens: createTransformedTokens(prefix),
210
214
  tokenMap: new Map(),
211
215
  } as unknown as Dictionary,
212
216
  platform: {},
213
217
  options: {
214
218
  prefix,
215
- selector: '@theme static',
216
- outputReferences,
219
+ selector: '@theme',
220
+ outputReferences: true,
217
221
  usesDtcg: true,
218
222
  fileHeader: '/* theme header */',
219
223
  },
@@ -222,7 +226,7 @@ const createMockFormatFnArguments = (
222
226
  options: {
223
227
  prefix,
224
228
  selector: '@theme',
225
- outputReferences,
229
+ outputReferences: true,
226
230
  usesDtcg: true,
227
231
  fileHeader: '/* theme header */',
228
232
  },
@@ -230,41 +234,26 @@ const createMockFormatFnArguments = (
230
234
  }) as unknown as FormatFnArguments
231
235
 
232
236
  describe('css/unity-theme Format', () => {
233
- it('should output theme configuration without references (outputReferences = false)', async () => {
234
- const args = createMockFormatFnArguments(undefined, false)
237
+ it('should output @theme with var() references when no prefix is set', async () => {
238
+ const args = createMockFormatFnArguments(undefined)
235
239
  const result = await unityThemeFormat(args)
236
240
 
237
241
  expect(result).toMatchInlineSnapshot(`
238
- "/**
239
- * Do not edit directly, this file was auto-generated.
240
- */
241
-
242
- @import "@fontsource/inter";
243
- @import "@fontsource/inter/500.css";
244
- @import "@fontsource/inter/600.css";
245
- @import "@fontsource/inter/700.css";
246
- @import "@fontsource/source-serif-4";
247
- @import "@fontsource/source-serif-4/500.css";
248
- @import "@fontsource/source-serif-4/600.css";
249
- @import "@fontsource/source-serif-4/700.css";
250
- @import "@fontsource/roboto-mono";
251
- @import "tailwindcss";
252
-
253
- @theme static {
242
+ "@theme {
254
243
  --color-*: initial;
255
- --color-primary: #000000;
256
- --color-secondary: #555555;
257
- --color-gray: #555555;
258
- --spacing-1: 0.25rem;
259
- --spacing-2: 0.25rem;
260
- --grid-12-column-columns--default: 12;
261
- --grid-12-column-gutter--default: 1rem;
262
- --grid-12-column-margin--default: 0.25rem;
244
+ --color-primary: var(--color-primary);
245
+ --color-secondary: var(--color-secondary);
246
+ --color-gray: var(--color-gray);
247
+ --spacing-1: var(--spacing-1);
248
+ --spacing-2: var(--spacing-2);
249
+ --grid-12-column-columns--default: var(--grid-12-column-columns--default);
250
+ --grid-12-column-gutter--default: var(--grid-12-column-gutter--default);
251
+ --grid-12-column-margin--default: var(--grid-12-column-margin--default);
263
252
  --breakpoint-tablet: 768px;
264
253
  --breakpoint-desktop: 1024px;
265
- --typography-default-h1: normal 700 32px/1.104 Inter, sans-serif;
266
- --typography-sm-h1: normal 700 36px/1.104 Inter, sans-serif;
267
- --typography-md-h2: normal 600 24px/1.2 Inter, sans-serif;
254
+ --typography-default-h1: var(--typography-default-h1);
255
+ --typography-sm-h1: var(--typography-sm-h1);
256
+ --typography-md-h2: var(--typography-md-h2);
268
257
  }
269
258
 
270
259
  @utility grid-12-column {
@@ -287,97 +276,26 @@ describe('css/unity-theme Format', () => {
287
276
  `)
288
277
  })
289
278
 
290
- it.skip('should output theme configuration with references (outputReferences = true)', async () => {
291
- const args = createMockFormatFnArguments(undefined, true)
292
- const result = await unityThemeFormat(args)
293
-
294
- expect(result).toMatchInlineSnapshot(`
295
- "/**
296
- * Do not edit directly, this file was auto-generated.
297
- */
298
-
299
- @import "@fontsource/inter";
300
- @import "@fontsource/inter/500.css";
301
- @import "@fontsource/inter/600.css";
302
- @import "@fontsource/inter/700.css";
303
- @import "@fontsource/source-serif-4";
304
- @import "@fontsource/source-serif-4/500.css";
305
- @import "@fontsource/source-serif-4/600.css";
306
- @import "@fontsource/source-serif-4/700.css";
307
- @import "tailwindcss";
308
-
309
- @theme {
310
- --color-*: initial;
311
- --color-primary: #000000;
312
- --color-gray: #555555;
313
- --color-secondary: var(--uy-color-gray);
314
- --spacing-1: 0.25rem;
315
- --spacing-2: var(--uy-spacing-1);
316
- --grid-12-column-columns--default: 12;
317
- --grid-12-column-gutter--default: 1rem;
318
- --grid-12-column-margin--default: var(--uy-spacing-1);
319
- --breakpoint-tablet: 768px;
320
- --breakpoint-desktop: 1024px;
321
- --typography-h1: normal 700 32px/1.104 Inter, sans-serif;
322
- }
323
-
324
- @layer components {
325
- .layout-grid-12-column {
326
- display: grid;
327
- grid-template-columns: repeat(var(--grid-12-column-columns), 1fr);
328
- grid-gap: var(--grid-12-column-gutter);
329
- margin: 0 var(--grid-12-column-margin);
330
- }
331
- }
332
-
333
- @utility typography-* {
334
- font: var(--value-default);
335
- @media screen and (min-width: 490px) {
336
- font: var(--value-sm, var(--value-default));
337
- }
338
- @media screen and (min-width: 768px) {
339
- font: var(--value-md, var(--value-sm));
340
- }
341
- }
342
- "
343
- `)
344
- })
345
-
346
- it('should output theme configuration with prefix (prefix: any string)', async () => {
347
- const args = createMockFormatFnArguments('uy', false)
279
+ it('should strip prefix from @theme declarations but keep it in var() references', async () => {
280
+ const args = createMockFormatFnArguments('uy')
348
281
  const result = await unityThemeFormat(args)
349
282
 
350
283
  expect(result).toMatchInlineSnapshot(`
351
- "/**
352
- * Do not edit directly, this file was auto-generated.
353
- */
354
-
355
- @import "@fontsource/inter";
356
- @import "@fontsource/inter/500.css";
357
- @import "@fontsource/inter/600.css";
358
- @import "@fontsource/inter/700.css";
359
- @import "@fontsource/source-serif-4";
360
- @import "@fontsource/source-serif-4/500.css";
361
- @import "@fontsource/source-serif-4/600.css";
362
- @import "@fontsource/source-serif-4/700.css";
363
- @import "@fontsource/roboto-mono";
364
- @import "tailwindcss" prefix(uy);
365
-
366
- @theme static {
284
+ "@theme {
367
285
  --color-*: initial;
368
- --color-primary: #000000;
369
- --color-secondary: #555555;
370
- --color-gray: #555555;
371
- --spacing-1: 0.25rem;
372
- --spacing-2: 0.25rem;
373
- --grid-12-column-columns--default: 12;
374
- --grid-12-column-gutter--default: 1rem;
375
- --grid-12-column-margin--default: 0.25rem;
286
+ --color-primary: var(--uy-color-primary);
287
+ --color-secondary: var(--uy-color-secondary);
288
+ --color-gray: var(--uy-color-gray);
289
+ --spacing-1: var(--uy-spacing-1);
290
+ --spacing-2: var(--uy-spacing-2);
291
+ --grid-12-column-columns--default: var(--uy-grid-12-column-columns--default);
292
+ --grid-12-column-gutter--default: var(--uy-grid-12-column-gutter--default);
293
+ --grid-12-column-margin--default: var(--uy-grid-12-column-margin--default);
376
294
  --breakpoint-tablet: 768px;
377
295
  --breakpoint-desktop: 1024px;
378
- --typography-default-h1: normal 700 32px/1.104 Inter, sans-serif;
379
- --typography-sm-h1: normal 700 36px/1.104 Inter, sans-serif;
380
- --typography-md-h2: normal 600 24px/1.2 Inter, sans-serif;
296
+ --typography-default-h1: var(--uy-typography-default-h1);
297
+ --typography-sm-h1: var(--uy-typography-sm-h1);
298
+ --typography-md-h2: var(--uy-typography-md-h2);
381
299
  }
382
300
 
383
301
  @utility grid-12-column {
@@ -399,4 +317,13 @@ describe('css/unity-theme Format', () => {
399
317
  "
400
318
  `)
401
319
  })
320
+
321
+ it('should output breakpoint values as static (not var references)', async () => {
322
+ const args = createMockFormatFnArguments('uy')
323
+ const result = await unityThemeFormat(args)
324
+
325
+ expect(result).toContain('--breakpoint-tablet: 768px;')
326
+ expect(result).toContain('--breakpoint-desktop: 1024px;')
327
+ expect(result).not.toContain('var(--uy-breakpoint-')
328
+ })
402
329
  })
@@ -1,12 +1,10 @@
1
1
  import type { FormatFnArguments } from 'style-dictionary/types'
2
2
 
3
3
  import prettier from 'prettier'
4
- import StyleDictionary from 'style-dictionary'
5
4
 
6
- import { generateThemeHeader } from './generators/header-generator.js'
7
5
  import { processGridTokens } from './processors/grid-processor.js'
8
6
  import { processTypographyTokens } from './processors/typography-processor.js'
9
- import { getPrefixes, processCssVariables } from './utils.js'
7
+ import { getPrefixes } from './utils.js'
10
8
 
11
9
  export const name = 'css/unity-theme'
12
10
 
@@ -14,73 +12,38 @@ export async function unityThemeFormat(args: FormatFnArguments) {
14
12
  const { dictionary, options } = args
15
13
  const { variablePrefix } = getPrefixes(options)
16
14
 
17
- const header = await generateThemeHeader(args)
15
+ // Build @theme block directly from the dictionary.
16
+ // Every variable becomes a var(--uy-*) reference so the CSS cascade
17
+ // controls which value is active at runtime.
18
+ // Exception: breakpoint variables must be static pixel values because
19
+ // Tailwind resolves them at build time to generate @media rules.
20
+ const themeLines: string[] = ['--color-*: initial;']
21
+
22
+ for (const token of dictionary.allTokens) {
23
+ // Strip the prefix from the declaration name (Tailwind adds it)
24
+ const unprefixedName = token.name.replace(
25
+ new RegExp(`^${variablePrefix}`),
26
+ '',
27
+ )
28
+
29
+ if (
30
+ unprefixedName.startsWith('breakpoint-') ||
31
+ unprefixedName.startsWith('container-')
32
+ ) {
33
+ themeLines.push(` --${unprefixedName}: ${token.$value};`)
34
+ } else {
35
+ themeLines.push(` --${unprefixedName}: var(--${token.name});`)
36
+ }
37
+ }
18
38
 
19
- // Get the raw CSS variable declarations without prefix for @theme block
20
- const rawCssVars = (await StyleDictionary.hooks.formats['css/variables']?.({
21
- ...args,
22
- file: {
23
- ...args.file,
24
- options: { ...args.file.options, showFileHeader: false },
25
- },
26
- options: {
27
- ...options,
28
- prefix: '',
29
- },
30
- })) as string
39
+ const themeBlock = `@theme {\n${themeLines.join('\n')}\n}`
31
40
 
32
- // Process the CSS variables to add prefix to var() references
33
- const processedCssVars = processCssVariables(
34
- rawCssVars,
35
- variablePrefix,
36
- ).replace('@theme static {', '@theme static {\n--color-*: initial;')
37
41
  const gridClasses = processGridTokens(dictionary, options)
38
42
  const typographyClasses = processTypographyTokens(dictionary, options)
39
43
 
40
- /*
41
- Important annotations
42
-
43
- When using prefix with `@import "tailwindcss" prefix(prefix);`, take into account:
44
-
45
- 1. variable declarations inside @theme must not have the prefix
46
- ```css
47
- @theme {
48
- // wrong! duplicated prefix
49
- --uy-color-primary: #000;
50
- }
51
- ```
52
-
53
- 2. When compiled by tailwind v4, the variables WILL HAVE the prefix
54
- ```css
55
- @theme {
56
- --color-primary: #000;
57
- }
58
-
59
- // generates:
60
- :root {
61
- --uy-color-primary: #000;
62
- }
63
-
64
- 3. Therefore, if we want `outputReferences` to work, the variable name referred to inside `var()` MUST have the prefix.
65
-
66
- ```css
67
- @theme {
68
- --color-gray-1000: #000;
69
- --color-primary: var(--color-gray-1000); // ⚠️Achtung! won't work because tailwind does not process variables inside var()
70
- --color-primary: var(--uy-color-gray-1000); // ✅ works!
71
- }
72
-
73
- // generates:
74
- :root {
75
- --uy-color-gray-1000: #000;
76
- --uy-color-primary: var(--uy-color-gray-1000);
77
- }
78
- ```
79
- **/
80
44
  return prettier.format(
81
- `${header}
82
-
83
- ${processedCssVars}
45
+ `
46
+ ${themeBlock}
84
47
 
85
48
  ${gridClasses}
86
49
 
@@ -282,5 +282,23 @@ describe('tailwind color token transform', () => {
282
282
 
283
283
  expect(result).toBe('color-primary')
284
284
  })
285
+
286
+ it('should prepend prefix when config.prefix is set', () => {
287
+ const token = createMockToken(['color', 'primary', 'default'])
288
+ const config = { ...createMockConfig(), prefix: 'uy' }
289
+
290
+ const result = transform(token, config, {})
291
+
292
+ expect(result).toBe('uy-color-primary')
293
+ })
294
+
295
+ it('should not prepend prefix when config.prefix is undefined', () => {
296
+ const token = createMockToken(['color', 'blue', '500'])
297
+ const config = createMockConfig()
298
+
299
+ const result = transform(token, config, {})
300
+
301
+ expect(result).toBe('color-blue-500')
302
+ })
285
303
  })
286
304
  })
@@ -1,13 +1,17 @@
1
1
  import type { Token } from 'style-dictionary'
2
- import type { Config, NameTransform } from 'style-dictionary/types'
2
+ import type { NameTransform } from 'style-dictionary/types'
3
+
4
+ import { prefixTransform } from '../utils/prefix-transform'
3
5
 
4
6
  type Transformer = NameTransform['transform']
5
7
 
6
- export function filter(token: Token, options: Config): boolean {
8
+ export function filter(token: Token): boolean {
7
9
  return token.path[0] === 'color'
8
10
  }
9
11
 
10
- export const transform: Transformer = (token, config) => {
12
+ export const tailwindColorTokenNameTransform: Transformer = token => {
11
13
  const ignoreDefault = (nameToken: string) => !nameToken.includes('default')
12
14
  return [...token.path.filter(ignoreDefault)].join('-').toLowerCase()
13
15
  }
16
+
17
+ export const transform = prefixTransform(tailwindColorTokenNameTransform)
@@ -88,5 +88,27 @@ describe('tailwind-grid-token', () => {
88
88
 
89
89
  expect(result).toBe('grid-layout-columns--default')
90
90
  })
91
+
92
+ it('should prepend prefix when config.prefix is set', () => {
93
+ const token: TransformedToken = {
94
+ name: 'grid-layout-default-columns',
95
+ path: ['grid', 'layout', 'default', 'columns'],
96
+ original: { $value: 6 },
97
+ attributes: {
98
+ category: 'grid',
99
+ type: 'layout',
100
+ item: 'default',
101
+ subitem: 'columns',
102
+ },
103
+ $value: 6,
104
+ $type: 'number',
105
+ filePath: 'test.json',
106
+ isSource: true,
107
+ }
108
+
109
+ const result = transform(token, { prefix: 'uy' }, {})
110
+
111
+ expect(result).toBe('uy-grid-layout-columns--default')
112
+ })
91
113
  })
92
114
  })