sonance-brand-mcp 1.3.5 → 1.3.7

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.
@@ -0,0 +1,72 @@
1
+ "use client";
2
+
3
+ import {
4
+ createContext,
5
+ useContext,
6
+ useState,
7
+ useEffect,
8
+ useCallback,
9
+ type ReactNode,
10
+ } from "react";
11
+ import { BrandId, brandPresets, applyThemeToDOM } from "./brand-system";
12
+
13
+ // ============================================
14
+ // BRAND CONTEXT
15
+ // Global state for the currently selected brand
16
+ // ============================================
17
+
18
+ const STORAGE_KEY = "sonance-devtools-brand";
19
+
20
+ interface BrandContextValue {
21
+ currentBrand: BrandId;
22
+ setBrand: (brand: BrandId) => void;
23
+ }
24
+
25
+ const BrandContext = createContext<BrandContextValue | null>(null);
26
+
27
+ export function BrandProvider({ children }: { children: ReactNode }) {
28
+ const [currentBrand, setCurrentBrand] = useState<BrandId>("sonance");
29
+ const [mounted, setMounted] = useState(false);
30
+
31
+ // Load persisted brand from localStorage on mount
32
+ useEffect(() => {
33
+ setMounted(true);
34
+ const stored = localStorage.getItem(STORAGE_KEY);
35
+ if (stored && (stored === "sonance" || stored === "iport" || stored === "blaze")) {
36
+ setCurrentBrand(stored as BrandId);
37
+ // Apply the theme when restoring from localStorage
38
+ const preset = brandPresets.find((p) => p.id === stored);
39
+ if (preset) {
40
+ applyThemeToDOM(preset.config);
41
+ }
42
+ }
43
+ }, []);
44
+
45
+ const setBrand = useCallback((brand: BrandId) => {
46
+ setCurrentBrand(brand);
47
+ localStorage.setItem(STORAGE_KEY, brand);
48
+ }, []);
49
+
50
+ // Don't render children until mounted to prevent hydration mismatch
51
+ if (!mounted) {
52
+ return <>{children}</>;
53
+ }
54
+
55
+ return (
56
+ <BrandContext.Provider value={{ currentBrand, setBrand }}>
57
+ {children}
58
+ </BrandContext.Provider>
59
+ );
60
+ }
61
+
62
+ export function useBrand(): BrandContextValue {
63
+ const context = useContext(BrandContext);
64
+ if (!context) {
65
+ // Return default values if not within provider (for SSR/initial render)
66
+ return {
67
+ currentBrand: "sonance",
68
+ setBrand: () => {},
69
+ };
70
+ }
71
+ return context;
72
+ }
@@ -4,7 +4,7 @@ import { useState, useEffect, useCallback, useRef } from "react";
4
4
  import { createPortal } from "react-dom";
5
5
  import { Palette, X, Copy, Check, RotateCcw, ChevronDown, Save, Loader2, AlertCircle, CheckCircle, Sun, Moon, Eye, EyeOff, Zap, Image as ImageIcon, Wand2, Scan, FileCode, Tag, Type, MousePointer, FormInput, Box } from "lucide-react";
6
6
  import { useTheme } from "next-themes";
7
- import { cn } from "@/lib/utils";
7
+ import { cn } from "../../lib/utils";
8
8
  import {
9
9
  ThemeConfig,
10
10
  BrandId,
@@ -17,8 +17,8 @@ import {
17
17
  generateThemeCSS,
18
18
  componentSnippets,
19
19
  isLightColor,
20
- } from "@/lib/brand-system";
21
- import { useBrand } from "@/lib/brand-context";
20
+ } from "../../lib/brand-system";
21
+ import { useBrand } from "../../lib/brand-context";
22
22
 
23
23
  // ============================================
24
24
  // SONANCE DEVTOOLS
package/dist/index.js CHANGED
@@ -313,6 +313,7 @@ function runDevToolsInstaller() {
313
313
  const themeDir = path.join(targetDir, "src/theme");
314
314
  // Source resolution
315
315
  let sourceBrandSystem;
316
+ let sourceBrandContext;
316
317
  let sourceDevTools;
317
318
  let sourceBrandOverridesCss;
318
319
  let sourceApiTheme;
@@ -323,6 +324,7 @@ function runDevToolsInstaller() {
323
324
  let sourceApiAnalyze;
324
325
  if (IS_BUNDLED) {
325
326
  sourceBrandSystem = path.join(BUNDLED_ASSETS, "brand-system.ts");
327
+ sourceBrandContext = path.join(BUNDLED_ASSETS, "brand-context.tsx");
326
328
  sourceDevTools = path.join(BUNDLED_ASSETS, "dev-tools");
327
329
  sourceBrandOverridesCss = path.join(BUNDLED_ASSETS, "styles/brand-overrides.css");
328
330
  sourceApiTheme = path.join(BUNDLED_ASSETS, "api/sonance-theme/route.ts");
@@ -334,6 +336,7 @@ function runDevToolsInstaller() {
334
336
  }
335
337
  else {
336
338
  sourceBrandSystem = path.join(DEV_PROJECT_ROOT, "src/lib/brand-system.ts");
339
+ sourceBrandContext = path.join(DEV_PROJECT_ROOT, "src/lib/brand-context.tsx");
337
340
  sourceDevTools = path.join(DEV_PROJECT_ROOT, "src/components/dev-tools");
338
341
  sourceBrandOverridesCss = path.join(DEV_PROJECT_ROOT, "src/styles/brand-overrides.css");
339
342
  sourceApiTheme = path.join(DEV_PROJECT_ROOT, "src/app/api/sonance-theme/route.ts");
@@ -349,6 +352,11 @@ function runDevToolsInstaller() {
349
352
  console.error(` Path: ${sourceBrandSystem}`);
350
353
  process.exit(1);
351
354
  }
355
+ if (!fs.existsSync(sourceBrandContext)) {
356
+ console.error(" ❌ Error: Could not find brand-context.tsx source file.");
357
+ console.error(` Path: ${sourceBrandContext}`);
358
+ process.exit(1);
359
+ }
352
360
  if (!fs.existsSync(sourceDevTools)) {
353
361
  console.error(" ❌ Error: Could not find dev-tools source directory.");
354
362
  console.error(` Path: ${sourceDevTools}`);
@@ -390,12 +398,14 @@ function runDevToolsInstaller() {
390
398
  process.exit(1);
391
399
  }
392
400
  console.log(" 📂 Installing files...");
393
- // 1. Install brand-system.ts
401
+ // 1. Install brand-system.ts and brand-context.tsx
394
402
  if (!fs.existsSync(libDir)) {
395
403
  fs.mkdirSync(libDir, { recursive: true });
396
404
  }
397
405
  fs.copyFileSync(sourceBrandSystem, path.join(libDir, "brand-system.ts"));
398
406
  console.log(" ✓ Created src/lib/brand-system.ts");
407
+ fs.copyFileSync(sourceBrandContext, path.join(libDir, "brand-context.tsx"));
408
+ console.log(" ✓ Created src/lib/brand-context.tsx");
399
409
  // 2. Install DevTools components
400
410
  if (!fs.existsSync(devToolsDir)) {
401
411
  fs.mkdirSync(devToolsDir, { recursive: true });
@@ -543,17 +553,23 @@ function runDevToolsInstaller() {
543
553
  try {
544
554
  let layoutContent = fs.readFileSync(layoutFullPath, "utf-8");
545
555
  let modified = false;
556
+ // Calculate relative import path from layout to dev-tools
557
+ const devToolsTarget = path.join(targetDir, "src/components/dev-tools");
558
+ let devToolsImportPath = getRelativeImportPath(layoutFullPath, devToolsTarget);
559
+ // Remove trailing slash for JS/TS imports
560
+ devToolsImportPath = devToolsImportPath.replace(/\/$/, '');
561
+ const importLine = `import { SonanceDevTools } from '${devToolsImportPath}';`;
546
562
  // Add import if not present
547
563
  if (!layoutContent.includes("SonanceDevTools")) {
548
564
  const importMatch = layoutContent.match(/^import .+$/gm);
549
565
  if (importMatch && importMatch.length > 0) {
550
566
  const lastImport = importMatch[importMatch.length - 1];
551
- layoutContent = layoutContent.replace(lastImport, `${lastImport}\nimport { SonanceDevTools } from '@/components/dev-tools';`);
567
+ layoutContent = layoutContent.replace(lastImport, `${lastImport}\n${importLine}`);
552
568
  modified = true;
553
569
  }
554
570
  else {
555
571
  // No imports found, add at the top
556
- layoutContent = `import { SonanceDevTools } from '@/components/dev-tools';\n${layoutContent}`;
572
+ layoutContent = `${importLine}\n${layoutContent}`;
557
573
  modified = true;
558
574
  }
559
575
  }
@@ -578,7 +594,7 @@ function runDevToolsInstaller() {
578
594
  }
579
595
  }
580
596
  else {
581
- manualSteps.push("layout.tsx not found - add to your layout:\n import { SonanceDevTools } from '@/components/dev-tools';\n {process.env.NODE_ENV === 'development' && <SonanceDevTools />}");
597
+ manualSteps.push("layout.tsx not found - add to your layout:\n import { SonanceDevTools } from '[path-to]/src/components/dev-tools';\n {process.env.NODE_ENV === 'development' && <SonanceDevTools />}\n (adjust the path based on your layout file location)");
582
598
  }
583
599
  // --- Output results ---
584
600
  console.log("");
@@ -696,7 +712,8 @@ function runDevToolsUninstaller() {
696
712
  "src/app/api/sonance-assets",
697
713
  "src/app/api/sonance-inject-id",
698
714
  "src/app/api/sonance-analyze",
699
- "src/lib/brand-system.ts"
715
+ "src/lib/brand-system.ts",
716
+ "src/lib/brand-context.tsx"
700
717
  ];
701
718
  for (const item of itemsToDelete) {
702
719
  const fullPath = path.join(targetDir, item);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonance-brand-mcp",
3
- "version": "1.3.5",
3
+ "version": "1.3.7",
4
4
  "description": "MCP Server for Sonance Brand Guidelines and Component Library - gives Claude instant access to brand colors, typography, and UI components.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",