@procaaso/alphinity-ui-components 1.0.9 → 1.0.11

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.cjs CHANGED
@@ -998,9 +998,13 @@ function DeviceControlPanel({
998
998
  binding,
999
999
  onClose,
1000
1000
  position = "bottom",
1001
+ align = "center",
1001
1002
  touchOptimized = true,
1003
+ compact = false,
1004
+ fontScale = 1,
1002
1005
  maxHeight,
1003
1006
  maxWidth,
1007
+ toastDuration = 3e3,
1004
1008
  onModeChange,
1005
1009
  onParameterChange,
1006
1010
  onStart,
@@ -1008,6 +1012,7 @@ function DeviceControlPanel({
1008
1012
  onCustomAction
1009
1013
  }) {
1010
1014
  const [localParameterValues, setLocalParameterValues] = (0, import_react5.useState)({});
1015
+ const [showToast, setShowToast] = (0, import_react5.useState)(true);
1011
1016
  (0, import_react5.useEffect)(() => {
1012
1017
  if (binding) {
1013
1018
  const currentParams2 = binding.parameters[binding.state.currentMode] || [];
@@ -1018,10 +1023,33 @@ function DeviceControlPanel({
1018
1023
  setLocalParameterValues(values);
1019
1024
  }
1020
1025
  }, [binding, binding?.state.currentMode]);
1026
+ (0, import_react5.useEffect)(() => {
1027
+ if (binding?.state.lastCommandResult) {
1028
+ setShowToast(true);
1029
+ const timer = setTimeout(() => {
1030
+ setShowToast(false);
1031
+ }, toastDuration);
1032
+ return () => clearTimeout(timer);
1033
+ }
1034
+ }, [binding?.state.lastCommandResult, toastDuration]);
1021
1035
  if (!binding) return null;
1022
1036
  const currentMode = binding.state.currentMode;
1023
1037
  const currentParams = binding.parameters[currentMode] || [];
1024
1038
  const touchSize = touchOptimized ? 56 : 40;
1039
+ const spacing = {
1040
+ padding: compact ? "12px" : "20px",
1041
+ gap: compact ? "6px" : "8px",
1042
+ marginBottom: compact ? "10px" : "16px",
1043
+ itemPadding: compact ? "8px 10px" : "10px 12px"
1044
+ };
1045
+ const fontSize = {
1046
+ title: Math.round(14 * fontScale),
1047
+ label: Math.round(11 * fontScale),
1048
+ value: Math.round(13 * fontScale),
1049
+ input: Math.round(14 * fontScale),
1050
+ button: Math.round(12 * fontScale),
1051
+ status: Math.round(10 * fontScale)
1052
+ };
1025
1053
  const currentModeObj = binding.modes.find((m) => m.value === currentMode);
1026
1054
  const activeCapabilities = currentModeObj?.capabilities ?? binding.capabilities ?? {};
1027
1055
  const backgroundColor = binding.theme?.backgroundColor || "#edeeef";
@@ -1060,12 +1088,9 @@ function DeviceControlPanel({
1060
1088
  position: "fixed",
1061
1089
  ...position === "bottom" ? {
1062
1090
  bottom: 0,
1063
- left: 0,
1064
- right: 0,
1091
+ ...align === "left" ? { left: 0, right: "auto" } : align === "right" ? { right: 0, left: "auto" } : { left: 0, right: 0, marginLeft: "auto", marginRight: "auto" },
1065
1092
  animation: "slideUp 0.3s ease-out",
1066
- maxWidth,
1067
- marginLeft: "auto",
1068
- marginRight: "auto"
1093
+ maxWidth
1069
1094
  } : {
1070
1095
  right: 0,
1071
1096
  top: 0,
@@ -1078,445 +1103,495 @@ function DeviceControlPanel({
1078
1103
  borderRadius: position === "bottom" ? "8px 8px 0 0" : "8px 0 0 8px",
1079
1104
  boxShadow: "none",
1080
1105
  border: `2px solid ${borderColor}`,
1081
- padding: "20px",
1106
+ padding: spacing.padding,
1082
1107
  zIndex: 9999,
1083
1108
  maxHeight: maxHeight || (position === "bottom" ? "70vh" : "100vh"),
1084
1109
  overflowY: "auto",
1085
1110
  ...binding.display?.style
1086
1111
  };
1087
1112
  const titleText = binding.display?.title || binding.deviceName || binding.tag || binding.nodeId;
1088
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: panelStyle, className: binding.display?.className, children: [
1089
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1090
- "div",
1091
- {
1092
- style: {
1093
- display: "flex",
1094
- justifyContent: "space-between",
1095
- alignItems: "center",
1096
- marginBottom: "16px",
1097
- paddingBottom: "12px",
1098
- borderBottom: `2px solid ${borderColor}`
1099
- },
1100
- children: [
1101
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1113
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1114
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: panelStyle, className: binding.display?.className, children: [
1115
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1116
+ "div",
1117
+ {
1118
+ style: {
1119
+ display: "flex",
1120
+ justifyContent: "space-between",
1121
+ alignItems: "center",
1122
+ marginBottom: "16px",
1123
+ paddingBottom: "12px",
1124
+ borderBottom: `2px solid ${borderColor}`
1125
+ },
1126
+ children: [
1127
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1128
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1129
+ "h3",
1130
+ {
1131
+ style: {
1132
+ margin: 0,
1133
+ fontSize: `${fontSize.title}px`,
1134
+ fontWeight: 600,
1135
+ fontFamily: "Arial, sans-serif",
1136
+ letterSpacing: "0.5px",
1137
+ textTransform: "uppercase",
1138
+ color: textColor
1139
+ },
1140
+ children: titleText
1141
+ }
1142
+ ),
1143
+ binding.deviceType && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1144
+ "div",
1145
+ {
1146
+ style: {
1147
+ fontSize: "11px",
1148
+ color: mutedTextColor,
1149
+ marginTop: "4px",
1150
+ fontFamily: "Arial, sans-serif"
1151
+ },
1152
+ children: binding.deviceType
1153
+ }
1154
+ )
1155
+ ] }),
1102
1156
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1103
- "h3",
1104
- {
1105
- style: {
1106
- margin: 0,
1107
- fontSize: "14px",
1108
- fontWeight: 600,
1109
- fontFamily: "Arial, sans-serif",
1110
- letterSpacing: "0.5px",
1111
- textTransform: "uppercase",
1112
- color: textColor
1113
- },
1114
- children: titleText
1115
- }
1116
- ),
1117
- binding.deviceType && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1118
- "div",
1157
+ "button",
1119
1158
  {
1159
+ onClick: onClose,
1120
1160
  style: {
1121
- fontSize: "11px",
1122
- color: mutedTextColor,
1123
- marginTop: "4px",
1161
+ width: touchSize * 0.7,
1162
+ height: touchSize * 0.7,
1163
+ backgroundColor: surfaceColor,
1164
+ color: textColor,
1165
+ border: `2px solid ${borderColor}`,
1166
+ borderRadius: "2px",
1167
+ fontSize: "18px",
1168
+ cursor: "pointer",
1169
+ fontWeight: "bold",
1124
1170
  fontFamily: "Arial, sans-serif"
1125
1171
  },
1126
- children: binding.deviceType
1172
+ children: "\xD7"
1127
1173
  }
1128
1174
  )
1129
- ] }),
1130
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1131
- "button",
1132
- {
1133
- onClick: onClose,
1134
- style: {
1135
- width: touchSize * 0.7,
1136
- height: touchSize * 0.7,
1137
- backgroundColor: surfaceColor,
1138
- color: textColor,
1139
- border: `2px solid ${borderColor}`,
1140
- borderRadius: "2px",
1141
- fontSize: "18px",
1142
- cursor: "pointer",
1143
- fontWeight: "bold",
1144
- fontFamily: "Arial, sans-serif"
1145
- },
1146
- children: "\xD7"
1147
- }
1148
- )
1149
- ]
1150
- }
1151
- ),
1152
- binding.state.status && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1153
- "div",
1154
- {
1155
- style: {
1156
- display: "flex",
1157
- alignItems: "center",
1158
- gap: "12px",
1159
- padding: "10px 12px",
1160
- backgroundColor: surfaceColor,
1161
- border: `1px solid ${borderColor}`,
1162
- borderRadius: "6px",
1163
- marginBottom: "16px"
1164
- },
1165
- children: [
1166
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1167
- "div",
1168
- {
1169
- style: {
1170
- width: "10px",
1171
- height: "10px",
1172
- borderRadius: "50%",
1173
- backgroundColor: statusColor,
1174
- border: "1px solid #333"
1175
- }
1176
- }
1177
- ),
1178
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { flex: 1 }, children: [
1175
+ ]
1176
+ }
1177
+ ),
1178
+ binding.state.status && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1179
+ "div",
1180
+ {
1181
+ style: {
1182
+ display: "flex",
1183
+ alignItems: "center",
1184
+ gap: "12px",
1185
+ padding: spacing.itemPadding,
1186
+ backgroundColor: surfaceColor,
1187
+ border: `1px solid ${borderColor}`,
1188
+ borderRadius: "6px",
1189
+ marginBottom: spacing.marginBottom
1190
+ },
1191
+ children: [
1179
1192
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1180
1193
  "div",
1181
1194
  {
1182
1195
  style: {
1183
- fontWeight: 600,
1184
- textTransform: "uppercase",
1185
- fontSize: "11px",
1186
- fontFamily: "Arial, sans-serif",
1187
- letterSpacing: "0.5px",
1188
- color: textColor
1189
- },
1190
- children: binding.state.status
1196
+ width: "10px",
1197
+ height: "10px",
1198
+ borderRadius: "50%",
1199
+ backgroundColor: statusColor,
1200
+ border: "1px solid #333"
1201
+ }
1191
1202
  }
1192
1203
  ),
1193
- binding.state.statusMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1204
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { flex: 1 }, children: [
1205
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1206
+ "div",
1207
+ {
1208
+ style: {
1209
+ fontWeight: 600,
1210
+ textTransform: "uppercase",
1211
+ fontSize: `${fontSize.label}px`,
1212
+ fontFamily: "Arial, sans-serif",
1213
+ letterSpacing: "0.5px",
1214
+ color: textColor
1215
+ },
1216
+ children: binding.state.status
1217
+ }
1218
+ ),
1219
+ binding.state.statusMessage && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1220
+ "div",
1221
+ {
1222
+ style: {
1223
+ fontSize: "10px",
1224
+ color: mutedTextColor,
1225
+ marginTop: "2px",
1226
+ fontFamily: "Arial, sans-serif"
1227
+ },
1228
+ children: binding.state.statusMessage
1229
+ }
1230
+ )
1231
+ ] }),
1232
+ binding.state.isRunning !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1194
1233
  "div",
1195
1234
  {
1196
1235
  style: {
1236
+ padding: "4px 10px",
1237
+ backgroundColor: binding.state.isRunning ? selectedColor : surfaceColor,
1238
+ border: `1px solid ${borderColor}`,
1239
+ borderRadius: "2px",
1197
1240
  fontSize: "10px",
1198
- color: mutedTextColor,
1199
- marginTop: "2px",
1200
- fontFamily: "Arial, sans-serif"
1241
+ fontWeight: 600,
1242
+ fontFamily: "Arial, sans-serif",
1243
+ letterSpacing: "0.5px",
1244
+ color: textColor
1201
1245
  },
1202
- children: binding.state.statusMessage
1246
+ children: binding.state.isRunning ? "RUNNING" : "STOPPED"
1203
1247
  }
1204
1248
  )
1205
- ] }),
1206
- binding.state.isRunning !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1207
- "div",
1208
- {
1209
- style: {
1210
- padding: "4px 10px",
1211
- backgroundColor: binding.state.isRunning ? selectedColor : surfaceColor,
1212
- border: `1px solid ${borderColor}`,
1213
- borderRadius: "2px",
1214
- fontSize: "10px",
1215
- fontWeight: 600,
1216
- fontFamily: "Arial, sans-serif",
1217
- letterSpacing: "0.5px",
1218
- color: textColor
1219
- },
1220
- children: binding.state.isRunning ? "RUNNING" : "STOPPED"
1221
- }
1222
- )
1223
- ]
1224
- }
1225
- ),
1226
- binding.display?.showModeSelector !== false && binding.modes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { marginBottom: "16px" }, children: [
1227
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1228
- "label",
1229
- {
1230
- style: {
1231
- display: "block",
1232
- marginBottom: "8px",
1233
- fontSize: "11px",
1234
- fontWeight: 600,
1235
- textTransform: "uppercase",
1236
- letterSpacing: "0.5px",
1237
- fontFamily: "Arial, sans-serif",
1238
- color: mutedTextColor
1239
- },
1240
- children: "Mode"
1249
+ ]
1241
1250
  }
1242
1251
  ),
1243
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap" }, children: binding.modes.map((mode) => {
1244
- const isSelected = mode.value === currentMode;
1245
- const isEnabled = mode.enabled !== false;
1246
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1247
- "button",
1252
+ binding.display?.showModeSelector !== false && binding.modes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { marginBottom: "16px" }, children: [
1253
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1254
+ "label",
1248
1255
  {
1249
- onClick: () => isEnabled && handleModeChange(mode.value),
1250
- disabled: !isEnabled,
1251
1256
  style: {
1252
- flex: 1,
1253
- minWidth: "80px",
1254
- height: touchSize,
1255
- backgroundColor: isSelected ? selectedColor : surfaceColor,
1256
- color: isSelected ? "#000000" : textColor,
1257
- border: `1px solid ${isSelected ? "#b4d0fe" : borderColor}`,
1258
- borderRadius: "6px",
1257
+ display: "block",
1258
+ marginBottom: "8px",
1259
1259
  fontSize: "11px",
1260
1260
  fontWeight: 600,
1261
- fontFamily: "Arial, sans-serif",
1261
+ textTransform: "uppercase",
1262
1262
  letterSpacing: "0.5px",
1263
+ fontFamily: "Arial, sans-serif",
1264
+ color: mutedTextColor
1265
+ },
1266
+ children: "Mode"
1267
+ }
1268
+ ),
1269
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1270
+ "div",
1271
+ {
1272
+ style: {
1273
+ display: "flex",
1274
+ gap: spacing.gap,
1275
+ overflowX: "auto",
1276
+ overflowY: "hidden",
1277
+ scrollbarWidth: "thin",
1278
+ scrollbarColor: `${borderColor} transparent`,
1279
+ paddingBottom: "4px",
1280
+ marginBottom: "-4px"
1281
+ },
1282
+ children: binding.modes.map((mode) => {
1283
+ const isSelected = mode.value === currentMode;
1284
+ const isEnabled = mode.enabled !== false;
1285
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1286
+ "button",
1287
+ {
1288
+ onClick: () => isEnabled && handleModeChange(mode.value),
1289
+ disabled: !isEnabled,
1290
+ style: {
1291
+ flex: "0 0 auto",
1292
+ minWidth: "90px",
1293
+ height: touchSize,
1294
+ backgroundColor: isSelected ? selectedColor : surfaceColor,
1295
+ color: isSelected ? "#000000" : textColor,
1296
+ border: `1px solid ${isSelected ? "#b4d0fe" : borderColor}`,
1297
+ borderRadius: "6px",
1298
+ fontSize: `${fontSize.label}px`,
1299
+ fontWeight: 600,
1300
+ fontFamily: "Arial, sans-serif",
1301
+ letterSpacing: "0.5px",
1302
+ textTransform: "uppercase",
1303
+ cursor: isEnabled ? "pointer" : "not-allowed",
1304
+ opacity: isEnabled ? 1 : 0.4,
1305
+ whiteSpace: "nowrap"
1306
+ },
1307
+ children: mode.label
1308
+ },
1309
+ mode.value
1310
+ );
1311
+ })
1312
+ }
1313
+ )
1314
+ ] }),
1315
+ currentParams.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { marginBottom: spacing.marginBottom }, children: [
1316
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1317
+ "label",
1318
+ {
1319
+ style: {
1320
+ display: "block",
1321
+ marginBottom: spacing.gap,
1322
+ fontSize: `${fontSize.label}px`,
1323
+ fontWeight: 600,
1263
1324
  textTransform: "uppercase",
1264
- cursor: isEnabled ? "pointer" : "not-allowed",
1265
- opacity: isEnabled ? 1 : 0.4
1325
+ letterSpacing: "0.5px",
1326
+ fontFamily: "Arial, sans-serif",
1327
+ color: mutedTextColor
1266
1328
  },
1267
- children: mode.label
1268
- },
1269
- mode.value
1270
- );
1271
- }) })
1272
- ] }),
1273
- currentParams.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { marginBottom: "16px" }, children: [
1274
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1275
- "label",
1276
- {
1277
- style: {
1278
- display: "block",
1279
- marginBottom: "8px",
1280
- fontSize: "11px",
1281
- fontWeight: 600,
1282
- textTransform: "uppercase",
1283
- letterSpacing: "0.5px",
1284
- fontFamily: "Arial, sans-serif",
1285
- color: mutedTextColor
1286
- },
1287
- children: "Parameters"
1288
- }
1289
- ),
1290
- currentParams.map((param) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1291
- "div",
1292
- {
1293
- style: {
1294
- marginBottom: "10px",
1295
- padding: "10px",
1296
- backgroundColor: surfaceColor,
1297
- border: `1px solid ${borderColor}`,
1298
- borderRadius: "6px"
1299
- },
1300
- children: [
1301
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1302
- "div",
1303
- {
1304
- style: { display: "flex", justifyContent: "space-between", marginBottom: "8px" },
1305
- children: [
1306
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1307
- "span",
1308
- {
1309
- style: {
1310
- fontSize: "11px",
1311
- fontWeight: 600,
1312
- textTransform: "uppercase",
1313
- letterSpacing: "0.5px",
1314
- fontFamily: "Arial, sans-serif",
1315
- color: mutedTextColor
1316
- },
1317
- children: param.label
1318
- }
1329
+ children: "Parameters"
1330
+ }
1331
+ ),
1332
+ currentParams.map((param) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1333
+ "div",
1334
+ {
1335
+ style: {
1336
+ marginBottom: spacing.gap,
1337
+ padding: spacing.itemPadding,
1338
+ backgroundColor: surfaceColor,
1339
+ border: `1px solid ${borderColor}`,
1340
+ borderRadius: "6px"
1341
+ },
1342
+ children: [
1343
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1344
+ "div",
1345
+ {
1346
+ style: {
1347
+ display: "flex",
1348
+ justifyContent: "space-between",
1349
+ marginBottom: spacing.gap
1350
+ },
1351
+ children: [
1352
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1353
+ "span",
1354
+ {
1355
+ style: {
1356
+ fontSize: `${fontSize.label}px`,
1357
+ fontWeight: 600,
1358
+ textTransform: "uppercase",
1359
+ letterSpacing: "0.5px",
1360
+ fontFamily: "Arial, sans-serif",
1361
+ color: mutedTextColor
1362
+ },
1363
+ children: param.label
1364
+ }
1365
+ ),
1366
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1367
+ "span",
1368
+ {
1369
+ style: {
1370
+ fontSize: `${fontSize.value}px`,
1371
+ fontWeight: 700,
1372
+ fontFamily: "Arial, sans-serif",
1373
+ color: textColor
1374
+ },
1375
+ children: [
1376
+ localParameterValues[param.id] ?? param.value,
1377
+ " ",
1378
+ param.unit && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: mutedTextColor, fontSize: "10px", fontWeight: 600 }, children: param.unit })
1379
+ ]
1380
+ }
1381
+ )
1382
+ ]
1383
+ }
1384
+ ),
1385
+ param.type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1386
+ "button",
1387
+ {
1388
+ onClick: () => {
1389
+ const newValue = !localParameterValues[param.id];
1390
+ handleParameterInput(param.id, newValue);
1391
+ handleParameterCommit(param.id, newValue);
1392
+ },
1393
+ disabled: param.readOnly,
1394
+ style: {
1395
+ width: "100%",
1396
+ height: touchSize,
1397
+ backgroundColor: localParameterValues[param.id] ? "#3f3f46" : surfaceColor,
1398
+ color: localParameterValues[param.id] ? textColor : mutedTextColor,
1399
+ border: `1px solid ${localParameterValues[param.id] ? "#52525b" : borderColor}`,
1400
+ borderRadius: "4px",
1401
+ fontSize: "12px",
1402
+ fontWeight: 600,
1403
+ fontFamily: "monospace",
1404
+ letterSpacing: "0.5px",
1405
+ cursor: param.readOnly ? "not-allowed" : "pointer",
1406
+ transition: "all 0.15s"
1407
+ },
1408
+ children: localParameterValues[param.id] ? "ON" : "OFF"
1409
+ }
1410
+ ) : param.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1411
+ "select",
1412
+ {
1413
+ value: localParameterValues[param.id] || param.value,
1414
+ onChange: (e) => {
1415
+ handleParameterInput(param.id, e.target.value);
1416
+ handleParameterCommit(param.id, e.target.value);
1417
+ },
1418
+ disabled: param.readOnly,
1419
+ style: {
1420
+ width: "100%",
1421
+ height: touchSize,
1422
+ backgroundColor: surfaceColor,
1423
+ color: textColor,
1424
+ border: `1px solid ${borderColor}`,
1425
+ borderRadius: "4px",
1426
+ padding: "0 12px",
1427
+ fontSize: "12px",
1428
+ fontFamily: "monospace",
1429
+ cursor: "pointer"
1430
+ },
1431
+ children: param.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
1432
+ }
1433
+ ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1434
+ "input",
1435
+ {
1436
+ type: param.type === "number" ? "number" : "text",
1437
+ value: localParameterValues[param.id] ?? param.value,
1438
+ onChange: (e) => handleParameterInput(
1439
+ param.id,
1440
+ param.type === "number" ? +e.target.value : e.target.value
1319
1441
  ),
1320
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1321
- "span",
1322
- {
1323
- style: {
1324
- fontSize: "13px",
1325
- fontWeight: 700,
1326
- fontFamily: "Arial, sans-serif",
1327
- color: textColor
1328
- },
1329
- children: [
1330
- localParameterValues[param.id] ?? param.value,
1331
- " ",
1332
- param.unit && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { color: mutedTextColor, fontSize: "10px", fontWeight: 600 }, children: param.unit })
1333
- ]
1334
- }
1335
- )
1336
- ]
1337
- }
1338
- ),
1339
- param.type === "boolean" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1340
- "button",
1341
- {
1342
- onClick: () => {
1343
- const newValue = !localParameterValues[param.id];
1344
- handleParameterInput(param.id, newValue);
1345
- handleParameterCommit(param.id, newValue);
1346
- },
1347
- disabled: param.readOnly,
1348
- style: {
1349
- width: "100%",
1350
- height: touchSize,
1351
- backgroundColor: localParameterValues[param.id] ? "#3f3f46" : surfaceColor,
1352
- color: localParameterValues[param.id] ? textColor : mutedTextColor,
1353
- border: `1px solid ${localParameterValues[param.id] ? "#52525b" : borderColor}`,
1354
- borderRadius: "4px",
1355
- fontSize: "12px",
1356
- fontWeight: 600,
1357
- fontFamily: "monospace",
1358
- letterSpacing: "0.5px",
1359
- cursor: param.readOnly ? "not-allowed" : "pointer",
1360
- transition: "all 0.15s"
1361
- },
1362
- children: localParameterValues[param.id] ? "ON" : "OFF"
1363
- }
1364
- ) : param.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1365
- "select",
1366
- {
1367
- value: localParameterValues[param.id] || param.value,
1368
- onChange: (e) => {
1369
- handleParameterInput(param.id, e.target.value);
1370
- handleParameterCommit(param.id, e.target.value);
1371
- },
1372
- disabled: param.readOnly,
1373
- style: {
1374
- width: "100%",
1375
- height: touchSize,
1376
- backgroundColor: surfaceColor,
1377
- color: textColor,
1378
- border: `1px solid ${borderColor}`,
1379
- borderRadius: "4px",
1380
- padding: "0 12px",
1381
- fontSize: "12px",
1382
- fontFamily: "monospace",
1383
- cursor: "pointer"
1384
- },
1385
- children: param.options?.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: opt.value, children: opt.label }, opt.value))
1386
- }
1387
- ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1388
- "input",
1389
- {
1390
- type: param.type === "number" ? "number" : "text",
1391
- value: localParameterValues[param.id] ?? param.value,
1392
- onChange: (e) => handleParameterInput(
1393
- param.id,
1394
- param.type === "number" ? +e.target.value : e.target.value
1395
- ),
1396
- onBlur: () => handleParameterCommit(param.id, localParameterValues[param.id]),
1397
- disabled: param.readOnly,
1398
- min: param.min,
1399
- max: param.max,
1400
- step: param.step,
1401
- style: {
1402
- width: "100%",
1403
- height: touchSize,
1404
- backgroundColor: "#ffffff",
1405
- color: textColor,
1406
- border: `1px solid ${borderColor}`,
1407
- borderRadius: "6px",
1408
- padding: "0 12px",
1409
- fontSize: "14px",
1410
- fontFamily: "Arial, sans-serif",
1411
- fontWeight: 600
1442
+ onBlur: () => handleParameterCommit(param.id, localParameterValues[param.id]),
1443
+ disabled: param.readOnly,
1444
+ min: param.min,
1445
+ max: param.max,
1446
+ step: param.step,
1447
+ style: {
1448
+ width: "100%",
1449
+ height: touchSize,
1450
+ backgroundColor: "#ffffff",
1451
+ color: textColor,
1452
+ border: `1px solid ${borderColor}`,
1453
+ borderRadius: "6px",
1454
+ padding: "0 12px",
1455
+ fontSize: `${fontSize.input}px`,
1456
+ fontFamily: "Arial, sans-serif",
1457
+ fontWeight: 600
1458
+ }
1412
1459
  }
1413
- }
1414
- )
1415
- ]
1416
- },
1417
- param.id
1418
- ))
1419
- ] }),
1420
- binding.display?.showStartStop !== false && (activeCapabilities?.canStart || activeCapabilities?.canStop) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: "8px", marginBottom: "16px" }, children: [
1421
- activeCapabilities?.canStart && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1422
- "button",
1423
- {
1424
- onClick: onStart,
1425
- disabled: binding.state.isRunning,
1426
- style: {
1427
- flex: 1,
1428
- height: touchSize,
1429
- backgroundColor: binding.state.isRunning ? "#a3a3a3" : "#10b981",
1430
- color: "#ffffff",
1431
- border: "none",
1432
- borderRadius: "6px",
1433
- fontSize: "12px",
1434
- fontWeight: 700,
1435
- fontFamily: "Arial, sans-serif",
1436
- letterSpacing: "0.5px",
1437
- cursor: binding.state.isRunning ? "not-allowed" : "pointer",
1438
- opacity: binding.state.isRunning ? 0.5 : 1
1460
+ )
1461
+ ]
1439
1462
  },
1440
- children: "START"
1441
- }
1442
- ),
1443
- activeCapabilities?.canStop && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1463
+ param.id
1464
+ ))
1465
+ ] }),
1466
+ binding.display?.showStartStop !== false && (activeCapabilities?.canStart || activeCapabilities?.canStop) && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: spacing.gap, marginBottom: spacing.marginBottom }, children: [
1467
+ activeCapabilities?.canStart && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1468
+ "button",
1469
+ {
1470
+ onClick: onStart,
1471
+ disabled: binding.state.isRunning,
1472
+ style: {
1473
+ flex: 1,
1474
+ height: touchSize,
1475
+ backgroundColor: binding.state.isRunning ? "#a3a3a3" : "#10b981",
1476
+ color: "#ffffff",
1477
+ border: "none",
1478
+ borderRadius: "6px",
1479
+ fontSize: "12px",
1480
+ fontWeight: 700,
1481
+ fontFamily: "Arial, sans-serif",
1482
+ letterSpacing: "0.5px",
1483
+ cursor: binding.state.isRunning ? "not-allowed" : "pointer",
1484
+ opacity: binding.state.isRunning ? 0.5 : 1
1485
+ },
1486
+ children: "START"
1487
+ }
1488
+ ),
1489
+ activeCapabilities?.canStop && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1490
+ "button",
1491
+ {
1492
+ onClick: onStop,
1493
+ disabled: !binding.state.isRunning,
1494
+ style: {
1495
+ flex: 1,
1496
+ height: touchSize,
1497
+ backgroundColor: !binding.state.isRunning ? "#a3a3a3" : "#ef4444",
1498
+ color: "#ffffff",
1499
+ border: "none",
1500
+ borderRadius: "6px",
1501
+ fontSize: "12px",
1502
+ fontWeight: 700,
1503
+ fontFamily: "Arial, sans-serif",
1504
+ letterSpacing: "0.5px",
1505
+ cursor: !binding.state.isRunning ? "not-allowed" : "pointer",
1506
+ opacity: !binding.state.isRunning ? 0.5 : 1
1507
+ },
1508
+ children: "STOP"
1509
+ }
1510
+ )
1511
+ ] }),
1512
+ activeCapabilities?.customActions && activeCapabilities.customActions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "8px" }, children: activeCapabilities.customActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1444
1513
  "button",
1445
1514
  {
1446
- onClick: onStop,
1447
- disabled: !binding.state.isRunning,
1515
+ onClick: () => onCustomAction?.(action.id),
1448
1516
  style: {
1449
1517
  flex: 1,
1518
+ minWidth: "120px",
1450
1519
  height: touchSize,
1451
- backgroundColor: !binding.state.isRunning ? "#a3a3a3" : "#ef4444",
1452
- color: "#ffffff",
1453
- border: "none",
1520
+ backgroundColor: surfaceColor,
1521
+ color: textColor,
1522
+ border: `1px solid ${borderColor}`,
1454
1523
  borderRadius: "6px",
1455
- fontSize: "12px",
1456
- fontWeight: 700,
1457
- fontFamily: "Arial, sans-serif",
1524
+ fontSize: "11px",
1525
+ fontWeight: 600,
1526
+ fontFamily: "monospace",
1458
1527
  letterSpacing: "0.5px",
1459
- cursor: !binding.state.isRunning ? "not-allowed" : "pointer",
1460
- opacity: !binding.state.isRunning ? 0.5 : 1
1528
+ textTransform: "uppercase",
1529
+ cursor: "pointer",
1530
+ transition: "all 0.15s"
1461
1531
  },
1462
- children: "STOP"
1463
- }
1464
- )
1465
- ] }),
1466
- activeCapabilities?.customActions && activeCapabilities.customActions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: "8px" }, children: activeCapabilities.customActions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1467
- "button",
1468
- {
1469
- onClick: () => onCustomAction?.(action.id),
1470
- style: {
1471
- flex: 1,
1472
- minWidth: "120px",
1473
- height: touchSize,
1474
- backgroundColor: surfaceColor,
1475
- color: textColor,
1476
- border: `1px solid ${borderColor}`,
1477
- borderRadius: "6px",
1478
- fontSize: "11px",
1479
- fontWeight: 600,
1480
- fontFamily: "monospace",
1481
- letterSpacing: "0.5px",
1482
- textTransform: "uppercase",
1483
- cursor: "pointer",
1484
- transition: "all 0.15s"
1532
+ children: [
1533
+ action.icon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { marginRight: "6px" }, children: action.icon }),
1534
+ action.label
1535
+ ]
1485
1536
  },
1486
- children: [
1487
- action.icon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { marginRight: "6px" }, children: action.icon }),
1488
- action.label
1489
- ]
1490
- },
1491
- action.id
1492
- )) }),
1493
- binding.state.lastCommandResult && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1537
+ action.id
1538
+ )) })
1539
+ ] }),
1540
+ binding.state.lastCommandResult && showToast && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1494
1541
  "div",
1495
1542
  {
1496
1543
  style: {
1497
- marginTop: "16px",
1498
- padding: "10px 12px",
1499
- backgroundColor: surfaceColor,
1500
- border: `1px solid ${binding.state.lastCommandResult.success ? "#52525b" : borderColor}`,
1501
- borderRadius: "4px",
1502
- fontSize: "11px",
1503
- fontFamily: "monospace",
1504
- color: binding.state.lastCommandResult.success ? textColor : mutedTextColor
1544
+ position: "fixed",
1545
+ bottom: "20px",
1546
+ ...position === "bottom" && align === "right" ? { left: "20px", right: "auto" } : { right: "20px", left: "auto" },
1547
+ // Default to right
1548
+ maxWidth: "400px",
1549
+ padding: "12px 16px",
1550
+ backgroundColor: binding.state.lastCommandResult.success ? "#10b981" : "#ef4444",
1551
+ color: "#ffffff",
1552
+ border: "none",
1553
+ borderRadius: "8px",
1554
+ fontSize: `${fontSize.label}px`,
1555
+ fontFamily: "Arial, sans-serif",
1556
+ fontWeight: 600,
1557
+ boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
1558
+ zIndex: 1e4,
1559
+ animation: position === "bottom" && align === "right" ? "slideInToastLeft 0.3s ease-out" : "slideInToast 0.3s ease-out"
1505
1560
  },
1506
1561
  children: binding.state.lastCommandResult.message
1507
1562
  }
1508
1563
  ),
1509
1564
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("style", { children: `
1510
- @keyframes slideUp {
1511
- from { transform: translateY(100%); }
1512
- to { transform: translateY(0); }
1565
+ @keyframes slideInToast {
1566
+ from {
1567
+ opacity: 0;
1568
+ transform: translateX(20px);
1569
+ }
1570
+ to {
1571
+ opacity: 1;
1572
+ transform: translateX(0);
1573
+ }
1574
+ }
1575
+ @keyframes slideInToastLeft {
1576
+ from {
1577
+ opacity: 0;
1578
+ transform: translateX(-20px);
1513
1579
  }
1514
- @keyframes slideIn {
1515
- from { transform: translateX(100%); }
1516
- to { transform: translateX(0); }
1580
+ to {
1581
+ opacity: 1;
1582
+ transform: translateX(0);
1517
1583
  }
1518
- ` })
1519
- ] }) });
1584
+ }
1585
+ @keyframes slideUp {
1586
+ from { transform: translateY(100%); }
1587
+ to { transform: translateY(0); }
1588
+ }
1589
+ @keyframes slideIn {
1590
+ from { transform: translateX(100%); }
1591
+ to { transform: translateX(0); }
1592
+ }
1593
+ ` })
1594
+ ] });
1520
1595
  }
1521
1596
 
1522
1597
  // src/components/layout/FullscreenWorkspace/FullscreenWorkspace.tsx