next-ai-editor 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -77
- package/dist/index.cjs +537 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +50 -0
- package/dist/index.js +538 -20
- package/dist/index.js.map +1 -1
- package/dist/next-ai-editor.css +707 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1364,7 +1364,7 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
1364
1364
|
* This source code is licensed under the ISC license.
|
|
1365
1365
|
* See the LICENSE file in the root directory of this source tree.
|
|
1366
1366
|
*/
|
|
1367
|
-
const __iconNode$
|
|
1367
|
+
const __iconNode$a = [
|
|
1368
1368
|
[
|
|
1369
1369
|
"path",
|
|
1370
1370
|
{
|
|
@@ -1375,14 +1375,22 @@ const __iconNode$4 = [
|
|
|
1375
1375
|
["path", { d: "m3.3 7 8.7 5 8.7-5", key: "g66t2b" }],
|
|
1376
1376
|
["path", { d: "M12 22V12", key: "d0xqtd" }]
|
|
1377
1377
|
];
|
|
1378
|
-
const Box = createLucideIcon("box", __iconNode$
|
|
1378
|
+
const Box = createLucideIcon("box", __iconNode$a);
|
|
1379
1379
|
/**
|
|
1380
1380
|
* @license lucide-react v0.562.0 - ISC
|
|
1381
1381
|
*
|
|
1382
1382
|
* This source code is licensed under the ISC license.
|
|
1383
1383
|
* See the LICENSE file in the root directory of this source tree.
|
|
1384
1384
|
*/
|
|
1385
|
-
const __iconNode$
|
|
1385
|
+
const __iconNode$9 = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
|
|
1386
|
+
const Check = createLucideIcon("check", __iconNode$9);
|
|
1387
|
+
/**
|
|
1388
|
+
* @license lucide-react v0.562.0 - ISC
|
|
1389
|
+
*
|
|
1390
|
+
* This source code is licensed under the ISC license.
|
|
1391
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1392
|
+
*/
|
|
1393
|
+
const __iconNode$8 = [
|
|
1386
1394
|
[
|
|
1387
1395
|
"path",
|
|
1388
1396
|
{
|
|
@@ -1394,14 +1402,68 @@ const __iconNode$3 = [
|
|
|
1394
1402
|
["path", { d: "M10 12.5 8 15l2 2.5", key: "1tg20x" }],
|
|
1395
1403
|
["path", { d: "m14 12.5 2 2.5-2 2.5", key: "yinavb" }]
|
|
1396
1404
|
];
|
|
1397
|
-
const FileCode = createLucideIcon("file-code", __iconNode$
|
|
1405
|
+
const FileCode = createLucideIcon("file-code", __iconNode$8);
|
|
1398
1406
|
/**
|
|
1399
1407
|
* @license lucide-react v0.562.0 - ISC
|
|
1400
1408
|
*
|
|
1401
1409
|
* This source code is licensed under the ISC license.
|
|
1402
1410
|
* See the LICENSE file in the root directory of this source tree.
|
|
1403
1411
|
*/
|
|
1404
|
-
const __iconNode$
|
|
1412
|
+
const __iconNode$7 = [
|
|
1413
|
+
[
|
|
1414
|
+
"path",
|
|
1415
|
+
{
|
|
1416
|
+
d: "M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",
|
|
1417
|
+
key: "1oefj6"
|
|
1418
|
+
}
|
|
1419
|
+
],
|
|
1420
|
+
["path", { d: "M14 2v5a1 1 0 0 0 1 1h5", key: "wfsgrz" }],
|
|
1421
|
+
["path", { d: "M10 9H8", key: "b1mrlr" }],
|
|
1422
|
+
["path", { d: "M16 13H8", key: "t4e002" }],
|
|
1423
|
+
["path", { d: "M16 17H8", key: "z1uh3a" }]
|
|
1424
|
+
];
|
|
1425
|
+
const FileText = createLucideIcon("file-text", __iconNode$7);
|
|
1426
|
+
/**
|
|
1427
|
+
* @license lucide-react v0.562.0 - ISC
|
|
1428
|
+
*
|
|
1429
|
+
* This source code is licensed under the ISC license.
|
|
1430
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1431
|
+
*/
|
|
1432
|
+
const __iconNode$6 = [
|
|
1433
|
+
["line", { x1: "6", x2: "6", y1: "3", y2: "15", key: "17qcm7" }],
|
|
1434
|
+
["circle", { cx: "18", cy: "6", r: "3", key: "1h7g24" }],
|
|
1435
|
+
["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
|
|
1436
|
+
["path", { d: "M18 9a9 9 0 0 1-9 9", key: "n2h4wq" }]
|
|
1437
|
+
];
|
|
1438
|
+
const GitBranch = createLucideIcon("git-branch", __iconNode$6);
|
|
1439
|
+
/**
|
|
1440
|
+
* @license lucide-react v0.562.0 - ISC
|
|
1441
|
+
*
|
|
1442
|
+
* This source code is licensed under the ISC license.
|
|
1443
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1444
|
+
*/
|
|
1445
|
+
const __iconNode$5 = [
|
|
1446
|
+
["circle", { cx: "18", cy: "18", r: "3", key: "1xkwt0" }],
|
|
1447
|
+
["circle", { cx: "6", cy: "6", r: "3", key: "1lh9wr" }],
|
|
1448
|
+
["path", { d: "M13 6h3a2 2 0 0 1 2 2v7", key: "1yeb86" }],
|
|
1449
|
+
["line", { x1: "6", x2: "6", y1: "9", y2: "21", key: "rroup" }]
|
|
1450
|
+
];
|
|
1451
|
+
const GitPullRequest = createLucideIcon("git-pull-request", __iconNode$5);
|
|
1452
|
+
/**
|
|
1453
|
+
* @license lucide-react v0.562.0 - ISC
|
|
1454
|
+
*
|
|
1455
|
+
* This source code is licensed under the ISC license.
|
|
1456
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1457
|
+
*/
|
|
1458
|
+
const __iconNode$4 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
|
|
1459
|
+
const LoaderCircle = createLucideIcon("loader-circle", __iconNode$4);
|
|
1460
|
+
/**
|
|
1461
|
+
* @license lucide-react v0.562.0 - ISC
|
|
1462
|
+
*
|
|
1463
|
+
* This source code is licensed under the ISC license.
|
|
1464
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1465
|
+
*/
|
|
1466
|
+
const __iconNode$3 = [
|
|
1405
1467
|
[
|
|
1406
1468
|
"path",
|
|
1407
1469
|
{
|
|
@@ -1411,7 +1473,26 @@ const __iconNode$2 = [
|
|
|
1411
1473
|
],
|
|
1412
1474
|
["path", { d: "m15 5 4 4", key: "1mk7zo" }]
|
|
1413
1475
|
];
|
|
1414
|
-
const Pencil = createLucideIcon("pencil", __iconNode$
|
|
1476
|
+
const Pencil = createLucideIcon("pencil", __iconNode$3);
|
|
1477
|
+
/**
|
|
1478
|
+
* @license lucide-react v0.562.0 - ISC
|
|
1479
|
+
*
|
|
1480
|
+
* This source code is licensed under the ISC license.
|
|
1481
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1482
|
+
*/
|
|
1483
|
+
const __iconNode$2 = [
|
|
1484
|
+
[
|
|
1485
|
+
"path",
|
|
1486
|
+
{
|
|
1487
|
+
d: "M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",
|
|
1488
|
+
key: "1s2grr"
|
|
1489
|
+
}
|
|
1490
|
+
],
|
|
1491
|
+
["path", { d: "M20 2v4", key: "1rf3ol" }],
|
|
1492
|
+
["path", { d: "M22 4h-4", key: "gwowj6" }],
|
|
1493
|
+
["circle", { cx: "4", cy: "20", r: "2", key: "6kqj1y" }]
|
|
1494
|
+
];
|
|
1495
|
+
const Sparkles = createLucideIcon("sparkles", __iconNode$2);
|
|
1415
1496
|
/**
|
|
1416
1497
|
* @license lucide-react v0.562.0 - ISC
|
|
1417
1498
|
*
|
|
@@ -1435,6 +1516,263 @@ const __iconNode = [
|
|
|
1435
1516
|
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
1436
1517
|
];
|
|
1437
1518
|
const X = createLucideIcon("x", __iconNode);
|
|
1519
|
+
function usePRStatus() {
|
|
1520
|
+
const [status, setStatus] = react.useState(null);
|
|
1521
|
+
const [isLoading, setIsLoading] = react.useState(true);
|
|
1522
|
+
const [error, setError] = react.useState(null);
|
|
1523
|
+
const fetchStatus = react.useCallback(async () => {
|
|
1524
|
+
try {
|
|
1525
|
+
setIsLoading(true);
|
|
1526
|
+
setError(null);
|
|
1527
|
+
const response = await fetch(buildServiceUrl("api/pr/status"));
|
|
1528
|
+
if (!response.ok) {
|
|
1529
|
+
throw new Error("Failed to fetch PR status");
|
|
1530
|
+
}
|
|
1531
|
+
const data = await response.json();
|
|
1532
|
+
setStatus(data);
|
|
1533
|
+
} catch (err) {
|
|
1534
|
+
setError(err instanceof Error ? err.message : "Unknown error");
|
|
1535
|
+
setStatus(null);
|
|
1536
|
+
} finally {
|
|
1537
|
+
setIsLoading(false);
|
|
1538
|
+
}
|
|
1539
|
+
}, []);
|
|
1540
|
+
react.useEffect(() => {
|
|
1541
|
+
fetchStatus();
|
|
1542
|
+
}, [fetchStatus]);
|
|
1543
|
+
return {
|
|
1544
|
+
status,
|
|
1545
|
+
isLoading,
|
|
1546
|
+
error,
|
|
1547
|
+
refresh: fetchStatus
|
|
1548
|
+
};
|
|
1549
|
+
}
|
|
1550
|
+
function useCreatePR() {
|
|
1551
|
+
const [isCreating, setIsCreating] = react.useState(false);
|
|
1552
|
+
const [isGenerating, setIsGenerating] = react.useState(false);
|
|
1553
|
+
const generateContent = react.useCallback(async () => {
|
|
1554
|
+
setIsGenerating(true);
|
|
1555
|
+
try {
|
|
1556
|
+
const response = await fetch(buildServiceUrl("api/pr/generate-description"), {
|
|
1557
|
+
method: "POST",
|
|
1558
|
+
headers: { "Content-Type": "application/json" },
|
|
1559
|
+
body: JSON.stringify({})
|
|
1560
|
+
});
|
|
1561
|
+
if (!response.ok) {
|
|
1562
|
+
throw new Error("Failed to generate PR content");
|
|
1563
|
+
}
|
|
1564
|
+
const data = await response.json();
|
|
1565
|
+
return {
|
|
1566
|
+
title: data.title || "",
|
|
1567
|
+
description: data.description || ""
|
|
1568
|
+
};
|
|
1569
|
+
} catch (err) {
|
|
1570
|
+
console.error("Error generating PR content:", err);
|
|
1571
|
+
return { title: "", description: "" };
|
|
1572
|
+
} finally {
|
|
1573
|
+
setIsGenerating(false);
|
|
1574
|
+
}
|
|
1575
|
+
}, []);
|
|
1576
|
+
const createPR = react.useCallback(async (input) => {
|
|
1577
|
+
setIsCreating(true);
|
|
1578
|
+
try {
|
|
1579
|
+
const response = await fetch(buildServiceUrl("api/pr/create"), {
|
|
1580
|
+
method: "POST",
|
|
1581
|
+
headers: { "Content-Type": "application/json" },
|
|
1582
|
+
body: JSON.stringify(input)
|
|
1583
|
+
});
|
|
1584
|
+
const data = await response.json();
|
|
1585
|
+
if (!response.ok) {
|
|
1586
|
+
return {
|
|
1587
|
+
success: false,
|
|
1588
|
+
error: data.error || "Failed to create PR",
|
|
1589
|
+
branchName: data.branchName,
|
|
1590
|
+
partialSuccess: data.partialSuccess
|
|
1591
|
+
};
|
|
1592
|
+
}
|
|
1593
|
+
return {
|
|
1594
|
+
success: true,
|
|
1595
|
+
prUrl: data.prUrl,
|
|
1596
|
+
prNumber: data.prNumber,
|
|
1597
|
+
branchName: data.branchName
|
|
1598
|
+
};
|
|
1599
|
+
} catch (err) {
|
|
1600
|
+
return {
|
|
1601
|
+
success: false,
|
|
1602
|
+
error: err instanceof Error ? err.message : "Failed to create PR"
|
|
1603
|
+
};
|
|
1604
|
+
} finally {
|
|
1605
|
+
setIsCreating(false);
|
|
1606
|
+
}
|
|
1607
|
+
}, []);
|
|
1608
|
+
return {
|
|
1609
|
+
createPR,
|
|
1610
|
+
generateContent,
|
|
1611
|
+
isCreating,
|
|
1612
|
+
isGenerating
|
|
1613
|
+
};
|
|
1614
|
+
}
|
|
1615
|
+
function PRBlock({ onCancel, onSuccess }) {
|
|
1616
|
+
const [title, setTitle] = react.useState("");
|
|
1617
|
+
const [description, setDescription] = react.useState("");
|
|
1618
|
+
const [error, setError] = react.useState(null);
|
|
1619
|
+
const [result, setResult] = react.useState(null);
|
|
1620
|
+
const [blockState, setBlockState] = react.useState("generating");
|
|
1621
|
+
const hasGenerated = react.useRef(false);
|
|
1622
|
+
const { status } = usePRStatus();
|
|
1623
|
+
const { createPR, generateContent, isGenerating } = useCreatePR();
|
|
1624
|
+
react.useEffect(() => {
|
|
1625
|
+
if (!hasGenerated.current) {
|
|
1626
|
+
hasGenerated.current = true;
|
|
1627
|
+
generateContent().then((content) => {
|
|
1628
|
+
setTitle(content.title);
|
|
1629
|
+
setDescription(content.description);
|
|
1630
|
+
setBlockState("form");
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
}, [generateContent]);
|
|
1634
|
+
const handleRegenerate = react.useCallback(async () => {
|
|
1635
|
+
setError(null);
|
|
1636
|
+
const content = await generateContent();
|
|
1637
|
+
setTitle(content.title);
|
|
1638
|
+
setDescription(content.description);
|
|
1639
|
+
}, [generateContent]);
|
|
1640
|
+
const handleSubmit = react.useCallback(async () => {
|
|
1641
|
+
if (!title.trim()) {
|
|
1642
|
+
setError("Title is required");
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
setError(null);
|
|
1646
|
+
setBlockState("creating");
|
|
1647
|
+
const prResult = await createPR({ title: title.trim(), description });
|
|
1648
|
+
if (prResult.success) {
|
|
1649
|
+
setResult(prResult);
|
|
1650
|
+
setBlockState("success");
|
|
1651
|
+
onSuccess == null ? void 0 : onSuccess(prResult);
|
|
1652
|
+
} else {
|
|
1653
|
+
setError(prResult.error || "Failed to create PR");
|
|
1654
|
+
setBlockState("form");
|
|
1655
|
+
}
|
|
1656
|
+
}, [title, description, createPR, onSuccess]);
|
|
1657
|
+
if (blockState === "success" && result) {
|
|
1658
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-block pr-block-success", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-success-content", children: [
|
|
1659
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-block-success-icon", children: /* @__PURE__ */ jsxRuntime.jsx(Check, { size: 16 }) }),
|
|
1660
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-success-text", children: [
|
|
1661
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pr-block-success-title", children: "PR Created" }),
|
|
1662
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1663
|
+
"a",
|
|
1664
|
+
{
|
|
1665
|
+
href: result.prUrl,
|
|
1666
|
+
target: "_blank",
|
|
1667
|
+
rel: "noopener noreferrer",
|
|
1668
|
+
className: "pr-block-success-link",
|
|
1669
|
+
children: [
|
|
1670
|
+
"#",
|
|
1671
|
+
result.prNumber
|
|
1672
|
+
]
|
|
1673
|
+
}
|
|
1674
|
+
),
|
|
1675
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "pr-block-success-branch", children: [
|
|
1676
|
+
"on ",
|
|
1677
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: result.branchName })
|
|
1678
|
+
] })
|
|
1679
|
+
] })
|
|
1680
|
+
] }) });
|
|
1681
|
+
}
|
|
1682
|
+
if (blockState === "generating") {
|
|
1683
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-block pr-block-generating", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-loading", children: [
|
|
1684
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { size: 16, className: "pr-block-spinner" }),
|
|
1685
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Generating PR details..." })
|
|
1686
|
+
] }) });
|
|
1687
|
+
}
|
|
1688
|
+
const isDisabled = blockState === "creating" || isGenerating;
|
|
1689
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block", children: [
|
|
1690
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-header", children: [
|
|
1691
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "pr-block-title", children: "Create Pull Request" }),
|
|
1692
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1693
|
+
"button",
|
|
1694
|
+
{
|
|
1695
|
+
className: "pr-block-cancel",
|
|
1696
|
+
onClick: onCancel,
|
|
1697
|
+
disabled: blockState === "creating",
|
|
1698
|
+
title: "Cancel",
|
|
1699
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(X, { size: 14 })
|
|
1700
|
+
}
|
|
1701
|
+
)
|
|
1702
|
+
] }),
|
|
1703
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-content", children: [
|
|
1704
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-block-error", children: error }),
|
|
1705
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-field", children: [
|
|
1706
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "pr-block-title", children: "Title" }),
|
|
1707
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1708
|
+
"input",
|
|
1709
|
+
{
|
|
1710
|
+
id: "pr-block-title",
|
|
1711
|
+
type: "text",
|
|
1712
|
+
value: title,
|
|
1713
|
+
onChange: (e) => setTitle(e.target.value),
|
|
1714
|
+
placeholder: "PR title...",
|
|
1715
|
+
disabled: isDisabled
|
|
1716
|
+
}
|
|
1717
|
+
)
|
|
1718
|
+
] }),
|
|
1719
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-field", children: [
|
|
1720
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-field-header", children: [
|
|
1721
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "pr-block-description", children: "Description" }),
|
|
1722
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1723
|
+
"button",
|
|
1724
|
+
{
|
|
1725
|
+
className: "pr-block-regenerate",
|
|
1726
|
+
onClick: handleRegenerate,
|
|
1727
|
+
disabled: isDisabled,
|
|
1728
|
+
children: [
|
|
1729
|
+
isGenerating ? /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { size: 12, className: "pr-block-spinner" }) : /* @__PURE__ */ jsxRuntime.jsx(Sparkles, { size: 12 }),
|
|
1730
|
+
"Regen"
|
|
1731
|
+
]
|
|
1732
|
+
}
|
|
1733
|
+
)
|
|
1734
|
+
] }),
|
|
1735
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1736
|
+
"textarea",
|
|
1737
|
+
{
|
|
1738
|
+
id: "pr-block-description",
|
|
1739
|
+
value: description,
|
|
1740
|
+
onChange: (e) => setDescription(e.target.value),
|
|
1741
|
+
placeholder: "Describe your changes...",
|
|
1742
|
+
disabled: isDisabled,
|
|
1743
|
+
rows: 3
|
|
1744
|
+
}
|
|
1745
|
+
)
|
|
1746
|
+
] }),
|
|
1747
|
+
status && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-block-info", children: [
|
|
1748
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1749
|
+
/* @__PURE__ */ jsxRuntime.jsx(FileText, { size: 12 }),
|
|
1750
|
+
status.changedFiles.length,
|
|
1751
|
+
" files"
|
|
1752
|
+
] }),
|
|
1753
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
1754
|
+
/* @__PURE__ */ jsxRuntime.jsx(GitBranch, { size: 12 }),
|
|
1755
|
+
status.baseBranch
|
|
1756
|
+
] })
|
|
1757
|
+
] })
|
|
1758
|
+
] }),
|
|
1759
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-block-footer", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1760
|
+
"button",
|
|
1761
|
+
{
|
|
1762
|
+
className: "pr-block-submit",
|
|
1763
|
+
onClick: handleSubmit,
|
|
1764
|
+
disabled: isDisabled || !title.trim(),
|
|
1765
|
+
children: blockState === "creating" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1766
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { size: 14, className: "pr-block-spinner" }),
|
|
1767
|
+
"Creating..."
|
|
1768
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1769
|
+
/* @__PURE__ */ jsxRuntime.jsx(GitPullRequest, { size: 14 }),
|
|
1770
|
+
"Create PR"
|
|
1771
|
+
] })
|
|
1772
|
+
}
|
|
1773
|
+
) })
|
|
1774
|
+
] });
|
|
1775
|
+
}
|
|
1438
1776
|
function ChatPanel({
|
|
1439
1777
|
isExpanded,
|
|
1440
1778
|
onToggle,
|
|
@@ -1449,9 +1787,19 @@ function ChatPanel({
|
|
|
1449
1787
|
const textareaRef = react.useRef(null);
|
|
1450
1788
|
const [contextRanges, setContextRanges] = react.useState([]);
|
|
1451
1789
|
const [isMessagesCollapsed, setMessagesCollapsed] = react.useState(false);
|
|
1790
|
+
const [showPRBlock, setShowPRBlock] = react.useState(false);
|
|
1452
1791
|
const { messages, isStreaming, sendMessage, startedToolIds, completedToolIds, todos } = useChatStream({
|
|
1453
1792
|
threadId
|
|
1454
1793
|
});
|
|
1794
|
+
const { status: prStatus, isLoading: prLoading, refresh: refreshPRStatus } = usePRStatus();
|
|
1795
|
+
const hasChanges = (prStatus == null ? void 0 : prStatus.hasChanges) ?? false;
|
|
1796
|
+
const prevIsStreaming = react.useRef(isStreaming);
|
|
1797
|
+
react.useEffect(() => {
|
|
1798
|
+
if (prevIsStreaming.current && !isStreaming) {
|
|
1799
|
+
refreshPRStatus();
|
|
1800
|
+
}
|
|
1801
|
+
prevIsStreaming.current = isStreaming;
|
|
1802
|
+
}, [isStreaming, refreshPRStatus]);
|
|
1455
1803
|
react.useEffect(() => {
|
|
1456
1804
|
if (attachedContext) {
|
|
1457
1805
|
setContextRanges((prev) => [...prev, {
|
|
@@ -1534,11 +1882,15 @@ function ChatPanel({
|
|
|
1534
1882
|
}
|
|
1535
1883
|
return count;
|
|
1536
1884
|
}, [commentMessages]);
|
|
1885
|
+
const handlePRCancel = react.useCallback(() => {
|
|
1886
|
+
setShowPRBlock(false);
|
|
1887
|
+
}, []);
|
|
1888
|
+
const prButtonTitle = prLoading ? "Checking for changes..." : hasChanges ? `Create PR (${prStatus == null ? void 0 : prStatus.changedFiles.length} files)` : "No changes to commit";
|
|
1537
1889
|
if (!isExpanded) {
|
|
1538
1890
|
return null;
|
|
1539
1891
|
}
|
|
1540
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `chat-panel ai-editor-ui ${theme} ${commentMessages.length === 0 ? "empty" : ""}`, children: [
|
|
1541
|
-
commentMessages.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `chat-panel-messages-container ${isMessagesCollapsed ? "collapsed" : "expanded"}`, children: [
|
|
1892
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `chat-panel ai-editor-ui ${theme} ${commentMessages.length === 0 && !showPRBlock ? "empty" : ""}`, children: [
|
|
1893
|
+
(commentMessages.length > 0 || showPRBlock) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `chat-panel-messages-container ${isMessagesCollapsed ? "collapsed" : "expanded"}`, children: [
|
|
1542
1894
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-panel-messages-header", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1543
1895
|
"div",
|
|
1544
1896
|
{
|
|
@@ -1554,18 +1906,21 @@ function ChatPanel({
|
|
|
1554
1906
|
]
|
|
1555
1907
|
}
|
|
1556
1908
|
) }),
|
|
1557
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1909
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chat-panel-messages", children: [
|
|
1910
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1911
|
+
MessageList,
|
|
1912
|
+
{
|
|
1913
|
+
messages: commentMessages,
|
|
1914
|
+
isStreaming,
|
|
1915
|
+
startedToolIds,
|
|
1916
|
+
completedToolIds,
|
|
1917
|
+
todos
|
|
1918
|
+
}
|
|
1919
|
+
),
|
|
1920
|
+
showPRBlock && /* @__PURE__ */ jsxRuntime.jsx(PRBlock, { onCancel: handlePRCancel })
|
|
1921
|
+
] })
|
|
1567
1922
|
] }),
|
|
1568
|
-
commentMessages.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-panel-empty-content", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1923
|
+
commentMessages.length === 0 && !showPRBlock && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "chat-panel-empty-content", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1569
1924
|
MessageList,
|
|
1570
1925
|
{
|
|
1571
1926
|
messages: [],
|
|
@@ -1642,6 +1997,16 @@ function ChatPanel({
|
|
|
1642
1997
|
title: "Select Text",
|
|
1643
1998
|
children: /* @__PURE__ */ jsxRuntime.jsx(Type, { size: 16 })
|
|
1644
1999
|
}
|
|
2000
|
+
),
|
|
2001
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2002
|
+
"button",
|
|
2003
|
+
{
|
|
2004
|
+
className: `tool-button ${showPRBlock ? "active" : ""}`,
|
|
2005
|
+
onClick: () => setShowPRBlock(!showPRBlock),
|
|
2006
|
+
disabled: !hasChanges || prLoading,
|
|
2007
|
+
title: prButtonTitle,
|
|
2008
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(GitPullRequest, { size: 16 })
|
|
2009
|
+
}
|
|
1645
2010
|
)
|
|
1646
2011
|
] }),
|
|
1647
2012
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2103,9 +2468,162 @@ function EditorOverlay({ theme, onComponentSelect }) {
|
|
|
2103
2468
|
}
|
|
2104
2469
|
);
|
|
2105
2470
|
}
|
|
2471
|
+
function PRView({ onClose, onSuccess }) {
|
|
2472
|
+
const [title, setTitle] = react.useState("");
|
|
2473
|
+
const [description, setDescription] = react.useState("");
|
|
2474
|
+
const [error, setError] = react.useState(null);
|
|
2475
|
+
const [result, setResult] = react.useState(null);
|
|
2476
|
+
const hasGenerated = react.useRef(false);
|
|
2477
|
+
const { status } = usePRStatus();
|
|
2478
|
+
const { createPR, generateContent, isCreating, isGenerating } = useCreatePR();
|
|
2479
|
+
react.useEffect(() => {
|
|
2480
|
+
if (!hasGenerated.current && !isGenerating) {
|
|
2481
|
+
hasGenerated.current = true;
|
|
2482
|
+
generateContent().then((content) => {
|
|
2483
|
+
setTitle(content.title);
|
|
2484
|
+
setDescription(content.description);
|
|
2485
|
+
});
|
|
2486
|
+
}
|
|
2487
|
+
}, [isGenerating, generateContent]);
|
|
2488
|
+
react.useEffect(() => {
|
|
2489
|
+
if (result == null ? void 0 : result.success) {
|
|
2490
|
+
const timer = setTimeout(() => {
|
|
2491
|
+
onClose();
|
|
2492
|
+
}, 2e3);
|
|
2493
|
+
return () => clearTimeout(timer);
|
|
2494
|
+
}
|
|
2495
|
+
}, [result == null ? void 0 : result.success, onClose]);
|
|
2496
|
+
const handleRegenerate = react.useCallback(async () => {
|
|
2497
|
+
setError(null);
|
|
2498
|
+
const content = await generateContent();
|
|
2499
|
+
setTitle(content.title);
|
|
2500
|
+
setDescription(content.description);
|
|
2501
|
+
}, [generateContent]);
|
|
2502
|
+
const handleSubmit = react.useCallback(async () => {
|
|
2503
|
+
if (!title.trim()) {
|
|
2504
|
+
setError("Title is required");
|
|
2505
|
+
return;
|
|
2506
|
+
}
|
|
2507
|
+
setError(null);
|
|
2508
|
+
const prResult = await createPR({ title: title.trim(), description });
|
|
2509
|
+
if (prResult.success) {
|
|
2510
|
+
setResult(prResult);
|
|
2511
|
+
onSuccess == null ? void 0 : onSuccess(prResult);
|
|
2512
|
+
} else {
|
|
2513
|
+
setError(prResult.error || "Failed to create PR");
|
|
2514
|
+
}
|
|
2515
|
+
}, [title, description, createPR, onSuccess]);
|
|
2516
|
+
if (result == null ? void 0 : result.success) {
|
|
2517
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-view", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view-success", children: [
|
|
2518
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-view-success-icon", children: /* @__PURE__ */ jsxRuntime.jsx(Check, { size: 32 }) }),
|
|
2519
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { children: "PR Created!" }),
|
|
2520
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
|
|
2521
|
+
/* @__PURE__ */ jsxRuntime.jsxs("a", { href: result.prUrl, target: "_blank", rel: "noopener noreferrer", children: [
|
|
2522
|
+
"#",
|
|
2523
|
+
result.prNumber
|
|
2524
|
+
] }),
|
|
2525
|
+
" ",
|
|
2526
|
+
"on ",
|
|
2527
|
+
/* @__PURE__ */ jsxRuntime.jsx("code", { children: result.branchName })
|
|
2528
|
+
] })
|
|
2529
|
+
] }) });
|
|
2530
|
+
}
|
|
2531
|
+
if (isGenerating && !title) {
|
|
2532
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-view", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view-loading", children: [
|
|
2533
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { size: 24, className: "pr-view-spinner" }),
|
|
2534
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Generating PR details..." })
|
|
2535
|
+
] }) });
|
|
2536
|
+
}
|
|
2537
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view", children: [
|
|
2538
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view-content", children: [
|
|
2539
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pr-view-error", children: error }),
|
|
2540
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view-field", children: [
|
|
2541
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "pr-title", children: "Title" }),
|
|
2542
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2543
|
+
"input",
|
|
2544
|
+
{
|
|
2545
|
+
id: "pr-title",
|
|
2546
|
+
type: "text",
|
|
2547
|
+
value: title,
|
|
2548
|
+
onChange: (e) => setTitle(e.target.value),
|
|
2549
|
+
placeholder: "PR title...",
|
|
2550
|
+
disabled: isCreating || isGenerating
|
|
2551
|
+
}
|
|
2552
|
+
)
|
|
2553
|
+
] }),
|
|
2554
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view-field", children: [
|
|
2555
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view-field-header", children: [
|
|
2556
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "pr-description", children: "Description" }),
|
|
2557
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2558
|
+
"button",
|
|
2559
|
+
{
|
|
2560
|
+
className: "pr-view-regenerate",
|
|
2561
|
+
onClick: handleRegenerate,
|
|
2562
|
+
disabled: isGenerating || isCreating,
|
|
2563
|
+
children: [
|
|
2564
|
+
isGenerating ? /* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { size: 12, className: "pr-view-spinner" }) : /* @__PURE__ */ jsxRuntime.jsx(Sparkles, { size: 12 }),
|
|
2565
|
+
"Regenerate"
|
|
2566
|
+
]
|
|
2567
|
+
}
|
|
2568
|
+
)
|
|
2569
|
+
] }),
|
|
2570
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2571
|
+
"textarea",
|
|
2572
|
+
{
|
|
2573
|
+
id: "pr-description",
|
|
2574
|
+
value: description,
|
|
2575
|
+
onChange: (e) => setDescription(e.target.value),
|
|
2576
|
+
placeholder: "Describe your changes...",
|
|
2577
|
+
disabled: isCreating || isGenerating
|
|
2578
|
+
}
|
|
2579
|
+
)
|
|
2580
|
+
] }),
|
|
2581
|
+
status && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view-info", children: [
|
|
2582
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2583
|
+
/* @__PURE__ */ jsxRuntime.jsx(FileText, { size: 12 }),
|
|
2584
|
+
status.changedFiles.length,
|
|
2585
|
+
" files"
|
|
2586
|
+
] }),
|
|
2587
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
2588
|
+
/* @__PURE__ */ jsxRuntime.jsx(GitBranch, { size: 12 }),
|
|
2589
|
+
status.baseBranch
|
|
2590
|
+
] })
|
|
2591
|
+
] })
|
|
2592
|
+
] }),
|
|
2593
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pr-view-footer", children: [
|
|
2594
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2595
|
+
"button",
|
|
2596
|
+
{
|
|
2597
|
+
className: "pr-view-btn pr-view-btn-secondary",
|
|
2598
|
+
onClick: onClose,
|
|
2599
|
+
disabled: isCreating,
|
|
2600
|
+
children: "Cancel"
|
|
2601
|
+
}
|
|
2602
|
+
),
|
|
2603
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2604
|
+
"button",
|
|
2605
|
+
{
|
|
2606
|
+
className: "pr-view-btn pr-view-btn-primary",
|
|
2607
|
+
onClick: handleSubmit,
|
|
2608
|
+
disabled: isCreating || !title.trim(),
|
|
2609
|
+
children: isCreating ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2610
|
+
/* @__PURE__ */ jsxRuntime.jsx(LoaderCircle, { size: 14, className: "pr-view-spinner" }),
|
|
2611
|
+
"Creating..."
|
|
2612
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2613
|
+
/* @__PURE__ */ jsxRuntime.jsx(GitPullRequest, { size: 14 }),
|
|
2614
|
+
"Create PR"
|
|
2615
|
+
] })
|
|
2616
|
+
}
|
|
2617
|
+
)
|
|
2618
|
+
] })
|
|
2619
|
+
] });
|
|
2620
|
+
}
|
|
2106
2621
|
exports.AIEditorProvider = AIEditorProvider;
|
|
2107
2622
|
exports.ChatPanel = ChatPanel;
|
|
2108
2623
|
exports.ControlPill = ControlPill;
|
|
2624
|
+
exports.PRView = PRView;
|
|
2109
2625
|
exports.buildServiceUrl = buildServiceUrl;
|
|
2110
2626
|
exports.getServiceUrl = getServiceUrl;
|
|
2627
|
+
exports.useCreatePR = useCreatePR;
|
|
2628
|
+
exports.usePRStatus = usePRStatus;
|
|
2111
2629
|
//# sourceMappingURL=index.cjs.map
|