@apteva/apteva-kit 0.1.110 → 0.1.112
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 +405 -132
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +338 -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,274 @@ 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
|
+
import { createPortal } from "react-dom";
|
|
1442
1443
|
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1444
|
+
function PortalDropdown({
|
|
1445
|
+
anchorRef,
|
|
1446
|
+
open,
|
|
1447
|
+
onClose,
|
|
1448
|
+
width,
|
|
1449
|
+
children
|
|
1450
|
+
}) {
|
|
1451
|
+
const dropdownRef = useRef3(null);
|
|
1452
|
+
const [pos, setPos] = useState3({ top: 0, left: 0, width: 0 });
|
|
1453
|
+
useEffect3(() => {
|
|
1454
|
+
if (!open || !anchorRef.current) return;
|
|
1455
|
+
const update = () => {
|
|
1456
|
+
const rect = anchorRef.current.getBoundingClientRect();
|
|
1457
|
+
setPos({
|
|
1458
|
+
top: rect.bottom + window.scrollY + 4,
|
|
1459
|
+
left: rect.left + window.scrollX,
|
|
1460
|
+
width: rect.width
|
|
1461
|
+
});
|
|
1462
|
+
};
|
|
1463
|
+
update();
|
|
1464
|
+
window.addEventListener("scroll", update, true);
|
|
1465
|
+
window.addEventListener("resize", update);
|
|
1466
|
+
return () => {
|
|
1467
|
+
window.removeEventListener("scroll", update, true);
|
|
1468
|
+
window.removeEventListener("resize", update);
|
|
1469
|
+
};
|
|
1470
|
+
}, [open, anchorRef]);
|
|
1471
|
+
useEffect3(() => {
|
|
1472
|
+
if (!open) return;
|
|
1473
|
+
const handler = (e) => {
|
|
1474
|
+
const target = e.target;
|
|
1475
|
+
if (dropdownRef.current && !dropdownRef.current.contains(target) && anchorRef.current && !anchorRef.current.contains(target)) {
|
|
1476
|
+
onClose();
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
document.addEventListener("mousedown", handler);
|
|
1480
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
1481
|
+
}, [open, onClose, anchorRef]);
|
|
1482
|
+
useEffect3(() => {
|
|
1483
|
+
if (!open) return;
|
|
1484
|
+
const handler = (e) => {
|
|
1485
|
+
if (e.key === "Escape") onClose();
|
|
1486
|
+
};
|
|
1487
|
+
document.addEventListener("keydown", handler);
|
|
1488
|
+
return () => document.removeEventListener("keydown", handler);
|
|
1489
|
+
}, [open, onClose]);
|
|
1490
|
+
if (!open) return null;
|
|
1491
|
+
return createPortal(
|
|
1492
|
+
/* @__PURE__ */ jsx6(
|
|
1493
|
+
"div",
|
|
1494
|
+
{
|
|
1495
|
+
ref: dropdownRef,
|
|
1496
|
+
className: "apteva-widget",
|
|
1497
|
+
style: {
|
|
1498
|
+
position: "absolute",
|
|
1499
|
+
top: pos.top,
|
|
1500
|
+
left: pos.left,
|
|
1501
|
+
width: width === "match" ? pos.width : void 0,
|
|
1502
|
+
zIndex: 99999
|
|
1503
|
+
},
|
|
1504
|
+
children
|
|
1505
|
+
}
|
|
1506
|
+
),
|
|
1507
|
+
document.body
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
function CustomSelect({
|
|
1511
|
+
name,
|
|
1512
|
+
value,
|
|
1513
|
+
options,
|
|
1514
|
+
placeholder,
|
|
1515
|
+
required,
|
|
1516
|
+
onChange
|
|
1517
|
+
}) {
|
|
1518
|
+
const [open, setOpen] = useState3(false);
|
|
1519
|
+
const triggerRef = useRef3(null);
|
|
1520
|
+
const selected = options?.find((o) => o.value === value);
|
|
1521
|
+
const close = useCallback(() => setOpen(false), []);
|
|
1522
|
+
return /* @__PURE__ */ jsxs4("div", { className: "apteva-select relative", children: [
|
|
1523
|
+
/* @__PURE__ */ jsxs4(
|
|
1524
|
+
"select",
|
|
1525
|
+
{
|
|
1526
|
+
name,
|
|
1527
|
+
value,
|
|
1528
|
+
required,
|
|
1529
|
+
onChange: () => {
|
|
1530
|
+
},
|
|
1531
|
+
tabIndex: -1,
|
|
1532
|
+
className: "absolute inset-0 opacity-0 pointer-events-none",
|
|
1533
|
+
"aria-hidden": true,
|
|
1534
|
+
children: [
|
|
1535
|
+
/* @__PURE__ */ jsx6("option", { value: "" }),
|
|
1536
|
+
options?.map((o) => /* @__PURE__ */ jsx6("option", { value: o.value, children: o.label }, o.value))
|
|
1537
|
+
]
|
|
1538
|
+
}
|
|
1539
|
+
),
|
|
1540
|
+
/* @__PURE__ */ jsxs4(
|
|
1541
|
+
"button",
|
|
1542
|
+
{
|
|
1543
|
+
ref: triggerRef,
|
|
1544
|
+
type: "button",
|
|
1545
|
+
onClick: () => setOpen(!open),
|
|
1546
|
+
className: "apteva-select-trigger w-full flex items-center justify-between px-3 py-2 rounded-lg border transition-colors text-left",
|
|
1547
|
+
children: [
|
|
1548
|
+
/* @__PURE__ */ jsx6("span", { className: selected ? "apteva-select-value" : "apteva-select-placeholder", children: selected ? selected.label : placeholder || "Select..." }),
|
|
1549
|
+
/* @__PURE__ */ jsx6(
|
|
1550
|
+
"svg",
|
|
1551
|
+
{
|
|
1552
|
+
className: `apteva-select-chevron w-4 h-4 flex-shrink-0 transition-transform ${open ? "rotate-180" : ""}`,
|
|
1553
|
+
fill: "none",
|
|
1554
|
+
stroke: "currentColor",
|
|
1555
|
+
viewBox: "0 0 24 24",
|
|
1556
|
+
children: /* @__PURE__ */ jsx6("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
|
|
1557
|
+
}
|
|
1558
|
+
)
|
|
1559
|
+
]
|
|
1560
|
+
}
|
|
1561
|
+
),
|
|
1562
|
+
/* @__PURE__ */ jsx6(PortalDropdown, { anchorRef: triggerRef, open, onClose: close, width: "match", children: /* @__PURE__ */ jsx6("div", { className: "apteva-select-dropdown rounded-lg border shadow-lg overflow-hidden", children: /* @__PURE__ */ jsxs4("div", { className: "max-h-48 overflow-y-auto py-1", children: [
|
|
1563
|
+
options?.map((opt) => /* @__PURE__ */ jsx6(
|
|
1564
|
+
"button",
|
|
1565
|
+
{
|
|
1566
|
+
type: "button",
|
|
1567
|
+
onClick: () => {
|
|
1568
|
+
onChange(opt.value);
|
|
1569
|
+
close();
|
|
1570
|
+
},
|
|
1571
|
+
className: `apteva-select-option w-full text-left px-3 py-2 text-sm transition-colors ${opt.value === value ? "apteva-select-option-active" : ""}`,
|
|
1572
|
+
children: opt.label
|
|
1573
|
+
},
|
|
1574
|
+
opt.value
|
|
1575
|
+
)),
|
|
1576
|
+
(!options || options.length === 0) && /* @__PURE__ */ jsx6("div", { className: "px-3 py-2 text-sm apteva-select-placeholder", children: "No options" })
|
|
1577
|
+
] }) }) })
|
|
1578
|
+
] });
|
|
1579
|
+
}
|
|
1580
|
+
function CustomDatePicker({
|
|
1581
|
+
name,
|
|
1582
|
+
value,
|
|
1583
|
+
placeholder,
|
|
1584
|
+
required,
|
|
1585
|
+
onChange
|
|
1586
|
+
}) {
|
|
1587
|
+
const [open, setOpen] = useState3(false);
|
|
1588
|
+
const triggerRef = useRef3(null);
|
|
1589
|
+
const close = useCallback(() => setOpen(false), []);
|
|
1590
|
+
const parseDate = (v) => {
|
|
1591
|
+
if (v) {
|
|
1592
|
+
const [y, m, d] = v.split("-").map(Number);
|
|
1593
|
+
return { year: y, month: m - 1, day: d };
|
|
1594
|
+
}
|
|
1595
|
+
const now = /* @__PURE__ */ new Date();
|
|
1596
|
+
return { year: now.getFullYear(), month: now.getMonth(), day: 0 };
|
|
1597
|
+
};
|
|
1598
|
+
const parsed = parseDate(value);
|
|
1599
|
+
const [viewYear, setViewYear] = useState3(parsed.year);
|
|
1600
|
+
const [viewMonth, setViewMonth] = useState3(parsed.month);
|
|
1601
|
+
useEffect3(() => {
|
|
1602
|
+
if (value) {
|
|
1603
|
+
const p = parseDate(value);
|
|
1604
|
+
setViewYear(p.year);
|
|
1605
|
+
setViewMonth(p.month);
|
|
1606
|
+
}
|
|
1607
|
+
}, [value]);
|
|
1608
|
+
const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate();
|
|
1609
|
+
const firstDayOfWeek = new Date(viewYear, viewMonth, 1).getDay();
|
|
1610
|
+
const startOffset = (firstDayOfWeek + 6) % 7;
|
|
1611
|
+
const prevMonth = () => {
|
|
1612
|
+
if (viewMonth === 0) {
|
|
1613
|
+
setViewMonth(11);
|
|
1614
|
+
setViewYear(viewYear - 1);
|
|
1615
|
+
} else setViewMonth(viewMonth - 1);
|
|
1616
|
+
};
|
|
1617
|
+
const nextMonth = () => {
|
|
1618
|
+
if (viewMonth === 11) {
|
|
1619
|
+
setViewMonth(0);
|
|
1620
|
+
setViewYear(viewYear + 1);
|
|
1621
|
+
} else setViewMonth(viewMonth + 1);
|
|
1622
|
+
};
|
|
1623
|
+
const selectDay = (day) => {
|
|
1624
|
+
const m = String(viewMonth + 1).padStart(2, "0");
|
|
1625
|
+
const d = String(day).padStart(2, "0");
|
|
1626
|
+
onChange(`${viewYear}-${m}-${d}`);
|
|
1627
|
+
close();
|
|
1628
|
+
};
|
|
1629
|
+
const formatDisplay = (v) => {
|
|
1630
|
+
if (!v) return "";
|
|
1631
|
+
const [y, m, d] = v.split("-");
|
|
1632
|
+
return `${d}/${m}/${y}`;
|
|
1633
|
+
};
|
|
1634
|
+
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
1635
|
+
const dayLabels = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
|
|
1636
|
+
const isSelected = (day) => {
|
|
1637
|
+
if (!value) return false;
|
|
1638
|
+
const p = parseDate(value);
|
|
1639
|
+
return p.year === viewYear && p.month === viewMonth && p.day === day;
|
|
1640
|
+
};
|
|
1641
|
+
const isToday = (day) => {
|
|
1642
|
+
const now = /* @__PURE__ */ new Date();
|
|
1643
|
+
return now.getFullYear() === viewYear && now.getMonth() === viewMonth && now.getDate() === day;
|
|
1644
|
+
};
|
|
1645
|
+
return /* @__PURE__ */ jsxs4("div", { className: "apteva-datepicker relative", children: [
|
|
1646
|
+
/* @__PURE__ */ jsx6(
|
|
1647
|
+
"input",
|
|
1648
|
+
{
|
|
1649
|
+
type: "text",
|
|
1650
|
+
name,
|
|
1651
|
+
value,
|
|
1652
|
+
required,
|
|
1653
|
+
onChange: () => {
|
|
1654
|
+
},
|
|
1655
|
+
tabIndex: -1,
|
|
1656
|
+
className: "absolute inset-0 opacity-0 pointer-events-none",
|
|
1657
|
+
"aria-hidden": true
|
|
1658
|
+
}
|
|
1659
|
+
),
|
|
1660
|
+
/* @__PURE__ */ jsxs4(
|
|
1661
|
+
"button",
|
|
1662
|
+
{
|
|
1663
|
+
ref: triggerRef,
|
|
1664
|
+
type: "button",
|
|
1665
|
+
onClick: () => setOpen(!open),
|
|
1666
|
+
className: "apteva-datepicker-trigger w-full flex items-center justify-between px-3 py-2 rounded-lg border transition-colors text-left",
|
|
1667
|
+
children: [
|
|
1668
|
+
/* @__PURE__ */ jsx6("span", { className: value ? "apteva-datepicker-value" : "apteva-select-placeholder", children: value ? formatDisplay(value) : placeholder || "Select date..." }),
|
|
1669
|
+
/* @__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" }) })
|
|
1670
|
+
]
|
|
1671
|
+
}
|
|
1672
|
+
),
|
|
1673
|
+
/* @__PURE__ */ jsx6(PortalDropdown, { anchorRef: triggerRef, open, onClose: close, width: "auto", children: /* @__PURE__ */ jsxs4("div", { className: "apteva-datepicker-dropdown rounded-lg border shadow-lg overflow-hidden", children: [
|
|
1674
|
+
/* @__PURE__ */ jsxs4("div", { className: "apteva-datepicker-header flex items-center justify-between px-3 py-2", children: [
|
|
1675
|
+
/* @__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" }) }) }),
|
|
1676
|
+
/* @__PURE__ */ jsxs4("span", { className: "apteva-datepicker-title text-sm font-semibold", children: [
|
|
1677
|
+
monthNames[viewMonth],
|
|
1678
|
+
" ",
|
|
1679
|
+
viewYear
|
|
1680
|
+
] }),
|
|
1681
|
+
/* @__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" }) }) })
|
|
1682
|
+
] }),
|
|
1683
|
+
/* @__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)) }),
|
|
1684
|
+
/* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-7 px-2 pb-2", children: [
|
|
1685
|
+
Array.from({ length: startOffset }).map((_, i) => /* @__PURE__ */ jsx6("div", {}, `empty-${i}`)),
|
|
1686
|
+
Array.from({ length: daysInMonth }).map((_, i) => {
|
|
1687
|
+
const day = i + 1;
|
|
1688
|
+
const sel = isSelected(day);
|
|
1689
|
+
const today = isToday(day);
|
|
1690
|
+
return /* @__PURE__ */ jsx6(
|
|
1691
|
+
"button",
|
|
1692
|
+
{
|
|
1693
|
+
type: "button",
|
|
1694
|
+
onClick: () => selectDay(day),
|
|
1695
|
+
className: [
|
|
1696
|
+
"apteva-datepicker-day text-center text-sm py-1 rounded transition-colors",
|
|
1697
|
+
sel ? "apteva-datepicker-day-selected" : "",
|
|
1698
|
+
today && !sel ? "apteva-datepicker-day-today" : ""
|
|
1699
|
+
].join(" "),
|
|
1700
|
+
children: day
|
|
1701
|
+
},
|
|
1702
|
+
day
|
|
1703
|
+
);
|
|
1704
|
+
})
|
|
1705
|
+
] })
|
|
1706
|
+
] }) })
|
|
1707
|
+
] });
|
|
1708
|
+
}
|
|
1443
1709
|
function Form({ widget, onAction }) {
|
|
1444
1710
|
const { title, fields } = widget.props;
|
|
1445
1711
|
const fileInputRefs = useRef3({});
|
|
@@ -1454,9 +1720,9 @@ function Form({ widget, onAction }) {
|
|
|
1454
1720
|
});
|
|
1455
1721
|
return initial;
|
|
1456
1722
|
});
|
|
1457
|
-
const handleChange = (name, value) => {
|
|
1723
|
+
const handleChange = useCallback((name, value) => {
|
|
1458
1724
|
setFormData((prev) => ({ ...prev, [name]: value }));
|
|
1459
|
-
};
|
|
1725
|
+
}, []);
|
|
1460
1726
|
const handleSubmit = (e) => {
|
|
1461
1727
|
e.preventDefault();
|
|
1462
1728
|
if (widget.actions?.[0] && onAction) {
|
|
@@ -1469,12 +1735,11 @@ function Form({ widget, onAction }) {
|
|
|
1469
1735
|
}
|
|
1470
1736
|
};
|
|
1471
1737
|
const renderField = (field) => {
|
|
1472
|
-
const baseInputClass = "w-full px-3 py-2 rounded-lg border transition-colors
|
|
1738
|
+
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
1739
|
switch (field.type) {
|
|
1474
1740
|
case "text":
|
|
1475
1741
|
case "password":
|
|
1476
1742
|
case "number":
|
|
1477
|
-
case "date":
|
|
1478
1743
|
return /* @__PURE__ */ jsx6(
|
|
1479
1744
|
"input",
|
|
1480
1745
|
{
|
|
@@ -1487,6 +1752,17 @@ function Form({ widget, onAction }) {
|
|
|
1487
1752
|
className: baseInputClass
|
|
1488
1753
|
}
|
|
1489
1754
|
);
|
|
1755
|
+
case "date":
|
|
1756
|
+
return /* @__PURE__ */ jsx6(
|
|
1757
|
+
CustomDatePicker,
|
|
1758
|
+
{
|
|
1759
|
+
name: field.name,
|
|
1760
|
+
value: formData[field.name] || "",
|
|
1761
|
+
placeholder: field.placeholder,
|
|
1762
|
+
required: field.required,
|
|
1763
|
+
onChange: (v) => handleChange(field.name, v)
|
|
1764
|
+
}
|
|
1765
|
+
);
|
|
1490
1766
|
case "textarea":
|
|
1491
1767
|
return /* @__PURE__ */ jsx6(
|
|
1492
1768
|
"textarea",
|
|
@@ -1501,22 +1777,19 @@ function Form({ widget, onAction }) {
|
|
|
1501
1777
|
}
|
|
1502
1778
|
);
|
|
1503
1779
|
case "select":
|
|
1504
|
-
return /* @__PURE__ */
|
|
1505
|
-
|
|
1780
|
+
return /* @__PURE__ */ jsx6(
|
|
1781
|
+
CustomSelect,
|
|
1506
1782
|
{
|
|
1507
1783
|
name: field.name,
|
|
1508
1784
|
value: formData[field.name] || "",
|
|
1509
|
-
|
|
1785
|
+
options: field.options,
|
|
1786
|
+
placeholder: field.placeholder,
|
|
1510
1787
|
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
|
-
]
|
|
1788
|
+
onChange: (v) => handleChange(field.name, v)
|
|
1516
1789
|
}
|
|
1517
1790
|
);
|
|
1518
1791
|
case "checkbox":
|
|
1519
|
-
return /* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-2 cursor-pointer", children: [
|
|
1792
|
+
return /* @__PURE__ */ jsxs4("label", { className: "apteva-checkbox flex items-center gap-2 cursor-pointer", children: [
|
|
1520
1793
|
/* @__PURE__ */ jsx6(
|
|
1521
1794
|
"input",
|
|
1522
1795
|
{
|
|
@@ -1524,10 +1797,10 @@ function Form({ widget, onAction }) {
|
|
|
1524
1797
|
name: field.name,
|
|
1525
1798
|
checked: formData[field.name] || false,
|
|
1526
1799
|
onChange: (e) => handleChange(field.name, e.target.checked),
|
|
1527
|
-
className: "w-4 h-4 rounded
|
|
1800
|
+
className: "w-4 h-4 rounded"
|
|
1528
1801
|
}
|
|
1529
1802
|
),
|
|
1530
|
-
/* @__PURE__ */ jsx6("span", {
|
|
1803
|
+
/* @__PURE__ */ jsx6("span", { children: field.label })
|
|
1531
1804
|
] });
|
|
1532
1805
|
case "file": {
|
|
1533
1806
|
const files = formData[field.name] || [];
|
|
@@ -1561,18 +1834,18 @@ function Form({ widget, onAction }) {
|
|
|
1561
1834
|
{
|
|
1562
1835
|
type: "button",
|
|
1563
1836
|
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
|
|
1837
|
+
className: "apteva-file-drop w-full px-3 py-3 rounded-lg border-2 border-dashed transition-colors cursor-pointer !text-sm",
|
|
1565
1838
|
children: field.placeholder || "Click to add files"
|
|
1566
1839
|
}
|
|
1567
1840
|
),
|
|
1568
1841
|
files.length > 0 && /* @__PURE__ */ jsx6("ul", { className: "space-y-1", children: files.map((file, idx) => /* @__PURE__ */ jsxs4(
|
|
1569
1842
|
"li",
|
|
1570
1843
|
{
|
|
1571
|
-
className: "apteva-file-item-row flex items-center justify-between px-2 py-1.5 rounded-lg
|
|
1844
|
+
className: "apteva-file-item-row flex items-center justify-between px-2 py-1.5 rounded-lg !text-sm",
|
|
1572
1845
|
children: [
|
|
1573
|
-
/* @__PURE__ */ jsxs4("span", { className: "
|
|
1846
|
+
/* @__PURE__ */ jsxs4("span", { className: "truncate mr-2", children: [
|
|
1574
1847
|
file.name,
|
|
1575
|
-
/* @__PURE__ */ jsxs4("span", { className: "
|
|
1848
|
+
/* @__PURE__ */ jsxs4("span", { className: "ml-1", style: { opacity: 0.6 }, children: [
|
|
1576
1849
|
"(",
|
|
1577
1850
|
(file.size / 1024).toFixed(0),
|
|
1578
1851
|
" KB)"
|
|
@@ -1583,7 +1856,7 @@ function Form({ widget, onAction }) {
|
|
|
1583
1856
|
{
|
|
1584
1857
|
type: "button",
|
|
1585
1858
|
onClick: () => handleChange(field.name, files.filter((_, i) => i !== idx)),
|
|
1586
|
-
className: "apteva-file-remove-btn
|
|
1859
|
+
className: "apteva-file-remove-btn transition-colors flex-shrink-0",
|
|
1587
1860
|
children: "\u2715"
|
|
1588
1861
|
}
|
|
1589
1862
|
)
|
|
@@ -1598,13 +1871,13 @@ function Form({ widget, onAction }) {
|
|
|
1598
1871
|
}
|
|
1599
1872
|
};
|
|
1600
1873
|
const submitAction = widget.actions?.find((a) => a.type === "submit") || widget.actions?.[0];
|
|
1601
|
-
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "border
|
|
1874
|
+
return /* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit, className: "border rounded-xl overflow-hidden", children: [
|
|
1602
1875
|
/* @__PURE__ */ jsxs4("div", { className: "p-4", children: [
|
|
1603
|
-
title && /* @__PURE__ */ jsx6("h3", { className: "!text-lg font-semibold
|
|
1876
|
+
title && /* @__PURE__ */ jsx6("h3", { className: "!text-lg font-semibold mb-4", children: title }),
|
|
1604
1877
|
/* @__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
|
|
1878
|
+
field.type !== "checkbox" && /* @__PURE__ */ jsxs4("label", { className: "apteva-field-label block !text-sm font-medium", children: [
|
|
1606
1879
|
field.label,
|
|
1607
|
-
field.required && /* @__PURE__ */ jsx6("span", {
|
|
1880
|
+
field.required && /* @__PURE__ */ jsx6("span", { style: { color: "var(--aw-danger)" }, className: "ml-1", children: "*" })
|
|
1608
1881
|
] }),
|
|
1609
1882
|
renderField(field)
|
|
1610
1883
|
] }, field.name)) })
|
|
@@ -1613,7 +1886,7 @@ function Form({ widget, onAction }) {
|
|
|
1613
1886
|
"button",
|
|
1614
1887
|
{
|
|
1615
1888
|
type: "submit",
|
|
1616
|
-
className: "px-3 py-1.5 !text-sm rounded-lg font-medium transition-colors
|
|
1889
|
+
className: "px-3 py-1.5 !text-sm rounded-lg font-medium transition-colors",
|
|
1617
1890
|
children: submitAction.label || "Submit"
|
|
1618
1891
|
}
|
|
1619
1892
|
) })
|
|
@@ -1983,7 +2256,7 @@ function Spacer({ widget }) {
|
|
|
1983
2256
|
}
|
|
1984
2257
|
|
|
1985
2258
|
// src/components/Widgets/widget-library/LiveView.tsx
|
|
1986
|
-
import { useState as useState4, useCallback, useRef as useRef4, useEffect as
|
|
2259
|
+
import { useState as useState4, useCallback as useCallback2, useRef as useRef4, useEffect as useEffect4 } from "react";
|
|
1987
2260
|
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1988
2261
|
function LiveView({ widget }) {
|
|
1989
2262
|
const { src, title, height, aspectRatio = "16/9", allowFullscreen = true, sandbox, allow, refreshInterval, showToolbar = true } = widget.props;
|
|
@@ -1991,18 +2264,18 @@ function LiveView({ widget }) {
|
|
|
1991
2264
|
const [isLoading, setIsLoading] = useState4(true);
|
|
1992
2265
|
const [hasError, setHasError] = useState4(false);
|
|
1993
2266
|
const [refreshKey, setRefreshKey] = useState4(0);
|
|
1994
|
-
const handleRefresh =
|
|
2267
|
+
const handleRefresh = useCallback2(() => {
|
|
1995
2268
|
setIsLoading(true);
|
|
1996
2269
|
setHasError(false);
|
|
1997
2270
|
setRefreshKey((k) => k + 1);
|
|
1998
2271
|
}, []);
|
|
1999
|
-
const handleFullscreen =
|
|
2272
|
+
const handleFullscreen = useCallback2(() => {
|
|
2000
2273
|
iframeRef.current?.requestFullscreen?.();
|
|
2001
2274
|
}, []);
|
|
2002
|
-
const handleOpenExternal =
|
|
2275
|
+
const handleOpenExternal = useCallback2(() => {
|
|
2003
2276
|
window.open(src, "_blank", "noopener,noreferrer");
|
|
2004
2277
|
}, [src]);
|
|
2005
|
-
|
|
2278
|
+
useEffect4(() => {
|
|
2006
2279
|
if (!refreshInterval || refreshInterval <= 0) return;
|
|
2007
2280
|
const interval = setInterval(handleRefresh, refreshInterval * 1e3);
|
|
2008
2281
|
return () => clearInterval(interval);
|
|
@@ -2150,7 +2423,7 @@ function Widgets({
|
|
|
2150
2423
|
columns = 3,
|
|
2151
2424
|
className
|
|
2152
2425
|
}) {
|
|
2153
|
-
|
|
2426
|
+
useEffect5(() => {
|
|
2154
2427
|
widgets.forEach((widget) => {
|
|
2155
2428
|
onWidgetMount?.(widget.id);
|
|
2156
2429
|
});
|
|
@@ -2574,7 +2847,7 @@ function Message({ message, onAction, enableWidgets, onWidgetRender, persistentW
|
|
|
2574
2847
|
const parsed = parseWidgetsFromText(message.content);
|
|
2575
2848
|
return parsed.segments.filter((seg) => seg.type === "widget" && !!seg.widget).map((seg) => seg.widget);
|
|
2576
2849
|
}, [enableWidgets, isUser, message.content]);
|
|
2577
|
-
|
|
2850
|
+
useEffect6(() => {
|
|
2578
2851
|
if (onWidgetRender && message.widgets) {
|
|
2579
2852
|
for (const widget of message.widgets) {
|
|
2580
2853
|
if (!reportedWidgetsRef.current.has(widget.id)) {
|
|
@@ -2584,7 +2857,7 @@ function Message({ message, onAction, enableWidgets, onWidgetRender, persistentW
|
|
|
2584
2857
|
}
|
|
2585
2858
|
}
|
|
2586
2859
|
}, [message.widgets, onWidgetRender]);
|
|
2587
|
-
|
|
2860
|
+
useEffect6(() => {
|
|
2588
2861
|
if (onWidgetRender && parsedWidgets.length > 0) {
|
|
2589
2862
|
for (const widget of parsedWidgets) {
|
|
2590
2863
|
if (!reportedWidgetsRef.current.has(widget.id)) {
|
|
@@ -3038,7 +3311,7 @@ function MessageList({
|
|
|
3038
3311
|
isNearBottomRef.current = scrollHeight - scrollTop - clientHeight < 100;
|
|
3039
3312
|
}
|
|
3040
3313
|
};
|
|
3041
|
-
|
|
3314
|
+
useEffect7(() => {
|
|
3042
3315
|
if (listRef.current && isNearBottomRef.current) {
|
|
3043
3316
|
const currentScrollHeight = listRef.current.scrollHeight;
|
|
3044
3317
|
if (currentScrollHeight !== lastScrollHeightRef.current) {
|
|
@@ -3893,7 +4166,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
3893
4166
|
const [showSettingsMenu, setShowSettingsMenu] = useState9(false);
|
|
3894
4167
|
const fileInputRef = useRef9(null);
|
|
3895
4168
|
const [persistentWidgets, setPersistentWidgets] = useState9(/* @__PURE__ */ new Map());
|
|
3896
|
-
const updatePersistentWidgets =
|
|
4169
|
+
const updatePersistentWidgets = useCallback3((msgs) => {
|
|
3897
4170
|
setPersistentWidgets((prev) => {
|
|
3898
4171
|
const next = new Map(prev);
|
|
3899
4172
|
let changed = false;
|
|
@@ -3911,7 +4184,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
3911
4184
|
return changed ? next : prev;
|
|
3912
4185
|
});
|
|
3913
4186
|
}, []);
|
|
3914
|
-
|
|
4187
|
+
useEffect8(() => {
|
|
3915
4188
|
updatePersistentWidgets(messages);
|
|
3916
4189
|
}, [messages, updatePersistentWidgets]);
|
|
3917
4190
|
const persistentWidgetList = useMemo2(() => Array.from(persistentWidgets.values()), [persistentWidgets]);
|
|
@@ -3937,7 +4210,7 @@ var Chat = forwardRef(function Chat2({
|
|
|
3937
4210
|
return context ? `${context}
|
|
3938
4211
|
${widgetContext}` : widgetContext;
|
|
3939
4212
|
}, [context, enableWidgets, availableWidgets, compactWidgetContext]);
|
|
3940
|
-
|
|
4213
|
+
useEffect8(() => {
|
|
3941
4214
|
if (apiUrl || apiKey) {
|
|
3942
4215
|
aptevaClient.configure({
|
|
3943
4216
|
...apiUrl && { apiUrl },
|
|
@@ -3945,15 +4218,15 @@ ${widgetContext}` : widgetContext;
|
|
|
3945
4218
|
});
|
|
3946
4219
|
}
|
|
3947
4220
|
}, [apiUrl, apiKey]);
|
|
3948
|
-
|
|
4221
|
+
useEffect8(() => {
|
|
3949
4222
|
if (threadId) {
|
|
3950
4223
|
onThreadChange?.(threadId);
|
|
3951
4224
|
}
|
|
3952
4225
|
}, [threadId, onThreadChange]);
|
|
3953
|
-
|
|
4226
|
+
useEffect8(() => {
|
|
3954
4227
|
setInternalPlanMode(planMode);
|
|
3955
4228
|
}, [planMode]);
|
|
3956
|
-
|
|
4229
|
+
useEffect8(() => {
|
|
3957
4230
|
const handleClickOutside = (event) => {
|
|
3958
4231
|
const target = event.target;
|
|
3959
4232
|
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
@@ -3973,7 +4246,7 @@ ${widgetContext}` : widgetContext;
|
|
|
3973
4246
|
}
|
|
3974
4247
|
};
|
|
3975
4248
|
const defaultPlaceholder = mode === "chat" ? "Type a message..." : "Enter your command...";
|
|
3976
|
-
const handleWidgetAction =
|
|
4249
|
+
const handleWidgetAction = useCallback3((action) => {
|
|
3977
4250
|
onAction?.(action);
|
|
3978
4251
|
if (action.type === "submit" && action.payload?.formData) {
|
|
3979
4252
|
const formData = action.payload.formData;
|
|
@@ -4574,7 +4847,7 @@ import { useState as useState10 } from "react";
|
|
|
4574
4847
|
import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4575
4848
|
|
|
4576
4849
|
// src/components/Command/Command.tsx
|
|
4577
|
-
import React, { useState as useState11, useEffect as
|
|
4850
|
+
import React, { useState as useState11, useEffect as useEffect9 } from "react";
|
|
4578
4851
|
import { Fragment as Fragment7, jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
4579
4852
|
function Command({
|
|
4580
4853
|
agentId,
|
|
@@ -4615,15 +4888,15 @@ function Command({
|
|
|
4615
4888
|
const [showSettingsMenu, setShowSettingsMenu] = useState11(false);
|
|
4616
4889
|
const [internalPlanMode, setInternalPlanMode] = useState11(planMode);
|
|
4617
4890
|
const fileInputRef = React.useRef(null);
|
|
4618
|
-
|
|
4891
|
+
useEffect9(() => {
|
|
4619
4892
|
if (autoExecute && state === "idle" && command) {
|
|
4620
4893
|
executeCommand();
|
|
4621
4894
|
}
|
|
4622
4895
|
}, [autoExecute]);
|
|
4623
|
-
|
|
4896
|
+
useEffect9(() => {
|
|
4624
4897
|
setInternalPlanMode(planMode);
|
|
4625
4898
|
}, [planMode]);
|
|
4626
|
-
|
|
4899
|
+
useEffect9(() => {
|
|
4627
4900
|
const handleClickOutside = (event) => {
|
|
4628
4901
|
const target = event.target;
|
|
4629
4902
|
if (showSettingsMenu && !target.closest(".settings-menu-container")) {
|
|
@@ -5656,7 +5929,7 @@ function Prompt({
|
|
|
5656
5929
|
}
|
|
5657
5930
|
|
|
5658
5931
|
// src/components/Stream/Stream.tsx
|
|
5659
|
-
import { useState as useState13, useEffect as
|
|
5932
|
+
import { useState as useState13, useEffect as useEffect10 } from "react";
|
|
5660
5933
|
import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
5661
5934
|
function Stream({
|
|
5662
5935
|
agentId,
|
|
@@ -5676,7 +5949,7 @@ function Stream({
|
|
|
5676
5949
|
const [text, setText] = useState13("");
|
|
5677
5950
|
const [isStreaming, setIsStreaming] = useState13(false);
|
|
5678
5951
|
const [isComplete, setIsComplete] = useState13(false);
|
|
5679
|
-
|
|
5952
|
+
useEffect10(() => {
|
|
5680
5953
|
if (autoStart && !isStreaming && !isComplete) {
|
|
5681
5954
|
startStreaming();
|
|
5682
5955
|
}
|
|
@@ -5947,7 +6220,7 @@ function Threads({
|
|
|
5947
6220
|
}
|
|
5948
6221
|
|
|
5949
6222
|
// src/components/AutoInterface/AutoInterface.tsx
|
|
5950
|
-
import { useState as useState16, useRef as useRef10, useCallback as
|
|
6223
|
+
import { useState as useState16, useRef as useRef10, useCallback as useCallback4, useEffect as useEffect11 } from "react";
|
|
5951
6224
|
|
|
5952
6225
|
// src/components/AutoInterface/LayoutRenderer.tsx
|
|
5953
6226
|
import { useState as useState15 } from "react";
|
|
@@ -6225,11 +6498,11 @@ function AutoInterface({
|
|
|
6225
6498
|
generateInterfaceContext(),
|
|
6226
6499
|
context || ""
|
|
6227
6500
|
].filter(Boolean).join("\n\n");
|
|
6228
|
-
const updateInterface =
|
|
6501
|
+
const updateInterface = useCallback4((newSpec) => {
|
|
6229
6502
|
setInterfaceSpec(newSpec);
|
|
6230
6503
|
onInterfaceChange?.(newSpec);
|
|
6231
6504
|
}, [onInterfaceChange]);
|
|
6232
|
-
const handleAction =
|
|
6505
|
+
const handleAction = useCallback4((action) => {
|
|
6233
6506
|
onAction?.(action);
|
|
6234
6507
|
if (chatRef.current) {
|
|
6235
6508
|
chatRef.current.sendMessage(
|
|
@@ -6237,7 +6510,7 @@ function AutoInterface({
|
|
|
6237
6510
|
);
|
|
6238
6511
|
}
|
|
6239
6512
|
}, [onAction]);
|
|
6240
|
-
const handleMessageComplete =
|
|
6513
|
+
const handleMessageComplete = useCallback4((result) => {
|
|
6241
6514
|
if (!result?.data) return;
|
|
6242
6515
|
const text = typeof result.data === "string" ? result.data : result.data.message || "";
|
|
6243
6516
|
console.log("[AutoInterface] Chat message complete, text (" + text.length + " chars):", text.substring(0, 300));
|
|
@@ -6258,7 +6531,7 @@ function AutoInterface({
|
|
|
6258
6531
|
}
|
|
6259
6532
|
setIsGenerating(false);
|
|
6260
6533
|
}, [interfaceSpec, updateInterface]);
|
|
6261
|
-
|
|
6534
|
+
useEffect11(() => {
|
|
6262
6535
|
if (!initialPrompt || initialInterface || useMock) return;
|
|
6263
6536
|
if (!apiUrl) return;
|
|
6264
6537
|
let cancelled = false;
|
|
@@ -6383,29 +6656,29 @@ function getThemeScript() {
|
|
|
6383
6656
|
}
|
|
6384
6657
|
|
|
6385
6658
|
// src/hooks/useInterfaceState.ts
|
|
6386
|
-
import { useState as useState17, useCallback as
|
|
6659
|
+
import { useState as useState17, useCallback as useCallback5 } from "react";
|
|
6387
6660
|
function useInterfaceState(initialSpec) {
|
|
6388
6661
|
const [spec, setSpec] = useState17(initialSpec || null);
|
|
6389
6662
|
const [isStreaming, setIsStreaming] = useState17(false);
|
|
6390
|
-
const setInterface =
|
|
6663
|
+
const setInterface = useCallback5((newSpec) => {
|
|
6391
6664
|
setSpec(newSpec);
|
|
6392
6665
|
}, []);
|
|
6393
|
-
const clearInterface =
|
|
6666
|
+
const clearInterface = useCallback5(() => {
|
|
6394
6667
|
setSpec(null);
|
|
6395
6668
|
}, []);
|
|
6396
|
-
const applyInterfaceUpdate =
|
|
6669
|
+
const applyInterfaceUpdate = useCallback5((update) => {
|
|
6397
6670
|
setSpec((prev) => {
|
|
6398
6671
|
if (!prev) return prev;
|
|
6399
6672
|
return applyUpdate(prev, update);
|
|
6400
6673
|
});
|
|
6401
6674
|
}, []);
|
|
6402
|
-
const applyInterfaceUpdates =
|
|
6675
|
+
const applyInterfaceUpdates = useCallback5((updates) => {
|
|
6403
6676
|
setSpec((prev) => {
|
|
6404
6677
|
if (!prev) return prev;
|
|
6405
6678
|
return applyUpdates(prev, updates);
|
|
6406
6679
|
});
|
|
6407
6680
|
}, []);
|
|
6408
|
-
const getNode =
|
|
6681
|
+
const getNode = useCallback5((id) => {
|
|
6409
6682
|
if (!spec) return null;
|
|
6410
6683
|
return findNode(spec.root, id);
|
|
6411
6684
|
}, [spec]);
|
|
@@ -6422,7 +6695,7 @@ function useInterfaceState(initialSpec) {
|
|
|
6422
6695
|
}
|
|
6423
6696
|
|
|
6424
6697
|
// src/hooks/useInterfaceAI.ts
|
|
6425
|
-
import { useCallback as
|
|
6698
|
+
import { useCallback as useCallback6, useRef as useRef11 } from "react";
|
|
6426
6699
|
function useInterfaceAI({
|
|
6427
6700
|
agentId,
|
|
6428
6701
|
apiUrl,
|
|
@@ -6442,7 +6715,7 @@ function useInterfaceAI({
|
|
|
6442
6715
|
...apiKey && { apiKey }
|
|
6443
6716
|
});
|
|
6444
6717
|
}
|
|
6445
|
-
const sendMessage =
|
|
6718
|
+
const sendMessage = useCallback6(async (message) => {
|
|
6446
6719
|
accumulatedTextRef.current = "";
|
|
6447
6720
|
onStreamStart?.();
|
|
6448
6721
|
const systemPrompt = [
|