@styleframe/transpiler 1.0.2 → 1.0.3

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 (60) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/transpiler.d.ts +120 -0
  3. package/dist/transpiler.js +432 -0
  4. package/dist/transpiler.umd.cjs +14 -0
  5. package/package.json +8 -2
  6. package/.tsbuildinfo +0 -1
  7. package/src/constants.ts +0 -4
  8. package/src/consume/at-rule.test.ts +0 -339
  9. package/src/consume/at-rule.ts +0 -34
  10. package/src/consume/consume.test.ts +0 -259
  11. package/src/consume/consume.ts +0 -81
  12. package/src/consume/container.test.ts +0 -501
  13. package/src/consume/container.ts +0 -73
  14. package/src/consume/css.test.ts +0 -187
  15. package/src/consume/css.ts +0 -17
  16. package/src/consume/declarations.test.ts +0 -210
  17. package/src/consume/declarations.ts +0 -17
  18. package/src/consume/index.ts +0 -12
  19. package/src/consume/primitive.test.ts +0 -52
  20. package/src/consume/primitive.ts +0 -16
  21. package/src/consume/ref.test.ts +0 -84
  22. package/src/consume/ref.ts +0 -22
  23. package/src/consume/root.test.ts +0 -353
  24. package/src/consume/root.ts +0 -19
  25. package/src/consume/selector.test.ts +0 -441
  26. package/src/consume/selector.ts +0 -17
  27. package/src/consume/theme.test.ts +0 -215
  28. package/src/consume/theme.ts +0 -15
  29. package/src/consume/utility.test.ts +0 -696
  30. package/src/consume/utility.ts +0 -31
  31. package/src/consume/variable.test.ts +0 -197
  32. package/src/consume/variable.ts +0 -20
  33. package/src/defaults.ts +0 -21
  34. package/src/generator/genAtRuleQuery.test.ts +0 -148
  35. package/src/generator/genAtRuleQuery.ts +0 -3
  36. package/src/generator/genDeclaration.test.ts +0 -283
  37. package/src/generator/genDeclaration.ts +0 -9
  38. package/src/generator/genDeclarationsBlock.test.ts +0 -278
  39. package/src/generator/genDeclarationsBlock.ts +0 -7
  40. package/src/generator/genDeclareVariable.test.ts +0 -323
  41. package/src/generator/genDeclareVariable.ts +0 -6
  42. package/src/generator/genInlineAtRule.test.ts +0 -351
  43. package/src/generator/genInlineAtRule.ts +0 -5
  44. package/src/generator/genReferenceVariable.test.ts +0 -392
  45. package/src/generator/genReferenceVariable.ts +0 -5
  46. package/src/generator/genSafePropertyName.test.ts +0 -489
  47. package/src/generator/genSafePropertyName.ts +0 -5
  48. package/src/generator/genSafeVariableName.test.ts +0 -358
  49. package/src/generator/genSafeVariableName.ts +0 -21
  50. package/src/generator/genSelector.test.ts +0 -357
  51. package/src/generator/genSelector.ts +0 -5
  52. package/src/generator/index.ts +0 -9
  53. package/src/index.ts +0 -6
  54. package/src/transpile.test.ts +0 -829
  55. package/src/transpile.ts +0 -34
  56. package/src/types.ts +0 -23
  57. package/src/utils.ts +0 -18
  58. package/src/vite-env.d.ts +0 -1
  59. package/tsconfig.json +0 -7
  60. package/vite.config.ts +0 -5
@@ -1,829 +0,0 @@
1
- import type { Styleframe, StyleframeOptions } from "@styleframe/core";
2
- import {
3
- createAtRuleFunction,
4
- createCssFunction,
5
- createRefFunction,
6
- createSelectorFunction,
7
- createThemeFunction,
8
- createUtilityFunction,
9
- createVariableFunction,
10
- styleframe,
11
- } from "@styleframe/core";
12
- import { createFile, transpile } from "./transpile";
13
-
14
- describe("transpile", () => {
15
- let instance: Styleframe;
16
- let variable: ReturnType<typeof createVariableFunction>;
17
- let ref: ReturnType<typeof createRefFunction>;
18
- let css: ReturnType<typeof createCssFunction>;
19
- let selector: ReturnType<typeof createSelectorFunction>;
20
- let theme: ReturnType<typeof createThemeFunction>;
21
- let atRule: ReturnType<typeof createAtRuleFunction>;
22
- let utility: ReturnType<typeof createUtilityFunction>;
23
-
24
- beforeEach(() => {
25
- instance = styleframe();
26
- ({
27
- variable = variable,
28
- ref = ref,
29
- css = css,
30
- selector = selector,
31
- theme = theme,
32
- atRule = atRule,
33
- utility = utility,
34
- } = instance);
35
- });
36
-
37
- describe("createFile", () => {
38
- it("should create a file with name and content", () => {
39
- const file = createFile("test.css", "body { margin: 0; }");
40
-
41
- expect(file.name).toBe("test.css");
42
- expect(file.content).toEqual("body { margin: 0; }");
43
- });
44
-
45
- it("should create a file with empty content when no content provided", () => {
46
- const file = createFile("empty.css");
47
-
48
- expect(file.name).toBe("empty.css");
49
- expect(file.content).toEqual("");
50
- });
51
-
52
- it("should create a file with content string", () => {
53
- const content = ":root {\n\t--color: #000;\n}";
54
- const file = createFile("variables.css", content);
55
-
56
- expect(file.name).toBe("variables.css");
57
- expect(file.content).toEqual(content);
58
- });
59
- });
60
-
61
- describe("transpile", () => {
62
- it("should transpile an empty Styleframe instance", () => {
63
- const output = transpile(instance);
64
-
65
- expect(output.files).toHaveLength(2);
66
- expect(output.files[0]!.name).toBe("index.css");
67
- expect(output.files[0]!.content).toEqual("");
68
- expect(output.files[1]!.name).toBe("index.ts");
69
- expect(output.files[1]!.content).toEqual("");
70
- });
71
-
72
- it("should transpile a simple variable", () => {
73
- variable("primary-color", "#006cff");
74
-
75
- const output = transpile(instance);
76
-
77
- expect(output.files).toHaveLength(2);
78
- expect(output.files[0]!.name).toBe("index.css");
79
- expect(output.files[0]!.content).toEqual(`:root {
80
- \t--primary-color: #006cff;
81
- }`);
82
- expect(output.files[1]!.name).toBe("index.ts");
83
- expect(output.files[1]!.content).toEqual("");
84
- });
85
-
86
- it("should transpile multiple variables", () => {
87
- variable("primary-color", "#006cff");
88
- variable("secondary-color", "#ff6c00");
89
- variable("font-size", "16px");
90
-
91
- const output = transpile(instance);
92
- const content = output.files[0]!.content;
93
-
94
- expect(content).toEqual(`:root {
95
- \t--primary-color: #006cff;
96
- \t--secondary-color: #ff6c00;
97
- \t--font-size: 16px;
98
- }`);
99
- });
100
-
101
- it("should transpile selectors", () => {
102
- selector(".button", {
103
- padding: "0.5rem 1rem",
104
- backgroundColor: "#006cff",
105
- color: "#ffffff",
106
- });
107
-
108
- const output = transpile(instance);
109
- const content = output.files[0]!.content;
110
-
111
- expect(content).toEqual(`.button {
112
- \tpadding: 0.5rem 1rem;
113
- \tbackground-color: #006cff;
114
- \tcolor: #ffffff;
115
- }`);
116
- });
117
-
118
- it("should transpile themes", () => {
119
- theme("light", ({ variable: v }) => {
120
- v("background-color", "#ffffff");
121
- v("text-color", "#000000");
122
- });
123
-
124
- theme("dark", ({ variable: v }) => {
125
- v("background-color", "#000000");
126
- v("text-color", "#ffffff");
127
- });
128
-
129
- const output = transpile(instance);
130
- const content = output.files[0]!.content;
131
-
132
- expect(content).toEqual(`
133
-
134
- [data-theme="light"] {
135
- \t--background-color: #ffffff;
136
- \t--text-color: #000000;
137
- }
138
-
139
- [data-theme="dark"] {
140
- \t--background-color: #000000;
141
- \t--text-color: #ffffff;
142
- }`);
143
- });
144
-
145
- it("should transpile at-rules", () => {
146
- atRule("media", "(min-width: 768px)", ({ selector: s }) => {
147
- s(".container", {
148
- maxWidth: "1200px",
149
- margin: "0 auto",
150
- });
151
- });
152
-
153
- const output = transpile(instance);
154
- const content = output.files[0]!.content;
155
-
156
- expect(content).toEqual(`@media (min-width: 768px) {
157
- \t.container {
158
- \t\tmax-width: 1200px;
159
- \t\tmargin: 0 auto;
160
- \t}
161
- }`);
162
- });
163
-
164
- it("should transpile utilities", () => {
165
- const createMarginUtility = utility("margin", ({ value }) => ({
166
- margin: value,
167
- }));
168
-
169
- createMarginUtility({
170
- sm: "8px",
171
- md: "16px",
172
- lg: "24px",
173
- });
174
-
175
- const output = transpile(instance);
176
- const content = output.files[0]!.content;
177
-
178
- expect(content).toEqual(`._margin\\:sm {
179
- \tmargin: 8px;
180
- }
181
-
182
- ._margin\\:md {
183
- \tmargin: 16px;
184
- }
185
-
186
- ._margin\\:lg {
187
- \tmargin: 24px;
188
- }`);
189
- });
190
-
191
- it("should transpile with custom options", () => {
192
- const customOptions: StyleframeOptions = {
193
- variables: {
194
- name: ({ name }) => `--app-${name}`,
195
- },
196
- };
197
-
198
- const customInstance = styleframe(customOptions);
199
- const customRoot = customInstance.root;
200
- const customVariable = createVariableFunction(customRoot, customRoot);
201
-
202
- customVariable("primary", "#006cff");
203
- customVariable("secondary", "#ff6c00");
204
-
205
- const output = transpile(customInstance);
206
- const content = output.files[0]!.content;
207
-
208
- expect(content).toEqual(`:root {
209
- \t--app-primary: #006cff;
210
- \t--app-secondary: #ff6c00;
211
- }`);
212
- });
213
-
214
- it("should handle variable references", () => {
215
- const primaryColor = variable("primary-color", "#006cff");
216
-
217
- selector(".button", {
218
- backgroundColor: ref(primaryColor),
219
- border: css`2px solid ${ref(primaryColor)}`,
220
- });
221
-
222
- const output = transpile(instance);
223
- const content = output.files[0]!.content;
224
-
225
- expect(content).toEqual(`:root {
226
- \t--primary-color: #006cff;
227
- }
228
-
229
- .button {
230
- \tbackground-color: var(--primary-color);
231
- \tborder: 2px solid var(--primary-color);
232
- }`);
233
- });
234
-
235
- it("should handle nested selectors", () => {
236
- selector(".card", ({ selector: s }) => {
237
- s(".title", {
238
- fontSize: "1.5rem",
239
- fontWeight: "bold",
240
- });
241
-
242
- s("&:hover", {
243
- transform: "translateY(-2px)",
244
- boxShadow: "0 4px 8px rgba(0,0,0,0.1)",
245
- });
246
-
247
- return {
248
- padding: "1rem",
249
- borderRadius: "8px",
250
- };
251
- });
252
-
253
- const output = transpile(instance);
254
- const content = output.files[0]!.content;
255
-
256
- expect(content).toEqual(`.card {
257
- \tpadding: 1rem;
258
- \tborder-radius: 8px;
259
- \t
260
- \t.title {
261
- \t\tfont-size: 1.5rem;
262
- \t\tfont-weight: bold;
263
- \t}
264
- \t
265
- \t&:hover {
266
- \t\ttransform: translateY(-2px);
267
- \t\tbox-shadow: 0 4px 8px rgba(0,0,0,0.1);
268
- \t}
269
- }`);
270
- });
271
-
272
- it("should transpile a complex scenario with utilities, modifiers, themes, and nested structures", () => {
273
- // Define global variables
274
- const primaryColor = variable("primary-color", "#006cff");
275
- const secondaryColor = variable("secondary-color", "#ff6c00");
276
- variable("font-family", "'Inter', sans-serif");
277
- variable("spacing-unit", "8px");
278
-
279
- // Create utilities
280
- const createPaddingUtility = utility("padding", ({ value }) => ({
281
- padding: value,
282
- }));
283
-
284
- const createFlexUtility = utility("flex", ({ value }) => ({
285
- display: "flex",
286
- flexDirection: value,
287
- }));
288
-
289
- createPaddingUtility({
290
- sm: "8px",
291
- md: "16px",
292
- lg: "24px",
293
- xl: "32px",
294
- });
295
-
296
- createFlexUtility({
297
- row: "row",
298
- col: "column",
299
- });
300
-
301
- // Create base styles
302
- selector("*", {
303
- boxSizing: "border-box",
304
- margin: "0",
305
- padding: "0",
306
- });
307
-
308
- selector("body", {
309
- fontFamily: ref("font-family"),
310
- lineHeight: "1.6",
311
- });
312
-
313
- // Create component styles with nested selectors and modifiers
314
- selector(".button", ({ selector: s, variable: v }) => {
315
- v("button-bg", ref(primaryColor));
316
- v("button-hover-bg", ref(secondaryColor));
317
-
318
- s("&:hover", {
319
- backgroundColor: ref("button-hover-bg"),
320
- transform: "scale(1.05)",
321
- });
322
-
323
- s("&:active", {
324
- transform: "scale(0.98)",
325
- });
326
-
327
- s("&.button--large", {
328
- padding: "1rem 2rem",
329
- fontSize: "1.125rem",
330
- });
331
-
332
- s("&.button--disabled", {
333
- opacity: "0.5",
334
- cursor: "not-allowed",
335
- });
336
-
337
- s(".button__icon", {
338
- marginRight: "0.5rem",
339
- verticalAlign: "middle",
340
- });
341
-
342
- return {
343
- backgroundColor: ref("button-bg"),
344
- color: "#ffffff",
345
- padding: "0.75rem 1.5rem",
346
- border: "none",
347
- borderRadius: "4px",
348
- cursor: "pointer",
349
- transition: "all 0.3s ease",
350
- fontSize: "1rem",
351
- };
352
- });
353
-
354
- // Create card component with complex nesting
355
- selector(".card", ({ selector: s, variable: v }) => {
356
- v("card-shadow", "0 2px 8px rgba(0,0,0,0.1)");
357
- v("card-bg", "#ffffff");
358
-
359
- s(".card__header", ({ selector: nested }) => {
360
- nested(".card__title", {
361
- fontSize: "1.5rem",
362
- fontWeight: "600",
363
- color: ref(primaryColor),
364
- });
365
-
366
- nested(".card__subtitle", {
367
- fontSize: "0.875rem",
368
- color: "#666666",
369
- marginTop: "0.25rem",
370
- });
371
-
372
- return {
373
- padding: "1.5rem",
374
- borderBottom: "1px solid #e0e0e0",
375
- };
376
- });
377
-
378
- s(".card__body", {
379
- padding: "1.5rem",
380
- });
381
-
382
- s(".card__footer", ({ selector: nested }) => {
383
- nested(".button", {
384
- marginRight: "0.5rem",
385
- });
386
-
387
- return {
388
- padding: "1rem 1.5rem",
389
- borderTop: "1px solid #e0e0e0",
390
- display: "flex",
391
- justifyContent: "flex-end",
392
- };
393
- });
394
-
395
- s("&:hover", {
396
- boxShadow: "0 4px 16px rgba(0,0,0,0.15)",
397
- transform: "translateY(-2px)",
398
- });
399
-
400
- return {
401
- backgroundColor: ref("card-bg"),
402
- boxShadow: ref("card-shadow"),
403
- borderRadius: "8px",
404
- overflow: "hidden",
405
- transition: "all 0.3s ease",
406
- };
407
- });
408
-
409
- // Create themes with overrides
410
- theme("light", ({ variable: v, selector: s }) => {
411
- v("bg-primary", "#ffffff");
412
- v("bg-secondary", "#f5f5f5");
413
- v("text-primary", "#1a1a1a");
414
- v("text-secondary", "#666666");
415
- v("border-color", "#e0e0e0");
416
-
417
- s(".card", ({ variable: cardVar }) => {
418
- cardVar("card-bg", ref("bg-primary"));
419
- cardVar("card-shadow", "0 2px 8px rgba(0,0,0,0.08)");
420
- });
421
-
422
- s(".button", ({ variable: btnVar }) => {
423
- btnVar("button-bg", ref(primaryColor));
424
- });
425
- });
426
-
427
- theme("dark", ({ variable: v, selector: s }) => {
428
- v("bg-primary", "#1a1a1a");
429
- v("bg-secondary", "#2d2d2d");
430
- v("text-primary", "#ffffff");
431
- v("text-secondary", "#b0b0b0");
432
- v("border-color", "#404040");
433
-
434
- s("body", {
435
- backgroundColor: ref("bg-primary"),
436
- color: ref("text-primary"),
437
- });
438
-
439
- s(".card", ({ variable: cardVar }) => {
440
- cardVar("card-bg", ref("bg-secondary"));
441
- cardVar("card-shadow", "0 2px 8px rgba(0,0,0,0.3)");
442
-
443
- return {
444
- borderColor: ref("border-color"),
445
- };
446
- });
447
-
448
- s(".button", ({ variable: btnVar }) => {
449
- btnVar("button-bg", "#0080ff");
450
- btnVar("button-hover-bg", "#0066cc");
451
- });
452
- });
453
-
454
- // Create responsive at-rules
455
- atRule("media", "(min-width: 768px)", ({ selector: s }) => {
456
- s(".container", {
457
- maxWidth: "768px",
458
- margin: "0 auto",
459
- padding: "0 1rem",
460
- });
461
-
462
- s(".card", {
463
- maxWidth: "600px",
464
- });
465
- });
466
-
467
- atRule("media", "(min-width: 1024px)", ({ selector: s }) => {
468
- s(".container", {
469
- maxWidth: "1024px",
470
- });
471
-
472
- s(".grid", {
473
- display: "grid",
474
- gridTemplateColumns: "repeat(3, 1fr)",
475
- gap: "1.5rem",
476
- });
477
- });
478
-
479
- // Create print styles
480
- atRule("media", "print", ({ selector: s }) => {
481
- s("body", {
482
- backgroundColor: "#ffffff",
483
- color: "#000000",
484
- });
485
-
486
- s(".button", {
487
- display: "none",
488
- });
489
-
490
- s(".card", {
491
- boxShadow: "none",
492
- border: "1px solid #000000",
493
- });
494
- });
495
-
496
- // Create animation keyframes
497
- atRule("keyframes", "fadeIn", {
498
- "0%": {
499
- opacity: "0",
500
- },
501
- "100%": {
502
- opacity: "1",
503
- },
504
- });
505
-
506
- atRule("keyframes", "slideUp", {
507
- "0%": {
508
- transform: "translateY(20px)",
509
- opacity: "0",
510
- },
511
- "100%": {
512
- transform: "translateY(0)",
513
- opacity: "1",
514
- },
515
- });
516
-
517
- // Create animation classes using the keyframes
518
- selector(".fade-in", {
519
- animation: "fadeIn 0.3s ease-in-out",
520
- });
521
-
522
- selector(".slide-up", {
523
- animation: "slideUp 0.5s ease-out",
524
- });
525
-
526
- // Transpile the complex scenario
527
- const output = transpile(instance);
528
-
529
- expect(output.files).toHaveLength(2);
530
- expect(output.files[0]!.name).toBe("index.css");
531
-
532
- const content = output.files[0]!.content;
533
-
534
- // This is a complex test that validates the structure is correct
535
- // TODO: Fix keyframes output - currently outputs as [object Object] instead of proper CSS properties
536
- // Note: The order of items matters - atRules and keyframes come before themes in the output
537
- expect(content).toEqual(`:root {
538
- \t--primary-color: #006cff;
539
- \t--secondary-color: #ff6c00;
540
- \t--font-family: 'Inter', sans-serif;
541
- \t--spacing-unit: 8px;
542
- }
543
-
544
- ._padding\\:sm {
545
- \tpadding: 8px;
546
- }
547
-
548
- ._padding\\:md {
549
- \tpadding: 16px;
550
- }
551
-
552
- ._padding\\:lg {
553
- \tpadding: 24px;
554
- }
555
-
556
- ._padding\\:xl {
557
- \tpadding: 32px;
558
- }
559
-
560
- ._flex\\:row {
561
- \tdisplay: flex;
562
- \tflex-direction: row;
563
- }
564
-
565
- ._flex\\:col {
566
- \tdisplay: flex;
567
- \tflex-direction: column;
568
- }
569
-
570
- * {
571
- \tbox-sizing: border-box;
572
- \tmargin: 0;
573
- \tpadding: 0;
574
- }
575
-
576
- body {
577
- \tfont-family: var(--font-family);
578
- \tline-height: 1.6;
579
- }
580
-
581
- .button {
582
- \t--button-bg: var(--primary-color);
583
- \t--button-hover-bg: var(--secondary-color);
584
- \t
585
- \tbackground-color: var(--button-bg);
586
- \tcolor: #ffffff;
587
- \tpadding: 0.75rem 1.5rem;
588
- \tborder: none;
589
- \tborder-radius: 4px;
590
- \tcursor: pointer;
591
- \ttransition: all 0.3s ease;
592
- \tfont-size: 1rem;
593
- \t
594
- \t&:hover {
595
- \t\tbackground-color: var(--button-hover-bg);
596
- \t\ttransform: scale(1.05);
597
- \t}
598
- \t
599
- \t&:active {
600
- \t\ttransform: scale(0.98);
601
- \t}
602
- \t
603
- \t&.button--large {
604
- \t\tpadding: 1rem 2rem;
605
- \t\tfont-size: 1.125rem;
606
- \t}
607
- \t
608
- \t&.button--disabled {
609
- \t\topacity: 0.5;
610
- \t\tcursor: not-allowed;
611
- \t}
612
- \t
613
- \t.button__icon {
614
- \t\tmargin-right: 0.5rem;
615
- \t\tvertical-align: middle;
616
- \t}
617
- }
618
-
619
- .card {
620
- \t--card-shadow: 0 2px 8px rgba(0,0,0,0.1);
621
- \t--card-bg: #ffffff;
622
- \t
623
- \tbackground-color: var(--card-bg);
624
- \tbox-shadow: var(--card-shadow);
625
- \tborder-radius: 8px;
626
- \toverflow: hidden;
627
- \ttransition: all 0.3s ease;
628
- \t
629
- \t.card__header {
630
- \t\tpadding: 1.5rem;
631
- \t\tborder-bottom: 1px solid #e0e0e0;
632
- \t\t
633
- \t\t.card__title {
634
- \t\t\tfont-size: 1.5rem;
635
- \t\t\tfont-weight: 600;
636
- \t\t\tcolor: var(--primary-color);
637
- \t\t}
638
- \t\t
639
- \t\t.card__subtitle {
640
- \t\t\tfont-size: 0.875rem;
641
- \t\t\tcolor: #666666;
642
- \t\t\tmargin-top: 0.25rem;
643
- \t\t}
644
- \t}
645
- \t
646
- \t.card__body {
647
- \t\tpadding: 1.5rem;
648
- \t}
649
- \t
650
- \t.card__footer {
651
- \t\tpadding: 1rem 1.5rem;
652
- \t\tborder-top: 1px solid #e0e0e0;
653
- \t\tdisplay: flex;
654
- \t\tjustify-content: flex-end;
655
- \t\t
656
- \t\t.button {
657
- \t\t\tmargin-right: 0.5rem;
658
- \t\t}
659
- \t}
660
- \t
661
- \t&:hover {
662
- \t\tbox-shadow: 0 4px 16px rgba(0,0,0,0.15);
663
- \t\ttransform: translateY(-2px);
664
- \t}
665
- }
666
-
667
- @media (min-width: 768px) {
668
- \t.container {
669
- \t\tmax-width: 768px;
670
- \t\tmargin: 0 auto;
671
- \t\tpadding: 0 1rem;
672
- \t}
673
- \t
674
- \t.card {
675
- \t\tmax-width: 600px;
676
- \t}
677
- }
678
-
679
- @media (min-width: 1024px) {
680
- \t.container {
681
- \t\tmax-width: 1024px;
682
- \t}
683
- \t
684
- \t.grid {
685
- \t\tdisplay: grid;
686
- \t\tgrid-template-columns: repeat(3, 1fr);
687
- \t\tgap: 1.5rem;
688
- \t}
689
- }
690
-
691
- @media print {
692
- \tbody {
693
- \t\tbackground-color: #ffffff;
694
- \t\tcolor: #000000;
695
- \t}
696
- \t
697
- \t.button {
698
- \t\tdisplay: none;
699
- \t}
700
- \t
701
- \t.card {
702
- \t\tbox-shadow: none;
703
- \t\tborder: 1px solid #000000;
704
- \t}
705
- }
706
-
707
- @keyframes fadeIn {
708
- \t0%: [object Object];
709
- \t100%: [object Object];
710
- }
711
-
712
- @keyframes slideUp {
713
- \t0%: [object Object];
714
- \t100%: [object Object];
715
- }
716
-
717
- .fade-in {
718
- \tanimation: fadeIn 0.3s ease-in-out;
719
- }
720
-
721
- .slide-up {
722
- \tanimation: slideUp 0.5s ease-out;
723
- }
724
-
725
- [data-theme="light"] {
726
- \t--bg-primary: #ffffff;
727
- \t--bg-secondary: #f5f5f5;
728
- \t--text-primary: #1a1a1a;
729
- \t--text-secondary: #666666;
730
- \t--border-color: #e0e0e0;
731
- \t
732
- \t.card {
733
- \t\t--card-bg: var(--bg-primary);
734
- \t\t--card-shadow: 0 2px 8px rgba(0,0,0,0.08);
735
- \t}
736
- \t
737
- \t.button {
738
- \t\t--button-bg: var(--primary-color);
739
- \t}
740
- }
741
-
742
- [data-theme="dark"] {
743
- \t--bg-primary: #1a1a1a;
744
- \t--bg-secondary: #2d2d2d;
745
- \t--text-primary: #ffffff;
746
- \t--text-secondary: #b0b0b0;
747
- \t--border-color: #404040;
748
- \t
749
- \tbody {
750
- \t\tbackground-color: var(--bg-primary);
751
- \t\tcolor: var(--text-primary);
752
- \t}
753
- \t
754
- \t.card {
755
- \t\t--card-bg: var(--bg-secondary);
756
- \t\t--card-shadow: 0 2px 8px rgba(0,0,0,0.3);
757
- \t\t
758
- \t\tborder-color: var(--border-color);
759
- \t}
760
- \t
761
- \t.button {
762
- \t\t--button-bg: #0080ff;
763
- \t\t--button-hover-bg: #0066cc;
764
- \t}
765
- }`);
766
- });
767
-
768
- it("should maintain output file structure", () => {
769
- variable("test", "value");
770
- selector(".test", { color: "red" });
771
-
772
- const output = transpile(instance);
773
-
774
- expect(output).toHaveProperty("files");
775
- expect(Array.isArray(output.files)).toBe(true);
776
- expect(output.files[0]!).toHaveProperty("name");
777
- expect(output.files[0]!).toHaveProperty("content");
778
- expect(typeof output.files[0]!.content).toBe("string");
779
-
780
- const content = output.files[0]!.content;
781
- expect(content).toEqual(`:root {
782
- \t--test: value;
783
- }
784
-
785
- .test {
786
- \tcolor: red;
787
- }`);
788
- });
789
-
790
- it("should pass options to consume function", () => {
791
- const customOptions: StyleframeOptions = {
792
- variables: {
793
- name: ({ name }) => `--custom-${name}`,
794
- },
795
- };
796
-
797
- const customInstance = styleframe(customOptions);
798
- const customRoot = customInstance.root;
799
- const customVariable = createVariableFunction(customRoot, customRoot);
800
- const customUtility = createUtilityFunction(customRoot, customRoot);
801
-
802
- customVariable("color", "#123456");
803
-
804
- const createSpacingUtility = customUtility("space", ({ value }) => ({
805
- marginBottom: value,
806
- }));
807
-
808
- createSpacingUtility({
809
- small: "4px",
810
- large: "16px",
811
- });
812
-
813
- const output = transpile(customInstance);
814
- const content = output.files[0]!.content;
815
-
816
- expect(content).toEqual(`:root {
817
- \t--custom-color: #123456;
818
- }
819
-
820
- ._space\\:small {
821
- \tmargin-bottom: 4px;
822
- }
823
-
824
- ._space\\:large {
825
- \tmargin-bottom: 16px;
826
- }`);
827
- });
828
- });
829
- });