afterbefore 0.2.19 → 0.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/overlay/index.js +870 -568
- package/dist/overlay/index.js.map +1 -1
- package/package.json +5 -1
package/dist/overlay/index.js
CHANGED
|
@@ -10,7 +10,7 @@ var initialState = {
|
|
|
10
10
|
lastCapture: null
|
|
11
11
|
};
|
|
12
12
|
function useOverlayState() {
|
|
13
|
-
const [
|
|
13
|
+
const [state2, setState] = useState(initialState);
|
|
14
14
|
const captureComplete = useCallback(
|
|
15
15
|
(result) => {
|
|
16
16
|
setState({ phase: "ready", lastCapture: result });
|
|
@@ -20,7 +20,7 @@ function useOverlayState() {
|
|
|
20
20
|
const reset = useCallback(() => {
|
|
21
21
|
setState(initialState);
|
|
22
22
|
}, []);
|
|
23
|
-
return { state, captureComplete, reset };
|
|
23
|
+
return { state: state2, captureComplete, reset };
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// src/overlay/capture.ts
|
|
@@ -31,7 +31,9 @@ var DEFAULT_FRAME_SETTINGS = {
|
|
|
31
31
|
bgType: "color",
|
|
32
32
|
bgColor: "#000000",
|
|
33
33
|
bgImage: null,
|
|
34
|
-
padding: 40
|
|
34
|
+
padding: 40,
|
|
35
|
+
browserChrome: false,
|
|
36
|
+
browserTheme: "dark"
|
|
35
37
|
};
|
|
36
38
|
var FRAME_SIZE_PRESETS = [
|
|
37
39
|
{ label: "1920 x 1080", hint: "Desktop / HD", w: 1920, h: 1080 },
|
|
@@ -62,7 +64,7 @@ async function toPngDataUrl(el, opts) {
|
|
|
62
64
|
async function capture(options) {
|
|
63
65
|
const { mode, element } = options;
|
|
64
66
|
if (mode === "viewport") {
|
|
65
|
-
return captureViewport();
|
|
67
|
+
return captureViewport(options.frameSettings);
|
|
66
68
|
}
|
|
67
69
|
if (mode === "fullpage") {
|
|
68
70
|
return captureFullPage();
|
|
@@ -72,19 +74,19 @@ async function capture(options) {
|
|
|
72
74
|
}
|
|
73
75
|
throw new Error(`Invalid capture mode: ${mode}`);
|
|
74
76
|
}
|
|
75
|
-
async function captureViewport() {
|
|
77
|
+
async function captureViewport(frameSettings) {
|
|
76
78
|
const dpr = window.devicePixelRatio || 1;
|
|
77
79
|
const vw = window.innerWidth;
|
|
78
80
|
const vh = window.innerHeight;
|
|
79
81
|
const scrollY = window.scrollY;
|
|
80
82
|
const fullDataUrl = await captureFullPage();
|
|
81
|
-
const
|
|
83
|
+
const fullImg = await loadImage(fullDataUrl);
|
|
82
84
|
const canvas = document.createElement("canvas");
|
|
83
85
|
canvas.width = vw * dpr;
|
|
84
86
|
canvas.height = vh * dpr;
|
|
85
87
|
const ctx = canvas.getContext("2d");
|
|
86
88
|
ctx.drawImage(
|
|
87
|
-
|
|
89
|
+
fullImg,
|
|
88
90
|
0,
|
|
89
91
|
scrollY * dpr,
|
|
90
92
|
vw * dpr,
|
|
@@ -94,8 +96,77 @@ async function captureViewport() {
|
|
|
94
96
|
vw * dpr,
|
|
95
97
|
vh * dpr
|
|
96
98
|
);
|
|
99
|
+
const viewportDataUrl = canvas.toDataURL("image/png");
|
|
100
|
+
if (!frameSettings?.browserChrome) {
|
|
101
|
+
return viewportDataUrl;
|
|
102
|
+
}
|
|
103
|
+
const viewportImg = await loadImage(viewportDataUrl);
|
|
104
|
+
return drawBrowserChrome(viewportImg, frameSettings.browserTheme, dpr);
|
|
105
|
+
}
|
|
106
|
+
function drawBrowserChrome(img, theme, dpr) {
|
|
107
|
+
const TITLE_BAR_H = 40;
|
|
108
|
+
const URL_BAR_H = 28;
|
|
109
|
+
const URL_BAR_MARGIN_TOP = 6;
|
|
110
|
+
const URL_BAR_MARGIN_BOTTOM = 6;
|
|
111
|
+
const CHROME_H = TITLE_BAR_H + URL_BAR_H + URL_BAR_MARGIN_TOP + URL_BAR_MARGIN_BOTTOM;
|
|
112
|
+
const imgW = img.width;
|
|
113
|
+
const imgH = img.height;
|
|
114
|
+
const canvas = document.createElement("canvas");
|
|
115
|
+
canvas.width = imgW;
|
|
116
|
+
canvas.height = imgH + CHROME_H * dpr;
|
|
117
|
+
const ctx = canvas.getContext("2d");
|
|
118
|
+
const colors = theme === "dark" ? { titleBar: "#1C1C1C", urlBar: "#262626", text: "#7B7B7B", border: "#333333" } : { titleBar: "#F5F5F5", urlBar: "#FFFFFF", text: "#999999", border: "#EBEBEB" };
|
|
119
|
+
ctx.fillStyle = colors.titleBar;
|
|
120
|
+
ctx.fillRect(0, 0, canvas.width, CHROME_H * dpr);
|
|
121
|
+
ctx.fillStyle = colors.border;
|
|
122
|
+
ctx.fillRect(0, (CHROME_H - 1) * dpr, canvas.width, dpr);
|
|
123
|
+
const dotY = TITLE_BAR_H / 2 * dpr;
|
|
124
|
+
const dotR = 6 * dpr;
|
|
125
|
+
const dotStartX = 18 * dpr;
|
|
126
|
+
const dotGap = 20 * dpr;
|
|
127
|
+
const dotColors = ["#FF5F57", "#FEBC2E", "#28C840"];
|
|
128
|
+
for (let i = 0; i < 3; i++) {
|
|
129
|
+
ctx.beginPath();
|
|
130
|
+
ctx.arc(dotStartX + i * dotGap, dotY, dotR, 0, Math.PI * 2);
|
|
131
|
+
ctx.fillStyle = dotColors[i];
|
|
132
|
+
ctx.fill();
|
|
133
|
+
}
|
|
134
|
+
const urlBarY = (TITLE_BAR_H + URL_BAR_MARGIN_TOP) * dpr;
|
|
135
|
+
const urlBarPadX = 80 * dpr;
|
|
136
|
+
const urlBarX = urlBarPadX;
|
|
137
|
+
const urlBarW = canvas.width - urlBarPadX * 2;
|
|
138
|
+
const urlBarH = URL_BAR_H * dpr;
|
|
139
|
+
const urlBarR = 6 * dpr;
|
|
140
|
+
ctx.fillStyle = colors.urlBar;
|
|
141
|
+
roundRect(ctx, urlBarX, urlBarY, urlBarW, urlBarH, urlBarR);
|
|
142
|
+
ctx.fill();
|
|
143
|
+
if (theme === "light") {
|
|
144
|
+
ctx.strokeStyle = colors.border;
|
|
145
|
+
ctx.lineWidth = dpr;
|
|
146
|
+
roundRect(ctx, urlBarX, urlBarY, urlBarW, urlBarH, urlBarR);
|
|
147
|
+
ctx.stroke();
|
|
148
|
+
}
|
|
149
|
+
ctx.fillStyle = colors.text;
|
|
150
|
+
ctx.font = `${11 * dpr}px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif`;
|
|
151
|
+
ctx.textAlign = "center";
|
|
152
|
+
ctx.textBaseline = "middle";
|
|
153
|
+
ctx.fillText("localhost", canvas.width / 2, urlBarY + urlBarH / 2);
|
|
154
|
+
ctx.drawImage(img, 0, CHROME_H * dpr);
|
|
97
155
|
return canvas.toDataURL("image/png");
|
|
98
156
|
}
|
|
157
|
+
function roundRect(ctx, x, y, w, h, r) {
|
|
158
|
+
ctx.beginPath();
|
|
159
|
+
ctx.moveTo(x + r, y);
|
|
160
|
+
ctx.lineTo(x + w - r, y);
|
|
161
|
+
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
|
|
162
|
+
ctx.lineTo(x + w, y + h - r);
|
|
163
|
+
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
|
|
164
|
+
ctx.lineTo(x + r, y + h);
|
|
165
|
+
ctx.quadraticCurveTo(x, y + h, x, y + h - r);
|
|
166
|
+
ctx.lineTo(x, y + r);
|
|
167
|
+
ctx.quadraticCurveTo(x, y, x + r, y);
|
|
168
|
+
ctx.closePath();
|
|
169
|
+
}
|
|
99
170
|
async function captureFullPage() {
|
|
100
171
|
const scrollY = window.scrollY;
|
|
101
172
|
const body = document.body;
|
|
@@ -177,6 +248,64 @@ function loadImage(src) {
|
|
|
177
248
|
});
|
|
178
249
|
}
|
|
179
250
|
|
|
251
|
+
// src/overlay/font.ts
|
|
252
|
+
var FONT_FAMILY = "'Inter var', 'Inter', system-ui, -apple-system, sans-serif";
|
|
253
|
+
var FONT_FEATURE_SETTINGS = "'ss11' 1, 'calt' 1";
|
|
254
|
+
var fontBase = {
|
|
255
|
+
fontFamily: FONT_FAMILY,
|
|
256
|
+
fontFeatureSettings: FONT_FEATURE_SETTINGS
|
|
257
|
+
};
|
|
258
|
+
function style(fontSize, lineHeight, fontWeight, letterSpacing, extra) {
|
|
259
|
+
return { fontSize, lineHeight: `${lineHeight}px`, fontWeight, letterSpacing, ...extra };
|
|
260
|
+
}
|
|
261
|
+
var text = {
|
|
262
|
+
// --- Title (Medium 500) ---
|
|
263
|
+
title: {
|
|
264
|
+
h1: style(56, 64, 500, "-0.01em"),
|
|
265
|
+
h2: style(48, 56, 500, "-0.01em"),
|
|
266
|
+
h3: style(40, 48, 500, "-0.01em"),
|
|
267
|
+
h4: style(32, 40, 500, "-0.005em"),
|
|
268
|
+
h5: style(24, 32, 500, "0em"),
|
|
269
|
+
h6: style(20, 28, 500, "0em")
|
|
270
|
+
},
|
|
271
|
+
// --- Label (Medium 500) ---
|
|
272
|
+
label: {
|
|
273
|
+
xl: style(24, 32, 500, "-0.015em"),
|
|
274
|
+
lg: style(18, 24, 500, "-0.015em"),
|
|
275
|
+
md: style(16, 24, 500, "-0.011em"),
|
|
276
|
+
sm: style(14, 20, 500, "-0.006em"),
|
|
277
|
+
xs: style(12, 16, 500, "0em")
|
|
278
|
+
},
|
|
279
|
+
// --- Paragraph (Regular 400) ---
|
|
280
|
+
paragraph: {
|
|
281
|
+
xl: style(24, 32, 400, "-0.015em"),
|
|
282
|
+
lg: style(18, 24, 400, "-0.015em"),
|
|
283
|
+
md: style(16, 24, 400, "-0.011em"),
|
|
284
|
+
sm: style(14, 20, 400, "-0.006em"),
|
|
285
|
+
xs: style(12, 16, 400, "0em")
|
|
286
|
+
},
|
|
287
|
+
// --- Subheading (Medium 500, uppercase) ---
|
|
288
|
+
subheading: {
|
|
289
|
+
md: style(16, 24, 500, "0.06em", { textTransform: "uppercase" }),
|
|
290
|
+
sm: style(14, 20, 500, "0.06em", { textTransform: "uppercase" }),
|
|
291
|
+
xs: style(12, 16, 500, "0.04em", { textTransform: "uppercase" }),
|
|
292
|
+
xxs: style(11, 12, 500, "0.02em", { textTransform: "uppercase" })
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
var INTER_CSS_ID = "afterbefore-inter-font";
|
|
296
|
+
function injectInterFont() {
|
|
297
|
+
if (document.getElementById(INTER_CSS_ID)) return;
|
|
298
|
+
const preconnect = document.createElement("link");
|
|
299
|
+
preconnect.rel = "preconnect";
|
|
300
|
+
preconnect.href = "https://rsms.me/";
|
|
301
|
+
document.head.appendChild(preconnect);
|
|
302
|
+
const stylesheet = document.createElement("link");
|
|
303
|
+
stylesheet.id = INTER_CSS_ID;
|
|
304
|
+
stylesheet.rel = "stylesheet";
|
|
305
|
+
stylesheet.href = "https://rsms.me/inter/inter.css";
|
|
306
|
+
document.head.appendChild(stylesheet);
|
|
307
|
+
}
|
|
308
|
+
|
|
180
309
|
// src/overlay/ui/toolbar.tsx
|
|
181
310
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
|
|
182
311
|
import {
|
|
@@ -191,11 +320,73 @@ import {
|
|
|
191
320
|
FileText,
|
|
192
321
|
Monitor,
|
|
193
322
|
MousePointer2,
|
|
194
|
-
Settings,
|
|
195
323
|
Trash2 as Trash22,
|
|
196
324
|
X as X2
|
|
197
325
|
} from "lucide-react";
|
|
198
326
|
|
|
327
|
+
// src/overlay/color.ts
|
|
328
|
+
var gray = {
|
|
329
|
+
950: "#171717",
|
|
330
|
+
900: "#1C1C1C",
|
|
331
|
+
800: "#262626",
|
|
332
|
+
700: "#333333",
|
|
333
|
+
600: "#5C5C5C",
|
|
334
|
+
500: "#7B7B7B",
|
|
335
|
+
400: "#A3A3A3",
|
|
336
|
+
300: "#D1D1D1",
|
|
337
|
+
200: "#EBEBEB",
|
|
338
|
+
100: "#F5F5F5",
|
|
339
|
+
50: "#F7F7F7",
|
|
340
|
+
0: "#FFFFFF"
|
|
341
|
+
};
|
|
342
|
+
var bg = {
|
|
343
|
+
base: gray[900],
|
|
344
|
+
elevated: gray[950],
|
|
345
|
+
dropdown: gray[900]
|
|
346
|
+
};
|
|
347
|
+
var fg = {
|
|
348
|
+
strong: gray[200],
|
|
349
|
+
default: gray[300],
|
|
350
|
+
sub: gray[500],
|
|
351
|
+
muted: gray[600],
|
|
352
|
+
faint: gray[600]
|
|
353
|
+
};
|
|
354
|
+
var stroke = {
|
|
355
|
+
soft: "rgba(255, 255, 255, 0.08)",
|
|
356
|
+
default: "rgba(255, 255, 255, 0.1)",
|
|
357
|
+
strong: "rgba(255, 255, 255, 0.12)",
|
|
358
|
+
interactive: "rgba(255, 255, 255, 0.18)"
|
|
359
|
+
};
|
|
360
|
+
var state = {
|
|
361
|
+
subtle: "rgba(255, 255, 255, 0.04)",
|
|
362
|
+
button: "rgba(255, 255, 255, 0.06)",
|
|
363
|
+
input: "rgba(255, 255, 255, 0.07)",
|
|
364
|
+
active: "rgba(255, 255, 255, 0.08)",
|
|
365
|
+
hover: "rgba(255, 255, 255, 0.1)",
|
|
366
|
+
hoverStrong: "rgba(255, 255, 255, 0.12)",
|
|
367
|
+
pressed: "rgba(255, 255, 255, 0.14)"
|
|
368
|
+
};
|
|
369
|
+
var accent = {
|
|
370
|
+
primary: "#335CFF",
|
|
371
|
+
toggle: "#38bdf8",
|
|
372
|
+
check: "#4ade80",
|
|
373
|
+
highlight: "rgba(125, 211, 252, 0.96)"
|
|
374
|
+
};
|
|
375
|
+
var feedback = {
|
|
376
|
+
success: "rgba(34, 197, 94, 0.9)",
|
|
377
|
+
error: "rgba(239, 68, 68, 0.9)",
|
|
378
|
+
errorText: "rgba(239, 68, 68, 0.9)",
|
|
379
|
+
errorBg: "rgba(239, 68, 68, 0.1)"
|
|
380
|
+
};
|
|
381
|
+
var shadow = {
|
|
382
|
+
toolbar: "0 8px 32px rgba(0, 0, 0, 0.4)",
|
|
383
|
+
panel: "0 14px 36px rgba(0, 0, 0, 0.32)",
|
|
384
|
+
dropdown: "0 10px 30px rgba(0, 0, 0, 0.3)",
|
|
385
|
+
tooltip: "0 8px 28px rgba(0, 0, 0, 0.28)",
|
|
386
|
+
toast: "0 2px 8px rgba(0, 0, 0, 0.3)",
|
|
387
|
+
status: "0 4px 20px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.08)"
|
|
388
|
+
};
|
|
389
|
+
|
|
199
390
|
// src/overlay/ui/settings-panel.tsx
|
|
200
391
|
import { useEffect, useRef, useState as useState2 } from "react";
|
|
201
392
|
import {
|
|
@@ -207,140 +398,110 @@ import {
|
|
|
207
398
|
X
|
|
208
399
|
} from "lucide-react";
|
|
209
400
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
210
|
-
function
|
|
211
|
-
style,
|
|
212
|
-
onClose,
|
|
213
|
-
selectedMode,
|
|
401
|
+
function SettingsContent({
|
|
214
402
|
frameSettings,
|
|
215
|
-
onFrameSettingsChange
|
|
403
|
+
onFrameSettingsChange,
|
|
404
|
+
saveDir,
|
|
405
|
+
picking,
|
|
406
|
+
onPickFolder
|
|
216
407
|
}) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
await fetch("/__afterbefore/config", {
|
|
230
|
-
method: "POST",
|
|
231
|
-
headers: { "Content-Type": "application/json" },
|
|
232
|
-
body: JSON.stringify({ saveDir: data.folder })
|
|
233
|
-
});
|
|
234
|
-
setSaveDir(data.folder);
|
|
408
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
409
|
+
/* @__PURE__ */ jsx(
|
|
410
|
+
SettingsRow,
|
|
411
|
+
{
|
|
412
|
+
title: "Frame",
|
|
413
|
+
control: /* @__PURE__ */ jsx(
|
|
414
|
+
ToggleSwitch,
|
|
415
|
+
{
|
|
416
|
+
enabled: frameSettings.enabled,
|
|
417
|
+
onChange: () => onFrameSettingsChange({ ...frameSettings, enabled: !frameSettings.enabled })
|
|
418
|
+
}
|
|
419
|
+
)
|
|
235
420
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
421
|
+
),
|
|
422
|
+
frameSettings.enabled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
423
|
+
/* @__PURE__ */ jsx(SettingsDivider, {}),
|
|
424
|
+
/* @__PURE__ */ jsx(
|
|
425
|
+
FrameSizeControl,
|
|
426
|
+
{
|
|
427
|
+
size: frameSettings.size,
|
|
428
|
+
onChange: (size) => onFrameSettingsChange({ ...frameSettings, size })
|
|
429
|
+
}
|
|
430
|
+
),
|
|
431
|
+
/* @__PURE__ */ jsx(SettingsDivider, {}),
|
|
432
|
+
/* @__PURE__ */ jsx(
|
|
433
|
+
FrameBackgroundControl,
|
|
434
|
+
{
|
|
435
|
+
bgType: frameSettings.bgType,
|
|
436
|
+
bgColor: frameSettings.bgColor,
|
|
437
|
+
bgImage: frameSettings.bgImage,
|
|
438
|
+
frameSize: frameSettings.size,
|
|
439
|
+
onChange: (updates) => onFrameSettingsChange({ ...frameSettings, ...updates })
|
|
440
|
+
}
|
|
441
|
+
)
|
|
442
|
+
] }),
|
|
443
|
+
/* @__PURE__ */ jsx(SettingsDivider, {}),
|
|
444
|
+
/* @__PURE__ */ jsx(
|
|
445
|
+
SettingsRow,
|
|
446
|
+
{
|
|
447
|
+
title: "Browser Chrome",
|
|
448
|
+
control: /* @__PURE__ */ jsx(
|
|
449
|
+
ToggleSwitch,
|
|
450
|
+
{
|
|
451
|
+
enabled: frameSettings.browserChrome,
|
|
452
|
+
onChange: () => onFrameSettingsChange({ ...frameSettings, browserChrome: !frameSettings.browserChrome })
|
|
453
|
+
}
|
|
454
|
+
)
|
|
455
|
+
}
|
|
456
|
+
),
|
|
457
|
+
frameSettings.browserChrome && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
458
|
+
/* @__PURE__ */ jsx(SettingsDivider, {}),
|
|
459
|
+
/* @__PURE__ */ jsx(
|
|
460
|
+
SettingsRow,
|
|
461
|
+
{
|
|
462
|
+
title: "Theme",
|
|
463
|
+
control: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 2, flexShrink: 0 }, children: [
|
|
274
464
|
/* @__PURE__ */ jsx(
|
|
275
|
-
|
|
465
|
+
SegmentButton,
|
|
276
466
|
{
|
|
277
|
-
|
|
278
|
-
|
|
467
|
+
active: frameSettings.browserTheme === "light",
|
|
468
|
+
onClick: () => onFrameSettingsChange({ ...frameSettings, browserTheme: "light" }),
|
|
469
|
+
style: { borderRadius: "6px 0 0 6px" },
|
|
470
|
+
children: "Light"
|
|
279
471
|
}
|
|
280
472
|
),
|
|
281
|
-
/* @__PURE__ */ jsx(SettingsDivider, {}),
|
|
282
473
|
/* @__PURE__ */ jsx(
|
|
283
|
-
|
|
474
|
+
SegmentButton,
|
|
284
475
|
{
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
onChange: (updates) => onFrameSettingsChange({ ...frameSettings, ...updates })
|
|
476
|
+
active: frameSettings.browserTheme === "dark",
|
|
477
|
+
onClick: () => onFrameSettingsChange({ ...frameSettings, browserTheme: "dark" }),
|
|
478
|
+
style: { borderRadius: "0 6px 6px 0" },
|
|
479
|
+
children: "Dark"
|
|
290
480
|
}
|
|
291
481
|
)
|
|
292
|
-
] })
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
482
|
+
] })
|
|
483
|
+
}
|
|
484
|
+
)
|
|
485
|
+
] }),
|
|
486
|
+
/* @__PURE__ */ jsx(SettingsDivider, {}),
|
|
487
|
+
saveDir !== void 0 && onPickFolder && /* @__PURE__ */ jsx(
|
|
488
|
+
SettingsRow,
|
|
489
|
+
{
|
|
490
|
+
title: "Save Location",
|
|
491
|
+
description: /* @__PURE__ */ jsx(
|
|
492
|
+
"span",
|
|
297
493
|
{
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
"
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
display: "block"
|
|
307
|
-
},
|
|
308
|
-
title: shortDir,
|
|
309
|
-
children: shortDir
|
|
310
|
-
}
|
|
311
|
-
),
|
|
312
|
-
control: /* @__PURE__ */ jsx(SmallButton, { onClick: handlePickFolder, children: picking ? "..." : "Change" })
|
|
494
|
+
style: {
|
|
495
|
+
overflow: "hidden",
|
|
496
|
+
textOverflow: "ellipsis",
|
|
497
|
+
whiteSpace: "nowrap",
|
|
498
|
+
display: "block"
|
|
499
|
+
},
|
|
500
|
+
title: saveDir,
|
|
501
|
+
children: saveDir
|
|
313
502
|
}
|
|
314
|
-
)
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
function SettingsHeader({ onClose }) {
|
|
320
|
-
const [hovered, setHovered] = useState2(false);
|
|
321
|
-
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", paddingBottom: 8 }, children: [
|
|
322
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, fontWeight: 600, color: "rgba(255, 255, 255, 0.92)" }, children: "Settings" }),
|
|
323
|
-
/* @__PURE__ */ jsx(
|
|
324
|
-
"button",
|
|
325
|
-
{
|
|
326
|
-
onClick: onClose,
|
|
327
|
-
onMouseEnter: () => setHovered(true),
|
|
328
|
-
onMouseLeave: () => setHovered(false),
|
|
329
|
-
style: {
|
|
330
|
-
width: 24,
|
|
331
|
-
height: 24,
|
|
332
|
-
borderRadius: 6,
|
|
333
|
-
border: "none",
|
|
334
|
-
background: hovered ? "rgba(255, 255, 255, 0.1)" : "transparent",
|
|
335
|
-
display: "flex",
|
|
336
|
-
alignItems: "center",
|
|
337
|
-
justifyContent: "center",
|
|
338
|
-
cursor: "pointer",
|
|
339
|
-
color: hovered ? "rgba(255, 255, 255, 0.8)" : "rgba(255, 255, 255, 0.46)",
|
|
340
|
-
padding: 0,
|
|
341
|
-
transition: "background 0.12s ease, color 0.12s ease"
|
|
342
|
-
},
|
|
343
|
-
children: /* @__PURE__ */ jsx(X, { size: 14, strokeWidth: 2 })
|
|
503
|
+
),
|
|
504
|
+
control: /* @__PURE__ */ jsx(SmallButton, { onClick: onPickFolder, children: picking ? "..." : "Change" })
|
|
344
505
|
}
|
|
345
506
|
)
|
|
346
507
|
] });
|
|
@@ -350,16 +511,23 @@ function SettingsRow({
|
|
|
350
511
|
description,
|
|
351
512
|
control
|
|
352
513
|
}) {
|
|
353
|
-
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, padding: "
|
|
354
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap:
|
|
355
|
-
/* @__PURE__ */ jsx("span", { style: {
|
|
356
|
-
description && /* @__PURE__ */ jsx("span", { style: {
|
|
514
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, padding: "10px 0" }, children: [
|
|
515
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 2, flex: 1, minWidth: 0 }, children: [
|
|
516
|
+
/* @__PURE__ */ jsx("span", { style: { ...text.label.sm, color: fg.strong }, children: title }),
|
|
517
|
+
description && /* @__PURE__ */ jsx("span", { style: { ...text.paragraph.xs, color: fg.muted }, children: description })
|
|
357
518
|
] }),
|
|
358
519
|
/* @__PURE__ */ jsx("div", { style: { flexShrink: 0 }, children: control })
|
|
359
520
|
] });
|
|
360
521
|
}
|
|
361
522
|
function SettingsDivider() {
|
|
362
|
-
return /* @__PURE__ */ jsx(
|
|
523
|
+
return /* @__PURE__ */ jsx(
|
|
524
|
+
"div",
|
|
525
|
+
{
|
|
526
|
+
style: {
|
|
527
|
+
borderBottom: `1px solid ${stroke.soft}`
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
);
|
|
363
531
|
}
|
|
364
532
|
function ToggleSwitch({
|
|
365
533
|
enabled,
|
|
@@ -375,7 +543,7 @@ function ToggleSwitch({
|
|
|
375
543
|
height: 22,
|
|
376
544
|
borderRadius: 999,
|
|
377
545
|
border: "none",
|
|
378
|
-
background: enabled ?
|
|
546
|
+
background: enabled ? accent.toggle : stroke.interactive,
|
|
379
547
|
position: "relative",
|
|
380
548
|
cursor: "pointer",
|
|
381
549
|
padding: 0,
|
|
@@ -407,12 +575,9 @@ function FrameSizeControl({
|
|
|
407
575
|
const [sizeOpen, setSizeOpen] = useState2(false);
|
|
408
576
|
const currentPreset = FRAME_SIZE_PRESETS.find((p) => p.w === size.w && p.h === size.h);
|
|
409
577
|
const isCustom = !currentPreset;
|
|
410
|
-
return /* @__PURE__ */ jsxs("div", { style: { padding: "
|
|
578
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "10px 0" }, children: [
|
|
411
579
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16 }, children: [
|
|
412
|
-
/* @__PURE__ */
|
|
413
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 600, color: "rgba(255, 255, 255, 0.92)" }, children: "Size" }),
|
|
414
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: "rgba(255, 255, 255, 0.42)", lineHeight: 1.3 }, children: "Set the frame dimensions" })
|
|
415
|
-
] }),
|
|
580
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("span", { style: { ...text.label.sm, color: fg.strong }, children: "Size" }) }),
|
|
416
581
|
/* @__PURE__ */ jsxs("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
417
582
|
/* @__PURE__ */ jsxs(
|
|
418
583
|
"button",
|
|
@@ -425,11 +590,11 @@ function FrameSizeControl({
|
|
|
425
590
|
height: 30,
|
|
426
591
|
padding: "0 10px",
|
|
427
592
|
borderRadius: 7,
|
|
428
|
-
border:
|
|
429
|
-
background:
|
|
430
|
-
color:
|
|
593
|
+
border: `1px solid ${stroke.default}`,
|
|
594
|
+
background: state.input,
|
|
595
|
+
color: fg.strong,
|
|
431
596
|
cursor: "pointer",
|
|
432
|
-
|
|
597
|
+
...text.label.xs,
|
|
433
598
|
fontFamily: "inherit",
|
|
434
599
|
whiteSpace: "nowrap"
|
|
435
600
|
},
|
|
@@ -447,11 +612,11 @@ function FrameSizeControl({
|
|
|
447
612
|
bottom: "calc(100% + 4px)",
|
|
448
613
|
right: 0,
|
|
449
614
|
minWidth: 180,
|
|
450
|
-
background:
|
|
451
|
-
border:
|
|
615
|
+
background: bg.base,
|
|
616
|
+
border: `1px solid ${stroke.default}`,
|
|
452
617
|
borderRadius: 8,
|
|
453
618
|
padding: "4px 0",
|
|
454
|
-
boxShadow:
|
|
619
|
+
boxShadow: shadow.dropdown,
|
|
455
620
|
zIndex: 1
|
|
456
621
|
},
|
|
457
622
|
children: FRAME_SIZE_PRESETS.map((preset) => /* @__PURE__ */ jsxs(
|
|
@@ -464,7 +629,7 @@ function FrameSizeControl({
|
|
|
464
629
|
},
|
|
465
630
|
children: [
|
|
466
631
|
/* @__PURE__ */ jsx("span", { children: preset.label }),
|
|
467
|
-
/* @__PURE__ */ jsx("span", { style: { marginLeft: 6, fontSize: 10, color:
|
|
632
|
+
/* @__PURE__ */ jsx("span", { style: { marginLeft: 6, fontSize: 10, color: fg.faint }, children: preset.hint })
|
|
468
633
|
]
|
|
469
634
|
},
|
|
470
635
|
preset.label
|
|
@@ -523,12 +688,9 @@ function FrameBackgroundControl({
|
|
|
523
688
|
reader.readAsDataURL(file);
|
|
524
689
|
e.target.value = "";
|
|
525
690
|
};
|
|
526
|
-
return /* @__PURE__ */ jsxs("div", { style: { padding: "
|
|
691
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "10px 0" }, children: [
|
|
527
692
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16 }, children: [
|
|
528
|
-
/* @__PURE__ */
|
|
529
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: 13, fontWeight: 600, color: "rgba(255, 255, 255, 0.92)" }, children: "Background" }),
|
|
530
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: "rgba(255, 255, 255, 0.42)", lineHeight: 1.3 }, children: "Frame background color or image" })
|
|
531
|
-
] }),
|
|
693
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("span", { style: { ...text.label.sm, color: fg.strong }, children: "Background" }) }),
|
|
532
694
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 2, flexShrink: 0 }, children: [
|
|
533
695
|
/* @__PURE__ */ jsxs(
|
|
534
696
|
SegmentButton,
|
|
@@ -582,7 +744,7 @@ function FrameBackgroundControl({
|
|
|
582
744
|
height: 28,
|
|
583
745
|
borderRadius: 4,
|
|
584
746
|
objectFit: "cover",
|
|
585
|
-
border:
|
|
747
|
+
border: `1px solid ${stroke.strong}`
|
|
586
748
|
}
|
|
587
749
|
}
|
|
588
750
|
),
|
|
@@ -602,7 +764,7 @@ function SegmentButton({
|
|
|
602
764
|
children,
|
|
603
765
|
active,
|
|
604
766
|
onClick,
|
|
605
|
-
style
|
|
767
|
+
style: style2
|
|
606
768
|
}) {
|
|
607
769
|
return /* @__PURE__ */ jsx(
|
|
608
770
|
"button",
|
|
@@ -612,16 +774,16 @@ function SegmentButton({
|
|
|
612
774
|
display: "flex",
|
|
613
775
|
alignItems: "center",
|
|
614
776
|
gap: 4,
|
|
615
|
-
height:
|
|
777
|
+
height: 28,
|
|
616
778
|
padding: "0 10px",
|
|
617
|
-
border:
|
|
618
|
-
background: active ?
|
|
619
|
-
color: active ?
|
|
779
|
+
border: `1px solid ${stroke.default}`,
|
|
780
|
+
background: active ? state.pressed : state.subtle,
|
|
781
|
+
color: active ? fg.strong : fg.sub,
|
|
620
782
|
cursor: "pointer",
|
|
621
|
-
|
|
783
|
+
...text.label.xs,
|
|
622
784
|
fontFamily: "inherit",
|
|
623
785
|
transition: "background 0.12s ease, color 0.12s ease",
|
|
624
|
-
...
|
|
786
|
+
...style2
|
|
625
787
|
},
|
|
626
788
|
children
|
|
627
789
|
}
|
|
@@ -641,7 +803,7 @@ function ColorSwatch({
|
|
|
641
803
|
width: 24,
|
|
642
804
|
height: 24,
|
|
643
805
|
borderRadius: 6,
|
|
644
|
-
border:
|
|
806
|
+
border: `1px solid ${stroke.interactive}`,
|
|
645
807
|
background: color,
|
|
646
808
|
cursor: "pointer",
|
|
647
809
|
padding: 0
|
|
@@ -683,12 +845,12 @@ function SmallButton({
|
|
|
683
845
|
display: "flex",
|
|
684
846
|
alignItems: "center",
|
|
685
847
|
gap: 4,
|
|
686
|
-
padding: "
|
|
848
|
+
padding: "4px 10px",
|
|
687
849
|
borderRadius: 6,
|
|
688
|
-
border:
|
|
689
|
-
background: hovered ?
|
|
690
|
-
color:
|
|
691
|
-
|
|
850
|
+
border: `1px solid ${stroke.strong}`,
|
|
851
|
+
background: hovered ? state.hoverStrong : state.button,
|
|
852
|
+
color: fg.default,
|
|
853
|
+
...text.label.xs,
|
|
692
854
|
cursor: "pointer",
|
|
693
855
|
fontFamily: "inherit",
|
|
694
856
|
transition: "background 0.12s ease"
|
|
@@ -702,7 +864,7 @@ function NumInput({
|
|
|
702
864
|
onChange
|
|
703
865
|
}) {
|
|
704
866
|
const [editing, setEditing] = useState2(false);
|
|
705
|
-
const [
|
|
867
|
+
const [text2, setText] = useState2(String(value));
|
|
706
868
|
useEffect(() => {
|
|
707
869
|
if (!editing) {
|
|
708
870
|
setText(String(value));
|
|
@@ -712,14 +874,14 @@ function NumInput({
|
|
|
712
874
|
"input",
|
|
713
875
|
{
|
|
714
876
|
type: "text",
|
|
715
|
-
value: editing ?
|
|
877
|
+
value: editing ? text2 : String(value),
|
|
716
878
|
onFocus: () => {
|
|
717
879
|
setEditing(true);
|
|
718
880
|
setText(String(value));
|
|
719
881
|
},
|
|
720
882
|
onBlur: () => {
|
|
721
883
|
setEditing(false);
|
|
722
|
-
onChange(
|
|
884
|
+
onChange(text2);
|
|
723
885
|
},
|
|
724
886
|
onChange: (e) => setText(e.target.value),
|
|
725
887
|
onKeyDown: (e) => {
|
|
@@ -730,12 +892,12 @@ function NumInput({
|
|
|
730
892
|
style: {
|
|
731
893
|
width: 54,
|
|
732
894
|
padding: "4px 6px",
|
|
733
|
-
background:
|
|
734
|
-
border:
|
|
895
|
+
background: state.input,
|
|
896
|
+
border: `1px solid ${stroke.default}`,
|
|
735
897
|
borderRadius: 7,
|
|
736
|
-
color:
|
|
737
|
-
|
|
738
|
-
fontFamily: "
|
|
898
|
+
color: fg.strong,
|
|
899
|
+
...text.label.xs,
|
|
900
|
+
fontFamily: "inherit",
|
|
739
901
|
textAlign: "center",
|
|
740
902
|
outline: "none"
|
|
741
903
|
}
|
|
@@ -747,7 +909,7 @@ function HexInput({
|
|
|
747
909
|
onChange
|
|
748
910
|
}) {
|
|
749
911
|
const [editing, setEditing] = useState2(false);
|
|
750
|
-
const [
|
|
912
|
+
const [text2, setText] = useState2(value);
|
|
751
913
|
useEffect(() => {
|
|
752
914
|
if (!editing) {
|
|
753
915
|
setText(value);
|
|
@@ -763,14 +925,14 @@ function HexInput({
|
|
|
763
925
|
"input",
|
|
764
926
|
{
|
|
765
927
|
type: "text",
|
|
766
|
-
value: editing ?
|
|
928
|
+
value: editing ? text2 : value,
|
|
767
929
|
onFocus: () => {
|
|
768
930
|
setEditing(true);
|
|
769
931
|
setText(value);
|
|
770
932
|
},
|
|
771
933
|
onBlur: () => {
|
|
772
934
|
setEditing(false);
|
|
773
|
-
commit(
|
|
935
|
+
commit(text2);
|
|
774
936
|
},
|
|
775
937
|
onChange: (e) => setText(e.target.value),
|
|
776
938
|
onKeyDown: (e) => {
|
|
@@ -781,12 +943,12 @@ function HexInput({
|
|
|
781
943
|
style: {
|
|
782
944
|
width: 72,
|
|
783
945
|
padding: "4px 6px",
|
|
784
|
-
background:
|
|
785
|
-
border:
|
|
946
|
+
background: state.input,
|
|
947
|
+
border: `1px solid ${stroke.default}`,
|
|
786
948
|
borderRadius: 7,
|
|
787
|
-
color:
|
|
788
|
-
|
|
789
|
-
fontFamily: "
|
|
949
|
+
color: fg.strong,
|
|
950
|
+
...text.label.xs,
|
|
951
|
+
fontFamily: "inherit",
|
|
790
952
|
textAlign: "left",
|
|
791
953
|
outline: "none"
|
|
792
954
|
}
|
|
@@ -799,7 +961,7 @@ function StaticText({ children }) {
|
|
|
799
961
|
{
|
|
800
962
|
style: {
|
|
801
963
|
fontSize: 11,
|
|
802
|
-
color:
|
|
964
|
+
color: fg.faint,
|
|
803
965
|
minWidth: 8,
|
|
804
966
|
textAlign: "center"
|
|
805
967
|
},
|
|
@@ -820,12 +982,12 @@ function DropItem({
|
|
|
820
982
|
display: "block",
|
|
821
983
|
width: "100%",
|
|
822
984
|
padding: "7px 12px",
|
|
823
|
-
background: active ?
|
|
985
|
+
background: active ? state.active : "transparent",
|
|
824
986
|
border: "none",
|
|
825
|
-
color:
|
|
987
|
+
color: fg.strong,
|
|
826
988
|
textAlign: "left",
|
|
827
989
|
cursor: "pointer",
|
|
828
|
-
|
|
990
|
+
...text.paragraph.sm,
|
|
829
991
|
fontFamily: "inherit"
|
|
830
992
|
},
|
|
831
993
|
children
|
|
@@ -879,6 +1041,20 @@ function snapToCorner(x, y) {
|
|
|
879
1041
|
}
|
|
880
1042
|
return y < cy ? "top-right" : "bottom-right";
|
|
881
1043
|
}
|
|
1044
|
+
function getCornerPosition(corner, w, h) {
|
|
1045
|
+
const vw = window.innerWidth;
|
|
1046
|
+
const vh = window.innerHeight;
|
|
1047
|
+
switch (corner) {
|
|
1048
|
+
case "bottom-right":
|
|
1049
|
+
return { x: vw - EDGE_MARGIN - w, y: vh - EDGE_MARGIN - h };
|
|
1050
|
+
case "bottom-left":
|
|
1051
|
+
return { x: EDGE_MARGIN, y: vh - EDGE_MARGIN - h };
|
|
1052
|
+
case "top-right":
|
|
1053
|
+
return { x: vw - EDGE_MARGIN - w, y: EDGE_MARGIN };
|
|
1054
|
+
case "top-left":
|
|
1055
|
+
return { x: EDGE_MARGIN, y: EDGE_MARGIN };
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
882
1058
|
var MODES = [
|
|
883
1059
|
{ mode: "component", label: "Component", icon: MousePointer2 },
|
|
884
1060
|
{ mode: "viewport", label: "Viewport", icon: Monitor },
|
|
@@ -896,8 +1072,29 @@ function Toolbar({
|
|
|
896
1072
|
frameSettings,
|
|
897
1073
|
onFrameSettingsChange
|
|
898
1074
|
}) {
|
|
899
|
-
const [settingsOpen, setSettingsOpen] = useState3(false);
|
|
900
1075
|
const [historyOpen, setHistoryOpen] = useState3(false);
|
|
1076
|
+
const [modesExpanded, setModesExpanded] = useState3(true);
|
|
1077
|
+
const [buttonsVisible, setButtonsVisible] = useState3(expanded);
|
|
1078
|
+
const [animIn, setAnimIn] = useState3(expanded);
|
|
1079
|
+
const [animDone, setAnimDone] = useState3(expanded);
|
|
1080
|
+
useEffect2(() => {
|
|
1081
|
+
if (expanded) {
|
|
1082
|
+
setAnimDone(false);
|
|
1083
|
+
setButtonsVisible(true);
|
|
1084
|
+
setAnimIn(false);
|
|
1085
|
+
requestAnimationFrame(() => {
|
|
1086
|
+
requestAnimationFrame(() => setAnimIn(true));
|
|
1087
|
+
});
|
|
1088
|
+
const timer = setTimeout(() => setAnimDone(true), 250);
|
|
1089
|
+
return () => clearTimeout(timer);
|
|
1090
|
+
} else if (buttonsVisible) {
|
|
1091
|
+
setHistoryOpen(false);
|
|
1092
|
+
setAnimDone(false);
|
|
1093
|
+
setAnimIn(false);
|
|
1094
|
+
const timer = setTimeout(() => setButtonsVisible(false), 150);
|
|
1095
|
+
return () => clearTimeout(timer);
|
|
1096
|
+
}
|
|
1097
|
+
}, [expanded]);
|
|
901
1098
|
const [corner, setCorner] = useState3(() => {
|
|
902
1099
|
try {
|
|
903
1100
|
const stored = localStorage.getItem("ab-toolbar-corner");
|
|
@@ -910,6 +1107,7 @@ function Toolbar({
|
|
|
910
1107
|
});
|
|
911
1108
|
const [dragging, setDragging] = useState3(false);
|
|
912
1109
|
const [dragPos, setDragPos] = useState3(null);
|
|
1110
|
+
const [snapAnim, setSnapAnim] = useState3(null);
|
|
913
1111
|
const dragState = useRef2(null);
|
|
914
1112
|
const toolbarRef = useRef2(null);
|
|
915
1113
|
const [cameraHovered, setCameraHovered] = useState3(false);
|
|
@@ -923,8 +1121,8 @@ function Toolbar({
|
|
|
923
1121
|
return;
|
|
924
1122
|
}
|
|
925
1123
|
if (e.key === "Escape") {
|
|
926
|
-
if (
|
|
927
|
-
|
|
1124
|
+
if (historyOpen) {
|
|
1125
|
+
setHistoryOpen(false);
|
|
928
1126
|
return;
|
|
929
1127
|
}
|
|
930
1128
|
onCancel();
|
|
@@ -934,7 +1132,7 @@ function Toolbar({
|
|
|
934
1132
|
};
|
|
935
1133
|
document.addEventListener("keydown", onKey);
|
|
936
1134
|
return () => document.removeEventListener("keydown", onKey);
|
|
937
|
-
}, [expanded, onCancel, onCapture, selectedMode,
|
|
1135
|
+
}, [expanded, onCancel, onCapture, selectedMode, historyOpen]);
|
|
938
1136
|
const handleMouseDown = useCallback2(
|
|
939
1137
|
(e) => {
|
|
940
1138
|
e.preventDefault();
|
|
@@ -971,22 +1169,35 @@ function Toolbar({
|
|
|
971
1169
|
if (!ds) return;
|
|
972
1170
|
if (ds.distance < 5) {
|
|
973
1171
|
onToggle();
|
|
1172
|
+
setDragging(false);
|
|
1173
|
+
setDragPos(null);
|
|
1174
|
+
dragState.current = null;
|
|
974
1175
|
} else {
|
|
975
1176
|
const el = toolbarRef.current;
|
|
976
1177
|
const w = el?.offsetWidth ?? CONTAINER_SIZE;
|
|
977
1178
|
const h = el?.offsetHeight ?? CONTAINER_SIZE;
|
|
978
|
-
const
|
|
979
|
-
const
|
|
1179
|
+
const currentX = ds.origX + (e.clientX - ds.startX);
|
|
1180
|
+
const currentY = ds.origY + (e.clientY - ds.startY);
|
|
1181
|
+
const centerX = currentX + w / 2;
|
|
1182
|
+
const centerY = currentY + h / 2;
|
|
980
1183
|
const newCorner = snapToCorner(centerX, centerY);
|
|
981
1184
|
setCorner(newCorner);
|
|
982
1185
|
try {
|
|
983
1186
|
localStorage.setItem("ab-toolbar-corner", newCorner);
|
|
984
1187
|
} catch {
|
|
985
1188
|
}
|
|
1189
|
+
const targetPos = getCornerPosition(newCorner, w, h);
|
|
1190
|
+
setDragging(false);
|
|
1191
|
+
setDragPos(null);
|
|
1192
|
+
setSnapAnim({ x: currentX, y: currentY, animate: false });
|
|
1193
|
+
dragState.current = null;
|
|
1194
|
+
requestAnimationFrame(() => {
|
|
1195
|
+
requestAnimationFrame(() => {
|
|
1196
|
+
setSnapAnim({ ...targetPos, animate: true });
|
|
1197
|
+
setTimeout(() => setSnapAnim(null), 300);
|
|
1198
|
+
});
|
|
1199
|
+
});
|
|
986
1200
|
}
|
|
987
|
-
setDragging(false);
|
|
988
|
-
setDragPos(null);
|
|
989
|
-
dragState.current = null;
|
|
990
1201
|
};
|
|
991
1202
|
window.addEventListener("mousemove", handleMouseMove);
|
|
992
1203
|
window.addEventListener("mouseup", handleMouseUp);
|
|
@@ -998,7 +1209,13 @@ function Toolbar({
|
|
|
998
1209
|
const panelSide = isRightCorner(corner) ? "left" : "right";
|
|
999
1210
|
const tooltipSide = panelSide;
|
|
1000
1211
|
const bottom = isBottomCorner(corner);
|
|
1001
|
-
const positionStyle = dragging && dragPos ? { left: dragPos.x, top: dragPos.y } :
|
|
1212
|
+
const positionStyle = dragging && dragPos ? { left: dragPos.x, top: dragPos.y } : snapAnim ? {
|
|
1213
|
+
left: snapAnim.x,
|
|
1214
|
+
top: snapAnim.y,
|
|
1215
|
+
...snapAnim.animate && {
|
|
1216
|
+
transition: "left 0.3s cubic-bezier(0.23, 1, 0.32, 1), top 0.3s cubic-bezier(0.23, 1, 0.32, 1)"
|
|
1217
|
+
}
|
|
1218
|
+
} : getCornerStyle(corner);
|
|
1002
1219
|
const cameraTooltipLabel = expanded ? "Close" : void 0;
|
|
1003
1220
|
const cameraTooltipStyle = cameraTooltipLabel ? tooltipSide === "left" ? { right: "calc(100% + 10px)", top: "50%", transform: "translateY(-50%)" } : { left: "calc(100% + 10px)", top: "50%", transform: "translateY(-50%)" } : void 0;
|
|
1004
1221
|
const cameraButton = /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
|
|
@@ -1008,14 +1225,17 @@ function Toolbar({
|
|
|
1008
1225
|
style: {
|
|
1009
1226
|
position: "absolute",
|
|
1010
1227
|
...cameraTooltipStyle,
|
|
1011
|
-
background:
|
|
1012
|
-
border:
|
|
1228
|
+
background: bg.base,
|
|
1229
|
+
border: `1px solid ${stroke.default}`,
|
|
1013
1230
|
borderRadius: 6,
|
|
1014
|
-
padding: "
|
|
1015
|
-
|
|
1016
|
-
|
|
1231
|
+
padding: "0 8px",
|
|
1232
|
+
height: 24,
|
|
1233
|
+
display: "flex",
|
|
1234
|
+
alignItems: "center",
|
|
1235
|
+
color: fg.strong,
|
|
1236
|
+
...text.label.xs,
|
|
1017
1237
|
whiteSpace: "nowrap",
|
|
1018
|
-
boxShadow:
|
|
1238
|
+
boxShadow: shadow.tooltip,
|
|
1019
1239
|
pointerEvents: "none"
|
|
1020
1240
|
},
|
|
1021
1241
|
children: cameraTooltipLabel
|
|
@@ -1036,7 +1256,7 @@ function Toolbar({
|
|
|
1036
1256
|
alignItems: "center",
|
|
1037
1257
|
justifyContent: "center",
|
|
1038
1258
|
cursor: dragging ? "grabbing" : "pointer",
|
|
1039
|
-
background: expanded && cameraHovered ?
|
|
1259
|
+
background: expanded && cameraHovered ? state.hoverStrong : "transparent",
|
|
1040
1260
|
transition: "background 0.12s ease"
|
|
1041
1261
|
},
|
|
1042
1262
|
children: [
|
|
@@ -1048,7 +1268,12 @@ function Toolbar({
|
|
|
1048
1268
|
@keyframes ab-spin {
|
|
1049
1269
|
0% { transform: rotate(0deg); }
|
|
1050
1270
|
100% { transform: rotate(360deg); }
|
|
1051
|
-
}
|
|
1271
|
+
}
|
|
1272
|
+
@keyframes ab-panel-in {
|
|
1273
|
+
from { opacity: 0; transform: translateY(4px); }
|
|
1274
|
+
to { opacity: 1; transform: translateY(0); }
|
|
1275
|
+
}
|
|
1276
|
+
`
|
|
1052
1277
|
}
|
|
1053
1278
|
}
|
|
1054
1279
|
),
|
|
@@ -1059,78 +1284,111 @@ function Toolbar({
|
|
|
1059
1284
|
strokeWidth: 2,
|
|
1060
1285
|
style: { animation: "ab-spin 0.8s linear infinite", color: "white" }
|
|
1061
1286
|
}
|
|
1062
|
-
) : phase === "ready" ? /* @__PURE__ */ jsx2(Check, { size: 16, strokeWidth: 2.6, color:
|
|
1287
|
+
) : phase === "ready" ? /* @__PURE__ */ jsx2(Check, { size: 16, strokeWidth: 2.6, color: accent.check }) : expanded ? /* @__PURE__ */ jsx2(
|
|
1063
1288
|
X2,
|
|
1064
1289
|
{
|
|
1065
1290
|
size: 16,
|
|
1066
1291
|
strokeWidth: 1.7,
|
|
1067
|
-
color: cameraHovered ?
|
|
1292
|
+
color: cameraHovered ? fg.strong : fg.sub
|
|
1068
1293
|
}
|
|
1069
1294
|
) : /* @__PURE__ */ jsx2(
|
|
1070
1295
|
Camera,
|
|
1071
1296
|
{
|
|
1072
1297
|
size: 16,
|
|
1073
1298
|
strokeWidth: 1.9,
|
|
1074
|
-
color:
|
|
1299
|
+
color: fg.sub
|
|
1075
1300
|
}
|
|
1076
1301
|
)
|
|
1077
1302
|
]
|
|
1078
1303
|
}
|
|
1079
1304
|
)
|
|
1080
1305
|
] });
|
|
1081
|
-
const toolbarButtons =
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
{
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
onClick: () => {
|
|
1089
|
-
setSettingsOpen(false);
|
|
1090
|
-
setHistoryOpen(false);
|
|
1091
|
-
if (mode === "viewport" || mode === "fullpage") {
|
|
1092
|
-
onModeChange(mode);
|
|
1093
|
-
onCapture(mode);
|
|
1094
|
-
} else {
|
|
1095
|
-
onModeChange(mode);
|
|
1096
|
-
}
|
|
1097
|
-
},
|
|
1098
|
-
children: /* @__PURE__ */ jsx2(ModeIcon, { size: 16, strokeWidth: 1.7 })
|
|
1306
|
+
const toolbarButtons = buttonsVisible ? /* @__PURE__ */ jsx2(
|
|
1307
|
+
"div",
|
|
1308
|
+
{
|
|
1309
|
+
style: {
|
|
1310
|
+
overflow: animDone ? "visible" : "hidden",
|
|
1311
|
+
maxHeight: animIn ? 195 : 0,
|
|
1312
|
+
transition: animIn ? "max-height 250ms cubic-bezier(0.23, 1, 0.32, 1)" : "max-height 150ms cubic-bezier(0.23, 1, 0.32, 1)"
|
|
1099
1313
|
},
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1314
|
+
children: /* @__PURE__ */ jsxs2(
|
|
1315
|
+
"div",
|
|
1316
|
+
{
|
|
1317
|
+
style: {
|
|
1318
|
+
display: "flex",
|
|
1319
|
+
flexDirection: "column",
|
|
1320
|
+
alignItems: "center",
|
|
1321
|
+
opacity: animIn ? 1 : 0,
|
|
1322
|
+
transform: animIn ? "translateY(0)" : `translateY(${bottom ? 6 : -6}px)`,
|
|
1323
|
+
transition: animIn ? "opacity 200ms cubic-bezier(0.23, 1, 0.32, 1), transform 200ms cubic-bezier(0.23, 1, 0.32, 1)" : "opacity 150ms cubic-bezier(0.23, 1, 0.32, 1), transform 150ms cubic-bezier(0.23, 1, 0.32, 1)",
|
|
1324
|
+
willChange: "transform, opacity"
|
|
1325
|
+
},
|
|
1326
|
+
children: [
|
|
1327
|
+
/* @__PURE__ */ jsx2("div", { style: { paddingBottom: 2 }, children: /* @__PURE__ */ jsx2(
|
|
1328
|
+
IconButton,
|
|
1329
|
+
{
|
|
1330
|
+
active: selectedMode === "component" && !historyOpen,
|
|
1331
|
+
tooltipSide,
|
|
1332
|
+
tooltip: "Component",
|
|
1333
|
+
onClick: () => {
|
|
1334
|
+
setHistoryOpen(false);
|
|
1335
|
+
onModeChange("component");
|
|
1336
|
+
},
|
|
1337
|
+
children: /* @__PURE__ */ jsx2(MousePointer2, { size: 16, strokeWidth: 1.7 })
|
|
1338
|
+
}
|
|
1339
|
+
) }),
|
|
1340
|
+
MODES.filter((m) => m.mode !== "component").map(({ mode, label, icon: ModeIcon }) => /* @__PURE__ */ jsx2(
|
|
1341
|
+
"div",
|
|
1342
|
+
{
|
|
1343
|
+
style: {
|
|
1344
|
+
maxHeight: modesExpanded ? 34 : 0,
|
|
1345
|
+
opacity: modesExpanded ? 1 : 0,
|
|
1346
|
+
transition: "max-height 200ms cubic-bezier(0.23, 1, 0.32, 1), opacity 150ms cubic-bezier(0.23, 1, 0.32, 1)"
|
|
1347
|
+
},
|
|
1348
|
+
children: /* @__PURE__ */ jsx2(
|
|
1349
|
+
IconButton,
|
|
1350
|
+
{
|
|
1351
|
+
active: selectedMode === mode && !historyOpen,
|
|
1352
|
+
tooltipSide,
|
|
1353
|
+
tooltip: label,
|
|
1354
|
+
onClick: () => {
|
|
1355
|
+
setHistoryOpen(false);
|
|
1356
|
+
onModeChange(mode);
|
|
1357
|
+
onCapture(mode);
|
|
1358
|
+
},
|
|
1359
|
+
children: /* @__PURE__ */ jsx2(ModeIcon, { size: 16, strokeWidth: 1.7 })
|
|
1360
|
+
}
|
|
1361
|
+
)
|
|
1362
|
+
},
|
|
1363
|
+
mode
|
|
1364
|
+
)),
|
|
1365
|
+
/* @__PURE__ */ jsx2(
|
|
1366
|
+
Separator,
|
|
1367
|
+
{
|
|
1368
|
+
vertical: false,
|
|
1369
|
+
onClick: () => setModesExpanded((p) => !p)
|
|
1370
|
+
}
|
|
1371
|
+
),
|
|
1372
|
+
/* @__PURE__ */ jsx2(
|
|
1373
|
+
HistoryButton,
|
|
1374
|
+
{
|
|
1375
|
+
open: historyOpen,
|
|
1376
|
+
onClick: () => {
|
|
1377
|
+
setHistoryOpen((prev) => !prev);
|
|
1378
|
+
},
|
|
1379
|
+
selectedMode,
|
|
1380
|
+
frameSettings,
|
|
1381
|
+
onFrameSettingsChange,
|
|
1382
|
+
panelSide,
|
|
1383
|
+
tooltipSide,
|
|
1384
|
+
bottom
|
|
1385
|
+
}
|
|
1386
|
+
)
|
|
1387
|
+
]
|
|
1388
|
+
}
|
|
1389
|
+
)
|
|
1390
|
+
}
|
|
1391
|
+
) : null;
|
|
1134
1392
|
return /* @__PURE__ */ jsx2(
|
|
1135
1393
|
"div",
|
|
1136
1394
|
{
|
|
@@ -1143,11 +1401,11 @@ function Toolbar({
|
|
|
1143
1401
|
display: "flex",
|
|
1144
1402
|
flexDirection: "column",
|
|
1145
1403
|
alignItems: "center",
|
|
1146
|
-
background:
|
|
1404
|
+
background: bg.base,
|
|
1147
1405
|
borderRadius: 999,
|
|
1148
1406
|
padding: 6,
|
|
1149
|
-
boxShadow:
|
|
1150
|
-
|
|
1407
|
+
boxShadow: shadow.toolbar,
|
|
1408
|
+
...fontBase,
|
|
1151
1409
|
userSelect: "none"
|
|
1152
1410
|
},
|
|
1153
1411
|
children: bottom ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
@@ -1184,14 +1442,17 @@ function IconButton({
|
|
|
1184
1442
|
style: {
|
|
1185
1443
|
position: "absolute",
|
|
1186
1444
|
...tooltipStyle,
|
|
1187
|
-
background:
|
|
1188
|
-
border:
|
|
1445
|
+
background: bg.base,
|
|
1446
|
+
border: `1px solid ${stroke.default}`,
|
|
1189
1447
|
borderRadius: 6,
|
|
1190
|
-
padding: "
|
|
1191
|
-
|
|
1192
|
-
|
|
1448
|
+
padding: "0 8px",
|
|
1449
|
+
height: 24,
|
|
1450
|
+
display: "flex",
|
|
1451
|
+
alignItems: "center",
|
|
1452
|
+
color: fg.strong,
|
|
1453
|
+
...text.label.xs,
|
|
1193
1454
|
whiteSpace: "nowrap",
|
|
1194
|
-
boxShadow:
|
|
1455
|
+
boxShadow: shadow.tooltip,
|
|
1195
1456
|
pointerEvents: "none"
|
|
1196
1457
|
},
|
|
1197
1458
|
children: tooltip
|
|
@@ -1208,13 +1469,13 @@ function IconButton({
|
|
|
1208
1469
|
height: 32,
|
|
1209
1470
|
borderRadius: "50%",
|
|
1210
1471
|
border: "none",
|
|
1211
|
-
background: active || hovered ?
|
|
1472
|
+
background: active || hovered ? state.hoverStrong : "transparent",
|
|
1212
1473
|
display: "flex",
|
|
1213
1474
|
alignItems: "center",
|
|
1214
1475
|
justifyContent: "center",
|
|
1215
1476
|
cursor: "pointer",
|
|
1216
1477
|
padding: 0,
|
|
1217
|
-
color: active || hovered ?
|
|
1478
|
+
color: active || hovered ? fg.strong : fg.sub,
|
|
1218
1479
|
transition: "background 0.12s ease, color 0.12s ease"
|
|
1219
1480
|
},
|
|
1220
1481
|
children
|
|
@@ -1222,37 +1483,11 @@ function IconButton({
|
|
|
1222
1483
|
)
|
|
1223
1484
|
] });
|
|
1224
1485
|
}
|
|
1225
|
-
function SettingsButton({
|
|
1226
|
-
open,
|
|
1227
|
-
onClick,
|
|
1228
|
-
selectedMode,
|
|
1229
|
-
frameSettings,
|
|
1230
|
-
onFrameSettingsChange,
|
|
1231
|
-
panelSide,
|
|
1232
|
-
tooltipSide,
|
|
1233
|
-
bottom
|
|
1234
|
-
}) {
|
|
1235
|
-
const verticalAlign = bottom ? { bottom: 0 } : { top: 0 };
|
|
1236
|
-
const panelStyle = panelSide === "left" ? { right: "calc(100% + 10px)", ...verticalAlign } : { left: "calc(100% + 10px)", ...verticalAlign };
|
|
1237
|
-
return /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
|
|
1238
|
-
/* @__PURE__ */ jsx2(IconButton, { active: open, tooltipSide, tooltip: !open ? "Settings" : void 0, onClick, children: /* @__PURE__ */ jsx2(Settings, { size: 16, strokeWidth: 1.7 }) }),
|
|
1239
|
-
open && /* @__PURE__ */ jsx2(
|
|
1240
|
-
SettingsPanel,
|
|
1241
|
-
{
|
|
1242
|
-
style: { position: "absolute", ...panelStyle },
|
|
1243
|
-
onClose: onClick,
|
|
1244
|
-
selectedMode,
|
|
1245
|
-
frameSettings,
|
|
1246
|
-
onFrameSettingsChange
|
|
1247
|
-
}
|
|
1248
|
-
)
|
|
1249
|
-
] });
|
|
1250
|
-
}
|
|
1251
1486
|
function DropItem2({
|
|
1252
1487
|
children,
|
|
1253
1488
|
onClick,
|
|
1254
1489
|
active,
|
|
1255
|
-
accent
|
|
1490
|
+
accent: accent2
|
|
1256
1491
|
}) {
|
|
1257
1492
|
return /* @__PURE__ */ jsx2(
|
|
1258
1493
|
"button",
|
|
@@ -1262,41 +1497,79 @@ function DropItem2({
|
|
|
1262
1497
|
display: "block",
|
|
1263
1498
|
width: "100%",
|
|
1264
1499
|
padding: "7px 12px",
|
|
1265
|
-
background: active ?
|
|
1500
|
+
background: active ? state.active : "transparent",
|
|
1266
1501
|
border: "none",
|
|
1267
|
-
color:
|
|
1502
|
+
color: accent2 ? accent.highlight : fg.strong,
|
|
1268
1503
|
textAlign: "left",
|
|
1269
1504
|
cursor: "pointer",
|
|
1270
|
-
|
|
1505
|
+
...text.paragraph.sm,
|
|
1271
1506
|
fontFamily: "inherit"
|
|
1272
1507
|
},
|
|
1273
1508
|
children
|
|
1274
1509
|
}
|
|
1275
1510
|
);
|
|
1276
1511
|
}
|
|
1277
|
-
function Separator({
|
|
1512
|
+
function Separator({
|
|
1513
|
+
vertical = true,
|
|
1514
|
+
onClick
|
|
1515
|
+
}) {
|
|
1278
1516
|
return /* @__PURE__ */ jsx2(
|
|
1279
1517
|
"div",
|
|
1280
1518
|
{
|
|
1519
|
+
onClick,
|
|
1281
1520
|
style: {
|
|
1521
|
+
position: "relative",
|
|
1282
1522
|
width: vertical ? 1 : 24,
|
|
1283
1523
|
height: vertical ? 18 : 1,
|
|
1284
|
-
background:
|
|
1524
|
+
background: stroke.strong,
|
|
1285
1525
|
flexShrink: 0,
|
|
1286
|
-
margin: vertical ? "0 6px" : "6px 0"
|
|
1287
|
-
|
|
1526
|
+
margin: vertical ? "0 6px" : "6px 0",
|
|
1527
|
+
cursor: onClick ? "pointer" : void 0
|
|
1528
|
+
},
|
|
1529
|
+
children: onClick && /* @__PURE__ */ jsx2("div", { style: { position: "absolute", inset: vertical ? "0 -8px" : "-8px 0" } })
|
|
1530
|
+
}
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
function PanelTab({
|
|
1534
|
+
children,
|
|
1535
|
+
active,
|
|
1536
|
+
onClick
|
|
1537
|
+
}) {
|
|
1538
|
+
return /* @__PURE__ */ jsx2(
|
|
1539
|
+
"button",
|
|
1540
|
+
{
|
|
1541
|
+
onClick,
|
|
1542
|
+
style: {
|
|
1543
|
+
flex: 1,
|
|
1544
|
+
padding: "6px 0",
|
|
1545
|
+
border: "none",
|
|
1546
|
+
borderBottom: `2px solid ${active ? fg.strong : "transparent"}`,
|
|
1547
|
+
background: "transparent",
|
|
1548
|
+
color: active ? fg.strong : fg.muted,
|
|
1549
|
+
...text.label.xs,
|
|
1550
|
+
fontFamily: "inherit",
|
|
1551
|
+
cursor: "pointer",
|
|
1552
|
+
transition: "color 0.12s ease, border-color 0.12s ease"
|
|
1553
|
+
},
|
|
1554
|
+
children
|
|
1288
1555
|
}
|
|
1289
1556
|
);
|
|
1290
1557
|
}
|
|
1291
1558
|
function HistoryButton({
|
|
1292
1559
|
open,
|
|
1293
1560
|
onClick,
|
|
1561
|
+
selectedMode,
|
|
1562
|
+
frameSettings,
|
|
1563
|
+
onFrameSettingsChange,
|
|
1294
1564
|
panelSide,
|
|
1295
1565
|
tooltipSide,
|
|
1296
1566
|
bottom
|
|
1297
1567
|
}) {
|
|
1568
|
+
const [activeTab, setActiveTab] = useState3("screenshots");
|
|
1298
1569
|
const [toast, setToast] = useState3(null);
|
|
1299
1570
|
const [pushing, setPushing] = useState3(false);
|
|
1571
|
+
const [saveDir, setSaveDir] = useState3(null);
|
|
1572
|
+
const [picking, setPicking] = useState3(false);
|
|
1300
1573
|
const [repos, setRepos] = useState3([]);
|
|
1301
1574
|
const [branches, setBranches] = useState3([]);
|
|
1302
1575
|
const [screenshots, setScreenshots] = useState3([]);
|
|
@@ -1309,6 +1582,30 @@ function HistoryButton({
|
|
|
1309
1582
|
const [editingFile, setEditingFile] = useState3(null);
|
|
1310
1583
|
const [editValue, setEditValue] = useState3("");
|
|
1311
1584
|
const [hoveredThumb, setHoveredThumb] = useState3(null);
|
|
1585
|
+
useEffect2(() => {
|
|
1586
|
+
if (!open) return;
|
|
1587
|
+
fetch("/__afterbefore/config").then((r) => r.json()).then((data) => setSaveDir(data.saveDir)).catch(() => {
|
|
1588
|
+
});
|
|
1589
|
+
}, [open]);
|
|
1590
|
+
const handlePickFolder = async () => {
|
|
1591
|
+
setPicking(true);
|
|
1592
|
+
try {
|
|
1593
|
+
const res = await fetch("/__afterbefore/pick-folder", { method: "POST" });
|
|
1594
|
+
const data = await res.json();
|
|
1595
|
+
if (data.folder) {
|
|
1596
|
+
await fetch("/__afterbefore/config", {
|
|
1597
|
+
method: "POST",
|
|
1598
|
+
headers: { "Content-Type": "application/json" },
|
|
1599
|
+
body: JSON.stringify({ saveDir: data.folder })
|
|
1600
|
+
});
|
|
1601
|
+
setSaveDir(data.folder);
|
|
1602
|
+
}
|
|
1603
|
+
} catch {
|
|
1604
|
+
} finally {
|
|
1605
|
+
setPicking(false);
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
1608
|
+
const shortDir = saveDir ? saveDir.replace(/^\/Users\/[^/]+/, "~") : "~/Desktop";
|
|
1312
1609
|
useEffect2(() => {
|
|
1313
1610
|
if (!open) {
|
|
1314
1611
|
setRepoDropOpen(false);
|
|
@@ -1425,255 +1722,259 @@ function HistoryButton({
|
|
|
1425
1722
|
maxWidth: 360,
|
|
1426
1723
|
padding: "10px 12px",
|
|
1427
1724
|
borderRadius: 12,
|
|
1428
|
-
background:
|
|
1429
|
-
border:
|
|
1430
|
-
boxShadow:
|
|
1725
|
+
background: bg.base,
|
|
1726
|
+
border: `1px solid ${stroke.default}`,
|
|
1727
|
+
boxShadow: shadow.panel,
|
|
1728
|
+
animation: "ab-panel-in 150ms cubic-bezier(0.23, 1, 0.32, 1)"
|
|
1431
1729
|
},
|
|
1432
1730
|
children: [
|
|
1433
|
-
/* @__PURE__ */
|
|
1434
|
-
"
|
|
1731
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: 2, marginBottom: 10 }, children: [
|
|
1732
|
+
/* @__PURE__ */ jsx2(PanelTab, { active: activeTab === "screenshots", onClick: () => setActiveTab("screenshots"), children: "Screenshots" }),
|
|
1733
|
+
/* @__PURE__ */ jsx2(PanelTab, { active: activeTab === "settings", onClick: () => setActiveTab("settings"), children: "Settings" })
|
|
1734
|
+
] }),
|
|
1735
|
+
activeTab === "settings" && /* @__PURE__ */ jsx2(
|
|
1736
|
+
SettingsContent,
|
|
1435
1737
|
{
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
marginBottom: 10
|
|
1442
|
-
},
|
|
1443
|
-
children: "Screenshots"
|
|
1738
|
+
frameSettings,
|
|
1739
|
+
onFrameSettingsChange,
|
|
1740
|
+
saveDir: shortDir,
|
|
1741
|
+
picking,
|
|
1742
|
+
onPickFolder: handlePickFolder
|
|
1444
1743
|
}
|
|
1445
1744
|
),
|
|
1446
|
-
/* @__PURE__ */ jsxs2(
|
|
1447
|
-
/* @__PURE__ */
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1745
|
+
activeTab === "screenshots" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1746
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: 6, marginBottom: 10 }, children: [
|
|
1747
|
+
/* @__PURE__ */ jsx2(
|
|
1748
|
+
FilterDropdown,
|
|
1749
|
+
{
|
|
1750
|
+
label: "Project",
|
|
1751
|
+
value: selectedRepo,
|
|
1752
|
+
options: repos,
|
|
1753
|
+
isOpen: repoDropOpen,
|
|
1754
|
+
onToggle: () => {
|
|
1755
|
+
setRepoDropOpen((p) => !p);
|
|
1756
|
+
setBranchDropOpen(false);
|
|
1757
|
+
},
|
|
1758
|
+
onSelect: (repo) => {
|
|
1759
|
+
setSelectedRepo(repo);
|
|
1760
|
+
setSelectedBranch(null);
|
|
1761
|
+
setRepoDropOpen(false);
|
|
1762
|
+
}
|
|
1462
1763
|
}
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1764
|
+
),
|
|
1765
|
+
/* @__PURE__ */ jsx2(
|
|
1766
|
+
FilterDropdown,
|
|
1767
|
+
{
|
|
1768
|
+
label: "Branch",
|
|
1769
|
+
value: selectedBranch,
|
|
1770
|
+
options: branches,
|
|
1771
|
+
isOpen: branchDropOpen,
|
|
1772
|
+
onToggle: () => {
|
|
1773
|
+
setBranchDropOpen((p) => !p);
|
|
1774
|
+
setRepoDropOpen(false);
|
|
1775
|
+
},
|
|
1776
|
+
onSelect: (branch) => {
|
|
1777
|
+
setSelectedBranch(branch);
|
|
1778
|
+
setBranchDropOpen(false);
|
|
1779
|
+
}
|
|
1479
1780
|
}
|
|
1480
|
-
|
|
1481
|
-
)
|
|
1482
|
-
|
|
1483
|
-
loading ? /* @__PURE__ */ jsx2(
|
|
1484
|
-
"div",
|
|
1485
|
-
{
|
|
1486
|
-
style: {
|
|
1487
|
-
padding: "12px 0",
|
|
1488
|
-
textAlign: "center",
|
|
1489
|
-
fontSize: 12,
|
|
1490
|
-
color: "rgba(255, 255, 255, 0.35)"
|
|
1491
|
-
},
|
|
1492
|
-
children: "Loading..."
|
|
1493
|
-
}
|
|
1494
|
-
) : screenshots.length === 0 ? /* @__PURE__ */ jsx2(
|
|
1495
|
-
"div",
|
|
1496
|
-
{
|
|
1497
|
-
style: {
|
|
1498
|
-
padding: "12px 0",
|
|
1499
|
-
textAlign: "center",
|
|
1500
|
-
fontSize: 12,
|
|
1501
|
-
color: "rgba(255, 255, 255, 0.35)"
|
|
1502
|
-
},
|
|
1503
|
-
children: "No screenshots yet"
|
|
1504
|
-
}
|
|
1505
|
-
) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1506
|
-
/* @__PURE__ */ jsx2(
|
|
1781
|
+
)
|
|
1782
|
+
] }),
|
|
1783
|
+
loading ? /* @__PURE__ */ jsx2(
|
|
1507
1784
|
"div",
|
|
1508
1785
|
{
|
|
1509
1786
|
style: {
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
gap: 8
|
|
1787
|
+
padding: "12px 0",
|
|
1788
|
+
textAlign: "center",
|
|
1789
|
+
...text.paragraph.xs,
|
|
1790
|
+
color: fg.faint
|
|
1515
1791
|
},
|
|
1516
|
-
children:
|
|
1517
|
-
const imgUrl = `/__afterbefore/history/image?repo=${encodeURIComponent(selectedRepo || "")}&branch=${encodeURIComponent(selectedBranch || "")}&file=${encodeURIComponent(shot.filename)}`;
|
|
1518
|
-
const isEditing = editingFile === shot.filename;
|
|
1519
|
-
return /* @__PURE__ */ jsxs2(
|
|
1520
|
-
"div",
|
|
1521
|
-
{
|
|
1522
|
-
style: {
|
|
1523
|
-
display: "flex",
|
|
1524
|
-
gap: 10,
|
|
1525
|
-
alignItems: "center"
|
|
1526
|
-
},
|
|
1527
|
-
children: [
|
|
1528
|
-
/* @__PURE__ */ jsxs2(
|
|
1529
|
-
"div",
|
|
1530
|
-
{
|
|
1531
|
-
style: {
|
|
1532
|
-
position: "relative",
|
|
1533
|
-
width: 56,
|
|
1534
|
-
height: 36,
|
|
1535
|
-
flexShrink: 0,
|
|
1536
|
-
borderRadius: 4,
|
|
1537
|
-
overflow: "hidden",
|
|
1538
|
-
cursor: "pointer"
|
|
1539
|
-
},
|
|
1540
|
-
onMouseEnter: () => setHoveredThumb(shot.filename),
|
|
1541
|
-
onMouseLeave: () => setHoveredThumb(null),
|
|
1542
|
-
onClick: () => setLightboxSrc(imgUrl),
|
|
1543
|
-
children: [
|
|
1544
|
-
/* @__PURE__ */ jsx2(
|
|
1545
|
-
"img",
|
|
1546
|
-
{
|
|
1547
|
-
src: imgUrl,
|
|
1548
|
-
alt: "",
|
|
1549
|
-
style: {
|
|
1550
|
-
width: 56,
|
|
1551
|
-
height: 36,
|
|
1552
|
-
objectFit: "cover",
|
|
1553
|
-
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
1554
|
-
borderRadius: 4,
|
|
1555
|
-
background: "rgba(255, 255, 255, 0.05)",
|
|
1556
|
-
display: "block"
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
|
-
),
|
|
1560
|
-
/* @__PURE__ */ jsx2(
|
|
1561
|
-
"div",
|
|
1562
|
-
{
|
|
1563
|
-
style: {
|
|
1564
|
-
position: "absolute",
|
|
1565
|
-
inset: 0,
|
|
1566
|
-
background: "rgba(0, 0, 0, 0.55)",
|
|
1567
|
-
display: "flex",
|
|
1568
|
-
alignItems: "center",
|
|
1569
|
-
justifyContent: "center",
|
|
1570
|
-
borderRadius: 4,
|
|
1571
|
-
opacity: hoveredThumb === shot.filename ? 1 : 0,
|
|
1572
|
-
transition: "opacity 0.15s ease"
|
|
1573
|
-
},
|
|
1574
|
-
children: /* @__PURE__ */ jsx2(Eye, { size: 16, strokeWidth: 1.8, color: "rgba(255, 255, 255, 0.9)" })
|
|
1575
|
-
}
|
|
1576
|
-
)
|
|
1577
|
-
]
|
|
1578
|
-
}
|
|
1579
|
-
),
|
|
1580
|
-
/* @__PURE__ */ jsx2("div", { style: { flex: 1, minWidth: 0 }, children: isEditing ? /* @__PURE__ */ jsx2(
|
|
1581
|
-
"input",
|
|
1582
|
-
{
|
|
1583
|
-
autoFocus: true,
|
|
1584
|
-
value: editValue,
|
|
1585
|
-
onChange: (e) => setEditValue(e.target.value),
|
|
1586
|
-
onKeyDown: (e) => {
|
|
1587
|
-
if (e.key === "Enter") handleRename(shot.filename, editValue);
|
|
1588
|
-
if (e.key === "Escape") setEditingFile(null);
|
|
1589
|
-
},
|
|
1590
|
-
onBlur: () => handleRename(shot.filename, editValue),
|
|
1591
|
-
style: {
|
|
1592
|
-
width: "100%",
|
|
1593
|
-
fontSize: 12,
|
|
1594
|
-
color: "rgba(255, 255, 255, 0.88)",
|
|
1595
|
-
background: "rgba(255, 255, 255, 0.1)",
|
|
1596
|
-
border: "1px solid rgba(255, 255, 255, 0.2)",
|
|
1597
|
-
borderRadius: 4,
|
|
1598
|
-
padding: "2px 6px",
|
|
1599
|
-
outline: "none",
|
|
1600
|
-
fontFamily: "inherit"
|
|
1601
|
-
}
|
|
1602
|
-
}
|
|
1603
|
-
) : /* @__PURE__ */ jsx2(
|
|
1604
|
-
"div",
|
|
1605
|
-
{
|
|
1606
|
-
onClick: () => {
|
|
1607
|
-
setEditingFile(shot.filename);
|
|
1608
|
-
setEditValue(shot.filename.replace(/\.png$/, ""));
|
|
1609
|
-
},
|
|
1610
|
-
style: {
|
|
1611
|
-
fontSize: 12,
|
|
1612
|
-
color: "rgba(255, 255, 255, 0.88)",
|
|
1613
|
-
cursor: "pointer",
|
|
1614
|
-
overflow: "hidden",
|
|
1615
|
-
textOverflow: "ellipsis",
|
|
1616
|
-
whiteSpace: "nowrap"
|
|
1617
|
-
},
|
|
1618
|
-
title: "Click to rename",
|
|
1619
|
-
children: formatTimestamp(shot.filename)
|
|
1620
|
-
}
|
|
1621
|
-
) }),
|
|
1622
|
-
/* @__PURE__ */ jsx2(
|
|
1623
|
-
"button",
|
|
1624
|
-
{
|
|
1625
|
-
onClick: () => handleDelete(shot.filename),
|
|
1626
|
-
title: "Delete screenshot",
|
|
1627
|
-
style: {
|
|
1628
|
-
flexShrink: 0,
|
|
1629
|
-
width: 24,
|
|
1630
|
-
height: 24,
|
|
1631
|
-
borderRadius: 4,
|
|
1632
|
-
border: "none",
|
|
1633
|
-
background: "transparent",
|
|
1634
|
-
color: "rgba(255, 255, 255, 0.35)",
|
|
1635
|
-
cursor: "pointer",
|
|
1636
|
-
display: "flex",
|
|
1637
|
-
alignItems: "center",
|
|
1638
|
-
justifyContent: "center",
|
|
1639
|
-
padding: 0
|
|
1640
|
-
},
|
|
1641
|
-
onMouseEnter: (e) => {
|
|
1642
|
-
e.currentTarget.style.color = "rgba(239, 68, 68, 0.9)";
|
|
1643
|
-
e.currentTarget.style.background = "rgba(239, 68, 68, 0.1)";
|
|
1644
|
-
},
|
|
1645
|
-
onMouseLeave: (e) => {
|
|
1646
|
-
e.currentTarget.style.color = "rgba(255, 255, 255, 0.35)";
|
|
1647
|
-
e.currentTarget.style.background = "transparent";
|
|
1648
|
-
},
|
|
1649
|
-
children: /* @__PURE__ */ jsx2(Trash22, { size: 13, strokeWidth: 1.8 })
|
|
1650
|
-
}
|
|
1651
|
-
)
|
|
1652
|
-
]
|
|
1653
|
-
},
|
|
1654
|
-
shot.filename
|
|
1655
|
-
);
|
|
1656
|
-
})
|
|
1792
|
+
children: "Loading..."
|
|
1657
1793
|
}
|
|
1658
|
-
)
|
|
1659
|
-
/* @__PURE__ */ jsx2(
|
|
1794
|
+
) : screenshots.length === 0 ? /* @__PURE__ */ jsx2(
|
|
1660
1795
|
"div",
|
|
1661
1796
|
{
|
|
1662
1797
|
style: {
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1798
|
+
padding: "12px 0",
|
|
1799
|
+
textAlign: "center",
|
|
1800
|
+
...text.paragraph.xs,
|
|
1801
|
+
color: fg.faint
|
|
1802
|
+
},
|
|
1803
|
+
children: "No screenshots yet"
|
|
1667
1804
|
}
|
|
1668
|
-
),
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1805
|
+
) : /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
1806
|
+
/* @__PURE__ */ jsx2(
|
|
1807
|
+
"div",
|
|
1808
|
+
{
|
|
1809
|
+
style: {
|
|
1810
|
+
maxHeight: 240,
|
|
1811
|
+
overflowY: "auto",
|
|
1812
|
+
display: "flex",
|
|
1813
|
+
flexDirection: "column",
|
|
1814
|
+
gap: 8
|
|
1815
|
+
},
|
|
1816
|
+
children: screenshots.map((shot) => {
|
|
1817
|
+
const imgUrl = `/__afterbefore/history/image?repo=${encodeURIComponent(selectedRepo || "")}&branch=${encodeURIComponent(selectedBranch || "")}&file=${encodeURIComponent(shot.filename)}`;
|
|
1818
|
+
const isEditing = editingFile === shot.filename;
|
|
1819
|
+
return /* @__PURE__ */ jsxs2(
|
|
1820
|
+
"div",
|
|
1821
|
+
{
|
|
1822
|
+
style: {
|
|
1823
|
+
display: "flex",
|
|
1824
|
+
gap: 10,
|
|
1825
|
+
alignItems: "center"
|
|
1826
|
+
},
|
|
1827
|
+
children: [
|
|
1828
|
+
/* @__PURE__ */ jsxs2(
|
|
1829
|
+
"div",
|
|
1830
|
+
{
|
|
1831
|
+
style: {
|
|
1832
|
+
position: "relative",
|
|
1833
|
+
width: 56,
|
|
1834
|
+
height: 36,
|
|
1835
|
+
flexShrink: 0,
|
|
1836
|
+
borderRadius: 4,
|
|
1837
|
+
overflow: "hidden",
|
|
1838
|
+
cursor: "pointer"
|
|
1839
|
+
},
|
|
1840
|
+
onMouseEnter: () => setHoveredThumb(shot.filename),
|
|
1841
|
+
onMouseLeave: () => setHoveredThumb(null),
|
|
1842
|
+
onClick: () => setLightboxSrc(imgUrl),
|
|
1843
|
+
children: [
|
|
1844
|
+
/* @__PURE__ */ jsx2(
|
|
1845
|
+
"img",
|
|
1846
|
+
{
|
|
1847
|
+
src: imgUrl,
|
|
1848
|
+
alt: "",
|
|
1849
|
+
style: {
|
|
1850
|
+
width: 56,
|
|
1851
|
+
height: 36,
|
|
1852
|
+
objectFit: "cover",
|
|
1853
|
+
border: `1px solid ${stroke.default}`,
|
|
1854
|
+
borderRadius: 4,
|
|
1855
|
+
background: state.subtle,
|
|
1856
|
+
display: "block"
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
),
|
|
1860
|
+
/* @__PURE__ */ jsx2(
|
|
1861
|
+
"div",
|
|
1862
|
+
{
|
|
1863
|
+
style: {
|
|
1864
|
+
position: "absolute",
|
|
1865
|
+
inset: 0,
|
|
1866
|
+
background: "rgba(0, 0, 0, 0.55)",
|
|
1867
|
+
display: "flex",
|
|
1868
|
+
alignItems: "center",
|
|
1869
|
+
justifyContent: "center",
|
|
1870
|
+
borderRadius: 4,
|
|
1871
|
+
opacity: hoveredThumb === shot.filename ? 1 : 0,
|
|
1872
|
+
transition: "opacity 0.15s ease"
|
|
1873
|
+
},
|
|
1874
|
+
children: /* @__PURE__ */ jsx2(Eye, { size: 16, strokeWidth: 1.8, color: fg.strong })
|
|
1875
|
+
}
|
|
1876
|
+
)
|
|
1877
|
+
]
|
|
1878
|
+
}
|
|
1879
|
+
),
|
|
1880
|
+
/* @__PURE__ */ jsx2("div", { style: { flex: 1, minWidth: 0 }, children: isEditing ? /* @__PURE__ */ jsx2(
|
|
1881
|
+
"input",
|
|
1882
|
+
{
|
|
1883
|
+
autoFocus: true,
|
|
1884
|
+
value: editValue,
|
|
1885
|
+
onChange: (e) => setEditValue(e.target.value),
|
|
1886
|
+
onKeyDown: (e) => {
|
|
1887
|
+
if (e.key === "Enter") handleRename(shot.filename, editValue);
|
|
1888
|
+
if (e.key === "Escape") setEditingFile(null);
|
|
1889
|
+
},
|
|
1890
|
+
onBlur: () => handleRename(shot.filename, editValue),
|
|
1891
|
+
style: {
|
|
1892
|
+
width: "100%",
|
|
1893
|
+
...text.label.xs,
|
|
1894
|
+
color: fg.strong,
|
|
1895
|
+
background: state.hover,
|
|
1896
|
+
border: `1px solid ${stroke.interactive}`,
|
|
1897
|
+
borderRadius: 4,
|
|
1898
|
+
padding: "2px 6px",
|
|
1899
|
+
outline: "none",
|
|
1900
|
+
fontFamily: "inherit"
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
) : /* @__PURE__ */ jsx2(
|
|
1904
|
+
"div",
|
|
1905
|
+
{
|
|
1906
|
+
onClick: () => {
|
|
1907
|
+
setEditingFile(shot.filename);
|
|
1908
|
+
setEditValue(shot.filename.replace(/\.png$/, ""));
|
|
1909
|
+
},
|
|
1910
|
+
style: {
|
|
1911
|
+
...text.label.xs,
|
|
1912
|
+
color: fg.strong,
|
|
1913
|
+
cursor: "pointer",
|
|
1914
|
+
overflow: "hidden",
|
|
1915
|
+
textOverflow: "ellipsis",
|
|
1916
|
+
whiteSpace: "nowrap"
|
|
1917
|
+
},
|
|
1918
|
+
title: "Click to rename",
|
|
1919
|
+
children: formatTimestamp(shot.filename)
|
|
1920
|
+
}
|
|
1921
|
+
) }),
|
|
1922
|
+
/* @__PURE__ */ jsx2(
|
|
1923
|
+
"button",
|
|
1924
|
+
{
|
|
1925
|
+
onClick: () => handleDelete(shot.filename),
|
|
1926
|
+
title: "Delete screenshot",
|
|
1927
|
+
style: {
|
|
1928
|
+
flexShrink: 0,
|
|
1929
|
+
width: 24,
|
|
1930
|
+
height: 24,
|
|
1931
|
+
borderRadius: 4,
|
|
1932
|
+
border: "none",
|
|
1933
|
+
background: "transparent",
|
|
1934
|
+
color: fg.faint,
|
|
1935
|
+
cursor: "pointer",
|
|
1936
|
+
display: "flex",
|
|
1937
|
+
alignItems: "center",
|
|
1938
|
+
justifyContent: "center",
|
|
1939
|
+
padding: 0
|
|
1940
|
+
},
|
|
1941
|
+
onMouseEnter: (e) => {
|
|
1942
|
+
e.currentTarget.style.color = feedback.error;
|
|
1943
|
+
e.currentTarget.style.background = feedback.errorBg;
|
|
1944
|
+
},
|
|
1945
|
+
onMouseLeave: (e) => {
|
|
1946
|
+
e.currentTarget.style.color = fg.faint;
|
|
1947
|
+
e.currentTarget.style.background = "transparent";
|
|
1948
|
+
},
|
|
1949
|
+
children: /* @__PURE__ */ jsx2(Trash22, { size: 13, strokeWidth: 1.8 })
|
|
1950
|
+
}
|
|
1951
|
+
)
|
|
1952
|
+
]
|
|
1953
|
+
},
|
|
1954
|
+
shot.filename
|
|
1955
|
+
);
|
|
1956
|
+
})
|
|
1957
|
+
}
|
|
1958
|
+
),
|
|
1959
|
+
/* @__PURE__ */ jsx2(
|
|
1960
|
+
"div",
|
|
1961
|
+
{
|
|
1962
|
+
style: {
|
|
1963
|
+
height: 1,
|
|
1964
|
+
background: state.active,
|
|
1965
|
+
margin: "8px 0"
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
),
|
|
1969
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
1970
|
+
/* @__PURE__ */ jsxs2(ActionButton, { onClick: handleOpenFolder, children: [
|
|
1971
|
+
/* @__PURE__ */ jsx2(FolderOpen, { size: 13, strokeWidth: 1.8 }),
|
|
1972
|
+
"Open Folder"
|
|
1973
|
+
] }),
|
|
1974
|
+
/* @__PURE__ */ jsxs2(ActionButton, { onClick: handlePush, disabled: pushing, children: [
|
|
1975
|
+
/* @__PURE__ */ jsx2(ArrowUp, { size: 13, strokeWidth: 1.8 }),
|
|
1976
|
+
pushing ? "Pushing..." : "Push to PR"
|
|
1977
|
+
] })
|
|
1677
1978
|
] })
|
|
1678
1979
|
] })
|
|
1679
1980
|
] }),
|
|
@@ -1688,12 +1989,11 @@ function HistoryButton({
|
|
|
1688
1989
|
marginBottom: 8,
|
|
1689
1990
|
padding: "6px 12px",
|
|
1690
1991
|
borderRadius: 6,
|
|
1691
|
-
|
|
1692
|
-
fontWeight: 500,
|
|
1992
|
+
...text.label.xs,
|
|
1693
1993
|
whiteSpace: "nowrap",
|
|
1694
1994
|
color: "white",
|
|
1695
|
-
background: toast.type === "success" ?
|
|
1696
|
-
boxShadow:
|
|
1995
|
+
background: toast.type === "success" ? feedback.success : feedback.error,
|
|
1996
|
+
boxShadow: shadow.toast
|
|
1697
1997
|
},
|
|
1698
1998
|
children: toast.message
|
|
1699
1999
|
}
|
|
@@ -1747,7 +2047,7 @@ function HistoryButton({
|
|
|
1747
2047
|
height: 32,
|
|
1748
2048
|
borderRadius: "50%",
|
|
1749
2049
|
border: "none",
|
|
1750
|
-
background:
|
|
2050
|
+
background: state.pressed,
|
|
1751
2051
|
color: "white",
|
|
1752
2052
|
cursor: "pointer",
|
|
1753
2053
|
display: "flex",
|
|
@@ -1776,9 +2076,8 @@ function FilterDropdown({
|
|
|
1776
2076
|
"div",
|
|
1777
2077
|
{
|
|
1778
2078
|
style: {
|
|
1779
|
-
|
|
1780
|
-
color:
|
|
1781
|
-
letterSpacing: "0.02em",
|
|
2079
|
+
...text.subheading.xxs,
|
|
2080
|
+
color: fg.muted,
|
|
1782
2081
|
marginBottom: 3
|
|
1783
2082
|
},
|
|
1784
2083
|
children: label
|
|
@@ -1798,11 +2097,11 @@ function FilterDropdown({
|
|
|
1798
2097
|
height: 30,
|
|
1799
2098
|
padding: "0 8px",
|
|
1800
2099
|
borderRadius: 7,
|
|
1801
|
-
border:
|
|
1802
|
-
background:
|
|
1803
|
-
color:
|
|
2100
|
+
border: `1px solid ${stroke.default}`,
|
|
2101
|
+
background: state.input,
|
|
2102
|
+
color: fg.strong,
|
|
1804
2103
|
cursor: "pointer",
|
|
1805
|
-
|
|
2104
|
+
...text.label.xs,
|
|
1806
2105
|
fontFamily: "inherit"
|
|
1807
2106
|
},
|
|
1808
2107
|
children: [
|
|
@@ -1831,11 +2130,11 @@ function FilterDropdown({
|
|
|
1831
2130
|
right: 0,
|
|
1832
2131
|
maxHeight: 160,
|
|
1833
2132
|
overflowY: "auto",
|
|
1834
|
-
background:
|
|
1835
|
-
border:
|
|
2133
|
+
background: bg.base,
|
|
2134
|
+
border: `1px solid ${stroke.default}`,
|
|
1836
2135
|
borderRadius: 8,
|
|
1837
2136
|
padding: "4px 0",
|
|
1838
|
-
boxShadow:
|
|
2137
|
+
boxShadow: shadow.dropdown,
|
|
1839
2138
|
zIndex: 1
|
|
1840
2139
|
},
|
|
1841
2140
|
children: options.map((opt) => /* @__PURE__ */ jsx2(
|
|
@@ -1872,9 +2171,9 @@ function ActionButton({
|
|
|
1872
2171
|
width: "100%",
|
|
1873
2172
|
padding: "6px 8px",
|
|
1874
2173
|
border: "none",
|
|
1875
|
-
background: hovered ?
|
|
1876
|
-
color:
|
|
1877
|
-
|
|
2174
|
+
background: hovered ? state.active : "transparent",
|
|
2175
|
+
color: fg.default,
|
|
2176
|
+
...text.label.xs,
|
|
1878
2177
|
borderRadius: 6,
|
|
1879
2178
|
cursor: disabled ? "wait" : "pointer",
|
|
1880
2179
|
textAlign: "left",
|
|
@@ -1907,18 +2206,18 @@ function Inspector({ onSelect, onCancel }) {
|
|
|
1907
2206
|
const hoveredEl = useRef3(null);
|
|
1908
2207
|
const styleEl = useRef3(null);
|
|
1909
2208
|
useEffect3(() => {
|
|
1910
|
-
const
|
|
1911
|
-
|
|
1912
|
-
|
|
2209
|
+
const style2 = document.createElement("style");
|
|
2210
|
+
style2.setAttribute("data-afterbefore", "true");
|
|
2211
|
+
style2.textContent = [
|
|
1913
2212
|
"* { cursor: crosshair !important; }",
|
|
1914
2213
|
"[data-afterbefore], [data-afterbefore] * { cursor: auto !important; }",
|
|
1915
2214
|
"[data-afterbefore] button, [data-afterbefore] label, [data-afterbefore] a { cursor: pointer !important; }",
|
|
1916
2215
|
"[data-afterbefore] input, [data-afterbefore] textarea { cursor: text !important; }"
|
|
1917
2216
|
].join("\n");
|
|
1918
|
-
document.head.appendChild(
|
|
1919
|
-
styleEl.current =
|
|
2217
|
+
document.head.appendChild(style2);
|
|
2218
|
+
styleEl.current = style2;
|
|
1920
2219
|
return () => {
|
|
1921
|
-
|
|
2220
|
+
style2.remove();
|
|
1922
2221
|
};
|
|
1923
2222
|
}, []);
|
|
1924
2223
|
const isOverlayElement = useCallback3((el) => {
|
|
@@ -2015,12 +2314,15 @@ async function saveCapture(mode, dataUrl) {
|
|
|
2015
2314
|
}
|
|
2016
2315
|
}
|
|
2017
2316
|
function AfterBefore() {
|
|
2018
|
-
const { state, captureComplete, reset } = useOverlayState();
|
|
2317
|
+
const { state: state2, captureComplete, reset } = useOverlayState();
|
|
2019
2318
|
const [toolbarActive, setToolbarActive] = useState5(false);
|
|
2020
2319
|
const [inspectorActive, setInspectorActive] = useState5(false);
|
|
2021
2320
|
const [loading, setLoading] = useState5(false);
|
|
2022
2321
|
const [selectedMode, setSelectedMode] = useState5("component");
|
|
2023
2322
|
const [frameSettings, setFrameSettings] = useState5(DEFAULT_FRAME_SETTINGS);
|
|
2323
|
+
useEffect4(() => {
|
|
2324
|
+
injectInterFont();
|
|
2325
|
+
}, []);
|
|
2024
2326
|
useEffect4(() => {
|
|
2025
2327
|
try {
|
|
2026
2328
|
const stored = localStorage.getItem("ab-frame-settings");
|
|
@@ -2037,16 +2339,16 @@ function AfterBefore() {
|
|
|
2037
2339
|
}
|
|
2038
2340
|
}, []);
|
|
2039
2341
|
useEffect4(() => {
|
|
2040
|
-
if (
|
|
2342
|
+
if (state2.phase === "ready") {
|
|
2041
2343
|
const timer = setTimeout(() => {
|
|
2042
2344
|
reset();
|
|
2043
2345
|
}, 1500);
|
|
2044
2346
|
return () => clearTimeout(timer);
|
|
2045
2347
|
}
|
|
2046
|
-
}, [
|
|
2348
|
+
}, [state2.phase, reset]);
|
|
2047
2349
|
const handleToggle = useCallback4(() => {
|
|
2048
2350
|
if (loading) return;
|
|
2049
|
-
if (
|
|
2351
|
+
if (state2.phase === "ready") {
|
|
2050
2352
|
reset();
|
|
2051
2353
|
}
|
|
2052
2354
|
if (toolbarActive || inspectorActive) {
|
|
@@ -2061,7 +2363,7 @@ function AfterBefore() {
|
|
|
2061
2363
|
setInspectorActive(false);
|
|
2062
2364
|
}
|
|
2063
2365
|
}
|
|
2064
|
-
}, [
|
|
2366
|
+
}, [state2.phase, loading, toolbarActive, inspectorActive, selectedMode, reset]);
|
|
2065
2367
|
const performCapture = useCallback4(
|
|
2066
2368
|
async (mode, element) => {
|
|
2067
2369
|
setLoading(true);
|
|
@@ -2128,7 +2430,7 @@ function AfterBefore() {
|
|
|
2128
2430
|
{
|
|
2129
2431
|
expanded: toolbarActive,
|
|
2130
2432
|
onToggle: handleToggle,
|
|
2131
|
-
phase:
|
|
2433
|
+
phase: state2.phase,
|
|
2132
2434
|
loading,
|
|
2133
2435
|
selectedMode,
|
|
2134
2436
|
onModeChange: handleModeChange,
|