@decantr/cli 1.6.1 → 1.6.2

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/bin.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import "./chunk-DESYSWLL.js";
3
- import "./chunk-PMBLHVBX.js";
2
+ import "./chunk-TL5VMEPJ.js";
3
+ import "./chunk-7QOXORFL.js";
@@ -217,20 +217,13 @@ function generateTreatmentCSS(spatialTokens, treatmentOverrides, themeDecorators
217
217
  lines.push("}");
218
218
  lines.push("");
219
219
  lines.push("} /* end @layer treatments */");
220
- if (themeDecorators && Object.keys(themeDecorators).length > 0) {
221
- const label = themeName ? ` (${themeName})` : "";
222
- lines.push("");
223
- lines.push("@layer decorators {");
224
- lines.push("");
225
- lines.push(`/* \u2500\u2500 Layer 3: Theme Decorators${label} \u2500\u2500 */`);
226
- lines.push("");
227
- for (const [name, description] of Object.entries(themeDecorators)) {
228
- const rule = generateDecoratorRule(name, description);
229
- lines.push(rule);
230
- lines.push("");
231
- }
232
- lines.push("} /* end @layer decorators */");
233
- }
220
+ const decoratorBlock = `
221
+ @layer decorators {
222
+ /* Decorator CSS is AI-generated from structured definitions in section context files. */
223
+ /* See .decantr/context/section-*.md for intent, suggested properties, and usage guidance. */
224
+ }
225
+ `;
226
+ lines.push(decoratorBlock);
234
227
  return lines.join("\n");
235
228
  }
236
229
  function generatePersonalityCSS(personality, themeData) {
@@ -693,135 +686,6 @@ input, button, textarea, select {
693
686
  }
694
687
  `;
695
688
  }
696
- function generateDecoratorRule(name, description) {
697
- const rules = [];
698
- const descLower = description.toLowerCase();
699
- const nameLower = name.toLowerCase();
700
- const isCard = descLower.includes("card") || descLower.includes("panel") || nameLower.includes("card") || nameLower.includes("panel");
701
- const isInput = descLower.includes("input") || descLower.includes("field") || descLower.includes("textarea") || nameLower.includes("input") || nameLower.includes("textarea");
702
- const isGlass = descLower.includes("glassmorphic") || descLower.includes("glass") || nameLower.includes("glass");
703
- const isInteractive = isCard || isInput || isGlass;
704
- const isNonInteractive = descLower.includes("divider") || descLower.includes("skeleton") || descLower.includes("keyframe") || descLower.includes("canvas") || nameLower.includes("divider") || nameLower.includes("skeleton") || nameLower.includes("canvas");
705
- if (descLower.includes("monospace") || descLower.includes("mono font")) {
706
- rules.push("font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace");
707
- }
708
- if (descLower.includes("surface-raised") || descLower.includes("surface raised")) {
709
- rules.push("background: var(--d-surface-raised)");
710
- } else if (descLower.includes("surface background") || descLower.includes("surface elevation")) {
711
- rules.push("background: var(--d-surface)");
712
- } else if (descLower.includes("background") && descLower.includes("theme")) {
713
- rules.push("background: var(--d-bg)");
714
- } else if (descLower.includes("primary-tinted") || descLower.includes("primary background")) {
715
- rules.push("background: color-mix(in srgb, var(--d-primary) 15%, var(--d-surface))");
716
- }
717
- if (isInput) {
718
- if (!rules.some((r) => r.startsWith("background"))) {
719
- rules.push("background: var(--d-surface)");
720
- }
721
- rules.push("color: var(--d-text)");
722
- rules.push("padding: 0.5rem 0.75rem");
723
- rules.push("border-radius: var(--d-radius)");
724
- rules.push("width: 100%");
725
- rules.push("outline: none");
726
- }
727
- const leftBorderMatch = descLower.match(/(\d+)px\s+left\s+border/);
728
- if (leftBorderMatch) {
729
- rules.push(`border-left: ${leftBorderMatch[1]}px solid var(--d-primary)`);
730
- } else if (descLower.includes("left border")) {
731
- rules.push("border-left: 3px solid var(--d-primary)");
732
- } else if (descLower.includes("1px border") || descLower.includes("subtle border")) {
733
- rules.push("border: 1px solid var(--d-border)");
734
- } else if (descLower.includes("border") && !descLower.includes("radius")) {
735
- rules.push("border: 1px solid var(--d-border)");
736
- }
737
- const radiusMatch = descLower.match(/(\d+)px radius/);
738
- if (radiusMatch) {
739
- rules.push(`border-radius: ${radiusMatch[1]}px`);
740
- } else if ((descLower.includes("radius") || descLower.includes("rounded")) && !isInput) {
741
- rules.push("border-radius: var(--d-radius)");
742
- }
743
- if (descLower.includes("elevation") || descLower.includes("shadow")) {
744
- rules.push("box-shadow: var(--d-shadow)");
745
- }
746
- if (isInteractive && !isNonInteractive) {
747
- rules.push("transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease");
748
- }
749
- if (descLower.includes("entrance animation") || descLower.includes("fade")) {
750
- rules.push("animation: decantr-fade-in 0.2s ease-out");
751
- }
752
- if (descLower.includes("pulse animation") || descLower.includes("skeleton")) {
753
- rules.push("animation: decantr-pulse 1.5s ease-in-out infinite");
754
- }
755
- const blurMatch = descLower.match(/blur\((\d+)px\)/);
756
- if (blurMatch) {
757
- rules.push(`backdrop-filter: blur(${blurMatch[1]}px)`);
758
- rules.push(`-webkit-backdrop-filter: blur(${blurMatch[1]}px)`);
759
- } else if (isGlass) {
760
- rules.push("backdrop-filter: blur(12px)");
761
- rules.push("-webkit-backdrop-filter: blur(12px)");
762
- } else if (descLower.includes("blur")) {
763
- rules.push("backdrop-filter: blur(8px)");
764
- rules.push("-webkit-backdrop-filter: blur(8px)");
765
- }
766
- if (descLower.includes("semi-transparent") || descLower.includes("glassmorphic")) {
767
- const bgIdx = rules.findIndex((r) => r.startsWith("background:"));
768
- const rgbaBg = "background: rgba(31, 31, 35, 0.8)";
769
- if (bgIdx !== -1) {
770
- rules[bgIdx] = rgbaBg;
771
- } else {
772
- rules.push(rgbaBg);
773
- }
774
- }
775
- if (descLower.includes("right-aligned")) {
776
- rules.push("margin-left: auto");
777
- } else if (descLower.includes("left-aligned")) {
778
- rules.push("margin-right: auto");
779
- }
780
- if (descLower.includes("message bubble") || descLower.includes("bubble")) {
781
- rules.push("padding: var(--d-gap-3) var(--d-gap-4)");
782
- rules.push("border-radius: var(--d-radius-lg)");
783
- rules.push("max-width: 80%");
784
- }
785
- if (descLower.includes("monospace") || descLower.includes("code")) {
786
- if (!rules.some((r) => r.startsWith("padding"))) {
787
- rules.push("padding: 0.75rem 1rem");
788
- }
789
- if (!rules.some((r) => r.startsWith("border-radius"))) {
790
- rules.push("border-radius: var(--d-radius-sm)");
791
- }
792
- rules.push("overflow-x: auto");
793
- }
794
- if (rules.length === 0) {
795
- return `/* .${name}: ${description} */`;
796
- }
797
- let css = `.${name} {
798
- ${rules.join(";\n ")};
799
- }`;
800
- if (isInteractive && !isNonInteractive) {
801
- const stateRules = [];
802
- if (isCard || isGlass) {
803
- stateRules.push(`.${name}:hover {
804
- border-color: var(--d-primary-hover, var(--d-border));
805
- box-shadow: var(--d-shadow-md);
806
- }`);
807
- }
808
- if (isInput) {
809
- stateRules.push(`.${name}:focus {
810
- border-color: var(--d-primary);
811
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--d-primary) 25%, transparent);
812
- }`);
813
- stateRules.push(`.${name}::placeholder {
814
- color: var(--d-text-muted);
815
- }`);
816
- stateRules.push(`.${name}:disabled {
817
- opacity: 0.5;
818
- cursor: not-allowed;
819
- }`);
820
- }
821
- css += "\n\n" + stateRules.join("\n\n");
822
- }
823
- return css;
824
- }
825
689
  function serializeLayoutItem(item) {
826
690
  if (typeof item === "string") {
827
691
  return item;
@@ -897,64 +761,6 @@ function resolvePatternAlias(item, patterns) {
897
761
  }
898
762
  return item;
899
763
  }
900
- function buildEssence(options, archetypeData) {
901
- let structure = [
902
- { id: "home", shell: options.shell, layout: ["hero"] }
903
- ];
904
- let features = options.features;
905
- if (archetypeData?.pages) {
906
- structure = archetypeData.pages.map((p) => {
907
- const resolvedLayout = (p.default_layout?.length ? p.default_layout : ["hero"]).map((item) => resolvePatternAlias(item, p.patterns));
908
- return {
909
- id: p.id,
910
- shell: p.shell || options.shell,
911
- layout: resolvedLayout
912
- };
913
- });
914
- }
915
- if (archetypeData?.features) {
916
- features = [.../* @__PURE__ */ new Set([...features, ...archetypeData.features])];
917
- }
918
- const contentGapMap = {
919
- compact: "_gap2",
920
- comfortable: "_gap4",
921
- spacious: "_gap6"
922
- };
923
- const archetype = options.archetype || "custom";
924
- const essence = {
925
- version: "2.0.0",
926
- archetype,
927
- theme: {
928
- style: options.theme,
929
- mode: options.mode,
930
- recipe: options.theme,
931
- // Legacy v2 field — kept for backward compatibility
932
- shape: options.shape
933
- },
934
- personality: options.personality,
935
- platform: {
936
- type: "spa",
937
- routing: "hash"
938
- },
939
- structure,
940
- features,
941
- guard: {
942
- enforce_style: true,
943
- enforce_recipe: true,
944
- // Legacy v2 field — kept for backward compatibility
945
- mode: options.guard
946
- },
947
- density: {
948
- level: options.density,
949
- content_gap: contentGapMap[options.density] || "_gap4"
950
- },
951
- target: options.target
952
- };
953
- if (options.accessibility) {
954
- essence.accessibility = options.accessibility;
955
- }
956
- return essence;
957
- }
958
764
  function buildEssenceV3(options, archetypeData, themeHints) {
959
765
  let pages = [
960
766
  { id: "home", layout: ["hero"] }
@@ -1337,7 +1143,17 @@ function generateDecantrMdV31(params) {
1337
1143
  }
1338
1144
  briefLines.push(`- **Guard mode:** ${params.guardMode}`);
1339
1145
  briefLines.push("");
1340
- if (params.decorators && params.decorators.length > 0) {
1146
+ if (params.decoratorDefinitions && Object.keys(params.decoratorDefinitions).length > 0) {
1147
+ briefLines.push("### Decorator Quick Reference");
1148
+ briefLines.push("| Class | Intent | Key CSS |");
1149
+ briefLines.push("|-------|--------|---------|");
1150
+ for (const [name, def] of Object.entries(params.decoratorDefinitions)) {
1151
+ const intent = def.intent || "";
1152
+ const cssProps = def.css ? Object.entries(def.css).map(([p, v]) => `${p}: ${v}`).join("; ") : "";
1153
+ briefLines.push(`| \`.${name}\` | ${intent} | ${cssProps} |`);
1154
+ }
1155
+ briefLines.push("");
1156
+ } else if (params.decorators && params.decorators.length > 0) {
1341
1157
  briefLines.push("### Decorator Quick Reference");
1342
1158
  briefLines.push("| Class | Purpose |");
1343
1159
  briefLines.push("|-------|---------|");
@@ -1391,29 +1207,6 @@ function buildFlagsString(options) {
1391
1207
  if (options.guard) flags.push(`--guard=${options.guard}`);
1392
1208
  return flags.join(" ");
1393
1209
  }
1394
- function generateTaskContext(templateName, essence) {
1395
- const template = loadTemplate(templateName);
1396
- const defaultShell = essence.structure[0]?.shell || "sidebar-main";
1397
- const layout = essence.structure[0]?.layout.map(serializeLayoutItem).join(", ") || "none";
1398
- const scaffoldStructure = essence.structure.map((p) => {
1399
- const patterns = p.layout.length > 0 ? `
1400
- - Patterns: ${p.layout.map(serializeLayoutItem).join(", ")}` : "";
1401
- return `- **${p.id}** (${p.shell})${patterns}`;
1402
- }).join("\n");
1403
- const vars = {
1404
- TARGET: essence.target,
1405
- THEME_STYLE: essence.theme.style,
1406
- THEME_MODE: essence.theme.mode,
1407
- THEME_RECIPE: essence.theme.style,
1408
- DEFAULT_SHELL: defaultShell,
1409
- GUARD_MODE: essence.guard.mode,
1410
- LAYOUT: layout,
1411
- DENSITY: essence.density.level,
1412
- CONTENT_GAP: essence.density.content_gap,
1413
- SCAFFOLD_STRUCTURE: scaffoldStructure
1414
- };
1415
- return renderTemplate(template, vars);
1416
- }
1417
1210
  function generateTaskContextV3(templateName, essence) {
1418
1211
  const template = loadTemplate(templateName);
1419
1212
  const pages = essence.blueprint.sections && essence.blueprint.sections.length > 0 ? essence.blueprint.sections.flatMap((s) => s.pages) : essence.blueprint.pages || [];
@@ -1506,7 +1299,6 @@ ${cacheEntry}
1506
1299
  }
1507
1300
  async function scaffoldProject(projectRoot, options, detected, registry, archetypeData, registrySource = "cache", themeData, topologyMarkdown, composedSections, routeMap, patternSpecs, blueprintData) {
1508
1301
  const essenceV3 = buildEssenceV3(options, archetypeData, themeData);
1509
- const essence = buildEssence(options, archetypeData);
1510
1302
  const decantrDir = join(projectRoot, ".decantr");
1511
1303
  const contextDir = join(decantrDir, "context");
1512
1304
  const cacheDir = join(decantrDir, "cache");
@@ -1518,7 +1310,7 @@ async function scaffoldProject(projectRoot, options, detected, registry, archety
1518
1310
  writeFileSync(projectJsonPath, generateProjectJson(detected, options, registrySource));
1519
1311
  const contextFiles = [];
1520
1312
  const scaffoldPath = join(contextDir, "task-scaffold.md");
1521
- writeFileSync(scaffoldPath, generateTaskContext("task-scaffold.md.template", essence));
1313
+ writeFileSync(scaffoldPath, generateTaskContextV3("task-scaffold.md.template", essenceV3));
1522
1314
  contextFiles.push(scaffoldPath);
1523
1315
  if (composedSections) {
1524
1316
  essenceV3.version = "3.1.0";
@@ -1541,7 +1333,7 @@ async function scaffoldProject(projectRoot, options, detected, registry, archety
1541
1333
  }
1542
1334
  writeFileSync(essencePath, JSON.stringify(essenceV3, null, 2) + "\n");
1543
1335
  }
1544
- const refreshResult = await refreshDerivedFiles(projectRoot, essenceV3, registry, themeData, { isInitialScaffold: true });
1336
+ const refreshResult = await refreshDerivedFiles(projectRoot, essenceV3, registry, themeData, { isInitialScaffold: true, patternSpecs });
1545
1337
  contextFiles.push(...refreshResult.contextFiles);
1546
1338
  const gitignoreUpdated = updateGitignore(projectRoot);
1547
1339
  return {
@@ -1741,6 +1533,68 @@ When available, use these tools:
1741
1533
  gitignoreUpdated
1742
1534
  };
1743
1535
  }
1536
+ async function resolvePatternSpec(name, registry, prefetched, includeExtendedFields = true) {
1537
+ if (prefetched && (prefetched.layout_hints || prefetched.visual_brief || !includeExtendedFields)) {
1538
+ if (!prefetched.components || prefetched.components.length === 0) {
1539
+ const syntheticComps2 = generateSyntheticComponents(name, prefetched.description);
1540
+ if (syntheticComps2.length > 0) prefetched.components = syntheticComps2;
1541
+ }
1542
+ if (!prefetched.slots || Object.keys(prefetched.slots).length === 0) {
1543
+ const synthetic = generateSyntheticSlots(name, prefetched.description);
1544
+ if (Object.keys(synthetic).length > 0) prefetched.slots = synthetic;
1545
+ }
1546
+ return prefetched;
1547
+ }
1548
+ try {
1549
+ const patResult = await registry.fetchPattern(name);
1550
+ if (patResult?.data) {
1551
+ const inner = patResult.data;
1552
+ const defaultPreset = inner.default_preset || "standard";
1553
+ const preset = inner.presets?.[defaultPreset];
1554
+ let slots = preset?.layout?.slots || {};
1555
+ if (Object.keys(slots).length === 0) {
1556
+ const synthetic = generateSyntheticSlots(name, inner.description || "");
1557
+ if (Object.keys(synthetic).length > 0) slots = synthetic;
1558
+ }
1559
+ const spec = {
1560
+ description: inner.description || prefetched?.description || "",
1561
+ components: inner.components || prefetched?.components || [],
1562
+ slots,
1563
+ layout_hints: inner.layout_hints,
1564
+ ...includeExtendedFields ? {
1565
+ visual_brief: inner.visual_brief,
1566
+ composition: inner.composition,
1567
+ motion: inner.motion,
1568
+ responsive: inner.responsive,
1569
+ accessibility: inner.accessibility
1570
+ } : {}
1571
+ };
1572
+ if (!spec.components || spec.components.length === 0) {
1573
+ const syntheticComps2 = generateSyntheticComponents(name, spec.description);
1574
+ if (syntheticComps2.length > 0) spec.components = syntheticComps2;
1575
+ }
1576
+ return spec;
1577
+ }
1578
+ } catch {
1579
+ }
1580
+ if (prefetched) {
1581
+ if (!prefetched.components || prefetched.components.length === 0) {
1582
+ const syntheticComps2 = generateSyntheticComponents(name, prefetched.description);
1583
+ if (syntheticComps2.length > 0) prefetched.components = syntheticComps2;
1584
+ }
1585
+ if (!prefetched.slots || Object.keys(prefetched.slots).length === 0) {
1586
+ const synthetic = generateSyntheticSlots(name, prefetched.description);
1587
+ if (Object.keys(synthetic).length > 0) prefetched.slots = synthetic;
1588
+ }
1589
+ return prefetched;
1590
+ }
1591
+ const syntheticSlots = generateSyntheticSlots(name, "");
1592
+ const syntheticComps = generateSyntheticComponents(name, "");
1593
+ if (Object.keys(syntheticSlots).length > 0 || syntheticComps.length > 0) {
1594
+ return { description: "", components: syntheticComps, slots: syntheticSlots };
1595
+ }
1596
+ return null;
1597
+ }
1744
1598
  async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThemeData, options) {
1745
1599
  const decantrDir = join(projectRoot, ".decantr");
1746
1600
  const contextDir = join(decantrDir, "context");
@@ -1869,7 +1723,8 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
1869
1723
  personality,
1870
1724
  sections: sectionSummaries.length > 0 ? sectionSummaries : void 0,
1871
1725
  features: allFeatures.length > 0 ? allFeatures : void 0,
1872
- decorators: earlyDecoratorList.length > 0 ? earlyDecoratorList : void 0
1726
+ decorators: earlyDecoratorList.length > 0 ? earlyDecoratorList : void 0,
1727
+ decoratorDefinitions: themeData?.decorator_definitions
1873
1728
  }));
1874
1729
  const hasSections = essence.blueprint.sections && essence.blueprint.sections.length > 0;
1875
1730
  const contextFiles = [];
@@ -1895,6 +1750,7 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
1895
1750
  section.shell = primarySectionShell;
1896
1751
  }
1897
1752
  }
1753
+ const prefetchedSpecs = options?.patternSpecs;
1898
1754
  const patternSpecs = {};
1899
1755
  const seenPatterns = /* @__PURE__ */ new Set();
1900
1756
  for (const section of sections) {
@@ -1904,49 +1760,8 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
1904
1760
  for (const name of names) {
1905
1761
  if (!seenPatterns.has(name)) {
1906
1762
  seenPatterns.add(name);
1907
- try {
1908
- const patResult = await registry.fetchPattern(name);
1909
- if (patResult?.data) {
1910
- const inner = patResult.data;
1911
- const defaultPreset = inner.default_preset || "standard";
1912
- const preset = inner.presets?.[defaultPreset];
1913
- let slots = preset?.layout?.slots || {};
1914
- if (Object.keys(slots).length === 0) {
1915
- const synthetic = generateSyntheticSlots(name, inner.description || "");
1916
- if (Object.keys(synthetic).length > 0) {
1917
- slots = synthetic;
1918
- }
1919
- }
1920
- const spec = {
1921
- description: inner.description || "",
1922
- components: inner.components || [],
1923
- slots,
1924
- layout_hints: inner.layout_hints,
1925
- visual_brief: inner.visual_brief,
1926
- composition: inner.composition,
1927
- motion: inner.motion,
1928
- responsive: inner.responsive,
1929
- accessibility: inner.accessibility
1930
- };
1931
- if (!spec.components || spec.components.length === 0) {
1932
- const syntheticComps = generateSyntheticComponents(name, spec.description);
1933
- if (syntheticComps.length > 0) spec.components = syntheticComps;
1934
- }
1935
- patternSpecs[name] = spec;
1936
- } else {
1937
- const synthetic = generateSyntheticSlots(name, "");
1938
- const syntheticComps = generateSyntheticComponents(name, "");
1939
- if (Object.keys(synthetic).length > 0 || syntheticComps.length > 0) {
1940
- patternSpecs[name] = { description: "", components: syntheticComps, slots: synthetic };
1941
- }
1942
- }
1943
- } catch {
1944
- const synthetic = generateSyntheticSlots(name, "");
1945
- const syntheticComps = generateSyntheticComponents(name, "");
1946
- if (Object.keys(synthetic).length > 0 || syntheticComps.length > 0) {
1947
- patternSpecs[name] = { description: "", components: syntheticComps, slots: synthetic };
1948
- }
1949
- }
1763
+ const spec = await resolvePatternSpec(name, registry, prefetchedSpecs?.[name], true);
1764
+ if (spec) patternSpecs[name] = spec;
1950
1765
  }
1951
1766
  }
1952
1767
  }
@@ -2074,6 +1889,7 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
2074
1889
  description: `${essence.meta.archetype || "Application"} section`,
2075
1890
  pages
2076
1891
  };
1892
+ const prefetchedSpecs = options?.patternSpecs;
2077
1893
  const patternSpecs = {};
2078
1894
  const seenPatterns = /* @__PURE__ */ new Set();
2079
1895
  for (const page of pages) {
@@ -2082,44 +1898,8 @@ async function refreshDerivedFiles(projectRoot, essence, registry, prefetchedThe
2082
1898
  for (const name of names) {
2083
1899
  if (!seenPatterns.has(name)) {
2084
1900
  seenPatterns.add(name);
2085
- try {
2086
- const patResult = await registry.fetchPattern(name);
2087
- if (patResult?.data) {
2088
- const inner = patResult.data;
2089
- const defaultPreset = inner.default_preset || "standard";
2090
- const preset = inner.presets?.[defaultPreset];
2091
- let slots = preset?.layout?.slots || {};
2092
- if (Object.keys(slots).length === 0) {
2093
- const synthetic = generateSyntheticSlots(name, inner.description || "");
2094
- if (Object.keys(synthetic).length > 0) {
2095
- slots = synthetic;
2096
- }
2097
- }
2098
- const spec = {
2099
- description: inner.description || "",
2100
- components: inner.components || [],
2101
- slots,
2102
- layout_hints: inner.layout_hints
2103
- };
2104
- if (!spec.components || spec.components.length === 0) {
2105
- const syntheticComps = generateSyntheticComponents(name, spec.description);
2106
- if (syntheticComps.length > 0) spec.components = syntheticComps;
2107
- }
2108
- patternSpecs[name] = spec;
2109
- } else {
2110
- const synthetic = generateSyntheticSlots(name, "");
2111
- const syntheticComps = generateSyntheticComponents(name, "");
2112
- if (Object.keys(synthetic).length > 0 || syntheticComps.length > 0) {
2113
- patternSpecs[name] = { description: "", components: syntheticComps, slots: synthetic };
2114
- }
2115
- }
2116
- } catch {
2117
- const synthetic = generateSyntheticSlots(name, "");
2118
- const syntheticComps = generateSyntheticComponents(name, "");
2119
- if (Object.keys(synthetic).length > 0 || syntheticComps.length > 0) {
2120
- patternSpecs[name] = { description: "", components: syntheticComps, slots: synthetic };
2121
- }
2122
- }
1901
+ const spec = await resolvePatternSpec(name, registry, prefetchedSpecs?.[name], false);
1902
+ if (spec) patternSpecs[name] = spec;
2123
1903
  }
2124
1904
  }
2125
1905
  }
@@ -2322,7 +2102,27 @@ function generateSectionContext(input) {
2322
2102
  lines.push("Full token set: `src/styles/tokens.css`");
2323
2103
  lines.push("");
2324
2104
  lines.push("**Visual Treatments:** All 6 base treatments available (see DECANTR.md for usage).");
2325
- if (decorators.length > 0) {
2105
+ const decoratorDefs = input.themeData?.decorator_definitions;
2106
+ if (decoratorDefs && Object.keys(decoratorDefs).length > 0) {
2107
+ lines.push("**Theme decorators:**");
2108
+ lines.push("");
2109
+ lines.push("| Class | Intent | Key CSS | Pairs with |");
2110
+ lines.push("|-------|--------|---------|------------|");
2111
+ for (const [name, def] of Object.entries(decoratorDefs)) {
2112
+ const intent = def.intent || "";
2113
+ const cssProps = def.css ? Object.entries(def.css).map(([p, v]) => `${p}: ${v}`).join("; ") : "";
2114
+ const pairsWith = def.pairs_with || "";
2115
+ lines.push(`| \`.${name}\` | ${intent} | ${cssProps} | ${pairsWith} |`);
2116
+ }
2117
+ lines.push("");
2118
+ lines.push("**Decorator usage guide:**");
2119
+ for (const [name, def] of Object.entries(decoratorDefs)) {
2120
+ if (def.usage && def.usage.length > 0) {
2121
+ lines.push(`- \`.${name}\`: ${def.usage.join(", ")}`);
2122
+ }
2123
+ }
2124
+ lines.push("");
2125
+ } else if (decorators.length > 0) {
2326
2126
  lines.push("**Theme decorators:**");
2327
2127
  lines.push("");
2328
2128
  lines.push("| Class | Usage |");
@@ -2332,7 +2132,7 @@ function generateSectionContext(input) {
2332
2132
  }
2333
2133
  lines.push("");
2334
2134
  } else {
2335
- lines.push("**Theme decorators:** None defined for this theme.");
2135
+ lines.push("No theme decorators defined.");
2336
2136
  lines.push("");
2337
2137
  }
2338
2138
  if (themeHints) {
@@ -9,7 +9,7 @@ import {
9
9
  scaffoldMinimal,
10
10
  scaffoldProject,
11
11
  syncRegistry
12
- } from "./chunk-PMBLHVBX.js";
12
+ } from "./chunk-7QOXORFL.js";
13
13
 
14
14
  // src/index.ts
15
15
  import { readFileSync as readFileSync15, existsSync as existsSync23, readdirSync as readdirSync6 } from "fs";
@@ -4332,7 +4332,7 @@ async function main() {
4332
4332
  break;
4333
4333
  }
4334
4334
  case "upgrade": {
4335
- const { cmdUpgrade } = await import("./upgrade-2OG7UKTR.js");
4335
+ const { cmdUpgrade } = await import("./upgrade-PKKLUMFJ.js");
4336
4336
  const applyFlag = args.includes("--apply");
4337
4337
  await cmdUpgrade(process.cwd(), { apply: applyFlag });
4338
4338
  break;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import "./chunk-DESYSWLL.js";
2
- import "./chunk-PMBLHVBX.js";
1
+ import "./chunk-TL5VMEPJ.js";
2
+ import "./chunk-7QOXORFL.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  RegistryClient,
3
3
  refreshDerivedFiles
4
- } from "./chunk-PMBLHVBX.js";
4
+ } from "./chunk-7QOXORFL.js";
5
5
 
6
6
  // src/commands/upgrade.ts
7
7
  import { readFileSync, writeFileSync, existsSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decantr/cli",
3
- "version": "1.6.1",
3
+ "version": "1.6.2",
4
4
  "description": "Decantr CLI — search the registry, validate essence files, and access design intelligence from the terminal",
5
5
  "license": "MIT",
6
6
  "repository": {