afterbefore 0.2.14 → 0.2.15
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 +41 -30
- package/dist/{chunk-N33DB2F6.js → chunk-XSDO6N5Q.js} +146 -7
- package/dist/chunk-XSDO6N5Q.js.map +1 -0
- package/dist/overlay/index.js +500 -379
- package/dist/overlay/index.js.map +1 -1
- package/dist/server/middleware.js +9 -1
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/route.d.ts +6 -2
- package/dist/server/route.js +13 -3
- package/dist/server/route.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-N33DB2F6.js.map +0 -1
package/dist/overlay/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/overlay/index.tsx
|
|
4
|
-
import { useState as
|
|
4
|
+
import { useState as useState5, useCallback as useCallback5, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
5
5
|
|
|
6
6
|
// src/overlay/state.ts
|
|
7
7
|
import { useState, useCallback } from "react";
|
|
@@ -336,9 +336,12 @@ function CapturePreview({ mode, onClick }) {
|
|
|
336
336
|
}
|
|
337
337
|
|
|
338
338
|
// src/overlay/ui/toolbar.tsx
|
|
339
|
-
import { useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
|
|
339
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
|
|
340
340
|
import {
|
|
341
|
+
ArrowUp,
|
|
341
342
|
ChevronDown,
|
|
343
|
+
Clock,
|
|
344
|
+
Copy,
|
|
342
345
|
Maximize,
|
|
343
346
|
FolderOpen,
|
|
344
347
|
Frame,
|
|
@@ -366,6 +369,7 @@ function Toolbar({
|
|
|
366
369
|
onFrameSettingsChange
|
|
367
370
|
}) {
|
|
368
371
|
const [settingsOpen, setSettingsOpen] = useState3(false);
|
|
372
|
+
const [historyOpen, setHistoryOpen] = useState3(false);
|
|
369
373
|
useEffect2(() => {
|
|
370
374
|
const onKey = (e) => {
|
|
371
375
|
if (e.target?.tagName === "INPUT") {
|
|
@@ -421,6 +425,7 @@ function Toolbar({
|
|
|
421
425
|
selected: selectedMode === mode,
|
|
422
426
|
onClick: () => {
|
|
423
427
|
setSettingsOpen(false);
|
|
428
|
+
setHistoryOpen(false);
|
|
424
429
|
onModeChange(mode);
|
|
425
430
|
},
|
|
426
431
|
children: /* @__PURE__ */ jsx3(Icon2, { size: 16, strokeWidth: 1.7 })
|
|
@@ -432,11 +437,24 @@ function Toolbar({
|
|
|
432
437
|
SettingsButton,
|
|
433
438
|
{
|
|
434
439
|
open: settingsOpen,
|
|
435
|
-
onClick: () =>
|
|
440
|
+
onClick: () => {
|
|
441
|
+
setSettingsOpen((prev) => !prev);
|
|
442
|
+
setHistoryOpen(false);
|
|
443
|
+
},
|
|
436
444
|
selectedMode,
|
|
437
445
|
frameSettings,
|
|
438
446
|
onFrameSettingsChange
|
|
439
447
|
}
|
|
448
|
+
),
|
|
449
|
+
/* @__PURE__ */ jsx3(
|
|
450
|
+
HistoryButton,
|
|
451
|
+
{
|
|
452
|
+
open: historyOpen,
|
|
453
|
+
onClick: () => {
|
|
454
|
+
setHistoryOpen((prev) => !prev);
|
|
455
|
+
setSettingsOpen(false);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
440
458
|
)
|
|
441
459
|
] })
|
|
442
460
|
}
|
|
@@ -1253,9 +1271,463 @@ function Separator({ vertical = true }) {
|
|
|
1253
1271
|
}
|
|
1254
1272
|
);
|
|
1255
1273
|
}
|
|
1274
|
+
function HistoryButton({
|
|
1275
|
+
open,
|
|
1276
|
+
onClick
|
|
1277
|
+
}) {
|
|
1278
|
+
const [hovered, setHovered] = useState3(false);
|
|
1279
|
+
const [toast, setToast] = useState3(null);
|
|
1280
|
+
const [pushing, setPushing] = useState3(false);
|
|
1281
|
+
const [repos, setRepos] = useState3([]);
|
|
1282
|
+
const [branches, setBranches] = useState3([]);
|
|
1283
|
+
const [screenshots, setScreenshots] = useState3([]);
|
|
1284
|
+
const [selectedRepo, setSelectedRepo] = useState3(null);
|
|
1285
|
+
const [selectedBranch, setSelectedBranch] = useState3(null);
|
|
1286
|
+
const [loading, setLoading] = useState3(false);
|
|
1287
|
+
const [repoDropOpen, setRepoDropOpen] = useState3(false);
|
|
1288
|
+
const [branchDropOpen, setBranchDropOpen] = useState3(false);
|
|
1289
|
+
useEffect2(() => {
|
|
1290
|
+
if (!open) {
|
|
1291
|
+
setRepoDropOpen(false);
|
|
1292
|
+
setBranchDropOpen(false);
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
setLoading(true);
|
|
1296
|
+
const params = new URLSearchParams();
|
|
1297
|
+
if (selectedRepo) params.set("repo", selectedRepo);
|
|
1298
|
+
if (selectedBranch) params.set("branch", selectedBranch);
|
|
1299
|
+
fetch(`/__afterbefore/history?${params}`).then((r) => r.json()).then((data) => {
|
|
1300
|
+
setRepos(data.repos || []);
|
|
1301
|
+
setBranches(data.branches || []);
|
|
1302
|
+
setScreenshots(data.screenshots || []);
|
|
1303
|
+
if (!selectedRepo && data.currentRepo) setSelectedRepo(data.currentRepo);
|
|
1304
|
+
if (!selectedBranch && data.currentBranch) setSelectedBranch(data.currentBranch);
|
|
1305
|
+
}).catch(() => {
|
|
1306
|
+
}).finally(() => setLoading(false));
|
|
1307
|
+
}, [open, selectedRepo, selectedBranch]);
|
|
1308
|
+
const showToast = useCallback3((message, type) => {
|
|
1309
|
+
setToast({ message, type });
|
|
1310
|
+
setTimeout(() => setToast(null), 3e3);
|
|
1311
|
+
}, []);
|
|
1312
|
+
const handleOpenFolder = async () => {
|
|
1313
|
+
try {
|
|
1314
|
+
const res = await fetch("/__afterbefore/open", { method: "POST" });
|
|
1315
|
+
if (!res.ok) throw new Error();
|
|
1316
|
+
showToast("Opened folder", "success");
|
|
1317
|
+
} catch {
|
|
1318
|
+
showToast("Could not open folder", "error");
|
|
1319
|
+
}
|
|
1320
|
+
};
|
|
1321
|
+
const handleCopyMarkdown = async () => {
|
|
1322
|
+
try {
|
|
1323
|
+
const res = await fetch("/__afterbefore/markdown");
|
|
1324
|
+
if (!res.ok) throw new Error();
|
|
1325
|
+
const { markdown } = await res.json();
|
|
1326
|
+
await navigator.clipboard.writeText(markdown);
|
|
1327
|
+
showToast("Copied!", "success");
|
|
1328
|
+
} catch {
|
|
1329
|
+
showToast("Copy failed", "error");
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
const handlePush = async () => {
|
|
1333
|
+
setPushing(true);
|
|
1334
|
+
try {
|
|
1335
|
+
const res = await fetch("/__afterbefore/push", { method: "POST" });
|
|
1336
|
+
const data = await res.json();
|
|
1337
|
+
if (!res.ok) {
|
|
1338
|
+
showToast(data.error || "Push failed", "error");
|
|
1339
|
+
} else if (data.pr) {
|
|
1340
|
+
showToast(`Posted to PR #${data.pr}`, "success");
|
|
1341
|
+
} else {
|
|
1342
|
+
showToast("No PR found", "error");
|
|
1343
|
+
}
|
|
1344
|
+
} catch {
|
|
1345
|
+
showToast("Push failed", "error");
|
|
1346
|
+
} finally {
|
|
1347
|
+
setPushing(false);
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
return /* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
|
|
1351
|
+
hovered && !open && /* @__PURE__ */ jsx3(
|
|
1352
|
+
"div",
|
|
1353
|
+
{
|
|
1354
|
+
style: {
|
|
1355
|
+
position: "absolute",
|
|
1356
|
+
left: "50%",
|
|
1357
|
+
bottom: "calc(100% + 10px)",
|
|
1358
|
+
transform: "translateX(-50%)",
|
|
1359
|
+
background: "rgba(32, 32, 36, 0.96)",
|
|
1360
|
+
backdropFilter: "blur(20px)",
|
|
1361
|
+
WebkitBackdropFilter: "blur(20px)",
|
|
1362
|
+
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
1363
|
+
borderRadius: 8,
|
|
1364
|
+
padding: "5px 10px",
|
|
1365
|
+
color: "rgba(255, 255, 255, 0.88)",
|
|
1366
|
+
fontSize: 12,
|
|
1367
|
+
whiteSpace: "nowrap",
|
|
1368
|
+
boxShadow: "0 8px 28px rgba(0, 0, 0, 0.28)",
|
|
1369
|
+
pointerEvents: "none"
|
|
1370
|
+
},
|
|
1371
|
+
children: "Screenshots"
|
|
1372
|
+
}
|
|
1373
|
+
),
|
|
1374
|
+
/* @__PURE__ */ jsx3(
|
|
1375
|
+
"button",
|
|
1376
|
+
{
|
|
1377
|
+
onClick,
|
|
1378
|
+
onMouseEnter: () => setHovered(true),
|
|
1379
|
+
onMouseLeave: () => setHovered(false),
|
|
1380
|
+
style: {
|
|
1381
|
+
width: 32,
|
|
1382
|
+
height: 32,
|
|
1383
|
+
borderRadius: "50%",
|
|
1384
|
+
border: "none",
|
|
1385
|
+
background: open || hovered ? "rgba(255, 255, 255, 0.12)" : "transparent",
|
|
1386
|
+
display: "flex",
|
|
1387
|
+
alignItems: "center",
|
|
1388
|
+
justifyContent: "center",
|
|
1389
|
+
cursor: "pointer",
|
|
1390
|
+
padding: 0,
|
|
1391
|
+
color: open || hovered ? "rgba(255, 255, 255, 0.96)" : "rgba(255, 255, 255, 0.52)",
|
|
1392
|
+
transition: "background 0.12s ease, color 0.12s ease"
|
|
1393
|
+
},
|
|
1394
|
+
children: /* @__PURE__ */ jsx3(Clock, { size: 16, strokeWidth: 1.7 })
|
|
1395
|
+
}
|
|
1396
|
+
),
|
|
1397
|
+
open && /* @__PURE__ */ jsxs2(
|
|
1398
|
+
"div",
|
|
1399
|
+
{
|
|
1400
|
+
style: {
|
|
1401
|
+
position: "absolute",
|
|
1402
|
+
left: "50%",
|
|
1403
|
+
bottom: "calc(100% + 12px)",
|
|
1404
|
+
transform: "translateX(-50%)",
|
|
1405
|
+
minWidth: 300,
|
|
1406
|
+
maxWidth: 360,
|
|
1407
|
+
padding: "10px 12px",
|
|
1408
|
+
borderRadius: 12,
|
|
1409
|
+
background: "rgba(32, 32, 36, 0.96)",
|
|
1410
|
+
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
1411
|
+
boxShadow: "0 14px 36px rgba(0, 0, 0, 0.32)",
|
|
1412
|
+
backdropFilter: "blur(20px)",
|
|
1413
|
+
WebkitBackdropFilter: "blur(20px)"
|
|
1414
|
+
},
|
|
1415
|
+
children: [
|
|
1416
|
+
/* @__PURE__ */ jsx3(
|
|
1417
|
+
"div",
|
|
1418
|
+
{
|
|
1419
|
+
style: {
|
|
1420
|
+
fontSize: 11,
|
|
1421
|
+
color: "rgba(255, 255, 255, 0.46)",
|
|
1422
|
+
letterSpacing: "0.03em",
|
|
1423
|
+
textTransform: "uppercase",
|
|
1424
|
+
marginBottom: 10
|
|
1425
|
+
},
|
|
1426
|
+
children: "Screenshots"
|
|
1427
|
+
}
|
|
1428
|
+
),
|
|
1429
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: 6, marginBottom: 10 }, children: [
|
|
1430
|
+
/* @__PURE__ */ jsx3(
|
|
1431
|
+
FilterDropdown,
|
|
1432
|
+
{
|
|
1433
|
+
label: "Project",
|
|
1434
|
+
value: selectedRepo,
|
|
1435
|
+
options: repos,
|
|
1436
|
+
isOpen: repoDropOpen,
|
|
1437
|
+
onToggle: () => {
|
|
1438
|
+
setRepoDropOpen((p) => !p);
|
|
1439
|
+
setBranchDropOpen(false);
|
|
1440
|
+
},
|
|
1441
|
+
onSelect: (repo) => {
|
|
1442
|
+
setSelectedRepo(repo);
|
|
1443
|
+
setSelectedBranch(null);
|
|
1444
|
+
setRepoDropOpen(false);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
),
|
|
1448
|
+
/* @__PURE__ */ jsx3(
|
|
1449
|
+
FilterDropdown,
|
|
1450
|
+
{
|
|
1451
|
+
label: "Branch",
|
|
1452
|
+
value: selectedBranch,
|
|
1453
|
+
options: branches,
|
|
1454
|
+
isOpen: branchDropOpen,
|
|
1455
|
+
onToggle: () => {
|
|
1456
|
+
setBranchDropOpen((p) => !p);
|
|
1457
|
+
setRepoDropOpen(false);
|
|
1458
|
+
},
|
|
1459
|
+
onSelect: (branch) => {
|
|
1460
|
+
setSelectedBranch(branch);
|
|
1461
|
+
setBranchDropOpen(false);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
)
|
|
1465
|
+
] }),
|
|
1466
|
+
loading ? /* @__PURE__ */ jsx3(
|
|
1467
|
+
"div",
|
|
1468
|
+
{
|
|
1469
|
+
style: {
|
|
1470
|
+
padding: "12px 0",
|
|
1471
|
+
textAlign: "center",
|
|
1472
|
+
fontSize: 12,
|
|
1473
|
+
color: "rgba(255, 255, 255, 0.35)"
|
|
1474
|
+
},
|
|
1475
|
+
children: "Loading..."
|
|
1476
|
+
}
|
|
1477
|
+
) : screenshots.length === 0 ? /* @__PURE__ */ jsx3(
|
|
1478
|
+
"div",
|
|
1479
|
+
{
|
|
1480
|
+
style: {
|
|
1481
|
+
padding: "12px 0",
|
|
1482
|
+
textAlign: "center",
|
|
1483
|
+
fontSize: 12,
|
|
1484
|
+
color: "rgba(255, 255, 255, 0.35)"
|
|
1485
|
+
},
|
|
1486
|
+
children: "No screenshots yet"
|
|
1487
|
+
}
|
|
1488
|
+
) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1489
|
+
/* @__PURE__ */ jsx3(
|
|
1490
|
+
"div",
|
|
1491
|
+
{
|
|
1492
|
+
style: {
|
|
1493
|
+
maxHeight: 240,
|
|
1494
|
+
overflowY: "auto",
|
|
1495
|
+
display: "flex",
|
|
1496
|
+
flexDirection: "column",
|
|
1497
|
+
gap: 8
|
|
1498
|
+
},
|
|
1499
|
+
children: screenshots.map((shot) => /* @__PURE__ */ jsxs2(
|
|
1500
|
+
"div",
|
|
1501
|
+
{
|
|
1502
|
+
style: {
|
|
1503
|
+
display: "flex",
|
|
1504
|
+
gap: 10,
|
|
1505
|
+
alignItems: "center"
|
|
1506
|
+
},
|
|
1507
|
+
children: [
|
|
1508
|
+
/* @__PURE__ */ jsx3(
|
|
1509
|
+
"img",
|
|
1510
|
+
{
|
|
1511
|
+
src: `/__afterbefore/history/image?repo=${encodeURIComponent(selectedRepo || "")}&branch=${encodeURIComponent(selectedBranch || "")}&file=${encodeURIComponent(shot.filename)}`,
|
|
1512
|
+
alt: "",
|
|
1513
|
+
style: {
|
|
1514
|
+
width: 56,
|
|
1515
|
+
height: 36,
|
|
1516
|
+
borderRadius: 4,
|
|
1517
|
+
objectFit: "cover",
|
|
1518
|
+
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
1519
|
+
flexShrink: 0,
|
|
1520
|
+
background: "rgba(255, 255, 255, 0.05)"
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
),
|
|
1524
|
+
/* @__PURE__ */ jsx3("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx3(
|
|
1525
|
+
"div",
|
|
1526
|
+
{
|
|
1527
|
+
style: {
|
|
1528
|
+
fontSize: 12,
|
|
1529
|
+
color: "rgba(255, 255, 255, 0.88)"
|
|
1530
|
+
},
|
|
1531
|
+
children: formatTimestamp(shot.filename)
|
|
1532
|
+
}
|
|
1533
|
+
) })
|
|
1534
|
+
]
|
|
1535
|
+
},
|
|
1536
|
+
shot.filename
|
|
1537
|
+
))
|
|
1538
|
+
}
|
|
1539
|
+
),
|
|
1540
|
+
/* @__PURE__ */ jsx3(
|
|
1541
|
+
"div",
|
|
1542
|
+
{
|
|
1543
|
+
style: {
|
|
1544
|
+
height: 1,
|
|
1545
|
+
background: "rgba(255, 255, 255, 0.08)",
|
|
1546
|
+
margin: "8px 0"
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
),
|
|
1550
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
1551
|
+
/* @__PURE__ */ jsxs2(ActionButton, { onClick: handleOpenFolder, children: [
|
|
1552
|
+
/* @__PURE__ */ jsx3(FolderOpen, { size: 13, strokeWidth: 1.8 }),
|
|
1553
|
+
"Open Folder"
|
|
1554
|
+
] }),
|
|
1555
|
+
/* @__PURE__ */ jsxs2(ActionButton, { onClick: handleCopyMarkdown, children: [
|
|
1556
|
+
/* @__PURE__ */ jsx3(Copy, { size: 13, strokeWidth: 1.8 }),
|
|
1557
|
+
"Copy Markdown"
|
|
1558
|
+
] }),
|
|
1559
|
+
/* @__PURE__ */ jsxs2(ActionButton, { onClick: handlePush, disabled: pushing, children: [
|
|
1560
|
+
/* @__PURE__ */ jsx3(ArrowUp, { size: 13, strokeWidth: 1.8 }),
|
|
1561
|
+
pushing ? "Pushing..." : "Push to PR"
|
|
1562
|
+
] })
|
|
1563
|
+
] })
|
|
1564
|
+
] }),
|
|
1565
|
+
toast && /* @__PURE__ */ jsx3(
|
|
1566
|
+
"div",
|
|
1567
|
+
{
|
|
1568
|
+
style: {
|
|
1569
|
+
position: "absolute",
|
|
1570
|
+
bottom: "100%",
|
|
1571
|
+
left: "50%",
|
|
1572
|
+
transform: "translateX(-50%)",
|
|
1573
|
+
marginBottom: 8,
|
|
1574
|
+
padding: "6px 12px",
|
|
1575
|
+
borderRadius: 6,
|
|
1576
|
+
fontSize: 12,
|
|
1577
|
+
fontWeight: 500,
|
|
1578
|
+
whiteSpace: "nowrap",
|
|
1579
|
+
color: "white",
|
|
1580
|
+
background: toast.type === "success" ? "rgba(34, 197, 94, 0.9)" : "rgba(239, 68, 68, 0.9)",
|
|
1581
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.3)"
|
|
1582
|
+
},
|
|
1583
|
+
children: toast.message
|
|
1584
|
+
}
|
|
1585
|
+
)
|
|
1586
|
+
]
|
|
1587
|
+
}
|
|
1588
|
+
)
|
|
1589
|
+
] });
|
|
1590
|
+
}
|
|
1591
|
+
function FilterDropdown({
|
|
1592
|
+
label,
|
|
1593
|
+
value,
|
|
1594
|
+
options,
|
|
1595
|
+
isOpen,
|
|
1596
|
+
onToggle,
|
|
1597
|
+
onSelect
|
|
1598
|
+
}) {
|
|
1599
|
+
return /* @__PURE__ */ jsxs2("div", { children: [
|
|
1600
|
+
/* @__PURE__ */ jsx3(
|
|
1601
|
+
"div",
|
|
1602
|
+
{
|
|
1603
|
+
style: {
|
|
1604
|
+
fontSize: 11,
|
|
1605
|
+
color: "rgba(255, 255, 255, 0.42)",
|
|
1606
|
+
letterSpacing: "0.02em",
|
|
1607
|
+
marginBottom: 3
|
|
1608
|
+
},
|
|
1609
|
+
children: label
|
|
1610
|
+
}
|
|
1611
|
+
),
|
|
1612
|
+
/* @__PURE__ */ jsxs2("div", { style: { position: "relative" }, children: [
|
|
1613
|
+
/* @__PURE__ */ jsxs2(
|
|
1614
|
+
"button",
|
|
1615
|
+
{
|
|
1616
|
+
onClick: onToggle,
|
|
1617
|
+
style: {
|
|
1618
|
+
display: "flex",
|
|
1619
|
+
alignItems: "center",
|
|
1620
|
+
justifyContent: "space-between",
|
|
1621
|
+
gap: 6,
|
|
1622
|
+
width: "100%",
|
|
1623
|
+
height: 30,
|
|
1624
|
+
padding: "0 8px",
|
|
1625
|
+
borderRadius: 7,
|
|
1626
|
+
border: "1px solid rgba(255,255,255,0.1)",
|
|
1627
|
+
background: "rgba(255,255,255,0.07)",
|
|
1628
|
+
color: "rgba(255,255,255,0.88)",
|
|
1629
|
+
cursor: "pointer",
|
|
1630
|
+
fontSize: 12,
|
|
1631
|
+
fontFamily: "inherit"
|
|
1632
|
+
},
|
|
1633
|
+
children: [
|
|
1634
|
+
/* @__PURE__ */ jsx3(
|
|
1635
|
+
"span",
|
|
1636
|
+
{
|
|
1637
|
+
style: {
|
|
1638
|
+
overflow: "hidden",
|
|
1639
|
+
textOverflow: "ellipsis",
|
|
1640
|
+
whiteSpace: "nowrap"
|
|
1641
|
+
},
|
|
1642
|
+
children: value || "\u2014"
|
|
1643
|
+
}
|
|
1644
|
+
),
|
|
1645
|
+
/* @__PURE__ */ jsx3(ChevronDown, { size: 12, strokeWidth: 2 })
|
|
1646
|
+
]
|
|
1647
|
+
}
|
|
1648
|
+
),
|
|
1649
|
+
isOpen && options.length > 0 && /* @__PURE__ */ jsx3(
|
|
1650
|
+
"div",
|
|
1651
|
+
{
|
|
1652
|
+
style: {
|
|
1653
|
+
position: "absolute",
|
|
1654
|
+
bottom: "calc(100% + 4px)",
|
|
1655
|
+
left: 0,
|
|
1656
|
+
right: 0,
|
|
1657
|
+
maxHeight: 160,
|
|
1658
|
+
overflowY: "auto",
|
|
1659
|
+
background: "rgba(32, 32, 36, 0.96)",
|
|
1660
|
+
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
1661
|
+
borderRadius: 8,
|
|
1662
|
+
padding: "4px 0",
|
|
1663
|
+
boxShadow: "0 10px 30px rgba(0, 0, 0, 0.3)",
|
|
1664
|
+
backdropFilter: "blur(20px)",
|
|
1665
|
+
WebkitBackdropFilter: "blur(20px)",
|
|
1666
|
+
zIndex: 1
|
|
1667
|
+
},
|
|
1668
|
+
children: options.map((opt) => /* @__PURE__ */ jsx3(
|
|
1669
|
+
DropItem,
|
|
1670
|
+
{
|
|
1671
|
+
active: opt === value,
|
|
1672
|
+
onClick: () => onSelect(opt),
|
|
1673
|
+
children: opt
|
|
1674
|
+
},
|
|
1675
|
+
opt
|
|
1676
|
+
))
|
|
1677
|
+
}
|
|
1678
|
+
)
|
|
1679
|
+
] })
|
|
1680
|
+
] });
|
|
1681
|
+
}
|
|
1682
|
+
function ActionButton({
|
|
1683
|
+
children,
|
|
1684
|
+
onClick,
|
|
1685
|
+
disabled
|
|
1686
|
+
}) {
|
|
1687
|
+
const [hovered, setHovered] = useState3(false);
|
|
1688
|
+
return /* @__PURE__ */ jsx3(
|
|
1689
|
+
"button",
|
|
1690
|
+
{
|
|
1691
|
+
onClick,
|
|
1692
|
+
disabled,
|
|
1693
|
+
onMouseEnter: () => setHovered(true),
|
|
1694
|
+
onMouseLeave: () => setHovered(false),
|
|
1695
|
+
style: {
|
|
1696
|
+
display: "flex",
|
|
1697
|
+
alignItems: "center",
|
|
1698
|
+
gap: 6,
|
|
1699
|
+
width: "100%",
|
|
1700
|
+
padding: "6px 8px",
|
|
1701
|
+
border: "none",
|
|
1702
|
+
background: hovered ? "rgba(255, 255, 255, 0.08)" : "transparent",
|
|
1703
|
+
color: "rgba(255, 255, 255, 0.78)",
|
|
1704
|
+
fontSize: 12,
|
|
1705
|
+
borderRadius: 6,
|
|
1706
|
+
cursor: disabled ? "wait" : "pointer",
|
|
1707
|
+
textAlign: "left",
|
|
1708
|
+
fontFamily: "inherit",
|
|
1709
|
+
transition: "background 0.1s ease"
|
|
1710
|
+
},
|
|
1711
|
+
children
|
|
1712
|
+
}
|
|
1713
|
+
);
|
|
1714
|
+
}
|
|
1715
|
+
function formatTimestamp(filename) {
|
|
1716
|
+
const iso = filename.replace(/\.png$/, "").replace(/T(\d{2})-(\d{2})-(\d{2})-(\d+)Z$/, "T$1:$2:$3.$4Z");
|
|
1717
|
+
const date = new Date(iso);
|
|
1718
|
+
if (Number.isNaN(date.getTime())) return filename.replace(/\.png$/, "");
|
|
1719
|
+
const now = /* @__PURE__ */ new Date();
|
|
1720
|
+
const diffMs = now.getTime() - date.getTime();
|
|
1721
|
+
const diffMin = Math.floor(diffMs / 6e4);
|
|
1722
|
+
if (diffMin < 1) return "Just now";
|
|
1723
|
+
if (diffMin < 60) return `${diffMin}m ago`;
|
|
1724
|
+
const diffHr = Math.floor(diffMin / 60);
|
|
1725
|
+
if (diffHr < 24) return `${diffHr}h ago`;
|
|
1726
|
+
return date.toLocaleDateString(void 0, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
|
|
1727
|
+
}
|
|
1256
1728
|
|
|
1257
1729
|
// src/overlay/ui/inspector.tsx
|
|
1258
|
-
import { useEffect as useEffect3, useRef as useRef3, useCallback as
|
|
1730
|
+
import { useEffect as useEffect3, useRef as useRef3, useCallback as useCallback4, useState as useState4 } from "react";
|
|
1259
1731
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1260
1732
|
function Inspector({ onSelect, onCancel }) {
|
|
1261
1733
|
const [highlight, setHighlight] = useState4(null);
|
|
@@ -1264,14 +1736,14 @@ function Inspector({ onSelect, onCancel }) {
|
|
|
1264
1736
|
useEffect3(() => {
|
|
1265
1737
|
const style = document.createElement("style");
|
|
1266
1738
|
style.setAttribute("data-afterbefore", "true");
|
|
1267
|
-
style.textContent = "
|
|
1739
|
+
style.textContent = ":not([data-afterbefore]):not([data-afterbefore] *) { cursor: crosshair !important; }";
|
|
1268
1740
|
document.head.appendChild(style);
|
|
1269
1741
|
styleEl.current = style;
|
|
1270
1742
|
return () => {
|
|
1271
1743
|
style.remove();
|
|
1272
1744
|
};
|
|
1273
1745
|
}, []);
|
|
1274
|
-
const isOverlayElement =
|
|
1746
|
+
const isOverlayElement = useCallback4((el) => {
|
|
1275
1747
|
let node = el;
|
|
1276
1748
|
while (node) {
|
|
1277
1749
|
if (node instanceof HTMLElement && node.dataset.afterbefore) return true;
|
|
@@ -1279,7 +1751,7 @@ function Inspector({ onSelect, onCancel }) {
|
|
|
1279
1751
|
}
|
|
1280
1752
|
return false;
|
|
1281
1753
|
}, []);
|
|
1282
|
-
const handleMouseMove =
|
|
1754
|
+
const handleMouseMove = useCallback4(
|
|
1283
1755
|
(e) => {
|
|
1284
1756
|
const el = document.elementFromPoint(e.clientX, e.clientY);
|
|
1285
1757
|
if (!el || !(el instanceof HTMLElement) || isOverlayElement(el)) {
|
|
@@ -1299,7 +1771,7 @@ function Inspector({ onSelect, onCancel }) {
|
|
|
1299
1771
|
},
|
|
1300
1772
|
[isOverlayElement]
|
|
1301
1773
|
);
|
|
1302
|
-
const handleClick =
|
|
1774
|
+
const handleClick = useCallback4(
|
|
1303
1775
|
(e) => {
|
|
1304
1776
|
if (isOverlayElement(e.target)) return;
|
|
1305
1777
|
e.preventDefault();
|
|
@@ -1311,7 +1783,7 @@ function Inspector({ onSelect, onCancel }) {
|
|
|
1311
1783
|
},
|
|
1312
1784
|
[onSelect, isOverlayElement]
|
|
1313
1785
|
);
|
|
1314
|
-
const handleKeyDown =
|
|
1786
|
+
const handleKeyDown = useCallback4(
|
|
1315
1787
|
(e) => {
|
|
1316
1788
|
if (e.key === "Escape") {
|
|
1317
1789
|
onCancel();
|
|
@@ -1369,339 +1841,8 @@ function Inspector({ onSelect, onCancel }) {
|
|
|
1369
1841
|
] }) });
|
|
1370
1842
|
}
|
|
1371
1843
|
|
|
1372
|
-
// src/overlay/ui/status.tsx
|
|
1373
|
-
import { useState as useState5, useRef as useRef4, useEffect as useEffect4, useCallback as useCallback4 } from "react";
|
|
1374
|
-
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1375
|
-
var PANEL_WIDTH = 220;
|
|
1376
|
-
function Status({ onReset, position, onClose }) {
|
|
1377
|
-
const panelRef = useRef4(null);
|
|
1378
|
-
const [toast, setToast] = useState5(null);
|
|
1379
|
-
const [pushing, setPushing] = useState5(false);
|
|
1380
|
-
const showToast = useCallback4((message, type) => {
|
|
1381
|
-
setToast({ message, type });
|
|
1382
|
-
setTimeout(() => setToast(null), 3e3);
|
|
1383
|
-
}, []);
|
|
1384
|
-
useEffect4(() => {
|
|
1385
|
-
const handler = (e) => {
|
|
1386
|
-
if (panelRef.current && !panelRef.current.contains(e.target)) {
|
|
1387
|
-
onClose();
|
|
1388
|
-
}
|
|
1389
|
-
};
|
|
1390
|
-
document.addEventListener("mousedown", handler);
|
|
1391
|
-
return () => document.removeEventListener("mousedown", handler);
|
|
1392
|
-
}, [onClose]);
|
|
1393
|
-
useEffect4(() => {
|
|
1394
|
-
const handler = (e) => {
|
|
1395
|
-
if (e.key === "Escape") onClose();
|
|
1396
|
-
};
|
|
1397
|
-
document.addEventListener("keydown", handler);
|
|
1398
|
-
return () => document.removeEventListener("keydown", handler);
|
|
1399
|
-
}, [onClose]);
|
|
1400
|
-
const handleOpenFolder = async () => {
|
|
1401
|
-
try {
|
|
1402
|
-
const res = await fetch("/__afterbefore/open", { method: "POST" });
|
|
1403
|
-
if (!res.ok) throw new Error();
|
|
1404
|
-
showToast("Opened folder", "success");
|
|
1405
|
-
} catch {
|
|
1406
|
-
showToast("Could not open folder", "error");
|
|
1407
|
-
}
|
|
1408
|
-
};
|
|
1409
|
-
const handleCopyMarkdown = async () => {
|
|
1410
|
-
try {
|
|
1411
|
-
const res = await fetch("/__afterbefore/markdown");
|
|
1412
|
-
if (!res.ok) throw new Error();
|
|
1413
|
-
const { markdown } = await res.json();
|
|
1414
|
-
await navigator.clipboard.writeText(markdown);
|
|
1415
|
-
showToast("Copied!", "success");
|
|
1416
|
-
} catch {
|
|
1417
|
-
showToast("Copy failed", "error");
|
|
1418
|
-
}
|
|
1419
|
-
};
|
|
1420
|
-
const handlePush = async () => {
|
|
1421
|
-
setPushing(true);
|
|
1422
|
-
try {
|
|
1423
|
-
const res = await fetch("/__afterbefore/push", { method: "POST" });
|
|
1424
|
-
const data = await res.json();
|
|
1425
|
-
if (!res.ok) {
|
|
1426
|
-
showToast(data.error || "Push failed", "error");
|
|
1427
|
-
} else if (data.pr) {
|
|
1428
|
-
showToast(`Posted to PR #${data.pr}`, "success");
|
|
1429
|
-
} else {
|
|
1430
|
-
showToast("No PR found", "error");
|
|
1431
|
-
}
|
|
1432
|
-
} catch {
|
|
1433
|
-
showToast("Push failed", "error");
|
|
1434
|
-
} finally {
|
|
1435
|
-
setPushing(false);
|
|
1436
|
-
}
|
|
1437
|
-
};
|
|
1438
|
-
const handleReset = () => {
|
|
1439
|
-
onReset();
|
|
1440
|
-
onClose();
|
|
1441
|
-
};
|
|
1442
|
-
const panelLeft = Math.max(
|
|
1443
|
-
8,
|
|
1444
|
-
Math.min(position.x - PANEL_WIDTH / 2 + 20, window.innerWidth - PANEL_WIDTH - 8)
|
|
1445
|
-
);
|
|
1446
|
-
const panelBottom = window.innerHeight - position.y + 8;
|
|
1447
|
-
const buttonStyle = {
|
|
1448
|
-
display: "flex",
|
|
1449
|
-
alignItems: "center",
|
|
1450
|
-
gap: 6,
|
|
1451
|
-
width: "100%",
|
|
1452
|
-
padding: "7px 10px",
|
|
1453
|
-
border: "none",
|
|
1454
|
-
background: "transparent",
|
|
1455
|
-
color: "rgba(255,255,255,0.9)",
|
|
1456
|
-
fontSize: 13,
|
|
1457
|
-
borderRadius: 6,
|
|
1458
|
-
cursor: "pointer",
|
|
1459
|
-
textAlign: "left",
|
|
1460
|
-
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
1461
|
-
transition: "background 0.1s"
|
|
1462
|
-
};
|
|
1463
|
-
const onEnter = (e) => {
|
|
1464
|
-
e.currentTarget.style.background = "rgba(255,255,255,0.1)";
|
|
1465
|
-
};
|
|
1466
|
-
const onLeave = (e) => {
|
|
1467
|
-
e.currentTarget.style.background = "transparent";
|
|
1468
|
-
};
|
|
1469
|
-
return /* @__PURE__ */ jsxs4(
|
|
1470
|
-
"div",
|
|
1471
|
-
{
|
|
1472
|
-
ref: panelRef,
|
|
1473
|
-
"data-afterbefore": "true",
|
|
1474
|
-
style: {
|
|
1475
|
-
position: "fixed",
|
|
1476
|
-
left: panelLeft,
|
|
1477
|
-
bottom: panelBottom,
|
|
1478
|
-
width: PANEL_WIDTH,
|
|
1479
|
-
background: "rgba(24, 24, 27, 0.95)",
|
|
1480
|
-
borderRadius: 10,
|
|
1481
|
-
boxShadow: "0 4px 20px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.08)",
|
|
1482
|
-
zIndex: 2147483647,
|
|
1483
|
-
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
1484
|
-
backdropFilter: "blur(12px)",
|
|
1485
|
-
overflow: "hidden"
|
|
1486
|
-
},
|
|
1487
|
-
children: [
|
|
1488
|
-
/* @__PURE__ */ jsx5(
|
|
1489
|
-
"div",
|
|
1490
|
-
{
|
|
1491
|
-
style: {
|
|
1492
|
-
padding: "10px 12px 6px",
|
|
1493
|
-
fontSize: 12,
|
|
1494
|
-
fontWeight: 600,
|
|
1495
|
-
color: "rgba(255,255,255,0.5)",
|
|
1496
|
-
letterSpacing: "0.02em"
|
|
1497
|
-
},
|
|
1498
|
-
children: "Screenshot captured"
|
|
1499
|
-
}
|
|
1500
|
-
),
|
|
1501
|
-
/* @__PURE__ */ jsxs4("div", { style: { padding: "0 4px 4px" }, children: [
|
|
1502
|
-
/* @__PURE__ */ jsxs4(
|
|
1503
|
-
"button",
|
|
1504
|
-
{
|
|
1505
|
-
style: buttonStyle,
|
|
1506
|
-
onClick: handleOpenFolder,
|
|
1507
|
-
onMouseEnter: onEnter,
|
|
1508
|
-
onMouseLeave: onLeave,
|
|
1509
|
-
children: [
|
|
1510
|
-
/* @__PURE__ */ jsx5(FolderIcon, {}),
|
|
1511
|
-
"Open Folder"
|
|
1512
|
-
]
|
|
1513
|
-
}
|
|
1514
|
-
),
|
|
1515
|
-
/* @__PURE__ */ jsxs4(
|
|
1516
|
-
"button",
|
|
1517
|
-
{
|
|
1518
|
-
style: buttonStyle,
|
|
1519
|
-
onClick: handleCopyMarkdown,
|
|
1520
|
-
onMouseEnter: onEnter,
|
|
1521
|
-
onMouseLeave: onLeave,
|
|
1522
|
-
children: [
|
|
1523
|
-
/* @__PURE__ */ jsx5(CopyIcon, {}),
|
|
1524
|
-
"Copy Markdown"
|
|
1525
|
-
]
|
|
1526
|
-
}
|
|
1527
|
-
),
|
|
1528
|
-
/* @__PURE__ */ jsxs4(
|
|
1529
|
-
"button",
|
|
1530
|
-
{
|
|
1531
|
-
style: buttonStyle,
|
|
1532
|
-
onClick: handlePush,
|
|
1533
|
-
disabled: pushing,
|
|
1534
|
-
onMouseEnter: onEnter,
|
|
1535
|
-
onMouseLeave: onLeave,
|
|
1536
|
-
children: [
|
|
1537
|
-
/* @__PURE__ */ jsx5(PushIcon, {}),
|
|
1538
|
-
pushing ? "Pushing..." : "Push to PR"
|
|
1539
|
-
]
|
|
1540
|
-
}
|
|
1541
|
-
),
|
|
1542
|
-
/* @__PURE__ */ jsx5(
|
|
1543
|
-
"div",
|
|
1544
|
-
{
|
|
1545
|
-
style: {
|
|
1546
|
-
height: 1,
|
|
1547
|
-
background: "rgba(255,255,255,0.08)",
|
|
1548
|
-
margin: "4px 6px"
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
),
|
|
1552
|
-
/* @__PURE__ */ jsxs4(
|
|
1553
|
-
"button",
|
|
1554
|
-
{
|
|
1555
|
-
style: { ...buttonStyle, color: "rgba(255,255,255,0.5)" },
|
|
1556
|
-
onClick: handleReset,
|
|
1557
|
-
onMouseEnter: onEnter,
|
|
1558
|
-
onMouseLeave: onLeave,
|
|
1559
|
-
children: [
|
|
1560
|
-
/* @__PURE__ */ jsx5(ResetIcon, {}),
|
|
1561
|
-
"Reset"
|
|
1562
|
-
]
|
|
1563
|
-
}
|
|
1564
|
-
)
|
|
1565
|
-
] }),
|
|
1566
|
-
toast && /* @__PURE__ */ jsx5(
|
|
1567
|
-
"div",
|
|
1568
|
-
{
|
|
1569
|
-
style: {
|
|
1570
|
-
position: "absolute",
|
|
1571
|
-
bottom: "100%",
|
|
1572
|
-
left: "50%",
|
|
1573
|
-
transform: "translateX(-50%)",
|
|
1574
|
-
marginBottom: 8,
|
|
1575
|
-
padding: "6px 12px",
|
|
1576
|
-
borderRadius: 6,
|
|
1577
|
-
fontSize: 12,
|
|
1578
|
-
fontWeight: 500,
|
|
1579
|
-
whiteSpace: "nowrap",
|
|
1580
|
-
color: "white",
|
|
1581
|
-
background: toast.type === "success" ? "rgba(34, 197, 94, 0.9)" : "rgba(239, 68, 68, 0.9)",
|
|
1582
|
-
boxShadow: "0 2px 8px rgba(0,0,0,0.3)"
|
|
1583
|
-
},
|
|
1584
|
-
children: toast.message
|
|
1585
|
-
}
|
|
1586
|
-
)
|
|
1587
|
-
]
|
|
1588
|
-
}
|
|
1589
|
-
);
|
|
1590
|
-
}
|
|
1591
|
-
function FolderIcon() {
|
|
1592
|
-
return /* @__PURE__ */ jsx5(
|
|
1593
|
-
"svg",
|
|
1594
|
-
{
|
|
1595
|
-
width: "14",
|
|
1596
|
-
height: "14",
|
|
1597
|
-
viewBox: "0 0 14 14",
|
|
1598
|
-
style: { color: "rgba(255,255,255,0.5)" },
|
|
1599
|
-
children: /* @__PURE__ */ jsx5(
|
|
1600
|
-
"path",
|
|
1601
|
-
{
|
|
1602
|
-
d: "M1.5 3A1.5 1.5 0 013 1.5h2.38a1 1 0 01.72.3L7 2.72a1 1 0 00.72.3H11A1.5 1.5 0 0112.5 4.5v6A1.5 1.5 0 0111 12H3A1.5 1.5 0 011.5 10.5V3z",
|
|
1603
|
-
fill: "none",
|
|
1604
|
-
stroke: "currentColor",
|
|
1605
|
-
strokeWidth: "1.3"
|
|
1606
|
-
}
|
|
1607
|
-
)
|
|
1608
|
-
}
|
|
1609
|
-
);
|
|
1610
|
-
}
|
|
1611
|
-
function CopyIcon() {
|
|
1612
|
-
return /* @__PURE__ */ jsxs4(
|
|
1613
|
-
"svg",
|
|
1614
|
-
{
|
|
1615
|
-
width: "14",
|
|
1616
|
-
height: "14",
|
|
1617
|
-
viewBox: "0 0 14 14",
|
|
1618
|
-
style: { color: "rgba(255,255,255,0.5)" },
|
|
1619
|
-
children: [
|
|
1620
|
-
/* @__PURE__ */ jsx5(
|
|
1621
|
-
"rect",
|
|
1622
|
-
{
|
|
1623
|
-
x: "4",
|
|
1624
|
-
y: "4",
|
|
1625
|
-
width: "8.5",
|
|
1626
|
-
height: "8.5",
|
|
1627
|
-
rx: "1.5",
|
|
1628
|
-
fill: "none",
|
|
1629
|
-
stroke: "currentColor",
|
|
1630
|
-
strokeWidth: "1.3"
|
|
1631
|
-
}
|
|
1632
|
-
),
|
|
1633
|
-
/* @__PURE__ */ jsx5(
|
|
1634
|
-
"path",
|
|
1635
|
-
{
|
|
1636
|
-
d: "M10 4V2.5A1.5 1.5 0 008.5 1h-6A1.5 1.5 0 001 2.5v6A1.5 1.5 0 002.5 10H4",
|
|
1637
|
-
fill: "none",
|
|
1638
|
-
stroke: "currentColor",
|
|
1639
|
-
strokeWidth: "1.3"
|
|
1640
|
-
}
|
|
1641
|
-
)
|
|
1642
|
-
]
|
|
1643
|
-
}
|
|
1644
|
-
);
|
|
1645
|
-
}
|
|
1646
|
-
function PushIcon() {
|
|
1647
|
-
return /* @__PURE__ */ jsx5(
|
|
1648
|
-
"svg",
|
|
1649
|
-
{
|
|
1650
|
-
width: "14",
|
|
1651
|
-
height: "14",
|
|
1652
|
-
viewBox: "0 0 14 14",
|
|
1653
|
-
style: { color: "rgba(255,255,255,0.5)" },
|
|
1654
|
-
children: /* @__PURE__ */ jsx5(
|
|
1655
|
-
"path",
|
|
1656
|
-
{
|
|
1657
|
-
d: "M7 11V3m0 0L4 6m3-3l3 3",
|
|
1658
|
-
fill: "none",
|
|
1659
|
-
stroke: "currentColor",
|
|
1660
|
-
strokeWidth: "1.3",
|
|
1661
|
-
strokeLinecap: "round",
|
|
1662
|
-
strokeLinejoin: "round"
|
|
1663
|
-
}
|
|
1664
|
-
)
|
|
1665
|
-
}
|
|
1666
|
-
);
|
|
1667
|
-
}
|
|
1668
|
-
function ResetIcon() {
|
|
1669
|
-
return /* @__PURE__ */ jsxs4(
|
|
1670
|
-
"svg",
|
|
1671
|
-
{
|
|
1672
|
-
width: "14",
|
|
1673
|
-
height: "14",
|
|
1674
|
-
viewBox: "0 0 14 14",
|
|
1675
|
-
style: { color: "rgba(255,255,255,0.4)" },
|
|
1676
|
-
children: [
|
|
1677
|
-
/* @__PURE__ */ jsx5(
|
|
1678
|
-
"path",
|
|
1679
|
-
{
|
|
1680
|
-
d: "M2.5 7a4.5 4.5 0 118 2.5",
|
|
1681
|
-
fill: "none",
|
|
1682
|
-
stroke: "currentColor",
|
|
1683
|
-
strokeWidth: "1.3",
|
|
1684
|
-
strokeLinecap: "round"
|
|
1685
|
-
}
|
|
1686
|
-
),
|
|
1687
|
-
/* @__PURE__ */ jsx5(
|
|
1688
|
-
"path",
|
|
1689
|
-
{
|
|
1690
|
-
d: "M2.5 3v4h4",
|
|
1691
|
-
fill: "none",
|
|
1692
|
-
stroke: "currentColor",
|
|
1693
|
-
strokeWidth: "1.3",
|
|
1694
|
-
strokeLinecap: "round",
|
|
1695
|
-
strokeLinejoin: "round"
|
|
1696
|
-
}
|
|
1697
|
-
)
|
|
1698
|
-
]
|
|
1699
|
-
}
|
|
1700
|
-
);
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
1844
|
// src/overlay/index.tsx
|
|
1704
|
-
import { jsx as
|
|
1845
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1705
1846
|
async function saveCapture(mode, dataUrl) {
|
|
1706
1847
|
try {
|
|
1707
1848
|
const res = await fetch("/__afterbefore/save", {
|
|
@@ -1719,14 +1860,13 @@ async function saveCapture(mode, dataUrl) {
|
|
|
1719
1860
|
}
|
|
1720
1861
|
function AfterBefore() {
|
|
1721
1862
|
const { state, captureComplete, reset } = useOverlayState();
|
|
1722
|
-
const [
|
|
1723
|
-
const [
|
|
1724
|
-
const [
|
|
1725
|
-
const [
|
|
1726
|
-
const [
|
|
1727
|
-
const
|
|
1728
|
-
|
|
1729
|
-
useEffect5(() => {
|
|
1863
|
+
const [toolbarActive, setToolbarActive] = useState5(false);
|
|
1864
|
+
const [inspectorActive, setInspectorActive] = useState5(false);
|
|
1865
|
+
const [loading, setLoading] = useState5(false);
|
|
1866
|
+
const [selectedMode, setSelectedMode] = useState5("component");
|
|
1867
|
+
const [frameSettings, setFrameSettings] = useState5(DEFAULT_FRAME_SETTINGS);
|
|
1868
|
+
const iconPos = useRef4({ x: 24, y: 0 });
|
|
1869
|
+
useEffect4(() => {
|
|
1730
1870
|
try {
|
|
1731
1871
|
const stored = localStorage.getItem("ab-frame-settings");
|
|
1732
1872
|
if (stored) {
|
|
@@ -1741,11 +1881,10 @@ function AfterBefore() {
|
|
|
1741
1881
|
setFrameSettings(DEFAULT_FRAME_SETTINGS);
|
|
1742
1882
|
}
|
|
1743
1883
|
}, []);
|
|
1744
|
-
|
|
1884
|
+
useEffect4(() => {
|
|
1745
1885
|
if (state.phase === "ready") {
|
|
1746
1886
|
const timer = setTimeout(() => {
|
|
1747
1887
|
reset();
|
|
1748
|
-
setStatusOpen(false);
|
|
1749
1888
|
}, 1500);
|
|
1750
1889
|
return () => clearTimeout(timer);
|
|
1751
1890
|
}
|
|
@@ -1759,13 +1898,12 @@ function AfterBefore() {
|
|
|
1759
1898
|
const handleIconClick = useCallback5(() => {
|
|
1760
1899
|
if (loading) return;
|
|
1761
1900
|
if (state.phase === "ready") {
|
|
1762
|
-
|
|
1763
|
-
}
|
|
1901
|
+
reset();
|
|
1902
|
+
}
|
|
1903
|
+
if (toolbarActive || inspectorActive) {
|
|
1764
1904
|
setToolbarActive(false);
|
|
1765
1905
|
setInspectorActive(false);
|
|
1766
|
-
setStatusOpen(false);
|
|
1767
1906
|
} else {
|
|
1768
|
-
setStatusOpen(false);
|
|
1769
1907
|
if (selectedMode === "component") {
|
|
1770
1908
|
setToolbarActive(true);
|
|
1771
1909
|
setInspectorActive(true);
|
|
@@ -1774,7 +1912,7 @@ function AfterBefore() {
|
|
|
1774
1912
|
setInspectorActive(false);
|
|
1775
1913
|
}
|
|
1776
1914
|
}
|
|
1777
|
-
}, [state.phase, loading, toolbarActive, inspectorActive, selectedMode]);
|
|
1915
|
+
}, [state.phase, loading, toolbarActive, inspectorActive, selectedMode, reset]);
|
|
1778
1916
|
const performCapture = useCallback5(
|
|
1779
1917
|
async (mode, element) => {
|
|
1780
1918
|
setLoading(true);
|
|
@@ -1832,19 +1970,10 @@ function AfterBefore() {
|
|
|
1832
1970
|
}, []);
|
|
1833
1971
|
const handleModeChange = useCallback5((mode) => {
|
|
1834
1972
|
setSelectedMode(mode);
|
|
1835
|
-
|
|
1836
|
-
setInspectorActive(true);
|
|
1837
|
-
}
|
|
1838
|
-
}, []);
|
|
1839
|
-
const handleReset = useCallback5(() => {
|
|
1840
|
-
reset();
|
|
1841
|
-
setStatusOpen(false);
|
|
1842
|
-
}, [reset]);
|
|
1843
|
-
const handleStatusClose = useCallback5(() => {
|
|
1844
|
-
setStatusOpen(false);
|
|
1973
|
+
setInspectorActive(mode === "component");
|
|
1845
1974
|
}, []);
|
|
1846
|
-
return /* @__PURE__ */
|
|
1847
|
-
/* @__PURE__ */
|
|
1975
|
+
return /* @__PURE__ */ jsxs4("div", { "data-afterbefore": "true", children: [
|
|
1976
|
+
/* @__PURE__ */ jsx5(
|
|
1848
1977
|
Icon,
|
|
1849
1978
|
{
|
|
1850
1979
|
phase: state.phase,
|
|
@@ -1853,14 +1982,14 @@ function AfterBefore() {
|
|
|
1853
1982
|
onPositionChange: handlePositionChange
|
|
1854
1983
|
}
|
|
1855
1984
|
),
|
|
1856
|
-
toolbarActive && !inspectorActive && !loading && /* @__PURE__ */
|
|
1985
|
+
toolbarActive && !inspectorActive && !loading && /* @__PURE__ */ jsx5(
|
|
1857
1986
|
CapturePreview,
|
|
1858
1987
|
{
|
|
1859
1988
|
mode: selectedMode,
|
|
1860
1989
|
onClick: () => handleToolbarCapture(selectedMode)
|
|
1861
1990
|
}
|
|
1862
1991
|
),
|
|
1863
|
-
toolbarActive && /* @__PURE__ */
|
|
1992
|
+
toolbarActive && /* @__PURE__ */ jsx5(
|
|
1864
1993
|
Toolbar,
|
|
1865
1994
|
{
|
|
1866
1995
|
selectedMode,
|
|
@@ -1871,15 +2000,7 @@ function AfterBefore() {
|
|
|
1871
2000
|
onFrameSettingsChange: handleFrameSettingsChange
|
|
1872
2001
|
}
|
|
1873
2002
|
),
|
|
1874
|
-
inspectorActive && /* @__PURE__ */
|
|
1875
|
-
statusOpen && state.phase === "ready" && /* @__PURE__ */ jsx6(
|
|
1876
|
-
Status,
|
|
1877
|
-
{
|
|
1878
|
-
onReset: handleReset,
|
|
1879
|
-
position: iconPos.current,
|
|
1880
|
-
onClose: handleStatusClose
|
|
1881
|
-
}
|
|
1882
|
-
)
|
|
2003
|
+
inspectorActive && /* @__PURE__ */ jsx5(Inspector, { onSelect: handleComponentSelect, onCancel: handleComponentCancel })
|
|
1883
2004
|
] });
|
|
1884
2005
|
}
|
|
1885
2006
|
export {
|