afterbefore 0.2.18 → 0.2.20
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/README.md +34 -58
- package/dist/overlay/index.js +7 -7
- package/dist/overlay/index.js.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/afterbefore)
|
|
4
4
|
[](https://www.npmjs.com/package/afterbefore)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Take screenshots of your Next.js app while you're building it. A small camera icon sits in the corner of your dev server — click it to capture a component, the current viewport, or the entire page. No browser extensions, no headless browsers, no extra setup.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Screenshots are named after your current git branch and saved to your Desktop, so you can quickly share before/after comparisons in pull requests.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
9
11
|
|
|
10
12
|
```bash
|
|
11
13
|
npm install afterbefore
|
|
12
14
|
```
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
Three things to add to your Next.js project:
|
|
17
|
+
|
|
18
|
+
**1. Drop the overlay into your root layout**
|
|
15
19
|
|
|
16
20
|
```tsx
|
|
17
21
|
// app/layout.tsx
|
|
@@ -29,14 +33,14 @@ export default function RootLayout({ children }) {
|
|
|
29
33
|
}
|
|
30
34
|
```
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
**2. Create the API route**
|
|
33
37
|
|
|
34
38
|
```ts
|
|
35
39
|
// app/api/afterbefore/[...path]/route.ts
|
|
36
40
|
export { GET, POST } from "afterbefore/server"
|
|
37
41
|
```
|
|
38
42
|
|
|
39
|
-
|
|
43
|
+
**3. Wrap your Next.js config**
|
|
40
44
|
|
|
41
45
|
```ts
|
|
42
46
|
// next.config.ts
|
|
@@ -47,9 +51,9 @@ export default withAfterBefore({
|
|
|
47
51
|
})
|
|
48
52
|
```
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
That's it. Start your dev server and you'll see a camera icon in the corner.
|
|
51
55
|
|
|
52
|
-
> **Next.js 16+ / Turbopack:** If `withAfterBefore` fails to import
|
|
56
|
+
> **Next.js 16+ / Turbopack:** If `withAfterBefore` fails to import, you can add the rewrite manually:
|
|
53
57
|
>
|
|
54
58
|
> ```ts
|
|
55
59
|
> rewrites: process.env.NODE_ENV === "development"
|
|
@@ -57,71 +61,43 @@ The config wrapper adds a dev-only rewrite from `/__afterbefore/*` to the API ro
|
|
|
57
61
|
> : undefined,
|
|
58
62
|
> ```
|
|
59
63
|
|
|
60
|
-
##
|
|
61
|
-
|
|
62
|
-
| Mode | Behavior |
|
|
63
|
-
|------|----------|
|
|
64
|
-
| **Component** | Hover to inspect elements — click to capture a specific component |
|
|
65
|
-
| **Viewport** | Captures the visible browser area |
|
|
66
|
-
| **Full Page** | Captures the entire document height |
|
|
67
|
-
|
|
68
|
-
Screenshots are rendered from the DOM using [snapdom](https://github.com/nicorevin/snapdom), which captures exactly what you see — logged-in state, open modals, scroll position, form inputs — without needing a headless browser.
|
|
64
|
+
## What you can capture
|
|
69
65
|
|
|
70
|
-
|
|
66
|
+
- **Component** — hover over any element to highlight it, click to capture just that component
|
|
67
|
+
- **Viewport** — captures exactly what's visible in the browser
|
|
68
|
+
- **Full Page** — captures the entire scrollable page
|
|
71
69
|
|
|
72
|
-
|
|
70
|
+
Everything is captured from the live DOM, so you get exactly what you see — logged-in state, open modals, form inputs, scroll position. No headless browser needed.
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
- **Background** — solid color (editable hex) or uploaded image (cover-fit)
|
|
76
|
-
- **Padding** — adjustable spacing around the component
|
|
77
|
-
- **Auto-scaling** — components that exceed the frame are scaled down to fit
|
|
72
|
+
## Framing (Component mode)
|
|
78
73
|
|
|
79
|
-
|
|
74
|
+
When capturing a component, you can wrap it in a presentation frame with a background color or image, adjustable padding, and preset sizes (1920×1080, 1080×1080, 1200×630, 1080×1920) or custom dimensions. Components that are too large for the frame are automatically scaled down. These settings persist across sessions.
|
|
80
75
|
|
|
81
|
-
##
|
|
76
|
+
## After you capture
|
|
82
77
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
~/Desktop/my-feature.png
|
|
87
|
-
```
|
|
78
|
+
Click the status icon to:
|
|
88
79
|
|
|
89
|
-
|
|
80
|
+
- **Open Folder** — jump to the screenshot in Finder
|
|
81
|
+
- **Copy Markdown** — get a before/after comparison table for pasting into PRs
|
|
82
|
+
- **Push to PR** — automatically commit the screenshot, push, and post a PR comment with the image (requires [GitHub CLI](https://cli.github.com/))
|
|
90
83
|
|
|
91
|
-
##
|
|
84
|
+
## Where screenshots are saved
|
|
92
85
|
|
|
93
|
-
|
|
86
|
+
By default, screenshots go to your Desktop named after the current git branch (`~/Desktop/my-feature.png`). You can change the save location in the toolbar settings.
|
|
94
87
|
|
|
95
|
-
|
|
96
|
-
- **Copy Markdown** — copies a before/after comparison table to your clipboard
|
|
97
|
-
- **Push to PR** — commits the screenshot to `.afterbefore/`, pushes, and posts a PR comment with the image (requires [GitHub CLI](https://cli.github.com/))
|
|
98
|
-
- **Reset** — start a new capture
|
|
99
|
-
|
|
100
|
-
## How it works
|
|
101
|
-
|
|
102
|
-
1. A floating camera icon appears in the corner of your dev server (draggable)
|
|
103
|
-
2. Click it to open the toolbar — pick a capture mode
|
|
104
|
-
3. For **Component** mode, hover over elements to highlight them, then click to capture
|
|
105
|
-
4. For **Viewport** or **Full Page**, the capture happens immediately
|
|
106
|
-
5. The screenshot is sent to the API route, which writes it to disk
|
|
107
|
-
6. The status menu appears with options to share or start over
|
|
88
|
+
## Requirements
|
|
108
89
|
|
|
109
|
-
|
|
90
|
+
- Next.js 14+ (app router)
|
|
91
|
+
- React 18+
|
|
92
|
+
- Node.js 18+
|
|
110
93
|
|
|
111
94
|
## Known limitations
|
|
112
95
|
|
|
113
|
-
- Web fonts may render slightly differently
|
|
114
|
-
-
|
|
115
|
-
- iframes and
|
|
116
|
-
-
|
|
117
|
-
- Next.js only (React overlay, API routes)
|
|
118
|
-
|
|
119
|
-
## Requirements
|
|
120
|
-
|
|
121
|
-
- Next.js >= 14 (app router)
|
|
122
|
-
- React >= 18
|
|
123
|
-
- Node.js >= 18
|
|
96
|
+
- Web fonts may render slightly differently
|
|
97
|
+
- Some CSS effects (`backdrop-filter`, `mix-blend-mode`) may not reproduce perfectly
|
|
98
|
+
- iframes and WebGL content are not captured
|
|
99
|
+
- Native folder picker is macOS-only
|
|
124
100
|
|
|
125
101
|
## License
|
|
126
102
|
|
|
127
|
-
|
|
103
|
+
[PolyForm Shield 1.0.0](https://polyformproject.org/licenses/shield/1.0.0)
|
package/dist/overlay/index.js
CHANGED
|
@@ -184,11 +184,11 @@ import {
|
|
|
184
184
|
Camera,
|
|
185
185
|
Check,
|
|
186
186
|
ChevronDown as ChevronDown2,
|
|
187
|
-
|
|
187
|
+
Image as Image2,
|
|
188
188
|
Eye,
|
|
189
189
|
FolderOpen,
|
|
190
190
|
LoaderCircle,
|
|
191
|
-
|
|
191
|
+
FileText,
|
|
192
192
|
Monitor,
|
|
193
193
|
MousePointer2,
|
|
194
194
|
Settings,
|
|
@@ -882,7 +882,7 @@ function snapToCorner(x, y) {
|
|
|
882
882
|
var MODES = [
|
|
883
883
|
{ mode: "component", label: "Component", icon: MousePointer2 },
|
|
884
884
|
{ mode: "viewport", label: "Viewport", icon: Monitor },
|
|
885
|
-
{ mode: "fullpage", label: "Full Page", icon:
|
|
885
|
+
{ mode: "fullpage", label: "Full Page", icon: FileText }
|
|
886
886
|
];
|
|
887
887
|
function Toolbar({
|
|
888
888
|
expanded,
|
|
@@ -1028,9 +1028,9 @@ function Toolbar({
|
|
|
1028
1028
|
onMouseEnter: () => setCameraHovered(true),
|
|
1029
1029
|
onMouseLeave: () => setCameraHovered(false),
|
|
1030
1030
|
style: {
|
|
1031
|
-
width:
|
|
1032
|
-
height:
|
|
1033
|
-
padding:
|
|
1031
|
+
width: 32,
|
|
1032
|
+
height: 32,
|
|
1033
|
+
padding: 0,
|
|
1034
1034
|
borderRadius: "50%",
|
|
1035
1035
|
display: "flex",
|
|
1036
1036
|
alignItems: "center",
|
|
@@ -1414,7 +1414,7 @@ function HistoryButton({
|
|
|
1414
1414
|
const verticalAlign = bottom ? { bottom: 0 } : { top: 0 };
|
|
1415
1415
|
const panelStyle = panelSide === "left" ? { right: "calc(100% + 10px)", ...verticalAlign } : { left: "calc(100% + 10px)", ...verticalAlign };
|
|
1416
1416
|
return /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
|
|
1417
|
-
/* @__PURE__ */ jsx2(IconButton, { active: open, tooltipSide, tooltip: !open ? "Screenshots" : void 0, onClick, children: /* @__PURE__ */ jsx2(
|
|
1417
|
+
/* @__PURE__ */ jsx2(IconButton, { active: open, tooltipSide, tooltip: !open ? "Screenshots" : void 0, onClick, children: /* @__PURE__ */ jsx2(Image2, { size: 16, strokeWidth: 1.7 }) }),
|
|
1418
1418
|
open && /* @__PURE__ */ jsxs2(
|
|
1419
1419
|
"div",
|
|
1420
1420
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/overlay/index.tsx","../../src/overlay/state.ts","../../src/overlay/capture.ts","../../src/overlay/ui/toolbar.tsx","../../src/overlay/ui/settings-panel.tsx","../../src/overlay/ui/inspector.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useState, useCallback, useEffect } from \"react\";\nimport { useOverlayState } from \"./state\";\nimport type { CaptureMode } from \"./state\";\nimport { capture, DEFAULT_FRAME_SETTINGS, type FrameSettings } from \"./capture\";\nimport { Toolbar } from \"./ui/toolbar\";\nimport { Inspector } from \"./ui/inspector\";\n\nasync function saveCapture(mode: CaptureMode, dataUrl: string) {\n try {\n const res = await fetch(\"/__afterbefore/save\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ mode, image: dataUrl }),\n });\n if (!res.ok) throw new Error(\"Save failed\");\n } catch {\n // Fallback: browser download (no branch info available client-side)\n const link = document.createElement(\"a\");\n link.download = \"screenshot.png\";\n link.href = dataUrl;\n link.click();\n }\n}\n\nexport function AfterBefore() {\n const { state, captureComplete, reset } = useOverlayState();\n const [toolbarActive, setToolbarActive] = useState(false);\n const [inspectorActive, setInspectorActive] = useState(false);\n const [loading, setLoading] = useState(false);\n const [selectedMode, setSelectedMode] = useState<CaptureMode>(\"component\");\n const [frameSettings, setFrameSettings] = useState<FrameSettings>(DEFAULT_FRAME_SETTINGS);\n\n useEffect(() => {\n try {\n const stored = localStorage.getItem(\"ab-frame-settings\");\n if (stored) {\n setFrameSettings({ ...DEFAULT_FRAME_SETTINGS, ...JSON.parse(stored) });\n } else if (localStorage.getItem(\"ab-frame-black\") === \"true\") {\n // Migration from old boolean setting\n const migrated = { ...DEFAULT_FRAME_SETTINGS, enabled: true };\n setFrameSettings(migrated);\n localStorage.setItem(\"ab-frame-settings\", JSON.stringify(migrated));\n localStorage.removeItem(\"ab-frame-black\");\n }\n } catch {\n setFrameSettings(DEFAULT_FRAME_SETTINGS);\n }\n }, []);\n\n useEffect(() => {\n if (state.phase === \"ready\") {\n const timer = setTimeout(() => {\n reset();\n }, 1500);\n return () => clearTimeout(timer);\n }\n }, [state.phase, reset]);\n\n const handleToggle = useCallback(() => {\n if (loading) return;\n\n if (state.phase === \"ready\") {\n reset();\n }\n\n if (toolbarActive || inspectorActive) {\n setToolbarActive(false);\n setInspectorActive(false);\n } else {\n if (selectedMode === \"component\") {\n setToolbarActive(true);\n setInspectorActive(true);\n } else {\n setToolbarActive(true);\n setInspectorActive(false);\n }\n }\n }, [state.phase, loading, toolbarActive, inspectorActive, selectedMode, reset]);\n\n const performCapture = useCallback(\n async (\n mode: CaptureMode,\n element?: HTMLElement,\n ) => {\n setLoading(true);\n try {\n const dataUrl = await capture({ mode, element, frameSettings });\n await saveCapture(mode, dataUrl);\n captureComplete({\n dataUrl,\n mode,\n timestamp: Date.now(),\n });\n } catch (err) {\n console.error(\"[afterbefore] Capture failed:\", err);\n } finally {\n setLoading(false);\n }\n },\n [captureComplete, frameSettings],\n );\n\n const handleToolbarCapture = useCallback(\n (mode: CaptureMode) => {\n if (mode === \"viewport\") {\n setToolbarActive(false);\n performCapture(\"viewport\");\n } else if (mode === \"fullpage\") {\n setToolbarActive(false);\n performCapture(\"fullpage\");\n } else if (mode === \"component\") {\n setInspectorActive(true);\n }\n },\n [performCapture],\n );\n\n const handleToolbarCancel = useCallback(() => {\n setToolbarActive(false);\n setInspectorActive(false);\n }, []);\n\n const handleComponentSelect = useCallback(\n (element: HTMLElement) => {\n setInspectorActive(false);\n setToolbarActive(false);\n performCapture(\"component\", element);\n },\n [performCapture],\n );\n\n const handleComponentCancel = useCallback(() => {\n setInspectorActive(false);\n setToolbarActive(true);\n }, []);\n\n const handleFrameSettingsChange = useCallback((next: FrameSettings) => {\n setFrameSettings(next);\n try {\n localStorage.setItem(\"ab-frame-settings\", JSON.stringify(next));\n } catch {\n // noop\n }\n }, []);\n\n const handleModeChange = useCallback((mode: CaptureMode) => {\n setSelectedMode(mode);\n setInspectorActive(mode === \"component\");\n }, []);\n\n return (\n <div data-afterbefore=\"true\">\n <Toolbar\n expanded={toolbarActive}\n onToggle={handleToggle}\n phase={state.phase}\n loading={loading}\n selectedMode={selectedMode}\n onModeChange={handleModeChange}\n onCapture={handleToolbarCapture}\n onCancel={handleToolbarCancel}\n frameSettings={frameSettings}\n onFrameSettingsChange={handleFrameSettingsChange}\n />\n\n {inspectorActive && (\n <Inspector onSelect={handleComponentSelect} onCancel={handleComponentCancel} />\n )}\n </div>\n );\n}\n","import { useState, useCallback } from \"react\";\n\nexport type CaptureMode = \"viewport\" | \"fullpage\" | \"component\";\n\nexport type OverlayPhase = \"idle\" | \"ready\";\n\nexport interface CaptureResult {\n dataUrl: string;\n mode: CaptureMode;\n timestamp: number;\n}\n\nexport interface OverlayState {\n phase: OverlayPhase;\n lastCapture: CaptureResult | null;\n}\n\nconst initialState: OverlayState = {\n phase: \"idle\",\n lastCapture: null,\n};\n\nexport function useOverlayState() {\n const [state, setState] = useState<OverlayState>(initialState);\n\n const captureComplete = useCallback(\n (result: CaptureResult) => {\n setState({ phase: \"ready\", lastCapture: result });\n },\n [],\n );\n\n const reset = useCallback(() => {\n setState(initialState);\n }, []);\n\n return { state, captureComplete, reset };\n}\n","import { snapdom } from \"@zumer/snapdom\";\nimport type { CaptureMode } from \"./state\";\n\nexport interface FrameSettings {\n enabled: boolean;\n size: { w: number; h: number };\n bgType: \"color\" | \"image\";\n bgColor: string;\n bgImage: string | null;\n padding: number;\n}\n\nexport const DEFAULT_FRAME_SETTINGS: FrameSettings = {\n enabled: false,\n size: { w: 1920, h: 1080 },\n bgType: \"color\",\n bgColor: \"#000000\",\n bgImage: null,\n padding: 40,\n};\n\nexport const FRAME_SIZE_PRESETS: { label: string; hint: string; w: number; h: number }[] = [\n { label: \"1920 x 1080\", hint: \"Desktop / HD\", w: 1920, h: 1080 },\n { label: \"1080 x 1080\", hint: \"Social square\", w: 1080, h: 1080 },\n { label: \"1200 x 630\", hint: \"Open Graph / link preview\", w: 1200, h: 630 },\n { label: \"1080 x 1920\", hint: \"Story / portrait\", w: 1080, h: 1920 },\n];\n\ninterface CaptureOptions {\n mode: CaptureMode;\n element?: HTMLElement;\n frameSettings?: FrameSettings;\n}\n\n/** Selectors for dev tool UI that should be excluded from capture */\nconst DEV_UI_SELECTORS = [\n // Afterbefore overlay\n \"[data-afterbefore]\",\n // Next.js dev indicators\n \"[data-nextjs-toast]\",\n \"[data-nextjs-dev-overlay]\",\n \"[data-nextjs-dialog]\",\n \"[data-nextjs-dialog-backdrop]\",\n \"[data-next-badge]\",\n \"[data-next-mark]\",\n];\n\nconst SNAPDOM_BASE = {\n exclude: DEV_UI_SELECTORS,\n excludeMode: \"remove\" as const,\n};\n\nasync function toPngDataUrl(\n el: Element,\n opts?: Record<string, unknown>,\n): Promise<string> {\n const result = await snapdom(el, { ...SNAPDOM_BASE, ...opts });\n const img = await result.toPng();\n return img.src;\n}\n\nexport async function capture(options: CaptureOptions): Promise<string> {\n const { mode, element } = options;\n\n if (mode === \"viewport\") {\n return captureViewport();\n }\n if (mode === \"fullpage\") {\n return captureFullPage();\n }\n if (mode === \"component\" && element) {\n return captureComponent(element, options.frameSettings);\n }\n throw new Error(`Invalid capture mode: ${mode}`);\n}\n\nasync function captureViewport(): Promise<string> {\n const dpr = window.devicePixelRatio || 1;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const scrollY = window.scrollY;\n\n // snapdom renders the full element content, so capture full page and crop to viewport\n const fullDataUrl = await captureFullPage();\n const img = await loadImage(fullDataUrl);\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = vw * dpr;\n canvas.height = vh * dpr;\n\n const ctx = canvas.getContext(\"2d\")!;\n ctx.drawImage(\n img,\n 0,\n scrollY * dpr,\n vw * dpr,\n vh * dpr,\n 0,\n 0,\n vw * dpr,\n vh * dpr,\n );\n\n return canvas.toDataURL(\"image/png\");\n}\n\nasync function captureFullPage(): Promise<string> {\n const scrollY = window.scrollY;\n const body = document.body;\n const html = document.documentElement;\n\n const fullHeight = Math.max(\n body.scrollHeight,\n body.offsetHeight,\n html.clientHeight,\n html.scrollHeight,\n html.offsetHeight,\n );\n\n const prevOverflow = html.style.overflow;\n const prevHeight = html.style.height;\n html.style.overflow = \"visible\";\n html.style.height = `${fullHeight}px`;\n\n try {\n return await toPngDataUrl(document.documentElement, {\n width: window.innerWidth,\n height: fullHeight,\n });\n } finally {\n html.style.overflow = prevOverflow;\n html.style.height = prevHeight;\n window.scrollTo(0, scrollY);\n }\n}\n\nasync function captureComponent(\n element: HTMLElement,\n frameSettings?: FrameSettings,\n): Promise<string> {\n const dataUrl = await toPngDataUrl(element);\n\n if (!frameSettings?.enabled) {\n return dataUrl;\n }\n\n const img = await loadImage(dataUrl);\n const dpr = window.devicePixelRatio || 1;\n\n const FRAME_W = frameSettings.size.w;\n const FRAME_H = frameSettings.size.h;\n const padding = frameSettings.padding;\n\n // Component dimensions in CSS pixels\n const compW = img.width / dpr;\n const compH = img.height / dpr;\n\n // Scale down if component exceeds frame (with padding)\n const maxW = FRAME_W - padding * 2;\n const maxH = FRAME_H - padding * 2;\n const scale = Math.min(1, maxW / compW, maxH / compH);\n\n const drawW = compW * scale * dpr;\n const drawH = compH * scale * dpr;\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = FRAME_W * dpr;\n canvas.height = FRAME_H * dpr;\n\n const ctx = canvas.getContext(\"2d\")!;\n\n // Draw background\n if (frameSettings.bgType === \"image\" && frameSettings.bgImage) {\n try {\n const bgImg = await loadImage(frameSettings.bgImage);\n drawCover(ctx, bgImg, canvas.width, canvas.height);\n } catch {\n // Fallback to color if image fails\n ctx.fillStyle = frameSettings.bgColor;\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n }\n } else {\n ctx.fillStyle = frameSettings.bgColor;\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n }\n\n // Center the component\n const dx = (canvas.width - drawW) / 2;\n const dy = (canvas.height - drawH) / 2;\n ctx.drawImage(img, dx, dy, drawW, drawH);\n\n return canvas.toDataURL(\"image/png\");\n}\n\n/** Draw image with cover-fit (like CSS background-size: cover) */\nfunction drawCover(\n ctx: CanvasRenderingContext2D,\n img: HTMLImageElement,\n cw: number,\n ch: number,\n) {\n const scale = Math.max(cw / img.width, ch / img.height);\n const sw = cw / scale;\n const sh = ch / scale;\n const sx = (img.width - sw) / 2;\n const sy = (img.height - sh) / 2;\n ctx.drawImage(img, sx, sy, sw, sh, 0, 0, cw, ch);\n}\n\nfunction loadImage(src: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = reject;\n img.src = src;\n });\n}\n","\"use client\";\n\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n ArrowUp,\n Camera,\n Check,\n ChevronDown,\n Clock,\n Eye,\n FolderOpen,\n LoaderCircle,\n Maximize,\n Monitor,\n MousePointer2,\n Settings,\n Trash2,\n X,\n} from \"lucide-react\";\nimport type { CaptureMode } from \"../state\";\nimport type { OverlayPhase } from \"../state\";\nimport { type FrameSettings } from \"../capture\";\nimport { SettingsPanel } from \"./settings-panel\";\n\ntype Corner = \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\nconst EDGE_MARGIN = 24;\nconst CONTAINER_SIZE = 38;\n\nfunction getCornerStyle(corner: Corner): React.CSSProperties {\n switch (corner) {\n case \"bottom-right\":\n return { bottom: EDGE_MARGIN, right: EDGE_MARGIN };\n case \"bottom-left\":\n return { bottom: EDGE_MARGIN, left: EDGE_MARGIN };\n case \"top-right\":\n return { top: EDGE_MARGIN, right: EDGE_MARGIN };\n case \"top-left\":\n return { top: EDGE_MARGIN, left: EDGE_MARGIN };\n }\n}\n\nfunction isBottomCorner(corner: Corner): boolean {\n return corner === \"bottom-right\" || corner === \"bottom-left\";\n}\n\nfunction isRightCorner(corner: Corner): boolean {\n return corner === \"bottom-right\" || corner === \"top-right\";\n}\n\nfunction snapToCorner(x: number, y: number): Corner {\n const cx = window.innerWidth / 2;\n const cy = window.innerHeight / 2;\n if (x < cx) {\n return y < cy ? \"top-left\" : \"bottom-left\";\n }\n return y < cy ? \"top-right\" : \"bottom-right\";\n}\n\ninterface ToolbarProps {\n expanded: boolean;\n onToggle: () => void;\n phase: OverlayPhase;\n loading: boolean;\n selectedMode: CaptureMode;\n onModeChange: (mode: CaptureMode) => void;\n onCapture: (mode: CaptureMode) => void;\n onCancel: () => void;\n frameSettings: FrameSettings;\n onFrameSettingsChange: (settings: FrameSettings) => void;\n}\n\nconst MODES: { mode: CaptureMode; label: string; icon: React.ComponentType<{ size?: number; strokeWidth?: number }> }[] = [\n { mode: \"component\", label: \"Component\", icon: MousePointer2 },\n { mode: \"viewport\", label: \"Viewport\", icon: Monitor },\n { mode: \"fullpage\", label: \"Full Page\", icon: Maximize },\n];\n\nexport function Toolbar({\n expanded,\n onToggle,\n phase,\n loading,\n selectedMode,\n onModeChange,\n onCapture,\n onCancel,\n frameSettings,\n onFrameSettingsChange,\n}: ToolbarProps) {\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [historyOpen, setHistoryOpen] = useState(false);\n const [corner, setCorner] = useState<Corner>(() => {\n try {\n const stored = localStorage.getItem(\"ab-toolbar-corner\");\n if (stored && [\"bottom-right\", \"bottom-left\", \"top-right\", \"top-left\"].includes(stored)) {\n return stored as Corner;\n }\n } catch {}\n return \"bottom-right\";\n });\n\n // Drag state\n const [dragging, setDragging] = useState(false);\n const [dragPos, setDragPos] = useState<{ x: number; y: number } | null>(null);\n const dragState = useRef<{\n dragging: boolean;\n startX: number;\n startY: number;\n origX: number;\n origY: number;\n distance: number;\n } | null>(null);\n const toolbarRef = useRef<HTMLDivElement>(null);\n\n // Camera button hover\n const [cameraHovered, setCameraHovered] = useState(false);\n\n useEffect(() => {\n if (!expanded) return;\n const onKey = (e: KeyboardEvent) => {\n if ((e.target as HTMLElement)?.tagName === \"INPUT\") {\n if (e.key === \"Escape\") {\n (e.target as HTMLElement).blur();\n }\n return;\n }\n\n if (e.key === \"Escape\") {\n if (settingsOpen) {\n setSettingsOpen(false);\n return;\n }\n onCancel();\n } else if (e.key === \"Enter\") {\n onCapture(selectedMode);\n }\n };\n\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [expanded, onCancel, onCapture, selectedMode, settingsOpen]);\n\n // Drag handlers\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n const el = toolbarRef.current;\n if (!el) return;\n const rect = el.getBoundingClientRect();\n setDragging(true);\n setDragPos({ x: rect.left, y: rect.top });\n dragState.current = {\n dragging: true,\n startX: e.clientX,\n startY: e.clientY,\n origX: rect.left,\n origY: rect.top,\n distance: 0,\n };\n },\n [],\n );\n\n useEffect(() => {\n const handleMouseMove = (e: MouseEvent) => {\n const ds = dragState.current;\n if (!ds || !ds.dragging) return;\n\n const dx = e.clientX - ds.startX;\n const dy = e.clientY - ds.startY;\n ds.distance = Math.sqrt(dx * dx + dy * dy);\n\n setDragPos({\n x: ds.origX + dx,\n y: ds.origY + dy,\n });\n };\n\n const handleMouseUp = (e: MouseEvent) => {\n const ds = dragState.current;\n if (!ds) return;\n\n if (ds.distance < 5) {\n onToggle();\n } else {\n // Snap to nearest corner based on toolbar center\n const el = toolbarRef.current;\n const w = el?.offsetWidth ?? CONTAINER_SIZE;\n const h = el?.offsetHeight ?? CONTAINER_SIZE;\n const centerX = (ds.origX + (e.clientX - ds.startX)) + w / 2;\n const centerY = (ds.origY + (e.clientY - ds.startY)) + h / 2;\n const newCorner = snapToCorner(centerX, centerY);\n setCorner(newCorner);\n try {\n localStorage.setItem(\"ab-toolbar-corner\", newCorner);\n } catch {}\n }\n\n setDragging(false);\n setDragPos(null);\n dragState.current = null;\n };\n\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n return () => {\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [onToggle]);\n\n const panelSide: \"left\" | \"right\" = isRightCorner(corner) ? \"left\" : \"right\";\n const tooltipSide: \"left\" | \"right\" = panelSide;\n const bottom = isBottomCorner(corner);\n\n // Build position style\n const positionStyle: React.CSSProperties = dragging && dragPos\n ? { left: dragPos.x, top: dragPos.y }\n : getCornerStyle(corner);\n\n const cameraTooltipLabel = expanded ? \"Close\" : undefined;\n const cameraTooltipStyle: React.CSSProperties | undefined = cameraTooltipLabel\n ? tooltipSide === \"left\"\n ? { right: \"calc(100% + 10px)\", top: \"50%\", transform: \"translateY(-50%)\" }\n : { left: \"calc(100% + 10px)\", top: \"50%\", transform: \"translateY(-50%)\" }\n : undefined;\n\n const cameraButton = (\n <div style={{ position: \"relative\" }}>\n {cameraTooltipLabel && cameraHovered && !dragging && (\n <div\n style={{\n position: \"absolute\",\n ...cameraTooltipStyle,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 6,\n padding: \"3px 8px\",\n color: \"rgba(255, 255, 255, 0.88)\",\n fontSize: 11,\n whiteSpace: \"nowrap\",\n boxShadow: \"0 8px 28px rgba(0, 0, 0, 0.28)\",\n pointerEvents: \"none\",\n }}\n >\n {cameraTooltipLabel}\n </div>\n )}\n <div\n onMouseDown={handleMouseDown}\n onMouseEnter={() => setCameraHovered(true)}\n onMouseLeave={() => setCameraHovered(false)}\n style={{\n width: 36,\n height: 36,\n padding: 2,\n borderRadius: \"50%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: dragging ? \"grabbing\" : \"pointer\",\n background: expanded && cameraHovered ? \"rgba(255, 255, 255, 0.12)\" : \"transparent\",\n transition: \"background 0.12s ease\",\n }}\n >\n <style\n dangerouslySetInnerHTML={{\n __html: `\n@keyframes ab-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}`,\n }}\n />\n {loading ? (\n <LoaderCircle\n size={16}\n strokeWidth={2}\n style={{ animation: \"ab-spin 0.8s linear infinite\", color: \"white\" }}\n />\n ) : phase === \"ready\" ? (\n <Check size={16} strokeWidth={2.6} color=\"#4ade80\" />\n ) : expanded ? (\n <X\n size={16}\n strokeWidth={1.7}\n color={cameraHovered ? \"rgba(255, 255, 255, 0.96)\" : \"rgba(255, 255, 255, 0.52)\"}\n />\n ) : (\n <Camera\n size={16}\n strokeWidth={1.9}\n color=\"rgba(255, 255, 255, 0.52)\"\n />\n )}\n </div>\n </div>\n );\n\n const toolbarButtons = expanded ? (\n <>\n <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: 2, padding: \"4px 0\" }}>\n {MODES.map(({ mode, label, icon: ModeIcon }) => (\n <IconButton\n key={mode}\n active={selectedMode === mode}\n tooltipSide={tooltipSide}\n tooltip={label}\n onClick={() => {\n setSettingsOpen(false);\n setHistoryOpen(false);\n if (mode === \"viewport\" || mode === \"fullpage\") {\n onModeChange(mode);\n onCapture(mode);\n } else {\n onModeChange(mode);\n }\n }}\n >\n <ModeIcon size={16} strokeWidth={1.7} />\n </IconButton>\n ))}\n </div>\n\n <Separator vertical={false} />\n\n <SettingsButton\n open={settingsOpen}\n onClick={() => {\n setSettingsOpen((prev) => !prev);\n setHistoryOpen(false);\n }}\n selectedMode={selectedMode}\n frameSettings={frameSettings}\n onFrameSettingsChange={onFrameSettingsChange}\n panelSide={panelSide}\n tooltipSide={tooltipSide}\n bottom={bottom}\n />\n\n <HistoryButton\n open={historyOpen}\n onClick={() => {\n setHistoryOpen((prev) => !prev);\n setSettingsOpen(false);\n }}\n panelSide={panelSide}\n tooltipSide={tooltipSide}\n bottom={bottom}\n />\n\n <Separator vertical={false} />\n </>\n ) : null;\n\n return (\n <div\n ref={toolbarRef}\n data-afterbefore=\"true\"\n style={{\n position: \"fixed\",\n ...positionStyle,\n zIndex: 2147483647,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n background: \"rgb(32, 32, 36)\",\n borderRadius: 999,\n padding: 6,\n boxShadow: \"0 8px 32px rgba(0, 0, 0, 0.4)\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n userSelect: \"none\",\n }}\n >\n {bottom ? (\n <>\n {toolbarButtons}\n {cameraButton}\n </>\n ) : (\n <>\n {cameraButton}\n {toolbarButtons}\n </>\n )}\n </div>\n );\n}\n\nfunction IconButton({\n children,\n active,\n tooltip,\n tooltipSide = \"left\",\n onClick,\n}: {\n children: React.ReactNode;\n active?: boolean;\n tooltip?: string;\n tooltipSide?: \"left\" | \"right\";\n onClick: () => void;\n}) {\n const [hovered, setHovered] = useState(false);\n\n const tooltipStyle: React.CSSProperties = tooltipSide === \"left\"\n ? {\n right: \"calc(100% + 10px)\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n }\n : {\n left: \"calc(100% + 10px)\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n };\n\n return (\n <div style={{ position: \"relative\" }}>\n {tooltip && hovered && (\n <div\n style={{\n position: \"absolute\",\n ...tooltipStyle,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 6,\n padding: \"3px 8px\",\n color: \"rgba(255, 255, 255, 0.88)\",\n fontSize: 11,\n whiteSpace: \"nowrap\",\n boxShadow: \"0 8px 28px rgba(0, 0, 0, 0.28)\",\n pointerEvents: \"none\",\n }}\n >\n {tooltip}\n </div>\n )}\n\n <button\n onClick={onClick}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n border: \"none\",\n background: active || hovered\n ? \"rgba(255, 255, 255, 0.12)\"\n : \"transparent\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n padding: 0,\n color: active || hovered\n ? \"rgba(255, 255, 255, 0.96)\"\n : \"rgba(255, 255, 255, 0.52)\",\n transition: \"background 0.12s ease, color 0.12s ease\",\n }}\n >\n {children}\n </button>\n </div>\n );\n}\n\nfunction SettingsButton({\n open,\n onClick,\n selectedMode,\n frameSettings,\n onFrameSettingsChange,\n panelSide,\n tooltipSide,\n bottom,\n}: {\n open: boolean;\n onClick: () => void;\n selectedMode: CaptureMode;\n frameSettings: FrameSettings;\n onFrameSettingsChange: (settings: FrameSettings) => void;\n panelSide: \"left\" | \"right\";\n tooltipSide: \"left\" | \"right\";\n bottom: boolean;\n}) {\n const verticalAlign = bottom ? { bottom: 0 } : { top: 0 };\n const panelStyle: React.CSSProperties = panelSide === \"left\"\n ? { right: \"calc(100% + 10px)\", ...verticalAlign }\n : { left: \"calc(100% + 10px)\", ...verticalAlign };\n\n return (\n <div style={{ position: \"relative\" }}>\n <IconButton active={open} tooltipSide={tooltipSide} tooltip={!open ? \"Settings\" : undefined} onClick={onClick}>\n <Settings size={16} strokeWidth={1.7} />\n </IconButton>\n\n {open && (\n <SettingsPanel\n style={{ position: \"absolute\", ...panelStyle }}\n onClose={onClick}\n selectedMode={selectedMode}\n frameSettings={frameSettings}\n onFrameSettingsChange={onFrameSettingsChange}\n />\n )}\n </div>\n );\n}\n\n\n\n\n\n\n\nfunction DropItem({\n children,\n onClick,\n active,\n accent,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n active?: boolean;\n accent?: boolean;\n}) {\n return (\n <button\n onClick={onClick}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"7px 12px\",\n background: active ? \"rgba(255, 255, 255, 0.08)\" : \"transparent\",\n border: \"none\",\n color: accent\n ? \"rgba(125, 211, 252, 0.96)\"\n : \"rgba(255, 255, 255, 0.86)\",\n textAlign: \"left\",\n cursor: \"pointer\",\n fontSize: 13,\n fontFamily: \"inherit\",\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction Separator({ vertical = true }: { vertical?: boolean }) {\n return (\n <div\n style={{\n width: vertical ? 1 : 24,\n height: vertical ? 18 : 1,\n background: \"rgba(255,255,255,0.12)\",\n flexShrink: 0,\n margin: vertical ? \"0 6px\" : \"6px 0\",\n }}\n />\n );\n}\n\ninterface ScreenshotMeta {\n filename: string;\n timestamp: string;\n}\n\nfunction HistoryButton({\n open,\n onClick,\n panelSide,\n tooltipSide,\n bottom,\n}: {\n open: boolean;\n onClick: () => void;\n panelSide: \"left\" | \"right\";\n tooltipSide: \"left\" | \"right\";\n bottom: boolean;\n}) {\n const [toast, setToast] = useState<{ message: string; type: \"success\" | \"error\" } | null>(null);\n const [pushing, setPushing] = useState(false);\n\n const [repos, setRepos] = useState<string[]>([]);\n const [branches, setBranches] = useState<string[]>([]);\n const [screenshots, setScreenshots] = useState<ScreenshotMeta[]>([]);\n const [selectedRepo, setSelectedRepo] = useState<string | null>(null);\n const [selectedBranch, setSelectedBranch] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [repoDropOpen, setRepoDropOpen] = useState(false);\n const [branchDropOpen, setBranchDropOpen] = useState(false);\n const [lightboxSrc, setLightboxSrc] = useState<string | null>(null);\n const [editingFile, setEditingFile] = useState<string | null>(null);\n const [editValue, setEditValue] = useState(\"\");\n const [hoveredThumb, setHoveredThumb] = useState<string | null>(null);\n\n useEffect(() => {\n if (!open) {\n setRepoDropOpen(false);\n setBranchDropOpen(false);\n return;\n }\n setLoading(true);\n const params = new URLSearchParams();\n if (selectedRepo) params.set(\"repo\", selectedRepo);\n if (selectedBranch) params.set(\"branch\", selectedBranch);\n fetch(`/__afterbefore/history?${params}`)\n .then((r) => r.json())\n .then((data) => {\n setRepos(data.repos || []);\n setBranches(data.branches || []);\n setScreenshots(data.screenshots || []);\n if (!selectedRepo && data.currentRepo) setSelectedRepo(data.currentRepo);\n if (!selectedBranch && data.currentBranch) setSelectedBranch(data.currentBranch);\n })\n .catch(() => {})\n .finally(() => setLoading(false));\n }, [open, selectedRepo, selectedBranch]);\n\n const showToast = useCallback((message: string, type: \"success\" | \"error\") => {\n setToast({ message, type });\n setTimeout(() => setToast(null), 3000);\n }, []);\n\n const handleOpenFolder = async () => {\n try {\n const body = selectedRepo && selectedBranch\n ? JSON.stringify({ repo: selectedRepo, branch: selectedBranch })\n : undefined;\n const res = await fetch(\"/__afterbefore/open\", {\n method: \"POST\",\n headers: body ? { \"Content-Type\": \"application/json\" } : undefined,\n body,\n });\n if (!res.ok) throw new Error();\n showToast(\"Opened folder\", \"success\");\n } catch {\n showToast(\"Could not open folder\", \"error\");\n }\n };\n\n const handleRename = async (oldName: string, newName: string) => {\n if (!newName.trim() || newName.trim() === oldName.replace(/\\.png$/, \"\")) {\n setEditingFile(null);\n return;\n }\n try {\n const res = await fetch(\"/__afterbefore/history/rename\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n repo: selectedRepo,\n branch: selectedBranch,\n oldName,\n newName: newName.trim(),\n }),\n });\n if (!res.ok) throw new Error();\n const data = await res.json();\n setScreenshots((prev) =>\n prev.map((s) =>\n s.filename === oldName\n ? { ...s, filename: data.filename, timestamp: data.filename.replace(/\\.png$/, \"\") }\n : s,\n ),\n );\n showToast(\"Renamed\", \"success\");\n } catch {\n showToast(\"Rename failed\", \"error\");\n }\n setEditingFile(null);\n };\n\n const handleDelete = async (filename: string) => {\n try {\n const res = await fetch(\"/__afterbefore/history/delete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n repo: selectedRepo,\n branch: selectedBranch,\n file: filename,\n }),\n });\n if (!res.ok) throw new Error();\n setScreenshots((prev) => prev.filter((s) => s.filename !== filename));\n showToast(\"Deleted\", \"success\");\n } catch {\n showToast(\"Delete failed\", \"error\");\n }\n };\n\n const handlePush = async () => {\n setPushing(true);\n try {\n const res = await fetch(\"/__afterbefore/push\", { method: \"POST\" });\n const data = await res.json();\n if (!res.ok) {\n showToast(data.error || \"Push failed\", \"error\");\n } else if (data.pr) {\n showToast(`Posted to PR #${data.pr}`, \"success\");\n } else {\n showToast(\"No PR found\", \"error\");\n }\n } catch {\n showToast(\"Push failed\", \"error\");\n } finally {\n setPushing(false);\n }\n };\n\n const verticalAlign = bottom ? { bottom: 0 } : { top: 0 };\n const panelStyle: React.CSSProperties = panelSide === \"left\"\n ? { right: \"calc(100% + 10px)\", ...verticalAlign }\n : { left: \"calc(100% + 10px)\", ...verticalAlign };\n\n return (\n <div style={{ position: \"relative\" }}>\n <IconButton active={open} tooltipSide={tooltipSide} tooltip={!open ? \"Screenshots\" : undefined} onClick={onClick}>\n <Clock size={16} strokeWidth={1.7} />\n </IconButton>\n\n {open && (\n <div\n style={{\n position: \"absolute\",\n ...panelStyle,\n minWidth: 300,\n maxWidth: 360,\n padding: \"10px 12px\",\n borderRadius: 12,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"0 14px 36px rgba(0, 0, 0, 0.32)\",\n }}\n >\n <div\n style={{\n fontSize: 11,\n color: \"rgba(255, 255, 255, 0.46)\",\n letterSpacing: \"0.03em\",\n textTransform: \"uppercase\",\n marginBottom: 10,\n }}\n >\n Screenshots\n </div>\n\n {/* Filter dropdowns */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6, marginBottom: 10 }}>\n <FilterDropdown\n label=\"Project\"\n value={selectedRepo}\n options={repos}\n isOpen={repoDropOpen}\n onToggle={() => {\n setRepoDropOpen((p) => !p);\n setBranchDropOpen(false);\n }}\n onSelect={(repo) => {\n setSelectedRepo(repo);\n setSelectedBranch(null);\n setRepoDropOpen(false);\n }}\n />\n <FilterDropdown\n label=\"Branch\"\n value={selectedBranch}\n options={branches}\n isOpen={branchDropOpen}\n onToggle={() => {\n setBranchDropOpen((p) => !p);\n setRepoDropOpen(false);\n }}\n onSelect={(branch) => {\n setSelectedBranch(branch);\n setBranchDropOpen(false);\n }}\n />\n </div>\n\n {loading ? (\n <div\n style={{\n padding: \"12px 0\",\n textAlign: \"center\",\n fontSize: 12,\n color: \"rgba(255, 255, 255, 0.35)\",\n }}\n >\n Loading...\n </div>\n ) : screenshots.length === 0 ? (\n <div\n style={{\n padding: \"12px 0\",\n textAlign: \"center\",\n fontSize: 12,\n color: \"rgba(255, 255, 255, 0.35)\",\n }}\n >\n No screenshots yet\n </div>\n ) : (\n <>\n <div\n style={{\n maxHeight: 240,\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 8,\n }}\n >\n {screenshots.map((shot) => {\n const imgUrl = `/__afterbefore/history/image?repo=${encodeURIComponent(selectedRepo || \"\")}&branch=${encodeURIComponent(selectedBranch || \"\")}&file=${encodeURIComponent(shot.filename)}`;\n const isEditing = editingFile === shot.filename;\n return (\n <div\n key={shot.filename}\n style={{\n display: \"flex\",\n gap: 10,\n alignItems: \"center\",\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: 56,\n height: 36,\n flexShrink: 0,\n borderRadius: 4,\n overflow: \"hidden\",\n cursor: \"pointer\",\n }}\n onMouseEnter={() => setHoveredThumb(shot.filename)}\n onMouseLeave={() => setHoveredThumb(null)}\n onClick={() => setLightboxSrc(imgUrl)}\n >\n <img\n src={imgUrl}\n alt=\"\"\n style={{\n width: 56,\n height: 36,\n objectFit: \"cover\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 4,\n background: \"rgba(255, 255, 255, 0.05)\",\n display: \"block\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background: \"rgba(0, 0, 0, 0.55)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: 4,\n opacity: hoveredThumb === shot.filename ? 1 : 0,\n transition: \"opacity 0.15s ease\",\n }}\n >\n <Eye size={16} strokeWidth={1.8} color=\"rgba(255, 255, 255, 0.9)\" />\n </div>\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n {isEditing ? (\n <input\n autoFocus\n value={editValue}\n onChange={(e) => setEditValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleRename(shot.filename, editValue);\n if (e.key === \"Escape\") setEditingFile(null);\n }}\n onBlur={() => handleRename(shot.filename, editValue)}\n style={{\n width: \"100%\",\n fontSize: 12,\n color: \"rgba(255, 255, 255, 0.88)\",\n background: \"rgba(255, 255, 255, 0.1)\",\n border: \"1px solid rgba(255, 255, 255, 0.2)\",\n borderRadius: 4,\n padding: \"2px 6px\",\n outline: \"none\",\n fontFamily: \"inherit\",\n }}\n />\n ) : (\n <div\n onClick={() => {\n setEditingFile(shot.filename);\n setEditValue(shot.filename.replace(/\\.png$/, \"\"));\n }}\n style={{\n fontSize: 12,\n color: \"rgba(255, 255, 255, 0.88)\",\n cursor: \"pointer\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n title=\"Click to rename\"\n >\n {formatTimestamp(shot.filename)}\n </div>\n )}\n </div>\n <button\n onClick={() => handleDelete(shot.filename)}\n title=\"Delete screenshot\"\n style={{\n flexShrink: 0,\n width: 24,\n height: 24,\n borderRadius: 4,\n border: \"none\",\n background: \"transparent\",\n color: \"rgba(255, 255, 255, 0.35)\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 0,\n }}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLButtonElement).style.color = \"rgba(239, 68, 68, 0.9)\";\n (e.currentTarget as HTMLButtonElement).style.background = \"rgba(239, 68, 68, 0.1)\";\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLButtonElement).style.color = \"rgba(255, 255, 255, 0.35)\";\n (e.currentTarget as HTMLButtonElement).style.background = \"transparent\";\n }}\n >\n <Trash2 size={13} strokeWidth={1.8} />\n </button>\n </div>\n );\n })}\n </div>\n\n <div\n style={{\n height: 1,\n background: \"rgba(255, 255, 255, 0.08)\",\n margin: \"8px 0\",\n }}\n />\n\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 2 }}>\n <ActionButton onClick={handleOpenFolder}>\n <FolderOpen size={13} strokeWidth={1.8} />\n Open Folder\n </ActionButton>\n <ActionButton onClick={handlePush} disabled={pushing}>\n <ArrowUp size={13} strokeWidth={1.8} />\n {pushing ? \"Pushing...\" : \"Push to PR\"}\n </ActionButton>\n </div>\n </>\n )}\n\n {toast && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: 8,\n padding: \"6px 12px\",\n borderRadius: 6,\n fontSize: 12,\n fontWeight: 500,\n whiteSpace: \"nowrap\",\n color: \"white\",\n background:\n toast.type === \"success\"\n ? \"rgba(34, 197, 94, 0.9)\"\n : \"rgba(239, 68, 68, 0.9)\",\n boxShadow: \"0 2px 8px rgba(0,0,0,0.3)\",\n }}\n >\n {toast.message}\n </div>\n )}\n </div>\n )}\n\n {lightboxSrc && (\n <div\n onClick={() => setLightboxSrc(null)}\n onKeyDown={(e) => { if (e.key === \"Escape\") setLightboxSrc(null); }}\n style={{\n position: \"fixed\",\n inset: 0,\n bottom: 100,\n zIndex: 2147483646,\n background: \"rgba(0, 0, 0, 0.85)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"zoom-out\",\n }}\n >\n <img\n src={lightboxSrc}\n alt=\"\"\n onClick={(e) => e.stopPropagation()}\n style={{\n maxWidth: \"90vw\",\n maxHeight: \"calc(100% - 32px)\",\n borderRadius: 8,\n boxShadow: \"0 20px 60px rgba(0, 0, 0, 0.5)\",\n cursor: \"default\",\n }}\n />\n <button\n onClick={() => setLightboxSrc(null)}\n style={{\n position: \"absolute\",\n top: 16,\n right: 16,\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n border: \"none\",\n background: \"rgba(255, 255, 255, 0.15)\",\n color: \"white\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 0,\n }}\n >\n <X size={18} strokeWidth={2} />\n </button>\n </div>\n )}\n </div>\n );\n}\n\nfunction FilterDropdown({\n label,\n value,\n options,\n isOpen,\n onToggle,\n onSelect,\n}: {\n label: string;\n value: string | null;\n options: string[];\n isOpen: boolean;\n onToggle: () => void;\n onSelect: (value: string) => void;\n}) {\n return (\n <div>\n <div\n style={{\n fontSize: 11,\n color: \"rgba(255, 255, 255, 0.42)\",\n letterSpacing: \"0.02em\",\n marginBottom: 3,\n }}\n >\n {label}\n </div>\n <div style={{ position: \"relative\" }}>\n <button\n onClick={onToggle}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: 6,\n width: \"100%\",\n height: 30,\n padding: \"0 8px\",\n borderRadius: 7,\n border: \"1px solid rgba(255,255,255,0.1)\",\n background: \"rgba(255,255,255,0.07)\",\n color: \"rgba(255,255,255,0.88)\",\n cursor: \"pointer\",\n fontSize: 12,\n fontFamily: \"inherit\",\n }}\n >\n <span\n style={{\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {value || \"\\u2014\"}\n </span>\n <ChevronDown size={12} strokeWidth={2} />\n </button>\n\n {isOpen && options.length > 0 && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 4px)\",\n left: 0,\n right: 0,\n maxHeight: 160,\n overflowY: \"auto\",\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 8,\n padding: \"4px 0\",\n boxShadow: \"0 10px 30px rgba(0, 0, 0, 0.3)\",\n zIndex: 1,\n }}\n >\n {options.map((opt) => (\n <DropItem\n key={opt}\n active={opt === value}\n onClick={() => onSelect(opt)}\n >\n {opt}\n </DropItem>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction ActionButton({\n children,\n onClick,\n disabled,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n}) {\n const [hovered, setHovered] = useState(false);\n\n return (\n <button\n onClick={onClick}\n disabled={disabled}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n width: \"100%\",\n padding: \"6px 8px\",\n border: \"none\",\n background: hovered ? \"rgba(255, 255, 255, 0.08)\" : \"transparent\",\n color: \"rgba(255, 255, 255, 0.78)\",\n fontSize: 12,\n borderRadius: 6,\n cursor: disabled ? \"wait\" : \"pointer\",\n textAlign: \"left\" as const,\n fontFamily: \"inherit\",\n transition: \"background 0.1s ease\",\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction formatTimestamp(filename: string): string {\n // Filename format: \"2026-03-18T23-05-12-345Z.png\"\n // Reverse the ISO replacement: restore colons and dots\n const iso = filename\n .replace(/\\.png$/, \"\")\n .replace(/T(\\d{2})-(\\d{2})-(\\d{2})-(\\d+)Z$/, \"T$1:$2:$3.$4Z\");\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) return filename.replace(/\\.png$/, \"\");\n\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMin = Math.floor(diffMs / 60000);\n\n if (diffMin < 1) return \"Just now\";\n if (diffMin < 60) return `${diffMin}m ago`;\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return `${diffHr}h ago`;\n\n return date.toLocaleDateString(undefined, { month: \"short\", day: \"numeric\", hour: \"2-digit\", minute: \"2-digit\" });\n}\n","\"use client\";\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport {\n ChevronDown,\n ImageIcon,\n Palette,\n Trash2,\n Upload,\n X,\n} from \"lucide-react\";\nimport type { CaptureMode } from \"../state\";\nimport { FRAME_SIZE_PRESETS, type FrameSettings } from \"../capture\";\n\nexport function SettingsPanel({\n style,\n onClose,\n selectedMode,\n frameSettings,\n onFrameSettingsChange,\n}: {\n style?: React.CSSProperties;\n onClose: () => void;\n selectedMode: CaptureMode;\n frameSettings: FrameSettings;\n onFrameSettingsChange: (settings: FrameSettings) => void;\n}) {\n const [saveDir, setSaveDir] = useState<string | null>(null);\n const [picking, setPicking] = useState(false);\n\n useEffect(() => {\n fetch(\"/__afterbefore/config\")\n .then((r) => r.json())\n .then((data) => setSaveDir(data.saveDir))\n .catch(() => {});\n }, []);\n\n const handlePickFolder = async () => {\n setPicking(true);\n try {\n const res = await fetch(\"/__afterbefore/pick-folder\", { method: \"POST\" });\n const data = await res.json();\n if (data.folder) {\n await fetch(\"/__afterbefore/config\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ saveDir: data.folder }),\n });\n setSaveDir(data.folder);\n }\n } catch {\n // noop\n } finally {\n setPicking(false);\n }\n };\n\n const shortDir = saveDir\n ? saveDir.replace(/^\\/Users\\/[^/]+/, \"~\")\n : \"~/Desktop\";\n\n return (\n <div\n style={{\n minWidth: 300,\n padding: \"12px 16px\",\n borderRadius: 12,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"0 14px 36px rgba(0, 0, 0, 0.32)\",\n ...style,\n }}\n >\n <SettingsHeader onClose={onClose} />\n\n <SettingsDivider />\n\n {selectedMode === \"component\" && (\n <>\n <SettingsRow\n title=\"Frame\"\n description=\"Wrap in a sized canvas with background\"\n control={\n <ToggleSwitch\n enabled={frameSettings.enabled}\n onChange={() =>\n onFrameSettingsChange({ ...frameSettings, enabled: !frameSettings.enabled })\n }\n />\n }\n />\n\n {frameSettings.enabled && (\n <>\n <SettingsDivider />\n\n <FrameSizeControl\n size={frameSettings.size}\n onChange={(size) => onFrameSettingsChange({ ...frameSettings, size })}\n />\n\n <SettingsDivider />\n\n <FrameBackgroundControl\n bgType={frameSettings.bgType}\n bgColor={frameSettings.bgColor}\n bgImage={frameSettings.bgImage}\n frameSize={frameSettings.size}\n onChange={(updates) => onFrameSettingsChange({ ...frameSettings, ...updates })}\n />\n </>\n )}\n\n <SettingsDivider />\n </>\n )}\n\n <SettingsRow\n title=\"Save Location\"\n description={\n <span\n style={{\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n display: \"block\",\n }}\n title={shortDir}\n >\n {shortDir}\n </span>\n }\n control={\n <SmallButton onClick={handlePickFolder}>\n {picking ? \"...\" : \"Change\"}\n </SmallButton>\n }\n />\n </div>\n );\n}\n\nfunction SettingsHeader({ onClose }: { onClose: () => void }) {\n const [hovered, setHovered] = useState(false);\n\n return (\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", paddingBottom: 8 }}>\n <span style={{ fontSize: 14, fontWeight: 600, color: \"rgba(255, 255, 255, 0.92)\" }}>\n Settings\n </span>\n <button\n onClick={onClose}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n width: 24,\n height: 24,\n borderRadius: 6,\n border: \"none\",\n background: hovered ? \"rgba(255, 255, 255, 0.1)\" : \"transparent\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n color: hovered ? \"rgba(255, 255, 255, 0.8)\" : \"rgba(255, 255, 255, 0.46)\",\n padding: 0,\n transition: \"background 0.12s ease, color 0.12s ease\",\n }}\n >\n <X size={14} strokeWidth={2} />\n </button>\n </div>\n );\n}\n\nfunction SettingsRow({\n title,\n description,\n control,\n}: {\n title: string;\n description?: string | React.ReactNode;\n control: React.ReactNode;\n}) {\n return (\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 16, padding: \"14px 0\" }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3, flex: 1, minWidth: 0 }}>\n <span style={{ fontSize: 13, fontWeight: 600, color: \"rgba(255, 255, 255, 0.92)\" }}>\n {title}\n </span>\n {description && (\n <span style={{ fontSize: 11, color: \"rgba(255, 255, 255, 0.42)\", lineHeight: 1.3 }}>\n {description}\n </span>\n )}\n </div>\n <div style={{ flexShrink: 0 }}>\n {control}\n </div>\n </div>\n );\n}\n\nfunction SettingsDivider() {\n return <div style={{ height: 1, background: \"rgba(255, 255, 255, 0.08)\" }} />;\n}\n\nfunction ToggleSwitch({\n enabled,\n onChange,\n}: {\n enabled: boolean;\n onChange: () => void;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onChange}\n style={{\n width: 38,\n height: 22,\n borderRadius: 999,\n border: \"none\",\n background: enabled ? \"#38bdf8\" : \"rgba(255, 255, 255, 0.18)\",\n position: \"relative\",\n cursor: \"pointer\",\n padding: 0,\n flexShrink: 0,\n transition: \"background 0.12s ease\",\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 2,\n left: enabled ? 18 : 2,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.12s ease\",\n }}\n />\n </button>\n );\n}\n\nfunction FrameSizeControl({\n size,\n onChange,\n}: {\n size: { w: number; h: number };\n onChange: (size: { w: number; h: number }) => void;\n}) {\n const [sizeOpen, setSizeOpen] = useState(false);\n\n const currentPreset = FRAME_SIZE_PRESETS.find((p) => p.w === size.w && p.h === size.h);\n const isCustom = !currentPreset;\n\n return (\n <div style={{ padding: \"14px 0\" }}>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 16 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3 }}>\n <span style={{ fontSize: 13, fontWeight: 600, color: \"rgba(255, 255, 255, 0.92)\" }}>Size</span>\n <span style={{ fontSize: 11, color: \"rgba(255, 255, 255, 0.42)\", lineHeight: 1.3 }}>Set the frame dimensions</span>\n </div>\n <div style={{ position: \"relative\", flexShrink: 0 }}>\n <button\n onClick={() => setSizeOpen((prev) => !prev)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n height: 30,\n padding: \"0 10px\",\n borderRadius: 7,\n border: \"1px solid rgba(255,255,255,0.1)\",\n background: \"rgba(255,255,255,0.07)\",\n color: \"rgba(255,255,255,0.88)\",\n cursor: \"pointer\",\n fontSize: 12,\n fontFamily: \"inherit\",\n whiteSpace: \"nowrap\",\n }}\n >\n {currentPreset ? currentPreset.label : \"Custom\"}\n <ChevronDown size={12} strokeWidth={2} />\n </button>\n\n {sizeOpen && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 4px)\",\n right: 0,\n minWidth: 180,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 8,\n padding: \"4px 0\",\n boxShadow: \"0 10px 30px rgba(0, 0, 0, 0.3)\",\n zIndex: 1,\n }}\n >\n {FRAME_SIZE_PRESETS.map((preset) => (\n <DropItem\n key={preset.label}\n active={!isCustom && preset.w === size.w && preset.h === size.h}\n onClick={() => {\n onChange({ w: preset.w, h: preset.h });\n setSizeOpen(false);\n }}\n >\n <span>{preset.label}</span>\n <span style={{ marginLeft: 6, fontSize: 10, color: \"rgba(255,255,255,0.34)\" }}>\n {preset.hint}\n </span>\n </DropItem>\n ))}\n </div>\n )}\n </div>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4, marginTop: 10 }}>\n <NumInput\n value={size.w}\n onChange={(v) => {\n const n = parseInt(v, 10);\n if (!Number.isNaN(n) && n > 0) onChange({ ...size, w: n });\n }}\n />\n <StaticText>x</StaticText>\n <NumInput\n value={size.h}\n onChange={(v) => {\n const n = parseInt(v, 10);\n if (!Number.isNaN(n) && n > 0) onChange({ ...size, h: n });\n }}\n />\n </div>\n </div>\n );\n}\n\nfunction FrameBackgroundControl({\n bgType,\n bgColor,\n bgImage,\n frameSize,\n onChange,\n}: {\n bgType: \"color\" | \"image\";\n bgColor: string;\n bgImage: string | null;\n frameSize: { w: number; h: number };\n onChange: (updates: Partial<Pick<FrameSettings, \"bgType\" | \"bgColor\" | \"bgImage\">>) => void;\n}) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n if (dataUrl.length > 2 * 1024 * 1024) {\n downscaleImage(dataUrl, frameSize.w, frameSize.h).then((scaled) => {\n onChange({ bgType: \"image\", bgImage: scaled });\n });\n } else {\n onChange({ bgType: \"image\", bgImage: dataUrl });\n }\n };\n reader.readAsDataURL(file);\n e.target.value = \"\";\n };\n\n return (\n <div style={{ padding: \"14px 0\" }}>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 16 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3 }}>\n <span style={{ fontSize: 13, fontWeight: 600, color: \"rgba(255, 255, 255, 0.92)\" }}>Background</span>\n <span style={{ fontSize: 11, color: \"rgba(255, 255, 255, 0.42)\", lineHeight: 1.3 }}>Frame background color or image</span>\n </div>\n <div style={{ display: \"flex\", gap: 2, flexShrink: 0 }}>\n <SegmentButton\n active={bgType === \"color\"}\n onClick={() => onChange({ bgType: \"color\" })}\n style={{ borderRadius: \"6px 0 0 6px\" }}\n >\n <Palette size={12} strokeWidth={2} />\n Color\n </SegmentButton>\n <SegmentButton\n active={bgType === \"image\"}\n onClick={() => onChange({ bgType: \"image\" })}\n style={{ borderRadius: \"0 6px 6px 0\" }}\n >\n <ImageIcon size={12} strokeWidth={2} />\n Image\n </SegmentButton>\n </div>\n </div>\n\n {bgType === \"color\" && (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginTop: 10 }}>\n <ColorSwatch color={bgColor} onChange={(c) => onChange({ bgColor: c })} />\n <HexInput value={bgColor} onChange={(c) => onChange({ bgColor: c })} />\n </div>\n )}\n\n {bgType === \"image\" && (\n <div style={{ marginTop: 10 }}>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n style={{ display: \"none\" }}\n />\n\n {bgImage ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <img\n src={bgImage}\n alt=\"\"\n style={{\n width: 48,\n height: 28,\n borderRadius: 4,\n objectFit: \"cover\",\n border: \"1px solid rgba(255,255,255,0.12)\",\n }}\n />\n <SmallButton onClick={() => fileInputRef.current?.click()}>\n <Upload size={11} strokeWidth={2} />\n Replace\n </SmallButton>\n <SmallButton onClick={() => onChange({ bgImage: null })}>\n <Trash2 size={11} strokeWidth={2} />\n </SmallButton>\n </div>\n ) : (\n <SmallButton onClick={() => fileInputRef.current?.click()}>\n <Upload size={11} strokeWidth={2} />\n Upload image\n </SmallButton>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction SegmentButton({\n children,\n active,\n onClick,\n style,\n}: {\n children: React.ReactNode;\n active: boolean;\n onClick: () => void;\n style?: React.CSSProperties;\n}) {\n return (\n <button\n onClick={onClick}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n height: 26,\n padding: \"0 10px\",\n border: \"1px solid rgba(255,255,255,0.1)\",\n background: active ? \"rgba(255,255,255,0.14)\" : \"rgba(255,255,255,0.04)\",\n color: active ? \"rgba(255,255,255,0.92)\" : \"rgba(255,255,255,0.5)\",\n cursor: \"pointer\",\n fontSize: 11,\n fontFamily: \"inherit\",\n transition: \"background 0.12s ease, color 0.12s ease\",\n ...style,\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction ColorSwatch({\n color,\n onChange,\n}: {\n color: string;\n onChange: (color: string) => void;\n}) {\n const inputRef = useRef<HTMLInputElement>(null);\n\n return (\n <div style={{ position: \"relative\" }}>\n <button\n onClick={() => inputRef.current?.click()}\n style={{\n width: 24,\n height: 24,\n borderRadius: 6,\n border: \"1px solid rgba(255,255,255,0.18)\",\n background: color,\n cursor: \"pointer\",\n padding: 0,\n }}\n />\n <input\n ref={inputRef}\n type=\"color\"\n value={color}\n onChange={(e) => onChange(e.target.value)}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n opacity: 0,\n pointerEvents: \"none\",\n }}\n />\n </div>\n );\n}\n\nfunction SmallButton({\n children,\n onClick,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n}) {\n const [hovered, setHovered] = useState(false);\n\n return (\n <button\n onClick={onClick}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"3px 8px\",\n borderRadius: 6,\n border: \"1px solid rgba(255,255,255,0.12)\",\n background: hovered ? \"rgba(255,255,255,0.12)\" : \"rgba(255,255,255,0.06)\",\n color: \"rgba(255,255,255,0.78)\",\n fontSize: 11,\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background 0.12s ease\",\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction NumInput({\n value,\n onChange,\n}: {\n value: number;\n onChange: (value: string) => void;\n}) {\n const [editing, setEditing] = useState(false);\n const [text, setText] = useState(String(value));\n\n useEffect(() => {\n if (!editing) {\n setText(String(value));\n }\n }, [editing, value]);\n\n return (\n <input\n type=\"text\"\n value={editing ? text : String(value)}\n onFocus={() => {\n setEditing(true);\n setText(String(value));\n }}\n onBlur={() => {\n setEditing(false);\n onChange(text);\n }}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n (e.target as HTMLElement).blur();\n }\n }}\n style={{\n width: 54,\n padding: \"4px 6px\",\n background: \"rgba(255, 255, 255, 0.07)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 7,\n color: \"rgba(255, 255, 255, 0.9)\",\n fontSize: 12,\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n textAlign: \"center\",\n outline: \"none\",\n }}\n />\n );\n}\n\nfunction HexInput({\n value,\n onChange,\n}: {\n value: string;\n onChange: (color: string) => void;\n}) {\n const [editing, setEditing] = useState(false);\n const [text, setText] = useState(value);\n\n useEffect(() => {\n if (!editing) {\n setText(value);\n }\n }, [editing, value]);\n\n const commit = (raw: string) => {\n const hex = raw.startsWith(\"#\") ? raw : `#${raw}`;\n if (/^#[0-9a-fA-F]{6}$/.test(hex)) {\n onChange(hex);\n }\n };\n\n return (\n <input\n type=\"text\"\n value={editing ? text : value}\n onFocus={() => {\n setEditing(true);\n setText(value);\n }}\n onBlur={() => {\n setEditing(false);\n commit(text);\n }}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n (e.target as HTMLElement).blur();\n }\n }}\n style={{\n width: 72,\n padding: \"4px 6px\",\n background: \"rgba(255, 255, 255, 0.07)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 7,\n color: \"rgba(255, 255, 255, 0.9)\",\n fontSize: 12,\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n textAlign: \"left\",\n outline: \"none\",\n }}\n />\n );\n}\n\nfunction StaticText({ children }: { children: React.ReactNode }) {\n return (\n <span\n style={{\n fontSize: 11,\n color: \"rgba(255,255,255,0.35)\",\n minWidth: 8,\n textAlign: \"center\",\n }}\n >\n {children}\n </span>\n );\n}\n\nfunction DropItem({\n children,\n onClick,\n active,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n active?: boolean;\n}) {\n return (\n <button\n onClick={onClick}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"7px 12px\",\n background: active ? \"rgba(255, 255, 255, 0.08)\" : \"transparent\",\n border: \"none\",\n color: \"rgba(255, 255, 255, 0.86)\",\n textAlign: \"left\",\n cursor: \"pointer\",\n fontSize: 13,\n fontFamily: \"inherit\",\n }}\n >\n {children}\n </button>\n );\n}\n\nasync function downscaleImage(dataUrl: string, maxW: number, maxH: number): Promise<string> {\n return new Promise((resolve) => {\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement(\"canvas\");\n const scale = Math.min(maxW / img.width, maxH / img.height, 1);\n canvas.width = img.width * scale;\n canvas.height = img.height * scale;\n const ctx = canvas.getContext(\"2d\")!;\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n resolve(canvas.toDataURL(\"image/jpeg\", 0.85));\n };\n img.onerror = () => resolve(dataUrl);\n img.src = dataUrl;\n });\n}\n","\"use client\";\n\nimport React, { useEffect, useRef, useCallback, useState } from \"react\";\n\ninterface InspectorProps {\n onSelect: (element: HTMLElement) => void;\n onCancel: () => void;\n}\n\nexport function Inspector({ onSelect, onCancel }: InspectorProps) {\n const [highlight, setHighlight] = useState<{\n x: number;\n y: number;\n width: number;\n height: number;\n } | null>(null);\n const hoveredEl = useRef<HTMLElement | null>(null);\n const styleEl = useRef<HTMLStyleElement | null>(null);\n\n // Inject global crosshair cursor style\n useEffect(() => {\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-afterbefore\", \"true\");\n style.textContent = [\n \"* { cursor: crosshair !important; }\",\n \"[data-afterbefore], [data-afterbefore] * { cursor: auto !important; }\",\n \"[data-afterbefore] button, [data-afterbefore] label, [data-afterbefore] a { cursor: pointer !important; }\",\n \"[data-afterbefore] input, [data-afterbefore] textarea { cursor: text !important; }\",\n ].join(\"\\n\");\n document.head.appendChild(style);\n styleEl.current = style;\n return () => {\n style.remove();\n };\n }, []);\n\n const isOverlayElement = useCallback((el: Element | null): boolean => {\n let node = el;\n while (node) {\n if (node instanceof HTMLElement && node.dataset.afterbefore) return true;\n node = node.parentElement;\n }\n return false;\n }, []);\n\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n const el = document.elementFromPoint(e.clientX, e.clientY);\n if (!el || !(el instanceof HTMLElement) || isOverlayElement(el)) {\n setHighlight(null);\n hoveredEl.current = null;\n return;\n }\n hoveredEl.current = el;\n const rect = el.getBoundingClientRect();\n setHighlight({\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n });\n },\n [isOverlayElement],\n );\n\n const handleClick = useCallback(\n (e: MouseEvent) => {\n if (isOverlayElement(e.target as Element)) return;\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n if (hoveredEl.current) {\n onSelect(hoveredEl.current);\n }\n },\n [onSelect, isOverlayElement],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onCancel();\n }\n },\n [onCancel],\n );\n\n useEffect(() => {\n document.addEventListener(\"mousemove\", handleMouseMove, true);\n document.addEventListener(\"click\", handleClick, true);\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove, true);\n document.removeEventListener(\"click\", handleClick, true);\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [handleMouseMove, handleClick, handleKeyDown]);\n\n return (\n <div data-afterbefore=\"true\" style={{ position: \"fixed\", inset: 0, zIndex: 2147483646, pointerEvents: \"none\" }}>\n {highlight && (\n <div\n style={{\n position: \"fixed\",\n left: highlight.x,\n top: highlight.y,\n width: highlight.width,\n height: highlight.height,\n background: \"transparent\",\n border: \"1px solid #fff\",\n borderRadius: 2,\n boxShadow: \"0 0 0 9999px rgba(0, 0, 0, 0.5)\",\n pointerEvents: \"none\",\n }}\n />\n )}\n\n </div>\n );\n}\n"],"mappings":"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","names":["useState","useCallback","useEffect","useCallback","useEffect","useRef","useState","ChevronDown","Trash2","X","useState","useState","Fragment","jsx","jsxs","useState","useRef","useEffect","useCallback","X","DropItem","Trash2","ChevronDown","useEffect","useRef","useCallback","useState","jsx","jsx","jsxs","useState","useEffect","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../../src/overlay/index.tsx","../../src/overlay/state.ts","../../src/overlay/capture.ts","../../src/overlay/ui/toolbar.tsx","../../src/overlay/ui/settings-panel.tsx","../../src/overlay/ui/inspector.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useState, useCallback, useEffect } from \"react\";\nimport { useOverlayState } from \"./state\";\nimport type { CaptureMode } from \"./state\";\nimport { capture, DEFAULT_FRAME_SETTINGS, type FrameSettings } from \"./capture\";\nimport { Toolbar } from \"./ui/toolbar\";\nimport { Inspector } from \"./ui/inspector\";\n\nasync function saveCapture(mode: CaptureMode, dataUrl: string) {\n try {\n const res = await fetch(\"/__afterbefore/save\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ mode, image: dataUrl }),\n });\n if (!res.ok) throw new Error(\"Save failed\");\n } catch {\n // Fallback: browser download (no branch info available client-side)\n const link = document.createElement(\"a\");\n link.download = \"screenshot.png\";\n link.href = dataUrl;\n link.click();\n }\n}\n\nexport function AfterBefore() {\n const { state, captureComplete, reset } = useOverlayState();\n const [toolbarActive, setToolbarActive] = useState(false);\n const [inspectorActive, setInspectorActive] = useState(false);\n const [loading, setLoading] = useState(false);\n const [selectedMode, setSelectedMode] = useState<CaptureMode>(\"component\");\n const [frameSettings, setFrameSettings] = useState<FrameSettings>(DEFAULT_FRAME_SETTINGS);\n\n useEffect(() => {\n try {\n const stored = localStorage.getItem(\"ab-frame-settings\");\n if (stored) {\n setFrameSettings({ ...DEFAULT_FRAME_SETTINGS, ...JSON.parse(stored) });\n } else if (localStorage.getItem(\"ab-frame-black\") === \"true\") {\n // Migration from old boolean setting\n const migrated = { ...DEFAULT_FRAME_SETTINGS, enabled: true };\n setFrameSettings(migrated);\n localStorage.setItem(\"ab-frame-settings\", JSON.stringify(migrated));\n localStorage.removeItem(\"ab-frame-black\");\n }\n } catch {\n setFrameSettings(DEFAULT_FRAME_SETTINGS);\n }\n }, []);\n\n useEffect(() => {\n if (state.phase === \"ready\") {\n const timer = setTimeout(() => {\n reset();\n }, 1500);\n return () => clearTimeout(timer);\n }\n }, [state.phase, reset]);\n\n const handleToggle = useCallback(() => {\n if (loading) return;\n\n if (state.phase === \"ready\") {\n reset();\n }\n\n if (toolbarActive || inspectorActive) {\n setToolbarActive(false);\n setInspectorActive(false);\n } else {\n if (selectedMode === \"component\") {\n setToolbarActive(true);\n setInspectorActive(true);\n } else {\n setToolbarActive(true);\n setInspectorActive(false);\n }\n }\n }, [state.phase, loading, toolbarActive, inspectorActive, selectedMode, reset]);\n\n const performCapture = useCallback(\n async (\n mode: CaptureMode,\n element?: HTMLElement,\n ) => {\n setLoading(true);\n try {\n const dataUrl = await capture({ mode, element, frameSettings });\n await saveCapture(mode, dataUrl);\n captureComplete({\n dataUrl,\n mode,\n timestamp: Date.now(),\n });\n } catch (err) {\n console.error(\"[afterbefore] Capture failed:\", err);\n } finally {\n setLoading(false);\n }\n },\n [captureComplete, frameSettings],\n );\n\n const handleToolbarCapture = useCallback(\n (mode: CaptureMode) => {\n if (mode === \"viewport\") {\n setToolbarActive(false);\n performCapture(\"viewport\");\n } else if (mode === \"fullpage\") {\n setToolbarActive(false);\n performCapture(\"fullpage\");\n } else if (mode === \"component\") {\n setInspectorActive(true);\n }\n },\n [performCapture],\n );\n\n const handleToolbarCancel = useCallback(() => {\n setToolbarActive(false);\n setInspectorActive(false);\n }, []);\n\n const handleComponentSelect = useCallback(\n (element: HTMLElement) => {\n setInspectorActive(false);\n setToolbarActive(false);\n performCapture(\"component\", element);\n },\n [performCapture],\n );\n\n const handleComponentCancel = useCallback(() => {\n setInspectorActive(false);\n setToolbarActive(true);\n }, []);\n\n const handleFrameSettingsChange = useCallback((next: FrameSettings) => {\n setFrameSettings(next);\n try {\n localStorage.setItem(\"ab-frame-settings\", JSON.stringify(next));\n } catch {\n // noop\n }\n }, []);\n\n const handleModeChange = useCallback((mode: CaptureMode) => {\n setSelectedMode(mode);\n setInspectorActive(mode === \"component\");\n }, []);\n\n return (\n <div data-afterbefore=\"true\">\n <Toolbar\n expanded={toolbarActive}\n onToggle={handleToggle}\n phase={state.phase}\n loading={loading}\n selectedMode={selectedMode}\n onModeChange={handleModeChange}\n onCapture={handleToolbarCapture}\n onCancel={handleToolbarCancel}\n frameSettings={frameSettings}\n onFrameSettingsChange={handleFrameSettingsChange}\n />\n\n {inspectorActive && (\n <Inspector onSelect={handleComponentSelect} onCancel={handleComponentCancel} />\n )}\n </div>\n );\n}\n","import { useState, useCallback } from \"react\";\n\nexport type CaptureMode = \"viewport\" | \"fullpage\" | \"component\";\n\nexport type OverlayPhase = \"idle\" | \"ready\";\n\nexport interface CaptureResult {\n dataUrl: string;\n mode: CaptureMode;\n timestamp: number;\n}\n\nexport interface OverlayState {\n phase: OverlayPhase;\n lastCapture: CaptureResult | null;\n}\n\nconst initialState: OverlayState = {\n phase: \"idle\",\n lastCapture: null,\n};\n\nexport function useOverlayState() {\n const [state, setState] = useState<OverlayState>(initialState);\n\n const captureComplete = useCallback(\n (result: CaptureResult) => {\n setState({ phase: \"ready\", lastCapture: result });\n },\n [],\n );\n\n const reset = useCallback(() => {\n setState(initialState);\n }, []);\n\n return { state, captureComplete, reset };\n}\n","import { snapdom } from \"@zumer/snapdom\";\nimport type { CaptureMode } from \"./state\";\n\nexport interface FrameSettings {\n enabled: boolean;\n size: { w: number; h: number };\n bgType: \"color\" | \"image\";\n bgColor: string;\n bgImage: string | null;\n padding: number;\n}\n\nexport const DEFAULT_FRAME_SETTINGS: FrameSettings = {\n enabled: false,\n size: { w: 1920, h: 1080 },\n bgType: \"color\",\n bgColor: \"#000000\",\n bgImage: null,\n padding: 40,\n};\n\nexport const FRAME_SIZE_PRESETS: { label: string; hint: string; w: number; h: number }[] = [\n { label: \"1920 x 1080\", hint: \"Desktop / HD\", w: 1920, h: 1080 },\n { label: \"1080 x 1080\", hint: \"Social square\", w: 1080, h: 1080 },\n { label: \"1200 x 630\", hint: \"Open Graph / link preview\", w: 1200, h: 630 },\n { label: \"1080 x 1920\", hint: \"Story / portrait\", w: 1080, h: 1920 },\n];\n\ninterface CaptureOptions {\n mode: CaptureMode;\n element?: HTMLElement;\n frameSettings?: FrameSettings;\n}\n\n/** Selectors for dev tool UI that should be excluded from capture */\nconst DEV_UI_SELECTORS = [\n // Afterbefore overlay\n \"[data-afterbefore]\",\n // Next.js dev indicators\n \"[data-nextjs-toast]\",\n \"[data-nextjs-dev-overlay]\",\n \"[data-nextjs-dialog]\",\n \"[data-nextjs-dialog-backdrop]\",\n \"[data-next-badge]\",\n \"[data-next-mark]\",\n];\n\nconst SNAPDOM_BASE = {\n exclude: DEV_UI_SELECTORS,\n excludeMode: \"remove\" as const,\n};\n\nasync function toPngDataUrl(\n el: Element,\n opts?: Record<string, unknown>,\n): Promise<string> {\n const result = await snapdom(el, { ...SNAPDOM_BASE, ...opts });\n const img = await result.toPng();\n return img.src;\n}\n\nexport async function capture(options: CaptureOptions): Promise<string> {\n const { mode, element } = options;\n\n if (mode === \"viewport\") {\n return captureViewport();\n }\n if (mode === \"fullpage\") {\n return captureFullPage();\n }\n if (mode === \"component\" && element) {\n return captureComponent(element, options.frameSettings);\n }\n throw new Error(`Invalid capture mode: ${mode}`);\n}\n\nasync function captureViewport(): Promise<string> {\n const dpr = window.devicePixelRatio || 1;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const scrollY = window.scrollY;\n\n // snapdom renders the full element content, so capture full page and crop to viewport\n const fullDataUrl = await captureFullPage();\n const img = await loadImage(fullDataUrl);\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = vw * dpr;\n canvas.height = vh * dpr;\n\n const ctx = canvas.getContext(\"2d\")!;\n ctx.drawImage(\n img,\n 0,\n scrollY * dpr,\n vw * dpr,\n vh * dpr,\n 0,\n 0,\n vw * dpr,\n vh * dpr,\n );\n\n return canvas.toDataURL(\"image/png\");\n}\n\nasync function captureFullPage(): Promise<string> {\n const scrollY = window.scrollY;\n const body = document.body;\n const html = document.documentElement;\n\n const fullHeight = Math.max(\n body.scrollHeight,\n body.offsetHeight,\n html.clientHeight,\n html.scrollHeight,\n html.offsetHeight,\n );\n\n const prevOverflow = html.style.overflow;\n const prevHeight = html.style.height;\n html.style.overflow = \"visible\";\n html.style.height = `${fullHeight}px`;\n\n try {\n return await toPngDataUrl(document.documentElement, {\n width: window.innerWidth,\n height: fullHeight,\n });\n } finally {\n html.style.overflow = prevOverflow;\n html.style.height = prevHeight;\n window.scrollTo(0, scrollY);\n }\n}\n\nasync function captureComponent(\n element: HTMLElement,\n frameSettings?: FrameSettings,\n): Promise<string> {\n const dataUrl = await toPngDataUrl(element);\n\n if (!frameSettings?.enabled) {\n return dataUrl;\n }\n\n const img = await loadImage(dataUrl);\n const dpr = window.devicePixelRatio || 1;\n\n const FRAME_W = frameSettings.size.w;\n const FRAME_H = frameSettings.size.h;\n const padding = frameSettings.padding;\n\n // Component dimensions in CSS pixels\n const compW = img.width / dpr;\n const compH = img.height / dpr;\n\n // Scale down if component exceeds frame (with padding)\n const maxW = FRAME_W - padding * 2;\n const maxH = FRAME_H - padding * 2;\n const scale = Math.min(1, maxW / compW, maxH / compH);\n\n const drawW = compW * scale * dpr;\n const drawH = compH * scale * dpr;\n\n const canvas = document.createElement(\"canvas\");\n canvas.width = FRAME_W * dpr;\n canvas.height = FRAME_H * dpr;\n\n const ctx = canvas.getContext(\"2d\")!;\n\n // Draw background\n if (frameSettings.bgType === \"image\" && frameSettings.bgImage) {\n try {\n const bgImg = await loadImage(frameSettings.bgImage);\n drawCover(ctx, bgImg, canvas.width, canvas.height);\n } catch {\n // Fallback to color if image fails\n ctx.fillStyle = frameSettings.bgColor;\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n }\n } else {\n ctx.fillStyle = frameSettings.bgColor;\n ctx.fillRect(0, 0, canvas.width, canvas.height);\n }\n\n // Center the component\n const dx = (canvas.width - drawW) / 2;\n const dy = (canvas.height - drawH) / 2;\n ctx.drawImage(img, dx, dy, drawW, drawH);\n\n return canvas.toDataURL(\"image/png\");\n}\n\n/** Draw image with cover-fit (like CSS background-size: cover) */\nfunction drawCover(\n ctx: CanvasRenderingContext2D,\n img: HTMLImageElement,\n cw: number,\n ch: number,\n) {\n const scale = Math.max(cw / img.width, ch / img.height);\n const sw = cw / scale;\n const sh = ch / scale;\n const sx = (img.width - sw) / 2;\n const sy = (img.height - sh) / 2;\n ctx.drawImage(img, sx, sy, sw, sh, 0, 0, cw, ch);\n}\n\nfunction loadImage(src: string): Promise<HTMLImageElement> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.onload = () => resolve(img);\n img.onerror = reject;\n img.src = src;\n });\n}\n","\"use client\";\n\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n ArrowUp,\n Camera,\n Check,\n ChevronDown,\n Image,\n Eye,\n FolderOpen,\n LoaderCircle,\n FileText,\n Monitor,\n MousePointer2,\n Settings,\n Trash2,\n X,\n} from \"lucide-react\";\nimport type { CaptureMode } from \"../state\";\nimport type { OverlayPhase } from \"../state\";\nimport { type FrameSettings } from \"../capture\";\nimport { SettingsPanel } from \"./settings-panel\";\n\ntype Corner = \"bottom-right\" | \"bottom-left\" | \"top-right\" | \"top-left\";\nconst EDGE_MARGIN = 24;\nconst CONTAINER_SIZE = 38;\n\nfunction getCornerStyle(corner: Corner): React.CSSProperties {\n switch (corner) {\n case \"bottom-right\":\n return { bottom: EDGE_MARGIN, right: EDGE_MARGIN };\n case \"bottom-left\":\n return { bottom: EDGE_MARGIN, left: EDGE_MARGIN };\n case \"top-right\":\n return { top: EDGE_MARGIN, right: EDGE_MARGIN };\n case \"top-left\":\n return { top: EDGE_MARGIN, left: EDGE_MARGIN };\n }\n}\n\nfunction isBottomCorner(corner: Corner): boolean {\n return corner === \"bottom-right\" || corner === \"bottom-left\";\n}\n\nfunction isRightCorner(corner: Corner): boolean {\n return corner === \"bottom-right\" || corner === \"top-right\";\n}\n\nfunction snapToCorner(x: number, y: number): Corner {\n const cx = window.innerWidth / 2;\n const cy = window.innerHeight / 2;\n if (x < cx) {\n return y < cy ? \"top-left\" : \"bottom-left\";\n }\n return y < cy ? \"top-right\" : \"bottom-right\";\n}\n\ninterface ToolbarProps {\n expanded: boolean;\n onToggle: () => void;\n phase: OverlayPhase;\n loading: boolean;\n selectedMode: CaptureMode;\n onModeChange: (mode: CaptureMode) => void;\n onCapture: (mode: CaptureMode) => void;\n onCancel: () => void;\n frameSettings: FrameSettings;\n onFrameSettingsChange: (settings: FrameSettings) => void;\n}\n\nconst MODES: { mode: CaptureMode; label: string; icon: React.ComponentType<{ size?: number; strokeWidth?: number }> }[] = [\n { mode: \"component\", label: \"Component\", icon: MousePointer2 },\n { mode: \"viewport\", label: \"Viewport\", icon: Monitor },\n { mode: \"fullpage\", label: \"Full Page\", icon: FileText },\n];\n\nexport function Toolbar({\n expanded,\n onToggle,\n phase,\n loading,\n selectedMode,\n onModeChange,\n onCapture,\n onCancel,\n frameSettings,\n onFrameSettingsChange,\n}: ToolbarProps) {\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [historyOpen, setHistoryOpen] = useState(false);\n const [corner, setCorner] = useState<Corner>(() => {\n try {\n const stored = localStorage.getItem(\"ab-toolbar-corner\");\n if (stored && [\"bottom-right\", \"bottom-left\", \"top-right\", \"top-left\"].includes(stored)) {\n return stored as Corner;\n }\n } catch {}\n return \"bottom-right\";\n });\n\n // Drag state\n const [dragging, setDragging] = useState(false);\n const [dragPos, setDragPos] = useState<{ x: number; y: number } | null>(null);\n const dragState = useRef<{\n dragging: boolean;\n startX: number;\n startY: number;\n origX: number;\n origY: number;\n distance: number;\n } | null>(null);\n const toolbarRef = useRef<HTMLDivElement>(null);\n\n // Camera button hover\n const [cameraHovered, setCameraHovered] = useState(false);\n\n useEffect(() => {\n if (!expanded) return;\n const onKey = (e: KeyboardEvent) => {\n if ((e.target as HTMLElement)?.tagName === \"INPUT\") {\n if (e.key === \"Escape\") {\n (e.target as HTMLElement).blur();\n }\n return;\n }\n\n if (e.key === \"Escape\") {\n if (settingsOpen) {\n setSettingsOpen(false);\n return;\n }\n onCancel();\n } else if (e.key === \"Enter\") {\n onCapture(selectedMode);\n }\n };\n\n document.addEventListener(\"keydown\", onKey);\n return () => document.removeEventListener(\"keydown\", onKey);\n }, [expanded, onCancel, onCapture, selectedMode, settingsOpen]);\n\n // Drag handlers\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n const el = toolbarRef.current;\n if (!el) return;\n const rect = el.getBoundingClientRect();\n setDragging(true);\n setDragPos({ x: rect.left, y: rect.top });\n dragState.current = {\n dragging: true,\n startX: e.clientX,\n startY: e.clientY,\n origX: rect.left,\n origY: rect.top,\n distance: 0,\n };\n },\n [],\n );\n\n useEffect(() => {\n const handleMouseMove = (e: MouseEvent) => {\n const ds = dragState.current;\n if (!ds || !ds.dragging) return;\n\n const dx = e.clientX - ds.startX;\n const dy = e.clientY - ds.startY;\n ds.distance = Math.sqrt(dx * dx + dy * dy);\n\n setDragPos({\n x: ds.origX + dx,\n y: ds.origY + dy,\n });\n };\n\n const handleMouseUp = (e: MouseEvent) => {\n const ds = dragState.current;\n if (!ds) return;\n\n if (ds.distance < 5) {\n onToggle();\n } else {\n // Snap to nearest corner based on toolbar center\n const el = toolbarRef.current;\n const w = el?.offsetWidth ?? CONTAINER_SIZE;\n const h = el?.offsetHeight ?? CONTAINER_SIZE;\n const centerX = (ds.origX + (e.clientX - ds.startX)) + w / 2;\n const centerY = (ds.origY + (e.clientY - ds.startY)) + h / 2;\n const newCorner = snapToCorner(centerX, centerY);\n setCorner(newCorner);\n try {\n localStorage.setItem(\"ab-toolbar-corner\", newCorner);\n } catch {}\n }\n\n setDragging(false);\n setDragPos(null);\n dragState.current = null;\n };\n\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n return () => {\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [onToggle]);\n\n const panelSide: \"left\" | \"right\" = isRightCorner(corner) ? \"left\" : \"right\";\n const tooltipSide: \"left\" | \"right\" = panelSide;\n const bottom = isBottomCorner(corner);\n\n // Build position style\n const positionStyle: React.CSSProperties = dragging && dragPos\n ? { left: dragPos.x, top: dragPos.y }\n : getCornerStyle(corner);\n\n const cameraTooltipLabel = expanded ? \"Close\" : undefined;\n const cameraTooltipStyle: React.CSSProperties | undefined = cameraTooltipLabel\n ? tooltipSide === \"left\"\n ? { right: \"calc(100% + 10px)\", top: \"50%\", transform: \"translateY(-50%)\" }\n : { left: \"calc(100% + 10px)\", top: \"50%\", transform: \"translateY(-50%)\" }\n : undefined;\n\n const cameraButton = (\n <div style={{ position: \"relative\" }}>\n {cameraTooltipLabel && cameraHovered && !dragging && (\n <div\n style={{\n position: \"absolute\",\n ...cameraTooltipStyle,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 6,\n padding: \"3px 8px\",\n color: \"rgba(255, 255, 255, 0.88)\",\n fontSize: 11,\n whiteSpace: \"nowrap\",\n boxShadow: \"0 8px 28px rgba(0, 0, 0, 0.28)\",\n pointerEvents: \"none\",\n }}\n >\n {cameraTooltipLabel}\n </div>\n )}\n <div\n onMouseDown={handleMouseDown}\n onMouseEnter={() => setCameraHovered(true)}\n onMouseLeave={() => setCameraHovered(false)}\n style={{\n width: 32,\n height: 32,\n padding: 0,\n borderRadius: \"50%\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: dragging ? \"grabbing\" : \"pointer\",\n background: expanded && cameraHovered ? \"rgba(255, 255, 255, 0.12)\" : \"transparent\",\n transition: \"background 0.12s ease\",\n }}\n >\n <style\n dangerouslySetInnerHTML={{\n __html: `\n@keyframes ab-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}`,\n }}\n />\n {loading ? (\n <LoaderCircle\n size={16}\n strokeWidth={2}\n style={{ animation: \"ab-spin 0.8s linear infinite\", color: \"white\" }}\n />\n ) : phase === \"ready\" ? (\n <Check size={16} strokeWidth={2.6} color=\"#4ade80\" />\n ) : expanded ? (\n <X\n size={16}\n strokeWidth={1.7}\n color={cameraHovered ? \"rgba(255, 255, 255, 0.96)\" : \"rgba(255, 255, 255, 0.52)\"}\n />\n ) : (\n <Camera\n size={16}\n strokeWidth={1.9}\n color=\"rgba(255, 255, 255, 0.52)\"\n />\n )}\n </div>\n </div>\n );\n\n const toolbarButtons = expanded ? (\n <>\n <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"center\", gap: 2, padding: \"4px 0\" }}>\n {MODES.map(({ mode, label, icon: ModeIcon }) => (\n <IconButton\n key={mode}\n active={selectedMode === mode}\n tooltipSide={tooltipSide}\n tooltip={label}\n onClick={() => {\n setSettingsOpen(false);\n setHistoryOpen(false);\n if (mode === \"viewport\" || mode === \"fullpage\") {\n onModeChange(mode);\n onCapture(mode);\n } else {\n onModeChange(mode);\n }\n }}\n >\n <ModeIcon size={16} strokeWidth={1.7} />\n </IconButton>\n ))}\n </div>\n\n <Separator vertical={false} />\n\n <SettingsButton\n open={settingsOpen}\n onClick={() => {\n setSettingsOpen((prev) => !prev);\n setHistoryOpen(false);\n }}\n selectedMode={selectedMode}\n frameSettings={frameSettings}\n onFrameSettingsChange={onFrameSettingsChange}\n panelSide={panelSide}\n tooltipSide={tooltipSide}\n bottom={bottom}\n />\n\n <HistoryButton\n open={historyOpen}\n onClick={() => {\n setHistoryOpen((prev) => !prev);\n setSettingsOpen(false);\n }}\n panelSide={panelSide}\n tooltipSide={tooltipSide}\n bottom={bottom}\n />\n\n <Separator vertical={false} />\n </>\n ) : null;\n\n return (\n <div\n ref={toolbarRef}\n data-afterbefore=\"true\"\n style={{\n position: \"fixed\",\n ...positionStyle,\n zIndex: 2147483647,\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n background: \"rgb(32, 32, 36)\",\n borderRadius: 999,\n padding: 6,\n boxShadow: \"0 8px 32px rgba(0, 0, 0, 0.4)\",\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n userSelect: \"none\",\n }}\n >\n {bottom ? (\n <>\n {toolbarButtons}\n {cameraButton}\n </>\n ) : (\n <>\n {cameraButton}\n {toolbarButtons}\n </>\n )}\n </div>\n );\n}\n\nfunction IconButton({\n children,\n active,\n tooltip,\n tooltipSide = \"left\",\n onClick,\n}: {\n children: React.ReactNode;\n active?: boolean;\n tooltip?: string;\n tooltipSide?: \"left\" | \"right\";\n onClick: () => void;\n}) {\n const [hovered, setHovered] = useState(false);\n\n const tooltipStyle: React.CSSProperties = tooltipSide === \"left\"\n ? {\n right: \"calc(100% + 10px)\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n }\n : {\n left: \"calc(100% + 10px)\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n };\n\n return (\n <div style={{ position: \"relative\" }}>\n {tooltip && hovered && (\n <div\n style={{\n position: \"absolute\",\n ...tooltipStyle,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 6,\n padding: \"3px 8px\",\n color: \"rgba(255, 255, 255, 0.88)\",\n fontSize: 11,\n whiteSpace: \"nowrap\",\n boxShadow: \"0 8px 28px rgba(0, 0, 0, 0.28)\",\n pointerEvents: \"none\",\n }}\n >\n {tooltip}\n </div>\n )}\n\n <button\n onClick={onClick}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n border: \"none\",\n background: active || hovered\n ? \"rgba(255, 255, 255, 0.12)\"\n : \"transparent\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n padding: 0,\n color: active || hovered\n ? \"rgba(255, 255, 255, 0.96)\"\n : \"rgba(255, 255, 255, 0.52)\",\n transition: \"background 0.12s ease, color 0.12s ease\",\n }}\n >\n {children}\n </button>\n </div>\n );\n}\n\nfunction SettingsButton({\n open,\n onClick,\n selectedMode,\n frameSettings,\n onFrameSettingsChange,\n panelSide,\n tooltipSide,\n bottom,\n}: {\n open: boolean;\n onClick: () => void;\n selectedMode: CaptureMode;\n frameSettings: FrameSettings;\n onFrameSettingsChange: (settings: FrameSettings) => void;\n panelSide: \"left\" | \"right\";\n tooltipSide: \"left\" | \"right\";\n bottom: boolean;\n}) {\n const verticalAlign = bottom ? { bottom: 0 } : { top: 0 };\n const panelStyle: React.CSSProperties = panelSide === \"left\"\n ? { right: \"calc(100% + 10px)\", ...verticalAlign }\n : { left: \"calc(100% + 10px)\", ...verticalAlign };\n\n return (\n <div style={{ position: \"relative\" }}>\n <IconButton active={open} tooltipSide={tooltipSide} tooltip={!open ? \"Settings\" : undefined} onClick={onClick}>\n <Settings size={16} strokeWidth={1.7} />\n </IconButton>\n\n {open && (\n <SettingsPanel\n style={{ position: \"absolute\", ...panelStyle }}\n onClose={onClick}\n selectedMode={selectedMode}\n frameSettings={frameSettings}\n onFrameSettingsChange={onFrameSettingsChange}\n />\n )}\n </div>\n );\n}\n\n\n\n\n\n\n\nfunction DropItem({\n children,\n onClick,\n active,\n accent,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n active?: boolean;\n accent?: boolean;\n}) {\n return (\n <button\n onClick={onClick}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"7px 12px\",\n background: active ? \"rgba(255, 255, 255, 0.08)\" : \"transparent\",\n border: \"none\",\n color: accent\n ? \"rgba(125, 211, 252, 0.96)\"\n : \"rgba(255, 255, 255, 0.86)\",\n textAlign: \"left\",\n cursor: \"pointer\",\n fontSize: 13,\n fontFamily: \"inherit\",\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction Separator({ vertical = true }: { vertical?: boolean }) {\n return (\n <div\n style={{\n width: vertical ? 1 : 24,\n height: vertical ? 18 : 1,\n background: \"rgba(255,255,255,0.12)\",\n flexShrink: 0,\n margin: vertical ? \"0 6px\" : \"6px 0\",\n }}\n />\n );\n}\n\ninterface ScreenshotMeta {\n filename: string;\n timestamp: string;\n}\n\nfunction HistoryButton({\n open,\n onClick,\n panelSide,\n tooltipSide,\n bottom,\n}: {\n open: boolean;\n onClick: () => void;\n panelSide: \"left\" | \"right\";\n tooltipSide: \"left\" | \"right\";\n bottom: boolean;\n}) {\n const [toast, setToast] = useState<{ message: string; type: \"success\" | \"error\" } | null>(null);\n const [pushing, setPushing] = useState(false);\n\n const [repos, setRepos] = useState<string[]>([]);\n const [branches, setBranches] = useState<string[]>([]);\n const [screenshots, setScreenshots] = useState<ScreenshotMeta[]>([]);\n const [selectedRepo, setSelectedRepo] = useState<string | null>(null);\n const [selectedBranch, setSelectedBranch] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n const [repoDropOpen, setRepoDropOpen] = useState(false);\n const [branchDropOpen, setBranchDropOpen] = useState(false);\n const [lightboxSrc, setLightboxSrc] = useState<string | null>(null);\n const [editingFile, setEditingFile] = useState<string | null>(null);\n const [editValue, setEditValue] = useState(\"\");\n const [hoveredThumb, setHoveredThumb] = useState<string | null>(null);\n\n useEffect(() => {\n if (!open) {\n setRepoDropOpen(false);\n setBranchDropOpen(false);\n return;\n }\n setLoading(true);\n const params = new URLSearchParams();\n if (selectedRepo) params.set(\"repo\", selectedRepo);\n if (selectedBranch) params.set(\"branch\", selectedBranch);\n fetch(`/__afterbefore/history?${params}`)\n .then((r) => r.json())\n .then((data) => {\n setRepos(data.repos || []);\n setBranches(data.branches || []);\n setScreenshots(data.screenshots || []);\n if (!selectedRepo && data.currentRepo) setSelectedRepo(data.currentRepo);\n if (!selectedBranch && data.currentBranch) setSelectedBranch(data.currentBranch);\n })\n .catch(() => {})\n .finally(() => setLoading(false));\n }, [open, selectedRepo, selectedBranch]);\n\n const showToast = useCallback((message: string, type: \"success\" | \"error\") => {\n setToast({ message, type });\n setTimeout(() => setToast(null), 3000);\n }, []);\n\n const handleOpenFolder = async () => {\n try {\n const body = selectedRepo && selectedBranch\n ? JSON.stringify({ repo: selectedRepo, branch: selectedBranch })\n : undefined;\n const res = await fetch(\"/__afterbefore/open\", {\n method: \"POST\",\n headers: body ? { \"Content-Type\": \"application/json\" } : undefined,\n body,\n });\n if (!res.ok) throw new Error();\n showToast(\"Opened folder\", \"success\");\n } catch {\n showToast(\"Could not open folder\", \"error\");\n }\n };\n\n const handleRename = async (oldName: string, newName: string) => {\n if (!newName.trim() || newName.trim() === oldName.replace(/\\.png$/, \"\")) {\n setEditingFile(null);\n return;\n }\n try {\n const res = await fetch(\"/__afterbefore/history/rename\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n repo: selectedRepo,\n branch: selectedBranch,\n oldName,\n newName: newName.trim(),\n }),\n });\n if (!res.ok) throw new Error();\n const data = await res.json();\n setScreenshots((prev) =>\n prev.map((s) =>\n s.filename === oldName\n ? { ...s, filename: data.filename, timestamp: data.filename.replace(/\\.png$/, \"\") }\n : s,\n ),\n );\n showToast(\"Renamed\", \"success\");\n } catch {\n showToast(\"Rename failed\", \"error\");\n }\n setEditingFile(null);\n };\n\n const handleDelete = async (filename: string) => {\n try {\n const res = await fetch(\"/__afterbefore/history/delete\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n repo: selectedRepo,\n branch: selectedBranch,\n file: filename,\n }),\n });\n if (!res.ok) throw new Error();\n setScreenshots((prev) => prev.filter((s) => s.filename !== filename));\n showToast(\"Deleted\", \"success\");\n } catch {\n showToast(\"Delete failed\", \"error\");\n }\n };\n\n const handlePush = async () => {\n setPushing(true);\n try {\n const res = await fetch(\"/__afterbefore/push\", { method: \"POST\" });\n const data = await res.json();\n if (!res.ok) {\n showToast(data.error || \"Push failed\", \"error\");\n } else if (data.pr) {\n showToast(`Posted to PR #${data.pr}`, \"success\");\n } else {\n showToast(\"No PR found\", \"error\");\n }\n } catch {\n showToast(\"Push failed\", \"error\");\n } finally {\n setPushing(false);\n }\n };\n\n const verticalAlign = bottom ? { bottom: 0 } : { top: 0 };\n const panelStyle: React.CSSProperties = panelSide === \"left\"\n ? { right: \"calc(100% + 10px)\", ...verticalAlign }\n : { left: \"calc(100% + 10px)\", ...verticalAlign };\n\n return (\n <div style={{ position: \"relative\" }}>\n <IconButton active={open} tooltipSide={tooltipSide} tooltip={!open ? \"Screenshots\" : undefined} onClick={onClick}>\n <Image size={16} strokeWidth={1.7} />\n </IconButton>\n\n {open && (\n <div\n style={{\n position: \"absolute\",\n ...panelStyle,\n minWidth: 300,\n maxWidth: 360,\n padding: \"10px 12px\",\n borderRadius: 12,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"0 14px 36px rgba(0, 0, 0, 0.32)\",\n }}\n >\n <div\n style={{\n fontSize: 11,\n color: \"rgba(255, 255, 255, 0.46)\",\n letterSpacing: \"0.03em\",\n textTransform: \"uppercase\",\n marginBottom: 10,\n }}\n >\n Screenshots\n </div>\n\n {/* Filter dropdowns */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6, marginBottom: 10 }}>\n <FilterDropdown\n label=\"Project\"\n value={selectedRepo}\n options={repos}\n isOpen={repoDropOpen}\n onToggle={() => {\n setRepoDropOpen((p) => !p);\n setBranchDropOpen(false);\n }}\n onSelect={(repo) => {\n setSelectedRepo(repo);\n setSelectedBranch(null);\n setRepoDropOpen(false);\n }}\n />\n <FilterDropdown\n label=\"Branch\"\n value={selectedBranch}\n options={branches}\n isOpen={branchDropOpen}\n onToggle={() => {\n setBranchDropOpen((p) => !p);\n setRepoDropOpen(false);\n }}\n onSelect={(branch) => {\n setSelectedBranch(branch);\n setBranchDropOpen(false);\n }}\n />\n </div>\n\n {loading ? (\n <div\n style={{\n padding: \"12px 0\",\n textAlign: \"center\",\n fontSize: 12,\n color: \"rgba(255, 255, 255, 0.35)\",\n }}\n >\n Loading...\n </div>\n ) : screenshots.length === 0 ? (\n <div\n style={{\n padding: \"12px 0\",\n textAlign: \"center\",\n fontSize: 12,\n color: \"rgba(255, 255, 255, 0.35)\",\n }}\n >\n No screenshots yet\n </div>\n ) : (\n <>\n <div\n style={{\n maxHeight: 240,\n overflowY: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 8,\n }}\n >\n {screenshots.map((shot) => {\n const imgUrl = `/__afterbefore/history/image?repo=${encodeURIComponent(selectedRepo || \"\")}&branch=${encodeURIComponent(selectedBranch || \"\")}&file=${encodeURIComponent(shot.filename)}`;\n const isEditing = editingFile === shot.filename;\n return (\n <div\n key={shot.filename}\n style={{\n display: \"flex\",\n gap: 10,\n alignItems: \"center\",\n }}\n >\n <div\n style={{\n position: \"relative\",\n width: 56,\n height: 36,\n flexShrink: 0,\n borderRadius: 4,\n overflow: \"hidden\",\n cursor: \"pointer\",\n }}\n onMouseEnter={() => setHoveredThumb(shot.filename)}\n onMouseLeave={() => setHoveredThumb(null)}\n onClick={() => setLightboxSrc(imgUrl)}\n >\n <img\n src={imgUrl}\n alt=\"\"\n style={{\n width: 56,\n height: 36,\n objectFit: \"cover\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 4,\n background: \"rgba(255, 255, 255, 0.05)\",\n display: \"block\",\n }}\n />\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background: \"rgba(0, 0, 0, 0.55)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n borderRadius: 4,\n opacity: hoveredThumb === shot.filename ? 1 : 0,\n transition: \"opacity 0.15s ease\",\n }}\n >\n <Eye size={16} strokeWidth={1.8} color=\"rgba(255, 255, 255, 0.9)\" />\n </div>\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n {isEditing ? (\n <input\n autoFocus\n value={editValue}\n onChange={(e) => setEditValue(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") handleRename(shot.filename, editValue);\n if (e.key === \"Escape\") setEditingFile(null);\n }}\n onBlur={() => handleRename(shot.filename, editValue)}\n style={{\n width: \"100%\",\n fontSize: 12,\n color: \"rgba(255, 255, 255, 0.88)\",\n background: \"rgba(255, 255, 255, 0.1)\",\n border: \"1px solid rgba(255, 255, 255, 0.2)\",\n borderRadius: 4,\n padding: \"2px 6px\",\n outline: \"none\",\n fontFamily: \"inherit\",\n }}\n />\n ) : (\n <div\n onClick={() => {\n setEditingFile(shot.filename);\n setEditValue(shot.filename.replace(/\\.png$/, \"\"));\n }}\n style={{\n fontSize: 12,\n color: \"rgba(255, 255, 255, 0.88)\",\n cursor: \"pointer\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n title=\"Click to rename\"\n >\n {formatTimestamp(shot.filename)}\n </div>\n )}\n </div>\n <button\n onClick={() => handleDelete(shot.filename)}\n title=\"Delete screenshot\"\n style={{\n flexShrink: 0,\n width: 24,\n height: 24,\n borderRadius: 4,\n border: \"none\",\n background: \"transparent\",\n color: \"rgba(255, 255, 255, 0.35)\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 0,\n }}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLButtonElement).style.color = \"rgba(239, 68, 68, 0.9)\";\n (e.currentTarget as HTMLButtonElement).style.background = \"rgba(239, 68, 68, 0.1)\";\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLButtonElement).style.color = \"rgba(255, 255, 255, 0.35)\";\n (e.currentTarget as HTMLButtonElement).style.background = \"transparent\";\n }}\n >\n <Trash2 size={13} strokeWidth={1.8} />\n </button>\n </div>\n );\n })}\n </div>\n\n <div\n style={{\n height: 1,\n background: \"rgba(255, 255, 255, 0.08)\",\n margin: \"8px 0\",\n }}\n />\n\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 2 }}>\n <ActionButton onClick={handleOpenFolder}>\n <FolderOpen size={13} strokeWidth={1.8} />\n Open Folder\n </ActionButton>\n <ActionButton onClick={handlePush} disabled={pushing}>\n <ArrowUp size={13} strokeWidth={1.8} />\n {pushing ? \"Pushing...\" : \"Push to PR\"}\n </ActionButton>\n </div>\n </>\n )}\n\n {toast && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"100%\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n marginBottom: 8,\n padding: \"6px 12px\",\n borderRadius: 6,\n fontSize: 12,\n fontWeight: 500,\n whiteSpace: \"nowrap\",\n color: \"white\",\n background:\n toast.type === \"success\"\n ? \"rgba(34, 197, 94, 0.9)\"\n : \"rgba(239, 68, 68, 0.9)\",\n boxShadow: \"0 2px 8px rgba(0,0,0,0.3)\",\n }}\n >\n {toast.message}\n </div>\n )}\n </div>\n )}\n\n {lightboxSrc && (\n <div\n onClick={() => setLightboxSrc(null)}\n onKeyDown={(e) => { if (e.key === \"Escape\") setLightboxSrc(null); }}\n style={{\n position: \"fixed\",\n inset: 0,\n bottom: 100,\n zIndex: 2147483646,\n background: \"rgba(0, 0, 0, 0.85)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"zoom-out\",\n }}\n >\n <img\n src={lightboxSrc}\n alt=\"\"\n onClick={(e) => e.stopPropagation()}\n style={{\n maxWidth: \"90vw\",\n maxHeight: \"calc(100% - 32px)\",\n borderRadius: 8,\n boxShadow: \"0 20px 60px rgba(0, 0, 0, 0.5)\",\n cursor: \"default\",\n }}\n />\n <button\n onClick={() => setLightboxSrc(null)}\n style={{\n position: \"absolute\",\n top: 16,\n right: 16,\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n border: \"none\",\n background: \"rgba(255, 255, 255, 0.15)\",\n color: \"white\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 0,\n }}\n >\n <X size={18} strokeWidth={2} />\n </button>\n </div>\n )}\n </div>\n );\n}\n\nfunction FilterDropdown({\n label,\n value,\n options,\n isOpen,\n onToggle,\n onSelect,\n}: {\n label: string;\n value: string | null;\n options: string[];\n isOpen: boolean;\n onToggle: () => void;\n onSelect: (value: string) => void;\n}) {\n return (\n <div>\n <div\n style={{\n fontSize: 11,\n color: \"rgba(255, 255, 255, 0.42)\",\n letterSpacing: \"0.02em\",\n marginBottom: 3,\n }}\n >\n {label}\n </div>\n <div style={{ position: \"relative\" }}>\n <button\n onClick={onToggle}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: 6,\n width: \"100%\",\n height: 30,\n padding: \"0 8px\",\n borderRadius: 7,\n border: \"1px solid rgba(255,255,255,0.1)\",\n background: \"rgba(255,255,255,0.07)\",\n color: \"rgba(255,255,255,0.88)\",\n cursor: \"pointer\",\n fontSize: 12,\n fontFamily: \"inherit\",\n }}\n >\n <span\n style={{\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {value || \"\\u2014\"}\n </span>\n <ChevronDown size={12} strokeWidth={2} />\n </button>\n\n {isOpen && options.length > 0 && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 4px)\",\n left: 0,\n right: 0,\n maxHeight: 160,\n overflowY: \"auto\",\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 8,\n padding: \"4px 0\",\n boxShadow: \"0 10px 30px rgba(0, 0, 0, 0.3)\",\n zIndex: 1,\n }}\n >\n {options.map((opt) => (\n <DropItem\n key={opt}\n active={opt === value}\n onClick={() => onSelect(opt)}\n >\n {opt}\n </DropItem>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction ActionButton({\n children,\n onClick,\n disabled,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n disabled?: boolean;\n}) {\n const [hovered, setHovered] = useState(false);\n\n return (\n <button\n onClick={onClick}\n disabled={disabled}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n width: \"100%\",\n padding: \"6px 8px\",\n border: \"none\",\n background: hovered ? \"rgba(255, 255, 255, 0.08)\" : \"transparent\",\n color: \"rgba(255, 255, 255, 0.78)\",\n fontSize: 12,\n borderRadius: 6,\n cursor: disabled ? \"wait\" : \"pointer\",\n textAlign: \"left\" as const,\n fontFamily: \"inherit\",\n transition: \"background 0.1s ease\",\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction formatTimestamp(filename: string): string {\n // Filename format: \"2026-03-18T23-05-12-345Z.png\"\n // Reverse the ISO replacement: restore colons and dots\n const iso = filename\n .replace(/\\.png$/, \"\")\n .replace(/T(\\d{2})-(\\d{2})-(\\d{2})-(\\d+)Z$/, \"T$1:$2:$3.$4Z\");\n const date = new Date(iso);\n if (Number.isNaN(date.getTime())) return filename.replace(/\\.png$/, \"\");\n\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffMin = Math.floor(diffMs / 60000);\n\n if (diffMin < 1) return \"Just now\";\n if (diffMin < 60) return `${diffMin}m ago`;\n const diffHr = Math.floor(diffMin / 60);\n if (diffHr < 24) return `${diffHr}h ago`;\n\n return date.toLocaleDateString(undefined, { month: \"short\", day: \"numeric\", hour: \"2-digit\", minute: \"2-digit\" });\n}\n","\"use client\";\n\nimport React, { useEffect, useRef, useState } from \"react\";\nimport {\n ChevronDown,\n ImageIcon,\n Palette,\n Trash2,\n Upload,\n X,\n} from \"lucide-react\";\nimport type { CaptureMode } from \"../state\";\nimport { FRAME_SIZE_PRESETS, type FrameSettings } from \"../capture\";\n\nexport function SettingsPanel({\n style,\n onClose,\n selectedMode,\n frameSettings,\n onFrameSettingsChange,\n}: {\n style?: React.CSSProperties;\n onClose: () => void;\n selectedMode: CaptureMode;\n frameSettings: FrameSettings;\n onFrameSettingsChange: (settings: FrameSettings) => void;\n}) {\n const [saveDir, setSaveDir] = useState<string | null>(null);\n const [picking, setPicking] = useState(false);\n\n useEffect(() => {\n fetch(\"/__afterbefore/config\")\n .then((r) => r.json())\n .then((data) => setSaveDir(data.saveDir))\n .catch(() => {});\n }, []);\n\n const handlePickFolder = async () => {\n setPicking(true);\n try {\n const res = await fetch(\"/__afterbefore/pick-folder\", { method: \"POST\" });\n const data = await res.json();\n if (data.folder) {\n await fetch(\"/__afterbefore/config\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ saveDir: data.folder }),\n });\n setSaveDir(data.folder);\n }\n } catch {\n // noop\n } finally {\n setPicking(false);\n }\n };\n\n const shortDir = saveDir\n ? saveDir.replace(/^\\/Users\\/[^/]+/, \"~\")\n : \"~/Desktop\";\n\n return (\n <div\n style={{\n minWidth: 300,\n padding: \"12px 16px\",\n borderRadius: 12,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n boxShadow: \"0 14px 36px rgba(0, 0, 0, 0.32)\",\n ...style,\n }}\n >\n <SettingsHeader onClose={onClose} />\n\n <SettingsDivider />\n\n {selectedMode === \"component\" && (\n <>\n <SettingsRow\n title=\"Frame\"\n description=\"Wrap in a sized canvas with background\"\n control={\n <ToggleSwitch\n enabled={frameSettings.enabled}\n onChange={() =>\n onFrameSettingsChange({ ...frameSettings, enabled: !frameSettings.enabled })\n }\n />\n }\n />\n\n {frameSettings.enabled && (\n <>\n <SettingsDivider />\n\n <FrameSizeControl\n size={frameSettings.size}\n onChange={(size) => onFrameSettingsChange({ ...frameSettings, size })}\n />\n\n <SettingsDivider />\n\n <FrameBackgroundControl\n bgType={frameSettings.bgType}\n bgColor={frameSettings.bgColor}\n bgImage={frameSettings.bgImage}\n frameSize={frameSettings.size}\n onChange={(updates) => onFrameSettingsChange({ ...frameSettings, ...updates })}\n />\n </>\n )}\n\n <SettingsDivider />\n </>\n )}\n\n <SettingsRow\n title=\"Save Location\"\n description={\n <span\n style={{\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n display: \"block\",\n }}\n title={shortDir}\n >\n {shortDir}\n </span>\n }\n control={\n <SmallButton onClick={handlePickFolder}>\n {picking ? \"...\" : \"Change\"}\n </SmallButton>\n }\n />\n </div>\n );\n}\n\nfunction SettingsHeader({ onClose }: { onClose: () => void }) {\n const [hovered, setHovered] = useState(false);\n\n return (\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", paddingBottom: 8 }}>\n <span style={{ fontSize: 14, fontWeight: 600, color: \"rgba(255, 255, 255, 0.92)\" }}>\n Settings\n </span>\n <button\n onClick={onClose}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n width: 24,\n height: 24,\n borderRadius: 6,\n border: \"none\",\n background: hovered ? \"rgba(255, 255, 255, 0.1)\" : \"transparent\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n color: hovered ? \"rgba(255, 255, 255, 0.8)\" : \"rgba(255, 255, 255, 0.46)\",\n padding: 0,\n transition: \"background 0.12s ease, color 0.12s ease\",\n }}\n >\n <X size={14} strokeWidth={2} />\n </button>\n </div>\n );\n}\n\nfunction SettingsRow({\n title,\n description,\n control,\n}: {\n title: string;\n description?: string | React.ReactNode;\n control: React.ReactNode;\n}) {\n return (\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 16, padding: \"14px 0\" }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3, flex: 1, minWidth: 0 }}>\n <span style={{ fontSize: 13, fontWeight: 600, color: \"rgba(255, 255, 255, 0.92)\" }}>\n {title}\n </span>\n {description && (\n <span style={{ fontSize: 11, color: \"rgba(255, 255, 255, 0.42)\", lineHeight: 1.3 }}>\n {description}\n </span>\n )}\n </div>\n <div style={{ flexShrink: 0 }}>\n {control}\n </div>\n </div>\n );\n}\n\nfunction SettingsDivider() {\n return <div style={{ height: 1, background: \"rgba(255, 255, 255, 0.08)\" }} />;\n}\n\nfunction ToggleSwitch({\n enabled,\n onChange,\n}: {\n enabled: boolean;\n onChange: () => void;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onChange}\n style={{\n width: 38,\n height: 22,\n borderRadius: 999,\n border: \"none\",\n background: enabled ? \"#38bdf8\" : \"rgba(255, 255, 255, 0.18)\",\n position: \"relative\",\n cursor: \"pointer\",\n padding: 0,\n flexShrink: 0,\n transition: \"background 0.12s ease\",\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 2,\n left: enabled ? 18 : 2,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.12s ease\",\n }}\n />\n </button>\n );\n}\n\nfunction FrameSizeControl({\n size,\n onChange,\n}: {\n size: { w: number; h: number };\n onChange: (size: { w: number; h: number }) => void;\n}) {\n const [sizeOpen, setSizeOpen] = useState(false);\n\n const currentPreset = FRAME_SIZE_PRESETS.find((p) => p.w === size.w && p.h === size.h);\n const isCustom = !currentPreset;\n\n return (\n <div style={{ padding: \"14px 0\" }}>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 16 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3 }}>\n <span style={{ fontSize: 13, fontWeight: 600, color: \"rgba(255, 255, 255, 0.92)\" }}>Size</span>\n <span style={{ fontSize: 11, color: \"rgba(255, 255, 255, 0.42)\", lineHeight: 1.3 }}>Set the frame dimensions</span>\n </div>\n <div style={{ position: \"relative\", flexShrink: 0 }}>\n <button\n onClick={() => setSizeOpen((prev) => !prev)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n height: 30,\n padding: \"0 10px\",\n borderRadius: 7,\n border: \"1px solid rgba(255,255,255,0.1)\",\n background: \"rgba(255,255,255,0.07)\",\n color: \"rgba(255,255,255,0.88)\",\n cursor: \"pointer\",\n fontSize: 12,\n fontFamily: \"inherit\",\n whiteSpace: \"nowrap\",\n }}\n >\n {currentPreset ? currentPreset.label : \"Custom\"}\n <ChevronDown size={12} strokeWidth={2} />\n </button>\n\n {sizeOpen && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 4px)\",\n right: 0,\n minWidth: 180,\n background: \"rgb(32, 32, 36)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 8,\n padding: \"4px 0\",\n boxShadow: \"0 10px 30px rgba(0, 0, 0, 0.3)\",\n zIndex: 1,\n }}\n >\n {FRAME_SIZE_PRESETS.map((preset) => (\n <DropItem\n key={preset.label}\n active={!isCustom && preset.w === size.w && preset.h === size.h}\n onClick={() => {\n onChange({ w: preset.w, h: preset.h });\n setSizeOpen(false);\n }}\n >\n <span>{preset.label}</span>\n <span style={{ marginLeft: 6, fontSize: 10, color: \"rgba(255,255,255,0.34)\" }}>\n {preset.hint}\n </span>\n </DropItem>\n ))}\n </div>\n )}\n </div>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4, marginTop: 10 }}>\n <NumInput\n value={size.w}\n onChange={(v) => {\n const n = parseInt(v, 10);\n if (!Number.isNaN(n) && n > 0) onChange({ ...size, w: n });\n }}\n />\n <StaticText>x</StaticText>\n <NumInput\n value={size.h}\n onChange={(v) => {\n const n = parseInt(v, 10);\n if (!Number.isNaN(n) && n > 0) onChange({ ...size, h: n });\n }}\n />\n </div>\n </div>\n );\n}\n\nfunction FrameBackgroundControl({\n bgType,\n bgColor,\n bgImage,\n frameSize,\n onChange,\n}: {\n bgType: \"color\" | \"image\";\n bgColor: string;\n bgImage: string | null;\n frameSize: { w: number; h: number };\n onChange: (updates: Partial<Pick<FrameSettings, \"bgType\" | \"bgColor\" | \"bgImage\">>) => void;\n}) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n if (dataUrl.length > 2 * 1024 * 1024) {\n downscaleImage(dataUrl, frameSize.w, frameSize.h).then((scaled) => {\n onChange({ bgType: \"image\", bgImage: scaled });\n });\n } else {\n onChange({ bgType: \"image\", bgImage: dataUrl });\n }\n };\n reader.readAsDataURL(file);\n e.target.value = \"\";\n };\n\n return (\n <div style={{ padding: \"14px 0\" }}>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 16 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3 }}>\n <span style={{ fontSize: 13, fontWeight: 600, color: \"rgba(255, 255, 255, 0.92)\" }}>Background</span>\n <span style={{ fontSize: 11, color: \"rgba(255, 255, 255, 0.42)\", lineHeight: 1.3 }}>Frame background color or image</span>\n </div>\n <div style={{ display: \"flex\", gap: 2, flexShrink: 0 }}>\n <SegmentButton\n active={bgType === \"color\"}\n onClick={() => onChange({ bgType: \"color\" })}\n style={{ borderRadius: \"6px 0 0 6px\" }}\n >\n <Palette size={12} strokeWidth={2} />\n Color\n </SegmentButton>\n <SegmentButton\n active={bgType === \"image\"}\n onClick={() => onChange({ bgType: \"image\" })}\n style={{ borderRadius: \"0 6px 6px 0\" }}\n >\n <ImageIcon size={12} strokeWidth={2} />\n Image\n </SegmentButton>\n </div>\n </div>\n\n {bgType === \"color\" && (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginTop: 10 }}>\n <ColorSwatch color={bgColor} onChange={(c) => onChange({ bgColor: c })} />\n <HexInput value={bgColor} onChange={(c) => onChange({ bgColor: c })} />\n </div>\n )}\n\n {bgType === \"image\" && (\n <div style={{ marginTop: 10 }}>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n style={{ display: \"none\" }}\n />\n\n {bgImage ? (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <img\n src={bgImage}\n alt=\"\"\n style={{\n width: 48,\n height: 28,\n borderRadius: 4,\n objectFit: \"cover\",\n border: \"1px solid rgba(255,255,255,0.12)\",\n }}\n />\n <SmallButton onClick={() => fileInputRef.current?.click()}>\n <Upload size={11} strokeWidth={2} />\n Replace\n </SmallButton>\n <SmallButton onClick={() => onChange({ bgImage: null })}>\n <Trash2 size={11} strokeWidth={2} />\n </SmallButton>\n </div>\n ) : (\n <SmallButton onClick={() => fileInputRef.current?.click()}>\n <Upload size={11} strokeWidth={2} />\n Upload image\n </SmallButton>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction SegmentButton({\n children,\n active,\n onClick,\n style,\n}: {\n children: React.ReactNode;\n active: boolean;\n onClick: () => void;\n style?: React.CSSProperties;\n}) {\n return (\n <button\n onClick={onClick}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n height: 26,\n padding: \"0 10px\",\n border: \"1px solid rgba(255,255,255,0.1)\",\n background: active ? \"rgba(255,255,255,0.14)\" : \"rgba(255,255,255,0.04)\",\n color: active ? \"rgba(255,255,255,0.92)\" : \"rgba(255,255,255,0.5)\",\n cursor: \"pointer\",\n fontSize: 11,\n fontFamily: \"inherit\",\n transition: \"background 0.12s ease, color 0.12s ease\",\n ...style,\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction ColorSwatch({\n color,\n onChange,\n}: {\n color: string;\n onChange: (color: string) => void;\n}) {\n const inputRef = useRef<HTMLInputElement>(null);\n\n return (\n <div style={{ position: \"relative\" }}>\n <button\n onClick={() => inputRef.current?.click()}\n style={{\n width: 24,\n height: 24,\n borderRadius: 6,\n border: \"1px solid rgba(255,255,255,0.18)\",\n background: color,\n cursor: \"pointer\",\n padding: 0,\n }}\n />\n <input\n ref={inputRef}\n type=\"color\"\n value={color}\n onChange={(e) => onChange(e.target.value)}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n opacity: 0,\n pointerEvents: \"none\",\n }}\n />\n </div>\n );\n}\n\nfunction SmallButton({\n children,\n onClick,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n}) {\n const [hovered, setHovered] = useState(false);\n\n return (\n <button\n onClick={onClick}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"3px 8px\",\n borderRadius: 6,\n border: \"1px solid rgba(255,255,255,0.12)\",\n background: hovered ? \"rgba(255,255,255,0.12)\" : \"rgba(255,255,255,0.06)\",\n color: \"rgba(255,255,255,0.78)\",\n fontSize: 11,\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background 0.12s ease\",\n }}\n >\n {children}\n </button>\n );\n}\n\nfunction NumInput({\n value,\n onChange,\n}: {\n value: number;\n onChange: (value: string) => void;\n}) {\n const [editing, setEditing] = useState(false);\n const [text, setText] = useState(String(value));\n\n useEffect(() => {\n if (!editing) {\n setText(String(value));\n }\n }, [editing, value]);\n\n return (\n <input\n type=\"text\"\n value={editing ? text : String(value)}\n onFocus={() => {\n setEditing(true);\n setText(String(value));\n }}\n onBlur={() => {\n setEditing(false);\n onChange(text);\n }}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n (e.target as HTMLElement).blur();\n }\n }}\n style={{\n width: 54,\n padding: \"4px 6px\",\n background: \"rgba(255, 255, 255, 0.07)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 7,\n color: \"rgba(255, 255, 255, 0.9)\",\n fontSize: 12,\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n textAlign: \"center\",\n outline: \"none\",\n }}\n />\n );\n}\n\nfunction HexInput({\n value,\n onChange,\n}: {\n value: string;\n onChange: (color: string) => void;\n}) {\n const [editing, setEditing] = useState(false);\n const [text, setText] = useState(value);\n\n useEffect(() => {\n if (!editing) {\n setText(value);\n }\n }, [editing, value]);\n\n const commit = (raw: string) => {\n const hex = raw.startsWith(\"#\") ? raw : `#${raw}`;\n if (/^#[0-9a-fA-F]{6}$/.test(hex)) {\n onChange(hex);\n }\n };\n\n return (\n <input\n type=\"text\"\n value={editing ? text : value}\n onFocus={() => {\n setEditing(true);\n setText(value);\n }}\n onBlur={() => {\n setEditing(false);\n commit(text);\n }}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n (e.target as HTMLElement).blur();\n }\n }}\n style={{\n width: 72,\n padding: \"4px 6px\",\n background: \"rgba(255, 255, 255, 0.07)\",\n border: \"1px solid rgba(255, 255, 255, 0.1)\",\n borderRadius: 7,\n color: \"rgba(255, 255, 255, 0.9)\",\n fontSize: 12,\n fontFamily: \"system-ui, -apple-system, sans-serif\",\n textAlign: \"left\",\n outline: \"none\",\n }}\n />\n );\n}\n\nfunction StaticText({ children }: { children: React.ReactNode }) {\n return (\n <span\n style={{\n fontSize: 11,\n color: \"rgba(255,255,255,0.35)\",\n minWidth: 8,\n textAlign: \"center\",\n }}\n >\n {children}\n </span>\n );\n}\n\nfunction DropItem({\n children,\n onClick,\n active,\n}: {\n children: React.ReactNode;\n onClick: () => void;\n active?: boolean;\n}) {\n return (\n <button\n onClick={onClick}\n style={{\n display: \"block\",\n width: \"100%\",\n padding: \"7px 12px\",\n background: active ? \"rgba(255, 255, 255, 0.08)\" : \"transparent\",\n border: \"none\",\n color: \"rgba(255, 255, 255, 0.86)\",\n textAlign: \"left\",\n cursor: \"pointer\",\n fontSize: 13,\n fontFamily: \"inherit\",\n }}\n >\n {children}\n </button>\n );\n}\n\nasync function downscaleImage(dataUrl: string, maxW: number, maxH: number): Promise<string> {\n return new Promise((resolve) => {\n const img = new Image();\n img.onload = () => {\n const canvas = document.createElement(\"canvas\");\n const scale = Math.min(maxW / img.width, maxH / img.height, 1);\n canvas.width = img.width * scale;\n canvas.height = img.height * scale;\n const ctx = canvas.getContext(\"2d\")!;\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n resolve(canvas.toDataURL(\"image/jpeg\", 0.85));\n };\n img.onerror = () => resolve(dataUrl);\n img.src = dataUrl;\n });\n}\n","\"use client\";\n\nimport React, { useEffect, useRef, useCallback, useState } from \"react\";\n\ninterface InspectorProps {\n onSelect: (element: HTMLElement) => void;\n onCancel: () => void;\n}\n\nexport function Inspector({ onSelect, onCancel }: InspectorProps) {\n const [highlight, setHighlight] = useState<{\n x: number;\n y: number;\n width: number;\n height: number;\n } | null>(null);\n const hoveredEl = useRef<HTMLElement | null>(null);\n const styleEl = useRef<HTMLStyleElement | null>(null);\n\n // Inject global crosshair cursor style\n useEffect(() => {\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-afterbefore\", \"true\");\n style.textContent = [\n \"* { cursor: crosshair !important; }\",\n \"[data-afterbefore], [data-afterbefore] * { cursor: auto !important; }\",\n \"[data-afterbefore] button, [data-afterbefore] label, [data-afterbefore] a { cursor: pointer !important; }\",\n \"[data-afterbefore] input, [data-afterbefore] textarea { cursor: text !important; }\",\n ].join(\"\\n\");\n document.head.appendChild(style);\n styleEl.current = style;\n return () => {\n style.remove();\n };\n }, []);\n\n const isOverlayElement = useCallback((el: Element | null): boolean => {\n let node = el;\n while (node) {\n if (node instanceof HTMLElement && node.dataset.afterbefore) return true;\n node = node.parentElement;\n }\n return false;\n }, []);\n\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n const el = document.elementFromPoint(e.clientX, e.clientY);\n if (!el || !(el instanceof HTMLElement) || isOverlayElement(el)) {\n setHighlight(null);\n hoveredEl.current = null;\n return;\n }\n hoveredEl.current = el;\n const rect = el.getBoundingClientRect();\n setHighlight({\n x: rect.x,\n y: rect.y,\n width: rect.width,\n height: rect.height,\n });\n },\n [isOverlayElement],\n );\n\n const handleClick = useCallback(\n (e: MouseEvent) => {\n if (isOverlayElement(e.target as Element)) return;\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n if (hoveredEl.current) {\n onSelect(hoveredEl.current);\n }\n },\n [onSelect, isOverlayElement],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n onCancel();\n }\n },\n [onCancel],\n );\n\n useEffect(() => {\n document.addEventListener(\"mousemove\", handleMouseMove, true);\n document.addEventListener(\"click\", handleClick, true);\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove, true);\n document.removeEventListener(\"click\", handleClick, true);\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [handleMouseMove, handleClick, handleKeyDown]);\n\n return (\n <div data-afterbefore=\"true\" style={{ position: \"fixed\", inset: 0, zIndex: 2147483646, pointerEvents: \"none\" }}>\n {highlight && (\n <div\n style={{\n position: \"fixed\",\n left: highlight.x,\n top: highlight.y,\n width: highlight.width,\n height: highlight.height,\n background: \"transparent\",\n border: \"1px solid #fff\",\n borderRadius: 2,\n boxShadow: \"0 0 0 9999px rgba(0, 0, 0, 0.5)\",\n pointerEvents: \"none\",\n }}\n />\n )}\n\n </div>\n );\n}\n"],"mappings":"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","names":["useState","useCallback","useEffect","useCallback","useEffect","useRef","useState","ChevronDown","Image","Trash2","X","useState","useState","Fragment","jsx","jsxs","useState","useRef","useEffect","useCallback","X","DropItem","Image","Trash2","ChevronDown","useEffect","useRef","useCallback","useState","jsx","jsx","jsxs","useState","useEffect","useCallback"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "afterbefore",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.20",
|
|
4
4
|
"description": "Before/after screenshot overlay for Next.js development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/overlay/index.js",
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
"test:watch": "vitest",
|
|
32
32
|
"typecheck": "tsc --noEmit",
|
|
33
33
|
"lint": "tsc --noEmit",
|
|
34
|
+
"storybook": "storybook dev -p 6006",
|
|
35
|
+
"build-storybook": "storybook build",
|
|
34
36
|
"prepare": "tsup"
|
|
35
37
|
},
|
|
36
38
|
"keywords": [
|
|
@@ -69,12 +71,14 @@
|
|
|
69
71
|
}
|
|
70
72
|
},
|
|
71
73
|
"devDependencies": {
|
|
74
|
+
"@storybook/react-vite": "^10.3.1",
|
|
72
75
|
"@types/node": "^22.0.0",
|
|
73
76
|
"@types/react": "^19.0.0",
|
|
74
77
|
"@types/react-dom": "^19.0.0",
|
|
75
78
|
"next": "^15.0.0",
|
|
76
79
|
"react": "^19.0.0",
|
|
77
80
|
"react-dom": "^19.0.0",
|
|
81
|
+
"storybook": "^10.3.1",
|
|
78
82
|
"tsup": "^8.5.1",
|
|
79
83
|
"typescript": "^5.9.3",
|
|
80
84
|
"vitest": "^4.0.18"
|