rafters 0.0.37 → 0.0.39
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 +414 -60
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -46768,6 +46768,13 @@ var DEFAULT_SEMANTIC_COLOR_MAPPINGS = {
|
|
|
46768
46768
|
};
|
|
46769
46769
|
|
|
46770
46770
|
// ../design-tokens/src/exporters/tailwind.ts
|
|
46771
|
+
var SHADOW_PART_SUFFIX = /-(offset-x|offset-y|blur|spread|color)$/;
|
|
46772
|
+
function isShadowDecomposedPart(name2) {
|
|
46773
|
+
return SHADOW_PART_SUFFIX.test(name2);
|
|
46774
|
+
}
|
|
46775
|
+
function isMediaQueryToken(token) {
|
|
46776
|
+
return typeof token.value === "string" && token.value.startsWith("(");
|
|
46777
|
+
}
|
|
46771
46778
|
function colorRefToString(ref) {
|
|
46772
46779
|
return `${ref.family}-${ref.position}`;
|
|
46773
46780
|
}
|
|
@@ -46965,8 +46972,12 @@ function generateThemeBlock(groups) {
|
|
|
46965
46972
|
for (const token of groups.shadow) {
|
|
46966
46973
|
const value2 = tokenValueToCSS(token);
|
|
46967
46974
|
if (value2 === null) continue;
|
|
46968
|
-
|
|
46969
|
-
|
|
46975
|
+
if (isShadowDecomposedPart(token.name)) {
|
|
46976
|
+
lines.push(` --rafters-${token.name}: ${value2};`);
|
|
46977
|
+
} else {
|
|
46978
|
+
const key = token.name.replace(/^shadow-/, "");
|
|
46979
|
+
lines.push(` --shadow-${key}: ${value2};`);
|
|
46980
|
+
}
|
|
46970
46981
|
}
|
|
46971
46982
|
lines.push("");
|
|
46972
46983
|
}
|
|
@@ -47010,6 +47021,7 @@ function generateThemeBlock(groups) {
|
|
|
47010
47021
|
for (const token of groups.breakpoint) {
|
|
47011
47022
|
const value2 = tokenValueToCSS(token);
|
|
47012
47023
|
if (value2 === null) continue;
|
|
47024
|
+
if (isMediaQueryToken(token)) continue;
|
|
47013
47025
|
lines.push(` --${token.name}: ${value2};`);
|
|
47014
47026
|
}
|
|
47015
47027
|
lines.push("");
|
|
@@ -47218,7 +47230,7 @@ function generateVarsRootBlock(groups) {
|
|
|
47218
47230
|
for (const token of groups.shadow) {
|
|
47219
47231
|
const value2 = tokenValueToCSS(token);
|
|
47220
47232
|
if (value2 === null) continue;
|
|
47221
|
-
lines.push(` --rafters
|
|
47233
|
+
lines.push(` --rafters-${token.name}: ${value2};`);
|
|
47222
47234
|
}
|
|
47223
47235
|
lines.push("");
|
|
47224
47236
|
}
|
|
@@ -47260,6 +47272,7 @@ function generateVarsRootBlock(groups) {
|
|
|
47260
47272
|
for (const token of groups.breakpoint) {
|
|
47261
47273
|
const value2 = tokenValueToCSS(token);
|
|
47262
47274
|
if (value2 === null) continue;
|
|
47275
|
+
if (isMediaQueryToken(token)) continue;
|
|
47263
47276
|
lines.push(` --rafters-${token.name}: ${value2};`);
|
|
47264
47277
|
}
|
|
47265
47278
|
lines.push("");
|
|
@@ -57673,6 +57686,13 @@ function generateMotionTokens(config3, durationDefs, easingDefs, delayDefs) {
|
|
|
57673
57686
|
}
|
|
57674
57687
|
|
|
57675
57688
|
// ../design-tokens/src/generators/radius.ts
|
|
57689
|
+
var CORNERS = ["tl", "tr", "bl", "br"];
|
|
57690
|
+
var CORNER_NAMES = {
|
|
57691
|
+
tl: "top-left",
|
|
57692
|
+
tr: "top-right",
|
|
57693
|
+
bl: "bottom-left",
|
|
57694
|
+
br: "bottom-right"
|
|
57695
|
+
};
|
|
57676
57696
|
function generateRadiusTokens(config3, radiusDefs) {
|
|
57677
57697
|
const tokens = [];
|
|
57678
57698
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -57695,6 +57715,20 @@ function generateRadiusTokens(config3, radiusDefs) {
|
|
|
57695
57715
|
never: ["Change without understanding scale impact"]
|
|
57696
57716
|
}
|
|
57697
57717
|
});
|
|
57718
|
+
for (const corner of CORNERS) {
|
|
57719
|
+
tokens.push({
|
|
57720
|
+
name: `radius-${corner}`,
|
|
57721
|
+
value: "var(--rafters-radius-base)",
|
|
57722
|
+
category: "radius",
|
|
57723
|
+
namespace: "radius",
|
|
57724
|
+
semanticMeaning: `Base ${CORNER_NAMES[corner]} radius - override to affect all scales for this corner`,
|
|
57725
|
+
usageContext: ["designer-override"],
|
|
57726
|
+
dependsOn: ["radius-base"],
|
|
57727
|
+
description: `${CORNER_NAMES[corner]} radius. Defaults to radius-base. Set to 0 for a sharp corner on every component.`,
|
|
57728
|
+
generatedAt: timestamp,
|
|
57729
|
+
containerQueryAware: false
|
|
57730
|
+
});
|
|
57731
|
+
}
|
|
57698
57732
|
for (const scale3 of RADIUS_SCALE) {
|
|
57699
57733
|
const def = radiusDefs[scale3];
|
|
57700
57734
|
if (!def) continue;
|
|
@@ -57715,8 +57749,9 @@ function generateRadiusTokens(config3, radiusDefs) {
|
|
|
57715
57749
|
value2 = `calc(var(--rafters-radius-base) * ${multiplier})`;
|
|
57716
57750
|
mathRelationship = `base \xD7 ${progression.ratio}^${def.step} (\xD7${multiplier})`;
|
|
57717
57751
|
}
|
|
57752
|
+
const scaleName = scale3 === "DEFAULT" ? "radius" : `radius-${scale3}`;
|
|
57718
57753
|
tokens.push({
|
|
57719
|
-
name:
|
|
57754
|
+
name: scaleName,
|
|
57720
57755
|
value: value2,
|
|
57721
57756
|
category: "radius",
|
|
57722
57757
|
namespace: "radius",
|
|
@@ -57730,6 +57765,25 @@ function generateRadiusTokens(config3, radiusDefs) {
|
|
|
57730
57765
|
generatedAt: timestamp,
|
|
57731
57766
|
containerQueryAware: false
|
|
57732
57767
|
});
|
|
57768
|
+
if (def.step !== "none" && def.step !== "full" && scale3 !== "DEFAULT") {
|
|
57769
|
+
const cornerMultiplier = def.step === 0 ? null : Math.round(progression.ratio ** def.step * 1e3) / 1e3;
|
|
57770
|
+
for (const corner of CORNERS) {
|
|
57771
|
+
const cornerValue = cornerMultiplier === null ? `var(--rafters-radius-${corner})` : `calc(var(--rafters-radius-${corner}) * ${cornerMultiplier})`;
|
|
57772
|
+
tokens.push({
|
|
57773
|
+
name: `radius-${scale3}-${corner}`,
|
|
57774
|
+
value: cornerValue,
|
|
57775
|
+
category: "radius",
|
|
57776
|
+
namespace: "radius",
|
|
57777
|
+
semanticMeaning: `${CORNER_NAMES[corner]} radius at ${scale3} scale`,
|
|
57778
|
+
usageContext: def.contexts,
|
|
57779
|
+
scalePosition: scaleIndex,
|
|
57780
|
+
dependsOn: [`radius-${corner}`],
|
|
57781
|
+
description: `${CORNER_NAMES[corner]} radius ${scale3}: derives from radius-${corner} base`,
|
|
57782
|
+
generatedAt: timestamp,
|
|
57783
|
+
containerQueryAware: false
|
|
57784
|
+
});
|
|
57785
|
+
}
|
|
57786
|
+
}
|
|
57733
57787
|
}
|
|
57734
57788
|
return {
|
|
57735
57789
|
namespace: "radius",
|
|
@@ -57786,26 +57840,29 @@ function pxToRem2(px) {
|
|
|
57786
57840
|
const rem = Math.round(px / 16 * 1e3) / 1e3;
|
|
57787
57841
|
return `${rem}rem`;
|
|
57788
57842
|
}
|
|
57789
|
-
|
|
57790
|
-
|
|
57791
|
-
|
|
57792
|
-
|
|
57793
|
-
|
|
57794
|
-
|
|
57795
|
-
|
|
57796
|
-
|
|
57797
|
-
|
|
57798
|
-
|
|
57799
|
-
|
|
57800
|
-
|
|
57801
|
-
|
|
57802
|
-
|
|
57803
|
-
|
|
57804
|
-
|
|
57805
|
-
|
|
57806
|
-
|
|
57807
|
-
}
|
|
57808
|
-
|
|
57843
|
+
var SHADOW_PARTS = ["offset-x", "offset-y", "blur", "spread", "color"];
|
|
57844
|
+
function scalePx(multiplier, baseSpacing) {
|
|
57845
|
+
return Math.round(multiplier * baseSpacing * 100) / 100;
|
|
57846
|
+
}
|
|
57847
|
+
function resolveShadowParts(def, baseSpacing) {
|
|
57848
|
+
return {
|
|
57849
|
+
// Shadows are vertical-only by design (material elevation model)
|
|
57850
|
+
"offset-x": "0rem",
|
|
57851
|
+
"offset-y": pxToRem2(scalePx(def.yOffset, baseSpacing)),
|
|
57852
|
+
blur: pxToRem2(scalePx(def.blur, baseSpacing)),
|
|
57853
|
+
spread: pxToRem2(scalePx(def.spread, baseSpacing)),
|
|
57854
|
+
color: `rgb(0 0 0 / ${def.opacity})`
|
|
57855
|
+
};
|
|
57856
|
+
}
|
|
57857
|
+
function generateInnerShadowValue(inner, baseSpacing) {
|
|
57858
|
+
const y = pxToRem2(scalePx(inner.yOffset, baseSpacing));
|
|
57859
|
+
const blur = pxToRem2(scalePx(inner.blur, baseSpacing));
|
|
57860
|
+
const spread = pxToRem2(scalePx(inner.spread, baseSpacing));
|
|
57861
|
+
return `0 ${y} ${blur} ${spread} rgb(0 0 0 / ${inner.opacity})`;
|
|
57862
|
+
}
|
|
57863
|
+
function buildCompositeFromVars(prefix, innerValue) {
|
|
57864
|
+
const primary = SHADOW_PARTS.map((part) => `var(--rafters-${prefix}-${part})`).join(" ");
|
|
57865
|
+
return innerValue ? `${primary}, ${innerValue}` : primary;
|
|
57809
57866
|
}
|
|
57810
57867
|
function generateShadowTokens(config3, shadowDefs) {
|
|
57811
57868
|
const tokens = [];
|
|
@@ -57830,23 +57887,65 @@ function generateShadowTokens(config3, shadowDefs) {
|
|
|
57830
57887
|
const def = shadowDefs[scale3];
|
|
57831
57888
|
if (!def) continue;
|
|
57832
57889
|
const scaleIndex = SHADOW_SCALE.indexOf(scale3);
|
|
57833
|
-
const
|
|
57890
|
+
const scaleName = scale3 === "DEFAULT" ? "shadow" : `shadow-${scale3}`;
|
|
57891
|
+
if (def.opacity === 0) {
|
|
57892
|
+
tokens.push({
|
|
57893
|
+
name: scaleName,
|
|
57894
|
+
value: "none",
|
|
57895
|
+
category: "shadow",
|
|
57896
|
+
namespace: "shadow",
|
|
57897
|
+
semanticMeaning: def.meaning,
|
|
57898
|
+
usageContext: def.contexts,
|
|
57899
|
+
scalePosition: scaleIndex,
|
|
57900
|
+
progressionSystem: progressionRatio,
|
|
57901
|
+
dependsOn: [],
|
|
57902
|
+
description: `Shadow ${scale3}: ${def.meaning}`,
|
|
57903
|
+
generatedAt: timestamp,
|
|
57904
|
+
containerQueryAware: false,
|
|
57905
|
+
usagePatterns: {
|
|
57906
|
+
do: ["Use for flat elements", "Use for disabled states"],
|
|
57907
|
+
never: ["Use on interactive elements that need depth feedback"]
|
|
57908
|
+
}
|
|
57909
|
+
});
|
|
57910
|
+
continue;
|
|
57911
|
+
}
|
|
57912
|
+
const parts = resolveShadowParts(def, baseSpacingUnit);
|
|
57913
|
+
const partDeps = [];
|
|
57914
|
+
for (const part of SHADOW_PARTS) {
|
|
57915
|
+
const partName = `${scaleName}-${part}`;
|
|
57916
|
+
partDeps.push(partName);
|
|
57917
|
+
tokens.push({
|
|
57918
|
+
name: partName,
|
|
57919
|
+
value: parts[part],
|
|
57920
|
+
category: "shadow",
|
|
57921
|
+
namespace: "shadow",
|
|
57922
|
+
semanticMeaning: `${part} component of ${scale3} shadow`,
|
|
57923
|
+
usageContext: ["designer-override"],
|
|
57924
|
+
scalePosition: scaleIndex,
|
|
57925
|
+
dependsOn: ["shadow-base-unit"],
|
|
57926
|
+
description: `Shadow ${scale3} ${part}: ${parts[part]}. Override to customize this shadow layer.`,
|
|
57927
|
+
generatedAt: timestamp,
|
|
57928
|
+
containerQueryAware: false
|
|
57929
|
+
});
|
|
57930
|
+
}
|
|
57931
|
+
const innerValue = def.innerShadow && def.innerShadow.opacity > 0 ? generateInnerShadowValue(def.innerShadow, baseSpacingUnit) : null;
|
|
57932
|
+
const compositeValue = buildCompositeFromVars(scaleName, innerValue);
|
|
57834
57933
|
tokens.push({
|
|
57835
|
-
name:
|
|
57836
|
-
value:
|
|
57934
|
+
name: scaleName,
|
|
57935
|
+
value: compositeValue,
|
|
57837
57936
|
category: "shadow",
|
|
57838
57937
|
namespace: "shadow",
|
|
57839
57938
|
semanticMeaning: def.meaning,
|
|
57840
57939
|
usageContext: def.contexts,
|
|
57841
57940
|
scalePosition: scaleIndex,
|
|
57842
57941
|
progressionSystem: progressionRatio,
|
|
57843
|
-
dependsOn:
|
|
57844
|
-
description: `Shadow ${scale3}: ${def.meaning}.
|
|
57942
|
+
dependsOn: partDeps,
|
|
57943
|
+
description: `Shadow ${scale3}: ${def.meaning}. Composed from var() refs to ${scaleName}-* tokens.`,
|
|
57845
57944
|
generatedAt: timestamp,
|
|
57846
57945
|
containerQueryAware: false,
|
|
57847
57946
|
usagePatterns: {
|
|
57848
|
-
do:
|
|
57849
|
-
never:
|
|
57947
|
+
do: scaleIndex <= 2 ? ["Use for subtle depth", "Use for cards at rest"] : scaleIndex <= 4 ? ["Use for hovering elements", "Use for focus states"] : ["Use for floating elements", "Use for modals"],
|
|
57948
|
+
never: ["Use shadows that don't match element's semantic depth"]
|
|
57850
57949
|
}
|
|
57851
57950
|
});
|
|
57852
57951
|
}
|
|
@@ -57857,27 +57956,33 @@ function generateShadowTokens(config3, shadowDefs) {
|
|
|
57857
57956
|
{
|
|
57858
57957
|
name: "shadow-primary",
|
|
57859
57958
|
desc: "Primary colored shadow for emphasis",
|
|
57860
|
-
color: "var(--primary)"
|
|
57959
|
+
color: "var(--primary)",
|
|
57960
|
+
colorToken: "primary"
|
|
57861
57961
|
},
|
|
57862
57962
|
{
|
|
57863
57963
|
name: "shadow-destructive",
|
|
57864
57964
|
desc: "Destructive colored shadow for warnings",
|
|
57865
|
-
color: "var(--destructive)"
|
|
57965
|
+
color: "var(--destructive)",
|
|
57966
|
+
colorToken: "destructive"
|
|
57866
57967
|
}
|
|
57867
57968
|
];
|
|
57868
|
-
for (const { name: name2, desc, color } of coloredShadows) {
|
|
57869
|
-
const
|
|
57870
|
-
const blurPx = Math.round(baseDef.blur * baseSpacingUnit * 100) / 100;
|
|
57871
|
-
const spreadPx = Math.round(baseDef.spread * baseSpacingUnit * 100) / 100;
|
|
57969
|
+
for (const { name: name2, desc, color, colorToken } of coloredShadows) {
|
|
57970
|
+
const value2 = `var(--rafters-shadow-offset-x) var(--rafters-shadow-offset-y) var(--rafters-shadow-blur) var(--rafters-shadow-spread) color-mix(in oklch, ${color} ${coloredOpacity * 100}%, transparent)`;
|
|
57872
57971
|
tokens.push({
|
|
57873
57972
|
name: name2,
|
|
57874
|
-
value:
|
|
57973
|
+
value: value2,
|
|
57875
57974
|
category: "shadow",
|
|
57876
57975
|
namespace: "shadow",
|
|
57877
57976
|
semanticMeaning: desc,
|
|
57878
57977
|
usageContext: ["branded-elements", "emphasis"],
|
|
57879
|
-
dependsOn: [
|
|
57880
|
-
|
|
57978
|
+
dependsOn: [
|
|
57979
|
+
"shadow-offset-x",
|
|
57980
|
+
"shadow-offset-y",
|
|
57981
|
+
"shadow-blur",
|
|
57982
|
+
"shadow-spread",
|
|
57983
|
+
colorToken
|
|
57984
|
+
],
|
|
57985
|
+
description: `${desc}. Reuses DEFAULT shadow geometry, swaps color via color-mix.`,
|
|
57881
57986
|
generatedAt: timestamp,
|
|
57882
57987
|
containerQueryAware: false
|
|
57883
57988
|
});
|
|
@@ -59853,6 +59958,7 @@ When onboarding an existing project, do NOT skip the learning step.
|
|
|
59853
59958
|
6. The 11 semantic families (primary, secondary, tertiary, accent, neutral, success, warning, destructive, info, highlight, muted) MUST all be mapped. Extra colors are custom families in the color namespace.
|
|
59854
59959
|
7. If analyze detects color scale patterns (e.g., --color-blaze-50 through --color-blaze-950), map the family using its base color. Do NOT create 11 individual tokens.
|
|
59855
59960
|
8. Call rafters_onboard map to execute the migration once the designer confirms. Colors are automatically enriched with full OKLCH scales, harmonies, accessibility data, and API intelligence.
|
|
59961
|
+
9. AFTER mapping color families, check if semantic surface tokens (background, foreground, card, popover, etc.) need remapping. By default they reference "neutral" family. For dark-themed sites or custom palettes, remap them using the "light" and "dark" fields in the mapping: { source: "--bg", target: "background", light: "neutral-50", dark: "custom-dark-950", reason: "..." }. The light/dark values are "family-position" references to existing color tokens. Map color families FIRST, then remap semantic tokens that reference them.
|
|
59856
59962
|
|
|
59857
59963
|
When in doubt: less code, not more. Rafters has already made the design decision.`;
|
|
59858
59964
|
var CONSUMER_QUICKSTART = {
|
|
@@ -60246,6 +60352,10 @@ var TOOL_DEFINITIONS = [
|
|
|
60246
60352
|
category: {
|
|
60247
60353
|
type: "string",
|
|
60248
60354
|
description: 'Token category (required for create). E.g., "color", "spacing", "font".'
|
|
60355
|
+
},
|
|
60356
|
+
dark: {
|
|
60357
|
+
type: "string",
|
|
60358
|
+
description: 'Dark mode color reference as "family-position" (e.g., "neutral-950"). For semantic tokens, sets dependsOn[1] so the CSS dark mode layer uses this reference instead of the light value.'
|
|
60249
60359
|
}
|
|
60250
60360
|
},
|
|
60251
60361
|
required: ["name"]
|
|
@@ -60273,7 +60383,7 @@ var TOOL_DEFINITIONS = [
|
|
|
60273
60383
|
},
|
|
60274
60384
|
{
|
|
60275
60385
|
name: "rafters_onboard",
|
|
60276
|
-
description: 'Analyze an existing project for design decisions and map them into Rafters tokens. Use "analyze" to surface raw findings. Use "map" to execute -- but map REQUIRES the designer to confirm every mapping first. The tool will reject unconfirmed mappings and instruct you to ask the designer.
|
|
60386
|
+
description: 'Analyze an existing project for design decisions and map them into Rafters tokens. Use "analyze" to surface raw findings. Use "map" to execute -- but map REQUIRES the designer to confirm every mapping first. The tool will reject unconfirmed mappings and instruct you to ask the designer. Supports two mapping types: (1) color family mapping with "value" field (enriches CSS color into full ColorValue), (2) semantic remapping with "light"/"dark" fields (remaps which color family+position a semantic token like "background" or "card" references for light/dark mode). Map color families first, then remap semantic surface tokens.',
|
|
60277
60387
|
inputSchema: {
|
|
60278
60388
|
type: "object",
|
|
60279
60389
|
properties: {
|
|
@@ -60301,7 +60411,15 @@ var TOOL_DEFINITIONS = [
|
|
|
60301
60411
|
},
|
|
60302
60412
|
value: {
|
|
60303
60413
|
type: "string",
|
|
60304
|
-
description: "The value to set (from the original CSS)"
|
|
60414
|
+
description: "The CSS color value to set (from the original CSS). Required for color family mappings. Omit for semantic remappings that use light/dark instead."
|
|
60415
|
+
},
|
|
60416
|
+
light: {
|
|
60417
|
+
type: "string",
|
|
60418
|
+
description: 'Light mode color reference as "family-position" (e.g., "neutral-50"). Used for semantic token remapping -- tells the token which color family+position to use in light mode.'
|
|
60419
|
+
},
|
|
60420
|
+
dark: {
|
|
60421
|
+
type: "string",
|
|
60422
|
+
description: 'Dark mode color reference as "family-position" (e.g., "neutral-950"). Used for semantic token remapping -- tells the token which color family+position to use in dark mode.'
|
|
60305
60423
|
},
|
|
60306
60424
|
reason: {
|
|
60307
60425
|
type: "string",
|
|
@@ -60316,7 +60434,7 @@ var TOOL_DEFINITIONS = [
|
|
|
60316
60434
|
description: "Category for new tokens (required if token does not exist)"
|
|
60317
60435
|
}
|
|
60318
60436
|
},
|
|
60319
|
-
required: ["source", "target", "
|
|
60437
|
+
required: ["source", "target", "reason"]
|
|
60320
60438
|
},
|
|
60321
60439
|
description: "Array of mappings to execute (required for map action)"
|
|
60322
60440
|
}
|
|
@@ -60936,6 +61054,19 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
60936
61054
|
}
|
|
60937
61055
|
}
|
|
60938
61056
|
// ==================== Token Write Operations ====================
|
|
61057
|
+
static VALID_SCALE_POSITIONS = /^(50|100|200|300|400|500|600|700|800|900|950)$/;
|
|
61058
|
+
/**
|
|
61059
|
+
* Parse "family-position" string (e.g., "neutral-950") into { family, position }.
|
|
61060
|
+
* Returns null if the string is not a valid color reference.
|
|
61061
|
+
*/
|
|
61062
|
+
static parseColorRef(ref) {
|
|
61063
|
+
const lastDash = ref.lastIndexOf("-");
|
|
61064
|
+
if (lastDash <= 0) return null;
|
|
61065
|
+
const position = ref.slice(lastDash + 1);
|
|
61066
|
+
const family = ref.slice(0, lastDash);
|
|
61067
|
+
if (!_RaftersToolHandler.VALID_SCALE_POSITIONS.test(position)) return null;
|
|
61068
|
+
return { family, position };
|
|
61069
|
+
}
|
|
60939
61070
|
/**
|
|
60940
61071
|
* Handle set, create, and reset actions for rafters_token.
|
|
60941
61072
|
* Loads the full registry, mutates, cascades, persists, and regenerates outputs.
|
|
@@ -60944,6 +61075,7 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
60944
61075
|
const name2 = args.name;
|
|
60945
61076
|
const reason = args.reason;
|
|
60946
61077
|
const value2 = args.value;
|
|
61078
|
+
const dark = args.dark;
|
|
60947
61079
|
if (!reason) {
|
|
60948
61080
|
return {
|
|
60949
61081
|
content: [
|
|
@@ -60989,14 +61121,64 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
60989
61121
|
isError: true
|
|
60990
61122
|
};
|
|
60991
61123
|
}
|
|
61124
|
+
if (dark) {
|
|
61125
|
+
if (existing.namespace !== "semantic") {
|
|
61126
|
+
return {
|
|
61127
|
+
content: [
|
|
61128
|
+
{
|
|
61129
|
+
type: "text",
|
|
61130
|
+
text: JSON.stringify({
|
|
61131
|
+
error: `The "dark" parameter only applies to semantic color tokens. Token "${name2}" is in the "${existing.namespace}" namespace.`
|
|
61132
|
+
})
|
|
61133
|
+
}
|
|
61134
|
+
],
|
|
61135
|
+
isError: true
|
|
61136
|
+
};
|
|
61137
|
+
}
|
|
61138
|
+
if (!_RaftersToolHandler.parseColorRef(dark)) {
|
|
61139
|
+
return {
|
|
61140
|
+
content: [
|
|
61141
|
+
{
|
|
61142
|
+
type: "text",
|
|
61143
|
+
text: JSON.stringify({
|
|
61144
|
+
error: `Invalid dark reference "${dark}". Use format "family-position" (e.g., "neutral-950"). Valid positions: 50, 100-900 by 100, 950.`
|
|
61145
|
+
})
|
|
61146
|
+
}
|
|
61147
|
+
],
|
|
61148
|
+
isError: true
|
|
61149
|
+
};
|
|
61150
|
+
}
|
|
61151
|
+
}
|
|
60992
61152
|
const previousValue = existing.value;
|
|
60993
61153
|
existing.userOverride = {
|
|
60994
61154
|
previousValue: typeof previousValue === "string" ? previousValue : JSON.stringify(previousValue),
|
|
60995
61155
|
reason
|
|
60996
61156
|
};
|
|
60997
|
-
|
|
61157
|
+
const parsed = existing.namespace === "semantic" && typeof value2 === "string" ? _RaftersToolHandler.parseColorRef(value2) : null;
|
|
61158
|
+
if (existing.namespace === "semantic" && typeof value2 === "string" && !parsed) {
|
|
61159
|
+
return {
|
|
61160
|
+
content: [
|
|
61161
|
+
{
|
|
61162
|
+
type: "text",
|
|
61163
|
+
text: JSON.stringify({
|
|
61164
|
+
error: `Semantic token "${name2}" requires a color reference in "family-position" format (e.g., "neutral-50"), not "${value2}". Use rafters_vocabulary to find available color families.`
|
|
61165
|
+
})
|
|
61166
|
+
}
|
|
61167
|
+
],
|
|
61168
|
+
isError: true
|
|
61169
|
+
};
|
|
61170
|
+
}
|
|
61171
|
+
if (parsed) {
|
|
61172
|
+
existing.value = parsed;
|
|
61173
|
+
const lightRefStr = `${parsed.family}-${parsed.position}`;
|
|
61174
|
+
const darkRef = dark ?? existing.dependsOn?.[1] ?? lightRefStr;
|
|
61175
|
+
existing.dependsOn = [lightRefStr, darkRef];
|
|
61176
|
+
} else {
|
|
61177
|
+
existing.value = value2;
|
|
61178
|
+
}
|
|
61179
|
+
await registry2.setToken(existing);
|
|
60998
61180
|
const affected = this.getAffectedTokens(registry2, name2);
|
|
60999
|
-
await this.regenerateOutputs(registry2);
|
|
61181
|
+
const outputFiles = await this.regenerateOutputs(registry2);
|
|
61000
61182
|
return {
|
|
61001
61183
|
content: [
|
|
61002
61184
|
{
|
|
@@ -61006,7 +61188,13 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61006
61188
|
action: "set",
|
|
61007
61189
|
name: name2,
|
|
61008
61190
|
reason,
|
|
61009
|
-
|
|
61191
|
+
persisted: {
|
|
61192
|
+
value: existing.value,
|
|
61193
|
+
dependsOn: existing.dependsOn,
|
|
61194
|
+
namespace: existing.namespace
|
|
61195
|
+
},
|
|
61196
|
+
cascaded: affected,
|
|
61197
|
+
outputFiles
|
|
61010
61198
|
})
|
|
61011
61199
|
}
|
|
61012
61200
|
]
|
|
@@ -61063,7 +61251,7 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61063
61251
|
};
|
|
61064
61252
|
registry2.add(newToken);
|
|
61065
61253
|
await this.adapter.save(registry2.list());
|
|
61066
|
-
await this.regenerateOutputs(registry2);
|
|
61254
|
+
const outputFiles = await this.regenerateOutputs(registry2);
|
|
61067
61255
|
return {
|
|
61068
61256
|
content: [
|
|
61069
61257
|
{
|
|
@@ -61073,7 +61261,13 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61073
61261
|
action: "create",
|
|
61074
61262
|
name: name2,
|
|
61075
61263
|
namespace,
|
|
61076
|
-
reason
|
|
61264
|
+
reason,
|
|
61265
|
+
persisted: {
|
|
61266
|
+
value: newToken.value,
|
|
61267
|
+
dependsOn: newToken.dependsOn,
|
|
61268
|
+
namespace: newToken.namespace
|
|
61269
|
+
},
|
|
61270
|
+
outputFiles
|
|
61077
61271
|
})
|
|
61078
61272
|
}
|
|
61079
61273
|
]
|
|
@@ -61090,8 +61284,9 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61090
61284
|
};
|
|
61091
61285
|
}
|
|
61092
61286
|
await registry2.set(name2, COMPUTED);
|
|
61287
|
+
const resolved = registry2.get(name2);
|
|
61093
61288
|
const affected = this.getAffectedTokens(registry2, name2);
|
|
61094
|
-
await this.regenerateOutputs(registry2);
|
|
61289
|
+
const outputFiles = await this.regenerateOutputs(registry2);
|
|
61095
61290
|
return {
|
|
61096
61291
|
content: [
|
|
61097
61292
|
{
|
|
@@ -61101,7 +61296,13 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61101
61296
|
action: "reset",
|
|
61102
61297
|
name: name2,
|
|
61103
61298
|
reason,
|
|
61104
|
-
|
|
61299
|
+
persisted: {
|
|
61300
|
+
value: resolved?.value,
|
|
61301
|
+
dependsOn: resolved?.dependsOn,
|
|
61302
|
+
namespace: resolved?.namespace
|
|
61303
|
+
},
|
|
61304
|
+
cascaded: affected,
|
|
61305
|
+
outputFiles
|
|
61105
61306
|
})
|
|
61106
61307
|
}
|
|
61107
61308
|
]
|
|
@@ -61137,10 +61338,11 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61137
61338
|
return affected;
|
|
61138
61339
|
}
|
|
61139
61340
|
/**
|
|
61140
|
-
* Regenerate output files (CSS, TS, DTCG) from registry state
|
|
61341
|
+
* Regenerate output files (CSS, TS, DTCG) from registry state.
|
|
61342
|
+
* Returns list of files written so callers can report what changed.
|
|
61141
61343
|
*/
|
|
61142
61344
|
async regenerateOutputs(registry2) {
|
|
61143
|
-
if (!this.projectRoot) return;
|
|
61345
|
+
if (!this.projectRoot) return [];
|
|
61144
61346
|
const paths = getRaftersPaths(this.projectRoot);
|
|
61145
61347
|
const config3 = await this.loadConfig();
|
|
61146
61348
|
const exports = config3?.exports ?? {
|
|
@@ -61150,20 +61352,28 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61150
61352
|
compiled: false
|
|
61151
61353
|
};
|
|
61152
61354
|
const shadcn = config3?.shadcn ?? false;
|
|
61355
|
+
const written = [];
|
|
61153
61356
|
await mkdir4(paths.output, { recursive: true });
|
|
61154
61357
|
if (exports.tailwind) {
|
|
61155
61358
|
const darkMode = config3?.darkMode ?? "class";
|
|
61156
61359
|
const css3 = registryToTailwind(registry2, { includeImport: !shadcn, darkMode });
|
|
61157
|
-
|
|
61360
|
+
const cssPath = join10(paths.output, "rafters.css");
|
|
61361
|
+
await writeFile4(cssPath, css3);
|
|
61362
|
+
written.push(relative2(this.projectRoot, cssPath));
|
|
61158
61363
|
}
|
|
61159
61364
|
if (exports.typescript) {
|
|
61160
61365
|
const ts = registryToTypeScript(registry2, { includeJSDoc: true });
|
|
61161
|
-
|
|
61366
|
+
const tsPath = join10(paths.output, "rafters.ts");
|
|
61367
|
+
await writeFile4(tsPath, ts);
|
|
61368
|
+
written.push(relative2(this.projectRoot, tsPath));
|
|
61162
61369
|
}
|
|
61163
61370
|
if (exports.dtcg) {
|
|
61164
61371
|
const json3 = toDTCG(registry2.list());
|
|
61165
|
-
|
|
61372
|
+
const jsonPath = join10(paths.output, "rafters.json");
|
|
61373
|
+
await writeFile4(jsonPath, JSON.stringify(json3, null, 2));
|
|
61374
|
+
written.push(relative2(this.projectRoot, jsonPath));
|
|
61166
61375
|
}
|
|
61376
|
+
return written;
|
|
61167
61377
|
}
|
|
61168
61378
|
// ==================== Tool 6: Onboard ====================
|
|
61169
61379
|
/**
|
|
@@ -61349,6 +61559,20 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61349
61559
|
(s) => s.status === "designer"
|
|
61350
61560
|
).length;
|
|
61351
61561
|
const totalFamilies = _RaftersToolHandler.SEMANTIC_FAMILIES.length;
|
|
61562
|
+
const hasDarkMode = cssFindings.some(
|
|
61563
|
+
(f) => f.customProperties.some(
|
|
61564
|
+
(p2) => p2.context === ".dark" || p2.context === "prefers-color-scheme: dark"
|
|
61565
|
+
)
|
|
61566
|
+
);
|
|
61567
|
+
let guidance;
|
|
61568
|
+
if (detectedFamilies.length > 0) {
|
|
61569
|
+
guidance = `Found ${detectedFamilies.length} color scale pattern(s): ${detectedFamilies.map((f) => f.family).join(", ")}. Map each family using its base color (position 500/600), not individual scale positions. buildColorValue() will regenerate the full 11-step scale.`;
|
|
61570
|
+
} else {
|
|
61571
|
+
guidance = 'Review the custom properties above. Map each to a rafters token using rafters_onboard with action: "map". For ambiguous decisions, ask the designer.';
|
|
61572
|
+
}
|
|
61573
|
+
if (hasDarkMode) {
|
|
61574
|
+
guidance += ' DARK MODE DETECTED: After mapping color families, remap semantic surface tokens (background, foreground, card, popover, etc.) to point at the correct family+position for dark mode. Use the "light" and "dark" fields in the mapping instead of "value". Default semantic tokens reference "neutral" family -- if the project uses a different dark palette, these must be remapped.';
|
|
61575
|
+
}
|
|
61352
61576
|
const result = {
|
|
61353
61577
|
framework,
|
|
61354
61578
|
cssFiles: cssFindings,
|
|
@@ -61358,7 +61582,8 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61358
61582
|
shadcn,
|
|
61359
61583
|
designDependencies: designDeps,
|
|
61360
61584
|
existingTokenCount,
|
|
61361
|
-
|
|
61585
|
+
hasDarkMode,
|
|
61586
|
+
guidance
|
|
61362
61587
|
};
|
|
61363
61588
|
return {
|
|
61364
61589
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
@@ -61537,15 +61762,133 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61537
61762
|
const registry2 = new TokenRegistry(allTokens);
|
|
61538
61763
|
registry2.setAdapter(this.adapter);
|
|
61539
61764
|
const results = [];
|
|
61765
|
+
const parseRef = _RaftersToolHandler.parseColorRef;
|
|
61540
61766
|
for (const mapping of mappings) {
|
|
61541
61767
|
const { source, target, value: value2, reason, namespace, category } = mapping;
|
|
61542
|
-
|
|
61768
|
+
const lightRef = mapping.light;
|
|
61769
|
+
const darkRef = mapping.dark;
|
|
61770
|
+
if (!source || !target || !reason) {
|
|
61543
61771
|
results.push({
|
|
61544
61772
|
source: source ?? "?",
|
|
61545
61773
|
target: target ?? "?",
|
|
61546
61774
|
action: "skipped",
|
|
61547
61775
|
ok: false,
|
|
61548
|
-
error: "Missing required fields: source, target,
|
|
61776
|
+
error: "Missing required fields: source, target, reason"
|
|
61777
|
+
});
|
|
61778
|
+
continue;
|
|
61779
|
+
}
|
|
61780
|
+
if (lightRef || darkRef) {
|
|
61781
|
+
const existing = registry2.get(target);
|
|
61782
|
+
if (!existing) {
|
|
61783
|
+
results.push({
|
|
61784
|
+
source,
|
|
61785
|
+
target,
|
|
61786
|
+
action: "skipped",
|
|
61787
|
+
ok: false,
|
|
61788
|
+
error: `Semantic token "${target}" not found. Only existing semantic tokens can be remapped.`
|
|
61789
|
+
});
|
|
61790
|
+
continue;
|
|
61791
|
+
}
|
|
61792
|
+
const currentValue = existing.value;
|
|
61793
|
+
const currentLight = typeof currentValue === "object" && currentValue !== null && "family" in currentValue ? currentValue : null;
|
|
61794
|
+
const newLight = lightRef ? parseRef(lightRef) : currentLight;
|
|
61795
|
+
if (lightRef && !newLight) {
|
|
61796
|
+
results.push({
|
|
61797
|
+
source,
|
|
61798
|
+
target,
|
|
61799
|
+
action: "skipped",
|
|
61800
|
+
ok: false,
|
|
61801
|
+
error: `Invalid light reference "${lightRef}". Use format "family-position" (e.g., "neutral-50"). Valid positions: 50, 100-900 by 100, 950.`
|
|
61802
|
+
});
|
|
61803
|
+
continue;
|
|
61804
|
+
}
|
|
61805
|
+
if (!lightRef && !currentLight) {
|
|
61806
|
+
results.push({
|
|
61807
|
+
source,
|
|
61808
|
+
target,
|
|
61809
|
+
action: "skipped",
|
|
61810
|
+
ok: false,
|
|
61811
|
+
error: `Token "${target}" has no existing ColorReference value. You must supply an explicit "light" field to remap it.`
|
|
61812
|
+
});
|
|
61813
|
+
continue;
|
|
61814
|
+
}
|
|
61815
|
+
const darkFallbackRef = existing.dependsOn?.[1];
|
|
61816
|
+
const newDark = darkRef ? parseRef(darkRef) : darkFallbackRef ? parseRef(darkFallbackRef) : newLight;
|
|
61817
|
+
if (darkRef && !newDark) {
|
|
61818
|
+
results.push({
|
|
61819
|
+
source,
|
|
61820
|
+
target,
|
|
61821
|
+
action: "skipped",
|
|
61822
|
+
ok: false,
|
|
61823
|
+
error: `Invalid dark reference "${darkRef}". Use format "family-position" (e.g., "neutral-950"). Valid positions: 50, 100-900 by 100, 950.`
|
|
61824
|
+
});
|
|
61825
|
+
continue;
|
|
61826
|
+
}
|
|
61827
|
+
if (!darkRef && darkFallbackRef && !newDark) {
|
|
61828
|
+
results.push({
|
|
61829
|
+
source,
|
|
61830
|
+
target,
|
|
61831
|
+
action: "skipped",
|
|
61832
|
+
ok: false,
|
|
61833
|
+
error: `Could not infer dark reference from existing dependsOn value "${darkFallbackRef}". Supply an explicit "dark" field.`
|
|
61834
|
+
});
|
|
61835
|
+
continue;
|
|
61836
|
+
}
|
|
61837
|
+
if (!newLight || !newDark) {
|
|
61838
|
+
results.push({
|
|
61839
|
+
source,
|
|
61840
|
+
target,
|
|
61841
|
+
action: "skipped",
|
|
61842
|
+
ok: false,
|
|
61843
|
+
error: `Could not resolve light/dark references for "${target}". Supply explicit "light" and "dark" fields.`
|
|
61844
|
+
});
|
|
61845
|
+
continue;
|
|
61846
|
+
}
|
|
61847
|
+
const lightTokenName = `${newLight.family}-${newLight.position}`;
|
|
61848
|
+
const darkTokenName = `${newDark.family}-${newDark.position}`;
|
|
61849
|
+
const missingRefs = [];
|
|
61850
|
+
if (!registry2.has(lightTokenName)) missingRefs.push(lightTokenName);
|
|
61851
|
+
if (!registry2.has(darkTokenName)) missingRefs.push(darkTokenName);
|
|
61852
|
+
if (missingRefs.length > 0) {
|
|
61853
|
+
results.push({
|
|
61854
|
+
source,
|
|
61855
|
+
target,
|
|
61856
|
+
action: "skipped",
|
|
61857
|
+
ok: false,
|
|
61858
|
+
error: `Referenced color tokens not found: ${missingRefs.join(", ")}. Map the color family first, then remap the semantic token.`
|
|
61859
|
+
});
|
|
61860
|
+
continue;
|
|
61861
|
+
}
|
|
61862
|
+
const previousValue = typeof existing.value === "string" ? existing.value : JSON.stringify(existing.value);
|
|
61863
|
+
existing.userOverride = {
|
|
61864
|
+
previousValue,
|
|
61865
|
+
reason: `Remapped from ${source}: ${reason}`
|
|
61866
|
+
};
|
|
61867
|
+
const newColorRef = { family: newLight.family, position: newLight.position };
|
|
61868
|
+
await registry2.setToken({
|
|
61869
|
+
...existing,
|
|
61870
|
+
value: newColorRef,
|
|
61871
|
+
dependsOn: [lightTokenName, darkTokenName]
|
|
61872
|
+
});
|
|
61873
|
+
results.push({
|
|
61874
|
+
source,
|
|
61875
|
+
target,
|
|
61876
|
+
action: "remap",
|
|
61877
|
+
ok: true,
|
|
61878
|
+
persisted: {
|
|
61879
|
+
value: newColorRef,
|
|
61880
|
+
dependsOn: [lightTokenName, darkTokenName]
|
|
61881
|
+
}
|
|
61882
|
+
});
|
|
61883
|
+
continue;
|
|
61884
|
+
}
|
|
61885
|
+
if (!value2) {
|
|
61886
|
+
results.push({
|
|
61887
|
+
source,
|
|
61888
|
+
target,
|
|
61889
|
+
action: "skipped",
|
|
61890
|
+
ok: false,
|
|
61891
|
+
error: 'Missing "value" for color family mapping. Provide a CSS color value, or use "light"/"dark" for semantic remapping.'
|
|
61549
61892
|
});
|
|
61550
61893
|
continue;
|
|
61551
61894
|
}
|
|
@@ -61569,6 +61912,14 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61569
61912
|
};
|
|
61570
61913
|
await registry2.set(target, tokenValue);
|
|
61571
61914
|
results.push({ source, target, action: "set", ok: true, enriched });
|
|
61915
|
+
} else {
|
|
61916
|
+
results.push({
|
|
61917
|
+
source,
|
|
61918
|
+
target,
|
|
61919
|
+
action: "skipped",
|
|
61920
|
+
ok: false,
|
|
61921
|
+
error: `Token "${target}" exists in registry index but could not be retrieved.`
|
|
61922
|
+
});
|
|
61572
61923
|
}
|
|
61573
61924
|
} else {
|
|
61574
61925
|
const ns = namespace ?? (enriched ? "color" : "custom");
|
|
@@ -61589,9 +61940,10 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61589
61940
|
}
|
|
61590
61941
|
}
|
|
61591
61942
|
await this.adapter.save(registry2.list());
|
|
61592
|
-
await this.regenerateOutputs(registry2);
|
|
61943
|
+
const outputFiles = await this.regenerateOutputs(registry2);
|
|
61593
61944
|
const setCount = results.filter((r) => r.action === "set" && r.ok).length;
|
|
61594
61945
|
const createCount = results.filter((r) => r.action === "create" && r.ok).length;
|
|
61946
|
+
const remapCount = results.filter((r) => r.action === "remap" && r.ok).length;
|
|
61595
61947
|
const enrichedCount = results.filter((r) => r.enriched).length;
|
|
61596
61948
|
const failCount = results.filter((r) => !r.ok).length;
|
|
61597
61949
|
return {
|
|
@@ -61604,10 +61956,12 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61604
61956
|
summary: {
|
|
61605
61957
|
set: setCount,
|
|
61606
61958
|
created: createCount,
|
|
61959
|
+
remapped: remapCount,
|
|
61607
61960
|
enriched: enrichedCount,
|
|
61608
61961
|
failed: failCount
|
|
61609
61962
|
},
|
|
61610
|
-
results
|
|
61963
|
+
results,
|
|
61964
|
+
outputFiles
|
|
61611
61965
|
},
|
|
61612
61966
|
null,
|
|
61613
61967
|
2
|