sonance-brand-mcp 1.3.110 → 1.3.112

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/assets/api/sonance-ai-edit/route.ts +30 -7
  2. package/dist/assets/api/sonance-save-image/route.ts +625 -0
  3. package/dist/assets/api/sonance-vision-apply/image-styling-detection.ts +1360 -0
  4. package/dist/assets/api/sonance-vision-apply/route.ts +1020 -64
  5. package/dist/assets/api/sonance-vision-apply/styling-detection.ts +730 -0
  6. package/dist/assets/api/sonance-vision-apply/theme-discovery.ts +1 -1
  7. package/dist/assets/api/sonance-vision-edit/route.ts +33 -8
  8. package/dist/assets/brand-system.ts +13 -12
  9. package/dist/assets/components/accordion.tsx +15 -7
  10. package/dist/assets/components/alert-dialog.tsx +35 -10
  11. package/dist/assets/components/alert.tsx +11 -10
  12. package/dist/assets/components/avatar.tsx +4 -4
  13. package/dist/assets/components/badge.tsx +16 -12
  14. package/dist/assets/components/button.stories.tsx +3 -3
  15. package/dist/assets/components/button.tsx +50 -31
  16. package/dist/assets/components/calendar.tsx +12 -8
  17. package/dist/assets/components/card.tsx +35 -29
  18. package/dist/assets/components/checkbox.tsx +9 -8
  19. package/dist/assets/components/code.tsx +19 -11
  20. package/dist/assets/components/command.tsx +32 -13
  21. package/dist/assets/components/context-menu.tsx +37 -16
  22. package/dist/assets/components/dialog.tsx +8 -5
  23. package/dist/assets/components/divider.tsx +15 -5
  24. package/dist/assets/components/drawer.tsx +4 -3
  25. package/dist/assets/components/dropdown-menu.tsx +15 -13
  26. package/dist/assets/components/hover-card.tsx +4 -1
  27. package/dist/assets/components/image.tsx +1 -1
  28. package/dist/assets/components/input.tsx +29 -14
  29. package/dist/assets/components/kbd.stories.tsx +3 -3
  30. package/dist/assets/components/kbd.tsx +29 -13
  31. package/dist/assets/components/listbox.tsx +8 -8
  32. package/dist/assets/components/menubar.tsx +50 -23
  33. package/dist/assets/components/navbar.stories.tsx +140 -13
  34. package/dist/assets/components/navbar.tsx +22 -5
  35. package/dist/assets/components/navigation-menu.tsx +28 -6
  36. package/dist/assets/components/pagination.tsx +10 -10
  37. package/dist/assets/components/popover.tsx +10 -8
  38. package/dist/assets/components/progress.tsx +6 -4
  39. package/dist/assets/components/radio-group.tsx +5 -5
  40. package/dist/assets/components/select.tsx +49 -29
  41. package/dist/assets/components/separator.tsx +3 -3
  42. package/dist/assets/components/sheet.tsx +4 -4
  43. package/dist/assets/components/sidebar.tsx +10 -10
  44. package/dist/assets/components/skeleton.tsx +13 -5
  45. package/dist/assets/components/slider.tsx +12 -10
  46. package/dist/assets/components/switch.tsx +4 -4
  47. package/dist/assets/components/table.tsx +5 -5
  48. package/dist/assets/components/tabs.tsx +8 -8
  49. package/dist/assets/components/textarea.tsx +11 -9
  50. package/dist/assets/components/toast.tsx +7 -7
  51. package/dist/assets/components/toggle.tsx +27 -7
  52. package/dist/assets/components/tooltip.tsx +10 -8
  53. package/dist/assets/components/user.tsx +8 -6
  54. package/dist/assets/dev-tools/SonanceDevTools.tsx +851 -708
  55. package/dist/assets/dev-tools/components/ApplyFirstPreview.tsx +10 -10
  56. package/dist/assets/dev-tools/components/ChatHistory.tsx +145 -0
  57. package/dist/assets/dev-tools/components/ChatInterface.tsx +444 -295
  58. package/dist/assets/dev-tools/components/ChatTabBar.tsx +82 -0
  59. package/dist/assets/dev-tools/components/DiffPreview.tsx +1 -1
  60. package/dist/assets/dev-tools/components/InlineDiffPreview.tsx +528 -0
  61. package/dist/assets/dev-tools/components/InspectorOverlay.tsx +21 -18
  62. package/dist/assets/dev-tools/components/PropertiesPanel.tsx +1345 -0
  63. package/dist/assets/dev-tools/components/ScreenshotAnnotator.tsx +1 -1
  64. package/dist/assets/dev-tools/components/SectionHighlight.tsx +1 -1
  65. package/dist/assets/dev-tools/components/VisionDiffPreview.tsx +7 -7
  66. package/dist/assets/dev-tools/components/VisionModeBorder.tsx +12 -63
  67. package/dist/assets/dev-tools/constants.ts +38 -6
  68. package/dist/assets/dev-tools/hooks/index.ts +69 -0
  69. package/dist/assets/dev-tools/hooks/useComponentDetection.ts +132 -0
  70. package/dist/assets/dev-tools/hooks/useComputedStyles.ts +471 -0
  71. package/dist/assets/dev-tools/hooks/useContentHash.ts +212 -0
  72. package/dist/assets/dev-tools/hooks/useElementScanner.ts +398 -0
  73. package/dist/assets/dev-tools/hooks/useImageDetection.ts +162 -0
  74. package/dist/assets/dev-tools/hooks/useTextDetection.ts +217 -0
  75. package/dist/assets/dev-tools/index.ts +3 -0
  76. package/dist/assets/dev-tools/panels/AnalysisPanel.tsx +32 -32
  77. package/dist/assets/dev-tools/panels/ComponentsPanel.tsx +384 -131
  78. package/dist/assets/dev-tools/panels/TextPanel.tsx +10 -10
  79. package/dist/assets/dev-tools/types.ts +93 -2
  80. package/dist/assets/globals.css +225 -9
  81. package/dist/assets/styles/brand-overrides.css +3 -2
  82. package/dist/assets/utils.ts +2 -1
  83. package/dist/index.js +22 -3
  84. package/package.json +2 -1
@@ -368,7 +368,7 @@ export function ScreenshotAnnotator({
368
368
  }}
369
369
  >
370
370
  <Crop size={18} />
371
- <span>Click and drag to select the area you want to focus on</span>
371
+ <span id="span-click-and-drag-to-se">Click and drag to select the area you want to focus on</span>
372
372
  </div>
373
373
 
374
374
  {/* Current rectangle selection */}
@@ -96,7 +96,7 @@ export function SectionHighlight({ active, focusedElements }: SectionHighlightPr
96
96
  }}
97
97
  >
98
98
  <Box size={12} />
99
- <span>Section: {labelText}</span>
99
+ <span id="span-section-labeltext">Section: {labelText}</span>
100
100
  </div>
101
101
 
102
102
  {/* Corner markers for emphasis */}
@@ -34,14 +34,14 @@ function FileModificationCard({
34
34
  <ChevronRight className="h-3.5 w-3.5 text-gray-400 flex-shrink-0" />
35
35
  )}
36
36
  <FileCode className="h-3.5 w-3.5 text-purple-500 flex-shrink-0" />
37
- <span className="text-xs font-mono text-gray-700 truncate flex-1">
37
+ <span id="file-modification-card-span-modificationfilepath" className="text-xs font-mono text-gray-700 truncate flex-1">
38
38
  {modification.filePath}
39
39
  </span>
40
40
  </button>
41
41
 
42
42
  {/* Explanation */}
43
43
  <div className="px-2 pb-2">
44
- <p className="text-[10px] text-gray-500">{modification.explanation}</p>
44
+ <p id="file-modification-card-p-modificationexplanat" className="text-[10px] text-gray-500">{modification.explanation}</p>
45
45
  </div>
46
46
 
47
47
  {/* Expanded Diff */}
@@ -108,10 +108,10 @@ export function VisionDiffPreview({
108
108
  <div className="flex items-center justify-between">
109
109
  <div className="flex items-center gap-2">
110
110
  <Eye className="h-4 w-4 text-purple-600" />
111
- <span className="text-xs font-semibold text-gray-900">
111
+ <span id="vision-diff-preview-span-vision-mode-changes-" className="text-xs font-semibold text-gray-900">
112
112
  Vision Mode Changes Ready
113
113
  </span>
114
- <span className="text-[10px] px-1.5 py-0.5 rounded bg-purple-200 text-purple-700 font-medium">
114
+ <span id="vision-diff-preview-span-filecount-filefileco" className="text-[10px] px-1.5 py-0.5 rounded bg-purple-200 text-purple-700 font-medium">
115
115
  {fileCount} file{fileCount !== 1 ? "s" : ""}
116
116
  </span>
117
117
  </div>
@@ -124,7 +124,7 @@ export function VisionDiffPreview({
124
124
  </div>
125
125
 
126
126
  {/* Overall Explanation */}
127
- <p className="text-xs text-gray-600">{pendingEdit.explanation}</p>
127
+ <p id="vision-diff-preview-p-pendingeditexplanati" className="text-xs text-gray-600">{pendingEdit.explanation}</p>
128
128
 
129
129
  {/* File Modifications List */}
130
130
  <div className="space-y-2 max-h-80 overflow-y-auto">
@@ -141,7 +141,7 @@ export function VisionDiffPreview({
141
141
  {/* Live Preview Indicator */}
142
142
  <div className="flex items-center gap-2 p-2 rounded bg-purple-100 border border-purple-200">
143
143
  <Eye className="h-3.5 w-3.5 text-purple-600" />
144
- <span className="text-xs text-purple-700">
144
+ <span id="vision-diff-preview-span-live-preview-active-" className="text-xs text-purple-700">
145
145
  Live preview active - scroll to see changes on the page
146
146
  </span>
147
147
  </div>
@@ -150,7 +150,7 @@ export function VisionDiffPreview({
150
150
  {fileCount > 1 && (
151
151
  <div className="flex items-start gap-2 p-2 rounded bg-amber-50 border border-amber-200">
152
152
  <AlertCircle className="h-3.5 w-3.5 text-amber-600 mt-0.5 flex-shrink-0" />
153
- <span className="text-xs text-amber-700">
153
+ <span id="vision-diff-preview-span-multiple-files-will-" className="text-xs text-amber-700">
154
154
  Multiple files will be modified. Review each file before saving.
155
155
  </span>
156
156
  </div>
@@ -2,14 +2,16 @@
2
2
 
3
3
  import React, { useEffect, useState } from "react";
4
4
  import { createPortal } from "react-dom";
5
- import { Eye } from "lucide-react";
6
5
 
7
6
  interface VisionModeBorderProps {
8
7
  active: boolean;
9
8
  focusedCount?: number;
9
+ highlightEnabled?: boolean;
10
10
  }
11
11
 
12
- export function VisionModeBorder({ active, focusedCount = 0 }: VisionModeBorderProps) {
12
+ export function VisionModeBorder({
13
+ active,
14
+ }: VisionModeBorderProps) {
13
15
  const [mounted, setMounted] = useState(false);
14
16
 
15
17
  useEffect(() => {
@@ -39,77 +41,24 @@ export function VisionModeBorder({ active, focusedCount = 0 }: VisionModeBorderP
39
41
  }
40
42
  `}</style>
41
43
 
42
- {/* Main border overlay */}
44
+ {/* Main border overlay - respects devtools frame if present */}
45
+ {/* Removed corner pill and bottom instruction to not cover UI elements */}
43
46
  <div
44
47
  data-vision-mode-border="true"
45
48
  style={{
46
49
  position: "fixed",
47
- top: 0,
50
+ top: "var(--devtools-banner-height, 0px)",
48
51
  left: 0,
49
- right: 0,
52
+ right: "var(--devtools-sidebar-width, 0px)",
50
53
  bottom: 0,
51
54
  pointerEvents: "none",
52
55
  zIndex: 9996, // Below DevTools (9999) but above content
53
- border: "4px solid #8B5CF6",
54
- boxShadow: "inset 0 0 30px rgba(139, 92, 246, 0.3), 0 0 30px rgba(139, 92, 246, 0.3)",
56
+ border: "3px solid #8B5CF6",
57
+ boxShadow: "inset 0 0 20px rgba(139, 92, 246, 0.2), 0 0 20px rgba(139, 92, 246, 0.2)",
55
58
  animation: "vision-pulse 2s ease-in-out infinite, vision-glow 2s ease-in-out infinite",
59
+ transition: "all 0.2s ease-out",
56
60
  }}
57
- >
58
- {/* Corner indicator */}
59
- <div
60
- style={{
61
- position: "absolute",
62
- top: "12px",
63
- left: "12px",
64
- display: "flex",
65
- alignItems: "center",
66
- gap: "6px",
67
- backgroundColor: "#8B5CF6",
68
- color: "white",
69
- padding: "6px 12px",
70
- borderRadius: "6px",
71
- fontSize: "12px",
72
- fontWeight: 600,
73
- fontFamily: "system-ui, -apple-system, sans-serif",
74
- boxShadow: "0 2px 8px rgba(139, 92, 246, 0.4)",
75
- }}
76
- >
77
- <Eye size={14} />
78
- <span>Vision Mode</span>
79
- {focusedCount > 0 && (
80
- <span
81
- style={{
82
- backgroundColor: "rgba(255, 255, 255, 0.2)",
83
- padding: "2px 6px",
84
- borderRadius: "4px",
85
- marginLeft: "4px",
86
- }}
87
- >
88
- {focusedCount} focused
89
- </span>
90
- )}
91
- </div>
92
-
93
- {/* Instruction hint at bottom */}
94
- <div
95
- style={{
96
- position: "absolute",
97
- bottom: "12px",
98
- left: "50%",
99
- transform: "translateX(-50%)",
100
- backgroundColor: "rgba(139, 92, 246, 0.9)",
101
- color: "white",
102
- padding: "8px 16px",
103
- borderRadius: "8px",
104
- fontSize: "13px",
105
- fontFamily: "system-ui, -apple-system, sans-serif",
106
- boxShadow: "0 2px 12px rgba(139, 92, 246, 0.5)",
107
- whiteSpace: "nowrap",
108
- }}
109
- >
110
- Click elements to focus AI attention, then describe your changes in the chat
111
- </div>
112
- </div>
61
+ />
113
62
  </>,
114
63
  document.body
115
64
  );
@@ -1,13 +1,45 @@
1
1
 
2
2
  import { Box, Image as ImageIcon, Type, Scan } from "lucide-react";
3
- import { TabDefinition, ConfigSection } from "./types";
3
+ import { TabDefinition, ConfigSection, ElementFilters } from "./types";
4
4
  import { componentSnippets } from "../../lib/brand-system";
5
5
 
6
- export const tabs: TabDefinition[] = [
7
- { id: "components", label: "Components", icon: Box },
8
- { id: "logos", label: "Logos", icon: ImageIcon },
9
- { id: "text", label: "Text", icon: Type },
10
- ];
6
+ // Note: Tabs have been simplified - elements are now unified with filters
7
+ // Analysis is the only separate "tab" mode
8
+
9
+ // Default element filters - all enabled by default
10
+ export const DEFAULT_ELEMENT_FILTERS: ElementFilters = {
11
+ components: true,
12
+ images: true,
13
+ text: true,
14
+ };
15
+
16
+ // Element type color scheme for the unified view
17
+ export const ELEMENT_TYPE_COLORS = {
18
+ components: {
19
+ border: "#8B5CF6", // Purple
20
+ bg: "rgba(139, 92, 246, 0.1)",
21
+ activeBg: "bg-purple-100",
22
+ activeText: "text-purple-700",
23
+ activeBorder: "border-purple-300",
24
+ label: "Components",
25
+ },
26
+ images: {
27
+ border: "#3B82F6", // Blue
28
+ bg: "rgba(59, 130, 246, 0.1)",
29
+ activeBg: "bg-blue-100",
30
+ activeText: "text-blue-700",
31
+ activeBorder: "border-blue-300",
32
+ label: "Images",
33
+ },
34
+ text: {
35
+ border: "#F59E0B", // Amber
36
+ bg: "rgba(245, 158, 11, 0.1)",
37
+ activeBg: "bg-amber-100",
38
+ activeText: "text-amber-700",
39
+ activeBorder: "border-amber-300",
40
+ label: "Text",
41
+ },
42
+ };
11
43
 
12
44
  // Quick action presets for common styling changes
13
45
  export const QUICK_ACTIONS = [
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Dev Tools Hooks
3
+ *
4
+ * Modular hooks for element detection and styling in the Sonance DevTools.
5
+ *
6
+ * Architecture:
7
+ * - useElementScanner: Main orchestrator that combines all detection types
8
+ * - useComponentDetection: Component-specific detection
9
+ * - useImageDetection: Image/logo detection with original state tracking
10
+ * - useTextDetection: Text element detection with filtering
11
+ * - useContentHash: Content-based ID generation for stability
12
+ * - useComputedStyles: Get computed styles for selected elements
13
+ */
14
+
15
+ // Main scanner hook (use this in most cases)
16
+ export {
17
+ useElementScanner,
18
+ extractLogoName,
19
+ type ElementScannerOptions,
20
+ type ElementScannerResult,
21
+ } from "./useElementScanner";
22
+
23
+ // Individual detection hooks (for custom implementations)
24
+ export {
25
+ useComponentDetection,
26
+ detectComponents,
27
+ type ComponentDetectionConfig,
28
+ } from "./useComponentDetection";
29
+
30
+ export {
31
+ useImageDetection,
32
+ detectImages,
33
+ type ImageDetectionConfig,
34
+ type ImageDetectionResult,
35
+ } from "./useImageDetection";
36
+
37
+ export {
38
+ useTextDetection,
39
+ detectTextElements,
40
+ type TextDetectionConfig,
41
+ type TextDetectionResult,
42
+ } from "./useTextDetection";
43
+
44
+ // Content-based hashing utilities
45
+ export {
46
+ hashString,
47
+ generateTextElementId,
48
+ generateImageElementId,
49
+ generateComponentId,
50
+ generateVariantId,
51
+ migrateLegacyIds,
52
+ isLegacyId,
53
+ isMigrationComplete,
54
+ markMigrationComplete,
55
+ MIGRATION_STORAGE_KEY,
56
+ MIGRATION_VERSION,
57
+ } from "./useContentHash";
58
+
59
+ // Computed styles hook (existing)
60
+ export {
61
+ useComputedStyles,
62
+ useElementFromCoordinates,
63
+ type ComputedStyles,
64
+ type ComputedGeometry,
65
+ type ComputedTypography,
66
+ type ComputedFill,
67
+ type ComputedStroke,
68
+ type ComputedEffect,
69
+ } from "./useComputedStyles";
@@ -0,0 +1,132 @@
1
+ "use client";
2
+
3
+ import { useCallback } from "react";
4
+ import { DetectedElement } from "../types";
5
+ import { generateVariantId, generateComponentId } from "./useContentHash";
6
+
7
+ /**
8
+ * Component detection configuration
9
+ */
10
+ export interface ComponentDetectionConfig {
11
+ /** Whether to include elements in modals/dialogs */
12
+ includeModals: boolean;
13
+ /** Callback to check if element is in active layer */
14
+ isInActiveLayer: (el: Element) => boolean;
15
+ /** Callback to get visible rect (clipped to scroll container) */
16
+ getVisibleRect: (el: Element, rect: DOMRect) => DOMRect | null;
17
+ }
18
+
19
+ /**
20
+ * Generic element selectors for untagged primitives
21
+ */
22
+ const GENERIC_SELECTORS: Record<string, string> = {
23
+ button: "button:not([data-sonance-name])",
24
+ input: "input:not([data-sonance-name])",
25
+ select: "select:not([data-sonance-name])",
26
+ textarea: "textarea:not([data-sonance-name])",
27
+ };
28
+
29
+ /**
30
+ * Detect components on the page
31
+ * Handles both explicitly tagged components and generic primitives
32
+ */
33
+ export function detectComponents(config: ComponentDetectionConfig): DetectedElement[] {
34
+ const { isInActiveLayer, getVisibleRect } = config;
35
+ const detected: DetectedElement[] = [];
36
+
37
+ // 1. Scan for explicitly tagged components
38
+ const taggedComponents = document.querySelectorAll("[data-sonance-name]");
39
+ taggedComponents.forEach((el) => {
40
+ if (!isInActiveLayer(el)) return;
41
+
42
+ const name = el.getAttribute("data-sonance-name");
43
+ if (!name) return;
44
+
45
+ const rawRect = el.getBoundingClientRect();
46
+ const rect = getVisibleRect(el, rawRect);
47
+ if (!rect || rect.width <= 0 || rect.height <= 0) return;
48
+
49
+ // Get or generate stable variant ID
50
+ let variantId = el.getAttribute("data-sonance-variant");
51
+ if (!variantId) {
52
+ variantId = generateVariantId(el);
53
+ el.setAttribute("data-sonance-variant", variantId);
54
+ }
55
+
56
+ // Capture metadata for AI context
57
+ const textContent = (el.textContent?.trim() || "").substring(0, 100);
58
+ const className = el.className?.toString() || "";
59
+ const elementId = el.id || undefined;
60
+ const childIds = Array.from(el.querySelectorAll("[id]"))
61
+ .map((child) => child.id)
62
+ .filter((id) => id) as string[];
63
+
64
+ detected.push({
65
+ name,
66
+ rect,
67
+ type: "component",
68
+ variantId,
69
+ textContent,
70
+ className,
71
+ elementId,
72
+ childIds: childIds.length > 0 ? childIds : undefined,
73
+ });
74
+ });
75
+
76
+ // 2. Scan for untagged primitive elements
77
+ for (const [genericName, selector] of Object.entries(GENERIC_SELECTORS)) {
78
+ const elements = document.querySelectorAll(selector);
79
+ elements.forEach((el) => {
80
+ if (!isInActiveLayer(el)) return;
81
+
82
+ const rawRect = el.getBoundingClientRect();
83
+ const rect = getVisibleRect(el, rawRect);
84
+ if (!rect || rect.width <= 0 || rect.height <= 0) return;
85
+
86
+ // Get or generate stable variant ID
87
+ let variantId = el.getAttribute("data-sonance-variant");
88
+ if (!variantId) {
89
+ variantId = generateVariantId(el);
90
+ el.setAttribute("data-sonance-variant", variantId);
91
+ }
92
+
93
+ // Auto-tag generic elements for future detection
94
+ if (!el.getAttribute("data-sonance-name")) {
95
+ el.setAttribute("data-sonance-name", genericName);
96
+ }
97
+
98
+ // Capture metadata
99
+ const textContent = (el.textContent?.trim() || "").substring(0, 100);
100
+ const elClassName = el.className?.toString() || "";
101
+ const elementId = el.id || undefined;
102
+ const childIds = Array.from(el.querySelectorAll("[id]"))
103
+ .map((child) => child.id)
104
+ .filter((id) => id) as string[];
105
+
106
+ detected.push({
107
+ name: genericName,
108
+ rect,
109
+ type: "component",
110
+ variantId,
111
+ textContent,
112
+ className: elClassName,
113
+ elementId,
114
+ childIds: childIds.length > 0 ? childIds : undefined,
115
+ });
116
+ });
117
+ }
118
+
119
+ return detected;
120
+ }
121
+
122
+ /**
123
+ * Hook for component detection
124
+ * Returns a memoized detection function
125
+ */
126
+ export function useComponentDetection() {
127
+ const detect = useCallback((config: ComponentDetectionConfig): DetectedElement[] => {
128
+ return detectComponents(config);
129
+ }, []);
130
+
131
+ return { detectComponents: detect };
132
+ }