rafters 0.0.39 → 0.0.40

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