rafters 0.0.39 → 0.0.41

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 (2) hide show
  1. package/dist/index.js +122 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -46944,7 +46944,8 @@ function generateThemeBlock(groups) {
46944
46944
  const value2 = tokenValueToCSS(token);
46945
46945
  if (value2 === null) continue;
46946
46946
  const key = token.name.replace(/^spacing-/, "");
46947
- lines.push(` --spacing-${key}: ${value2};`);
46947
+ const themeValue = value2.replaceAll("var(--rafters-spacing-base)", "var(--spacing-base)");
46948
+ lines.push(` --spacing-${key}: ${themeValue};`);
46948
46949
  }
46949
46950
  lines.push("");
46950
46951
  }
@@ -61412,6 +61413,107 @@ var RaftersToolHandler = class _RaftersToolHandler {
61412
61413
  "highlight",
61413
61414
  "muted"
61414
61415
  ];
61416
+ static SEMANTIC_FAMILY_SET = new Set(
61417
+ _RaftersToolHandler.SEMANTIC_FAMILIES
61418
+ );
61419
+ /** Scale positions indexed 0-10, matching ColorValue.scale array indices */
61420
+ static SCALE_POSITIONS = [
61421
+ "50",
61422
+ "100",
61423
+ "200",
61424
+ "300",
61425
+ "400",
61426
+ "500",
61427
+ "600",
61428
+ "700",
61429
+ "800",
61430
+ "900",
61431
+ "950"
61432
+ ];
61433
+ static positionToIndex(position) {
61434
+ const idx = _RaftersToolHandler.SCALE_POSITIONS.indexOf(
61435
+ position
61436
+ );
61437
+ return idx >= 0 ? idx : 5;
61438
+ }
61439
+ /**
61440
+ * Find an accessible foreground position against a given background position.
61441
+ * Tries AAA first (7:1), falls back to AA (4.5:1), keeps default if both pass.
61442
+ */
61443
+ static findAccessibleFgPosition(bgPosition, defaultFgPosition, aaaPairs, aaPairs) {
61444
+ const bgIdx = _RaftersToolHandler.positionToIndex(bgPosition);
61445
+ const fgIdx = _RaftersToolHandler.positionToIndex(defaultFgPosition);
61446
+ const pairValid = (pairs) => pairs.some(([a2, b2]) => a2 === bgIdx && b2 === fgIdx || a2 === fgIdx && b2 === bgIdx);
61447
+ if (pairValid(aaaPairs) || pairValid(aaPairs)) return defaultFgPosition;
61448
+ const bestPair = aaaPairs.find(([a2]) => a2 === bgIdx) ?? aaPairs.find(([a2]) => a2 === bgIdx);
61449
+ if (bestPair && bestPair[1] !== void 0) {
61450
+ return _RaftersToolHandler.SCALE_POSITIONS[bestPair[1]] ?? defaultFgPosition;
61451
+ }
61452
+ return defaultFgPosition;
61453
+ }
61454
+ /**
61455
+ * When a semantic family is mapped to a color, cascade to all surface tokens
61456
+ * that reference that family. Uses precomputed accessibility data from the
61457
+ * ColorValue to verify WCAG AAA (fall back to AA) compliance for fg/bg pairs.
61458
+ */
61459
+ cascadeSemanticFamily(registry2, familyName, colorFamilyName, results) {
61460
+ const tokensToUpdate = [];
61461
+ const colorFamilyToken = registry2.get(colorFamilyName);
61462
+ const colorValue = colorFamilyToken?.value && typeof colorFamilyToken.value === "object" && "scale" in colorFamilyToken.value ? colorFamilyToken.value : null;
61463
+ const aaaPairs = colorValue?.accessibility?.wcagAAA?.normal ?? [];
61464
+ const aaPairs = colorValue?.accessibility?.wcagAA?.normal ?? [];
61465
+ for (const [name2, mapping] of Object.entries(DEFAULT_SEMANTIC_COLOR_MAPPINGS)) {
61466
+ const belongsToFamily = familyName === "neutral" ? mapping.light.family === "neutral" && mapping.dark.family === "neutral" : name2 === familyName || name2.startsWith(`${familyName}-`);
61467
+ if (!belongsToFamily) continue;
61468
+ const existing = registry2.get(name2);
61469
+ if (!existing) continue;
61470
+ if (existing.userOverride?.reason && !existing.userOverride.reason.startsWith("Auto-cascaded")) {
61471
+ continue;
61472
+ }
61473
+ let lightPos = mapping.light.position;
61474
+ let darkPos = mapping.dark.position;
61475
+ const isForeground = name2.endsWith("-foreground");
61476
+ const tokenFamily = isForeground ? "neutral" : colorFamilyName;
61477
+ if (isForeground && colorValue) {
61478
+ const bgName = name2.replace(/-foreground$/, "");
61479
+ const bgMapping = DEFAULT_SEMANTIC_COLOR_MAPPINGS[bgName];
61480
+ if (bgMapping) {
61481
+ lightPos = _RaftersToolHandler.findAccessibleFgPosition(
61482
+ bgMapping.light.position,
61483
+ lightPos,
61484
+ aaaPairs,
61485
+ aaPairs
61486
+ );
61487
+ darkPos = _RaftersToolHandler.findAccessibleFgPosition(
61488
+ bgMapping.dark.position,
61489
+ darkPos,
61490
+ aaaPairs,
61491
+ aaPairs
61492
+ );
61493
+ }
61494
+ }
61495
+ const lightRef = { family: tokenFamily, position: lightPos };
61496
+ const lightTokenName = `${tokenFamily}-${lightPos}`;
61497
+ const darkTokenName = `${tokenFamily}-${darkPos}`;
61498
+ tokensToUpdate.push({
61499
+ ...existing,
61500
+ value: lightRef,
61501
+ dependsOn: [lightTokenName, darkTokenName],
61502
+ userOverride: {
61503
+ previousValue: typeof existing.value === "string" ? existing.value : JSON.stringify(existing.value),
61504
+ reason: `Auto-cascaded from ${familyName} -> ${colorFamilyName}`
61505
+ }
61506
+ });
61507
+ results.push({
61508
+ source: familyName,
61509
+ target: name2,
61510
+ action: "cascade",
61511
+ ok: true,
61512
+ persisted: { value: lightRef, dependsOn: [lightTokenName, darkTokenName] }
61513
+ });
61514
+ }
61515
+ return tokensToUpdate;
61516
+ }
61415
61517
  /**
61416
61518
  * Handle rafters_onboard tool calls
61417
61519
  */
@@ -61763,6 +61865,7 @@ var RaftersToolHandler = class _RaftersToolHandler {
61763
61865
  registry2.setAdapter(this.adapter);
61764
61866
  const results = [];
61765
61867
  const parseRef = _RaftersToolHandler.parseColorRef;
61868
+ const allCascadeTokens = [];
61766
61869
  for (const mapping of mappings) {
61767
61870
  const { source, target, value: value2, reason, namespace, category } = mapping;
61768
61871
  const lightRef = mapping.light;
@@ -61938,12 +62041,29 @@ var RaftersToolHandler = class _RaftersToolHandler {
61938
62041
  registry2.add(newToken);
61939
62042
  results.push({ source, target, action: "create", ok: true, enriched });
61940
62043
  }
62044
+ if (_RaftersToolHandler.SEMANTIC_FAMILY_SET.has(target)) {
62045
+ if (!enriched) {
62046
+ results.push({
62047
+ source,
62048
+ target,
62049
+ action: "skipped",
62050
+ ok: false,
62051
+ error: `Cascade skipped for "${target}": value was not enriched. Provide a CSS color value so the color family can be created with accessibility data.`
62052
+ });
62053
+ } else {
62054
+ allCascadeTokens.push(...this.cascadeSemanticFamily(registry2, target, target, results));
62055
+ }
62056
+ }
62057
+ }
62058
+ if (allCascadeTokens.length > 0) {
62059
+ await registry2.setTokens(allCascadeTokens);
61941
62060
  }
61942
62061
  await this.adapter.save(registry2.list());
61943
62062
  const outputFiles = await this.regenerateOutputs(registry2);
61944
62063
  const setCount = results.filter((r) => r.action === "set" && r.ok).length;
61945
62064
  const createCount = results.filter((r) => r.action === "create" && r.ok).length;
61946
62065
  const remapCount = results.filter((r) => r.action === "remap" && r.ok).length;
62066
+ const cascadeCount = results.filter((r) => r.action === "cascade" && r.ok).length;
61947
62067
  const enrichedCount = results.filter((r) => r.enriched).length;
61948
62068
  const failCount = results.filter((r) => !r.ok).length;
61949
62069
  return {
@@ -61957,6 +62077,7 @@ var RaftersToolHandler = class _RaftersToolHandler {
61957
62077
  set: setCount,
61958
62078
  created: createCount,
61959
62079
  remapped: remapCount,
62080
+ cascaded: cascadeCount,
61960
62081
  enriched: enrichedCount,
61961
62082
  failed: failCount
61962
62083
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rafters",
3
- "version": "0.0.39",
3
+ "version": "0.0.41",
4
4
  "description": "CLI for Rafters design system - scaffold tokens and add components",
5
5
  "license": "MIT",
6
6
  "type": "module",