@reactor-team/js-sdk 1.0.16 → 1.0.18

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.d.mts CHANGED
@@ -169,6 +169,12 @@ interface ReactorViewProps {
169
169
  }
170
170
  declare function ReactorView({ width, height, className, style, videoObjectFit, }: ReactorViewProps): react_jsx_runtime.JSX.Element;
171
171
 
172
+ interface ReactorControllerProps {
173
+ className?: string;
174
+ style?: React.CSSProperties;
175
+ }
176
+ declare function ReactorController({ className, style, }: ReactorControllerProps): react_jsx_runtime.JSX.Element;
177
+
172
178
  interface Props {
173
179
  className?: string;
174
180
  style?: React.CSSProperties;
@@ -192,4 +198,4 @@ declare function useReactor<T>(selector: (state: ReactorStore) => T): T;
192
198
  */
193
199
  declare function useReactorMessage(handler: (message: any) => void): void;
194
200
 
195
- export { type Options, Reactor, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorSessionExpiration, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type ReactorWaitingInfo, WebcamStream, useReactor, useReactorMessage, useReactorStore };
201
+ export { type Options, Reactor, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorSessionExpiration, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type ReactorWaitingInfo, WebcamStream, useReactor, useReactorMessage, useReactorStore };
package/dist/index.d.ts CHANGED
@@ -169,6 +169,12 @@ interface ReactorViewProps {
169
169
  }
170
170
  declare function ReactorView({ width, height, className, style, videoObjectFit, }: ReactorViewProps): react_jsx_runtime.JSX.Element;
171
171
 
172
+ interface ReactorControllerProps {
173
+ className?: string;
174
+ style?: React.CSSProperties;
175
+ }
176
+ declare function ReactorController({ className, style, }: ReactorControllerProps): react_jsx_runtime.JSX.Element;
177
+
172
178
  interface Props {
173
179
  className?: string;
174
180
  style?: React.CSSProperties;
@@ -192,4 +198,4 @@ declare function useReactor<T>(selector: (state: ReactorStore) => T): T;
192
198
  */
193
199
  declare function useReactorMessage(handler: (message: any) => void): void;
194
200
 
195
- export { type Options, Reactor, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorSessionExpiration, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type ReactorWaitingInfo, WebcamStream, useReactor, useReactorMessage, useReactorStore };
201
+ export { type Options, Reactor, ReactorController, type ReactorControllerProps, type ReactorError, type ReactorEvent, ReactorProvider, type ReactorSessionExpiration, type ReactorState$1 as ReactorState, type ReactorStatus, ReactorView, type ReactorViewProps, type ReactorWaitingInfo, WebcamStream, useReactor, useReactorMessage, useReactorStore };
package/dist/index.js CHANGED
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __defProps = Object.defineProperties;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
7
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
8
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
9
+ var __getProtoOf = Object.getPrototypeOf;
8
10
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
11
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
12
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -44,6 +46,14 @@ var __copyProps = (to, from, except, desc) => {
44
46
  }
45
47
  return to;
46
48
  };
49
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
50
+ // If the importer is in node compatibility mode or this is not an ESM
51
+ // file that has been converted to a CommonJS file using a Babel-
52
+ // compatible transform (i.e. "__esModule" has not been set), then set
53
+ // "default" to the CommonJS "module.exports" for node compatibility.
54
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
55
+ mod
56
+ ));
47
57
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
48
58
  var __async = (__this, __arguments, generator) => {
49
59
  return new Promise((resolve, reject) => {
@@ -70,6 +80,7 @@ var __async = (__this, __arguments, generator) => {
70
80
  var index_exports = {};
71
81
  __export(index_exports, {
72
82
  Reactor: () => Reactor,
83
+ ReactorController: () => ReactorController,
73
84
  ReactorProvider: () => ReactorProvider,
74
85
  ReactorView: () => ReactorView,
75
86
  WebcamStream: () => WebcamStream,
@@ -1321,9 +1332,468 @@ function ReactorView({
1321
1332
  );
1322
1333
  }
1323
1334
 
1324
- // src/react/WebcamStream.tsx
1325
- var import_react6 = require("react");
1335
+ // src/react/ReactorController.tsx
1336
+ var import_react6 = __toESM(require("react"));
1326
1337
  var import_jsx_runtime3 = require("react/jsx-runtime");
1338
+ function ReactorController({
1339
+ className,
1340
+ style
1341
+ }) {
1342
+ const { sendMessage, status } = useReactor((state) => ({
1343
+ sendMessage: state.sendMessage,
1344
+ status: state.status
1345
+ }));
1346
+ const [commands, setCommands] = (0, import_react6.useState)({});
1347
+ const [formValues, setFormValues] = (0, import_react6.useState)({});
1348
+ const [expandedCommands, setExpandedCommands] = (0, import_react6.useState)({});
1349
+ import_react6.default.useEffect(() => {
1350
+ if (status === "disconnected") {
1351
+ setCommands({});
1352
+ setFormValues({});
1353
+ setExpandedCommands({});
1354
+ }
1355
+ }, [status]);
1356
+ const requestCapabilities = (0, import_react6.useCallback)(() => {
1357
+ if (status === "ready") {
1358
+ sendMessage({
1359
+ type: "requestCapabilities",
1360
+ data: {}
1361
+ });
1362
+ }
1363
+ }, [status, sendMessage]);
1364
+ import_react6.default.useEffect(() => {
1365
+ if (status === "ready") {
1366
+ requestCapabilities();
1367
+ }
1368
+ }, [status, requestCapabilities]);
1369
+ import_react6.default.useEffect(() => {
1370
+ if (status !== "ready" || Object.keys(commands).length > 0) {
1371
+ return;
1372
+ }
1373
+ const interval = setInterval(() => {
1374
+ requestCapabilities();
1375
+ }, 5e3);
1376
+ return () => clearInterval(interval);
1377
+ }, [status, commands, requestCapabilities]);
1378
+ useReactorMessage((message) => {
1379
+ if (message && typeof message === "object" && "commands" in message) {
1380
+ const commandsMessage = message;
1381
+ setCommands(commandsMessage.commands);
1382
+ const initialValues = {};
1383
+ const initialExpanded = {};
1384
+ Object.entries(commandsMessage.commands).forEach(
1385
+ ([commandName, commandSchema]) => {
1386
+ initialValues[commandName] = {};
1387
+ initialExpanded[commandName] = false;
1388
+ Object.entries(commandSchema.schema).forEach(
1389
+ ([paramName, paramSchema]) => {
1390
+ var _a, _b;
1391
+ if (paramSchema.type === "number") {
1392
+ initialValues[commandName][paramName] = (_a = paramSchema.minimum) != null ? _a : 0;
1393
+ } else if (paramSchema.type === "string") {
1394
+ initialValues[commandName][paramName] = "";
1395
+ } else if (paramSchema.type === "boolean") {
1396
+ initialValues[commandName][paramName] = false;
1397
+ } else if (paramSchema.type === "integer") {
1398
+ initialValues[commandName][paramName] = (_b = paramSchema.minimum) != null ? _b : 0;
1399
+ }
1400
+ }
1401
+ );
1402
+ }
1403
+ );
1404
+ setFormValues(initialValues);
1405
+ setExpandedCommands(initialExpanded);
1406
+ }
1407
+ });
1408
+ const handleInputChange = (0, import_react6.useCallback)(
1409
+ (commandName, paramName, value) => {
1410
+ setFormValues((prev) => __spreadProps(__spreadValues({}, prev), {
1411
+ [commandName]: __spreadProps(__spreadValues({}, prev[commandName]), {
1412
+ [paramName]: value
1413
+ })
1414
+ }));
1415
+ },
1416
+ []
1417
+ );
1418
+ const toggleCommandExpanded = (0, import_react6.useCallback)((commandName) => {
1419
+ setExpandedCommands((prev) => __spreadProps(__spreadValues({}, prev), {
1420
+ [commandName]: !prev[commandName]
1421
+ }));
1422
+ }, []);
1423
+ const handleCommandSubmit = (0, import_react6.useCallback)(
1424
+ (commandName) => __async(null, null, function* () {
1425
+ const commandSchema = commands[commandName];
1426
+ const formData = formValues[commandName] || {};
1427
+ const data = {};
1428
+ Object.keys(commandSchema.schema).forEach((paramName) => {
1429
+ var _a, _b;
1430
+ const paramSchema = commandSchema.schema[paramName];
1431
+ let value = formData[paramName];
1432
+ if (paramSchema.type === "number" && typeof value === "string") {
1433
+ value = parseFloat(value) || 0;
1434
+ } else if (paramSchema.type === "integer" && typeof value === "string") {
1435
+ value = parseInt(value) || 0;
1436
+ } else if (paramSchema.type === "boolean" && typeof value !== "boolean") {
1437
+ value = Boolean(value);
1438
+ }
1439
+ if (value !== void 0 && value !== "" && value !== null) {
1440
+ data[paramName] = value;
1441
+ } else if (paramSchema.required) {
1442
+ if (paramSchema.type === "number") {
1443
+ data[paramName] = (_a = paramSchema.minimum) != null ? _a : 0;
1444
+ } else if (paramSchema.type === "integer") {
1445
+ data[paramName] = (_b = paramSchema.minimum) != null ? _b : 0;
1446
+ } else if (paramSchema.type === "string") {
1447
+ data[paramName] = "";
1448
+ } else if (paramSchema.type === "boolean") {
1449
+ data[paramName] = false;
1450
+ }
1451
+ }
1452
+ });
1453
+ console.log(`Executing command: ${commandName}`, data);
1454
+ yield sendMessage({
1455
+ type: commandName,
1456
+ data
1457
+ });
1458
+ }),
1459
+ [formValues, sendMessage, commands]
1460
+ );
1461
+ const renderInput = (commandName, paramName, paramSchema) => {
1462
+ var _a, _b;
1463
+ const value = (_b = (_a = formValues[commandName]) == null ? void 0 : _a[paramName]) != null ? _b : "";
1464
+ if (paramSchema.type === "number" || paramSchema.type === "integer") {
1465
+ const isInteger = paramSchema.type === "integer";
1466
+ const step = isInteger ? 1 : 0.1;
1467
+ const parseValue = isInteger ? parseInt : parseFloat;
1468
+ if (typeof paramSchema.minimum === "number" && typeof paramSchema.maximum === "number") {
1469
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: "8px" }, children: [
1470
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1471
+ "label",
1472
+ {
1473
+ style: { fontSize: "12px", color: "#666", display: "block" },
1474
+ children: [
1475
+ paramName,
1476
+ " (",
1477
+ paramSchema.minimum,
1478
+ " - ",
1479
+ paramSchema.maximum,
1480
+ ")",
1481
+ paramSchema.description && ` - ${paramSchema.description}`,
1482
+ paramSchema.required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "red" }, children: " *" })
1483
+ ]
1484
+ }
1485
+ ),
1486
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1487
+ "input",
1488
+ {
1489
+ type: "range",
1490
+ min: paramSchema.minimum,
1491
+ max: paramSchema.maximum,
1492
+ step,
1493
+ value,
1494
+ onChange: (e) => {
1495
+ const newValue = parseValue(e.target.value) || 0;
1496
+ handleInputChange(commandName, paramName, newValue);
1497
+ handleCommandSubmit(commandName);
1498
+ },
1499
+ style: { width: "100%", marginBottom: "4px" }
1500
+ }
1501
+ ),
1502
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: "11px", color: "#888" }, children: [
1503
+ "Value: ",
1504
+ value
1505
+ ] })
1506
+ ] });
1507
+ } else {
1508
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: "8px" }, children: [
1509
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1510
+ "label",
1511
+ {
1512
+ style: { fontSize: "12px", color: "#666", display: "block" },
1513
+ children: [
1514
+ paramName,
1515
+ paramSchema.description && ` - ${paramSchema.description}`,
1516
+ paramSchema.required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "red" }, children: " *" })
1517
+ ]
1518
+ }
1519
+ ),
1520
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1521
+ "input",
1522
+ {
1523
+ type: "number",
1524
+ value,
1525
+ min: paramSchema.minimum,
1526
+ max: paramSchema.maximum,
1527
+ step,
1528
+ inputMode: "numeric",
1529
+ onChange: (e) => {
1530
+ const val = e.target.value;
1531
+ if (val === "" || val === "-") {
1532
+ handleInputChange(commandName, paramName, val);
1533
+ } else {
1534
+ const parsed = parseValue(val);
1535
+ if (!isNaN(parsed)) {
1536
+ handleInputChange(commandName, paramName, parsed);
1537
+ }
1538
+ }
1539
+ },
1540
+ onBlur: (e) => {
1541
+ const val = e.target.value;
1542
+ if (val === "" || val === "-") {
1543
+ handleInputChange(commandName, paramName, 0);
1544
+ }
1545
+ },
1546
+ style: {
1547
+ width: "100%",
1548
+ padding: "4px",
1549
+ fontSize: "12px",
1550
+ border: "1px solid #ccc",
1551
+ borderRadius: "2px"
1552
+ }
1553
+ }
1554
+ )
1555
+ ] });
1556
+ }
1557
+ } else if (paramSchema.type === "string") {
1558
+ if (paramSchema.enum) {
1559
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: "8px" }, children: [
1560
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1561
+ "label",
1562
+ {
1563
+ style: { fontSize: "12px", color: "#666", display: "block" },
1564
+ children: [
1565
+ paramName,
1566
+ paramSchema.description && ` - ${paramSchema.description}`,
1567
+ paramSchema.required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "red" }, children: " *" })
1568
+ ]
1569
+ }
1570
+ ),
1571
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1572
+ "select",
1573
+ {
1574
+ value,
1575
+ onChange: (e) => handleInputChange(commandName, paramName, e.target.value),
1576
+ style: {
1577
+ width: "100%",
1578
+ padding: "4px",
1579
+ fontSize: "12px",
1580
+ border: "1px solid #ccc",
1581
+ borderRadius: "2px"
1582
+ },
1583
+ children: [
1584
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "Select..." }),
1585
+ paramSchema.enum.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: option, children: option }, option))
1586
+ ]
1587
+ }
1588
+ )
1589
+ ] });
1590
+ } else {
1591
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: "8px" }, children: [
1592
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1593
+ "label",
1594
+ {
1595
+ style: { fontSize: "12px", color: "#666", display: "block" },
1596
+ children: [
1597
+ paramName,
1598
+ paramSchema.description && ` - ${paramSchema.description}`,
1599
+ paramSchema.required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "red" }, children: " *" })
1600
+ ]
1601
+ }
1602
+ ),
1603
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1604
+ "input",
1605
+ {
1606
+ type: "text",
1607
+ value,
1608
+ onChange: (e) => handleInputChange(commandName, paramName, e.target.value),
1609
+ style: {
1610
+ width: "100%",
1611
+ padding: "4px",
1612
+ fontSize: "12px",
1613
+ border: "1px solid #ccc",
1614
+ borderRadius: "2px"
1615
+ }
1616
+ }
1617
+ )
1618
+ ] });
1619
+ }
1620
+ } else if (paramSchema.type === "boolean") {
1621
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginBottom: "8px" }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1622
+ "label",
1623
+ {
1624
+ style: {
1625
+ fontSize: "12px",
1626
+ color: "#666",
1627
+ display: "flex",
1628
+ alignItems: "center"
1629
+ },
1630
+ children: [
1631
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1632
+ "input",
1633
+ {
1634
+ type: "checkbox",
1635
+ checked: value,
1636
+ onChange: (e) => handleInputChange(commandName, paramName, e.target.checked),
1637
+ style: { marginRight: "6px" }
1638
+ }
1639
+ ),
1640
+ paramName,
1641
+ paramSchema.description && ` - ${paramSchema.description}`,
1642
+ paramSchema.required && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "red" }, children: " *" })
1643
+ ]
1644
+ }
1645
+ ) });
1646
+ }
1647
+ return null;
1648
+ };
1649
+ const renderCommand = (commandName, commandSchema) => {
1650
+ const hasParams = Object.keys(commandSchema.schema).length > 0;
1651
+ const isExpanded = expandedCommands[commandName];
1652
+ const hasSliderInputs = Object.values(commandSchema.schema).some(
1653
+ (paramSchema) => (paramSchema.type === "number" || paramSchema.type === "integer") && typeof paramSchema.minimum === "number" && typeof paramSchema.maximum === "number"
1654
+ );
1655
+ const showExecuteButton = !hasSliderInputs;
1656
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1657
+ "div",
1658
+ {
1659
+ style: {
1660
+ border: "1px solid #ddd",
1661
+ borderRadius: "4px",
1662
+ marginBottom: "8px",
1663
+ backgroundColor: "#fafafa"
1664
+ },
1665
+ children: [
1666
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1667
+ "div",
1668
+ {
1669
+ onClick: () => toggleCommandExpanded(commandName),
1670
+ style: {
1671
+ padding: "8px 12px",
1672
+ cursor: "pointer",
1673
+ borderBottom: isExpanded ? "1px solid #ddd" : "none",
1674
+ display: "flex",
1675
+ justifyContent: "space-between",
1676
+ alignItems: "center"
1677
+ },
1678
+ children: [
1679
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
1680
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1681
+ "h4",
1682
+ {
1683
+ style: {
1684
+ margin: "0",
1685
+ fontSize: "13px",
1686
+ fontWeight: "bold"
1687
+ },
1688
+ children: commandName
1689
+ }
1690
+ ),
1691
+ isExpanded && commandSchema.description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1692
+ "p",
1693
+ {
1694
+ style: { margin: "4px 0 0 0", fontSize: "11px", color: "#666" },
1695
+ children: commandSchema.description
1696
+ }
1697
+ )
1698
+ ] }),
1699
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1700
+ "div",
1701
+ {
1702
+ style: {
1703
+ fontSize: "10px",
1704
+ color: "#999",
1705
+ transform: isExpanded ? "rotate(180deg)" : "rotate(0deg)",
1706
+ transition: "transform 0.2s"
1707
+ },
1708
+ children: "\u25BC"
1709
+ }
1710
+ )
1711
+ ]
1712
+ }
1713
+ ),
1714
+ isExpanded && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: "12px", paddingTop: "0" }, children: [
1715
+ hasParams && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: showExecuteButton ? "12px" : "0" }, children: [
1716
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1717
+ "div",
1718
+ {
1719
+ style: {
1720
+ marginBottom: "8px",
1721
+ fontSize: "12px",
1722
+ fontWeight: "bold",
1723
+ color: "#555"
1724
+ },
1725
+ children: "Parameters:"
1726
+ }
1727
+ ),
1728
+ Object.entries(commandSchema.schema).map(
1729
+ ([paramName, paramSchema]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1730
+ "div",
1731
+ {
1732
+ style: { marginLeft: "8px" },
1733
+ children: renderInput(commandName, paramName, paramSchema)
1734
+ },
1735
+ `${commandName}-${paramName}`
1736
+ )
1737
+ )
1738
+ ] }),
1739
+ !hasParams && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1740
+ "div",
1741
+ {
1742
+ style: {
1743
+ marginBottom: showExecuteButton ? "12px" : "0",
1744
+ marginTop: "2px",
1745
+ fontSize: "11px",
1746
+ color: "#666",
1747
+ fontStyle: "italic"
1748
+ },
1749
+ children: "No parameters required"
1750
+ }
1751
+ ),
1752
+ showExecuteButton && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1753
+ "button",
1754
+ {
1755
+ onClick: () => handleCommandSubmit(commandName),
1756
+ style: {
1757
+ padding: "8px 16px",
1758
+ fontSize: "12px",
1759
+ backgroundColor: "#007bff",
1760
+ color: "white",
1761
+ border: "none",
1762
+ borderRadius: "4px",
1763
+ cursor: "pointer",
1764
+ fontWeight: "bold"
1765
+ },
1766
+ children: [
1767
+ "Execute ",
1768
+ commandName
1769
+ ]
1770
+ }
1771
+ )
1772
+ ] })
1773
+ ]
1774
+ },
1775
+ commandName
1776
+ );
1777
+ };
1778
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className, style, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontFamily: "monospace", fontSize: "12px" }, children: Object.keys(commands).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { padding: "12px", color: "#666", fontStyle: "italic" }, children: "Waiting for commands schema..." }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
1779
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1780
+ "h3",
1781
+ {
1782
+ style: {
1783
+ margin: "0 0 16px 0",
1784
+ fontSize: "16px",
1785
+ fontWeight: "bold"
1786
+ },
1787
+ children: "Reactor Commands"
1788
+ }
1789
+ ),
1790
+ Object.entries(commands).map(([commandName, commandSchema]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: renderCommand(commandName, commandSchema) }, commandName))
1791
+ ] }) }) });
1792
+ }
1793
+
1794
+ // src/react/WebcamStream.tsx
1795
+ var import_react7 = require("react");
1796
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1327
1797
  function WebcamStream({
1328
1798
  className,
1329
1799
  style,
@@ -1334,16 +1804,16 @@ function WebcamStream({
1334
1804
  showWebcam = true,
1335
1805
  videoObjectFit = "contain"
1336
1806
  }) {
1337
- const [stream, setStream] = (0, import_react6.useState)(null);
1338
- const [isPublishing, setIsPublishing] = (0, import_react6.useState)(false);
1339
- const [permissionDenied, setPermissionDenied] = (0, import_react6.useState)(false);
1807
+ const [stream, setStream] = (0, import_react7.useState)(null);
1808
+ const [isPublishing, setIsPublishing] = (0, import_react7.useState)(false);
1809
+ const [permissionDenied, setPermissionDenied] = (0, import_react7.useState)(false);
1340
1810
  const { status, publishVideoStream, unpublishVideoStream, reactor } = useReactor((state) => ({
1341
1811
  status: state.status,
1342
1812
  publishVideoStream: state.publishVideoStream,
1343
1813
  unpublishVideoStream: state.unpublishVideoStream,
1344
1814
  reactor: state.internal.reactor
1345
1815
  }));
1346
- const videoRef = (0, import_react6.useRef)(null);
1816
+ const videoRef = (0, import_react7.useRef)(null);
1347
1817
  const startWebcam = () => __async(null, null, function* () {
1348
1818
  console.debug("[WebcamPublisher] Starting webcam");
1349
1819
  try {
@@ -1378,7 +1848,7 @@ function WebcamStream({
1378
1848
  setStream(null);
1379
1849
  console.debug("[WebcamPublisher] Webcam stopped");
1380
1850
  });
1381
- (0, import_react6.useEffect)(() => {
1851
+ (0, import_react7.useEffect)(() => {
1382
1852
  console.debug("[WebcamPublisher] Stream effect triggered", {
1383
1853
  hasVideoElement: !!videoRef.current,
1384
1854
  hasStream: !!stream
@@ -1395,7 +1865,7 @@ function WebcamStream({
1395
1865
  videoRef.current.srcObject = null;
1396
1866
  }
1397
1867
  }, [stream]);
1398
- (0, import_react6.useEffect)(() => {
1868
+ (0, import_react7.useEffect)(() => {
1399
1869
  if (!stream) {
1400
1870
  return;
1401
1871
  }
@@ -1419,7 +1889,7 @@ function WebcamStream({
1419
1889
  });
1420
1890
  }
1421
1891
  }, [status, stream, isPublishing, publishVideoStream, unpublishVideoStream]);
1422
- (0, import_react6.useEffect)(() => {
1892
+ (0, import_react7.useEffect)(() => {
1423
1893
  const handleError = (error) => {
1424
1894
  console.debug("[WebcamPublisher] Received error event:", error);
1425
1895
  if (error.code === "VIDEO_PUBLISH_FAILED") {
@@ -1434,7 +1904,7 @@ function WebcamStream({
1434
1904
  reactor.off("error", handleError);
1435
1905
  };
1436
1906
  }, [reactor]);
1437
- (0, import_react6.useEffect)(() => {
1907
+ (0, import_react7.useEffect)(() => {
1438
1908
  if (status !== "ready") {
1439
1909
  console.debug(
1440
1910
  "[WebcamPublisher] Status changed to",
@@ -1444,7 +1914,7 @@ function WebcamStream({
1444
1914
  setIsPublishing(false);
1445
1915
  }
1446
1916
  }, [status, isPublishing]);
1447
- (0, import_react6.useEffect)(() => {
1917
+ (0, import_react7.useEffect)(() => {
1448
1918
  console.debug("[WebcamPublisher] Auto-starting webcam");
1449
1919
  startWebcam();
1450
1920
  return () => {
@@ -1453,7 +1923,7 @@ function WebcamStream({
1453
1923
  };
1454
1924
  }, []);
1455
1925
  const showPlaceholder = !stream;
1456
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1926
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
1457
1927
  "div",
1458
1928
  {
1459
1929
  style: __spreadValues({
@@ -1463,7 +1933,7 @@ function WebcamStream({
1463
1933
  }, style),
1464
1934
  className,
1465
1935
  children: [
1466
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1936
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1467
1937
  "video",
1468
1938
  {
1469
1939
  ref: videoRef,
@@ -1478,7 +1948,7 @@ function WebcamStream({
1478
1948
  autoPlay: true
1479
1949
  }
1480
1950
  ),
1481
- showPlaceholder && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1951
+ showPlaceholder && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1482
1952
  "div",
1483
1953
  {
1484
1954
  style: {
@@ -1499,11 +1969,11 @@ function WebcamStream({
1499
1969
  flexDirection: "column",
1500
1970
  gap: "12px"
1501
1971
  },
1502
- children: permissionDenied ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: "12px", fontFamily: "monospace" }, children: [
1972
+ children: permissionDenied ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: "12px", fontFamily: "monospace" }, children: [
1503
1973
  "Camera access denied.",
1504
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("br", {}),
1974
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("br", {}),
1505
1975
  "Please allow access in your browser settings."
1506
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontSize: "12px", fontFamily: "monospace" }, children: "Starting camera..." })
1976
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: "12px", fontFamily: "monospace" }, children: "Starting camera..." })
1507
1977
  }
1508
1978
  )
1509
1979
  ]
@@ -1513,6 +1983,7 @@ function WebcamStream({
1513
1983
  // Annotate the CommonJS export names for ESM import in node:
1514
1984
  0 && (module.exports = {
1515
1985
  Reactor,
1986
+ ReactorController,
1516
1987
  ReactorProvider,
1517
1988
  ReactorView,
1518
1989
  WebcamStream,