dispersa 0.1.3 → 0.2.0

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.
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { constants } from 'fs';
4
4
  import { mkdir, writeFile, access, readFile } from 'fs/promises';
5
5
  import * as path from 'path';
6
6
  import { JsonPointer } from 'json-ptr';
7
- import { formatHex8, formatHex } from 'culori';
7
+ import { converter, formatHex8, formatHex } from 'culori';
8
8
  import prettier from 'prettier';
9
9
 
10
10
  var __defProp = Object.defineProperty;
@@ -159,10 +159,55 @@ var init_errors = __esm({
159
159
  }
160
160
  });
161
161
 
162
- // src/lib/validation/dtcg-schemas/2025.10/format/group.json
162
+ // src/shared/utils/validation-handler.ts
163
+ var ValidationHandler;
164
+ var init_validation_handler = __esm({
165
+ "src/shared/utils/validation-handler.ts"() {
166
+ ValidationHandler = class {
167
+ mode;
168
+ constructor(options) {
169
+ this.mode = options?.mode ?? "error";
170
+ }
171
+ /**
172
+ * Whether validation checks should run (mode is not 'off')
173
+ */
174
+ shouldValidate() {
175
+ return this.mode !== "off";
176
+ }
177
+ /**
178
+ * Whether the current mode is 'error' (strictest)
179
+ */
180
+ isStrict() {
181
+ return this.mode === "error";
182
+ }
183
+ /**
184
+ * Handle a validation issue: throw in 'error' mode, warn in 'warn' mode, ignore in 'off' mode
185
+ */
186
+ handleIssue(error) {
187
+ if (this.mode === "error") {
188
+ throw error;
189
+ }
190
+ if (this.mode === "warn") {
191
+ console.warn(error.message);
192
+ }
193
+ }
194
+ /**
195
+ * Emit a warning (in 'error' and 'warn' modes, skip in 'off')
196
+ */
197
+ warn(message) {
198
+ if (this.mode === "off") {
199
+ return;
200
+ }
201
+ console.warn(message);
202
+ }
203
+ };
204
+ }
205
+ });
206
+
207
+ // src/validation/dtcg-schemas/2025.10/format/group.json
163
208
  var group_default;
164
209
  var init_group = __esm({
165
- "src/lib/validation/dtcg-schemas/2025.10/format/group.json"() {
210
+ "src/validation/dtcg-schemas/2025.10/format/group.json"() {
166
211
  group_default = {
167
212
  $schema: "http://json-schema.org/draft-07/schema#",
168
213
  $id: "https://www.designtokens.org/schemas/2025.10/format/group.json",
@@ -220,10 +265,10 @@ var init_group = __esm({
220
265
  }
221
266
  });
222
267
 
223
- // src/lib/validation/dtcg-schemas/2025.10/format/groupOrToken.json
268
+ // src/validation/dtcg-schemas/2025.10/format/groupOrToken.json
224
269
  var groupOrToken_default;
225
270
  var init_groupOrToken = __esm({
226
- "src/lib/validation/dtcg-schemas/2025.10/format/groupOrToken.json"() {
271
+ "src/validation/dtcg-schemas/2025.10/format/groupOrToken.json"() {
227
272
  groupOrToken_default = {
228
273
  $schema: "http://json-schema.org/draft-07/schema#",
229
274
  $id: "https://www.designtokens.org/schemas/2025.10/format/groupOrToken.json",
@@ -241,10 +286,10 @@ var init_groupOrToken = __esm({
241
286
  }
242
287
  });
243
288
 
244
- // src/lib/validation/dtcg-schemas/2025.10/format/token.json
289
+ // src/validation/dtcg-schemas/2025.10/format/token.json
245
290
  var token_default;
246
291
  var init_token = __esm({
247
- "src/lib/validation/dtcg-schemas/2025.10/format/token.json"() {
292
+ "src/validation/dtcg-schemas/2025.10/format/token.json"() {
248
293
  token_default = {
249
294
  $schema: "http://json-schema.org/draft-07/schema#",
250
295
  $id: "https://www.designtokens.org/schemas/2025.10/format/token.json",
@@ -672,10 +717,10 @@ var init_token = __esm({
672
717
  }
673
718
  });
674
719
 
675
- // src/lib/validation/dtcg-schemas/2025.10/format/tokenType.json
720
+ // src/validation/dtcg-schemas/2025.10/format/tokenType.json
676
721
  var tokenType_default;
677
722
  var init_tokenType = __esm({
678
- "src/lib/validation/dtcg-schemas/2025.10/format/tokenType.json"() {
723
+ "src/validation/dtcg-schemas/2025.10/format/tokenType.json"() {
679
724
  tokenType_default = {
680
725
  $schema: "http://json-schema.org/draft-07/schema#",
681
726
  $id: "https://www.designtokens.org/schemas/2025.10/format/tokenType.json",
@@ -701,10 +746,10 @@ var init_tokenType = __esm({
701
746
  }
702
747
  });
703
748
 
704
- // src/lib/validation/dtcg-schemas/2025.10/format/values/border.json
749
+ // src/validation/dtcg-schemas/2025.10/format/values/border.json
705
750
  var border_default;
706
751
  var init_border = __esm({
707
- "src/lib/validation/dtcg-schemas/2025.10/format/values/border.json"() {
752
+ "src/validation/dtcg-schemas/2025.10/format/values/border.json"() {
708
753
  border_default = {
709
754
  $schema: "http://json-schema.org/draft-07/schema#",
710
755
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/border.json",
@@ -752,10 +797,10 @@ var init_border = __esm({
752
797
  }
753
798
  });
754
799
 
755
- // src/lib/validation/dtcg-schemas/2025.10/format/values/color.json
800
+ // src/validation/dtcg-schemas/2025.10/format/values/color.json
756
801
  var color_default;
757
802
  var init_color = __esm({
758
- "src/lib/validation/dtcg-schemas/2025.10/format/values/color.json"() {
803
+ "src/validation/dtcg-schemas/2025.10/format/values/color.json"() {
759
804
  color_default = {
760
805
  $schema: "http://json-schema.org/draft-07/schema#",
761
806
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/color.json",
@@ -1273,10 +1318,10 @@ var init_color = __esm({
1273
1318
  }
1274
1319
  });
1275
1320
 
1276
- // src/lib/validation/dtcg-schemas/2025.10/format/values/cubicBezier.json
1321
+ // src/validation/dtcg-schemas/2025.10/format/values/cubicBezier.json
1277
1322
  var cubicBezier_default;
1278
1323
  var init_cubicBezier = __esm({
1279
- "src/lib/validation/dtcg-schemas/2025.10/format/values/cubicBezier.json"() {
1324
+ "src/validation/dtcg-schemas/2025.10/format/values/cubicBezier.json"() {
1280
1325
  cubicBezier_default = {
1281
1326
  $schema: "http://json-schema.org/draft-07/schema#",
1282
1327
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/cubicBezier.json",
@@ -1336,10 +1381,10 @@ var init_cubicBezier = __esm({
1336
1381
  }
1337
1382
  });
1338
1383
 
1339
- // src/lib/validation/dtcg-schemas/2025.10/format/values/dimension.json
1384
+ // src/validation/dtcg-schemas/2025.10/format/values/dimension.json
1340
1385
  var dimension_default;
1341
1386
  var init_dimension = __esm({
1342
- "src/lib/validation/dtcg-schemas/2025.10/format/values/dimension.json"() {
1387
+ "src/validation/dtcg-schemas/2025.10/format/values/dimension.json"() {
1343
1388
  dimension_default = {
1344
1389
  $schema: "http://json-schema.org/draft-07/schema#",
1345
1390
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/dimension.json",
@@ -1377,10 +1422,10 @@ var init_dimension = __esm({
1377
1422
  }
1378
1423
  });
1379
1424
 
1380
- // src/lib/validation/dtcg-schemas/2025.10/format/values/duration.json
1425
+ // src/validation/dtcg-schemas/2025.10/format/values/duration.json
1381
1426
  var duration_default;
1382
1427
  var init_duration = __esm({
1383
- "src/lib/validation/dtcg-schemas/2025.10/format/values/duration.json"() {
1428
+ "src/validation/dtcg-schemas/2025.10/format/values/duration.json"() {
1384
1429
  duration_default = {
1385
1430
  $schema: "http://json-schema.org/draft-07/schema#",
1386
1431
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/duration.json",
@@ -1418,10 +1463,10 @@ var init_duration = __esm({
1418
1463
  }
1419
1464
  });
1420
1465
 
1421
- // src/lib/validation/dtcg-schemas/2025.10/format/values/fontFamily.json
1466
+ // src/validation/dtcg-schemas/2025.10/format/values/fontFamily.json
1422
1467
  var fontFamily_default;
1423
1468
  var init_fontFamily = __esm({
1424
- "src/lib/validation/dtcg-schemas/2025.10/format/values/fontFamily.json"() {
1469
+ "src/validation/dtcg-schemas/2025.10/format/values/fontFamily.json"() {
1425
1470
  fontFamily_default = {
1426
1471
  $schema: "http://json-schema.org/draft-07/schema#",
1427
1472
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/fontFamily.json",
@@ -1458,10 +1503,10 @@ var init_fontFamily = __esm({
1458
1503
  }
1459
1504
  });
1460
1505
 
1461
- // src/lib/validation/dtcg-schemas/2025.10/format/values/fontWeight.json
1506
+ // src/validation/dtcg-schemas/2025.10/format/values/fontWeight.json
1462
1507
  var fontWeight_default;
1463
1508
  var init_fontWeight = __esm({
1464
- "src/lib/validation/dtcg-schemas/2025.10/format/values/fontWeight.json"() {
1509
+ "src/validation/dtcg-schemas/2025.10/format/values/fontWeight.json"() {
1465
1510
  fontWeight_default = {
1466
1511
  $schema: "http://json-schema.org/draft-07/schema#",
1467
1512
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/fontWeight.json",
@@ -1503,10 +1548,10 @@ var init_fontWeight = __esm({
1503
1548
  }
1504
1549
  });
1505
1550
 
1506
- // src/lib/validation/dtcg-schemas/2025.10/format/values/gradient.json
1551
+ // src/validation/dtcg-schemas/2025.10/format/values/gradient.json
1507
1552
  var gradient_default;
1508
1553
  var init_gradient = __esm({
1509
- "src/lib/validation/dtcg-schemas/2025.10/format/values/gradient.json"() {
1554
+ "src/validation/dtcg-schemas/2025.10/format/values/gradient.json"() {
1510
1555
  gradient_default = {
1511
1556
  $schema: "http://json-schema.org/draft-07/schema#",
1512
1557
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/gradient.json",
@@ -1562,10 +1607,10 @@ var init_gradient = __esm({
1562
1607
  }
1563
1608
  });
1564
1609
 
1565
- // src/lib/validation/dtcg-schemas/2025.10/format/values/number.json
1610
+ // src/validation/dtcg-schemas/2025.10/format/values/number.json
1566
1611
  var number_default;
1567
1612
  var init_number = __esm({
1568
- "src/lib/validation/dtcg-schemas/2025.10/format/values/number.json"() {
1613
+ "src/validation/dtcg-schemas/2025.10/format/values/number.json"() {
1569
1614
  number_default = {
1570
1615
  $schema: "http://json-schema.org/draft-07/schema#",
1571
1616
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/number.json",
@@ -1576,10 +1621,10 @@ var init_number = __esm({
1576
1621
  }
1577
1622
  });
1578
1623
 
1579
- // src/lib/validation/dtcg-schemas/2025.10/format/values/shadow.json
1624
+ // src/validation/dtcg-schemas/2025.10/format/values/shadow.json
1580
1625
  var shadow_default;
1581
1626
  var init_shadow = __esm({
1582
- "src/lib/validation/dtcg-schemas/2025.10/format/values/shadow.json"() {
1627
+ "src/validation/dtcg-schemas/2025.10/format/values/shadow.json"() {
1583
1628
  shadow_default = {
1584
1629
  $schema: "http://json-schema.org/draft-07/schema#",
1585
1630
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/shadow.json",
@@ -1685,10 +1730,10 @@ var init_shadow = __esm({
1685
1730
  }
1686
1731
  });
1687
1732
 
1688
- // src/lib/validation/dtcg-schemas/2025.10/format/values/strokeStyle.json
1733
+ // src/validation/dtcg-schemas/2025.10/format/values/strokeStyle.json
1689
1734
  var strokeStyle_default;
1690
1735
  var init_strokeStyle = __esm({
1691
- "src/lib/validation/dtcg-schemas/2025.10/format/values/strokeStyle.json"() {
1736
+ "src/validation/dtcg-schemas/2025.10/format/values/strokeStyle.json"() {
1692
1737
  strokeStyle_default = {
1693
1738
  $schema: "http://json-schema.org/draft-07/schema#",
1694
1739
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/strokeStyle.json",
@@ -1746,10 +1791,10 @@ var init_strokeStyle = __esm({
1746
1791
  }
1747
1792
  });
1748
1793
 
1749
- // src/lib/validation/dtcg-schemas/2025.10/format/values/transition.json
1794
+ // src/validation/dtcg-schemas/2025.10/format/values/transition.json
1750
1795
  var transition_default;
1751
1796
  var init_transition = __esm({
1752
- "src/lib/validation/dtcg-schemas/2025.10/format/values/transition.json"() {
1797
+ "src/validation/dtcg-schemas/2025.10/format/values/transition.json"() {
1753
1798
  transition_default = {
1754
1799
  $schema: "http://json-schema.org/draft-07/schema#",
1755
1800
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/transition.json",
@@ -1797,10 +1842,10 @@ var init_transition = __esm({
1797
1842
  }
1798
1843
  });
1799
1844
 
1800
- // src/lib/validation/dtcg-schemas/2025.10/format/values/typography.json
1845
+ // src/validation/dtcg-schemas/2025.10/format/values/typography.json
1801
1846
  var typography_default;
1802
1847
  var init_typography = __esm({
1803
- "src/lib/validation/dtcg-schemas/2025.10/format/values/typography.json"() {
1848
+ "src/validation/dtcg-schemas/2025.10/format/values/typography.json"() {
1804
1849
  typography_default = {
1805
1850
  $schema: "http://json-schema.org/draft-07/schema#",
1806
1851
  $id: "https://www.designtokens.org/schemas/2025.10/format/values/typography.json",
@@ -1870,10 +1915,10 @@ var init_typography = __esm({
1870
1915
  }
1871
1916
  });
1872
1917
 
1873
- // src/lib/validation/dtcg-schemas/2025.10/format.json
1918
+ // src/validation/dtcg-schemas/2025.10/format.json
1874
1919
  var format_default;
1875
1920
  var init_format = __esm({
1876
- "src/lib/validation/dtcg-schemas/2025.10/format.json"() {
1921
+ "src/validation/dtcg-schemas/2025.10/format.json"() {
1877
1922
  format_default = {
1878
1923
  $schema: "http://json-schema.org/draft-07/schema#",
1879
1924
  $id: "https://www.designtokens.org/schemas/2025.10/format.json",
@@ -1982,10 +2027,10 @@ var init_format = __esm({
1982
2027
  }
1983
2028
  });
1984
2029
 
1985
- // src/lib/validation/dtcg-schemas/2025.10/resolver/modifier.json
2030
+ // src/validation/dtcg-schemas/2025.10/resolver/modifier.json
1986
2031
  var modifier_default;
1987
2032
  var init_modifier = __esm({
1988
- "src/lib/validation/dtcg-schemas/2025.10/resolver/modifier.json"() {
2033
+ "src/validation/dtcg-schemas/2025.10/resolver/modifier.json"() {
1989
2034
  modifier_default = {
1990
2035
  $schema: "http://json-schema.org/draft-07/schema#",
1991
2036
  $id: "https://www.designtokens.org/schemas/2025.10/resolver/modifier.json",
@@ -2073,10 +2118,10 @@ var init_modifier = __esm({
2073
2118
  }
2074
2119
  });
2075
2120
 
2076
- // src/lib/validation/dtcg-schemas/2025.10/resolver/resolutionOrder.json
2121
+ // src/validation/dtcg-schemas/2025.10/resolver/resolutionOrder.json
2077
2122
  var resolutionOrder_default;
2078
2123
  var init_resolutionOrder = __esm({
2079
- "src/lib/validation/dtcg-schemas/2025.10/resolver/resolutionOrder.json"() {
2124
+ "src/validation/dtcg-schemas/2025.10/resolver/resolutionOrder.json"() {
2080
2125
  resolutionOrder_default = {
2081
2126
  $schema: "http://json-schema.org/draft-07/schema#",
2082
2127
  $id: "https://www.designtokens.org/schemas/2025.10/resolver/resolutionOrder.json",
@@ -2196,10 +2241,10 @@ var init_resolutionOrder = __esm({
2196
2241
  }
2197
2242
  });
2198
2243
 
2199
- // src/lib/validation/dtcg-schemas/2025.10/resolver/set.json
2244
+ // src/validation/dtcg-schemas/2025.10/resolver/set.json
2200
2245
  var set_default;
2201
2246
  var init_set = __esm({
2202
- "src/lib/validation/dtcg-schemas/2025.10/resolver/set.json"() {
2247
+ "src/validation/dtcg-schemas/2025.10/resolver/set.json"() {
2203
2248
  set_default = {
2204
2249
  $schema: "http://json-schema.org/draft-07/schema#",
2205
2250
  $id: "https://www.designtokens.org/schemas/2025.10/resolver/set.json",
@@ -2273,10 +2318,10 @@ var init_set = __esm({
2273
2318
  }
2274
2319
  });
2275
2320
 
2276
- // src/lib/validation/dtcg-schemas/2025.10/resolver.json
2321
+ // src/validation/dtcg-schemas/2025.10/resolver.json
2277
2322
  var resolver_default;
2278
2323
  var init_resolver = __esm({
2279
- "src/lib/validation/dtcg-schemas/2025.10/resolver.json"() {
2324
+ "src/validation/dtcg-schemas/2025.10/resolver.json"() {
2280
2325
  resolver_default = {
2281
2326
  $schema: "http://json-schema.org/draft-07/schema#",
2282
2327
  $id: "https://www.designtokens.org/schemas/2025.10/resolver.json",
@@ -2341,10 +2386,10 @@ var init_resolver = __esm({
2341
2386
  }
2342
2387
  });
2343
2388
 
2344
- // src/lib/validation/schemas.ts
2389
+ // src/validation/schemas.ts
2345
2390
  var formatSchema, tokenSchema, tokenTypeSchema, groupSchema, groupOrTokenSchema, colorValueSchema, dimensionValueSchema, fontFamilyValueSchema, fontWeightValueSchema, durationValueSchema, cubicBezierValueSchema, numberValueSchema, strokeStyleValueSchema, borderValueSchema, transitionValueSchema, shadowValueSchema, gradientValueSchema, typographyValueSchema, resolverSchema, resolverSetSchema, resolverModifierSchema, resolverResolutionOrderSchema, dtcgSchemaRegistry;
2346
2391
  var init_schemas = __esm({
2347
- "src/lib/validation/schemas.ts"() {
2392
+ "src/validation/schemas.ts"() {
2348
2393
  init_group();
2349
2394
  init_groupOrToken();
2350
2395
  init_token();
@@ -2416,10 +2461,10 @@ var init_schemas = __esm({
2416
2461
  }
2417
2462
  });
2418
2463
 
2419
- // src/lib/validation/config-schemas.ts
2464
+ // src/validation/config-schemas.ts
2420
2465
  var resolverSchemaRef, basePluginProperties, commonRendererOptionsProperties, transformPluginSchema, rendererPluginSchema, filterPluginSchema, preprocessorPluginSchema, outputConfigSchema, dispersaOptionsSchema, buildConfigSchema;
2421
2466
  var init_config_schemas = __esm({
2422
- "src/lib/validation/config-schemas.ts"() {
2467
+ "src/validation/config-schemas.ts"() {
2423
2468
  init_schemas();
2424
2469
  resolverSchemaRef = resolverSchema;
2425
2470
  basePluginProperties = {
@@ -2473,6 +2518,25 @@ var init_config_schemas = __esm({
2473
2518
  additionalProperties: true
2474
2519
  // Allow custom properties for extended renderers
2475
2520
  });
2521
+ ({
2522
+ $schema: "http://json-schema.org/draft-07/schema#",
2523
+ type: "object",
2524
+ properties: {
2525
+ preset: { type: "string", enum: ["bundle", "standalone"] },
2526
+ includeImport: {
2527
+ type: "boolean",
2528
+ description: 'Prepend @import "tailwindcss" to the output'
2529
+ },
2530
+ namespace: {
2531
+ type: "string",
2532
+ description: "Optional Tailwind namespace prefix for @theme"
2533
+ },
2534
+ selector: { type: "string" },
2535
+ mediaQuery: { type: "string" },
2536
+ ...commonRendererOptionsProperties
2537
+ },
2538
+ additionalProperties: true
2539
+ });
2476
2540
  transformPluginSchema = {
2477
2541
  $schema: "http://json-schema.org/draft-07/schema#",
2478
2542
  type: "object",
@@ -2678,7 +2742,7 @@ var init_config_schemas = __esm({
2678
2742
  });
2679
2743
  var SchemaValidator;
2680
2744
  var init_validator = __esm({
2681
- "src/lib/validation/validator.ts"() {
2745
+ "src/validation/validator.ts"() {
2682
2746
  init_errors();
2683
2747
  init_token_utils();
2684
2748
  init_config_schemas();
@@ -2930,63 +2994,18 @@ var init_validator = __esm({
2930
2994
  }
2931
2995
  });
2932
2996
 
2933
- // src/lib/validation/index.ts
2997
+ // src/validation/index.ts
2934
2998
  var init_validation = __esm({
2935
- "src/lib/validation/index.ts"() {
2999
+ "src/validation/index.ts"() {
2936
3000
  init_validator();
2937
3001
  }
2938
3002
  });
2939
-
2940
- // src/shared/utils/validation-handler.ts
2941
- var ValidationHandler;
2942
- var init_validation_handler = __esm({
2943
- "src/shared/utils/validation-handler.ts"() {
2944
- ValidationHandler = class {
2945
- mode;
2946
- constructor(options) {
2947
- this.mode = options?.mode ?? "error";
2948
- }
2949
- /**
2950
- * Whether validation checks should run (mode is not 'off')
2951
- */
2952
- shouldValidate() {
2953
- return this.mode !== "off";
2954
- }
2955
- /**
2956
- * Whether the current mode is 'error' (strictest)
2957
- */
2958
- isStrict() {
2959
- return this.mode === "error";
2960
- }
2961
- /**
2962
- * Handle a validation issue: throw in 'error' mode, warn in 'warn' mode, ignore in 'off' mode
2963
- */
2964
- handleIssue(error) {
2965
- if (this.mode === "error") {
2966
- throw error;
2967
- }
2968
- if (this.mode === "warn") {
2969
- console.warn(error.message);
2970
- }
2971
- }
2972
- /**
2973
- * Emit a warning (in 'error' and 'warn' modes, skip in 'off')
2974
- */
2975
- warn(message) {
2976
- if (this.mode === "off") {
2977
- return;
2978
- }
2979
- console.warn(message);
2980
- }
2981
- };
2982
- }
2983
- });
2984
3003
  var ResolverParser;
2985
3004
  var init_resolver_parser = __esm({
2986
3005
  "src/adapters/filesystem/resolver-parser.ts"() {
2987
- init_validation();
2988
3006
  init_errors();
2989
3007
  init_validation_handler();
3008
+ init_validation();
2990
3009
  ResolverParser = class {
2991
3010
  validator;
2992
3011
  options;
@@ -3568,7 +3587,7 @@ var init_json = __esm({
3568
3587
  }
3569
3588
  });
3570
3589
 
3571
- // src/lib/codegen/type-generator.ts
3590
+ // src/codegen/type-generator.ts
3572
3591
  var TypeGenerator = class {
3573
3592
  /**
3574
3593
  * Generates complete TypeScript type definitions from resolved tokens
@@ -3700,8 +3719,8 @@ var TypeGenerator = class {
3700
3719
  /**
3701
3720
  * Add structure properties to lines
3702
3721
  */
3703
- addStructureProperties(lines, structure, indent) {
3704
- const indentStr = " ".repeat(indent);
3722
+ addStructureProperties(lines, structure, indent2) {
3723
+ const indentStr = " ".repeat(indent2);
3705
3724
  for (const [key, value] of Object.entries(structure)) {
3706
3725
  if (this.isToken(value)) {
3707
3726
  const token = value;
@@ -3712,7 +3731,7 @@ var TypeGenerator = class {
3712
3731
  lines.push(`${indentStr}${this.quoteKey(key)}: ${valueType}`);
3713
3732
  } else {
3714
3733
  lines.push(`${indentStr}${this.quoteKey(key)}: {`);
3715
- this.addStructureProperties(lines, value, indent + 1);
3734
+ this.addStructureProperties(lines, value, indent2 + 1);
3716
3735
  lines.push(`${indentStr}}`);
3717
3736
  }
3718
3737
  }
@@ -4057,7 +4076,7 @@ async function writeOutputFile(fileName, content, encoding = "utf-8") {
4057
4076
  }
4058
4077
  }
4059
4078
 
4060
- // src/lib/processing/token-modifier.ts
4079
+ // src/processing/token-modifier.ts
4061
4080
  function applyTransforms(tokens, transformList) {
4062
4081
  const result = {};
4063
4082
  for (const [name, token] of Object.entries(tokens)) {
@@ -4189,7 +4208,7 @@ init_validation_handler();
4189
4208
  // src/shared/constants.ts
4190
4209
  var DEFAULT_MAX_ALIAS_DEPTH = 10;
4191
4210
 
4192
- // src/lib/resolution/alias-resolver.ts
4211
+ // src/resolution/alias-resolver.ts
4193
4212
  init_errors();
4194
4213
 
4195
4214
  // src/shared/utils/string-similarity.ts
@@ -4240,7 +4259,7 @@ function findSimilar(target, candidates, maxDistance, maxResults = 3) {
4240
4259
  return scored.slice(0, maxResults).map((entry) => entry.value);
4241
4260
  }
4242
4261
 
4243
- // src/lib/resolution/alias-resolver.ts
4262
+ // src/resolution/alias-resolver.ts
4244
4263
  init_token_utils();
4245
4264
  init_validation_handler();
4246
4265
  var AliasResolver = class _AliasResolver {
@@ -4498,7 +4517,7 @@ var AliasResolver = class _AliasResolver {
4498
4517
  }
4499
4518
  };
4500
4519
 
4501
- // src/lib/resolution/reference-resolver.ts
4520
+ // src/resolution/reference-resolver.ts
4502
4521
  init_errors();
4503
4522
  init_validation_handler();
4504
4523
  var ReferenceResolver = class _ReferenceResolver {
@@ -4805,7 +4824,7 @@ var ReferenceResolver = class _ReferenceResolver {
4805
4824
  }
4806
4825
  };
4807
4826
 
4808
- // src/lib/resolution/resolution-engine.ts
4827
+ // src/resolution/resolution-engine.ts
4809
4828
  init_errors();
4810
4829
 
4811
4830
  // src/shared/utils/case-insensitive-map.ts
@@ -4907,10 +4926,10 @@ var CaseInsensitiveMap = class {
4907
4926
  }
4908
4927
  };
4909
4928
 
4910
- // src/lib/resolution/resolution-engine.ts
4929
+ // src/resolution/resolution-engine.ts
4911
4930
  init_validation_handler();
4912
4931
 
4913
- // src/lib/resolution/modifier-input-processor.ts
4932
+ // src/resolution/modifier-input-processor.ts
4914
4933
  init_errors();
4915
4934
  var ModifierInputProcessor = class {
4916
4935
  modifiers;
@@ -5093,7 +5112,7 @@ var ModifierInputProcessor = class {
5093
5112
  }
5094
5113
  };
5095
5114
 
5096
- // src/lib/resolution/resolution-engine.ts
5115
+ // src/resolution/resolution-engine.ts
5097
5116
  var JSON_POINTER_SETS_PREFIX = "#/sets/";
5098
5117
  var JSON_POINTER_MODIFIERS_PREFIX = "#/modifiers/";
5099
5118
  var ResolutionEngine = class {
@@ -5378,7 +5397,6 @@ var ResolutionEngine = class {
5378
5397
  return typeof obj === "object" && obj !== null && "contexts" in obj && typeof obj.contexts === "object";
5379
5398
  }
5380
5399
  };
5381
- init_validator();
5382
5400
  init_errors();
5383
5401
 
5384
5402
  // src/shared/utils/path-utils.ts
@@ -5389,11 +5407,12 @@ function formatTokenPath(parentPath, name) {
5389
5407
  return parentPath.length > 0 ? `${parentPath.join(".")}.${name}` : name;
5390
5408
  }
5391
5409
 
5392
- // src/lib/tokens/token-parser.ts
5410
+ // src/tokens/token-parser.ts
5393
5411
  init_token_utils();
5394
5412
  init_validation_handler();
5413
+ init_validator();
5395
5414
 
5396
- // src/lib/tokens/group-extension-resolver.ts
5415
+ // src/tokens/group-extension-resolver.ts
5397
5416
  init_errors();
5398
5417
  init_token_utils();
5399
5418
  var GroupExtensionResolver = class {
@@ -5555,7 +5574,7 @@ var GroupExtensionResolver = class {
5555
5574
  }
5556
5575
  };
5557
5576
 
5558
- // src/lib/tokens/token-parser.ts
5577
+ // src/tokens/token-parser.ts
5559
5578
  var INVALID_NAME_CHARS_REGEX = /[{}.]/;
5560
5579
  var TokenParser = class {
5561
5580
  validator;
@@ -6068,9 +6087,9 @@ var TokenPipeline = class {
6068
6087
  };
6069
6088
 
6070
6089
  // src/dispersa.ts
6071
- init_validator();
6072
6090
  init_errors();
6073
6091
  init_token_utils();
6092
+ init_validator();
6074
6093
  var Dispersa = class {
6075
6094
  validator;
6076
6095
  pipeline;
@@ -6352,7 +6371,7 @@ var Dispersa = class {
6352
6371
  }
6353
6372
  };
6354
6373
 
6355
- // src/lib/tokens/types.ts
6374
+ // src/tokens/types.ts
6356
6375
  function isColorToken(token) {
6357
6376
  return token.$type === "color";
6358
6377
  }
@@ -6434,7 +6453,7 @@ function colorObjectToHex(color) {
6434
6453
  return formatHex(culoriColor);
6435
6454
  }
6436
6455
 
6437
- // src/lib/processing/processors/transforms/built-in/dimension-converter.ts
6456
+ // src/processing/processors/transforms/built-in/dimension-converter.ts
6438
6457
  function isDimensionObject(value) {
6439
6458
  return typeof value === "object" && value !== null && "value" in value && "unit" in value;
6440
6459
  }
@@ -6442,127 +6461,868 @@ function dimensionObjectToString(dimension) {
6442
6461
  return `${dimension.value}${dimension.unit}`;
6443
6462
  }
6444
6463
 
6445
- // src/renderers/css.ts
6464
+ // src/renderers/android.ts
6446
6465
  init_errors();
6447
6466
  init_token_utils();
6448
-
6449
- // src/renderers/bundlers/css.ts
6450
- init_errors();
6451
6467
  init_utils();
6452
- var getSourceSet = (token) => {
6453
- if (typeof token !== "object" || token === null) {
6454
- return void 0;
6455
- }
6456
- const maybe = token;
6457
- return typeof maybe._sourceSet === "string" ? maybe._sourceSet : void 0;
6468
+ var toSRGB = converter("rgb");
6469
+ var toP3 = converter("p3");
6470
+ var KOTLIN_KEYWORDS = /* @__PURE__ */ new Set([
6471
+ "val",
6472
+ "var",
6473
+ "fun",
6474
+ "class",
6475
+ "object",
6476
+ "when",
6477
+ "is",
6478
+ "in",
6479
+ "return",
6480
+ "break",
6481
+ "continue",
6482
+ "do",
6483
+ "while",
6484
+ "for",
6485
+ "if",
6486
+ "else",
6487
+ "try",
6488
+ "catch",
6489
+ "throw",
6490
+ "as",
6491
+ "this",
6492
+ "super",
6493
+ "null",
6494
+ "true",
6495
+ "false"
6496
+ ]);
6497
+ var KOTLIN_TYPE_GROUP_MAP = {
6498
+ color: "Colors",
6499
+ dimension: "Spacing",
6500
+ fontFamily: "Fonts",
6501
+ fontWeight: "FontWeights",
6502
+ duration: "Durations",
6503
+ shadow: "Shadows",
6504
+ typography: "Typography",
6505
+ number: "Numbers",
6506
+ cubicBezier: "Animations",
6507
+ border: "Borders"
6458
6508
  };
6459
- var getSourceModifier = (token) => {
6460
- if (typeof token !== "object" || token === null) {
6461
- return void 0;
6509
+ function resolveColorFormat(format) {
6510
+ if (format === "argb_floats" || format === "argb_float") {
6511
+ return "argb_float";
6462
6512
  }
6463
- const maybe = token;
6464
- return typeof maybe._sourceModifier === "string" ? maybe._sourceModifier : void 0;
6465
- };
6466
- async function bundleAsCss(bundleData, resolver, options, formatTokens) {
6467
- const baseItem = bundleData.find((item) => item.isBase);
6468
- if (!baseItem) {
6469
- throw new BasePermutationError("Base permutation not found in bundle data");
6513
+ return "argb_hex";
6514
+ }
6515
+ function indent(width, level) {
6516
+ return " ".repeat(width * level);
6517
+ }
6518
+ function escapeKotlinString(str) {
6519
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\$/g, "\\$");
6520
+ }
6521
+ function escapeKDoc(str) {
6522
+ return str.replace(/\*\//g, "* /").replace(/\r?\n/g, " ").trim();
6523
+ }
6524
+ function formatKotlinNumber(value) {
6525
+ return Number.isInteger(value) ? `${value}.0` : String(value);
6526
+ }
6527
+ function roundComponent(value) {
6528
+ return Math.round(value * 1e3) / 1e3;
6529
+ }
6530
+ function toResourceName(family) {
6531
+ return family.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
6532
+ }
6533
+ function toPascalCase(name) {
6534
+ const pascal = name.replace(/[-._]+(.)/g, (_, c) => c.toUpperCase()).replace(/[-._]+$/g, "").replace(/^[-._]+/g, "");
6535
+ const result = pascal.charAt(0).toUpperCase() + pascal.slice(1);
6536
+ if (/^\d/.test(result)) {
6537
+ return `_${result}`;
6470
6538
  }
6471
- if (!formatTokens) {
6472
- throw new ConfigurationError("CSS formatter was not provided");
6539
+ return KOTLIN_KEYWORDS.has(result.charAt(0).toLowerCase() + result.slice(1)) ? `\`${result}\`` : result;
6540
+ }
6541
+ function toKotlinIdentifier(name) {
6542
+ const camel = name.replace(/[-._]+(.)/g, (_, c) => c.toUpperCase()).replace(/[-._]+$/g, "").replace(/^[-._]+/g, "");
6543
+ const identifier = camel.charAt(0).toLowerCase() + camel.slice(1);
6544
+ if (/^\d/.test(identifier)) {
6545
+ return `_${identifier}`;
6473
6546
  }
6474
- const orderedBundleData = orderBundleData(bundleData, resolver, baseItem);
6475
- const cssBlocks = [];
6476
- for (const item of orderedBundleData) {
6477
- if (item.isBase) {
6478
- const blocks = await formatBasePermutation(item, resolver, options, formatTokens);
6479
- cssBlocks.push(...blocks);
6480
- continue;
6547
+ return KOTLIN_KEYWORDS.has(identifier) ? `\`${identifier}\`` : identifier;
6548
+ }
6549
+ var AndroidRenderer = class {
6550
+ async format(context, options) {
6551
+ if (!options?.packageName) {
6552
+ throw new ConfigurationError(
6553
+ `Output "${context.output.name}": packageName is required for Android output`
6554
+ );
6481
6555
  }
6482
- const block = await formatModifierPermutation(item, baseItem, options, formatTokens);
6483
- if (block) {
6484
- cssBlocks.push(block);
6556
+ const opts = {
6557
+ preset: options?.preset ?? "standalone",
6558
+ packageName: options.packageName,
6559
+ objectName: options?.objectName ?? "DesignTokens",
6560
+ colorFormat: resolveColorFormat(options?.colorFormat),
6561
+ colorSpace: options?.colorSpace ?? "sRGB",
6562
+ structure: options?.structure ?? "nested",
6563
+ visibility: options?.visibility,
6564
+ indent: options?.indent ?? 4
6565
+ };
6566
+ if (opts.preset === "bundle") {
6567
+ return await this.formatBundle(context, opts);
6485
6568
  }
6569
+ return await this.formatStandalone(context, opts);
6486
6570
  }
6487
- return cssBlocks.join("\n\n");
6488
- }
6489
- async function formatBasePermutation({ tokens, modifierInputs }, resolver, options, formatTokens) {
6490
- const firstModifierName = resolver.modifiers ? Object.keys(resolver.modifiers)[0] : "";
6491
- const modifier = firstModifierName ?? "";
6492
- const context = modifierInputs[modifier] ?? "";
6493
- const selector = resolveSelector(options?.selector, modifier, context, true, modifierInputs);
6494
- const mediaQuery = resolveMediaQuery(options?.mediaQuery, modifier, context, true, modifierInputs);
6495
- const referenceTokens = stripInternalMetadata(tokens);
6496
- const defaultBlocks = buildDefaultLayerBlocks(tokens, modifierInputs, resolver);
6497
- const cssBlocks = [];
6498
- for (const block of defaultBlocks) {
6499
- const cleanTokens = stripInternalMetadata(block.tokens);
6500
- const css2 = await formatTokens(cleanTokens, {
6501
- selector,
6502
- mediaQuery,
6503
- minify: options?.minify,
6504
- referenceTokens
6505
- });
6506
- const header = block.description ? `/* ${block.key} */
6507
- /* ${block.description} */` : `/* ${block.key} */`;
6508
- cssBlocks.push(`${header}
6509
- ${css2}`);
6571
+ // -----------------------------------------------------------------------
6572
+ // Token tree (nested mode)
6573
+ // -----------------------------------------------------------------------
6574
+ buildTokenTree(tokens) {
6575
+ const root = { children: /* @__PURE__ */ new Map() };
6576
+ for (const [, token] of getSortedTokenEntries(tokens)) {
6577
+ let current = root;
6578
+ const segments = token.path;
6579
+ for (let i = 0; i < segments.length - 1; i++) {
6580
+ const seg = segments[i];
6581
+ if (!current.children.has(seg)) {
6582
+ current.children.set(seg, { children: /* @__PURE__ */ new Map() });
6583
+ }
6584
+ current = current.children.get(seg);
6585
+ }
6586
+ const leafName = segments[segments.length - 1] ?? token.name;
6587
+ const leaf = current.children.get(leafName) ?? { children: /* @__PURE__ */ new Map() };
6588
+ leaf.token = token;
6589
+ current.children.set(leafName, leaf);
6590
+ }
6591
+ return root;
6510
6592
  }
6511
- return cssBlocks;
6512
- }
6513
- async function formatModifierPermutation({ tokens, modifierInputs }, baseItem, options, formatTokens) {
6514
- const differenceCount = countModifierDifferences(modifierInputs, baseItem.modifierInputs);
6515
- if (differenceCount > 1) {
6516
- return void 0;
6593
+ // -----------------------------------------------------------------------
6594
+ // Flat structure grouping
6595
+ // -----------------------------------------------------------------------
6596
+ groupTokensByType(tokens) {
6597
+ const groupMap = /* @__PURE__ */ new Map();
6598
+ for (const [, token] of getSortedTokenEntries(tokens)) {
6599
+ const groupName = KOTLIN_TYPE_GROUP_MAP[token.$type ?? ""] ?? "Other";
6600
+ const existing = groupMap.get(groupName) ?? [];
6601
+ existing.push(token);
6602
+ groupMap.set(groupName, existing);
6603
+ }
6604
+ return Array.from(groupMap.entries()).map(([name, groupTokens]) => ({
6605
+ name,
6606
+ tokens: groupTokens
6607
+ }));
6517
6608
  }
6518
- const expectedSource = getExpectedSource(modifierInputs, baseItem.modifierInputs);
6519
- let tokensToInclude = filterTokensBySource(tokens, expectedSource);
6520
- const hasSourceMetadata = Object.values(tokens).some(
6521
- (token) => token != null && getSourceModifier(token) !== void 0
6522
- );
6523
- if (Object.keys(tokensToInclude).length === 0 && !hasSourceMetadata) {
6524
- tokensToInclude = tokens;
6609
+ /**
6610
+ * Builds a flattened camelCase name from a token's path, stripping the
6611
+ * type prefix segment (which is already represented by the group object).
6612
+ */
6613
+ buildFlatKotlinName(token) {
6614
+ const path7 = token.path;
6615
+ const withoutTypePrefix = path7.length > 1 ? path7.slice(1) : path7;
6616
+ const joined = withoutTypePrefix.join("_");
6617
+ return toKotlinIdentifier(joined);
6618
+ }
6619
+ // -----------------------------------------------------------------------
6620
+ // Rendering
6621
+ // -----------------------------------------------------------------------
6622
+ formatTokens(tokens, options) {
6623
+ if (options.structure === "flat") {
6624
+ return this.formatAsFlat(tokens, options);
6625
+ }
6626
+ return this.formatAsNested(tokens, options);
6627
+ }
6628
+ formatAsNested(tokens, options) {
6629
+ const tree = this.buildTokenTree(tokens);
6630
+ const tokenTypes = /* @__PURE__ */ new Set();
6631
+ this.collectTokenTypes(tree, tokenTypes);
6632
+ return this.buildFile(tokenTypes, options, (lines, vis) => {
6633
+ lines.push(`@Suppress("unused")`);
6634
+ lines.push(`${vis}object ${options.objectName} {`);
6635
+ this.renderTreeChildren(lines, tree, 1, options);
6636
+ lines.push("}");
6637
+ });
6525
6638
  }
6526
- if (Object.keys(tokensToInclude).length === 0) {
6527
- return void 0;
6639
+ formatAsFlat(tokens, options) {
6640
+ const groups = this.groupTokensByType(tokens);
6641
+ const tokenTypes = this.collectTokenTypesFromEntries(tokens);
6642
+ return this.buildFile(tokenTypes, options, (lines, vis) => {
6643
+ lines.push(`@Suppress("unused")`);
6644
+ lines.push(`${vis}object ${options.objectName} {`);
6645
+ this.renderFlatGroups(lines, groups, 1, options);
6646
+ lines.push("}");
6647
+ });
6528
6648
  }
6529
- const [modifier, context] = parseModifierSource(expectedSource);
6530
- const cleanTokens = stripInternalMetadata(tokensToInclude);
6531
- const referenceTokens = stripInternalMetadata(tokens);
6532
- const selector = resolveSelector(options?.selector, modifier, context, false, modifierInputs);
6533
- const mediaQuery = resolveMediaQuery(
6534
- options?.mediaQuery,
6535
- modifier,
6536
- context,
6537
- false,
6538
- modifierInputs
6539
- );
6540
- const css2 = await formatTokens(cleanTokens, {
6541
- selector,
6542
- mediaQuery,
6543
- minify: options?.minify,
6544
- referenceTokens
6545
- });
6546
- return `/* Modifier: ${modifier}=${context} */
6547
- ${css2}`;
6548
- }
6549
- function collectSetTokens(tokens, setName, included) {
6550
- const result = {};
6551
- for (const [name, token] of Object.entries(tokens)) {
6552
- if (!included.has(name) && getSourceSet(token) === setName) {
6553
- result[name] = token;
6649
+ /**
6650
+ * Shared file preamble: header, package, imports, optional ShadowToken class.
6651
+ * The `renderBody` callback appends the main object(s) to `lines`.
6652
+ */
6653
+ buildFile(tokenTypes, options, renderBody) {
6654
+ const imports = this.collectImports(tokenTypes, options);
6655
+ const vis = options.visibility ? `${options.visibility} ` : "";
6656
+ const lines = [];
6657
+ lines.push(this.buildFileHeader());
6658
+ lines.push("");
6659
+ lines.push(`package ${options.packageName}`);
6660
+ lines.push("");
6661
+ for (const imp of imports) {
6662
+ lines.push(`import ${imp}`);
6554
6663
  }
6555
- }
6556
- return result;
6557
- }
6558
- function collectModifierTokens(tokens, expectedSource, included) {
6559
- const result = {};
6560
- for (const [name, token] of Object.entries(tokens)) {
6561
- if (!included.has(name) && (getSourceModifier(token) ?? "").toLowerCase() === expectedSource) {
6562
- result[name] = token;
6664
+ if (imports.length > 0) {
6665
+ lines.push("");
6666
+ }
6667
+ if (tokenTypes.has("shadow")) {
6668
+ lines.push(...this.buildShadowTokenClass(vis, options));
6669
+ lines.push("");
6563
6670
  }
6671
+ renderBody(lines, vis);
6672
+ lines.push("");
6673
+ return lines.join("\n");
6564
6674
  }
6565
- return result;
6675
+ renderFlatGroups(lines, groups, baseDepth, options) {
6676
+ const vis = options.visibility ? `${options.visibility} ` : "";
6677
+ const groupIndent = indent(options.indent, baseDepth);
6678
+ const valIndent = indent(options.indent, baseDepth + 1);
6679
+ for (const group of groups) {
6680
+ lines.push(`${groupIndent}${vis}object ${group.name} {`);
6681
+ for (const token of group.tokens) {
6682
+ const kotlinName = this.buildFlatKotlinName(token);
6683
+ const kotlinValue = this.formatKotlinValue(token, options, baseDepth + 1);
6684
+ const annotation = this.typeAnnotationSuffix(token);
6685
+ if (token.$description) {
6686
+ lines.push(`${valIndent}/** ${escapeKDoc(token.$description)} */`);
6687
+ }
6688
+ lines.push(`${valIndent}${vis}val ${kotlinName}${annotation} = ${kotlinValue}`);
6689
+ }
6690
+ lines.push(`${groupIndent}}`);
6691
+ lines.push("");
6692
+ }
6693
+ }
6694
+ renderTreeChildren(lines, node, depth, options) {
6695
+ const vis = options.visibility ? `${options.visibility} ` : "";
6696
+ const pad = indent(options.indent, depth);
6697
+ const entries = Array.from(node.children.entries());
6698
+ for (let idx = 0; idx < entries.length; idx++) {
6699
+ const [key, child] = entries[idx];
6700
+ if (child.token && child.children.size === 0) {
6701
+ this.renderLeaf(lines, key, child.token, depth, options);
6702
+ } else if (child.children.size > 0 && !child.token) {
6703
+ const objectName = toPascalCase(key);
6704
+ lines.push(`${pad}${vis}object ${objectName} {`);
6705
+ this.renderTreeChildren(lines, child, depth + 1, options);
6706
+ lines.push(`${pad}}`);
6707
+ if (idx < entries.length - 1) {
6708
+ lines.push("");
6709
+ }
6710
+ } else {
6711
+ this.renderLeaf(lines, key, child.token, depth, options);
6712
+ this.renderTreeChildren(lines, child, depth, options);
6713
+ }
6714
+ }
6715
+ }
6716
+ renderLeaf(lines, key, token, depth, options) {
6717
+ const vis = options.visibility ? `${options.visibility} ` : "";
6718
+ const pad = indent(options.indent, depth);
6719
+ const kotlinName = toKotlinIdentifier(key);
6720
+ const kotlinValue = this.formatKotlinValue(token, options, depth);
6721
+ const annotation = this.typeAnnotationSuffix(token);
6722
+ if (token.$description) {
6723
+ lines.push(`${pad}/** ${escapeKDoc(token.$description)} */`);
6724
+ }
6725
+ lines.push(`${pad}${vis}val ${kotlinName}${annotation} = ${kotlinValue}`);
6726
+ }
6727
+ buildFileHeader() {
6728
+ return [
6729
+ "// Generated by Dispersa - do not edit manually",
6730
+ "// https://github.com/timges/dispersa"
6731
+ ].join("\n");
6732
+ }
6733
+ // -----------------------------------------------------------------------
6734
+ // Shadow data class
6735
+ // -----------------------------------------------------------------------
6736
+ buildShadowTokenClass(vis, options) {
6737
+ const i1 = indent(options.indent, 1);
6738
+ return [
6739
+ "@Immutable",
6740
+ `${vis}data class ShadowToken(`,
6741
+ `${i1}val color: Color,`,
6742
+ `${i1}val elevation: Dp,`,
6743
+ `${i1}val offsetX: Dp,`,
6744
+ `${i1}val offsetY: Dp,`,
6745
+ ")"
6746
+ ];
6747
+ }
6748
+ // -----------------------------------------------------------------------
6749
+ // Imports (tree-shaken)
6750
+ // -----------------------------------------------------------------------
6751
+ collectImports(tokenTypes, options) {
6752
+ const imports = /* @__PURE__ */ new Set();
6753
+ const ns = "androidx.compose";
6754
+ const hasColors = tokenTypes.has("color") || tokenTypes.has("shadow") || tokenTypes.has("border");
6755
+ if (hasColors) {
6756
+ imports.add(`${ns}.ui.graphics.Color`);
6757
+ }
6758
+ if (tokenTypes.has("dimension") || tokenTypes.has("shadow") || tokenTypes.has("border")) {
6759
+ imports.add(`${ns}.ui.unit.Dp`);
6760
+ imports.add(`${ns}.ui.unit.dp`);
6761
+ }
6762
+ if (tokenTypes.has("typography") || tokenTypes.has("fontFamily")) {
6763
+ imports.add(`${ns}.ui.text.TextStyle`);
6764
+ imports.add(`${ns}.ui.unit.sp`);
6765
+ }
6766
+ if (tokenTypes.has("typography") || tokenTypes.has("fontWeight")) {
6767
+ imports.add(`${ns}.ui.text.font.FontWeight`);
6768
+ }
6769
+ if (tokenTypes.has("fontFamily")) {
6770
+ imports.add(`${ns}.ui.text.font.FontFamily`);
6771
+ }
6772
+ if (tokenTypes.has("duration")) {
6773
+ imports.add("kotlin.time.Duration");
6774
+ imports.add("kotlin.time.Duration.Companion.milliseconds");
6775
+ imports.add("kotlin.time.Duration.Companion.seconds");
6776
+ }
6777
+ if (tokenTypes.has("cubicBezier")) {
6778
+ imports.add(`${ns}.animation.core.CubicBezierEasing`);
6779
+ }
6780
+ if (tokenTypes.has("shadow")) {
6781
+ imports.add(`${ns}.runtime.Immutable`);
6782
+ }
6783
+ if (tokenTypes.has("border")) {
6784
+ imports.add(`${ns}.foundation.BorderStroke`);
6785
+ }
6786
+ if (options.colorSpace === "displayP3" && hasColors) {
6787
+ imports.add(`${ns}.ui.graphics.colorspace.ColorSpaces`);
6788
+ }
6789
+ return Array.from(imports).sort();
6790
+ }
6791
+ collectTokenTypes(node, types) {
6792
+ if (node.token?.$type) {
6793
+ types.add(node.token.$type);
6794
+ }
6795
+ for (const child of node.children.values()) {
6796
+ this.collectTokenTypes(child, types);
6797
+ }
6798
+ }
6799
+ collectTokenTypesFromEntries(tokens) {
6800
+ const types = /* @__PURE__ */ new Set();
6801
+ for (const [, token] of Object.entries(tokens)) {
6802
+ if (token.$type) {
6803
+ types.add(token.$type);
6804
+ }
6805
+ }
6806
+ return types;
6807
+ }
6808
+ // -----------------------------------------------------------------------
6809
+ // Type annotations
6810
+ // -----------------------------------------------------------------------
6811
+ getTypeAnnotation(token) {
6812
+ switch (token.$type) {
6813
+ case "color":
6814
+ return "Color";
6815
+ case "dimension":
6816
+ return "Dp";
6817
+ case "fontFamily":
6818
+ return "FontFamily";
6819
+ case "fontWeight":
6820
+ return "FontWeight";
6821
+ case "duration":
6822
+ return "Duration";
6823
+ case "shadow":
6824
+ return "ShadowToken";
6825
+ case "cubicBezier":
6826
+ return "CubicBezierEasing";
6827
+ case "number":
6828
+ return "Double";
6829
+ case "typography":
6830
+ return "TextStyle";
6831
+ case "border":
6832
+ return "BorderStroke";
6833
+ default: {
6834
+ const value = token.$value;
6835
+ if (typeof value === "string") {
6836
+ return "String";
6837
+ }
6838
+ if (typeof value === "boolean") {
6839
+ return "Boolean";
6840
+ }
6841
+ if (typeof value === "number") {
6842
+ return "Double";
6843
+ }
6844
+ return void 0;
6845
+ }
6846
+ }
6847
+ }
6848
+ typeAnnotationSuffix(token) {
6849
+ const type = this.getTypeAnnotation(token);
6850
+ return type ? `: ${type}` : "";
6851
+ }
6852
+ // -----------------------------------------------------------------------
6853
+ // Value formatting
6854
+ // -----------------------------------------------------------------------
6855
+ formatKotlinValue(token, options, depth) {
6856
+ const value = token.$value;
6857
+ if (token.$type === "color") {
6858
+ return this.formatColorValue(value, options);
6859
+ }
6860
+ if (token.$type === "dimension") {
6861
+ return this.formatDimensionValue(value);
6862
+ }
6863
+ if (token.$type === "fontFamily") {
6864
+ return this.formatFontFamilyValue(value);
6865
+ }
6866
+ if (token.$type === "fontWeight") {
6867
+ return this.formatFontWeightValue(value);
6868
+ }
6869
+ if (token.$type === "duration") {
6870
+ return this.formatDurationValue(value);
6871
+ }
6872
+ if (token.$type === "shadow") {
6873
+ return this.formatShadowValue(value, options, depth);
6874
+ }
6875
+ if (token.$type === "typography") {
6876
+ return this.formatTypographyValue(value, options, depth);
6877
+ }
6878
+ if (token.$type === "border") {
6879
+ return this.formatBorderValue(value, options);
6880
+ }
6881
+ if (token.$type === "number") {
6882
+ return typeof value === "number" ? formatKotlinNumber(value) : String(value);
6883
+ }
6884
+ if (token.$type === "cubicBezier" && Array.isArray(value) && value.length === 4) {
6885
+ return `CubicBezierEasing(${value[0]}f, ${value[1]}f, ${value[2]}f, ${value[3]}f)`;
6886
+ }
6887
+ if (typeof value === "string") {
6888
+ return `"${escapeKotlinString(value)}"`;
6889
+ }
6890
+ if (typeof value === "number") {
6891
+ return formatKotlinNumber(value);
6892
+ }
6893
+ if (typeof value === "boolean") {
6894
+ return value ? "true" : "false";
6895
+ }
6896
+ return `"${escapeKotlinString(String(value))}"`;
6897
+ }
6898
+ formatColorValue(value, options) {
6899
+ if (!isColorObject(value)) {
6900
+ if (typeof value === "string") {
6901
+ const hex = value.replace("#", "");
6902
+ if (/^[0-9a-fA-F]{6,8}$/.test(hex)) {
6903
+ const argb = hex.length === 8 ? hex : `FF${hex}`;
6904
+ return `Color(0x${argb.toUpperCase()})`;
6905
+ }
6906
+ }
6907
+ return "Color.Unspecified";
6908
+ }
6909
+ const colorObj = value;
6910
+ const alpha = colorObj.alpha ?? 1;
6911
+ if (options.colorFormat === "argb_float" || options.colorSpace === "displayP3") {
6912
+ return this.formatFloatColor(colorObj, alpha, options);
6913
+ }
6914
+ return this.formatHexColor(colorObj, alpha);
6915
+ }
6916
+ formatFloatColor(colorObj, alpha, options) {
6917
+ if (options.colorSpace === "displayP3") {
6918
+ const p3 = toP3(dtcgObjectToCulori(colorObj));
6919
+ const r2 = roundComponent(p3?.r ?? 0);
6920
+ const g2 = roundComponent(p3?.g ?? 0);
6921
+ const b2 = roundComponent(p3?.b ?? 0);
6922
+ return `Color(${r2}f, ${g2}f, ${b2}f, ${roundComponent(alpha)}f, ColorSpaces.DisplayP3)`;
6923
+ }
6924
+ const rgb = toSRGB(dtcgObjectToCulori(colorObj));
6925
+ const r = roundComponent(rgb?.r ?? 0);
6926
+ const g = roundComponent(rgb?.g ?? 0);
6927
+ const b = roundComponent(rgb?.b ?? 0);
6928
+ return `Color(${r}f, ${g}f, ${b}f, ${roundComponent(alpha)}f)`;
6929
+ }
6930
+ formatHexColor(colorObj, alpha) {
6931
+ const hex = colorObjectToHex(colorObj);
6932
+ const hexClean = hex.replace("#", "");
6933
+ if (hexClean.length === 8) {
6934
+ const rrggbb = hexClean.slice(0, 6);
6935
+ const aa = hexClean.slice(6, 8);
6936
+ return `Color(0x${aa.toUpperCase()}${rrggbb.toUpperCase()})`;
6937
+ }
6938
+ const alphaHex = alpha < 1 ? Math.round(alpha * 255).toString(16).padStart(2, "0").toUpperCase() : "FF";
6939
+ return `Color(0x${alphaHex}${hexClean.toUpperCase()})`;
6940
+ }
6941
+ formatDimensionValue(value) {
6942
+ if (isDimensionObject(value)) {
6943
+ const dim = value;
6944
+ const dpValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
6945
+ return `${dpValue}.dp`;
6946
+ }
6947
+ return typeof value === "number" ? `${value}.dp` : `0.dp`;
6948
+ }
6949
+ formatFontFamilyValue(value) {
6950
+ if (Array.isArray(value)) {
6951
+ const primary = value[0];
6952
+ if (typeof primary === "string") {
6953
+ return this.mapKotlinFontFamily(primary);
6954
+ }
6955
+ return "FontFamily.Default";
6956
+ }
6957
+ return typeof value === "string" ? this.mapKotlinFontFamily(value) : "FontFamily.Default";
6958
+ }
6959
+ mapKotlinFontFamily(family) {
6960
+ const normalized = family.toLowerCase().replace(/['"]/g, "").trim();
6961
+ const builtIn = {
6962
+ "sans-serif": "FontFamily.SansSerif",
6963
+ serif: "FontFamily.Serif",
6964
+ monospace: "FontFamily.Monospace",
6965
+ cursive: "FontFamily.Cursive"
6966
+ };
6967
+ return builtIn[normalized] ?? `FontFamily.Default // TODO: load "${family}" via Font(R.font.${toResourceName(family)})`;
6968
+ }
6969
+ formatFontWeightValue(value) {
6970
+ if (typeof value === "number") {
6971
+ return this.numericFontWeight(value);
6972
+ }
6973
+ if (typeof value === "string") {
6974
+ return this.namedFontWeight(value) ?? "FontWeight.Normal";
6975
+ }
6976
+ return "FontWeight.Normal";
6977
+ }
6978
+ numericFontWeight(weight) {
6979
+ if (weight <= 100) {
6980
+ return "FontWeight.Thin";
6981
+ }
6982
+ if (weight <= 200) {
6983
+ return "FontWeight.ExtraLight";
6984
+ }
6985
+ if (weight <= 300) {
6986
+ return "FontWeight.Light";
6987
+ }
6988
+ if (weight <= 400) {
6989
+ return "FontWeight.Normal";
6990
+ }
6991
+ if (weight <= 500) {
6992
+ return "FontWeight.Medium";
6993
+ }
6994
+ if (weight <= 600) {
6995
+ return "FontWeight.SemiBold";
6996
+ }
6997
+ if (weight <= 700) {
6998
+ return "FontWeight.Bold";
6999
+ }
7000
+ if (weight <= 800) {
7001
+ return "FontWeight.ExtraBold";
7002
+ }
7003
+ return "FontWeight.Black";
7004
+ }
7005
+ namedFontWeight(name) {
7006
+ const map = {
7007
+ thin: "FontWeight.Thin",
7008
+ extralight: "FontWeight.ExtraLight",
7009
+ ultralight: "FontWeight.ExtraLight",
7010
+ light: "FontWeight.Light",
7011
+ regular: "FontWeight.Normal",
7012
+ normal: "FontWeight.Normal",
7013
+ medium: "FontWeight.Medium",
7014
+ semibold: "FontWeight.SemiBold",
7015
+ demibold: "FontWeight.SemiBold",
7016
+ bold: "FontWeight.Bold",
7017
+ extrabold: "FontWeight.ExtraBold",
7018
+ heavy: "FontWeight.ExtraBold",
7019
+ black: "FontWeight.Black",
7020
+ ultrabold: "FontWeight.Black"
7021
+ };
7022
+ return map[name.toLowerCase()];
7023
+ }
7024
+ formatDurationValue(value) {
7025
+ if (typeof value === "object" && value !== null && "value" in value && "unit" in value) {
7026
+ const dur = value;
7027
+ return dur.unit === "ms" ? `${dur.value}.milliseconds` : `${dur.value}.seconds`;
7028
+ }
7029
+ return typeof value === "number" ? `${value}.milliseconds` : "0.milliseconds";
7030
+ }
7031
+ formatShadowValue(value, options, depth) {
7032
+ if (Array.isArray(value) && value.length > 0) {
7033
+ return this.formatSingleShadow(value[0], options, depth);
7034
+ }
7035
+ if (typeof value === "object" && value !== null) {
7036
+ return this.formatSingleShadow(value, options, depth);
7037
+ }
7038
+ return "ShadowToken(color = Color.Unspecified, elevation = 0.dp, offsetX = 0.dp, offsetY = 0.dp)";
7039
+ }
7040
+ formatSingleShadow(shadow, options, depth) {
7041
+ const color = isColorObject(shadow.color) ? this.formatColorValue(shadow.color, options) : "Color.Black";
7042
+ const elevation = isDimensionObject(shadow.blur) ? this.formatDimensionValue(shadow.blur) : "0.dp";
7043
+ const offsetX = isDimensionObject(shadow.offsetX) ? this.formatDimensionValue(shadow.offsetX) : "0.dp";
7044
+ const offsetY = isDimensionObject(shadow.offsetY) ? this.formatDimensionValue(shadow.offsetY) : "0.dp";
7045
+ const propIndent = indent(options.indent, depth + 1);
7046
+ const closeIndent = indent(options.indent, depth);
7047
+ return [
7048
+ "ShadowToken(",
7049
+ `${propIndent}color = ${color},`,
7050
+ `${propIndent}elevation = ${elevation},`,
7051
+ `${propIndent}offsetX = ${offsetX},`,
7052
+ `${propIndent}offsetY = ${offsetY},`,
7053
+ `${closeIndent})`
7054
+ ].join("\n");
7055
+ }
7056
+ formatBorderValue(value, options) {
7057
+ if (typeof value !== "object" || value === null) {
7058
+ return "BorderStroke(0.dp, Color.Unspecified)";
7059
+ }
7060
+ const border = value;
7061
+ const width = isDimensionObject(border.width) ? this.formatDimensionValue(border.width) : "0.dp";
7062
+ const color = isColorObject(border.color) ? this.formatColorValue(border.color, options) : "Color.Unspecified";
7063
+ return `BorderStroke(${width}, ${color})`;
7064
+ }
7065
+ formatTypographyValue(value, options, depth) {
7066
+ if (typeof value !== "object" || value === null) {
7067
+ return "TextStyle()";
7068
+ }
7069
+ const typo = value;
7070
+ const parts = [];
7071
+ if (isDimensionObject(typo.fontSize)) {
7072
+ const dim = typo.fontSize;
7073
+ const spValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
7074
+ parts.push(`fontSize = ${spValue}.sp`);
7075
+ }
7076
+ if (typo.fontWeight != null) {
7077
+ parts.push(`fontWeight = ${this.formatFontWeightValue(typo.fontWeight)}`);
7078
+ }
7079
+ if (typo.lineHeight != null && typeof typo.lineHeight === "number") {
7080
+ if (isDimensionObject(typo.fontSize)) {
7081
+ const dim = typo.fontSize;
7082
+ const spValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
7083
+ const lineHeightSp = Math.round(spValue * typo.lineHeight * 100) / 100;
7084
+ parts.push(`lineHeight = ${lineHeightSp}.sp`);
7085
+ }
7086
+ }
7087
+ if (isDimensionObject(typo.letterSpacing)) {
7088
+ const dim = typo.letterSpacing;
7089
+ const spValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
7090
+ parts.push(`letterSpacing = ${spValue}.sp`);
7091
+ }
7092
+ if (parts.length === 0) {
7093
+ return "TextStyle()";
7094
+ }
7095
+ const propIndent = indent(options.indent, depth + 1);
7096
+ const closeIndent = indent(options.indent, depth);
7097
+ return `TextStyle(
7098
+ ${parts.map((p) => `${propIndent}${p}`).join(",\n")},
7099
+ ${closeIndent})`;
7100
+ }
7101
+ // -----------------------------------------------------------------------
7102
+ // Output: standalone
7103
+ // -----------------------------------------------------------------------
7104
+ async formatStandalone(context, options) {
7105
+ const requiresFile = context.buildPath !== void 0 && context.buildPath !== "";
7106
+ if (!context.output.file && requiresFile) {
7107
+ throw new ConfigurationError(
7108
+ `Output "${context.output.name}": file is required for standalone Android output`
7109
+ );
7110
+ }
7111
+ const files = {};
7112
+ for (const { tokens, modifierInputs } of context.permutations) {
7113
+ const processedTokens = stripInternalMetadata(tokens);
7114
+ const content = this.formatTokens(processedTokens, options);
7115
+ const fileName = context.output.file ? resolveFileName(context.output.file, modifierInputs) : buildInMemoryOutputKey({
7116
+ outputName: context.output.name,
7117
+ extension: "kt",
7118
+ modifierInputs,
7119
+ resolver: context.resolver,
7120
+ defaults: context.meta.defaults
7121
+ });
7122
+ files[fileName] = content;
7123
+ }
7124
+ return outputTree(files);
7125
+ }
7126
+ // -----------------------------------------------------------------------
7127
+ // Output: bundle
7128
+ // -----------------------------------------------------------------------
7129
+ async formatBundle(context, options) {
7130
+ const requiresFile = context.buildPath !== void 0 && context.buildPath !== "";
7131
+ if (!context.output.file && requiresFile) {
7132
+ throw new ConfigurationError(
7133
+ `Output "${context.output.name}": file is required for bundle Android output`
7134
+ );
7135
+ }
7136
+ const content = this.formatBundleContent(context, options);
7137
+ const fileName = context.output.file ? resolveFileName(context.output.file, context.meta.basePermutation) : buildInMemoryOutputKey({
7138
+ outputName: context.output.name,
7139
+ extension: "kt",
7140
+ modifierInputs: context.meta.basePermutation,
7141
+ resolver: context.resolver,
7142
+ defaults: context.meta.defaults
7143
+ });
7144
+ return outputTree({ [fileName]: content });
7145
+ }
7146
+ formatBundleContent(context, options) {
7147
+ const allTokenTypes = this.collectAllPermutationTypes(context);
7148
+ return this.buildFile(allTokenTypes, options, (lines, vis) => {
7149
+ const i1 = indent(options.indent, 1);
7150
+ lines.push(`@Suppress("unused")`);
7151
+ lines.push(`${vis}object ${options.objectName} {`);
7152
+ for (let idx = 0; idx < context.permutations.length; idx++) {
7153
+ const { tokens, modifierInputs } = context.permutations[idx];
7154
+ const processedTokens = stripInternalMetadata(tokens);
7155
+ const permName = this.buildPermutationName(modifierInputs);
7156
+ lines.push(`${i1}${vis}object ${permName} {`);
7157
+ this.renderBundleTokens(lines, processedTokens, options, 2);
7158
+ lines.push(`${i1}}`);
7159
+ if (idx < context.permutations.length - 1) {
7160
+ lines.push("");
7161
+ }
7162
+ }
7163
+ lines.push("}");
7164
+ });
7165
+ }
7166
+ collectAllPermutationTypes(context) {
7167
+ const allTokenTypes = /* @__PURE__ */ new Set();
7168
+ for (const { tokens } of context.permutations) {
7169
+ const processed = stripInternalMetadata(tokens);
7170
+ for (const [, token] of Object.entries(processed)) {
7171
+ if (token.$type) {
7172
+ allTokenTypes.add(token.$type);
7173
+ }
7174
+ }
7175
+ }
7176
+ return allTokenTypes;
7177
+ }
7178
+ renderBundleTokens(lines, tokens, options, baseDepth) {
7179
+ if (options.structure === "flat") {
7180
+ const groups = this.groupTokensByType(tokens);
7181
+ this.renderFlatGroups(lines, groups, baseDepth, options);
7182
+ return;
7183
+ }
7184
+ const tree = this.buildTokenTree(tokens);
7185
+ this.renderTreeChildren(lines, tree, baseDepth, options);
7186
+ }
7187
+ buildPermutationName(modifierInputs) {
7188
+ const values = Object.values(modifierInputs);
7189
+ if (values.length === 0) {
7190
+ return "Default";
7191
+ }
7192
+ return values.map((v) => toPascalCase(v)).join("");
7193
+ }
7194
+ };
7195
+ function androidRenderer() {
7196
+ const rendererInstance = new AndroidRenderer();
7197
+ return {
7198
+ format: (context, options) => rendererInstance.format(
7199
+ context,
7200
+ options ?? context.output.options
7201
+ )
7202
+ };
7203
+ }
7204
+
7205
+ // src/renderers/css.ts
7206
+ init_errors();
7207
+ init_token_utils();
7208
+
7209
+ // src/renderers/bundlers/css.ts
7210
+ init_errors();
7211
+ init_utils();
7212
+ var getSourceSet = (token) => {
7213
+ if (typeof token !== "object" || token === null) {
7214
+ return void 0;
7215
+ }
7216
+ const maybe = token;
7217
+ return typeof maybe._sourceSet === "string" ? maybe._sourceSet : void 0;
7218
+ };
7219
+ var getSourceModifier = (token) => {
7220
+ if (typeof token !== "object" || token === null) {
7221
+ return void 0;
7222
+ }
7223
+ const maybe = token;
7224
+ return typeof maybe._sourceModifier === "string" ? maybe._sourceModifier : void 0;
7225
+ };
7226
+ async function bundleAsCss(bundleData, resolver, options, formatTokens) {
7227
+ const baseItem = bundleData.find((item) => item.isBase);
7228
+ if (!baseItem) {
7229
+ throw new BasePermutationError("Base permutation not found in bundle data");
7230
+ }
7231
+ if (!formatTokens) {
7232
+ throw new ConfigurationError("CSS formatter was not provided");
7233
+ }
7234
+ const orderedBundleData = orderBundleData(bundleData, resolver, baseItem);
7235
+ const cssBlocks = [];
7236
+ for (const item of orderedBundleData) {
7237
+ if (item.isBase) {
7238
+ const blocks = await formatBasePermutation(item, resolver, options, formatTokens);
7239
+ cssBlocks.push(...blocks);
7240
+ continue;
7241
+ }
7242
+ const block = await formatModifierPermutation(item, baseItem, options, formatTokens);
7243
+ if (block) {
7244
+ cssBlocks.push(block);
7245
+ }
7246
+ }
7247
+ return cssBlocks.join("\n\n");
7248
+ }
7249
+ async function formatBasePermutation({ tokens, modifierInputs }, resolver, options, formatTokens) {
7250
+ const firstModifierName = resolver.modifiers ? Object.keys(resolver.modifiers)[0] : "";
7251
+ const modifier = firstModifierName ?? "";
7252
+ const context = modifierInputs[modifier] ?? "";
7253
+ const selector = resolveSelector(options?.selector, modifier, context, true, modifierInputs);
7254
+ const mediaQuery = resolveMediaQuery(options?.mediaQuery, modifier, context, true, modifierInputs);
7255
+ const referenceTokens = stripInternalMetadata(tokens);
7256
+ const defaultBlocks = buildDefaultLayerBlocks(tokens, modifierInputs, resolver);
7257
+ const cssBlocks = [];
7258
+ for (const block of defaultBlocks) {
7259
+ const cleanTokens = stripInternalMetadata(block.tokens);
7260
+ const css2 = await formatTokens(cleanTokens, {
7261
+ selector,
7262
+ mediaQuery,
7263
+ minify: options?.minify,
7264
+ referenceTokens
7265
+ });
7266
+ const header = block.description ? `/* ${block.key} */
7267
+ /* ${block.description} */` : `/* ${block.key} */`;
7268
+ cssBlocks.push(`${header}
7269
+ ${css2}`);
7270
+ }
7271
+ return cssBlocks;
7272
+ }
7273
+ async function formatModifierPermutation({ tokens, modifierInputs }, baseItem, options, formatTokens) {
7274
+ const differenceCount = countModifierDifferences(modifierInputs, baseItem.modifierInputs);
7275
+ if (differenceCount > 1) {
7276
+ return void 0;
7277
+ }
7278
+ const expectedSource = getExpectedSource(modifierInputs, baseItem.modifierInputs);
7279
+ let tokensToInclude = filterTokensBySource(tokens, expectedSource);
7280
+ const hasSourceMetadata = Object.values(tokens).some(
7281
+ (token) => token != null && getSourceModifier(token) !== void 0
7282
+ );
7283
+ if (Object.keys(tokensToInclude).length === 0 && !hasSourceMetadata) {
7284
+ tokensToInclude = tokens;
7285
+ }
7286
+ if (Object.keys(tokensToInclude).length === 0) {
7287
+ return void 0;
7288
+ }
7289
+ const [modifier, context] = parseModifierSource(expectedSource);
7290
+ const cleanTokens = stripInternalMetadata(tokensToInclude);
7291
+ const referenceTokens = stripInternalMetadata(tokens);
7292
+ const selector = resolveSelector(options?.selector, modifier, context, false, modifierInputs);
7293
+ const mediaQuery = resolveMediaQuery(
7294
+ options?.mediaQuery,
7295
+ modifier,
7296
+ context,
7297
+ false,
7298
+ modifierInputs
7299
+ );
7300
+ const css2 = await formatTokens(cleanTokens, {
7301
+ selector,
7302
+ mediaQuery,
7303
+ minify: options?.minify,
7304
+ referenceTokens
7305
+ });
7306
+ return `/* Modifier: ${modifier}=${context} */
7307
+ ${css2}`;
7308
+ }
7309
+ function collectSetTokens(tokens, setName, included) {
7310
+ const result = {};
7311
+ for (const [name, token] of Object.entries(tokens)) {
7312
+ if (!included.has(name) && getSourceSet(token) === setName) {
7313
+ result[name] = token;
7314
+ }
7315
+ }
7316
+ return result;
7317
+ }
7318
+ function collectModifierTokens(tokens, expectedSource, included) {
7319
+ const result = {};
7320
+ for (const [name, token] of Object.entries(tokens)) {
7321
+ if (!included.has(name) && (getSourceModifier(token) ?? "").toLowerCase() === expectedSource) {
7322
+ result[name] = token;
7323
+ }
7324
+ }
7325
+ return result;
6566
7326
  }
6567
7327
  function collectRemainder(tokens, included) {
6568
7328
  const result = {};
@@ -6768,14 +7528,14 @@ var CssRenderer = class _CssRenderer {
6768
7528
  return opts.minify ? cssString : await this.formatWithPrettier(cssString);
6769
7529
  }
6770
7530
  buildCssBlock(lines, groupTokens, selector, tokens, referenceTokens, opts) {
6771
- const indent = opts.minify ? "" : " ";
7531
+ const indent2 = opts.minify ? "" : " ";
6772
7532
  const newline = opts.minify ? "" : "\n";
6773
7533
  const space = opts.minify ? "" : " ";
6774
7534
  const hasMediaQuery = opts.mediaQuery != null && opts.mediaQuery !== "";
6775
- const tokenIndent = hasMediaQuery ? indent + indent : indent;
7535
+ const tokenIndent = hasMediaQuery ? indent2 + indent2 : indent2;
6776
7536
  if (hasMediaQuery) {
6777
7537
  lines.push(`@media ${opts.mediaQuery}${space}{${newline}`);
6778
- lines.push(`${indent}${selector}${space}{${newline}`);
7538
+ lines.push(`${indent2}${selector}${space}{${newline}`);
6779
7539
  } else {
6780
7540
  lines.push(`${selector}${space}{${newline}`);
6781
7541
  }
@@ -6792,21 +7552,21 @@ var CssRenderer = class _CssRenderer {
6792
7552
  );
6793
7553
  }
6794
7554
  if (hasMediaQuery) {
6795
- lines.push(`${indent}}${newline}`);
7555
+ lines.push(`${indent2}}${newline}`);
6796
7556
  }
6797
7557
  lines.push(`}${newline}${newline}`);
6798
7558
  }
6799
- pushTokenLines(lines, token, tokens, referenceTokens, preserveReferences, indent, newline, space) {
7559
+ pushTokenLines(lines, token, tokens, referenceTokens, preserveReferences, indent2, newline, space) {
6800
7560
  const entries = this.buildCssEntries(token, tokens, referenceTokens, preserveReferences);
6801
7561
  if (token.$deprecated != null && token.$deprecated !== false) {
6802
7562
  const deprecationMsg = formatDeprecationMessage(token, "", "comment");
6803
- lines.push(`${indent}/* ${this.sanitizeCssCommentText(deprecationMsg)} */${newline}`);
7563
+ lines.push(`${indent2}/* ${this.sanitizeCssCommentText(deprecationMsg)} */${newline}`);
6804
7564
  }
6805
7565
  if (token.$description && token.$description !== "") {
6806
- lines.push(`${indent}/* ${this.sanitizeCssCommentText(token.$description)} */${newline}`);
7566
+ lines.push(`${indent2}/* ${this.sanitizeCssCommentText(token.$description)} */${newline}`);
6807
7567
  }
6808
7568
  for (const entry of entries) {
6809
- lines.push(`${indent}--${entry.name}:${space}${entry.value};${newline}`);
7569
+ lines.push(`${indent2}--${entry.name}:${space}${entry.value};${newline}`);
6810
7570
  }
6811
7571
  }
6812
7572
  async formatWithPrettier(css2) {
@@ -7381,18 +8141,641 @@ var CssRenderer = class _CssRenderer {
7381
8141
  return { modifierName: name, modifierContext: value };
7382
8142
  }
7383
8143
  }
7384
- return { modifierName: "", modifierContext: "" };
7385
- }
7386
- isBasePermutation(modifierInputs, defaults) {
7387
- const normalizedInputs = normalizeModifierInputs(modifierInputs);
7388
- const normalizedDefaults = normalizeModifierInputs(defaults);
7389
- return Object.entries(normalizedDefaults).every(
7390
- ([key, value]) => normalizedInputs[key] === value
7391
- );
8144
+ return { modifierName: "", modifierContext: "" };
8145
+ }
8146
+ isBasePermutation(modifierInputs, defaults) {
8147
+ const normalizedInputs = normalizeModifierInputs(modifierInputs);
8148
+ const normalizedDefaults = normalizeModifierInputs(defaults);
8149
+ return Object.entries(normalizedDefaults).every(
8150
+ ([key, value]) => normalizedInputs[key] === value
8151
+ );
8152
+ }
8153
+ };
8154
+ function cssRenderer() {
8155
+ const rendererInstance = new CssRenderer();
8156
+ return {
8157
+ format: (context, options) => rendererInstance.format(
8158
+ context,
8159
+ options ?? context.output.options
8160
+ )
8161
+ };
8162
+ }
8163
+
8164
+ // src/renderers/ios.ts
8165
+ init_errors();
8166
+ init_token_utils();
8167
+ init_utils();
8168
+ var toSRGB2 = converter("rgb");
8169
+ var toP32 = converter("p3");
8170
+ var SWIFT_TYPE_GROUP_MAP = {
8171
+ color: "Colors",
8172
+ dimension: "Spacing",
8173
+ fontFamily: "Fonts",
8174
+ fontWeight: "FontWeights",
8175
+ duration: "Durations",
8176
+ shadow: "Shadows",
8177
+ typography: "Typography",
8178
+ number: "Numbers",
8179
+ cubicBezier: "Animations",
8180
+ border: "Borders",
8181
+ gradient: "Gradients"
8182
+ };
8183
+ var SWIFT_KEYWORDS = /* @__PURE__ */ new Set([
8184
+ "associatedtype",
8185
+ "class",
8186
+ "deinit",
8187
+ "enum",
8188
+ "extension",
8189
+ "fileprivate",
8190
+ "func",
8191
+ "import",
8192
+ "init",
8193
+ "inout",
8194
+ "internal",
8195
+ "let",
8196
+ "open",
8197
+ "operator",
8198
+ "private",
8199
+ "protocol",
8200
+ "public",
8201
+ "rethrows",
8202
+ "static",
8203
+ "struct",
8204
+ "subscript",
8205
+ "typealias",
8206
+ "var",
8207
+ "break",
8208
+ "case",
8209
+ "continue",
8210
+ "default",
8211
+ "defer",
8212
+ "do",
8213
+ "else",
8214
+ "fallthrough",
8215
+ "for",
8216
+ "guard",
8217
+ "if",
8218
+ "in",
8219
+ "repeat",
8220
+ "return",
8221
+ "switch",
8222
+ "where",
8223
+ "while",
8224
+ "as",
8225
+ "catch",
8226
+ "false",
8227
+ "is",
8228
+ "nil",
8229
+ "super",
8230
+ "self",
8231
+ "Self",
8232
+ "throw",
8233
+ "throws",
8234
+ "true",
8235
+ "try",
8236
+ "Type",
8237
+ "Protocol"
8238
+ ]);
8239
+ var IosRenderer = class {
8240
+ async format(context, options) {
8241
+ const opts = {
8242
+ preset: options?.preset ?? "standalone",
8243
+ accessLevel: options?.accessLevel ?? "public",
8244
+ structure: options?.structure ?? "enum",
8245
+ enumName: options?.enumName ?? "DesignTokens",
8246
+ extensionNamespace: options?.extensionNamespace ?? "DesignTokens",
8247
+ colorSpace: options?.colorSpace ?? "sRGB",
8248
+ swiftVersion: options?.swiftVersion ?? "5.9",
8249
+ indent: options?.indent ?? 4,
8250
+ frozen: options?.frozen ?? false
8251
+ };
8252
+ return await this.formatStandalone(context, opts);
8253
+ }
8254
+ formatTokens(tokens, options) {
8255
+ if (options.structure === "grouped") {
8256
+ return this.formatAsGrouped(tokens, options);
8257
+ }
8258
+ return this.formatAsEnum(tokens, options);
8259
+ }
8260
+ formatAsEnum(tokens, options) {
8261
+ const access3 = options.accessLevel;
8262
+ const groups = this.groupTokensByType(tokens);
8263
+ const imports = this.collectImports(tokens);
8264
+ const i1 = this.indentStr(options.indent, 1);
8265
+ const i2 = this.indentStr(options.indent, 2);
8266
+ const staticPrefix = this.staticLetPrefix(options);
8267
+ const frozen = this.frozenPrefix(options);
8268
+ const lines = [];
8269
+ lines.push(this.buildFileHeader());
8270
+ lines.push("");
8271
+ for (const imp of imports) {
8272
+ lines.push(`import ${imp}`);
8273
+ }
8274
+ lines.push(...this.buildStructDefinitions(tokens, access3, options));
8275
+ lines.push("");
8276
+ lines.push(`${frozen}${access3} enum ${options.enumName} {`);
8277
+ for (const group of groups) {
8278
+ lines.push(`${i1}${frozen}${access3} enum ${group.name} {`);
8279
+ for (const token of group.tokens) {
8280
+ const swiftName = this.buildQualifiedSwiftName(token);
8281
+ const swiftValue = this.formatSwiftValue(token, options);
8282
+ const typeAnnotation = this.getTypeAnnotation(token);
8283
+ const annotation = typeAnnotation ? `: ${typeAnnotation}` : "";
8284
+ const docComment = this.buildDocComment(token, i2);
8285
+ if (docComment) {
8286
+ lines.push(docComment);
8287
+ }
8288
+ lines.push(`${i2}${access3} ${staticPrefix}${swiftName}${annotation} = ${swiftValue}`);
8289
+ }
8290
+ lines.push(`${i1}}`);
8291
+ lines.push("");
8292
+ }
8293
+ lines.push("}");
8294
+ lines.push(...this.buildViewExtensions(tokens, access3, options));
8295
+ lines.push("");
8296
+ return lines.join("\n");
8297
+ }
8298
+ formatAsGrouped(tokens, options) {
8299
+ const access3 = options.accessLevel;
8300
+ const namespace = options.extensionNamespace;
8301
+ const groups = this.groupTokensByType(tokens);
8302
+ const imports = this.collectImports(tokens);
8303
+ const i1 = this.indentStr(options.indent, 1);
8304
+ const i2 = this.indentStr(options.indent, 2);
8305
+ const staticPrefix = this.staticLetPrefix(options);
8306
+ const frozen = this.frozenPrefix(options);
8307
+ const lines = [];
8308
+ lines.push(this.buildFileHeader());
8309
+ lines.push("");
8310
+ for (const imp of imports) {
8311
+ lines.push(`import ${imp}`);
8312
+ }
8313
+ lines.push(...this.buildStructDefinitions(tokens, access3, options));
8314
+ lines.push("");
8315
+ lines.push(`${frozen}${access3} enum ${namespace} {}`);
8316
+ lines.push("");
8317
+ for (const group of groups) {
8318
+ lines.push(`${access3} extension ${namespace} {`);
8319
+ lines.push(`${i1}${frozen}enum ${group.name} {`);
8320
+ for (const token of group.tokens) {
8321
+ const swiftName = this.buildQualifiedSwiftName(token);
8322
+ const swiftValue = this.formatSwiftValue(token, options);
8323
+ const typeAnnotation = this.getTypeAnnotation(token);
8324
+ const annotation = typeAnnotation ? `: ${typeAnnotation}` : "";
8325
+ const docComment = this.buildDocComment(token, i2);
8326
+ if (docComment) {
8327
+ lines.push(docComment);
8328
+ }
8329
+ lines.push(`${i2}${access3} ${staticPrefix}${swiftName}${annotation} = ${swiftValue}`);
8330
+ }
8331
+ lines.push(`${i1}}`);
8332
+ lines.push("}");
8333
+ lines.push("");
8334
+ }
8335
+ lines.push(...this.buildViewExtensions(tokens, access3, options));
8336
+ return lines.join("\n");
8337
+ }
8338
+ buildFileHeader() {
8339
+ return [
8340
+ "// Generated by Dispersa - do not edit manually",
8341
+ "// https://github.com/timges/dispersa"
8342
+ ].join("\n");
8343
+ }
8344
+ collectImports(tokens) {
8345
+ const imports = /* @__PURE__ */ new Set();
8346
+ imports.add("SwiftUI");
8347
+ for (const [, token] of Object.entries(tokens)) {
8348
+ if (token.$type === "duration") {
8349
+ imports.add("Foundation");
8350
+ }
8351
+ }
8352
+ return Array.from(imports).sort();
8353
+ }
8354
+ /**
8355
+ * Builds a `///` doc comment from a token's `$description`, if present.
8356
+ */
8357
+ buildDocComment(token, indent2) {
8358
+ if (!token.$description) {
8359
+ return void 0;
8360
+ }
8361
+ return `${indent2}/// ${token.$description}`;
8362
+ }
8363
+ groupTokensByType(tokens) {
8364
+ const groupMap = /* @__PURE__ */ new Map();
8365
+ for (const [, token] of getSortedTokenEntries(tokens)) {
8366
+ const groupName = SWIFT_TYPE_GROUP_MAP[token.$type ?? ""] ?? "Other";
8367
+ const existing = groupMap.get(groupName) ?? [];
8368
+ existing.push(token);
8369
+ groupMap.set(groupName, existing);
8370
+ }
8371
+ return Array.from(groupMap.entries()).map(([name, groupTokens]) => ({
8372
+ name,
8373
+ tokens: groupTokens
8374
+ }));
8375
+ }
8376
+ /**
8377
+ * Builds a qualified Swift name from a token's path, preserving parent
8378
+ * hierarchy segments to avoid duplicate identifiers.
8379
+ *
8380
+ * For example, `color.blue.400` in the `Colors` group becomes `blue400`
8381
+ * instead of just `_400`.
8382
+ */
8383
+ buildQualifiedSwiftName(token) {
8384
+ const path7 = token.path;
8385
+ const withoutTypePrefix = path7.length > 1 ? path7.slice(1) : path7;
8386
+ const joined = withoutTypePrefix.join("_");
8387
+ return this.toSwiftIdentifier(joined);
8388
+ }
8389
+ formatSwiftValue(token, options) {
8390
+ const value = token.$value;
8391
+ if (token.$type === "color") {
8392
+ return this.formatColorValue(value, options);
8393
+ }
8394
+ if (token.$type === "dimension") {
8395
+ return this.formatDimensionValue(value);
8396
+ }
8397
+ if (token.$type === "fontFamily") {
8398
+ return this.formatFontFamilyValue(value);
8399
+ }
8400
+ if (token.$type === "fontWeight") {
8401
+ return this.formatFontWeightValue(value);
8402
+ }
8403
+ if (token.$type === "duration") {
8404
+ return this.formatDurationValue(value);
8405
+ }
8406
+ if (token.$type === "shadow") {
8407
+ return this.formatShadowValue(value, options);
8408
+ }
8409
+ if (token.$type === "typography") {
8410
+ return this.formatTypographyValue(value);
8411
+ }
8412
+ if (token.$type === "border") {
8413
+ return this.formatBorderValue(value, options);
8414
+ }
8415
+ if (token.$type === "gradient") {
8416
+ return this.formatGradientValue(value, options);
8417
+ }
8418
+ if (token.$type === "number") {
8419
+ return String(value);
8420
+ }
8421
+ if (token.$type === "cubicBezier" && Array.isArray(value) && value.length === 4) {
8422
+ return `UnitCurve.bezier(startControlPoint: UnitPoint(x: ${value[0]}, y: ${value[1]}), endControlPoint: UnitPoint(x: ${value[2]}, y: ${value[3]}))`;
8423
+ }
8424
+ if (typeof value === "string") {
8425
+ return `"${this.escapeSwiftString(value)}"`;
8426
+ }
8427
+ if (typeof value === "number") {
8428
+ return String(value);
8429
+ }
8430
+ if (typeof value === "boolean") {
8431
+ return value ? "true" : "false";
8432
+ }
8433
+ return `"${this.escapeSwiftString(String(value))}"`;
8434
+ }
8435
+ formatColorValue(value, options) {
8436
+ if (!isColorObject(value)) {
8437
+ return typeof value === "string" ? `Color("${this.escapeSwiftString(value)}")` : "Color.clear";
8438
+ }
8439
+ const colorObj = value;
8440
+ const alpha = colorObj.alpha ?? 1;
8441
+ if (options.colorSpace === "displayP3") {
8442
+ const p3 = toP32(dtcgObjectToCulori(colorObj));
8443
+ const r2 = this.roundComponent(p3?.r ?? 0);
8444
+ const g2 = this.roundComponent(p3?.g ?? 0);
8445
+ const b2 = this.roundComponent(p3?.b ?? 0);
8446
+ return alpha < 1 ? `Color(.displayP3, red: ${r2}, green: ${g2}, blue: ${b2}, opacity: ${this.roundComponent(alpha)})` : `Color(.displayP3, red: ${r2}, green: ${g2}, blue: ${b2})`;
8447
+ }
8448
+ const rgb = toSRGB2(dtcgObjectToCulori(colorObj));
8449
+ const r = this.roundComponent(rgb?.r ?? 0);
8450
+ const g = this.roundComponent(rgb?.g ?? 0);
8451
+ const b = this.roundComponent(rgb?.b ?? 0);
8452
+ return alpha < 1 ? `Color(red: ${r}, green: ${g}, blue: ${b}, opacity: ${this.roundComponent(alpha)})` : `Color(red: ${r}, green: ${g}, blue: ${b})`;
8453
+ }
8454
+ formatDimensionValue(value) {
8455
+ if (isDimensionObject(value)) {
8456
+ const dim = value;
8457
+ const ptValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
8458
+ return String(ptValue);
8459
+ }
8460
+ return String(value);
8461
+ }
8462
+ formatFontFamilyValue(value) {
8463
+ if (Array.isArray(value)) {
8464
+ const primary = value[0];
8465
+ return typeof primary === "string" ? `"${this.escapeSwiftString(primary)}"` : '"system"';
8466
+ }
8467
+ return typeof value === "string" ? `"${this.escapeSwiftString(value)}"` : '"system"';
8468
+ }
8469
+ formatFontWeightValue(value) {
8470
+ if (typeof value === "number") {
8471
+ return this.numericFontWeight(value);
8472
+ }
8473
+ if (typeof value === "string") {
8474
+ return this.namedFontWeight(value) ?? "Font.Weight.regular";
8475
+ }
8476
+ return "Font.Weight.regular";
8477
+ }
8478
+ numericFontWeight(weight) {
8479
+ if (weight <= 100) {
8480
+ return "Font.Weight.ultraLight";
8481
+ }
8482
+ if (weight <= 200) {
8483
+ return "Font.Weight.thin";
8484
+ }
8485
+ if (weight <= 300) {
8486
+ return "Font.Weight.light";
8487
+ }
8488
+ if (weight <= 400) {
8489
+ return "Font.Weight.regular";
8490
+ }
8491
+ if (weight <= 500) {
8492
+ return "Font.Weight.medium";
8493
+ }
8494
+ if (weight <= 600) {
8495
+ return "Font.Weight.semibold";
8496
+ }
8497
+ if (weight <= 700) {
8498
+ return "Font.Weight.bold";
8499
+ }
8500
+ if (weight <= 800) {
8501
+ return "Font.Weight.heavy";
8502
+ }
8503
+ return "Font.Weight.black";
8504
+ }
8505
+ namedFontWeight(name) {
8506
+ const map = {
8507
+ thin: "Font.Weight.thin",
8508
+ ultralight: "Font.Weight.ultraLight",
8509
+ extralight: "Font.Weight.ultraLight",
8510
+ light: "Font.Weight.light",
8511
+ regular: "Font.Weight.regular",
8512
+ normal: "Font.Weight.regular",
8513
+ medium: "Font.Weight.medium",
8514
+ semibold: "Font.Weight.semibold",
8515
+ demibold: "Font.Weight.semibold",
8516
+ bold: "Font.Weight.bold",
8517
+ heavy: "Font.Weight.heavy",
8518
+ extrabold: "Font.Weight.heavy",
8519
+ black: "Font.Weight.black",
8520
+ ultrabold: "Font.Weight.black"
8521
+ };
8522
+ return map[name.toLowerCase()];
8523
+ }
8524
+ formatDurationValue(value) {
8525
+ if (typeof value === "object" && value !== null && "value" in value && "unit" in value) {
8526
+ const dur = value;
8527
+ const seconds = dur.unit === "ms" ? dur.value / 1e3 : dur.value;
8528
+ return String(seconds);
8529
+ }
8530
+ return typeof value === "number" ? String(value) : "0";
8531
+ }
8532
+ formatShadowValue(value, options) {
8533
+ if (Array.isArray(value) && value.length > 0) {
8534
+ return this.formatSingleShadow(value[0], options);
8535
+ }
8536
+ if (typeof value === "object" && value !== null) {
8537
+ return this.formatSingleShadow(value, options);
8538
+ }
8539
+ return "ShadowStyle(color: .clear, radius: 0, x: 0, y: 0, spread: 0)";
8540
+ }
8541
+ formatSingleShadow(shadow, options) {
8542
+ const color = isColorObject(shadow.color) ? this.formatColorValue(shadow.color, options) : "Color.black.opacity(0.25)";
8543
+ const radius = isDimensionObject(shadow.blur) ? this.dimensionToCGFloat(shadow.blur) : "8";
8544
+ const x = isDimensionObject(shadow.offsetX) ? this.dimensionToCGFloat(shadow.offsetX) : "0";
8545
+ const y = isDimensionObject(shadow.offsetY) ? this.dimensionToCGFloat(shadow.offsetY) : "0";
8546
+ const spread = isDimensionObject(shadow.spread) ? this.dimensionToCGFloat(shadow.spread) : "0";
8547
+ return `ShadowStyle(color: ${color}, radius: ${radius}, x: ${x}, y: ${y}, spread: ${spread})`;
8548
+ }
8549
+ formatTypographyValue(value) {
8550
+ if (typeof value !== "object" || value === null) {
8551
+ return "TypographyStyle(font: Font.body, tracking: 0, lineSpacing: 0)";
8552
+ }
8553
+ const typo = value;
8554
+ const size = isDimensionObject(typo.fontSize) ? this.dimensionToPoints(typo.fontSize) : "16";
8555
+ const weight = typo.fontWeight != null ? this.formatFontWeightValue(typo.fontWeight) : "Font.Weight.regular";
8556
+ const fontExpr = this.buildFontExpression(typo, size, weight);
8557
+ const tracking = this.extractTracking(typo);
8558
+ const lineSpacing = this.extractLineSpacing(typo);
8559
+ return `TypographyStyle(font: ${fontExpr}, tracking: ${tracking}, lineSpacing: ${lineSpacing})`;
8560
+ }
8561
+ buildFontExpression(typo, size, weight) {
8562
+ if (typo.fontFamily != null) {
8563
+ const family = Array.isArray(typo.fontFamily) ? typo.fontFamily[0] : typo.fontFamily;
8564
+ if (typeof family === "string") {
8565
+ return `Font.custom("${this.escapeSwiftString(family)}", size: ${size}).weight(${weight})`;
8566
+ }
8567
+ }
8568
+ return `Font.system(size: ${size}, weight: ${weight})`;
8569
+ }
8570
+ extractTracking(typo) {
8571
+ if (!isDimensionObject(typo.letterSpacing)) {
8572
+ return "0";
8573
+ }
8574
+ const dim = typo.letterSpacing;
8575
+ const ptValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
8576
+ return String(ptValue);
8577
+ }
8578
+ extractLineSpacing(typo) {
8579
+ if (typo.lineHeight == null || typeof typo.lineHeight !== "number") {
8580
+ return "0";
8581
+ }
8582
+ if (!isDimensionObject(typo.fontSize)) {
8583
+ return "0";
8584
+ }
8585
+ const dim = typo.fontSize;
8586
+ const basePt = dim.unit === "rem" ? dim.value * 16 : dim.value;
8587
+ const lineHeightPt = Math.round(basePt * typo.lineHeight * 100) / 100;
8588
+ return String(lineHeightPt - basePt);
8589
+ }
8590
+ dimensionToPoints(dim) {
8591
+ const ptValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
8592
+ return String(ptValue);
8593
+ }
8594
+ /** Formats a dimension as a CGFloat literal (appends `.0` for integers). */
8595
+ dimensionToCGFloat(dim) {
8596
+ const ptValue = dim.unit === "rem" ? dim.value * 16 : dim.value;
8597
+ return Number.isInteger(ptValue) ? `${ptValue}.0` : String(ptValue);
8598
+ }
8599
+ getTypeAnnotation(token) {
8600
+ switch (token.$type) {
8601
+ case "dimension":
8602
+ return "CGFloat";
8603
+ case "duration":
8604
+ return "TimeInterval";
8605
+ case "number":
8606
+ return "Double";
8607
+ case "fontWeight":
8608
+ return "Font.Weight";
8609
+ case "fontFamily":
8610
+ return "String";
8611
+ default:
8612
+ return void 0;
8613
+ }
8614
+ }
8615
+ toSwiftIdentifier(name) {
8616
+ const camel = name.replace(/[-._]+(.)/g, (_, c) => c.toUpperCase()).replace(/[-._]+$/g, "").replace(/^[-._]+/g, "");
8617
+ const identifier = camel.charAt(0).toLowerCase() + camel.slice(1);
8618
+ const safe = /^\d/.test(identifier) ? `_${identifier}` : identifier;
8619
+ return SWIFT_KEYWORDS.has(safe) ? `\`${safe}\`` : safe;
8620
+ }
8621
+ escapeSwiftString(str) {
8622
+ return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
8623
+ }
8624
+ roundComponent(value) {
8625
+ return Math.round(value * 1e4) / 1e4;
8626
+ }
8627
+ indentStr(width, level) {
8628
+ return " ".repeat(width * level);
8629
+ }
8630
+ /**
8631
+ * Returns the prefix for `static let` declarations.
8632
+ * Swift 6 requires `nonisolated(unsafe)` on global stored properties.
8633
+ */
8634
+ staticLetPrefix(options) {
8635
+ return options.swiftVersion === "6.0" ? "nonisolated(unsafe) static let " : "static let ";
8636
+ }
8637
+ /** Returns `@frozen ` when the frozen option is enabled, empty string otherwise. */
8638
+ frozenPrefix(options) {
8639
+ return options.frozen ? "@frozen " : "";
8640
+ }
8641
+ /** Returns `: Sendable` when targeting Swift 6, empty string otherwise. */
8642
+ structConformances(options) {
8643
+ return options.swiftVersion === "6.0" ? ": Sendable" : "";
8644
+ }
8645
+ hasShadowTokens(tokens) {
8646
+ return Object.values(tokens).some((t) => t.$type === "shadow");
8647
+ }
8648
+ hasTypographyTokens(tokens) {
8649
+ return Object.values(tokens).some((t) => t.$type === "typography");
8650
+ }
8651
+ hasBorderTokens(tokens) {
8652
+ return Object.values(tokens).some((t) => t.$type === "border");
8653
+ }
8654
+ /** Emits all struct definitions needed by the token set. */
8655
+ buildStructDefinitions(tokens, access3, options) {
8656
+ const lines = [];
8657
+ if (this.hasShadowTokens(tokens)) {
8658
+ lines.push("");
8659
+ lines.push(...this.buildShadowStyleStruct(access3, options));
8660
+ }
8661
+ if (this.hasTypographyTokens(tokens)) {
8662
+ lines.push("");
8663
+ lines.push(...this.buildTypographyStyleStruct(access3, options));
8664
+ }
8665
+ if (this.hasBorderTokens(tokens)) {
8666
+ lines.push("");
8667
+ lines.push(...this.buildBorderStyleStruct(access3, options));
8668
+ }
8669
+ return lines;
8670
+ }
8671
+ buildShadowStyleStruct(access3, options) {
8672
+ const i1 = this.indentStr(options.indent, 1);
8673
+ const conformances = this.structConformances(options);
8674
+ const frozen = this.frozenPrefix(options);
8675
+ return [
8676
+ `${frozen}${access3} struct ShadowStyle${conformances} {`,
8677
+ `${i1}${access3} let color: Color`,
8678
+ `${i1}${access3} let radius: CGFloat`,
8679
+ `${i1}${access3} let x: CGFloat`,
8680
+ `${i1}${access3} let y: CGFloat`,
8681
+ `${i1}${access3} let spread: CGFloat`,
8682
+ "}"
8683
+ ];
8684
+ }
8685
+ buildTypographyStyleStruct(access3, options) {
8686
+ const i1 = this.indentStr(options.indent, 1);
8687
+ const conformances = this.structConformances(options);
8688
+ const frozen = this.frozenPrefix(options);
8689
+ return [
8690
+ `${frozen}${access3} struct TypographyStyle${conformances} {`,
8691
+ `${i1}${access3} let font: Font`,
8692
+ `${i1}${access3} let tracking: CGFloat`,
8693
+ `${i1}${access3} let lineSpacing: CGFloat`,
8694
+ "}"
8695
+ ];
8696
+ }
8697
+ buildBorderStyleStruct(access3, options) {
8698
+ const i1 = this.indentStr(options.indent, 1);
8699
+ const conformances = this.structConformances(options);
8700
+ const frozen = this.frozenPrefix(options);
8701
+ return [
8702
+ `${frozen}${access3} struct BorderStyle${conformances} {`,
8703
+ `${i1}${access3} let color: Color`,
8704
+ `${i1}${access3} let width: CGFloat`,
8705
+ "}"
8706
+ ];
8707
+ }
8708
+ /** Emits convenience View extensions for shadow and typography application. */
8709
+ buildViewExtensions(tokens, access3, options) {
8710
+ const lines = [];
8711
+ const i1 = this.indentStr(options.indent, 1);
8712
+ const i2 = this.indentStr(options.indent, 2);
8713
+ if (this.hasShadowTokens(tokens)) {
8714
+ lines.push("");
8715
+ lines.push(`${access3} extension View {`);
8716
+ lines.push(`${i1}func shadowStyle(_ style: ShadowStyle) -> some View {`);
8717
+ lines.push(
8718
+ `${i2}self.shadow(color: style.color, radius: style.radius, x: style.x, y: style.y)`
8719
+ );
8720
+ lines.push(`${i1}}`);
8721
+ lines.push("}");
8722
+ }
8723
+ if (this.hasTypographyTokens(tokens)) {
8724
+ lines.push("");
8725
+ lines.push(`${access3} extension View {`);
8726
+ lines.push(`${i1}func typographyStyle(_ style: TypographyStyle) -> some View {`);
8727
+ lines.push(
8728
+ `${i2}self.font(style.font).tracking(style.tracking).lineSpacing(style.lineSpacing)`
8729
+ );
8730
+ lines.push(`${i1}}`);
8731
+ lines.push("}");
8732
+ }
8733
+ return lines;
8734
+ }
8735
+ formatBorderValue(value, options) {
8736
+ if (typeof value !== "object" || value === null) {
8737
+ return "BorderStyle(color: .clear, width: 0)";
8738
+ }
8739
+ const border = value;
8740
+ const color = isColorObject(border.color) ? this.formatColorValue(border.color, options) : "Color.clear";
8741
+ const width = isDimensionObject(border.width) ? this.dimensionToCGFloat(border.width) : "1.0";
8742
+ return `BorderStyle(color: ${color}, width: ${width})`;
8743
+ }
8744
+ formatGradientValue(value, options) {
8745
+ if (!Array.isArray(value) || value.length === 0) {
8746
+ return "Gradient(stops: [])";
8747
+ }
8748
+ const stops = value.map((stop) => {
8749
+ const color = isColorObject(stop.color) ? this.formatColorValue(stop.color, options) : "Color.clear";
8750
+ return `.init(color: ${color}, location: ${stop.position})`;
8751
+ });
8752
+ return `Gradient(stops: [${stops.join(", ")}])`;
8753
+ }
8754
+ async formatStandalone(context, options) {
8755
+ const requiresFile = context.buildPath !== void 0 && context.buildPath !== "";
8756
+ if (!context.output.file && requiresFile) {
8757
+ throw new ConfigurationError(
8758
+ `Output "${context.output.name}": file is required for standalone iOS output`
8759
+ );
8760
+ }
8761
+ const files = {};
8762
+ for (const { tokens, modifierInputs } of context.permutations) {
8763
+ const processedTokens = stripInternalMetadata(tokens);
8764
+ const content = this.formatTokens(processedTokens, options);
8765
+ const fileName = context.output.file ? resolveFileName(context.output.file, modifierInputs) : buildInMemoryOutputKey({
8766
+ outputName: context.output.name,
8767
+ extension: "swift",
8768
+ modifierInputs,
8769
+ resolver: context.resolver,
8770
+ defaults: context.meta.defaults
8771
+ });
8772
+ files[fileName] = content;
8773
+ }
8774
+ return outputTree(files);
7392
8775
  }
7393
8776
  };
7394
- function cssRenderer() {
7395
- const rendererInstance = new CssRenderer();
8777
+ function iosRenderer() {
8778
+ const rendererInstance = new IosRenderer();
7396
8779
  return {
7397
8780
  format: (context, options) => rendererInstance.format(
7398
8781
  context,
@@ -7518,8 +8901,8 @@ var JsModuleRenderer = class {
7518
8901
  /**
7519
8902
  * Add object properties to lines
7520
8903
  */
7521
- addObjectProperties(lines, obj, indent) {
7522
- const indentStr = " ".repeat(indent);
8904
+ addObjectProperties(lines, obj, indent2) {
8905
+ const indentStr = " ".repeat(indent2);
7523
8906
  const entries = Object.entries(obj).sort(([keyA], [keyB]) => keyA.localeCompare(keyB));
7524
8907
  for (let i = 0; i < entries.length; i++) {
7525
8908
  const entry = entries[i];
@@ -7530,7 +8913,7 @@ var JsModuleRenderer = class {
7530
8913
  const isLast = i === entries.length - 1;
7531
8914
  if (typeof value === "object" && value !== null && !Array.isArray(value)) {
7532
8915
  lines.push(`${indentStr}${this.quoteKey(key)}: {`);
7533
- this.addObjectProperties(lines, value, indent + 1);
8916
+ this.addObjectProperties(lines, value, indent2 + 1);
7534
8917
  lines.push(`${indentStr}}${isLast ? "" : ","}`);
7535
8918
  } else {
7536
8919
  const valueStr = JSON.stringify(value);
@@ -7722,6 +9105,349 @@ function jsonRenderer() {
7722
9105
  };
7723
9106
  }
7724
9107
 
9108
+ // src/renderers/tailwind.ts
9109
+ init_errors();
9110
+ init_token_utils();
9111
+
9112
+ // src/renderers/bundlers/tailwind.ts
9113
+ init_errors();
9114
+ init_utils();
9115
+ async function bundleAsTailwind(bundleData, options, formatThemeTokens, formatOverrideBlock) {
9116
+ const baseItem = bundleData.find((item) => item.isBase);
9117
+ if (!baseItem) {
9118
+ throw new BasePermutationError("Base permutation not found in bundle data");
9119
+ }
9120
+ const resolvedOpts = resolveOptions(options);
9121
+ const cssBlocks = [];
9122
+ const variantDeclarations = collectVariantDeclarations(bundleData, baseItem, resolvedOpts);
9123
+ const themeOpts = { ...resolvedOpts, variantDeclarations };
9124
+ const baseTokens = stripInternalMetadata(baseItem.tokens);
9125
+ const themeBlock = await formatThemeTokens(baseTokens, themeOpts);
9126
+ cssBlocks.push(themeBlock);
9127
+ for (const item of bundleData) {
9128
+ if (item.isBase) {
9129
+ continue;
9130
+ }
9131
+ const block = await formatModifierOverride(item, baseItem, resolvedOpts, formatOverrideBlock);
9132
+ if (block) {
9133
+ cssBlocks.push(block);
9134
+ }
9135
+ }
9136
+ return cssBlocks.join("\n");
9137
+ }
9138
+ async function formatModifierOverride({ tokens, modifierInputs }, baseItem, options, formatOverrideBlock) {
9139
+ const differenceCount = countModifierDifferences(modifierInputs, baseItem.modifierInputs);
9140
+ if (differenceCount > 1) {
9141
+ return void 0;
9142
+ }
9143
+ const tokensToInclude = filterTokensByValueChange(tokens, baseItem.tokens);
9144
+ if (Object.keys(tokensToInclude).length === 0) {
9145
+ return void 0;
9146
+ }
9147
+ const expectedSource = getExpectedSource(modifierInputs, baseItem.modifierInputs);
9148
+ const [modifier, context] = parseModifierSource(expectedSource);
9149
+ const cleanTokens = stripInternalMetadata(tokensToInclude);
9150
+ const selector = resolveSelector(
9151
+ options.selector,
9152
+ modifier,
9153
+ context,
9154
+ false,
9155
+ normalizeModifierInputs(modifierInputs)
9156
+ );
9157
+ const mediaQuery = resolveMediaQuery(
9158
+ options.mediaQuery,
9159
+ modifier,
9160
+ context,
9161
+ false,
9162
+ normalizeModifierInputs(modifierInputs)
9163
+ );
9164
+ const css2 = await formatOverrideBlock(cleanTokens, selector, mediaQuery, options.minify);
9165
+ return `/* Modifier: ${modifier}=${context} */
9166
+ ${css2}`;
9167
+ }
9168
+ function filterTokensByValueChange(currentTokens, baseTokens) {
9169
+ const changed = {};
9170
+ for (const [name, token] of Object.entries(currentTokens)) {
9171
+ const baseToken = baseTokens[name];
9172
+ if (!baseToken) {
9173
+ changed[name] = token;
9174
+ continue;
9175
+ }
9176
+ if (JSON.stringify(token.$value) !== JSON.stringify(baseToken.$value)) {
9177
+ changed[name] = token;
9178
+ }
9179
+ }
9180
+ return changed;
9181
+ }
9182
+ function collectVariantDeclarations(bundleData, baseItem, options) {
9183
+ const declarations = [];
9184
+ for (const item of bundleData) {
9185
+ if (item.isBase) {
9186
+ continue;
9187
+ }
9188
+ const differenceCount = countModifierDifferences(item.modifierInputs, baseItem.modifierInputs);
9189
+ if (differenceCount > 1) {
9190
+ continue;
9191
+ }
9192
+ const expectedSource = getExpectedSource(item.modifierInputs, baseItem.modifierInputs);
9193
+ const [modifier, context] = parseModifierSource(expectedSource);
9194
+ const variantName = `${modifier}-${context}`;
9195
+ const normalized = normalizeModifierInputs(item.modifierInputs);
9196
+ const mediaQuery = resolveMediaQuery(options.mediaQuery, modifier, context, false, normalized);
9197
+ if (mediaQuery !== "") {
9198
+ declarations.push(`@custom-variant ${variantName} (@media ${mediaQuery});`);
9199
+ continue;
9200
+ }
9201
+ const selector = resolveSelector(options.selector, modifier, context, false, normalized);
9202
+ declarations.push(`@custom-variant ${variantName} (&:where(${selector}, ${selector} *));`);
9203
+ }
9204
+ return declarations;
9205
+ }
9206
+ function resolveOptions(options) {
9207
+ return {
9208
+ preset: options.preset ?? "bundle",
9209
+ includeImport: options.includeImport ?? true,
9210
+ namespace: options.namespace ?? "",
9211
+ minify: options.minify ?? false,
9212
+ selector: options.selector,
9213
+ mediaQuery: options.mediaQuery,
9214
+ variantDeclarations: []
9215
+ };
9216
+ }
9217
+
9218
+ // src/renderers/tailwind.ts
9219
+ init_utils();
9220
+ var TAILWIND_NAMESPACE_MAP = {
9221
+ color: "color",
9222
+ dimension: "spacing",
9223
+ fontFamily: "font",
9224
+ fontWeight: "font-weight",
9225
+ duration: "duration",
9226
+ shadow: "shadow",
9227
+ number: "number",
9228
+ cubicBezier: "ease"
9229
+ };
9230
+ var TailwindRenderer = class {
9231
+ async format(context, options) {
9232
+ const opts = {
9233
+ preset: options?.preset ?? "bundle",
9234
+ includeImport: options?.includeImport ?? true,
9235
+ namespace: options?.namespace ?? "",
9236
+ minify: options?.minify ?? false,
9237
+ selector: options?.selector,
9238
+ mediaQuery: options?.mediaQuery,
9239
+ variantDeclarations: []
9240
+ };
9241
+ if (opts.preset === "bundle") {
9242
+ return await this.formatBundle(context, opts);
9243
+ }
9244
+ return await this.formatStandalone(context, opts);
9245
+ }
9246
+ /**
9247
+ * Format tokens as Tailwind v4 @theme CSS variables
9248
+ */
9249
+ async formatTokens(tokens, options) {
9250
+ const lines = [];
9251
+ const indent2 = options.minify ? "" : " ";
9252
+ const newline = options.minify ? "" : "\n";
9253
+ const space = options.minify ? "" : " ";
9254
+ if (options.includeImport) {
9255
+ lines.push(`@import "tailwindcss";${newline}`);
9256
+ }
9257
+ if (options.variantDeclarations.length > 0) {
9258
+ if (options.includeImport) {
9259
+ lines.push(newline);
9260
+ }
9261
+ for (const declaration of options.variantDeclarations) {
9262
+ lines.push(`${declaration}${newline}`);
9263
+ }
9264
+ }
9265
+ if (options.includeImport || options.variantDeclarations.length > 0) {
9266
+ lines.push(newline);
9267
+ }
9268
+ const themeDirective = options.namespace ? `@theme namespace(${options.namespace})` : "@theme";
9269
+ lines.push(`${themeDirective}${space}{${newline}`);
9270
+ for (const [, token] of getSortedTokenEntries(tokens)) {
9271
+ const varName = this.buildVariableName(token);
9272
+ const varValue = this.formatValue(token);
9273
+ lines.push(`${indent2}--${varName}:${space}${varValue};${newline}`);
9274
+ }
9275
+ lines.push(`}${newline}`);
9276
+ const cssString = lines.join("");
9277
+ return options.minify ? cssString : await this.formatWithPrettier(cssString);
9278
+ }
9279
+ /**
9280
+ * Format tokens as plain CSS custom property overrides inside a selector block.
9281
+ * Used for modifier overrides (e.g., dark mode) appended after the @theme block.
9282
+ */
9283
+ async formatOverrideBlock(tokens, selector, mediaQuery, minify) {
9284
+ const indent2 = minify ? "" : " ";
9285
+ const newline = minify ? "" : "\n";
9286
+ const space = minify ? "" : " ";
9287
+ const hasMediaQuery = mediaQuery !== "";
9288
+ const tokenIndent = hasMediaQuery ? indent2 + indent2 : indent2;
9289
+ const lines = [];
9290
+ if (hasMediaQuery) {
9291
+ lines.push(`@media ${mediaQuery}${space}{${newline}`);
9292
+ lines.push(`${indent2}${selector}${space}{${newline}`);
9293
+ } else {
9294
+ lines.push(`${selector}${space}{${newline}`);
9295
+ }
9296
+ for (const [, token] of getSortedTokenEntries(tokens)) {
9297
+ const varName = this.buildVariableName(token);
9298
+ const varValue = this.formatValue(token);
9299
+ lines.push(`${tokenIndent}--${varName}:${space}${varValue};${newline}`);
9300
+ }
9301
+ if (hasMediaQuery) {
9302
+ lines.push(`${indent2}}${newline}`);
9303
+ lines.push(`}${newline}`);
9304
+ } else {
9305
+ lines.push(`}${newline}`);
9306
+ }
9307
+ return lines.join("");
9308
+ }
9309
+ buildVariableName(token) {
9310
+ const prefix = TAILWIND_NAMESPACE_MAP[token.$type ?? ""];
9311
+ if (!prefix) {
9312
+ return token.name;
9313
+ }
9314
+ const nameLower = token.name.toLowerCase();
9315
+ const prefixLower = prefix.toLowerCase();
9316
+ if (nameLower.startsWith(`${prefixLower}-`) || nameLower.startsWith(`${prefixLower}.`)) {
9317
+ return token.name;
9318
+ }
9319
+ return `${prefix}-${token.name}`;
9320
+ }
9321
+ formatValue(token) {
9322
+ const value = token.$value;
9323
+ if (token.$type === "color" && isColorObject(value)) {
9324
+ return colorObjectToHex(value);
9325
+ }
9326
+ if (token.$type === "dimension" && isDimensionObject(value)) {
9327
+ return dimensionObjectToString(value);
9328
+ }
9329
+ if (token.$type === "duration" && this.isDurationObject(value)) {
9330
+ return `${value.value}${value.unit}`;
9331
+ }
9332
+ if (token.$type === "fontFamily") {
9333
+ if (Array.isArray(value)) {
9334
+ return value.map((v) => typeof v === "string" && v.includes(" ") ? `"${v}"` : v).join(", ");
9335
+ }
9336
+ return typeof value === "string" ? value : String(value);
9337
+ }
9338
+ if (token.$type === "shadow") {
9339
+ return this.formatShadowValue(value);
9340
+ }
9341
+ if (token.$type === "cubicBezier" && Array.isArray(value) && value.length === 4) {
9342
+ return `cubic-bezier(${value.join(", ")})`;
9343
+ }
9344
+ if (typeof value === "string") {
9345
+ return value;
9346
+ }
9347
+ if (typeof value === "number") {
9348
+ return String(value);
9349
+ }
9350
+ return String(value);
9351
+ }
9352
+ formatShadowValue(value) {
9353
+ if (Array.isArray(value) && value.length > 0 && typeof value[0] === "object") {
9354
+ return value.map((s) => this.formatSingleShadow(s)).join(", ");
9355
+ }
9356
+ if (typeof value === "object" && value !== null) {
9357
+ return this.formatSingleShadow(value);
9358
+ }
9359
+ return String(value);
9360
+ }
9361
+ formatSingleShadow(shadow) {
9362
+ const parts = [];
9363
+ if (shadow.inset === true) {
9364
+ parts.push("inset");
9365
+ }
9366
+ if (isDimensionObject(shadow.offsetX)) {
9367
+ parts.push(dimensionObjectToString(shadow.offsetX));
9368
+ }
9369
+ if (isDimensionObject(shadow.offsetY)) {
9370
+ parts.push(dimensionObjectToString(shadow.offsetY));
9371
+ }
9372
+ if (isDimensionObject(shadow.blur)) {
9373
+ parts.push(dimensionObjectToString(shadow.blur));
9374
+ }
9375
+ if (shadow.spread != null && isDimensionObject(shadow.spread)) {
9376
+ parts.push(dimensionObjectToString(shadow.spread));
9377
+ }
9378
+ if (isColorObject(shadow.color)) {
9379
+ parts.push(colorObjectToHex(shadow.color));
9380
+ } else if (shadow.color != null) {
9381
+ parts.push(String(shadow.color));
9382
+ }
9383
+ return parts.join(" ");
9384
+ }
9385
+ isDurationObject(value) {
9386
+ return typeof value === "object" && value !== null && "value" in value && "unit" in value && value.unit !== void 0;
9387
+ }
9388
+ async formatWithPrettier(css2) {
9389
+ try {
9390
+ return await prettier.format(css2, {
9391
+ parser: "css",
9392
+ printWidth: 80,
9393
+ tabWidth: 2,
9394
+ useTabs: false
9395
+ });
9396
+ } catch {
9397
+ return css2;
9398
+ }
9399
+ }
9400
+ async formatBundle(context, options) {
9401
+ const bundleData = context.permutations.map(({ tokens, modifierInputs }) => ({
9402
+ tokens,
9403
+ modifierInputs,
9404
+ isBase: this.isBasePermutation(modifierInputs, context.meta.defaults)
9405
+ }));
9406
+ return await bundleAsTailwind(
9407
+ bundleData,
9408
+ options,
9409
+ async (tokens, opts) => await this.formatTokens(tokens, opts),
9410
+ async (tokens, selector, mediaQuery, minify) => await this.formatOverrideBlock(tokens, selector, mediaQuery, minify)
9411
+ );
9412
+ }
9413
+ async formatStandalone(context, options) {
9414
+ const requiresFile = context.buildPath !== void 0 && context.buildPath !== "";
9415
+ if (!context.output.file && requiresFile) {
9416
+ throw new ConfigurationError(
9417
+ `Output "${context.output.name}": file is required for standalone Tailwind output`
9418
+ );
9419
+ }
9420
+ const files = {};
9421
+ for (const { tokens, modifierInputs } of context.permutations) {
9422
+ const processedTokens = stripInternalMetadata(tokens);
9423
+ const content = await this.formatTokens(processedTokens, options);
9424
+ const fileName = context.output.file ? resolveFileName(context.output.file, modifierInputs) : buildInMemoryOutputKey({
9425
+ outputName: context.output.name,
9426
+ extension: "css",
9427
+ modifierInputs,
9428
+ resolver: context.resolver,
9429
+ defaults: context.meta.defaults
9430
+ });
9431
+ files[fileName] = content;
9432
+ }
9433
+ return outputTree(files);
9434
+ }
9435
+ isBasePermutation(modifierInputs, defaults) {
9436
+ return Object.entries(defaults).every(
9437
+ ([key, value]) => modifierInputs[key]?.toLowerCase() === value.toLowerCase()
9438
+ );
9439
+ }
9440
+ };
9441
+ function tailwindRenderer() {
9442
+ const rendererInstance = new TailwindRenderer();
9443
+ return {
9444
+ format: (context, options) => rendererInstance.format(
9445
+ context,
9446
+ options ?? context.output.options
9447
+ )
9448
+ };
9449
+ }
9450
+
7725
9451
  // src/builders.ts
7726
9452
  function css(config) {
7727
9453
  const {
@@ -7783,6 +9509,58 @@ function js(config) {
7783
9509
  hooks
7784
9510
  };
7785
9511
  }
9512
+ function tailwind(config) {
9513
+ const { name, file, transforms, filters, hooks, preset = "bundle", ...rendererOptions } = config;
9514
+ return {
9515
+ name,
9516
+ file,
9517
+ renderer: tailwindRenderer(),
9518
+ options: { preset, ...rendererOptions },
9519
+ transforms,
9520
+ filters,
9521
+ hooks
9522
+ };
9523
+ }
9524
+ function ios(config) {
9525
+ const {
9526
+ name,
9527
+ file,
9528
+ transforms,
9529
+ filters,
9530
+ hooks,
9531
+ preset = "standalone",
9532
+ ...rendererOptions
9533
+ } = config;
9534
+ return {
9535
+ name,
9536
+ file,
9537
+ renderer: iosRenderer(),
9538
+ options: { preset, ...rendererOptions },
9539
+ transforms,
9540
+ filters,
9541
+ hooks
9542
+ };
9543
+ }
9544
+ function android(config) {
9545
+ const {
9546
+ name,
9547
+ file,
9548
+ transforms,
9549
+ filters,
9550
+ hooks,
9551
+ preset = "standalone",
9552
+ ...rendererOptions
9553
+ } = config;
9554
+ return {
9555
+ name,
9556
+ file,
9557
+ renderer: androidRenderer(),
9558
+ options: { preset, ...rendererOptions },
9559
+ transforms,
9560
+ filters,
9561
+ hooks
9562
+ };
9563
+ }
7786
9564
 
7787
9565
  // src/renderers/types.ts
7788
9566
  function defineRenderer(renderer) {
@@ -7796,7 +9574,14 @@ init_errors();
7796
9574
  * Copyright (c) 2025 Dispersa Contributors
7797
9575
  * SPDX-License-Identifier: MIT
7798
9576
  */
9577
+ /**
9578
+ * @license MIT
9579
+ * Copyright (c) 2025-present Dispersa Contributors
9580
+ *
9581
+ * This source code is licensed under the MIT license found in the
9582
+ * LICENSE file in the root directory of this source tree.
9583
+ */
7799
9584
 
7800
- export { BasePermutationError, CircularReferenceError, ColorParseError, ConfigurationError, DimensionFormatError, Dispersa, DispersaError, FileOperationError, ModifierError, TokenReferenceError, ValidationError, css, defineRenderer, isBorderToken, isColorToken, isDimensionToken, isDurationToken, isGradientToken, isOutputTree, isShadowToken, isTransitionToken, isTypographyToken, js, json, outputTree };
9585
+ export { BasePermutationError, CircularReferenceError, ColorParseError, ConfigurationError, DimensionFormatError, Dispersa, DispersaError, FileOperationError, ModifierError, TokenReferenceError, ValidationError, android, css, defineRenderer, ios, isBorderToken, isColorToken, isDimensionToken, isDurationToken, isGradientToken, isOutputTree, isShadowToken, isTransitionToken, isTypographyToken, js, json, outputTree, tailwind };
7801
9586
  //# sourceMappingURL=index.js.map
7802
9587
  //# sourceMappingURL=index.js.map