@imperosoft/cris-webui-components 1.1.2-beta.1 → 1.1.2-beta.10

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
@@ -73,9 +73,12 @@ function CrisButton({
73
73
  iconNameActive,
74
74
  iconClassActive,
75
75
  iconStyleActive,
76
+ selected,
76
77
  showControlFeedback = true,
77
78
  showLocalFeedback = true,
78
79
  suppressKeyClicks = false,
80
+ visible,
81
+ enabled,
79
82
  smartId,
80
83
  className = "",
81
84
  classActive = "",
@@ -99,11 +102,11 @@ function CrisButton({
99
102
  const touchStartedHereRef = useRef(false);
100
103
  const feedbackJoin = joinFeedback ?? join;
101
104
  const feedback = useDigital(feedbackJoin ?? 0);
102
- const enabled = useDigital(joinEnable ?? 0);
103
- const visible = useDigital(joinVisible ?? 0);
105
+ const enabledJoin = useDigital(joinEnable ?? 0);
106
+ const visibleJoin = useDigital(joinVisible ?? 0);
104
107
  const dSet = useJoinsStore((state) => state.dSet);
105
- const isEnabled = joinEnable == null ? true : enabled;
106
- const isVisible = joinVisible == null ? true : visible;
108
+ const isEnabled = enabled ?? (joinEnable == null ? true : enabledJoin);
109
+ const isVisible = visible ?? (joinVisible == null ? true : visibleJoin);
107
110
  useEffect(() => {
108
111
  log("visibility effect", { isVisible, pressedRef: pressedRef.current });
109
112
  if (!isVisible && pressedRef.current) {
@@ -126,7 +129,7 @@ function CrisButton({
126
129
  }
127
130
  };
128
131
  }, [join, smartId, dSet, log]);
129
- const hasControlFeedback = showControlFeedback && feedbackJoin != null && feedback;
132
+ const hasControlFeedback = showControlFeedback && (feedbackJoin != null && feedback || selected === true);
130
133
  const hasPressedFeedback = showLocalFeedback && pressed && isEnabled;
131
134
  const isActive = hasControlFeedback || hasPressedFeedback;
132
135
  let currentText = text ?? "";
@@ -1103,8 +1106,465 @@ function CrisOfflinePage({
1103
1106
  ] })
1104
1107
  ] }) });
1105
1108
  }
1109
+
1110
+ // src/components/CrisCoDebug.tsx
1111
+ import { useCustomObject, useCustomObjectSend } from "@imperosoft/cris-webui-ch5-core";
1112
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1113
+ var defaultStyles = {
1114
+ container: {
1115
+ display: "flex",
1116
+ flexDirection: "column",
1117
+ overflow: "auto",
1118
+ gap: 2
1119
+ },
1120
+ title: {
1121
+ fontSize: 14,
1122
+ fontWeight: 600,
1123
+ padding: "8px 12px",
1124
+ opacity: 0.7
1125
+ },
1126
+ item: {
1127
+ display: "flex",
1128
+ alignItems: "center",
1129
+ padding: "8px 12px",
1130
+ gap: 8,
1131
+ minHeight: 48
1132
+ },
1133
+ info: {
1134
+ flex: 1,
1135
+ minWidth: 0,
1136
+ overflow: "hidden"
1137
+ },
1138
+ moduleName: {
1139
+ fontSize: 14,
1140
+ fontWeight: 600,
1141
+ whiteSpace: "nowrap",
1142
+ overflow: "hidden",
1143
+ textOverflow: "ellipsis"
1144
+ },
1145
+ moduleType: {
1146
+ fontSize: 11,
1147
+ opacity: 0.5
1148
+ },
1149
+ icons: {
1150
+ display: "flex",
1151
+ gap: 4,
1152
+ alignItems: "center",
1153
+ minWidth: 56,
1154
+ justifyContent: "center"
1155
+ },
1156
+ buttons: {
1157
+ display: "flex",
1158
+ gap: 4,
1159
+ alignItems: "center"
1160
+ },
1161
+ iconBox: {
1162
+ width: 24,
1163
+ height: 24,
1164
+ display: "flex",
1165
+ alignItems: "center",
1166
+ justifyContent: "center",
1167
+ position: "relative"
1168
+ }
1169
+ };
1170
+ function ConnectionIcon({ on, type }) {
1171
+ const label = type === "eth" ? "ETH" : "RS";
1172
+ return /* @__PURE__ */ jsx7(
1173
+ "div",
1174
+ {
1175
+ style: {
1176
+ ...defaultStyles.iconBox,
1177
+ opacity: on ? 1 : 0.4
1178
+ },
1179
+ title: `${type === "eth" ? "Ethernet" : "RS232"}: ${on ? "Connected" : "Disconnected"}`,
1180
+ children: /* @__PURE__ */ jsxs6("svg", { width: "20", height: "20", viewBox: "0 0 20 20", children: [
1181
+ /* @__PURE__ */ jsx7("rect", { x: "1", y: "4", width: "18", height: "12", rx: "2", fill: "none", stroke: "currentColor", strokeWidth: "1.5" }),
1182
+ /* @__PURE__ */ jsx7("text", { x: "10", y: "12.5", textAnchor: "middle", fontSize: "7", fontWeight: "bold", fill: "currentColor", children: label }),
1183
+ on ? /* @__PURE__ */ jsx7("circle", { cx: "16", cy: "5", r: "3.5", fill: "#4caf50", stroke: "none" }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
1184
+ /* @__PURE__ */ jsx7("circle", { cx: "16", cy: "5", r: "3.5", fill: "#f44336", stroke: "none" }),
1185
+ /* @__PURE__ */ jsx7("line", { x1: "14", y1: "3", x2: "18", y2: "7", stroke: "white", strokeWidth: "1.5" })
1186
+ ] })
1187
+ ] })
1188
+ }
1189
+ );
1190
+ }
1191
+ function DebugModuleItem({
1192
+ module,
1193
+ onAction,
1194
+ itemClassName,
1195
+ itemStyle,
1196
+ buttonClassName,
1197
+ buttonActiveClassName,
1198
+ iconEthOn,
1199
+ iconEthOff,
1200
+ iconRs232On,
1201
+ iconRs232Off
1202
+ }) {
1203
+ const name = module.lb ? `${module.id} (${module.lb})` : module.id;
1204
+ return /* @__PURE__ */ jsxs6(
1205
+ "div",
1206
+ {
1207
+ className: itemClassName,
1208
+ style: itemClassName ? itemStyle : { ...defaultStyles.item, ...itemStyle },
1209
+ children: [
1210
+ /* @__PURE__ */ jsxs6("div", { style: defaultStyles.info, children: [
1211
+ /* @__PURE__ */ jsx7("div", { style: defaultStyles.moduleName, children: name }),
1212
+ /* @__PURE__ */ jsx7("div", { style: defaultStyles.moduleType, children: module.tp })
1213
+ ] }),
1214
+ /* @__PURE__ */ jsxs6("div", { style: defaultStyles.icons, children: [
1215
+ module.et.vs && (iconEthOn && iconEthOff ? module.et.on ? iconEthOn : iconEthOff : /* @__PURE__ */ jsx7(ConnectionIcon, { on: module.et.on, type: "eth" })),
1216
+ module.rs.vs && (iconRs232On && iconRs232Off ? module.rs.on ? iconRs232On : iconRs232Off : /* @__PURE__ */ jsx7(ConnectionIcon, { on: module.rs.on, type: "rs232" }))
1217
+ ] }),
1218
+ /* @__PURE__ */ jsxs6("div", { style: defaultStyles.buttons, children: [
1219
+ module.md.vs && /* @__PURE__ */ jsx7(
1220
+ CrisButton,
1221
+ {
1222
+ selected: module.md.on,
1223
+ text: "Mod",
1224
+ className: buttonClassName,
1225
+ classActive: buttonActiveClassName,
1226
+ onPress: () => onAction("toggleMod", module.id)
1227
+ }
1228
+ ),
1229
+ module.cm.vs && /* @__PURE__ */ jsx7(
1230
+ CrisButton,
1231
+ {
1232
+ selected: module.cm.on,
1233
+ text: "Com",
1234
+ className: buttonClassName,
1235
+ classActive: buttonActiveClassName,
1236
+ onPress: () => onAction("toggleCom", module.id)
1237
+ }
1238
+ )
1239
+ ] })
1240
+ ]
1241
+ }
1242
+ );
1243
+ }
1244
+ function CrisCoDebug({
1245
+ oid = "__DBG__",
1246
+ title,
1247
+ className,
1248
+ style,
1249
+ itemClassName,
1250
+ itemStyle,
1251
+ buttonClassName,
1252
+ buttonActiveClassName,
1253
+ iconEthOn,
1254
+ iconEthOff,
1255
+ iconRs232On,
1256
+ iconRs232Off
1257
+ }) {
1258
+ const modules = useCustomObject(oid);
1259
+ const send = useCustomObjectSend();
1260
+ const handleAction = (action, id) => {
1261
+ send(oid, { action, id });
1262
+ };
1263
+ if (!modules || modules.length === 0) {
1264
+ return null;
1265
+ }
1266
+ const visibleModules = modules.filter((m) => m.vs);
1267
+ return /* @__PURE__ */ jsxs6(
1268
+ "div",
1269
+ {
1270
+ className,
1271
+ style: className ? style : { ...defaultStyles.container, ...style },
1272
+ children: [
1273
+ title && /* @__PURE__ */ jsx7("div", { style: defaultStyles.title, children: title }),
1274
+ visibleModules.map((module) => /* @__PURE__ */ jsx7(
1275
+ DebugModuleItem,
1276
+ {
1277
+ module,
1278
+ onAction: handleAction,
1279
+ itemClassName,
1280
+ itemStyle,
1281
+ buttonClassName,
1282
+ buttonActiveClassName,
1283
+ iconEthOn,
1284
+ iconEthOff,
1285
+ iconRs232On,
1286
+ iconRs232Off
1287
+ },
1288
+ module.id
1289
+ ))
1290
+ ]
1291
+ }
1292
+ );
1293
+ }
1294
+
1295
+ // src/components/CrisCoMatrixListsTie.tsx
1296
+ import { useCustomObject as useCustomObject2, useCustomObjectSend as useCustomObjectSend2 } from "@imperosoft/cris-webui-ch5-core";
1297
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1298
+ var defaults = {
1299
+ container: {
1300
+ display: "flex",
1301
+ flexDirection: "row",
1302
+ gap: 8,
1303
+ height: "100%"
1304
+ },
1305
+ list: {
1306
+ flex: 1,
1307
+ display: "flex",
1308
+ flexDirection: "column",
1309
+ overflow: "hidden",
1310
+ minHeight: 0
1311
+ },
1312
+ header: {
1313
+ fontSize: 13,
1314
+ fontWeight: 600,
1315
+ padding: "6px 10px",
1316
+ textTransform: "uppercase",
1317
+ opacity: 0.6,
1318
+ flexShrink: 0
1319
+ },
1320
+ scroll: {
1321
+ flex: 1,
1322
+ minHeight: 0,
1323
+ overflow: "auto",
1324
+ WebkitOverflowScrolling: "touch",
1325
+ display: "flex",
1326
+ flexDirection: "column",
1327
+ gap: 2
1328
+ },
1329
+ item: {
1330
+ display: "flex",
1331
+ alignItems: "center",
1332
+ gap: 6,
1333
+ padding: "6px 10px",
1334
+ minHeight: 40,
1335
+ cursor: "pointer",
1336
+ userSelect: "none"
1337
+ },
1338
+ itemLabel: {
1339
+ flex: 1,
1340
+ fontSize: 13,
1341
+ whiteSpace: "nowrap",
1342
+ overflow: "hidden",
1343
+ textOverflow: "ellipsis"
1344
+ },
1345
+ indicators: {
1346
+ display: "flex",
1347
+ gap: 4,
1348
+ alignItems: "center"
1349
+ },
1350
+ indicator: {
1351
+ width: 8,
1352
+ height: 8,
1353
+ borderRadius: "50%",
1354
+ flexShrink: 0
1355
+ }
1356
+ };
1357
+ function DefaultIoIndicator({ on }) {
1358
+ return /* @__PURE__ */ jsx8(
1359
+ "div",
1360
+ {
1361
+ style: {
1362
+ ...defaults.indicator,
1363
+ backgroundColor: on ? "#4caf50" : "#f44336"
1364
+ },
1365
+ title: on ? "Online" : "Offline"
1366
+ }
1367
+ );
1368
+ }
1369
+ function DefaultSignalIndicator({ on }) {
1370
+ return /* @__PURE__ */ jsx8(
1371
+ "div",
1372
+ {
1373
+ style: {
1374
+ ...defaults.indicator,
1375
+ backgroundColor: on ? "#2196f3" : "#666"
1376
+ },
1377
+ title: on ? "Signal detected" : "No signal"
1378
+ }
1379
+ );
1380
+ }
1381
+ function MatrixItemRow({
1382
+ item,
1383
+ type,
1384
+ active,
1385
+ showChannels,
1386
+ onSelect,
1387
+ onToggleVideoMute,
1388
+ itemClassName,
1389
+ itemStyle: itemStyleProp,
1390
+ itemActiveClassName,
1391
+ itemActiveStyle,
1392
+ itemDisabledClassName,
1393
+ vmButtonClassName,
1394
+ vmButtonActiveClassName,
1395
+ renderIoIndicator,
1396
+ renderSignalIndicator
1397
+ }) {
1398
+ const isActive = active;
1399
+ const isEnabled = item.sl.en;
1400
+ const classes = [
1401
+ "cris-co-matrix-item",
1402
+ itemClassName,
1403
+ isActive && (itemActiveClassName || "active"),
1404
+ !isEnabled && (itemDisabledClassName || "disabled")
1405
+ ].filter(Boolean).join(" ");
1406
+ const computedStyle = itemClassName ? { ...itemStyleProp } : {
1407
+ ...defaults.item,
1408
+ ...itemStyleProp,
1409
+ ...isActive ? itemActiveStyle : void 0,
1410
+ opacity: isEnabled ? 1 : 0.4
1411
+ };
1412
+ return /* @__PURE__ */ jsxs7("div", { className: classes, style: computedStyle, children: [
1413
+ /* @__PURE__ */ jsx8(
1414
+ CrisButton,
1415
+ {
1416
+ selected: isActive,
1417
+ enabled: isEnabled,
1418
+ onPress: onSelect,
1419
+ className: `cris-co-matrix-item-btn ${itemActiveClassName ?? ""}`,
1420
+ classActive: itemActiveClassName,
1421
+ children: /* @__PURE__ */ jsxs7("div", { style: { display: "flex", alignItems: "center", gap: 6, width: "100%" }, children: [
1422
+ showChannels && /* @__PURE__ */ jsx8("span", { className: "cris-co-matrix-ch", style: { flexShrink: 0, opacity: 0.6 }, children: item.id }),
1423
+ /* @__PURE__ */ jsx8("span", { style: defaults.itemLabel, children: item.lb || `${type === "input" ? "Input" : "Output"} ${item.id}` }),
1424
+ /* @__PURE__ */ jsxs7("div", { style: defaults.indicators, children: [
1425
+ item.io.vs && (renderIoIndicator ? renderIoIndicator(item.io.on) : /* @__PURE__ */ jsx8(DefaultIoIndicator, { on: item.io.on })),
1426
+ item.sg.vs && (renderSignalIndicator ? renderSignalIndicator(item.sg.on) : /* @__PURE__ */ jsx8(DefaultSignalIndicator, { on: item.sg.on }))
1427
+ ] })
1428
+ ] })
1429
+ }
1430
+ ),
1431
+ item.vm.vs && /* @__PURE__ */ jsx8(
1432
+ CrisButton,
1433
+ {
1434
+ selected: item.vm.on,
1435
+ enabled: item.vm.en,
1436
+ text: "VM",
1437
+ onPress: onToggleVideoMute,
1438
+ className: vmButtonClassName,
1439
+ classActive: vmButtonActiveClassName
1440
+ }
1441
+ )
1442
+ ] });
1443
+ }
1444
+ function CrisCoMatrixListsTie({
1445
+ oid,
1446
+ inputTitle = "Inputs",
1447
+ outputTitle = "Outputs",
1448
+ showChannels = true,
1449
+ className,
1450
+ style,
1451
+ listClassName,
1452
+ listStyle,
1453
+ headerClassName,
1454
+ headerStyle,
1455
+ itemClassName,
1456
+ itemStyle,
1457
+ itemActiveClassName,
1458
+ itemActiveStyle,
1459
+ itemDisabledClassName,
1460
+ vmButtonClassName,
1461
+ vmButtonActiveClassName,
1462
+ renderIoIndicator,
1463
+ renderSignalIndicator
1464
+ }) {
1465
+ const matrix = useCustomObject2(oid);
1466
+ const send = useCustomObjectSend2();
1467
+ if (!matrix) return null;
1468
+ const { si, ip: inputs, op: outputs } = matrix;
1469
+ const handleSelectInput = (id) => {
1470
+ send(oid, { action: "selectInput", id });
1471
+ };
1472
+ const handleTie = (id) => {
1473
+ send(oid, { action: "tie", id });
1474
+ };
1475
+ const handleToggleVideoMute = (type, id) => {
1476
+ send(oid, { action: "toggleVideoMute", type, id });
1477
+ };
1478
+ return /* @__PURE__ */ jsxs7(
1479
+ "div",
1480
+ {
1481
+ className,
1482
+ style: className ? style : { ...defaults.container, ...style },
1483
+ children: [
1484
+ /* @__PURE__ */ jsxs7(
1485
+ "div",
1486
+ {
1487
+ className: listClassName,
1488
+ style: listClassName ? listStyle : { ...defaults.list, ...listStyle },
1489
+ children: [
1490
+ /* @__PURE__ */ jsx8(
1491
+ "div",
1492
+ {
1493
+ className: headerClassName,
1494
+ style: headerClassName ? headerStyle : { ...defaults.header, ...headerStyle },
1495
+ children: inputTitle
1496
+ }
1497
+ ),
1498
+ /* @__PURE__ */ jsx8("div", { style: defaults.scroll, children: inputs?.map((item) => /* @__PURE__ */ jsx8(
1499
+ MatrixItemRow,
1500
+ {
1501
+ item,
1502
+ type: "input",
1503
+ active: si === item.id,
1504
+ showChannels,
1505
+ onSelect: () => handleSelectInput(item.id),
1506
+ onToggleVideoMute: () => handleToggleVideoMute("input", item.id),
1507
+ itemClassName,
1508
+ itemStyle,
1509
+ itemActiveClassName,
1510
+ itemActiveStyle,
1511
+ itemDisabledClassName,
1512
+ vmButtonClassName,
1513
+ vmButtonActiveClassName,
1514
+ renderIoIndicator,
1515
+ renderSignalIndicator
1516
+ },
1517
+ item.id
1518
+ )) })
1519
+ ]
1520
+ }
1521
+ ),
1522
+ /* @__PURE__ */ jsxs7(
1523
+ "div",
1524
+ {
1525
+ className: listClassName,
1526
+ style: listClassName ? listStyle : { ...defaults.list, ...listStyle },
1527
+ children: [
1528
+ /* @__PURE__ */ jsx8(
1529
+ "div",
1530
+ {
1531
+ className: headerClassName,
1532
+ style: headerClassName ? headerStyle : { ...defaults.header, ...headerStyle },
1533
+ children: outputTitle
1534
+ }
1535
+ ),
1536
+ /* @__PURE__ */ jsx8("div", { style: defaults.scroll, children: outputs?.map((item) => /* @__PURE__ */ jsx8(
1537
+ MatrixItemRow,
1538
+ {
1539
+ item,
1540
+ type: "output",
1541
+ active: item.ti === si,
1542
+ showChannels,
1543
+ onSelect: () => handleTie(item.id),
1544
+ onToggleVideoMute: () => handleToggleVideoMute("output", item.id),
1545
+ itemClassName,
1546
+ itemStyle,
1547
+ itemActiveClassName,
1548
+ itemActiveStyle,
1549
+ itemDisabledClassName,
1550
+ vmButtonClassName,
1551
+ vmButtonActiveClassName,
1552
+ renderIoIndicator,
1553
+ renderSignalIndicator
1554
+ },
1555
+ item.id
1556
+ )) })
1557
+ ]
1558
+ }
1559
+ )
1560
+ ]
1561
+ }
1562
+ );
1563
+ }
1106
1564
  export {
1107
1565
  CrisButton,
1566
+ CrisCoDebug,
1567
+ CrisCoMatrixListsTie,
1108
1568
  CrisGauge,
1109
1569
  CrisOfflinePage,
1110
1570
  CrisSlider,