rafters 0.0.64 → 0.0.65

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 +295 -346
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -18394,94 +18394,6 @@ function generateHarmony(baseColor) {
18394
18394
  monochromatic
18395
18395
  };
18396
18396
  }
18397
- function generateSemanticColorSuggestions(baseColor) {
18398
- const danger = [
18399
- roundOKLCH({
18400
- l: Math.max(0.55, Math.min(0.7, baseColor.l + 0.1)),
18401
- c: Math.min(0.25, baseColor.c * 1.2),
18402
- h: 15,
18403
- alpha: 1
18404
- }),
18405
- roundOKLCH({
18406
- l: Math.max(0.6, Math.min(0.75, baseColor.l + 0.15)),
18407
- c: Math.min(0.22, baseColor.c * 1.1),
18408
- h: 25,
18409
- alpha: 1
18410
- }),
18411
- roundOKLCH({
18412
- l: Math.max(0.5, Math.min(0.65, baseColor.l + 0.05)),
18413
- c: Math.min(0.23, baseColor.c * 1.15),
18414
- h: 5,
18415
- alpha: 1
18416
- })
18417
- ];
18418
- const success2 = [
18419
- roundOKLCH({
18420
- l: Math.max(0.6, Math.min(0.75, baseColor.l + 0.15)),
18421
- c: Math.min(0.2, baseColor.c * 0.9),
18422
- h: 135,
18423
- alpha: 1
18424
- }),
18425
- roundOKLCH({
18426
- l: Math.max(0.55, Math.min(0.7, baseColor.l + 0.1)),
18427
- c: Math.min(0.22, baseColor.c * 1),
18428
- h: 145,
18429
- alpha: 1
18430
- }),
18431
- roundOKLCH({
18432
- l: Math.max(0.65, Math.min(0.8, baseColor.l + 0.2)),
18433
- c: Math.min(0.24, baseColor.c * 1.1),
18434
- h: 125,
18435
- alpha: 1
18436
- })
18437
- ];
18438
- const warning = [
18439
- roundOKLCH({
18440
- l: Math.max(0.7, Math.min(0.8, baseColor.l + 0.15)),
18441
- c: Math.min(0.2, baseColor.c * 0.95),
18442
- h: 45,
18443
- alpha: 1
18444
- }),
18445
- roundOKLCH({
18446
- l: Math.max(0.75, Math.min(0.85, baseColor.l + 0.2)),
18447
- c: Math.min(0.18, baseColor.c * 0.9),
18448
- h: 55,
18449
- alpha: 1
18450
- }),
18451
- roundOKLCH({
18452
- l: Math.max(0.72, Math.min(0.82, baseColor.l + 0.17)),
18453
- c: Math.min(0.19, baseColor.c * 0.92),
18454
- h: 35,
18455
- alpha: 1
18456
- })
18457
- ];
18458
- const info = [
18459
- roundOKLCH({
18460
- l: Math.max(0.6, Math.min(0.75, baseColor.l + 0.1)),
18461
- c: Math.min(0.2, baseColor.c * 0.9),
18462
- h: 220,
18463
- alpha: 1
18464
- }),
18465
- roundOKLCH({
18466
- l: Math.max(0.55, Math.min(0.7, baseColor.l + 0.05)),
18467
- c: Math.min(0.22, baseColor.c * 1),
18468
- h: 230,
18469
- alpha: 1
18470
- }),
18471
- roundOKLCH({
18472
- l: Math.max(0.5, Math.min(0.65, baseColor.l)),
18473
- c: Math.min(0.25, baseColor.c * 1.1),
18474
- h: 240,
18475
- alpha: 1
18476
- })
18477
- ];
18478
- return {
18479
- danger: danger.map(clampColor),
18480
- success: success2.map(clampColor),
18481
- warning: warning.map(clampColor),
18482
- info: info.map(clampColor)
18483
- };
18484
- }
18485
18397
  function validateScaleGeneration(baseColor) {
18486
18398
  const l = baseColor.l;
18487
18399
  if (l > 0.85) {
@@ -21213,44 +21125,255 @@ var POSITION_TO_INDEX = SCALE_POSITIONS.reduce(
21213
21125
  },
21214
21126
  {}
21215
21127
  );
21216
- var MIN_WCAG_PAIR_DISTANCE = 3;
21217
- function findBestWcagPair(sourceIndex, pairs, wantHigher) {
21218
- let best;
21219
- let bestDistance = -1;
21128
+
21129
+ // ../color-utils/src/semantic.ts
21130
+ var SemanticSelectionError = class extends Error {
21131
+ constructor(familyName, message) {
21132
+ super(`semantic selection: family "${familyName}" ${message}`);
21133
+ this.familyName = familyName;
21134
+ this.name = "SemanticSelectionError";
21135
+ }
21136
+ };
21137
+ var STATE_USES = ["hover", "active", "focus", "disabled"];
21138
+ var STATE_RANK_STEP = {
21139
+ hover: (rank) => rank + 1,
21140
+ active: (rank) => rank + 2,
21141
+ focus: (rank) => rank + 1,
21142
+ disabled: (_rank, ladder) => closestRankTo(ladder, 5)
21143
+ };
21144
+ function partnerForBase(pairs, base) {
21145
+ if (!pairs) return void 0;
21146
+ for (const [p1, p2] of pairs) {
21147
+ if (p1 === base) return p2;
21148
+ if (p2 === base) return p1;
21149
+ }
21150
+ return void 0;
21151
+ }
21152
+ function nearestPartner(pairs, base) {
21153
+ if (!pairs || pairs.length === 0) return void 0;
21154
+ const anchors = /* @__PURE__ */ new Set();
21220
21155
  for (const pair of pairs) {
21221
- if (!pair || pair.length < 2) continue;
21222
- const [a2, b2] = pair;
21223
- if (a2 === void 0 || b2 === void 0) continue;
21224
- let partner;
21225
- if (a2 === sourceIndex) partner = b2;
21226
- else if (b2 === sourceIndex) partner = a2;
21227
- else continue;
21228
- if (wantHigher && partner <= sourceIndex) continue;
21229
- if (!wantHigher && partner >= sourceIndex) continue;
21230
- const distance2 = Math.abs(partner - sourceIndex);
21231
- if (distance2 > bestDistance) {
21156
+ for (const position of pair) anchors.add(position);
21157
+ }
21158
+ let nearest = -1;
21159
+ let bestDistance = Number.POSITIVE_INFINITY;
21160
+ for (const anchor of anchors) {
21161
+ const distance2 = Math.abs(anchor - base);
21162
+ if (distance2 < bestDistance) {
21232
21163
  bestDistance = distance2;
21233
- best = partner;
21164
+ nearest = anchor;
21234
21165
  }
21235
21166
  }
21236
- return best;
21167
+ return nearest === -1 ? void 0 : partnerForBase(pairs, nearest);
21237
21168
  }
21238
- function findDarkCounterpartIndex(lightIndex, colorValue) {
21239
- const aaaPairs = colorValue.accessibility?.wcagAAA?.normal ?? [];
21240
- const aaPairs = colorValue.accessibility?.wcagAA?.normal ?? [];
21241
- if (aaaPairs.length === 0 && aaPairs.length === 0) {
21242
- throw new Error(
21243
- `No WCAG accessibility data available for dark mode counterpart of index ${lightIndex}. ColorValue must include accessibility.wcagAAA or wcagAA pair matrices.`
21244
- );
21169
+ function collectLadder(pairs) {
21170
+ const positions = /* @__PURE__ */ new Set();
21171
+ for (const pair of pairs) {
21172
+ for (const position of pair) positions.add(position);
21245
21173
  }
21246
- const wantHigher = lightIndex <= 5;
21247
- for (const pairs of [aaaPairs, aaPairs]) {
21248
- const match = findBestWcagPair(lightIndex, pairs, wantHigher);
21249
- if (match !== void 0 && Math.abs(match - lightIndex) >= MIN_WCAG_PAIR_DISTANCE) {
21250
- return match;
21174
+ return Array.from(positions).sort((a2, b2) => a2 - b2);
21175
+ }
21176
+ function closestRankTo(ladder, target) {
21177
+ let bestRank = 0;
21178
+ let bestDistance = Number.POSITIVE_INFINITY;
21179
+ for (let rank = 0; rank < ladder.length; rank++) {
21180
+ const position = ladder[rank];
21181
+ if (position === void 0) continue;
21182
+ const distance2 = Math.abs(position - target);
21183
+ if (distance2 < bestDistance) {
21184
+ bestDistance = distance2;
21185
+ bestRank = rank;
21251
21186
  }
21252
21187
  }
21253
- return Math.max(0, Math.min(10, 10 - lightIndex));
21188
+ return bestRank;
21189
+ }
21190
+ function requirePosition(index, familyName) {
21191
+ const position = SCALE_POSITIONS[index];
21192
+ if (!position) {
21193
+ throw new SemanticSelectionError(familyName, `produced invalid scale index ${index}`);
21194
+ }
21195
+ return position;
21196
+ }
21197
+ function requireIndex(position, familyName) {
21198
+ const index = POSITION_TO_INDEX[position];
21199
+ if (index === void 0) {
21200
+ throw new SemanticSelectionError(familyName, `has no scale position "${position}"`);
21201
+ }
21202
+ return index;
21203
+ }
21204
+ var STATUS_ROLE_ANCHORS = {
21205
+ // band is the recognizability range a variant may never leave;
21206
+ // [min > max] means the band wraps through 0 (destructive: 330..360..30).
21207
+ destructive: { hue: 25, l: 0.55, cCap: 0.2, cScale: 1, band: [330, 30] },
21208
+ success: { hue: 145, l: 0.55, cCap: 0.18, cScale: 0.9, band: [120, 160] },
21209
+ warning: { hue: 85, l: 0.75, cCap: 0.18, cScale: 0.9, band: [60, 110] },
21210
+ info: { hue: 230, l: 0.58, cCap: 0.15, cScale: 0.85, band: [200, 250] }
21211
+ };
21212
+ function statusAnchor(role, seed) {
21213
+ const spec = STATUS_ROLE_ANCHORS[role];
21214
+ return roundOKLCH({
21215
+ l: spec.l,
21216
+ c: Math.min(spec.cCap, seed.c * spec.cScale),
21217
+ h: spec.hue,
21218
+ alpha: seed.alpha ?? 1
21219
+ });
21220
+ }
21221
+ function clampHueToBand(hue, band) {
21222
+ const h = (hue % 360 + 360) % 360;
21223
+ const [min, max2] = band;
21224
+ if (min <= max2) return Math.max(min, Math.min(max2, h));
21225
+ if (h >= min || h <= max2) return h;
21226
+ const toMin = Math.abs(h - min);
21227
+ const toMax = Math.abs(h - max2);
21228
+ return toMin < toMax ? min : max2;
21229
+ }
21230
+ var VARIANT_OFFSETS = [
21231
+ { dh: 0, dl: 0 },
21232
+ { dh: 10, dl: 0.05 },
21233
+ { dh: -10, dl: -0.05 }
21234
+ ];
21235
+ function generateSemanticColorSuggestions(baseColor) {
21236
+ const roles = {};
21237
+ for (const role of Object.keys(STATUS_ROLE_ANCHORS)) {
21238
+ const anchor = statusAnchor(role, baseColor);
21239
+ const { band } = STATUS_ROLE_ANCHORS[role];
21240
+ roles[role] = VARIANT_OFFSETS.map(({ dh, dl }) => {
21241
+ const raw = roundOKLCH({
21242
+ l: Math.max(0, Math.min(1, anchor.l + dl)),
21243
+ c: anchor.c,
21244
+ h: clampHueToBand(anchor.h + dh, band),
21245
+ alpha: anchor.alpha ?? 1
21246
+ });
21247
+ return roundOKLCH(toNearestGamut(raw).color);
21248
+ });
21249
+ }
21250
+ return { ...roles, danger: roles.destructive };
21251
+ }
21252
+ function semanticFor(family, options) {
21253
+ const familyName = options?.name ?? family.name;
21254
+ const refs = family;
21255
+ const aaaPairs = family.accessibility?.wcagAAA?.normal;
21256
+ const aaPairs = family.accessibility?.wcagAA?.normal;
21257
+ function foregroundPair(from, level) {
21258
+ const auto = refs.foregroundReferences?.auto;
21259
+ if (auto) {
21260
+ return {
21261
+ from: { family: familyName, position: from },
21262
+ to: { family: auto.family, position: auto.position },
21263
+ standard: level,
21264
+ tier: "reference"
21265
+ };
21266
+ }
21267
+ const base = requireIndex(from, familyName);
21268
+ const exactAAA = partnerForBase(aaaPairs, base);
21269
+ const aaa = exactAAA ?? nearestPartner(aaaPairs, base);
21270
+ const exactAA = partnerForBase(aaPairs, base);
21271
+ const aa = exactAA ?? nearestPartner(aaPairs, base);
21272
+ const partner = level === "AAA" ? aaa ?? aa : aa;
21273
+ if (partner === void 0) {
21274
+ throw new SemanticSelectionError(
21275
+ familyName,
21276
+ `has no WCAG pair partner for position ${from} (accessibility metadata required)`
21277
+ );
21278
+ }
21279
+ const fromAAA = level === "AAA" && aaa !== void 0;
21280
+ return {
21281
+ from: { family: familyName, position: from },
21282
+ to: { family: familyName, position: requirePosition(partner, familyName) },
21283
+ standard: fromAAA ? "AAA" : "AA",
21284
+ tier: (fromAAA ? exactAAA : exactAA) !== void 0 ? "pair-exact" : "pair-nearest"
21285
+ };
21286
+ }
21287
+ function statePair(use, from) {
21288
+ const precomputed = refs.stateReferences?.[use];
21289
+ if (precomputed) {
21290
+ return {
21291
+ from: { family: familyName, position: from },
21292
+ to: { family: precomputed.family, position: String(precomputed.position) },
21293
+ standard: "AAA",
21294
+ tier: "reference"
21295
+ };
21296
+ }
21297
+ if (!aaaPairs || aaaPairs.length === 0) {
21298
+ throw new SemanticSelectionError(
21299
+ familyName,
21300
+ "has no accessibility.wcagAAA.normal ladder (color generator must emit accessibility metadata)"
21301
+ );
21302
+ }
21303
+ const base = requireIndex(from, familyName);
21304
+ const ladder = collectLadder(aaaPairs);
21305
+ const baseRank = closestRankTo(ladder, base);
21306
+ const targetRank = STATE_RANK_STEP[use](baseRank, ladder);
21307
+ const clampedRank = Math.max(0, Math.min(ladder.length - 1, targetRank));
21308
+ const targetIndex = ladder[clampedRank];
21309
+ if (targetIndex === void 0) {
21310
+ throw new SemanticSelectionError(familyName, `ladder lookup failed at rank ${clampedRank}`);
21311
+ }
21312
+ return {
21313
+ from: { family: familyName, position: from },
21314
+ to: { family: familyName, position: requirePosition(targetIndex, familyName) },
21315
+ standard: "AAA",
21316
+ tier: "ladder"
21317
+ };
21318
+ }
21319
+ function invert(pair) {
21320
+ if (pair.to.family !== familyName && pair.tier !== "reference") {
21321
+ throw new SemanticSelectionError(
21322
+ familyName,
21323
+ `cannot invert a pair whose legs belong to "${pair.from.family}"/"${pair.to.family}"`
21324
+ );
21325
+ }
21326
+ const fromTarget = 10 - requireIndex(pair.from.position, familyName);
21327
+ const toIndex = POSITION_TO_INDEX[pair.to.position];
21328
+ const toTarget = toIndex === void 0 ? void 0 : 10 - toIndex;
21329
+ for (const [pairs, standard] of [
21330
+ [aaaPairs, "AAA"],
21331
+ [aaPairs, "AA"]
21332
+ ]) {
21333
+ if (!pairs || pairs.length === 0) continue;
21334
+ let best = null;
21335
+ for (const [p1, p2] of pairs) {
21336
+ if (p1 === void 0 || p2 === void 0) continue;
21337
+ for (const [a2, b2] of [
21338
+ [p1, p2],
21339
+ [p2, p1]
21340
+ ]) {
21341
+ const fromDist = Math.abs(a2 - fromTarget);
21342
+ const toDist = toTarget === void 0 ? 0 : Math.abs(b2 - toTarget);
21343
+ const better = best === null || fromDist < best.fromDist || fromDist === best.fromDist && toDist < best.toDist || fromDist === best.fromDist && toDist === best.toDist && a2 < best.from;
21344
+ if (better) best = { from: a2, to: b2, fromDist, toDist };
21345
+ }
21346
+ }
21347
+ if (best) {
21348
+ return {
21349
+ from: { family: familyName, position: requirePosition(best.from, familyName) },
21350
+ to: { family: familyName, position: requirePosition(best.to, familyName) },
21351
+ standard,
21352
+ tier: best.fromDist === 0 && best.toDist === 0 ? "pair-exact" : "pair-nearest"
21353
+ };
21354
+ }
21355
+ }
21356
+ const toFallback = toTarget === void 0 ? fromTarget : toTarget;
21357
+ return {
21358
+ from: { family: familyName, position: requirePosition(fromTarget, familyName) },
21359
+ to: { family: familyName, position: requirePosition(toFallback, familyName) },
21360
+ standard: "none",
21361
+ tier: "inversion"
21362
+ };
21363
+ }
21364
+ return {
21365
+ pair(request) {
21366
+ const level = request.level ?? "AAA";
21367
+ if (request.use === "foreground") return foregroundPair(request.from, level);
21368
+ return statePair(request.use, request.from);
21369
+ },
21370
+ states(from) {
21371
+ const out = {};
21372
+ for (const use of STATE_USES) out[use] = statePair(use, from);
21373
+ return out;
21374
+ },
21375
+ invert
21376
+ };
21254
21377
  }
21255
21378
 
21256
21379
  // ../color-utils/src/builder.ts
@@ -21603,12 +21726,22 @@ var PerceptualWeightSchema = external_exports.object({
21603
21726
  density: external_exports.enum(["light", "medium", "heavy"]),
21604
21727
  balancingRecommendation: external_exports.string()
21605
21728
  });
21606
- var SemanticColorSuggestionsSchema = external_exports.object({
21607
- danger: external_exports.array(OKLCHSchema),
21608
- success: external_exports.array(OKLCHSchema),
21609
- warning: external_exports.array(OKLCHSchema),
21610
- info: external_exports.array(OKLCHSchema)
21611
- });
21729
+ var SemanticColorSuggestionsSchema = external_exports.preprocess(
21730
+ (raw) => {
21731
+ if (raw && typeof raw === "object" && !("destructive" in raw) && "danger" in raw) {
21732
+ return { ...raw, destructive: raw.danger };
21733
+ }
21734
+ return raw;
21735
+ },
21736
+ external_exports.object({
21737
+ destructive: external_exports.array(OKLCHSchema),
21738
+ success: external_exports.array(OKLCHSchema),
21739
+ warning: external_exports.array(OKLCHSchema),
21740
+ info: external_exports.array(OKLCHSchema),
21741
+ /** @deprecated mirror of `destructive`; dies when apps/api leaves the repo */
21742
+ danger: external_exports.array(OKLCHSchema).optional()
21743
+ })
21744
+ );
21612
21745
  var ColorValueSchema = external_exports.object({
21613
21746
  name: external_exports.string(),
21614
21747
  // the fancy name from color-utils, IE ocean-blue
@@ -27376,12 +27509,12 @@ function derivationParent(derivation, suffix = "") {
27376
27509
  return `${derivation.against}${suffix}`;
27377
27510
  }
27378
27511
  }
27379
- function deriveDarkBinding(derivation) {
27512
+ function deriveDarkBinding(derivation, parentName) {
27380
27513
  switch (derivation.kind) {
27381
27514
  case "scale":
27382
27515
  return {
27383
27516
  plugin: "invert",
27384
- input: { familyName: derivation.family, basePosition: derivation.scalePosition }
27517
+ input: { fromToken: parentName }
27385
27518
  };
27386
27519
  case "state":
27387
27520
  return {
@@ -27406,7 +27539,7 @@ function generateSemanticTokens(_config) {
27406
27539
  const binding = derivationToBinding(derivation);
27407
27540
  const parent = derivationParent(derivation);
27408
27541
  const darkName = `${name}--dark`;
27409
- const darkBinding = deriveDarkBinding(derivation);
27542
+ const darkBinding = deriveDarkBinding(derivation, name);
27410
27543
  const darkParent = derivationParent(derivation, "--dark");
27411
27544
  const dependsOn = [parent, darkName];
27412
27545
  tokens.push({
@@ -28883,14 +29016,30 @@ function readEnvelopes(dir) {
28883
29016
  // ../design-tokens/src/plugin.ts
28884
29017
  function resolveFamily(familyName, get3) {
28885
29018
  let resolved = get3(familyName);
28886
- let resolvedName = familyName;
29019
+ let name = familyName;
28887
29020
  if (resolved && typeof resolved === "object" && "family" in resolved && "position" in resolved) {
28888
- resolvedName = resolved.family;
28889
- resolved = get3(resolvedName);
29021
+ name = resolved.family;
29022
+ resolved = get3(name);
28890
29023
  }
28891
- const family = resolved;
28892
- if (!family) return null;
28893
- return { family, resolvedName };
29024
+ if (!resolved || typeof resolved !== "object" || !("scale" in resolved)) return null;
29025
+ return { family: resolved, familyName: name };
29026
+ }
29027
+ function resolveParent(tokenName, get3) {
29028
+ const raw = get3(tokenName);
29029
+ if (!raw || typeof raw !== "object" || !("family" in raw) || !("position" in raw)) return null;
29030
+ const ref = raw;
29031
+ const positionIndex = POSITION_TO_INDEX[ref.position];
29032
+ if (positionIndex === void 0) return null;
29033
+ const result = resolveFamily(ref.family, get3);
29034
+ if (!result) return null;
29035
+ return { ref, positionIndex, ...result };
29036
+ }
29037
+ function requireSemanticParent(tokenName, get3, pluginName) {
29038
+ const resolved = resolveParent(tokenName, get3);
29039
+ if (!resolved) {
29040
+ throw new Error(`${pluginName} plugin: "${tokenName}" could not resolve`);
29041
+ }
29042
+ return { sem: semanticFor(resolved.family, { name: resolved.familyName }), resolved };
28894
29043
  }
28895
29044
  function definePlugin(spec) {
28896
29045
  return {
@@ -28944,132 +29093,32 @@ var ContrastInputSchema = external_exports.object({
28944
29093
  against: external_exports.string(),
28945
29094
  level: external_exports.enum(["AA", "AAA"]).default("AAA")
28946
29095
  });
28947
- function partnerForBase(pairs, basePosition) {
28948
- if (!pairs) return void 0;
28949
- for (const [p1, p2] of pairs) {
28950
- if (p1 === basePosition) return p2;
28951
- if (p2 === basePosition) return p1;
28952
- }
28953
- return void 0;
28954
- }
28955
- function nearestPartner(pairs, basePosition) {
28956
- if (!pairs || pairs.length === 0) return void 0;
28957
- const anchors = /* @__PURE__ */ new Set();
28958
- for (const pair of pairs) {
28959
- for (const position of pair) anchors.add(position);
28960
- }
28961
- if (anchors.size === 0) return void 0;
28962
- let nearest = -1;
28963
- let bestDistance = Number.POSITIVE_INFINITY;
28964
- for (const anchor of anchors) {
28965
- const distance2 = Math.abs(anchor - basePosition);
28966
- if (distance2 < bestDistance) {
28967
- bestDistance = distance2;
28968
- nearest = anchor;
28969
- }
28970
- }
28971
- if (nearest === -1) return void 0;
28972
- return partnerForBase(pairs, nearest);
28973
- }
28974
- function requireScalePosition(index, label) {
28975
- const position = SCALE_POSITIONS[index];
28976
- if (!position) {
28977
- throw new Error(`contrast plugin: invalid scale index ${index} (${label})`);
28978
- }
28979
- return position;
28980
- }
28981
- function isPositionString(value) {
28982
- return typeof value === "string";
28983
- }
28984
- function resolveBasePosition(position) {
28985
- const map2 = {
28986
- "50": 0,
28987
- "100": 1,
28988
- "200": 2,
28989
- "300": 3,
28990
- "400": 4,
28991
- "500": 5,
28992
- "600": 6,
28993
- "700": 7,
28994
- "800": 8,
28995
- "900": 9,
28996
- "950": 10
28997
- };
28998
- const index = map2[position];
28999
- if (index === void 0) {
29000
- throw new Error(`contrast plugin: unknown scale position "${position}"`);
29001
- }
29002
- return index;
29003
- }
29004
29096
  var contrastPlugin = definePlugin({
29005
29097
  name: "contrast",
29006
29098
  inputSchema: ContrastInputSchema,
29007
29099
  outputSchema: ColorReferenceSchema,
29008
29100
  dependsOn: (input2) => [input2.against],
29009
29101
  transform: (input2, get3) => {
29010
- const parent = get3(input2.against);
29011
- if (!parent || typeof parent !== "object" || !("family" in parent) || !("position" in parent)) {
29012
- throw new Error(
29013
- `contrast plugin: parent token "${input2.against}" did not resolve to a ColorReference`
29014
- );
29015
- }
29016
- const parentRef = parent;
29017
- if (!isPositionString(parentRef.position)) {
29018
- throw new Error(
29019
- `contrast plugin: parent token "${input2.against}" position is not a scale string`
29020
- );
29021
- }
29022
- const basePosition = resolveBasePosition(parentRef.position);
29023
- const family = get3(parentRef.family);
29024
- if (!family) {
29025
- throw new Error(
29026
- `contrast plugin: family "${parentRef.family}" (from "${input2.against}") not in registry`
29027
- );
29028
- }
29029
- if (family.foregroundReferences?.auto) {
29030
- const ref = family.foregroundReferences.auto;
29031
- return { family: ref.family, position: ref.position };
29032
- }
29033
- if (family.accessibility) {
29034
- const aaaPartner = partnerForBase(family.accessibility.wcagAAA?.normal, basePosition) ?? nearestPartner(family.accessibility.wcagAAA?.normal, basePosition);
29035
- const aaPartner = partnerForBase(family.accessibility.wcagAA?.normal, basePosition) ?? nearestPartner(family.accessibility.wcagAA?.normal, basePosition);
29036
- const partner = input2.level === "AAA" ? aaaPartner ?? aaPartner : aaPartner;
29037
- if (partner !== void 0) {
29038
- return {
29039
- family: parentRef.family,
29040
- position: requireScalePosition(partner, `${parentRef.family} pair`)
29041
- };
29042
- }
29043
- }
29044
- throw new Error(
29045
- `contrast plugin: family "${parentRef.family}" has no foregroundReferences and no accessibility WCAG pair partner for position ${parentRef.position} (against ${input2.against})`
29046
- );
29102
+ const { sem, resolved } = requireSemanticParent(input2.against, get3, "contrast");
29103
+ const pair = sem.pair({ use: "foreground", from: resolved.ref.position, level: input2.level });
29104
+ return { family: pair.to.family, position: pair.to.position };
29047
29105
  }
29048
29106
  });
29049
29107
 
29050
29108
  // ../design-tokens/src/plugins/invert.ts
29051
29109
  var InvertInputSchema = external_exports.object({
29052
- familyName: external_exports.string(),
29053
- basePosition: external_exports.number().int().min(0).max(10)
29110
+ fromToken: external_exports.string()
29054
29111
  });
29055
29112
  var invertPlugin = definePlugin({
29056
29113
  name: "invert",
29057
29114
  inputSchema: InvertInputSchema,
29058
29115
  outputSchema: ColorReferenceSchema,
29059
- dependsOn: (input2) => [input2.familyName],
29116
+ dependsOn: (input2) => [input2.fromToken],
29060
29117
  transform: (input2, get3) => {
29061
- const result = resolveFamily(input2.familyName, get3);
29062
- if (!result) {
29063
- throw new Error(`invert plugin: family "${input2.familyName}" not found in registry`);
29064
- }
29065
- const darkIndex = findDarkCounterpartIndex(input2.basePosition, result.family);
29066
- const darkPosition = SCALE_POSITIONS[darkIndex];
29067
- if (!darkPosition) {
29068
- throw new Error(
29069
- `invert plugin: invalid dark index ${darkIndex} for base position ${input2.basePosition}`
29070
- );
29071
- }
29072
- return { family: result.resolvedName, position: darkPosition };
29118
+ const { sem, resolved } = requireSemanticParent(input2.fromToken, get3, "invert");
29119
+ const lightPair = sem.pair({ use: "foreground", from: resolved.ref.position });
29120
+ const darkPair = sem.invert(lightPair);
29121
+ return { family: resolved.familyName, position: darkPair.from.position };
29073
29122
  }
29074
29123
  });
29075
29124
 
@@ -29092,7 +29141,7 @@ var scalePlugin = definePlugin({
29092
29141
  if (position === void 0) {
29093
29142
  throw new Error(`scale plugin: invalid position index ${input2.scalePosition}`);
29094
29143
  }
29095
- return { family: result.resolvedName, position };
29144
+ return { family: result.familyName, position };
29096
29145
  }
29097
29146
  });
29098
29147
 
@@ -29102,115 +29151,15 @@ var StateInputSchema = external_exports.object({
29102
29151
  from: external_exports.string(),
29103
29152
  stateType: StateTypeSchema
29104
29153
  });
29105
- var POSITION_TO_INDEX3 = {
29106
- "50": 0,
29107
- "100": 1,
29108
- "200": 2,
29109
- "300": 3,
29110
- "400": 4,
29111
- "500": 5,
29112
- "600": 6,
29113
- "700": 7,
29114
- "800": 8,
29115
- "900": 9,
29116
- "950": 10
29117
- };
29118
- var STEP_BY_STATE = {
29119
- hover: (rank) => rank + 1,
29120
- active: (rank) => rank + 2,
29121
- focus: (rank) => rank + 1,
29122
- disabled: (_rank, ladder) => closestRankToMidpoint(ladder)
29123
- };
29124
- function closestRankToMidpoint(ladder) {
29125
- let bestRank = 0;
29126
- let bestDistance = Number.POSITIVE_INFINITY;
29127
- for (let r = 0; r < ladder.length; r++) {
29128
- const position = ladder[r];
29129
- if (position === void 0) continue;
29130
- const distance2 = Math.abs(position - 5);
29131
- if (distance2 < bestDistance) {
29132
- bestDistance = distance2;
29133
- bestRank = r;
29134
- }
29135
- }
29136
- return bestRank;
29137
- }
29138
- function nearestRankOnLadder(ladder, position) {
29139
- let bestRank = 0;
29140
- let bestDistance = Number.POSITIVE_INFINITY;
29141
- for (let r = 0; r < ladder.length; r++) {
29142
- const candidate = ladder[r];
29143
- if (candidate === void 0) continue;
29144
- const distance2 = Math.abs(candidate - position);
29145
- if (distance2 < bestDistance) {
29146
- bestDistance = distance2;
29147
- bestRank = r;
29148
- }
29149
- }
29150
- return bestRank;
29151
- }
29152
- function collectLadder(pairs) {
29153
- const positions = /* @__PURE__ */ new Set();
29154
- for (const pair of pairs) {
29155
- for (const position of pair) positions.add(position);
29156
- }
29157
- return Array.from(positions).sort((a2, b2) => a2 - b2);
29158
- }
29159
29154
  var statePlugin = definePlugin({
29160
29155
  name: "state",
29161
29156
  inputSchema: StateInputSchema,
29162
29157
  outputSchema: ColorReferenceSchema,
29163
29158
  dependsOn: (input2) => [input2.from],
29164
29159
  transform: (input2, get3) => {
29165
- const parent = get3(input2.from);
29166
- if (!parent || typeof parent !== "object" || !("family" in parent) || !("position" in parent)) {
29167
- throw new Error(
29168
- `state plugin: parent token "${input2.from}" did not resolve to a ColorReference`
29169
- );
29170
- }
29171
- const parentRef = parent;
29172
- if (typeof parentRef.position !== "string") {
29173
- throw new Error(`state plugin: parent token "${input2.from}" position is not a scale string`);
29174
- }
29175
- const basePosition = POSITION_TO_INDEX3[parentRef.position];
29176
- if (basePosition === void 0) {
29177
- throw new Error(
29178
- `state plugin: parent token "${input2.from}" position "${parentRef.position}" is not a known scale step`
29179
- );
29180
- }
29181
- const family = get3(parentRef.family);
29182
- if (!family) {
29183
- throw new Error(
29184
- `state plugin: family "${parentRef.family}" (from "${input2.from}") not in registry`
29185
- );
29186
- }
29187
- const precomputed = family.stateReferences?.[input2.stateType];
29188
- if (precomputed) {
29189
- return { family: precomputed.family, position: String(precomputed.position) };
29190
- }
29191
- const pairs = family.accessibility?.wcagAAA?.normal;
29192
- if (!pairs || pairs.length === 0) {
29193
- throw new Error(
29194
- `state plugin: family "${parentRef.family}" has no accessibility.wcagAAA.normal ladder (color generator must emit accessibility metadata)`
29195
- );
29196
- }
29197
- const ladder = collectLadder(pairs);
29198
- const baseRank = nearestRankOnLadder(ladder, basePosition);
29199
- const targetRank = STEP_BY_STATE[input2.stateType](baseRank, ladder);
29200
- const clampedRank = Math.max(0, Math.min(ladder.length - 1, targetRank));
29201
- const targetIndex = ladder[clampedRank];
29202
- if (targetIndex === void 0) {
29203
- throw new Error(
29204
- `state plugin: ladder lookup failed for rank ${clampedRank} on family "${parentRef.family}"`
29205
- );
29206
- }
29207
- const position = SCALE_POSITIONS[targetIndex];
29208
- if (!position) {
29209
- throw new Error(
29210
- `state plugin: invalid scale index ${targetIndex} for family "${parentRef.family}"`
29211
- );
29212
- }
29213
- return { family: parentRef.family, position };
29160
+ const { sem, resolved } = requireSemanticParent(input2.from, get3, "state");
29161
+ const pair = sem.pair({ use: input2.stateType, from: resolved.ref.position });
29162
+ return { family: pair.to.family, position: pair.to.position };
29214
29163
  }
29215
29164
  });
29216
29165
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rafters",
3
- "version": "0.0.64",
3
+ "version": "0.0.65",
4
4
  "description": "Design Intelligence CLI. Scaffold tokens, import existing shadcn/Tailwind v4 sources, add components, and serve an MCP server so AI agents read decisions instead of guessing.",
5
5
  "homepage": "https://rafters.studio",
6
6
  "license": "MIT",