rafters 0.0.36 → 0.0.38
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 +365 -55
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12829,6 +12829,7 @@ function frameworkToTarget(framework) {
|
|
|
12829
12829
|
if (framework === "astro") return "astro";
|
|
12830
12830
|
return "react";
|
|
12831
12831
|
}
|
|
12832
|
+
var COMPONENT_EXTENSIONS = [".tsx", ".astro", ".vue", ".svelte"];
|
|
12832
12833
|
function targetToExtension(target) {
|
|
12833
12834
|
const map2 = {
|
|
12834
12835
|
react: ".tsx",
|
|
@@ -12838,6 +12839,11 @@ function targetToExtension(target) {
|
|
|
12838
12839
|
};
|
|
12839
12840
|
return map2[target];
|
|
12840
12841
|
}
|
|
12842
|
+
function resolveComponentTarget(config3) {
|
|
12843
|
+
if (config3?.componentTarget) return config3.componentTarget;
|
|
12844
|
+
if (config3?.framework) return frameworkToTarget(config3.framework);
|
|
12845
|
+
return "react";
|
|
12846
|
+
}
|
|
12841
12847
|
async function hasAstroReact(cwd) {
|
|
12842
12848
|
try {
|
|
12843
12849
|
const content = await readFile(join(cwd, "package.json"), "utf-8");
|
|
@@ -13350,9 +13356,7 @@ function getInstalledNames(config3) {
|
|
|
13350
13356
|
return [...names2].sort();
|
|
13351
13357
|
}
|
|
13352
13358
|
function getComponentTarget(config3) {
|
|
13353
|
-
|
|
13354
|
-
if (config3?.framework) return frameworkToTarget(config3.framework);
|
|
13355
|
-
return "react";
|
|
13359
|
+
return resolveComponentTarget(config3);
|
|
13356
13360
|
}
|
|
13357
13361
|
var SHARED_EXTENSIONS = /* @__PURE__ */ new Set([".classes.ts", ".types.ts", ".constants.ts"]);
|
|
13358
13362
|
function isSharedFile(path2) {
|
|
@@ -46764,6 +46768,13 @@ var DEFAULT_SEMANTIC_COLOR_MAPPINGS = {
|
|
|
46764
46768
|
};
|
|
46765
46769
|
|
|
46766
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
|
+
}
|
|
46767
46778
|
function colorRefToString(ref) {
|
|
46768
46779
|
return `${ref.family}-${ref.position}`;
|
|
46769
46780
|
}
|
|
@@ -46961,8 +46972,12 @@ function generateThemeBlock(groups) {
|
|
|
46961
46972
|
for (const token of groups.shadow) {
|
|
46962
46973
|
const value2 = tokenValueToCSS(token);
|
|
46963
46974
|
if (value2 === null) continue;
|
|
46964
|
-
|
|
46965
|
-
|
|
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
|
+
}
|
|
46966
46981
|
}
|
|
46967
46982
|
lines.push("");
|
|
46968
46983
|
}
|
|
@@ -47006,6 +47021,7 @@ function generateThemeBlock(groups) {
|
|
|
47006
47021
|
for (const token of groups.breakpoint) {
|
|
47007
47022
|
const value2 = tokenValueToCSS(token);
|
|
47008
47023
|
if (value2 === null) continue;
|
|
47024
|
+
if (isMediaQueryToken(token)) continue;
|
|
47009
47025
|
lines.push(` --${token.name}: ${value2};`);
|
|
47010
47026
|
}
|
|
47011
47027
|
lines.push("");
|
|
@@ -47214,7 +47230,7 @@ function generateVarsRootBlock(groups) {
|
|
|
47214
47230
|
for (const token of groups.shadow) {
|
|
47215
47231
|
const value2 = tokenValueToCSS(token);
|
|
47216
47232
|
if (value2 === null) continue;
|
|
47217
|
-
lines.push(` --rafters
|
|
47233
|
+
lines.push(` --rafters-${token.name}: ${value2};`);
|
|
47218
47234
|
}
|
|
47219
47235
|
lines.push("");
|
|
47220
47236
|
}
|
|
@@ -47256,6 +47272,7 @@ function generateVarsRootBlock(groups) {
|
|
|
47256
47272
|
for (const token of groups.breakpoint) {
|
|
47257
47273
|
const value2 = tokenValueToCSS(token);
|
|
47258
47274
|
if (value2 === null) continue;
|
|
47275
|
+
if (isMediaQueryToken(token)) continue;
|
|
47259
47276
|
lines.push(` --rafters-${token.name}: ${value2};`);
|
|
47260
47277
|
}
|
|
47261
47278
|
lines.push("");
|
|
@@ -57669,6 +57686,13 @@ function generateMotionTokens(config3, durationDefs, easingDefs, delayDefs) {
|
|
|
57669
57686
|
}
|
|
57670
57687
|
|
|
57671
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
|
+
};
|
|
57672
57696
|
function generateRadiusTokens(config3, radiusDefs) {
|
|
57673
57697
|
const tokens = [];
|
|
57674
57698
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -57691,6 +57715,20 @@ function generateRadiusTokens(config3, radiusDefs) {
|
|
|
57691
57715
|
never: ["Change without understanding scale impact"]
|
|
57692
57716
|
}
|
|
57693
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
|
+
}
|
|
57694
57732
|
for (const scale3 of RADIUS_SCALE) {
|
|
57695
57733
|
const def = radiusDefs[scale3];
|
|
57696
57734
|
if (!def) continue;
|
|
@@ -57711,8 +57749,9 @@ function generateRadiusTokens(config3, radiusDefs) {
|
|
|
57711
57749
|
value2 = `calc(var(--rafters-radius-base) * ${multiplier})`;
|
|
57712
57750
|
mathRelationship = `base \xD7 ${progression.ratio}^${def.step} (\xD7${multiplier})`;
|
|
57713
57751
|
}
|
|
57752
|
+
const scaleName = scale3 === "DEFAULT" ? "radius" : `radius-${scale3}`;
|
|
57714
57753
|
tokens.push({
|
|
57715
|
-
name:
|
|
57754
|
+
name: scaleName,
|
|
57716
57755
|
value: value2,
|
|
57717
57756
|
category: "radius",
|
|
57718
57757
|
namespace: "radius",
|
|
@@ -57726,6 +57765,25 @@ function generateRadiusTokens(config3, radiusDefs) {
|
|
|
57726
57765
|
generatedAt: timestamp,
|
|
57727
57766
|
containerQueryAware: false
|
|
57728
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
|
+
}
|
|
57729
57787
|
}
|
|
57730
57788
|
return {
|
|
57731
57789
|
namespace: "radius",
|
|
@@ -57782,26 +57840,29 @@ function pxToRem2(px) {
|
|
|
57782
57840
|
const rem = Math.round(px / 16 * 1e3) / 1e3;
|
|
57783
57841
|
return `${rem}rem`;
|
|
57784
57842
|
}
|
|
57785
|
-
|
|
57786
|
-
|
|
57787
|
-
|
|
57788
|
-
|
|
57789
|
-
|
|
57790
|
-
|
|
57791
|
-
|
|
57792
|
-
|
|
57793
|
-
|
|
57794
|
-
|
|
57795
|
-
|
|
57796
|
-
|
|
57797
|
-
|
|
57798
|
-
|
|
57799
|
-
|
|
57800
|
-
|
|
57801
|
-
|
|
57802
|
-
|
|
57803
|
-
}
|
|
57804
|
-
|
|
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;
|
|
57805
57866
|
}
|
|
57806
57867
|
function generateShadowTokens(config3, shadowDefs) {
|
|
57807
57868
|
const tokens = [];
|
|
@@ -57826,23 +57887,65 @@ function generateShadowTokens(config3, shadowDefs) {
|
|
|
57826
57887
|
const def = shadowDefs[scale3];
|
|
57827
57888
|
if (!def) continue;
|
|
57828
57889
|
const scaleIndex = SHADOW_SCALE.indexOf(scale3);
|
|
57829
|
-
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);
|
|
57830
57933
|
tokens.push({
|
|
57831
|
-
name:
|
|
57832
|
-
value:
|
|
57934
|
+
name: scaleName,
|
|
57935
|
+
value: compositeValue,
|
|
57833
57936
|
category: "shadow",
|
|
57834
57937
|
namespace: "shadow",
|
|
57835
57938
|
semanticMeaning: def.meaning,
|
|
57836
57939
|
usageContext: def.contexts,
|
|
57837
57940
|
scalePosition: scaleIndex,
|
|
57838
57941
|
progressionSystem: progressionRatio,
|
|
57839
|
-
dependsOn:
|
|
57840
|
-
description: `Shadow ${scale3}: ${def.meaning}.
|
|
57942
|
+
dependsOn: partDeps,
|
|
57943
|
+
description: `Shadow ${scale3}: ${def.meaning}. Composed from var() refs to ${scaleName}-* tokens.`,
|
|
57841
57944
|
generatedAt: timestamp,
|
|
57842
57945
|
containerQueryAware: false,
|
|
57843
57946
|
usagePatterns: {
|
|
57844
|
-
do:
|
|
57845
|
-
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"]
|
|
57846
57949
|
}
|
|
57847
57950
|
});
|
|
57848
57951
|
}
|
|
@@ -57853,27 +57956,33 @@ function generateShadowTokens(config3, shadowDefs) {
|
|
|
57853
57956
|
{
|
|
57854
57957
|
name: "shadow-primary",
|
|
57855
57958
|
desc: "Primary colored shadow for emphasis",
|
|
57856
|
-
color: "var(--primary)"
|
|
57959
|
+
color: "var(--primary)",
|
|
57960
|
+
colorToken: "primary"
|
|
57857
57961
|
},
|
|
57858
57962
|
{
|
|
57859
57963
|
name: "shadow-destructive",
|
|
57860
57964
|
desc: "Destructive colored shadow for warnings",
|
|
57861
|
-
color: "var(--destructive)"
|
|
57965
|
+
color: "var(--destructive)",
|
|
57966
|
+
colorToken: "destructive"
|
|
57862
57967
|
}
|
|
57863
57968
|
];
|
|
57864
|
-
for (const { name: name2, desc, color } of coloredShadows) {
|
|
57865
|
-
const
|
|
57866
|
-
const blurPx = Math.round(baseDef.blur * baseSpacingUnit * 100) / 100;
|
|
57867
|
-
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)`;
|
|
57868
57971
|
tokens.push({
|
|
57869
57972
|
name: name2,
|
|
57870
|
-
value:
|
|
57973
|
+
value: value2,
|
|
57871
57974
|
category: "shadow",
|
|
57872
57975
|
namespace: "shadow",
|
|
57873
57976
|
semanticMeaning: desc,
|
|
57874
57977
|
usageContext: ["branded-elements", "emphasis"],
|
|
57875
|
-
dependsOn: [
|
|
57876
|
-
|
|
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.`,
|
|
57877
57986
|
generatedAt: timestamp,
|
|
57878
57987
|
containerQueryAware: false
|
|
57879
57988
|
});
|
|
@@ -59849,6 +59958,7 @@ When onboarding an existing project, do NOT skip the learning step.
|
|
|
59849
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.
|
|
59850
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.
|
|
59851
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.
|
|
59852
59962
|
|
|
59853
59963
|
When in doubt: less code, not more. Rafters has already made the design decision.`;
|
|
59854
59964
|
var CONSUMER_QUICKSTART = {
|
|
@@ -60269,7 +60379,7 @@ var TOOL_DEFINITIONS = [
|
|
|
60269
60379
|
},
|
|
60270
60380
|
{
|
|
60271
60381
|
name: "rafters_onboard",
|
|
60272
|
-
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.
|
|
60382
|
+
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.',
|
|
60273
60383
|
inputSchema: {
|
|
60274
60384
|
type: "object",
|
|
60275
60385
|
properties: {
|
|
@@ -60297,7 +60407,15 @@ var TOOL_DEFINITIONS = [
|
|
|
60297
60407
|
},
|
|
60298
60408
|
value: {
|
|
60299
60409
|
type: "string",
|
|
60300
|
-
description: "The value to set (from the original CSS)"
|
|
60410
|
+
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."
|
|
60411
|
+
},
|
|
60412
|
+
light: {
|
|
60413
|
+
type: "string",
|
|
60414
|
+
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.'
|
|
60415
|
+
},
|
|
60416
|
+
dark: {
|
|
60417
|
+
type: "string",
|
|
60418
|
+
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.'
|
|
60301
60419
|
},
|
|
60302
60420
|
reason: {
|
|
60303
60421
|
type: "string",
|
|
@@ -60312,7 +60430,7 @@ var TOOL_DEFINITIONS = [
|
|
|
60312
60430
|
description: "Category for new tokens (required if token does not exist)"
|
|
60313
60431
|
}
|
|
60314
60432
|
},
|
|
60315
|
-
required: ["source", "target", "
|
|
60433
|
+
required: ["source", "target", "reason"]
|
|
60316
60434
|
},
|
|
60317
60435
|
description: "Array of mappings to execute (required for map action)"
|
|
60318
60436
|
}
|
|
@@ -60601,12 +60719,32 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
60601
60719
|
return join10(this.projectRoot, "packages/ui/src/components/ui");
|
|
60602
60720
|
}
|
|
60603
60721
|
/**
|
|
60604
|
-
*
|
|
60722
|
+
* Find the actual component file on disk for a given name.
|
|
60723
|
+
* Checks the config's componentTarget extension first, then falls back
|
|
60724
|
+
* to all known extensions so Astro projects with React islands also work.
|
|
60725
|
+
*/
|
|
60726
|
+
async resolveComponentFile(componentsPath, name2) {
|
|
60727
|
+
const config3 = await this.loadConfig();
|
|
60728
|
+
const preferredExt = targetToExtension(resolveComponentTarget(config3));
|
|
60729
|
+
const preferred = join10(componentsPath, `${name2}${preferredExt}`);
|
|
60730
|
+
if (existsSync4(preferred)) return preferred;
|
|
60731
|
+
for (const ext2 of COMPONENT_EXTENSIONS) {
|
|
60732
|
+
if (ext2 === preferredExt) continue;
|
|
60733
|
+
const candidate = join10(componentsPath, `${name2}${ext2}`);
|
|
60734
|
+
if (existsSync4(candidate)) return candidate;
|
|
60735
|
+
}
|
|
60736
|
+
return null;
|
|
60737
|
+
}
|
|
60738
|
+
/**
|
|
60739
|
+
* Load component metadata from source file.
|
|
60740
|
+
* Resolves the actual file extension from the config's componentTarget
|
|
60741
|
+
* and merges variant/size data from .classes.ts companions when present.
|
|
60605
60742
|
*/
|
|
60606
60743
|
async loadComponentMetadata(name2) {
|
|
60607
60744
|
const componentsPath = await this.getComponentsPath();
|
|
60608
60745
|
if (!componentsPath) return null;
|
|
60609
|
-
const filePath =
|
|
60746
|
+
const filePath = await this.resolveComponentFile(componentsPath, name2);
|
|
60747
|
+
if (!filePath) return null;
|
|
60610
60748
|
try {
|
|
60611
60749
|
const source = await readFile6(filePath, "utf-8");
|
|
60612
60750
|
const intelligence = parseJSDocIntelligence(source);
|
|
@@ -60616,16 +60754,28 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
60616
60754
|
jsDocDeps = extractJSDocDependencies(source);
|
|
60617
60755
|
} catch {
|
|
60618
60756
|
}
|
|
60757
|
+
let variants = extractVariants(source);
|
|
60758
|
+
let sizes = extractSizes(source);
|
|
60759
|
+
try {
|
|
60760
|
+
const classesSource = await readFile6(join10(componentsPath, `${name2}.classes.ts`), "utf-8");
|
|
60761
|
+
if (!variants || variants.length === 0) {
|
|
60762
|
+
variants = extractVariants(classesSource);
|
|
60763
|
+
}
|
|
60764
|
+
if (!sizes || sizes.length === 0) {
|
|
60765
|
+
sizes = extractSizes(classesSource);
|
|
60766
|
+
}
|
|
60767
|
+
} catch {
|
|
60768
|
+
}
|
|
60619
60769
|
const metadata = {
|
|
60620
60770
|
name: name2,
|
|
60621
60771
|
displayName: toDisplayName(name2),
|
|
60622
60772
|
category: this.inferCategory(name2),
|
|
60623
|
-
variants
|
|
60624
|
-
sizes
|
|
60773
|
+
variants,
|
|
60774
|
+
sizes,
|
|
60625
60775
|
dependencies: extractDependencies(source),
|
|
60626
60776
|
primitives: extractPrimitiveDependencies(source),
|
|
60627
60777
|
// projectRoot is guaranteed non-null here: handleToolCall guards it
|
|
60628
|
-
filePath: relative2(this.projectRoot,
|
|
60778
|
+
filePath: relative2(this.projectRoot, filePath)
|
|
60629
60779
|
};
|
|
60630
60780
|
if (hasAnyDeps(jsDocDeps)) {
|
|
60631
60781
|
metadata.jsDocDependencies = jsDocDeps;
|
|
@@ -60722,7 +60872,12 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
60722
60872
|
if (componentsPath) {
|
|
60723
60873
|
try {
|
|
60724
60874
|
const files = await readdir3(componentsPath);
|
|
60725
|
-
available = files.filter(
|
|
60875
|
+
available = files.filter(
|
|
60876
|
+
(f) => COMPONENT_EXTENSIONS.some((ext2) => f.endsWith(ext2)) && !f.includes(".classes.")
|
|
60877
|
+
).map((f) => {
|
|
60878
|
+
const ext2 = COMPONENT_EXTENSIONS.find((e) => f.endsWith(e));
|
|
60879
|
+
return ext2 ? basename(f, ext2) : basename(f);
|
|
60880
|
+
}).filter((n2) => n2.includes(name2) || name2.includes(n2)).slice(0, 5);
|
|
60726
60881
|
} catch {
|
|
60727
60882
|
}
|
|
60728
60883
|
}
|
|
@@ -61308,6 +61463,20 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61308
61463
|
(s) => s.status === "designer"
|
|
61309
61464
|
).length;
|
|
61310
61465
|
const totalFamilies = _RaftersToolHandler.SEMANTIC_FAMILIES.length;
|
|
61466
|
+
const hasDarkMode = cssFindings.some(
|
|
61467
|
+
(f) => f.customProperties.some(
|
|
61468
|
+
(p2) => p2.context === ".dark" || p2.context === "prefers-color-scheme: dark"
|
|
61469
|
+
)
|
|
61470
|
+
);
|
|
61471
|
+
let guidance;
|
|
61472
|
+
if (detectedFamilies.length > 0) {
|
|
61473
|
+
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.`;
|
|
61474
|
+
} else {
|
|
61475
|
+
guidance = 'Review the custom properties above. Map each to a rafters token using rafters_onboard with action: "map". For ambiguous decisions, ask the designer.';
|
|
61476
|
+
}
|
|
61477
|
+
if (hasDarkMode) {
|
|
61478
|
+
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.';
|
|
61479
|
+
}
|
|
61311
61480
|
const result = {
|
|
61312
61481
|
framework,
|
|
61313
61482
|
cssFiles: cssFindings,
|
|
@@ -61317,7 +61486,8 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61317
61486
|
shadcn,
|
|
61318
61487
|
designDependencies: designDeps,
|
|
61319
61488
|
existingTokenCount,
|
|
61320
|
-
|
|
61489
|
+
hasDarkMode,
|
|
61490
|
+
guidance
|
|
61321
61491
|
};
|
|
61322
61492
|
return {
|
|
61323
61493
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
@@ -61496,15 +61666,145 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61496
61666
|
const registry2 = new TokenRegistry(allTokens);
|
|
61497
61667
|
registry2.setAdapter(this.adapter);
|
|
61498
61668
|
const results = [];
|
|
61669
|
+
const parseRef = (ref) => {
|
|
61670
|
+
const lastDash = ref.lastIndexOf("-");
|
|
61671
|
+
if (lastDash <= 0) return null;
|
|
61672
|
+
const position = ref.slice(lastDash + 1);
|
|
61673
|
+
const family = ref.slice(0, lastDash);
|
|
61674
|
+
if (!/^(50|100|200|300|400|500|600|700|800|900|950)$/.test(position)) return null;
|
|
61675
|
+
return { family, position };
|
|
61676
|
+
};
|
|
61499
61677
|
for (const mapping of mappings) {
|
|
61500
61678
|
const { source, target, value: value2, reason, namespace, category } = mapping;
|
|
61501
|
-
|
|
61679
|
+
const lightRef = mapping.light;
|
|
61680
|
+
const darkRef = mapping.dark;
|
|
61681
|
+
if (!source || !target || !reason) {
|
|
61502
61682
|
results.push({
|
|
61503
61683
|
source: source ?? "?",
|
|
61504
61684
|
target: target ?? "?",
|
|
61505
61685
|
action: "skipped",
|
|
61506
61686
|
ok: false,
|
|
61507
|
-
error: "Missing required fields: source, target,
|
|
61687
|
+
error: "Missing required fields: source, target, reason"
|
|
61688
|
+
});
|
|
61689
|
+
continue;
|
|
61690
|
+
}
|
|
61691
|
+
if (lightRef || darkRef) {
|
|
61692
|
+
const existing = registry2.get(target);
|
|
61693
|
+
if (!existing) {
|
|
61694
|
+
results.push({
|
|
61695
|
+
source,
|
|
61696
|
+
target,
|
|
61697
|
+
action: "skipped",
|
|
61698
|
+
ok: false,
|
|
61699
|
+
error: `Semantic token "${target}" not found. Only existing semantic tokens can be remapped.`
|
|
61700
|
+
});
|
|
61701
|
+
continue;
|
|
61702
|
+
}
|
|
61703
|
+
const currentValue = existing.value;
|
|
61704
|
+
const currentLight = typeof currentValue === "object" && currentValue !== null && "family" in currentValue ? currentValue : null;
|
|
61705
|
+
const newLight = lightRef ? parseRef(lightRef) : currentLight;
|
|
61706
|
+
if (lightRef && !newLight) {
|
|
61707
|
+
results.push({
|
|
61708
|
+
source,
|
|
61709
|
+
target,
|
|
61710
|
+
action: "skipped",
|
|
61711
|
+
ok: false,
|
|
61712
|
+
error: `Invalid light reference "${lightRef}". Use format "family-position" (e.g., "neutral-50"). Valid positions: 50, 100-900 by 100, 950.`
|
|
61713
|
+
});
|
|
61714
|
+
continue;
|
|
61715
|
+
}
|
|
61716
|
+
if (!lightRef && !currentLight) {
|
|
61717
|
+
results.push({
|
|
61718
|
+
source,
|
|
61719
|
+
target,
|
|
61720
|
+
action: "skipped",
|
|
61721
|
+
ok: false,
|
|
61722
|
+
error: `Token "${target}" has no existing ColorReference value. You must supply an explicit "light" field to remap it.`
|
|
61723
|
+
});
|
|
61724
|
+
continue;
|
|
61725
|
+
}
|
|
61726
|
+
const darkFallbackRef = existing.dependsOn?.[1];
|
|
61727
|
+
const newDark = darkRef ? parseRef(darkRef) : darkFallbackRef ? parseRef(darkFallbackRef) : newLight;
|
|
61728
|
+
if (darkRef && !newDark) {
|
|
61729
|
+
results.push({
|
|
61730
|
+
source,
|
|
61731
|
+
target,
|
|
61732
|
+
action: "skipped",
|
|
61733
|
+
ok: false,
|
|
61734
|
+
error: `Invalid dark reference "${darkRef}". Use format "family-position" (e.g., "neutral-950"). Valid positions: 50, 100-900 by 100, 950.`
|
|
61735
|
+
});
|
|
61736
|
+
continue;
|
|
61737
|
+
}
|
|
61738
|
+
if (!darkRef && darkFallbackRef && !newDark) {
|
|
61739
|
+
results.push({
|
|
61740
|
+
source,
|
|
61741
|
+
target,
|
|
61742
|
+
action: "skipped",
|
|
61743
|
+
ok: false,
|
|
61744
|
+
error: `Could not infer dark reference from existing dependsOn value "${darkFallbackRef}". Supply an explicit "dark" field.`
|
|
61745
|
+
});
|
|
61746
|
+
continue;
|
|
61747
|
+
}
|
|
61748
|
+
if (!newLight || !newDark) {
|
|
61749
|
+
results.push({
|
|
61750
|
+
source,
|
|
61751
|
+
target,
|
|
61752
|
+
action: "skipped",
|
|
61753
|
+
ok: false,
|
|
61754
|
+
error: `Could not resolve light/dark references for "${target}". Supply explicit "light" and "dark" fields.`
|
|
61755
|
+
});
|
|
61756
|
+
continue;
|
|
61757
|
+
}
|
|
61758
|
+
const lightTokenName = `${newLight.family}-${newLight.position}`;
|
|
61759
|
+
const darkTokenName = `${newDark.family}-${newDark.position}`;
|
|
61760
|
+
const missingRefs = [];
|
|
61761
|
+
if (!registry2.has(lightTokenName)) missingRefs.push(lightTokenName);
|
|
61762
|
+
if (!registry2.has(darkTokenName)) missingRefs.push(darkTokenName);
|
|
61763
|
+
if (missingRefs.length > 0) {
|
|
61764
|
+
results.push({
|
|
61765
|
+
source,
|
|
61766
|
+
target,
|
|
61767
|
+
action: "skipped",
|
|
61768
|
+
ok: false,
|
|
61769
|
+
error: `Referenced color tokens not found: ${missingRefs.join(", ")}. Map the color family first, then remap the semantic token.`
|
|
61770
|
+
});
|
|
61771
|
+
continue;
|
|
61772
|
+
}
|
|
61773
|
+
const previousValue = typeof existing.value === "string" ? existing.value : JSON.stringify(existing.value);
|
|
61774
|
+
existing.userOverride = {
|
|
61775
|
+
previousValue,
|
|
61776
|
+
reason: `Remapped from ${source}: ${reason}`
|
|
61777
|
+
};
|
|
61778
|
+
const newColorRef = { family: newLight.family, position: newLight.position };
|
|
61779
|
+
await registry2.set(target, newColorRef);
|
|
61780
|
+
const updated = registry2.get(target);
|
|
61781
|
+
if (updated) {
|
|
61782
|
+
updated.dependsOn = [lightTokenName, darkTokenName];
|
|
61783
|
+
} else {
|
|
61784
|
+
results.push({
|
|
61785
|
+
source,
|
|
61786
|
+
target,
|
|
61787
|
+
action: "skipped",
|
|
61788
|
+
ok: false,
|
|
61789
|
+
error: `Token "${target}" was set but could not be retrieved from registry to update dependencies.`
|
|
61790
|
+
});
|
|
61791
|
+
continue;
|
|
61792
|
+
}
|
|
61793
|
+
results.push({
|
|
61794
|
+
source,
|
|
61795
|
+
target,
|
|
61796
|
+
action: "remap",
|
|
61797
|
+
ok: true
|
|
61798
|
+
});
|
|
61799
|
+
continue;
|
|
61800
|
+
}
|
|
61801
|
+
if (!value2) {
|
|
61802
|
+
results.push({
|
|
61803
|
+
source,
|
|
61804
|
+
target,
|
|
61805
|
+
action: "skipped",
|
|
61806
|
+
ok: false,
|
|
61807
|
+
error: 'Missing "value" for color family mapping. Provide a CSS color value, or use "light"/"dark" for semantic remapping.'
|
|
61508
61808
|
});
|
|
61509
61809
|
continue;
|
|
61510
61810
|
}
|
|
@@ -61528,6 +61828,14 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61528
61828
|
};
|
|
61529
61829
|
await registry2.set(target, tokenValue);
|
|
61530
61830
|
results.push({ source, target, action: "set", ok: true, enriched });
|
|
61831
|
+
} else {
|
|
61832
|
+
results.push({
|
|
61833
|
+
source,
|
|
61834
|
+
target,
|
|
61835
|
+
action: "skipped",
|
|
61836
|
+
ok: false,
|
|
61837
|
+
error: `Token "${target}" exists in registry index but could not be retrieved.`
|
|
61838
|
+
});
|
|
61531
61839
|
}
|
|
61532
61840
|
} else {
|
|
61533
61841
|
const ns = namespace ?? (enriched ? "color" : "custom");
|
|
@@ -61551,6 +61859,7 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61551
61859
|
await this.regenerateOutputs(registry2);
|
|
61552
61860
|
const setCount = results.filter((r) => r.action === "set" && r.ok).length;
|
|
61553
61861
|
const createCount = results.filter((r) => r.action === "create" && r.ok).length;
|
|
61862
|
+
const remapCount = results.filter((r) => r.action === "remap" && r.ok).length;
|
|
61554
61863
|
const enrichedCount = results.filter((r) => r.enriched).length;
|
|
61555
61864
|
const failCount = results.filter((r) => !r.ok).length;
|
|
61556
61865
|
return {
|
|
@@ -61563,6 +61872,7 @@ var RaftersToolHandler = class _RaftersToolHandler {
|
|
|
61563
61872
|
summary: {
|
|
61564
61873
|
set: setCount,
|
|
61565
61874
|
created: createCount,
|
|
61875
|
+
remapped: remapCount,
|
|
61566
61876
|
enriched: enrichedCount,
|
|
61567
61877
|
failed: failCount
|
|
61568
61878
|
},
|