@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.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 useEffect7, useRef as useRef9, useMemo as useMemo2, useCallback as useCallback2, forwardRef, useImperativeHandle } from "react";
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 useEffect6, useRef as useRef6 } from "react";
10
+ import { useEffect as useEffect7, useRef as useRef6 } from "react";
11
11
 
12
12
  // src/components/Chat/Message.tsx
13
- import { useEffect as useEffect5, useRef as useRef5, useMemo } from "react";
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 useEffect4 } from "react";
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 border-neutral-200 dark:border-neutral-600 bg-neutral-50 dark:bg-neutral-800 !text-neutral-900 dark:!text-neutral-100 placeholder-neutral-400 dark:placeholder-neutral-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent";
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__ */ jsxs4(
1505
- "select",
1725
+ return /* @__PURE__ */ jsx6(
1726
+ CustomSelect,
1506
1727
  {
1507
1728
  name: field.name,
1508
1729
  value: formData[field.name] || "",
1509
- onChange: (e) => handleChange(field.name, e.target.value),
1730
+ options: field.options,
1731
+ placeholder: field.placeholder,
1510
1732
  required: field.required,
1511
- className: baseInputClass,
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 border-neutral-300 dark:border-neutral-600 text-blue-500 focus:ring-blue-500"
1745
+ className: "w-4 h-4 rounded"
1528
1746
  }
1529
1747
  ),
1530
- /* @__PURE__ */ jsx6("span", { className: "!text-neutral-700 dark:!text-neutral-300", children: field.label })
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 border-neutral-300 dark:border-neutral-600 bg-neutral-50 dark:bg-neutral-800 !text-neutral-500 dark:!text-neutral-400 hover:border-blue-400 hover:!text-blue-500 !text-sm",
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 bg-neutral-50 dark:bg-neutral-800 !text-sm",
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: "!text-neutral-700 dark:!text-neutral-300 truncate mr-2", children: [
1791
+ /* @__PURE__ */ jsxs4("span", { className: "truncate mr-2", children: [
1574
1792
  file.name,
1575
- /* @__PURE__ */ jsxs4("span", { className: "!text-neutral-400 ml-1", children: [
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 !text-neutral-400 hover:!text-red-500 transition-colors flex-shrink-0",
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 border-neutral-200 dark:border-neutral-700 rounded-xl bg-white dark:bg-neutral-900 overflow-hidden", children: [
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 !text-neutral-900 dark:!text-white mb-4", children: title }),
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 !text-neutral-600 dark:!text-neutral-400", children: [
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", { className: "text-red-500 ml-1", children: "*" })
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 bg-blue-500 !text-white hover:bg-blue-600",
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 useEffect3 } from "react";
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 = useCallback(() => {
2212
+ const handleRefresh = useCallback2(() => {
1995
2213
  setIsLoading(true);
1996
2214
  setHasError(false);
1997
2215
  setRefreshKey((k) => k + 1);
1998
2216
  }, []);
1999
- const handleFullscreen = useCallback(() => {
2217
+ const handleFullscreen = useCallback2(() => {
2000
2218
  iframeRef.current?.requestFullscreen?.();
2001
2219
  }, []);
2002
- const handleOpenExternal = useCallback(() => {
2220
+ const handleOpenExternal = useCallback2(() => {
2003
2221
  window.open(src, "_blank", "noopener,noreferrer");
2004
2222
  }, [src]);
2005
- useEffect3(() => {
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
- useEffect4(() => {
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
- useEffect5(() => {
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
- useEffect5(() => {
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
- useEffect6(() => {
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 = useCallback2((msgs) => {
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
- useEffect7(() => {
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
- useEffect7(() => {
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
- useEffect7(() => {
4166
+ useEffect8(() => {
3949
4167
  if (threadId) {
3950
4168
  onThreadChange?.(threadId);
3951
4169
  }
3952
4170
  }, [threadId, onThreadChange]);
3953
- useEffect7(() => {
4171
+ useEffect8(() => {
3954
4172
  setInternalPlanMode(planMode);
3955
4173
  }, [planMode]);
3956
- useEffect7(() => {
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 = useCallback2((action) => {
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 useEffect8 } from "react";
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
- useEffect8(() => {
4836
+ useEffect9(() => {
4619
4837
  if (autoExecute && state === "idle" && command) {
4620
4838
  executeCommand();
4621
4839
  }
4622
4840
  }, [autoExecute]);
4623
- useEffect8(() => {
4841
+ useEffect9(() => {
4624
4842
  setInternalPlanMode(planMode);
4625
4843
  }, [planMode]);
4626
- useEffect8(() => {
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 useEffect9 } from "react";
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
- useEffect9(() => {
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 useCallback3, useEffect as useEffect10 } from "react";
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 = useCallback3((newSpec) => {
6446
+ const updateInterface = useCallback4((newSpec) => {
6229
6447
  setInterfaceSpec(newSpec);
6230
6448
  onInterfaceChange?.(newSpec);
6231
6449
  }, [onInterfaceChange]);
6232
- const handleAction = useCallback3((action) => {
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 = useCallback3((result) => {
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
- useEffect10(() => {
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 useCallback4 } from "react";
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 = useCallback4((newSpec) => {
6608
+ const setInterface = useCallback5((newSpec) => {
6391
6609
  setSpec(newSpec);
6392
6610
  }, []);
6393
- const clearInterface = useCallback4(() => {
6611
+ const clearInterface = useCallback5(() => {
6394
6612
  setSpec(null);
6395
6613
  }, []);
6396
- const applyInterfaceUpdate = useCallback4((update) => {
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 = useCallback4((updates) => {
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 = useCallback4((id) => {
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 useCallback5, useRef as useRef11 } from "react";
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 = useCallback5(async (message) => {
6663
+ const sendMessage = useCallback6(async (message) => {
6446
6664
  accumulatedTextRef.current = "";
6447
6665
  onStreamStart?.();
6448
6666
  const systemPrompt = [