zyzz 0.0.20 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/Style.d.ts +7 -0
  2. package/dist/Style.d.ts.map +1 -1
  3. package/dist/Style.js +1 -5
  4. package/dist/Style.js.map +1 -1
  5. package/dist/compiler/Graph.d.ts +3 -0
  6. package/dist/compiler/Graph.d.ts.map +1 -1
  7. package/dist/compiler/Graph.js +44 -37
  8. package/dist/compiler/Graph.js.map +1 -1
  9. package/dist/compiler/Source.d.ts +4 -0
  10. package/dist/compiler/Source.d.ts.map +1 -1
  11. package/dist/compiler/Source.js +63 -6
  12. package/dist/compiler/Source.js.map +1 -1
  13. package/dist/compiler/Transform.d.ts +4 -1
  14. package/dist/compiler/Transform.d.ts.map +1 -1
  15. package/dist/compiler/Transform.js +32 -46
  16. package/dist/compiler/Transform.js.map +1 -1
  17. package/dist/compiler/internal/Catalogs.d.ts.map +1 -1
  18. package/dist/compiler/internal/Catalogs.js +6 -1
  19. package/dist/compiler/internal/Catalogs.js.map +1 -1
  20. package/dist/compiler/internal/Compositions.d.ts.map +1 -1
  21. package/dist/compiler/internal/Compositions.js +5 -0
  22. package/dist/compiler/internal/Compositions.js.map +1 -1
  23. package/dist/compiler/internal/Configurations.d.ts.map +1 -1
  24. package/dist/compiler/internal/Configurations.js +2 -1
  25. package/dist/compiler/internal/Configurations.js.map +1 -1
  26. package/dist/compiler/internal/Contract.d.ts +4 -1
  27. package/dist/compiler/internal/Contract.d.ts.map +1 -1
  28. package/dist/compiler/internal/Contract.js +56 -147
  29. package/dist/compiler/internal/Contract.js.map +1 -1
  30. package/dist/compiler/internal/Contributions.d.ts.map +1 -1
  31. package/dist/compiler/internal/Contributions.js +1 -3
  32. package/dist/compiler/internal/Contributions.js.map +1 -1
  33. package/dist/compiler/internal/Dynamic.d.ts +1 -1
  34. package/dist/compiler/internal/Dynamic.d.ts.map +1 -1
  35. package/dist/compiler/internal/Dynamic.js +5 -5
  36. package/dist/compiler/internal/Dynamic.js.map +1 -1
  37. package/dist/compiler/internal/Names.d.ts +5 -0
  38. package/dist/compiler/internal/Names.d.ts.map +1 -0
  39. package/dist/compiler/internal/Names.js +37 -0
  40. package/dist/compiler/internal/Names.js.map +1 -0
  41. package/dist/compiler/internal/Selectors.d.ts +1 -1
  42. package/dist/compiler/internal/Selectors.d.ts.map +1 -1
  43. package/dist/compiler/internal/Selectors.js +5 -2
  44. package/dist/compiler/internal/Selectors.js.map +1 -1
  45. package/dist/compiler/internal/Stylesheets.js +2 -2
  46. package/dist/compiler/internal/Stylesheets.js.map +1 -1
  47. package/dist/compiler/internal/Themes.d.ts.map +1 -1
  48. package/dist/compiler/internal/Themes.js +2 -1
  49. package/dist/compiler/internal/Themes.js.map +1 -1
  50. package/dist/compiler/internal/Vars.d.ts +2 -0
  51. package/dist/compiler/internal/Vars.d.ts.map +1 -1
  52. package/dist/compiler/internal/Vars.js +7 -1
  53. package/dist/compiler/internal/Vars.js.map +1 -1
  54. package/dist/default.d.ts +4 -4
  55. package/dist/default.d.ts.map +1 -1
  56. package/dist/default.js +9 -9
  57. package/dist/default.js.map +2 -2
  58. package/dist/default.js.zyzz.json +1 -1
  59. package/dist/internal/Authoring.d.ts.map +1 -1
  60. package/dist/internal/Authoring.js +8 -3
  61. package/dist/internal/Authoring.js.map +1 -1
  62. package/dist/internal/Binding.d.ts +4 -0
  63. package/dist/internal/Binding.d.ts.map +1 -1
  64. package/dist/internal/Binding.js +2 -0
  65. package/dist/internal/Binding.js.map +1 -1
  66. package/dist/internal/Configuration.d.ts +2 -2
  67. package/dist/internal/Configuration.d.ts.map +1 -1
  68. package/dist/internal/Configuration.js +4 -2
  69. package/dist/internal/Configuration.js.map +1 -1
  70. package/dist/internal/Identity.d.ts +3 -3
  71. package/dist/internal/Identity.d.ts.map +1 -1
  72. package/dist/internal/Identity.js +11 -9
  73. package/dist/internal/Identity.js.map +1 -1
  74. package/dist/internal/Theme.js +2 -2
  75. package/dist/internal/Theme.js.map +1 -1
  76. package/dist/internal/Token.d.ts +5 -1
  77. package/dist/internal/Token.d.ts.map +1 -1
  78. package/dist/internal/Token.js +9 -2
  79. package/dist/internal/Token.js.map +1 -1
  80. package/dist/internal/VariableSets.js +1 -1
  81. package/dist/internal/VariableSets.js.map +1 -1
  82. package/dist/node/Host.d.ts.map +1 -1
  83. package/dist/node/Host.js +2 -0
  84. package/dist/node/Host.js.map +1 -1
  85. package/dist/variable.js +1 -1
  86. package/dist/variable.js.map +1 -1
  87. package/dist/vite/index.d.ts.map +1 -1
  88. package/dist/vite/index.js +36 -12
  89. package/dist/vite/index.js.map +1 -1
  90. package/dist/web/Css.d.ts +7 -2
  91. package/dist/web/Css.d.ts.map +1 -1
  92. package/dist/web/Css.js +46 -39
  93. package/dist/web/Css.js.map +1 -1
  94. package/dist/web/internal/ClassName.d.ts +13 -2
  95. package/dist/web/internal/ClassName.d.ts.map +1 -1
  96. package/dist/web/internal/ClassName.js +17 -30
  97. package/dist/web/internal/ClassName.js.map +1 -1
  98. package/dist/web/internal/Themes.d.ts +3 -0
  99. package/dist/web/internal/Themes.d.ts.map +1 -1
  100. package/dist/web/internal/Themes.js +48 -24
  101. package/dist/web/internal/Themes.js.map +1 -1
  102. package/package.json +1 -1
  103. package/src/Style.ts +4 -1
  104. package/src/compiler/Graph.ts +60 -46
  105. package/src/compiler/Source.ts +83 -5
  106. package/src/compiler/Transform.ts +42 -60
  107. package/src/compiler/internal/Catalogs.ts +9 -1
  108. package/src/compiler/internal/Compositions.ts +7 -0
  109. package/src/compiler/internal/Configurations.ts +2 -1
  110. package/src/compiler/internal/Contract.ts +75 -253
  111. package/src/compiler/internal/Contributions.ts +1 -5
  112. package/src/compiler/internal/Dynamic.ts +14 -9
  113. package/src/compiler/internal/Names.ts +48 -0
  114. package/src/compiler/internal/Selectors.ts +6 -1
  115. package/src/compiler/internal/Stylesheets.ts +2 -2
  116. package/src/compiler/internal/Themes.ts +6 -1
  117. package/src/compiler/internal/Vars.ts +9 -1
  118. package/src/default.ts +9 -10
  119. package/src/internal/Authoring.ts +8 -2
  120. package/src/internal/Binding.ts +5 -0
  121. package/src/internal/Configuration.ts +7 -4
  122. package/src/internal/Identity.ts +14 -12
  123. package/src/internal/Theme.ts +2 -2
  124. package/src/internal/Token.ts +13 -1
  125. package/src/internal/VariableSets.ts +1 -1
  126. package/src/node/Host.ts +3 -0
  127. package/src/variable.ts +1 -1
  128. package/src/vite/index.ts +43 -18
  129. package/src/web/Css.ts +83 -49
  130. package/src/web/internal/ClassName.ts +31 -36
  131. package/src/web/internal/Themes.ts +75 -29
@@ -32,6 +32,8 @@ import * as Themes from './internal/Themes.js'
32
32
  import * as ThemeValues from '../web/internal/Themes.js'
33
33
  import * as Token from '../internal/Token.js'
34
34
  import * as Literal from '../internal/Literal.js'
35
+ import * as Names from './internal/Names.js'
36
+ import * as ClassName from '../web/internal/ClassName.js'
35
37
  import * as Typography from '../internal/Typography.js'
36
38
  import * as Value from '../internal/Value.js'
37
39
  import * as Vars from './internal/Vars.js'
@@ -57,6 +59,10 @@ export type Call = {
57
59
  | undefined
58
60
  /** Class identity available without source rewriting. */
59
61
  readonly portable?: string | undefined
62
+ /** Readable authored binding used for contextual CSS names. */
63
+ readonly cssName?: string | undefined
64
+ /** Explicit configuration namespace for emitted CSS. */
65
+ readonly cssNamespace?: string | undefined
60
66
  /** Flattened definition identities for nested compositions. */
61
67
  readonly portableInputs?: readonly string[] | undefined
62
68
  /** Ownership retained by a separately compiled callable. */
@@ -214,6 +220,7 @@ export function extract(options: extract.Options): extract.ReturnType {
214
220
  }
215
221
 
216
222
  const program = parsed.program
223
+ const authoredNames = Names.collect(program)
217
224
  const scopeTracker = new Scope.Tracker({ preserveExitedScopes: true })
218
225
 
219
226
  Walker.walk(program, { scopeTracker })
@@ -540,6 +547,13 @@ export function extract(options: extract.Options): extract.ReturnType {
540
547
  pending,
541
548
  options[Themes.context]?.links,
542
549
  selectorKeys,
550
+ new Map(
551
+ [...(themes?.styles ?? [])].flatMap(([start, context]) => {
552
+ const id = context.theme[Token.definition].contract[Token.identity]
553
+ return id?.startsWith('id-') ? [[start, id.slice(3)] as const] : []
554
+ }),
555
+ ),
556
+ options.moduleId,
543
557
  )
544
558
  } catch (error) {
545
559
  if (!(error instanceof Themes.InvalidError)) throw error
@@ -549,7 +563,13 @@ export function extract(options: extract.Options): extract.ReturnType {
549
563
  }
550
564
  })()
551
565
 
566
+ const cssNameCounts = new Map<string, number>()
552
567
  for (const call of pending) {
568
+ const name = authoredNames.get(call.start)!
569
+ cssNameCounts.set(name, (cssNameCounts.get(name) ?? 0) + 1)
570
+ }
571
+ const cssNameIndices = new Map<string, number>()
572
+ for (const [callIndex, call] of pending.entries()) {
553
573
  const explicitId = (() => {
554
574
  try {
555
575
  return Identifiers.explicit(call)
@@ -558,10 +578,29 @@ export function extract(options: extract.Options): extract.ReturnType {
558
578
  return undefined
559
579
  }
560
580
  })()
581
+ const contractIdentity = themes?.styles.get(call.start)?.theme[
582
+ Token.definition
583
+ ].contract[Token.identity]
584
+ const cssNamespace = contractIdentity?.startsWith('id-')
585
+ ? contractIdentity.slice(3)
586
+ : undefined
587
+ const authoredName = authoredNames.get(call.start)!
588
+ const nameIndex = cssNameIndices.get(authoredName) ?? 0
589
+ cssNameIndices.set(authoredName, nameIndex + 1)
590
+ const cssName =
591
+ explicitId !== undefined
592
+ ? Identity.name(explicitId)
593
+ : `${Identity.compact(options.moduleId).slice(-6)}-${
594
+ authoredName === 'style'
595
+ ? `style-${callIndex}`
596
+ : cssNameCounts.get(authoredName)! > 1
597
+ ? `${authoredName}-${nameIndex}`
598
+ : authoredName
599
+ }`
561
600
  const definitionId =
562
601
  explicitId === undefined
563
- ? `${namespace}-${call.start}`
564
- : Identity.requireId(explicitId, 'style')
602
+ ? `${cssNamespace ? `${cssNamespace}-` : ''}${cssName}`
603
+ : `id-${cssNamespace ? `${cssNamespace}-` : ''}${Identity.requireId(explicitId, 'style').slice(3)}`
565
604
  let argument = call.arguments[0]
566
605
 
567
606
  if (call.arguments.length === 0)
@@ -1305,10 +1344,12 @@ export function extract(options: extract.Options): extract.ReturnType {
1305
1344
  !definition.styles[0]!.targets)
1306
1345
  )
1307
1346
  return undefined
1308
- return Identity.style(definition.styles[0]!)
1347
+ return Identity.style(definition.styles[0]!, cssNamespace)
1309
1348
  })(),
1310
1349
  }
1311
1350
  : {}),
1351
+ cssName,
1352
+ cssNamespace,
1312
1353
  end: call.end,
1313
1354
  name,
1314
1355
  start: call.start,
@@ -1328,6 +1369,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1328
1369
  }
1329
1370
 
1330
1371
  try {
1372
+ let compositionIndex = 0
1331
1373
  for (const entry of options.target === 'native'
1332
1374
  ? []
1333
1375
  : Compositions.collect({
@@ -1339,7 +1381,16 @@ export function extract(options: extract.Options): extract.ReturnType {
1339
1381
  source: options.source,
1340
1382
  styles,
1341
1383
  })) {
1342
- calls.push(...(entry.cases ?? []).map((entry) => entry.call), entry.call)
1384
+ const authored = authoredNames.get(entry.call.start)
1385
+ const name = authored && authored !== 'style' ? authored : 'composition'
1386
+ const cssName = `${name}-${compositionIndex++}-${entry.call.cssName ?? 'style'}`
1387
+ calls.push(
1388
+ ...(entry.cases ?? []).map((value, index) => ({
1389
+ ...value.call,
1390
+ cssName: `${cssName}-${index}`,
1391
+ })),
1392
+ { ...entry.call, cssName },
1393
+ )
1343
1394
  styles.push(
1344
1395
  ...(entry.cases ?? []).map((entry) => entry.style),
1345
1396
  entry.style,
@@ -1483,6 +1534,33 @@ export function extract(options: extract.Options): extract.ReturnType {
1483
1534
  }
1484
1535
  }
1485
1536
 
1537
+ const callsByName = new Map(calls.map((call) => [call.name, call]))
1538
+ const definition = {
1539
+ styles: Object.freeze(styles),
1540
+ [ClassName.labels]: Object.freeze(
1541
+ Object.fromEntries(
1542
+ styles.map((style) => {
1543
+ let name = style.name
1544
+ let call = callsByName.get(name)
1545
+ while (!call && name.includes('-')) {
1546
+ name = name.slice(0, name.lastIndexOf('-'))
1547
+ call = callsByName.get(name)
1548
+ }
1549
+ return [
1550
+ style.name,
1551
+ {
1552
+ name: call?.cssName
1553
+ ? call.cssName + style.name.slice(call.name.length)
1554
+ : style.name,
1555
+ namespace: call?.cssNamespace,
1556
+ },
1557
+ ]
1558
+ }),
1559
+ ),
1560
+ ),
1561
+ }
1562
+ Object.defineProperty(definition, ClassName.labels, { enumerable: false })
1563
+
1486
1564
  return Object.freeze({
1487
1565
  namespaces: contributionData.filter(
1488
1566
  (value): value is Extract<Css.Contribution, { kind: 'namespace' }> =>
@@ -1522,7 +1600,7 @@ export function extract(options: extract.Options): extract.ReturnType {
1522
1600
  )
1523
1601
  }),
1524
1602
  ),
1525
- styles: Object.freeze({ styles: Object.freeze(styles) }),
1603
+ styles: Object.freeze(definition),
1526
1604
  ...(variables.calls.length
1527
1605
  ? { variableCalls: Object.freeze(variables.calls) }
1528
1606
  : {}),
@@ -7,6 +7,7 @@ import * as Token from '../internal/Token.js'
7
7
  import * as Applications from './internal/Applications.js'
8
8
  import type * as Ast from '@oxc-project/types'
9
9
  import * as Css from '../web/Css.js'
10
+ import * as ClassName from '../web/internal/ClassName.js'
10
11
  import * as Expression from './internal/Expression.js'
11
12
  import MagicString from 'magic-string'
12
13
  import * as Mapping from '@jridgewell/gen-mapping'
@@ -71,11 +72,7 @@ export function compile(options: compile.Options): compile.ReturnType {
71
72
  'CSS-only named stylesheet declarations require an explicit id.',
72
73
  )
73
74
  for (const call of extracted.variableCalls ?? [])
74
- if (
75
- Object.values(call.slots).some(
76
- (slot) => !slot.name.startsWith('--z-vid-'),
77
- )
78
- )
75
+ if (!call.explicit)
79
76
  throw new Error('CSS-only output requires an explicit variable id.')
80
77
  }
81
78
 
@@ -198,7 +195,7 @@ export function compile(options: compile.Options): compile.ReturnType {
198
195
  const emitted = Css.compile({
199
196
  [ThemeRules.shared]: options[ThemeRules.shared],
200
197
  development: options.development,
201
- scope: options.moduleId,
198
+ [ClassName.labels]: extracted.styles[ClassName.labels],
202
199
  composition: options.composition,
203
200
  cssOutput: options.cssOutput,
204
201
  names: portable ? portableNames : undefined,
@@ -291,56 +288,19 @@ export function compile(options: compile.Options): compile.ReturnType {
291
288
  `${variables}.create(${JSON.stringify(call.slots.value)})`,
292
289
  )
293
290
 
294
- const first = extracted.calls[0]
295
- const scope = first ? first.name.slice(6, first.name.lastIndexOf('-')) : ''
296
291
  const identities = new Map(
297
292
  extracted.calls
298
293
  .filter((call) => call.identity)
299
294
  .map((call) => [call.name, call.identity!]),
300
295
  )
301
296
 
302
- const modes = new Map(
303
- extracted.styles.styles.map((style) => [style.name, style.cssOutput]),
304
- )
305
- const ownersByClass = new Map<string, string | false>()
306
- for (const [style, value] of Object.entries(emitted.classes))
307
- for (const name of value.split(' ').filter(Boolean))
308
- ownersByClass.set(name, ownersByClass.has(name) ? false : style)
309
-
310
- const names = new Map<string, string>()
311
-
312
- for (const classes of Object.values(emitted.classes))
313
- for (const name of classes.split(' ').filter(Boolean))
314
- names.set(
315
- name,
316
- (() => {
317
- const owner = ownersByClass.get(name)
318
- const identity = owner && identities.get(owner)
319
- if (
320
- (modes.get(owner || '') ?? options.cssOutput) === 'grouped' &&
321
- options.composition === 'independent' &&
322
- name.startsWith('g_') &&
323
- identity &&
324
- !identity.includes(' ')
325
- )
326
- return identity
327
- if (name.startsWith('g_')) return `g_${scope}_${name.slice(2)}`
328
- return name.startsWith('z_base')
329
- ? `z-${scope}-${name.slice(2)}`
330
- : name
331
- })(),
332
- )
333
-
334
297
  const classes = Object.freeze(
335
298
  Object.fromEntries(
336
299
  Object.entries(emitted.classes).map(([name, value]) => [
337
300
  name,
338
301
  [
339
302
  ...new Set([
340
- ...value
341
- .split(' ')
342
- .filter(Boolean)
343
- .map((part) => names.get(part)!),
303
+ ...value.split(' ').filter(Boolean),
344
304
  ...(identities.has(name) &&
345
305
  (!portable || portableNames[name]?.startsWith('z-compose-'))
346
306
  ? [
@@ -930,8 +890,16 @@ export function compile(options: compile.Options): compile.ReturnType {
930
890
  (scoped ? scoped.split('\n') : [])
931
891
  .map((rule, index) => {
932
892
  const line = index + 1 + (prefix ? prefix.split('\n').length : 0)
933
- const brace = rule.indexOf('{')
934
- const name = rule.slice(1, brace)
893
+ const openers = new Map<number, number>()
894
+ const conditionStarts = declarationStarts(rule, true, openers)
895
+ const selectorStart =
896
+ conditionStarts.find((start) => rule[start] === '.') ?? 0
897
+ const brace = openers.get(selectorStart) ?? rule.indexOf('{')
898
+ const name = rule
899
+ .slice(selectorStart + 1, brace)
900
+ .replace(/\\([0-9a-f]+) ?/gi, (_, code: string) =>
901
+ String.fromCodePoint(Number.parseInt(code, 16)),
902
+ )
935
903
  const linkedOwner = linkedOwners.get(name)
936
904
 
937
905
  if (linkedOwner) {
@@ -995,11 +963,11 @@ export function compile(options: compile.Options): compile.ReturnType {
995
963
  return rule
996
964
  }
997
965
 
998
- const selector = `.${names.get(name)!}`
966
+ const selector = `.${ClassName.selector(name)}`
999
967
  const call = owners.get(name)!
1000
968
 
1001
969
  Mapping.addMapping(cssMap, {
1002
- generated: { column: 0, line },
970
+ generated: { column: selectorStart, line },
1003
971
  name: call.name,
1004
972
  original: position(call.start),
1005
973
  source: options.moduleId,
@@ -1071,8 +1039,6 @@ export function compile(options: compile.Options): compile.ReturnType {
1071
1039
 
1072
1040
  const ordered = declarations(style)
1073
1041
  const authored = locations(call.body ?? definitions.get(call.start)!)
1074
- const openers = new Map<number, number>()
1075
- const conditionStarts = declarationStarts(body, true, openers)
1076
1042
  const conditions: string[] = []
1077
1043
 
1078
1044
  function collectConditions(style: Style.NamedStyle) {
@@ -1084,17 +1050,25 @@ export function compile(options: compile.Options): compile.ReturnType {
1084
1050
  }
1085
1051
 
1086
1052
  collectConditions(style)
1087
- let conditionCursor = 0
1053
+ const mappedConditions = new Set<number>()
1088
1054
 
1089
1055
  for (const start of conditionStarts) {
1090
- const condition = body.slice(start, openers.get(start))
1091
- const index = conditions.indexOf(condition, conditionCursor)
1056
+ const condition = rule.slice(start, openers.get(start))
1057
+ const index = conditions.findIndex(
1058
+ (value, index) =>
1059
+ value === condition && !mappedConditions.has(index),
1060
+ )
1092
1061
  const node = conditionNodes[index]
1093
1062
  if (!node) continue
1094
1063
 
1095
- conditionCursor = index + 1
1064
+ mappedConditions.add(index)
1096
1065
  Mapping.addMapping(cssMap, {
1097
- generated: { column: selector.length + start, line },
1066
+ generated: {
1067
+ column:
1068
+ start +
1069
+ (start > brace ? selector.length - (brace - selectorStart) : 0),
1070
+ line,
1071
+ },
1098
1072
  name: options.source.slice(node.key.start, node.key.end),
1099
1073
  original: position(node.key.start),
1100
1074
  source: options.moduleId,
@@ -1124,7 +1098,10 @@ export function compile(options: compile.Options): compile.ReturnType {
1124
1098
  used.add(propertyIndex)
1125
1099
 
1126
1100
  Mapping.addMapping(cssMap, {
1127
- generated: { column: selector.length + start, line },
1101
+ generated: {
1102
+ column: selectorStart + selector.length + start,
1103
+ line,
1104
+ },
1128
1105
  name: declaration.property,
1129
1106
  original: position(location.start),
1130
1107
  source: options.moduleId,
@@ -1132,7 +1109,7 @@ export function compile(options: compile.Options): compile.ReturnType {
1132
1109
  cursor = start + text.length
1133
1110
  }
1134
1111
 
1135
- return selector + body
1112
+ return rule.slice(0, selectorStart) + selector + body
1136
1113
  })
1137
1114
  .join('\n'),
1138
1115
  ]
@@ -1153,10 +1130,11 @@ export function compile(options: compile.Options): compile.ReturnType {
1153
1130
  Mapping.toEncodedMap(cssMap),
1154
1131
  true,
1155
1132
  )
1156
- return Object.freeze({
1133
+ const result = {
1157
1134
  ...(emitted[ThemeRules.shared]
1158
1135
  ? { [ThemeRules.shared]: emitted[ThemeRules.shared] }
1159
1136
  : {}),
1137
+ [ClassName.rules]: emitted[ClassName.rules],
1160
1138
  classes,
1161
1139
  code: portable ? options.source : module.toString(),
1162
1140
  css: namespaced.css,
@@ -1170,7 +1148,9 @@ export function compile(options: compile.Options): compile.ReturnType {
1170
1148
  version: 3 as const,
1171
1149
  },
1172
1150
  vars: emitted.vars,
1173
- })
1151
+ }
1152
+ Object.defineProperty(result, ClassName.rules, { enumerable: false })
1153
+ return Object.freeze(result)
1174
1154
  }
1175
1155
 
1176
1156
  /** Source transform contracts. */
@@ -1187,7 +1167,7 @@ export declare namespace compile {
1187
1167
  readonly composition?: Css.compile.Options['composition']
1188
1168
  /** Default CSS representation for definitions without an explicit mode. */
1189
1169
  readonly cssOutput?: Css.compile.Options['cssOutput']
1190
- /** Stable declaration names for CSS-only development updates. */
1170
+ /** Retains live definitions for development updates. */
1191
1171
  readonly development?: boolean | undefined
1192
1172
  /**
1193
1173
  * Emit the `color-scheme` selection classes beside the theme scopes.
@@ -1206,6 +1186,8 @@ export declare namespace compile {
1206
1186
  readonly classes: Readonly<Record<string, string>>
1207
1187
  /** Rewritten source with imports for surviving props callables. */
1208
1188
  readonly code: string
1189
+ /** Exact emitted rules retained for collision diagnostics. */
1190
+ readonly [ClassName.rules]: Readonly<Record<string, string>>
1209
1191
  /** Ordered, unminified stylesheet text. */
1210
1192
  readonly css: string
1211
1193
  /** Standard stylesheet map with authored selector/declaration locations. */
@@ -90,7 +90,15 @@ export function read(contract: string): readonly Catalog[] {
90
90
  return [...configurations].map(([identity, { entries, storageKey }]) => ({
91
91
  entries: [...entries].map(
92
92
  ([name, scope]) =>
93
- [name, `z_theme-${ThemeValues.encode(scope)}`] as const,
93
+ [
94
+ name,
95
+ ThemeValues.scope(
96
+ scope.startsWith(`${identity}-`)
97
+ ? scope.slice(identity.length + 1)
98
+ : scope,
99
+ identity,
100
+ ),
101
+ ] as const,
94
102
  ),
95
103
  identity,
96
104
  storageKey,
@@ -503,6 +503,13 @@ export function collect(options: collect.Options) {
503
503
  )
504
504
  : undefined
505
505
  const call: Source.Call = {
506
+ cssName: selected
507
+ .map((call) =>
508
+ [call.cssNamespace, call.cssName ?? call.identity ?? 'style']
509
+ .filter(Boolean)
510
+ .join('-'),
511
+ )
512
+ .join('-'),
506
513
  ...(portable(selected)
507
514
  ? {
508
515
  portable: portable(selected),
@@ -162,7 +162,7 @@ export function collect(options: collect.Options): Themes.Link {
162
162
 
163
163
  for (const [key, original] of Object.entries(catalog)) {
164
164
  const name = `${identity}-${key}`
165
- const definition = Token.bind(original, contract)
165
+ const definition = Token.bind(original, contract, key)
166
166
  const tokenType = type({
167
167
  ...values(original.tokens),
168
168
  ...original[Token.definition].queries,
@@ -242,6 +242,7 @@ export function collect(options: collect.Options): Themes.Link {
242
242
 
243
243
  return {}
244
244
  })(),
245
+ ...(input.id !== undefined ? { id: input.id } : {}),
245
246
  ...(input.cssOutput ? { cssOutput: input.cssOutput } : {}),
246
247
  ...(input.defaultLayer !== undefined
247
248
  ? { defaultLayer: input.defaultLayer }