@apteva/apteva-kit 0.1.110 → 0.1.111
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/index.js +349 -131
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +283 -65
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4,13 +4,13 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
|
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
|
|
6
6
|
// src/components/Chat/Chat.tsx
|
|
7
|
-
import { useState as useState9, useEffect as
|
|
7
|
+
import { useState as useState9, useEffect as useEffect8, useRef as useRef9, useMemo as useMemo2, useCallback as useCallback3, forwardRef, useImperativeHandle } from "react";
|
|
8
8
|
|
|
9
9
|
// src/components/Chat/MessageList.tsx
|
|
10
|
-
import { useEffect as
|
|
10
|
+
import { useEffect as useEffect7, useRef as useRef6 } from "react";
|
|
11
11
|
|
|
12
12
|
// src/components/Chat/Message.tsx
|
|
13
|
-
import { useEffect as
|
|
13
|
+
import { useEffect as useEffect6, useRef as useRef5, useMemo } from "react";
|
|
14
14
|
|
|
15
15
|
// src/utils/cn.ts
|
|
16
16
|
import { clsx } from "clsx";
|
|
@@ -1139,7 +1139,7 @@ function convertApiMessages(apiMessages) {
|
|
|
1139
1139
|
}
|
|
1140
1140
|
|
|
1141
1141
|
// src/components/Widgets/Widgets.tsx
|
|
1142
|
-
import { useEffect as
|
|
1142
|
+
import { useEffect as useEffect5 } from "react";
|
|
1143
1143
|
|
|
1144
1144
|
// src/components/Widgets/widget-library/Card.tsx
|
|
1145
1145
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -1438,8 +1438,219 @@ function Table({ widget, onAction }) {
|
|
|
1438
1438
|
}
|
|
1439
1439
|
|
|
1440
1440
|
// src/components/Widgets/widget-library/Form.tsx
|
|
1441
|
-
import { useState as useState3, useRef as useRef3 } from "react";
|
|
1441
|
+
import { useState as useState3, useRef as useRef3, useEffect as useEffect3, useCallback } from "react";
|
|
1442
1442
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1443
|
+
function CustomSelect({
|
|
1444
|
+
name,
|
|
1445
|
+
value,
|
|
1446
|
+
options,
|
|
1447
|
+
placeholder,
|
|
1448
|
+
required,
|
|
1449
|
+
onChange
|
|
1450
|
+
}) {
|
|
1451
|
+
const [open, setOpen] = useState3(false);
|
|
1452
|
+
const ref = useRef3(null);
|
|
1453
|
+
const selected = options?.find((o) => o.value === value);
|
|
1454
|
+
useEffect3(() => {
|
|
1455
|
+
if (!open) return;
|
|
1456
|
+
const handler = (e) => {
|
|
1457
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
1458
|
+
};
|
|
1459
|
+
document.addEventListener("mousedown", handler);
|
|
1460
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
1461
|
+
}, [open]);
|
|
1462
|
+
return /* @__PURE__ */ jsxs4("div", { ref, className: "apteva-select relative", children: [
|
|
1463
|
+
/* @__PURE__ */ jsxs4(
|
|
1464
|
+
"select",
|
|
1465
|
+
{
|
|
1466
|
+
name,
|
|
1467
|
+
value,
|
|
1468
|
+
required,
|
|
1469
|
+
onChange: () => {
|
|
1470
|
+
},
|
|
1471
|
+
tabIndex: -1,
|
|
1472
|
+
className: "absolute inset-0 opacity-0 pointer-events-none",
|
|
1473
|
+
"aria-hidden": true,
|
|
1474
|
+
children: [
|
|
1475
|
+
/* @__PURE__ */ jsx6("option", { value: "" }),
|
|
1476
|
+
options?.map((o) => /* @__PURE__ */ jsx6("option", { value: o.value, children: o.label }, o.value))
|
|
1477
|
+
]
|
|
1478
|
+
}
|
|
1479
|
+
),
|
|
1480
|
+
/* @__PURE__ */ jsxs4(
|
|
1481
|
+
"button",
|
|
1482
|
+
{
|
|
1483
|
+
type: "button",
|
|
1484
|
+
onClick: () => setOpen(!open),
|
|
1485
|
+
className: "apteva-select-trigger w-full flex items-center justify-between px-3 py-2 rounded-lg border transition-colors text-left",
|
|
1486
|
+
children: [
|
|
1487
|
+
/* @__PURE__ */ jsx6("span", { className: selected ? "apteva-select-value" : "apteva-select-placeholder", children: selected ? selected.label : placeholder || "Select..." }),
|
|
1488
|
+
/* @__PURE__ */ jsx6(
|
|
1489
|
+
"svg",
|
|
1490
|
+
{
|
|
1491
|
+
className: `apteva-select-chevron w-4 h-4 flex-shrink-0 transition-transform ${open ? "rotate-180" : ""}`,
|
|
1492
|
+
fill: "none",
|
|
1493
|
+
stroke: "currentColor",
|
|
1494
|
+
viewBox: "0 0 24 24",
|
|
1495
|
+
children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
|
|
1496
|
+
}
|
|
1497
|
+
)
|
|
1498
|
+
]
|
|
1499
|
+
}
|
|
1500
|
+
),
|
|
1501
|
+
open && /* @__PURE__ */ jsx6("div", { className: "apteva-select-dropdown absolute z-50 w-full mt-1 rounded-lg border shadow-lg overflow-hidden", children: /* @__PURE__ */ jsxs4("div", { className: "max-h-48 overflow-y-auto py-1", children: [
|
|
1502
|
+
options?.map((opt) => /* @__PURE__ */ jsx6(
|
|
1503
|
+
"button",
|
|
1504
|
+
{
|
|
1505
|
+
type: "button",
|
|
1506
|
+
onClick: () => {
|
|
1507
|
+
onChange(opt.value);
|
|
1508
|
+
setOpen(false);
|
|
1509
|
+
},
|
|
1510
|
+
className: `apteva-select-option w-full text-left px-3 py-2 text-sm transition-colors ${opt.value === value ? "apteva-select-option-active" : ""}`,
|
|
1511
|
+
children: opt.label
|
|
1512
|
+
},
|
|
1513
|
+
opt.value
|
|
1514
|
+
)),
|
|
1515
|
+
(!options || options.length === 0) && /* @__PURE__ */ jsx6("div", { className: "px-3 py-2 text-sm apteva-select-placeholder", children: "No options" })
|
|
1516
|
+
] }) })
|
|
1517
|
+
] });
|
|
1518
|
+
}
|
|
1519
|
+
function CustomDatePicker({
|
|
1520
|
+
name,
|
|
1521
|
+
value,
|
|
1522
|
+
placeholder,
|
|
1523
|
+
required,
|
|
1524
|
+
onChange
|
|
1525
|
+
}) {
|
|
1526
|
+
const [open, setOpen] = useState3(false);
|
|
1527
|
+
const ref = useRef3(null);
|
|
1528
|
+
const parseDate = (v) => {
|
|
1529
|
+
if (v) {
|
|
1530
|
+
const [y, m, d] = v.split("-").map(Number);
|
|
1531
|
+
return { year: y, month: m - 1, day: d };
|
|
1532
|
+
}
|
|
1533
|
+
const now = /* @__PURE__ */ new Date();
|
|
1534
|
+
return { year: now.getFullYear(), month: now.getMonth(), day: 0 };
|
|
1535
|
+
};
|
|
1536
|
+
const parsed = parseDate(value);
|
|
1537
|
+
const [viewYear, setViewYear] = useState3(parsed.year);
|
|
1538
|
+
const [viewMonth, setViewMonth] = useState3(parsed.month);
|
|
1539
|
+
useEffect3(() => {
|
|
1540
|
+
if (!open) return;
|
|
1541
|
+
const handler = (e) => {
|
|
1542
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
1543
|
+
};
|
|
1544
|
+
document.addEventListener("mousedown", handler);
|
|
1545
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
1546
|
+
}, [open]);
|
|
1547
|
+
useEffect3(() => {
|
|
1548
|
+
if (value) {
|
|
1549
|
+
const p = parseDate(value);
|
|
1550
|
+
setViewYear(p.year);
|
|
1551
|
+
setViewMonth(p.month);
|
|
1552
|
+
}
|
|
1553
|
+
}, [value]);
|
|
1554
|
+
const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
|
|
1555
|
+
const firstDayOfWeek = new Date(viewYear, viewMonth, 1).getDay();
|
|
1556
|
+
const startOffset = (firstDayOfWeek + 6) % 7;
|
|
1557
|
+
const prevMonth = () => {
|
|
1558
|
+
if (viewMonth === 0) {
|
|
1559
|
+
setViewMonth(11);
|
|
1560
|
+
setViewYear(viewYear - 1);
|
|
1561
|
+
} else setViewMonth(viewMonth - 1);
|
|
1562
|
+
};
|
|
1563
|
+
const nextMonth = () => {
|
|
1564
|
+
if (viewMonth === 11) {
|
|
1565
|
+
setViewMonth(0);
|
|
1566
|
+
setViewYear(viewYear + 1);
|
|
1567
|
+
} else setViewMonth(viewMonth + 1);
|
|
1568
|
+
};
|
|
1569
|
+
const selectDay = (day) => {
|
|
1570
|
+
const m = String(viewMonth + 1).padStart(2, "0");
|
|
1571
|
+
const d = String(day).padStart(2, "0");
|
|
1572
|
+
onChange(`${viewYear}-${m}-${d}`);
|
|
1573
|
+
setOpen(false);
|
|
1574
|
+
};
|
|
1575
|
+
const formatDisplay = (v) => {
|
|
1576
|
+
if (!v) return "";
|
|
1577
|
+
const [y, m, d] = v.split("-");
|
|
1578
|
+
return `${d}/${m}/${y}`;
|
|
1579
|
+
};
|
|
1580
|
+
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
1581
|
+
const dayLabels = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
|
|
1582
|
+
const isSelected = (day) => {
|
|
1583
|
+
if (!value) return false;
|
|
1584
|
+
const p = parseDate(value);
|
|
1585
|
+
return p.year === viewYear && p.month === viewMonth && p.day === day;
|
|
1586
|
+
};
|
|
1587
|
+
const isToday = (day) => {
|
|
1588
|
+
const now = /* @__PURE__ */ new Date();
|
|
1589
|
+
return now.getFullYear() === viewYear && now.getMonth() === viewMonth && now.getDate() === day;
|
|
1590
|
+
};
|
|
1591
|
+
return /* @__PURE__ */ jsxs4("div", { ref, className: "apteva-datepicker relative", children: [
|
|
1592
|
+
/* @__PURE__ */ jsx6(
|
|
1593
|
+
"input",
|
|
1594
|
+
{
|
|
1595
|
+
type: "text",
|
|
1596
|
+
name,
|
|
1597
|
+
value,
|
|
1598
|
+
required,
|
|
1599
|
+
onChange: () => {
|
|
1600
|
+
},
|
|
1601
|
+
tabIndex: -1,
|
|
1602
|
+
className: "absolute inset-0 opacity-0 pointer-events-none",
|
|
1603
|
+
"aria-hidden": true
|
|
1604
|
+
}
|
|
1605
|
+
),
|
|
1606
|
+
/* @__PURE__ */ jsxs4(
|
|
1607
|
+
"button",
|
|
1608
|
+
{
|
|
1609
|
+
type: "button",
|
|
1610
|
+
onClick: () => setOpen(!open),
|
|
1611
|
+
className: "apteva-datepicker-trigger w-full flex items-center justify-between px-3 py-2 rounded-lg border transition-colors text-left",
|
|
1612
|
+
children: [
|
|
1613
|
+
/* @__PURE__ */ jsx6("span", { className: value ? "apteva-datepicker-value" : "apteva-select-placeholder", children: value ? formatDisplay(value) : placeholder || "Select date..." }),
|
|
1614
|
+
/* @__PURE__ */ jsx6("svg", { className: "apteva-select-chevron w-4 h-4 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) })
|
|
1615
|
+
]
|
|
1616
|
+
}
|
|
1617
|
+
),
|
|
1618
|
+
open && /* @__PURE__ */ jsxs4("div", { className: "apteva-datepicker-dropdown absolute z-50 mt-1 rounded-lg border shadow-lg overflow-hidden", children: [
|
|
1619
|
+
/* @__PURE__ */ jsxs4("div", { className: "apteva-datepicker-header flex items-center justify-between px-3 py-2", children: [
|
|
1620
|
+
/* @__PURE__ */ jsx6("button", { type: "button", onClick: prevMonth, className: "apteva-datepicker-nav p-1 rounded transition-colors", children: /* @__PURE__ */ jsx6("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }),
|
|
1621
|
+
/* @__PURE__ */ jsxs4("span", { className: "apteva-datepicker-title text-sm font-semibold", children: [
|
|
1622
|
+
monthNames[viewMonth],
|
|
1623
|
+
" ",
|
|
1624
|
+
viewYear
|
|
1625
|
+
] }),
|
|
1626
|
+
/* @__PURE__ */ jsx6("button", { type: "button", onClick: nextMonth, className: "apteva-datepicker-nav p-1 rounded transition-colors", children: /* @__PURE__ */ jsx6("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }) })
|
|
1627
|
+
] }),
|
|
1628
|
+
/* @__PURE__ */ jsx6("div", { className: "grid grid-cols-7 px-2", children: dayLabels.map((d) => /* @__PURE__ */ jsx6("div", { className: "apteva-datepicker-daylabel text-center text-xs font-medium py-1", children: d }, d)) }),
|
|
1629
|
+
/* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-7 px-2 pb-2", children: [
|
|
1630
|
+
Array.from({ length: startOffset }).map((_, i) => /* @__PURE__ */ jsx6("div", {}, `empty-${i}`)),
|
|
1631
|
+
Array.from({ length: daysInMonth }).map((_, i) => {
|
|
1632
|
+
const day = i + 1;
|
|
1633
|
+
const sel = isSelected(day);
|
|
1634
|
+
const today = isToday(day);
|
|
1635
|
+
return /* @__PURE__ */ jsx6(
|
|
1636
|
+
"button",
|
|
1637
|
+
{
|
|
1638
|
+
type: "button",
|
|
1639
|
+
onClick: () => selectDay(day),
|
|
1640
|
+
className: [
|
|
1641
|
+
"apteva-datepicker-day text-center text-sm py-1 rounded transition-colors",
|
|
1642
|
+
sel ? "apteva-datepicker-day-selected" : "",
|
|
1643
|
+
today && !sel ? "apteva-datepicker-day-today" : ""
|
|
1644
|
+
].join(" "),
|
|
1645
|
+
children: day
|
|
1646
|
+
},
|
|
1647
|
+
day
|
|
1648
|
+
);
|
|
1649
|
+
})
|
|
1650
|
+
] })
|
|
1651
|
+
] })
|
|
1652
|
+
] });
|
|
1653
|
+
}
|
|
1443
1654
|
function Form({ widget, onAction }) {
|
|
1444
1655
|
const { title, fields } = widget.props;
|
|
1445
1656
|
const fileInputRefs = useRef3({});
|
|
@@ -1454,9 +1665,9 @@ function Form({ widget, onAction }) {
|
|
|
1454
1665
|
});
|
|
1455
1666
|
return initial;
|
|
1456
1667
|
});
|
|
1457
|
-
const handleChange = (name, value) => {
|
|
1668
|
+
const handleChange = useCallback((name, value) => {
|
|
1458
1669
|
setFormData((prev) => ({ ...prev, [name]: value }));
|
|
1459
|
-
};
|
|
1670
|
+
}, []);
|
|
1460
1671
|
const handleSubmit = (e) => {
|
|
1461
1672
|
e.preventDefault();
|
|
1462
1673
|
if (widget.actions?.[0] && onAction) {
|
|
@@ -1469,12 +1680,11 @@ function Form({ widget, onAction }) {
|
|
|
1469
1680
|
}
|
|
1470
1681
|
};
|
|
1471
1682
|
const renderField = (field) => {
|
|
1472
|
-
const baseInputClass = "w-full px-3 py-2 rounded-lg border transition-colors
|
|
1683
|
+
const baseInputClass = "apteva-input w-full px-3 py-2 rounded-lg border transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent";
|
|
1473
1684
|
switch (field.type) {
|
|
1474
1685
|
case "text":
|
|
1475
1686
|
case "password":
|
|
1476
1687
|
case "number":
|
|
1477
|
-
case "date":
|
|
1478
1688
|
return /* @__PURE__ */ jsx6(
|
|
1479
1689
|
"input",
|
|
1480
1690
|
{
|
|
@@ -1487,6 +1697,17 @@ function Form({ widget, onAction }) {
|
|
|
1487
1697
|
className: baseInputClass
|
|
1488
1698
|
}
|
|
1489
1699
|
);
|
|
1700
|
+
case "date":
|
|
1701
|
+
return /* @__PURE__ */ jsx6(
|
|
1702
|
+
CustomDatePicker,
|
|
1703
|
+
{
|
|
1704
|
+
name: field.name,
|
|
1705
|
+
value: formData[field.name] || "",
|
|
1706
|
+
placeholder: field.placeholder,
|
|
1707
|
+
required: field.required,
|
|
1708
|
+
onChange: (v) => handleChange(field.name, v)
|
|
1709
|
+
}
|
|
1710
|
+
);
|
|
1490
1711
|
case "textarea":
|
|
1491
1712
|
return /* @__PURE__ */ jsx6(
|
|
1492
1713
|
"textarea",
|
|
@@ -1501,22 +1722,19 @@ function Form({ widget, onAction }) {
|
|
|
1501
1722
|
}
|
|
1502
1723
|
);
|
|
1503
1724
|
case "select":
|
|
1504
|
-
return /* @__PURE__ */
|
|
1505
|
-
|
|
1725
|
+
return /* @__PURE__ */ jsx6(
|
|
1726
|
+
CustomSelect,
|
|
1506
1727
|
{
|
|
1507
1728
|
name: field.name,
|
|
1508
1729
|
value: formData[field.name] || "",
|
|
1509
|
-
|
|
1730
|
+
options: field.options,
|
|
1731
|
+
placeholder: field.placeholder,
|
|
1510
1732
|
required: field.required,
|
|
1511
|
-
|
|
1512
|
-
children: [
|
|
1513
|
-
/* @__PURE__ */ jsx6("option", { value: "", children: field.placeholder || "Select..." }),
|
|
1514
|
-
field.options?.map((opt) => /* @__PURE__ */ jsx6("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1515
|
-
]
|
|
1733
|
+
onChange: (v) => handleChange(field.name, v)
|
|
1516
1734
|
}
|
|
1517
1735
|
);
|
|
1518
1736
|
case "checkbox":
|
|
1519
|
-
return /* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-2 cursor-pointer", children: [
|
|
1737
|
+
return /* @__PURE__ */ jsxs4("label", { className: "apteva-checkbox flex items-center gap-2 cursor-pointer", children: [
|
|
1520
1738
|
/* @__PURE__ */ jsx6(
|
|
1521
1739
|
"input",
|
|
1522
1740
|
{
|
|
@@ -1524,10 +1742,10 @@ function Form({ widget, onAction }) {
|
|
|
1524
1742
|
name: field.name,
|
|
1525
1743
|
checked: formData[field.name] || false,
|
|
1526
1744
|
onChange: (e) => handleChange(field.name, e.target.checked),
|
|
1527
|
-
className: "w-4 h-4 rounded
|
|
1745
|
+
className: "w-4 h-4 rounded"
|
|
1528
1746
|
}
|
|
1529
1747
|
),
|
|
1530
|
-
/* @__PURE__ */ jsx6("span", {
|
|
1748
|
+
/* @__PURE__ */ jsx6("span", { children: field.label })
|
|
1531
1749
|
] });
|
|
1532
1750
|
case "file": {
|
|
1533
1751
|
const files = formData[field.name] || [];
|
|
@@ -1561,18 +1779,18 @@ function Form({ widget, onAction }) {
|
|
|
1561
1779
|
{
|
|
1562
1780
|
type: "button",
|
|
1563
1781
|
onClick: () => fileInputRefs.current[field.name]?.click(),
|
|
1564
|
-
className: "apteva-file-drop w-full px-3 py-3 rounded-lg border-2 border-dashed transition-colors cursor-pointer
|
|
1782
|
+
className: "apteva-file-drop w-full px-3 py-3 rounded-lg border-2 border-dashed transition-colors cursor-pointer !text-sm",
|
|
1565
1783
|
children: field.placeholder || "Click to add files"
|
|
1566
1784
|
}
|
|
1567
1785
|
),
|
|
1568
1786
|
files.length > 0 && /* @__PURE__ */ jsx6("ul", { className: "space-y-1", children: files.map((file, idx) => /* @__PURE__ */ jsxs4(
|
|
1569
1787
|
"li",
|
|
1570
1788
|
{
|
|
1571
|
-
className: "apteva-file-item-row flex items-center justify-between px-2 py-1.5 rounded-lg
|
|
1789
|
+
className: "apteva-file-item-row flex items-center justify-between px-2 py-1.5 rounded-lg !text-sm",
|
|
1572
1790
|
children: [
|
|
1573
|
-
/* @__PURE__ */ jsxs4("span", { className: "
|
|
1791
|
+
/* @__PURE__ */ jsxs4("span", { className: "truncate mr-2", children: [
|
|
1574
1792
|
file.name,
|
|
1575
|
-
/* @__PURE__ */ jsxs4("span", { className: "
|
|
1793
|
+
/* @__PURE__ */ jsxs4("span", { className: "ml-1", style: { opacity: 0.6 }, children: [
|
|
1576
1794
|
"(",
|
|
1577
1795
|
(file.size / 1024).toFixed(0),
|
|
1578
1796
|
" KB)"
|
|
@@ -1583,7 +1801,7 @@ function Form({ widget, onAction }) {
|
|
|
1583
1801
|
{
|
|
1584
1802
|
type: "button",
|
|
1585
1803
|
onClick: () => handleChange(field.name, files.filter((_, i) => i !== idx)),
|
|
1586
|
-
className: "apteva-file-remove-btn
|
|
1804
|
+
className: "apteva-file-remove-btn transition-colors flex-shrink-0",
|
|
1587
1805
|
children: "\u2715"
|
|
1588
1806
|
}
|
|
1589
1807
|
)
|
|
@@ -1598,13 +1816,13 @@ function Form({ widget, onAction }) {
|
|
|
1598
1816
|
}
|
|
1599
1817
|
};
|
|
1600
1818
|
const submitAction = widget.actions?.find((a) => a.type === "submit") || widget.actions?.[0];
|
|
1601
|
-
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "border
|
|
1819
|
+
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "border rounded-xl overflow-hidden", children: [
|
|
1602
1820
|
/* @__PURE__ */ jsxs4("div", { className: "p-4", children: [
|
|
1603
|
-
title && /* @__PURE__ */ jsx6("h3", { className: "!text-lg font-semibold
|
|
1821
|
+
title && /* @__PURE__ */ jsx6("h3", { className: "!text-lg font-semibold mb-4", children: title }),
|
|
1604
1822
|
/* @__PURE__ */ jsx6("div", { className: "space-y-3", children: fields.map((field) => /* @__PURE__ */ jsxs4("div", { className: field.type === "checkbox" ? "" : "space-y-1", children: [
|
|
1605
|
-
field.type !== "checkbox" && /* @__PURE__ */ jsxs4("label", { className: "block !text-sm font-medium
|
|
1823
|
+
field.type !== "checkbox" && /* @__PURE__ */ jsxs4("label", { className: "apteva-field-label block !text-sm font-medium", children: [
|
|
1606
1824
|
field.label,
|
|
1607
|
-
field.required && /* @__PURE__ */ jsx6("span", {
|
|
1825
|
+
field.required && /* @__PURE__ */ jsx6("span", { style: { color: "var(--aw-danger)" }, className: "ml-1", children: "*" })
|
|
1608
1826
|
] }),
|
|
1609
1827
|
renderField(field)
|
|
1610
1828
|
] }, field.name)) })
|
|
@@ -1613,7 +1831,7 @@ function Form({ widget, onAction }) {
|
|
|
1613
1831
|
"button",
|
|
1614
1832
|
{
|
|
1615
1833
|
type: "submit",
|
|
1616
|
-
className: "px-3 py-1.5 !text-sm rounded-lg font-medium transition-colors
|
|
1834
|
+
className: "px-3 py-1.5 !text-sm rounded-lg font-medium transition-colors",
|
|
1617
1835
|
children: submitAction.label || "Submit"
|
|
1618
1836
|
}
|
|
1619
1837
|
) })
|
|
@@ -1983,7 +2201,7 @@ function Spacer({ widget }) {
|
|
|
1983
2201
|
}
|
|
1984
2202
|
|
|
1985
2203
|
// src/components/Widgets/widget-library/LiveView.tsx
|
|
1986
|
-
import { useState as useState4, useCallback, useRef as useRef4, useEffect as
|
|
2204
|
+
import { useState as useState4, useCallback as useCallback2, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
1987
2205
|
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1988
2206
|
function LiveView({ widget }) {
|
|
1989
2207
|
const { src, title, height, aspectRatio = "16/9", allowFullscreen = true, sandbox, allow, refreshInterval, showToolbar = true } = widget.props;
|
|
@@ -1991,18 +2209,18 @@ function LiveView({ widget }) {
|
|
|
1991
2209
|
const [isLoading, setIsLoading] = useState4(true);
|
|
1992
2210
|
const [hasError, setHasError] = useState4(false);
|
|
1993
2211
|
const [refreshKey, setRefreshKey] = useState4(0);
|
|
1994
|
-
const handleRefresh =
|
|
2212
|
+
const handleRefresh = useCallback2(() => {
|
|
1995
2213
|
setIsLoading(true);
|
|
1996
2214
|
setHasError(false);
|
|
1997
2215
|
setRefreshKey((k) => k + 1);
|
|
1998
2216
|
}, []);
|
|
1999
|
-
const handleFullscreen =
|
|
2217
|
+
const handleFullscreen = useCallback2(() => {
|
|
2000
2218
|
iframeRef.current?.requestFullscreen?.();
|
|
2001
2219
|
}, []);
|
|
2002
|
-
const handleOpenExternal =
|
|
2220
|
+
const handleOpenExternal = useCallback2(() => {
|
|
2003
2221
|
window.open(src, "_blank", "noopener,noreferrer");
|
|
2004
2222
|
}, [src]);
|
|
2005
|
-
|
|
2223
|
+
useEffect4(() => {
|
|
2006
2224
|
if (!refreshInterval || refreshInterval <= 0) return;
|
|
2007
2225
|
const interval = setInterval(handleRefresh, refreshInterval * 1e3);
|
|
2008
2226
|
return () => clearInterval(interval);
|
|
@@ -2150,7 +2368,7 @@ function Widgets({
|
|
|
2150
2368
|
columns = 3,
|
|
2151
2369
|
className
|
|
2152
2370
|
}) {
|
|
2153
|
-
|
|
2371
|
+
useEffect5(() => {
|
|
2154
2372
|
widgets.forEach((widget) => {
|
|
2155
2373
|
onWidgetMount?.(widget.id);
|
|
2156
2374
|
});
|
|
@@ -2574,7 +2792,7 @@ function Message({ message, onAction, enableWidgets, onWidgetRender, persistentW
|
|
|
2574
2792
|
const parsed = parseWidgetsFromText(message.content);
|
|
2575
2793
|
return parsed.segments.filter((seg) => seg.type === "widget" && !!seg.widget).map((seg) => seg.widget);
|
|
2576
2794
|
}, [enableWidgets, isUser, message.content]);
|
|
2577
|
-
|
|
2795
|
+
useEffect6(() => {
|
|
2578
2796
|
if (onWidgetRender && message.widgets) {
|
|
2579
2797
|
for (const widget of message.widgets) {
|
|
2580
2798
|
if (!reportedWidgetsRef.current.has(widget.id)) {
|
|
@@ -2584,7 +2802,7 @@ function Message({ message, onAction, enableWidgets, onWidgetRender, persistentW
|
|
|
2584
2802
|
}
|
|
2585
2803
|
}
|
|
2586
2804
|
}, [message.widgets, onWidgetRender]);
|
|
2587
|
-
|
|
2805
|
+
useEffect6(() => {
|
|
2588
2806
|
if (onWidgetRender && parsedWidgets.length > 0) {
|
|
2589
2807
|
for (const widget of parsedWidgets) {
|
|
2590
2808
|
if (!reportedWidgetsRef.current.has(widget.id)) {
|
|
@@ -3038,7 +3256,7 @@ function MessageList({
|
|
|
3038
3256
|
isNearBottomRef.current = scrollHeight - scrollTop - clientHeight < 100;
|
|
3039
3257
|
}
|
|
3040
3258
|
};
|
|
3041
|
-
|
|
3259
|
+
useEffect7(() => {
|
|
3042
3260
|
if (listRef.current && isNearBottomRef.current) {
|
|
3043
3261
|
const currentScrollHeight = listRef.current.scrollHeight;
|
|
3044
3262
|
if (currentScrollHeight !== lastScrollHeightRef.current) {
|
|
@@ -3893,7 +4111,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
3893
4111
|
const [showSettingsMenu, setShowSettingsMenu] = useState9(false);
|
|
3894
4112
|
const fileInputRef = useRef9(null);
|
|
3895
4113
|
const [persistentWidgets, setPersistentWidgets] = useState9(/* @__PURE__ */ new Map());
|
|
3896
|
-
const updatePersistentWidgets =
|
|
4114
|
+
const updatePersistentWidgets = useCallback3((msgs) => {
|
|
3897
4115
|
setPersistentWidgets((prev) => {
|
|
3898
4116
|
const next = new Map(prev);
|
|
3899
4117
|
let changed = false;
|
|
@@ -3911,7 +4129,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
3911
4129
|
return changed ? next : prev;
|
|
3912
4130
|
});
|
|
3913
4131
|
}, []);
|
|
3914
|
-
|
|
4132
|
+
useEffect8(() => {
|
|
3915
4133
|
updatePersistentWidgets(messages);
|
|
3916
4134
|
}, [messages, updatePersistentWidgets]);
|
|
3917
4135
|
const persistentWidgetList = useMemo2(() => Array.from(persistentWidgets.values()), [persistentWidgets]);
|
|
@@ -3937,7 +4155,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
3937
4155
|
return context ? `${context}
|
|
3938
4156
|
${widgetContext}` : widgetContext;
|
|
3939
4157
|
}, [context, enableWidgets, availableWidgets, compactWidgetContext]);
|
|
3940
|
-
|
|
4158
|
+
useEffect8(() => {
|
|
3941
4159
|
if (apiUrl || apiKey) {
|
|
3942
4160
|
aptevaClient.configure({
|
|
3943
4161
|
...apiUrl && { apiUrl },
|
|
@@ -3945,15 +4163,15 @@ ${widgetContext}` : widgetContext;
|
|
|
3945
4163
|
});
|
|
3946
4164
|
}
|
|
3947
4165
|
}, [apiUrl, apiKey]);
|
|
3948
|
-
|
|
4166
|
+
useEffect8(() => {
|
|
3949
4167
|
if (threadId) {
|
|
3950
4168
|
onThreadChange?.(threadId);
|
|
3951
4169
|
}
|
|
3952
4170
|
}, [threadId, onThreadChange]);
|
|
3953
|
-
|
|
4171
|
+
useEffect8(() => {
|
|
3954
4172
|
setInternalPlanMode(planMode);
|
|
3955
4173
|
}, [planMode]);
|
|
3956
|
-
|
|
4174
|
+
useEffect8(() => {
|
|
3957
4175
|
const handleClickOutside = (event) => {
|
|
3958
4176
|
const target = event.target;
|
|
3959
4177
|
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
@@ -3973,7 +4191,7 @@ ${widgetContext}` : widgetContext;
|
|
|
3973
4191
|
}
|
|
3974
4192
|
};
|
|
3975
4193
|
const defaultPlaceholder = mode === "chat" ? "Type a message..." : "Enter your command...";
|
|
3976
|
-
const handleWidgetAction =
|
|
4194
|
+
const handleWidgetAction = useCallback3((action) => {
|
|
3977
4195
|
onAction?.(action);
|
|
3978
4196
|
if (action.type === "submit" && action.payload?.formData) {
|
|
3979
4197
|
const formData = action.payload.formData;
|
|
@@ -4574,7 +4792,7 @@ import { useState as useState10 } from "react";
|
|
|
4574
4792
|
import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4575
4793
|
|
|
4576
4794
|
// src/components/Command/Command.tsx
|
|
4577
|
-
import React, { useState as useState11, useEffect as
|
|
4795
|
+
import React, { useState as useState11, useEffect as useEffect9 } from "react";
|
|
4578
4796
|
import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
4579
4797
|
function Command({
|
|
4580
4798
|
agentId,
|
|
@@ -4615,15 +4833,15 @@ function Command({
|
|
|
4615
4833
|
const [showSettingsMenu, setShowSettingsMenu] = useState11(false);
|
|
4616
4834
|
const [internalPlanMode, setInternalPlanMode] = useState11(planMode);
|
|
4617
4835
|
const fileInputRef = React.useRef(null);
|
|
4618
|
-
|
|
4836
|
+
useEffect9(() => {
|
|
4619
4837
|
if (autoExecute && state === "idle" && command) {
|
|
4620
4838
|
executeCommand();
|
|
4621
4839
|
}
|
|
4622
4840
|
}, [autoExecute]);
|
|
4623
|
-
|
|
4841
|
+
useEffect9(() => {
|
|
4624
4842
|
setInternalPlanMode(planMode);
|
|
4625
4843
|
}, [planMode]);
|
|
4626
|
-
|
|
4844
|
+
useEffect9(() => {
|
|
4627
4845
|
const handleClickOutside = (event) => {
|
|
4628
4846
|
const target = event.target;
|
|
4629
4847
|
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
@@ -5656,7 +5874,7 @@ function Prompt({
|
|
|
5656
5874
|
}
|
|
5657
5875
|
|
|
5658
5876
|
// src/components/Stream/Stream.tsx
|
|
5659
|
-
import { useState as useState13, useEffect as
|
|
5877
|
+
import { useState as useState13, useEffect as useEffect10 } from "react";
|
|
5660
5878
|
import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5661
5879
|
function Stream({
|
|
5662
5880
|
agentId,
|
|
@@ -5676,7 +5894,7 @@ function Stream({
|
|
|
5676
5894
|
const [text, setText] = useState13("");
|
|
5677
5895
|
const [isStreaming, setIsStreaming] = useState13(false);
|
|
5678
5896
|
const [isComplete, setIsComplete] = useState13(false);
|
|
5679
|
-
|
|
5897
|
+
useEffect10(() => {
|
|
5680
5898
|
if (autoStart && !isStreaming && !isComplete) {
|
|
5681
5899
|
startStreaming();
|
|
5682
5900
|
}
|
|
@@ -5947,7 +6165,7 @@ function Threads({
|
|
|
5947
6165
|
}
|
|
5948
6166
|
|
|
5949
6167
|
// src/components/AutoInterface/AutoInterface.tsx
|
|
5950
|
-
import { useState as useState16, useRef as useRef10, useCallback as
|
|
6168
|
+
import { useState as useState16, useRef as useRef10, useCallback as useCallback4, useEffect as useEffect11 } from "react";
|
|
5951
6169
|
|
|
5952
6170
|
// src/components/AutoInterface/LayoutRenderer.tsx
|
|
5953
6171
|
import { useState as useState15 } from "react";
|
|
@@ -6225,11 +6443,11 @@ function AutoInterface({
|
|
|
6225
6443
|
generateInterfaceContext(),
|
|
6226
6444
|
context || ""
|
|
6227
6445
|
].filter(Boolean).join("\n\n");
|
|
6228
|
-
const updateInterface =
|
|
6446
|
+
const updateInterface = useCallback4((newSpec) => {
|
|
6229
6447
|
setInterfaceSpec(newSpec);
|
|
6230
6448
|
onInterfaceChange?.(newSpec);
|
|
6231
6449
|
}, [onInterfaceChange]);
|
|
6232
|
-
const handleAction =
|
|
6450
|
+
const handleAction = useCallback4((action) => {
|
|
6233
6451
|
onAction?.(action);
|
|
6234
6452
|
if (chatRef.current) {
|
|
6235
6453
|
chatRef.current.sendMessage(
|
|
@@ -6237,7 +6455,7 @@ function AutoInterface({
|
|
|
6237
6455
|
);
|
|
6238
6456
|
}
|
|
6239
6457
|
}, [onAction]);
|
|
6240
|
-
const handleMessageComplete =
|
|
6458
|
+
const handleMessageComplete = useCallback4((result) => {
|
|
6241
6459
|
if (!result?.data) return;
|
|
6242
6460
|
const text = typeof result.data === "string" ? result.data : result.data.message || "";
|
|
6243
6461
|
console.log("[AutoInterface] Chat message complete, text (" + text.length + " chars):", text.substring(0, 300));
|
|
@@ -6258,7 +6476,7 @@ function AutoInterface({
|
|
|
6258
6476
|
}
|
|
6259
6477
|
setIsGenerating(false);
|
|
6260
6478
|
}, [interfaceSpec, updateInterface]);
|
|
6261
|
-
|
|
6479
|
+
useEffect11(() => {
|
|
6262
6480
|
if (!initialPrompt || initialInterface || useMock) return;
|
|
6263
6481
|
if (!apiUrl) return;
|
|
6264
6482
|
let cancelled = false;
|
|
@@ -6383,29 +6601,29 @@ function getThemeScript() {
|
|
|
6383
6601
|
}
|
|
6384
6602
|
|
|
6385
6603
|
// src/hooks/useInterfaceState.ts
|
|
6386
|
-
import { useState as useState17, useCallback as
|
|
6604
|
+
import { useState as useState17, useCallback as useCallback5 } from "react";
|
|
6387
6605
|
function useInterfaceState(initialSpec) {
|
|
6388
6606
|
const [spec, setSpec] = useState17(initialSpec || null);
|
|
6389
6607
|
const [isStreaming, setIsStreaming] = useState17(false);
|
|
6390
|
-
const setInterface =
|
|
6608
|
+
const setInterface = useCallback5((newSpec) => {
|
|
6391
6609
|
setSpec(newSpec);
|
|
6392
6610
|
}, []);
|
|
6393
|
-
const clearInterface =
|
|
6611
|
+
const clearInterface = useCallback5(() => {
|
|
6394
6612
|
setSpec(null);
|
|
6395
6613
|
}, []);
|
|
6396
|
-
const applyInterfaceUpdate =
|
|
6614
|
+
const applyInterfaceUpdate = useCallback5((update) => {
|
|
6397
6615
|
setSpec((prev) => {
|
|
6398
6616
|
if (!prev) return prev;
|
|
6399
6617
|
return applyUpdate(prev, update);
|
|
6400
6618
|
});
|
|
6401
6619
|
}, []);
|
|
6402
|
-
const applyInterfaceUpdates =
|
|
6620
|
+
const applyInterfaceUpdates = useCallback5((updates) => {
|
|
6403
6621
|
setSpec((prev) => {
|
|
6404
6622
|
if (!prev) return prev;
|
|
6405
6623
|
return applyUpdates(prev, updates);
|
|
6406
6624
|
});
|
|
6407
6625
|
}, []);
|
|
6408
|
-
const getNode =
|
|
6626
|
+
const getNode = useCallback5((id) => {
|
|
6409
6627
|
if (!spec) return null;
|
|
6410
6628
|
return findNode(spec.root, id);
|
|
6411
6629
|
}, [spec]);
|
|
@@ -6422,7 +6640,7 @@ function useInterfaceState(initialSpec) {
|
|
|
6422
6640
|
}
|
|
6423
6641
|
|
|
6424
6642
|
// src/hooks/useInterfaceAI.ts
|
|
6425
|
-
import { useCallback as
|
|
6643
|
+
import { useCallback as useCallback6, useRef as useRef11 } from "react";
|
|
6426
6644
|
function useInterfaceAI({
|
|
6427
6645
|
agentId,
|
|
6428
6646
|
apiUrl,
|
|
@@ -6442,7 +6660,7 @@ function useInterfaceAI({
|
|
|
6442
6660
|
...apiKey && { apiKey }
|
|
6443
6661
|
});
|
|
6444
6662
|
}
|
|
6445
|
-
const sendMessage =
|
|
6663
|
+
const sendMessage = useCallback6(async (message) => {
|
|
6446
6664
|
accumulatedTextRef.current = "";
|
|
6447
6665
|
onStreamStart?.();
|
|
6448
6666
|
const systemPrompt = [
|