@antigenic-oss/paint 0.1.0

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 (158) hide show
  1. package/LICENSE +178 -0
  2. package/NOTICE +4 -0
  3. package/README.md +180 -0
  4. package/bin/paint.js +266 -0
  5. package/next-env.d.ts +6 -0
  6. package/next.config.ts +19 -0
  7. package/package.json +81 -0
  8. package/postcss.config.mjs +8 -0
  9. package/public/dev-editor-inspector.js +1872 -0
  10. package/src/app/api/claude/analyze/route.ts +319 -0
  11. package/src/app/api/claude/apply/route.ts +185 -0
  12. package/src/app/api/claude/pick-folder/route.ts +64 -0
  13. package/src/app/api/claude/scan/route.ts +221 -0
  14. package/src/app/api/claude/status/route.ts +55 -0
  15. package/src/app/api/project/scan/route.ts +634 -0
  16. package/src/app/api/project-scan/css-variables/route.ts +238 -0
  17. package/src/app/api/project-scan/route.ts +40 -0
  18. package/src/app/api/project-scan/tailwind-config/route.ts +172 -0
  19. package/src/app/api/proxy/[[...path]]/route.ts +2400 -0
  20. package/src/app/docs/DocsClient.tsx +322 -0
  21. package/src/app/docs/layout.tsx +7 -0
  22. package/src/app/docs/page.tsx +855 -0
  23. package/src/app/globals.css +176 -0
  24. package/src/app/layout.tsx +19 -0
  25. package/src/app/page.tsx +46 -0
  26. package/src/bridge/api-handlers.ts +885 -0
  27. package/src/bridge/proxy-handler.ts +329 -0
  28. package/src/bridge/server.ts +113 -0
  29. package/src/components/BreakpointTabs.tsx +72 -0
  30. package/src/components/ChangeSummaryModal.tsx +267 -0
  31. package/src/components/ConnectModal.tsx +994 -0
  32. package/src/components/Editor.tsx +90 -0
  33. package/src/components/PageSelector.tsx +208 -0
  34. package/src/components/PreviewFrame.tsx +299 -0
  35. package/src/components/ProjectFolderBanner.tsx +91 -0
  36. package/src/components/ResponsiveToolbar.tsx +222 -0
  37. package/src/components/TargetSelector.tsx +243 -0
  38. package/src/components/TopBar.tsx +315 -0
  39. package/src/components/common/CollapsibleSection.tsx +36 -0
  40. package/src/components/common/ColorPicker.tsx +920 -0
  41. package/src/components/common/EditablePre.tsx +136 -0
  42. package/src/components/common/ErrorBoundary.tsx +65 -0
  43. package/src/components/common/ResizablePanel.tsx +83 -0
  44. package/src/components/common/ScanAnimation.tsx +76 -0
  45. package/src/components/common/ToastContainer.tsx +97 -0
  46. package/src/components/common/UnitInput.tsx +77 -0
  47. package/src/components/common/VariableColorPicker.tsx +622 -0
  48. package/src/components/left-panel/AddElementPanel.tsx +237 -0
  49. package/src/components/left-panel/ComponentsPanel.tsx +609 -0
  50. package/src/components/left-panel/IconSidebar.tsx +99 -0
  51. package/src/components/left-panel/LayerNode.tsx +874 -0
  52. package/src/components/left-panel/LayerSearch.tsx +23 -0
  53. package/src/components/left-panel/LayersPanel.tsx +52 -0
  54. package/src/components/left-panel/LeftPanel.tsx +122 -0
  55. package/src/components/left-panel/PagesPanel.tsx +114 -0
  56. package/src/components/left-panel/icons.tsx +162 -0
  57. package/src/components/left-panel/terminal/ScanOverlay.tsx +66 -0
  58. package/src/components/left-panel/terminal/TerminalPanel.tsx +217 -0
  59. package/src/components/right-panel/ElementLogBox.tsx +248 -0
  60. package/src/components/right-panel/PanelTabs.tsx +83 -0
  61. package/src/components/right-panel/RightPanel.tsx +41 -0
  62. package/src/components/right-panel/changes/AiScanResultPanel.tsx +285 -0
  63. package/src/components/right-panel/changes/ChangeEntry.tsx +59 -0
  64. package/src/components/right-panel/changes/ChangelogActions.tsx +105 -0
  65. package/src/components/right-panel/changes/ChangesPanel.tsx +1474 -0
  66. package/src/components/right-panel/claude/ApplyConfirmModal.tsx +376 -0
  67. package/src/components/right-panel/claude/ClaudeErrorState.tsx +125 -0
  68. package/src/components/right-panel/claude/ClaudeIntegrationPanel.tsx +482 -0
  69. package/src/components/right-panel/claude/ClaudeProgressIndicator.tsx +76 -0
  70. package/src/components/right-panel/claude/DiffCard.tsx +130 -0
  71. package/src/components/right-panel/claude/DiffViewer.tsx +54 -0
  72. package/src/components/right-panel/claude/ProjectRootSelector.tsx +275 -0
  73. package/src/components/right-panel/claude/ResultsSummary.tsx +119 -0
  74. package/src/components/right-panel/claude/SetupFlow.tsx +315 -0
  75. package/src/components/right-panel/console/ConsolePanel.tsx +209 -0
  76. package/src/components/right-panel/design/AppearanceSection.tsx +703 -0
  77. package/src/components/right-panel/design/BackgroundSection.tsx +516 -0
  78. package/src/components/right-panel/design/BorderSection.tsx +161 -0
  79. package/src/components/right-panel/design/CSSRawView.tsx +412 -0
  80. package/src/components/right-panel/design/DesignCSSTabToggle.tsx +51 -0
  81. package/src/components/right-panel/design/DesignPanel.tsx +275 -0
  82. package/src/components/right-panel/design/ElementBreadcrumb.tsx +51 -0
  83. package/src/components/right-panel/design/GradientEditor.tsx +726 -0
  84. package/src/components/right-panel/design/LayoutSection.tsx +1948 -0
  85. package/src/components/right-panel/design/PositionSection.tsx +865 -0
  86. package/src/components/right-panel/design/PropertiesSection.tsx +86 -0
  87. package/src/components/right-panel/design/SVGSection.tsx +361 -0
  88. package/src/components/right-panel/design/ShadowBlurSection.tsx +227 -0
  89. package/src/components/right-panel/design/SizeSection.tsx +183 -0
  90. package/src/components/right-panel/design/TextSection.tsx +719 -0
  91. package/src/components/right-panel/design/icons.tsx +948 -0
  92. package/src/components/right-panel/design/inputs/BoxModelPreview.tsx +467 -0
  93. package/src/components/right-panel/design/inputs/ColorInput.tsx +43 -0
  94. package/src/components/right-panel/design/inputs/CompactInput.tsx +333 -0
  95. package/src/components/right-panel/design/inputs/DraggableLabel.tsx +118 -0
  96. package/src/components/right-panel/design/inputs/IconToggleGroup.tsx +54 -0
  97. package/src/components/right-panel/design/inputs/LinkedInputPair.tsx +174 -0
  98. package/src/components/right-panel/design/inputs/SectionHeader.tsx +79 -0
  99. package/src/components/right-panel/variables/VariablesPanel.tsx +388 -0
  100. package/src/hooks/useBridge.ts +95 -0
  101. package/src/hooks/useChangeTracker.ts +563 -0
  102. package/src/hooks/useClaudeAPI.ts +118 -0
  103. package/src/hooks/useDOMTree.ts +25 -0
  104. package/src/hooks/useKeyboardShortcuts.ts +76 -0
  105. package/src/hooks/usePostMessage.ts +589 -0
  106. package/src/hooks/useProjectScan.ts +204 -0
  107. package/src/hooks/useResizable.ts +20 -0
  108. package/src/hooks/useSelectedElement.ts +51 -0
  109. package/src/hooks/useTargetUrl.ts +81 -0
  110. package/src/inspector/DOMTraverser.ts +71 -0
  111. package/src/inspector/ElementSelector.ts +23 -0
  112. package/src/inspector/HoverHighlighter.ts +54 -0
  113. package/src/inspector/SelectionHighlighter.ts +27 -0
  114. package/src/inspector/StyleExtractor.ts +19 -0
  115. package/src/inspector/inspector.ts +17 -0
  116. package/src/inspector/messaging.ts +30 -0
  117. package/src/lib/apiBase.ts +15 -0
  118. package/src/lib/classifyElement.ts +430 -0
  119. package/src/lib/claude-bin.ts +197 -0
  120. package/src/lib/claude-stream.ts +158 -0
  121. package/src/lib/clientProjectScanner.ts +344 -0
  122. package/src/lib/componentMatcher.ts +156 -0
  123. package/src/lib/constants.ts +573 -0
  124. package/src/lib/cssVariableUtils.ts +409 -0
  125. package/src/lib/diffParser.ts +206 -0
  126. package/src/lib/folderPicker.ts +84 -0
  127. package/src/lib/gradientParser.ts +160 -0
  128. package/src/lib/projectScanner.ts +355 -0
  129. package/src/lib/promptBuilder.ts +402 -0
  130. package/src/lib/shadowParser.ts +124 -0
  131. package/src/lib/tailwindClassParser.ts +248 -0
  132. package/src/lib/textShadowUtils.ts +106 -0
  133. package/src/lib/utils.ts +299 -0
  134. package/src/lib/validatePath.ts +40 -0
  135. package/src/proxy.ts +92 -0
  136. package/src/server/terminal-server.ts +104 -0
  137. package/src/store/changeSlice.ts +288 -0
  138. package/src/store/claudeSlice.ts +222 -0
  139. package/src/store/componentSlice.ts +90 -0
  140. package/src/store/consoleSlice.ts +51 -0
  141. package/src/store/cssVariableSlice.ts +94 -0
  142. package/src/store/elementSlice.ts +78 -0
  143. package/src/store/index.ts +35 -0
  144. package/src/store/terminalSlice.ts +30 -0
  145. package/src/store/treeSlice.ts +69 -0
  146. package/src/store/uiSlice.ts +327 -0
  147. package/src/types/changelog.ts +49 -0
  148. package/src/types/claude.ts +131 -0
  149. package/src/types/component.ts +49 -0
  150. package/src/types/cssVariables.ts +18 -0
  151. package/src/types/element.ts +21 -0
  152. package/src/types/file-system-access.d.ts +27 -0
  153. package/src/types/gradient.ts +12 -0
  154. package/src/types/messages.ts +392 -0
  155. package/src/types/shadow.ts +8 -0
  156. package/src/types/tree.ts +9 -0
  157. package/tsconfig.json +42 -0
  158. package/tsconfig.server.json +12 -0
@@ -0,0 +1,267 @@
1
+ 'use client'
2
+
3
+ import { useState } from 'react'
4
+ import { useEditorStore } from '@/store'
5
+ import { BREAKPOINT_LABELS } from '@/types/changelog'
6
+ import type { Breakpoint, StyleChange } from '@/types/changelog'
7
+
8
+ interface ChangeSummaryModalProps {
9
+ onClose: () => void
10
+ }
11
+
12
+ const BREAKPOINT_ORDER: Breakpoint[] = ['desktop', 'tablet', 'mobile']
13
+
14
+ export function ChangeSummaryModal({ onClose }: ChangeSummaryModalProps) {
15
+ const styleChanges = useEditorStore((s) => s.styleChanges)
16
+ const elementSnapshots = useEditorStore((s) => s.elementSnapshots)
17
+
18
+ // Group changes by breakpoint
19
+ const grouped = BREAKPOINT_ORDER.reduce<Record<Breakpoint, StyleChange[]>>(
20
+ (acc, bp) => {
21
+ acc[bp] = styleChanges.filter((c) => c.breakpoint === bp)
22
+ return acc
23
+ },
24
+ { desktop: [], tablet: [], mobile: [] },
25
+ )
26
+
27
+ // Track which sections are collapsed
28
+ const [collapsed, setCollapsed] = useState<Record<Breakpoint, boolean>>({
29
+ desktop: false,
30
+ tablet: false,
31
+ mobile: false,
32
+ })
33
+
34
+ const toggleSection = (bp: Breakpoint) => {
35
+ setCollapsed((prev) => ({ ...prev, [bp]: !prev[bp] }))
36
+ }
37
+
38
+ // Resolve the page path for an element selector
39
+ const getPagePath = (selector: string): string => {
40
+ const snap = elementSnapshots[selector]
41
+ return snap?.pagePath || '/'
42
+ }
43
+
44
+ // Group changes within a breakpoint by element selector
45
+ const groupByElement = (changes: StyleChange[]) => {
46
+ const map = new Map<string, StyleChange[]>()
47
+ for (const c of changes) {
48
+ const existing = map.get(c.elementSelector) || []
49
+ existing.push(c)
50
+ map.set(c.elementSelector, existing)
51
+ }
52
+ return map
53
+ }
54
+
55
+ return (
56
+ <div
57
+ className="fixed inset-0 z-[9999] flex items-center justify-center"
58
+ style={{ background: 'rgba(0, 0, 0, 0.6)' }}
59
+ onClick={onClose}
60
+ >
61
+ <div
62
+ className="w-[420px] max-h-[80vh] flex flex-col rounded-lg shadow-2xl"
63
+ style={{
64
+ background: 'var(--bg-primary)',
65
+ border: '1px solid var(--border)',
66
+ }}
67
+ onClick={(e) => e.stopPropagation()}
68
+ >
69
+ {/* Header */}
70
+ <div
71
+ className="flex items-center justify-between px-4 py-3 flex-shrink-0"
72
+ style={{ borderBottom: '1px solid var(--border)' }}
73
+ >
74
+ <div className="flex items-center gap-2">
75
+ <svg
76
+ width="16"
77
+ height="16"
78
+ viewBox="0 0 24 24"
79
+ fill="none"
80
+ stroke="var(--accent)"
81
+ strokeWidth="2"
82
+ strokeLinecap="round"
83
+ strokeLinejoin="round"
84
+ >
85
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
86
+ <polyline points="14 2 14 8 20 8" />
87
+ <line x1="16" y1="13" x2="8" y2="13" />
88
+ <line x1="16" y1="17" x2="8" y2="17" />
89
+ <polyline points="10 9 9 9 8 9" />
90
+ </svg>
91
+ <span
92
+ className="text-sm font-semibold"
93
+ style={{ color: 'var(--text-primary)' }}
94
+ >
95
+ Summary of Changes
96
+ </span>
97
+ </div>
98
+ <span
99
+ className="text-xs px-2 py-0.5 rounded"
100
+ style={{
101
+ background: 'var(--bg-tertiary)',
102
+ color: 'var(--text-secondary)',
103
+ }}
104
+ >
105
+ {styleChanges.length} change{styleChanges.length !== 1 ? 's' : ''}
106
+ </span>
107
+ </div>
108
+
109
+ {/* Body — scrollable */}
110
+ <div className="flex-1 overflow-y-auto px-4 py-3">
111
+ {styleChanges.length === 0 ? (
112
+ <div
113
+ className="text-xs text-center py-6"
114
+ style={{ color: 'var(--text-muted)' }}
115
+ >
116
+ No changes tracked yet.
117
+ </div>
118
+ ) : (
119
+ <div className="flex flex-col gap-2">
120
+ {BREAKPOINT_ORDER.map((bp) => {
121
+ const changes = grouped[bp]
122
+ if (changes.length === 0) return null
123
+
124
+ const elementGroups = groupByElement(changes)
125
+
126
+ return (
127
+ <div key={bp}>
128
+ {/* Section header */}
129
+ <button
130
+ onClick={() => toggleSection(bp)}
131
+ className="w-full flex items-center justify-between py-1.5 group"
132
+ >
133
+ <div className="flex items-center gap-2">
134
+ <span
135
+ className="text-xs font-semibold"
136
+ style={{ color: 'var(--text-primary)' }}
137
+ >
138
+ {BREAKPOINT_LABELS[bp]}
139
+ </span>
140
+ <span
141
+ className="text-[11px] px-1.5 py-0.5 rounded"
142
+ style={{
143
+ background: 'var(--bg-tertiary)',
144
+ color: 'var(--text-secondary)',
145
+ }}
146
+ >
147
+ {changes.length}
148
+ </span>
149
+ </div>
150
+ <svg
151
+ width="12"
152
+ height="12"
153
+ viewBox="0 0 24 24"
154
+ fill="none"
155
+ stroke="var(--text-muted)"
156
+ strokeWidth="2"
157
+ strokeLinecap="round"
158
+ strokeLinejoin="round"
159
+ className="transition-transform"
160
+ style={{
161
+ transform: collapsed[bp]
162
+ ? 'rotate(-90deg)'
163
+ : 'rotate(0deg)',
164
+ }}
165
+ >
166
+ <polyline points="6 9 12 15 18 9" />
167
+ </svg>
168
+ </button>
169
+
170
+ {/* Divider */}
171
+ <div
172
+ className="h-px mb-2"
173
+ style={{ background: 'var(--border)' }}
174
+ />
175
+
176
+ {/* Changes list */}
177
+ {!collapsed[bp] && (
178
+ <div className="flex flex-col gap-2 mb-2">
179
+ {Array.from(elementGroups.entries()).map(
180
+ ([selector, elChanges]) => (
181
+ <div
182
+ key={selector}
183
+ className="rounded px-3 py-2"
184
+ style={{ background: 'var(--bg-tertiary)' }}
185
+ >
186
+ {/* Page path */}
187
+ <div
188
+ className="text-[10px] truncate mb-0.5"
189
+ style={{ color: 'var(--text-muted)' }}
190
+ title={getPagePath(selector)}
191
+ >
192
+ {getPagePath(selector)}
193
+ </div>
194
+ {/* Element selector */}
195
+ <div
196
+ className="text-[11px] font-mono truncate mb-1.5"
197
+ style={{ color: 'var(--accent)' }}
198
+ title={selector}
199
+ >
200
+ {selector}
201
+ </div>
202
+ {/* Properties */}
203
+ <div className="flex flex-col gap-1">
204
+ {elChanges.map((change) => (
205
+ <div
206
+ key={change.id}
207
+ className="flex items-baseline gap-1.5 text-[11px] font-mono"
208
+ >
209
+ <span
210
+ style={{ color: 'var(--text-secondary)' }}
211
+ >
212
+ {change.property}:
213
+ </span>
214
+ <span
215
+ className="truncate"
216
+ style={{ color: 'var(--text-muted)' }}
217
+ title={change.originalValue}
218
+ >
219
+ &quot;{change.originalValue}&quot;
220
+ </span>
221
+ <span
222
+ style={{ color: 'var(--text-muted)' }}
223
+ >
224
+ &rarr;
225
+ </span>
226
+ <span
227
+ className="truncate"
228
+ style={{ color: 'var(--success)' }}
229
+ title={change.newValue}
230
+ >
231
+ &quot;{change.newValue}&quot;
232
+ </span>
233
+ </div>
234
+ ))}
235
+ </div>
236
+ </div>
237
+ ),
238
+ )}
239
+ </div>
240
+ )}
241
+ </div>
242
+ )
243
+ })}
244
+ </div>
245
+ )}
246
+ </div>
247
+
248
+ {/* Footer */}
249
+ <div
250
+ className="flex items-center justify-end px-4 py-3 flex-shrink-0"
251
+ style={{ borderTop: '1px solid var(--border)' }}
252
+ >
253
+ <button
254
+ onClick={onClose}
255
+ className="px-4 py-1.5 rounded text-xs font-medium transition-colors"
256
+ style={{
257
+ background: 'var(--bg-tertiary)',
258
+ color: 'var(--text-primary)',
259
+ }}
260
+ >
261
+ Close
262
+ </button>
263
+ </div>
264
+ </div>
265
+ </div>
266
+ )
267
+ }