@vention/machine-apps-components 1.10.0 → 1.11.0

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/index.esm.js CHANGED
@@ -10,10 +10,11 @@ import 'dayjs/locale/en';
10
10
  import 'dayjs/locale/fr';
11
11
  import 'dayjs/locale/de';
12
12
  import 'dayjs/locale/es';
13
- import { Box, useTheme, Typography, Button, InputAdornment, IconButton, TableContainer, Paper, Table, TableHead, TableRow, TableCell, TableBody, List, ListItem, Dialog, DialogTitle, DialogContent, DialogActions } from '@mui/material';
13
+ import { Box, useTheme, Typography, Button, InputAdornment, IconButton, TableContainer, Paper, Table, TableHead, TableRow, TableCell, TableBody, List, ListItem, Dialog, DialogTitle, DialogContent, DialogActions, CircularProgress, Alert, LinearProgress } from '@mui/material';
14
14
  import { VentionSelect, VentionModalBase, VentionIcon, VentionTextInput, COLORS, VentionButton, VentionStatusIndicator, VentionSpinner, VentionAlert, VentionDropZone, VentionUploadFile, VentionIconButton } from '@vention/machine-ui';
15
15
  import { tss } from 'tss-react/mui';
16
16
  import { useLocation, useNavigate } from 'react-router-dom';
17
+ import { useMqttSubscription } from '@vention/machine-logic-ui-sdk';
17
18
 
18
19
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
19
20
 
@@ -1850,6 +1851,42 @@ var enTranslations = {
1850
1851
  delete: "Delete",
1851
1852
  deleteConfirmation: "Are you sure you want to delete this item?",
1852
1853
  emptyState: "No items yet. Click Add to create one."
1854
+ },
1855
+ calibration: {
1856
+ footer: {
1857
+ loading: "Working...",
1858
+ cancel: "Cancel",
1859
+ neverCompleted: "Not calibrated yet",
1860
+ lastCompleted: "Last calibrated"
1861
+ },
1862
+ handEye: {
1863
+ calibrate: {
1864
+ calibrate: "Calibrate",
1865
+ update: "Update calibration",
1866
+ cancel: "Cancel calibration",
1867
+ cancelling: "Cancelling...",
1868
+ running: "{{percent}}% Completed",
1869
+ lastCalibratedOn: "Calibrated on {{date}}",
1870
+ never: "Not calibrated"
1871
+ },
1872
+ verify: {
1873
+ action: "Verify calibration",
1874
+ loading: "Verifying..."
1875
+ }
1876
+ },
1877
+ environment: {
1878
+ topAlert: "Before starting environment calibration, please contact Vention's team for assistance.",
1879
+ helper: "Enable free drive and move the robot to take photos covering the entire environment, including walls, bins, machines.",
1880
+ startSession: "Start new session",
1881
+ starting: "Starting...",
1882
+ takePhoto: "Take photo",
1883
+ endSession: "End session",
1884
+ sessionLabel: "Session",
1885
+ photoCount: "{{count}} photo(s) saved",
1886
+ noPhotos: "No photos captured yet",
1887
+ lastPhotoAt: "last on {{date}}",
1888
+ error: "Environment scan failed. Reset the bin and retry."
1889
+ }
1853
1890
  }
1854
1891
  };
1855
1892
 
@@ -1991,6 +2028,42 @@ var frTranslations = {
1991
2028
  delete: "Supprimer",
1992
2029
  deleteConfirmation: "Êtes-vous sûr de vouloir supprimer cet élément?",
1993
2030
  emptyState: "Aucun élément. Cliquez sur Ajouter pour en créer un."
2031
+ },
2032
+ calibration: {
2033
+ footer: {
2034
+ loading: "En cours...",
2035
+ cancel: "Annuler",
2036
+ neverCompleted: "Non calibré",
2037
+ lastCompleted: "Dernier calibrage"
2038
+ },
2039
+ handEye: {
2040
+ calibrate: {
2041
+ calibrate: "Calibrer",
2042
+ update: "Mettre à jour le calibrage",
2043
+ cancel: "Annuler le calibrage",
2044
+ cancelling: "Annulation...",
2045
+ running: "{{percent}} % effectué",
2046
+ lastCalibratedOn: "Calibré le {{date}}",
2047
+ never: "Non calibré"
2048
+ },
2049
+ verify: {
2050
+ action: "Vérifier le calibrage",
2051
+ loading: "Vérification..."
2052
+ }
2053
+ },
2054
+ environment: {
2055
+ topAlert: "Avant de démarrer le calibrage de l'environnement, veuillez contacter l'équipe Vention.",
2056
+ helper: "Activez le free drive et déplacez le robot pour prendre des photos couvrant tout l'environnement : murs, bacs, machines.",
2057
+ startSession: "Démarrer une session",
2058
+ starting: "Démarrage...",
2059
+ takePhoto: "Prendre une photo",
2060
+ endSession: "Terminer la session",
2061
+ sessionLabel: "Session",
2062
+ photoCount: "{{count}} photo(s) enregistrée(s)",
2063
+ noPhotos: "Aucune photo capturée",
2064
+ lastPhotoAt: "dernière le {{date}}",
2065
+ error: "Échec du balayage de l'environnement. Réinitialisez le bac et réessayez."
2066
+ }
1994
2067
  }
1995
2068
  };
1996
2069
 
@@ -2132,6 +2205,42 @@ var deTranslations = {
2132
2205
  delete: "Löschen",
2133
2206
  deleteConfirmation: "Sind Sie sicher, dass Sie dieses Element löschen möchten?",
2134
2207
  emptyState: "Noch keine Elemente. Klicken Sie auf Hinzufügen, um eines zu erstellen."
2208
+ },
2209
+ calibration: {
2210
+ footer: {
2211
+ loading: "Läuft...",
2212
+ cancel: "Abbrechen",
2213
+ neverCompleted: "Nicht kalibriert",
2214
+ lastCompleted: "Zuletzt kalibriert"
2215
+ },
2216
+ handEye: {
2217
+ calibrate: {
2218
+ calibrate: "Kalibrieren",
2219
+ update: "Kalibrierung aktualisieren",
2220
+ cancel: "Kalibrierung abbrechen",
2221
+ cancelling: "Abbrechen...",
2222
+ running: "{{percent}}% abgeschlossen",
2223
+ lastCalibratedOn: "Kalibriert am {{date}}",
2224
+ never: "Nicht kalibriert"
2225
+ },
2226
+ verify: {
2227
+ action: "Kalibrierung prüfen",
2228
+ loading: "Prüfung läuft..."
2229
+ }
2230
+ },
2231
+ environment: {
2232
+ topAlert: "Bitte kontaktieren Sie das Vention-Team, bevor Sie die Umgebungskalibrierung starten.",
2233
+ helper: "Aktivieren Sie Free Drive und bewegen Sie den Roboter, um Fotos der gesamten Umgebung aufzunehmen — Wände, Bins, Maschinen.",
2234
+ startSession: "Neue Sitzung starten",
2235
+ starting: "Wird gestartet...",
2236
+ takePhoto: "Foto aufnehmen",
2237
+ endSession: "Sitzung beenden",
2238
+ sessionLabel: "Sitzung",
2239
+ photoCount: "{{count}} Foto(s) gespeichert",
2240
+ noPhotos: "Noch keine Fotos aufgenommen",
2241
+ lastPhotoAt: "zuletzt am {{date}}",
2242
+ error: "Umgebungsscan fehlgeschlagen. Bin zurücksetzen und erneut versuchen."
2243
+ }
2135
2244
  }
2136
2245
  };
2137
2246
 
@@ -2273,6 +2382,42 @@ var esTranslations = {
2273
2382
  delete: "Eliminar",
2274
2383
  deleteConfirmation: "¿Está seguro de que desea eliminar este elemento?",
2275
2384
  emptyState: "Aún no hay elementos. Haz clic en Agregar para crear uno."
2385
+ },
2386
+ calibration: {
2387
+ footer: {
2388
+ loading: "En curso...",
2389
+ cancel: "Cancelar",
2390
+ neverCompleted: "Sin calibrar",
2391
+ lastCompleted: "Última calibración"
2392
+ },
2393
+ handEye: {
2394
+ calibrate: {
2395
+ calibrate: "Calibrar",
2396
+ update: "Actualizar calibración",
2397
+ cancel: "Cancelar calibración",
2398
+ cancelling: "Cancelando...",
2399
+ running: "{{percent}}% completado",
2400
+ lastCalibratedOn: "Calibrado el {{date}}",
2401
+ never: "Sin calibrar"
2402
+ },
2403
+ verify: {
2404
+ action: "Verificar calibración",
2405
+ loading: "Verificando..."
2406
+ }
2407
+ },
2408
+ environment: {
2409
+ topAlert: "Antes de iniciar la calibración del entorno, contacta al equipo de Vention.",
2410
+ helper: "Activa el free drive y mueve el robot para tomar fotos que cubran todo el entorno — paredes, contenedores, máquinas.",
2411
+ startSession: "Iniciar nueva sesión",
2412
+ starting: "Iniciando...",
2413
+ takePhoto: "Tomar foto",
2414
+ endSession: "Terminar sesión",
2415
+ sessionLabel: "Sesión",
2416
+ photoCount: "{{count}} foto(s) guardada(s)",
2417
+ noPhotos: "Sin fotos aún",
2418
+ lastPhotoAt: "última el {{date}}",
2419
+ error: "Falló el escaneo del entorno. Restablece el contenedor y vuelve a intentarlo."
2420
+ }
2276
2421
  }
2277
2422
  };
2278
2423
 
@@ -3048,7 +3193,7 @@ const I18nSettings = function I18nSettings({
3048
3193
  const {
3049
3194
  classes,
3050
3195
  cx
3051
- } = useStyles$h({
3196
+ } = useStyles$k({
3052
3197
  layout
3053
3198
  });
3054
3199
  const {
@@ -3138,7 +3283,7 @@ const I18nSettings = function I18nSettings({
3138
3283
  });
3139
3284
  };
3140
3285
  I18nSettings.displayName = "I18nSettings";
3141
- const useStyles$h = tss.withParams().create(({
3286
+ const useStyles$k = tss.withParams().create(({
3142
3287
  theme,
3143
3288
  layout
3144
3289
  }) => ({
@@ -5599,7 +5744,7 @@ const NavigationConfirmationModal = function NavigationConfirmationModal(props)
5599
5744
  } = props;
5600
5745
  const {
5601
5746
  classes
5602
- } = useStyles$g();
5747
+ } = useStyles$j();
5603
5748
  const {
5604
5749
  t
5605
5750
  } = useI18n();
@@ -5662,7 +5807,7 @@ const NavigationConfirmationModal = function NavigationConfirmationModal(props)
5662
5807
  })
5663
5808
  });
5664
5809
  };
5665
- const useStyles$g = tss.create(({
5810
+ const useStyles$j = tss.create(({
5666
5811
  theme
5667
5812
  }) => ({
5668
5813
  modalContent: {
@@ -5726,7 +5871,7 @@ const PasswordProtectionModal = function PasswordProtectionModal(props) {
5726
5871
  const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);
5727
5872
  const {
5728
5873
  classes
5729
- } = useStyles$f();
5874
+ } = useStyles$i();
5730
5875
  const {
5731
5876
  t
5732
5877
  } = useI18n();
@@ -5850,7 +5995,7 @@ const PasswordProtectionModal = function PasswordProtectionModal(props) {
5850
5995
  })]
5851
5996
  });
5852
5997
  };
5853
- const useStyles$f = tss.create(({
5998
+ const useStyles$i = tss.create(({
5854
5999
  theme
5855
6000
  }) => ({
5856
6001
  modalContent: {
@@ -5922,7 +6067,7 @@ const NavigationBarItem = function NavigationBarItem(props) {
5922
6067
  const {
5923
6068
  classes,
5924
6069
  cx
5925
- } = useStyles$e();
6070
+ } = useStyles$h();
5926
6071
  const {
5927
6072
  t
5928
6073
  } = useI18n();
@@ -5955,7 +6100,7 @@ const NavigationBarItem = function NavigationBarItem(props) {
5955
6100
  })]
5956
6101
  });
5957
6102
  };
5958
- const useStyles$e = tss.create(({
6103
+ const useStyles$h = tss.create(({
5959
6104
  theme
5960
6105
  }) => ({
5961
6106
  tabButton: {
@@ -6026,7 +6171,7 @@ const NavigationBarRoot = function NavigationBarRoot(props) {
6026
6171
  const theme = useTheme();
6027
6172
  const {
6028
6173
  classes
6029
- } = useStyles$d({
6174
+ } = useStyles$g({
6030
6175
  variant
6031
6176
  });
6032
6177
  const {
@@ -6167,7 +6312,7 @@ const NavigationBarRoot = function NavigationBarRoot(props) {
6167
6312
  })]
6168
6313
  });
6169
6314
  };
6170
- const useStyles$d = tss.withParams().create(({
6315
+ const useStyles$g = tss.withParams().create(({
6171
6316
  theme,
6172
6317
  variant
6173
6318
  }) => ({
@@ -6327,7 +6472,7 @@ const StatusTopBarButton = function StatusTopBarButton(props) {
6327
6472
  } = props;
6328
6473
  const {
6329
6474
  classes
6330
- } = useStyles$c();
6475
+ } = useStyles$f();
6331
6476
  if (!visible) return null;
6332
6477
  const getFadedColor = function getFadedColor(color, opacity = 1) {
6333
6478
  return `${color}${Math.round(opacity * 255).toString(16).padStart(2, "0")}`;
@@ -6373,7 +6518,7 @@ const StatusTopBarButton = function StatusTopBarButton(props) {
6373
6518
  })
6374
6519
  });
6375
6520
  };
6376
- const useStyles$c = tss.create(({
6521
+ const useStyles$f = tss.create(({
6377
6522
  theme
6378
6523
  }) => ({
6379
6524
  actionButton: {
@@ -6409,7 +6554,7 @@ const StatusTopBarRoot = function StatusTopBarRoot(props) {
6409
6554
  } = props;
6410
6555
  const {
6411
6556
  classes
6412
- } = useStyles$b({
6557
+ } = useStyles$e({
6413
6558
  variant
6414
6559
  });
6415
6560
  const visibleButtons = buttonConfigs.filter(config => config.visible !== false);
@@ -6436,7 +6581,7 @@ const StatusTopBarRoot = function StatusTopBarRoot(props) {
6436
6581
  })]
6437
6582
  });
6438
6583
  };
6439
- const useStyles$b = tss.withParams().create(({
6584
+ const useStyles$e = tss.withParams().create(({
6440
6585
  theme,
6441
6586
  variant
6442
6587
  }) => ({
@@ -6485,7 +6630,7 @@ const Sidebar = function Sidebar(props) {
6485
6630
  } = props;
6486
6631
  const {
6487
6632
  classes
6488
- } = useStyles$a({
6633
+ } = useStyles$d({
6489
6634
  variant
6490
6635
  });
6491
6636
  return jsx(Box, {
@@ -6549,7 +6694,7 @@ const SidebarItemComponent = function SidebarItemComponent(props) {
6549
6694
  })
6550
6695
  });
6551
6696
  };
6552
- const useStyles$a = tss.withParams().create(({
6697
+ const useStyles$d = tss.withParams().create(({
6553
6698
  theme,
6554
6699
  variant
6555
6700
  }) => ({
@@ -6741,7 +6886,7 @@ const LogsTable = /*#__PURE__*/memo(({
6741
6886
  const {
6742
6887
  classes,
6743
6888
  cx
6744
- } = useStyles$9({
6889
+ } = useStyles$c({
6745
6890
  tableHeight
6746
6891
  });
6747
6892
  const theme = useTheme();
@@ -7014,7 +7159,7 @@ const LogsTable = /*#__PURE__*/memo(({
7014
7159
  });
7015
7160
  });
7016
7161
  LogsTable.displayName = "LogsTable";
7017
- const useStyles$9 = tss.withParams().create(({
7162
+ const useStyles$c = tss.withParams().create(({
7018
7163
  theme,
7019
7164
  tableHeight
7020
7165
  }) => ({
@@ -7157,7 +7302,7 @@ const LogFilterForm = /*#__PURE__*/memo(({
7157
7302
  var _a, _b, _c, _d;
7158
7303
  const {
7159
7304
  classes
7160
- } = useStyles$8();
7305
+ } = useStyles$b();
7161
7306
  const {
7162
7307
  t
7163
7308
  } = useI18n();
@@ -7294,7 +7439,7 @@ const LogFilterForm = /*#__PURE__*/memo(({
7294
7439
  });
7295
7440
  });
7296
7441
  LogFilterForm.displayName = "LogFilterForm";
7297
- const useStyles$8 = tss.create(({
7442
+ const useStyles$b = tss.create(({
7298
7443
  theme
7299
7444
  }) => ({
7300
7445
  filterSection: {
@@ -7570,7 +7715,7 @@ const LogsPagination = /*#__PURE__*/memo(({
7570
7715
  }) => {
7571
7716
  const {
7572
7717
  classes
7573
- } = useStyles$7();
7718
+ } = useStyles$a();
7574
7719
  const {
7575
7720
  t
7576
7721
  } = useI18n();
@@ -7609,7 +7754,7 @@ const LogsPagination = /*#__PURE__*/memo(({
7609
7754
  });
7610
7755
  });
7611
7756
  LogsPagination.displayName = "LogsPagination";
7612
- const useStyles$7 = tss.create(({
7757
+ const useStyles$a = tss.create(({
7613
7758
  theme
7614
7759
  }) => ({
7615
7760
  paginationSection: {
@@ -7660,7 +7805,7 @@ const LogsPanel = /*#__PURE__*/forwardRef((props, ref) => {
7660
7805
  const {
7661
7806
  classes,
7662
7807
  cx
7663
- } = useStyles$6();
7808
+ } = useStyles$9();
7664
7809
  const [logs, setLogs] = useState([]);
7665
7810
  const [isLoading, setIsLoading] = useState(true);
7666
7811
  const [error, setError] = useState(null);
@@ -7796,7 +7941,7 @@ const LogsPanel = /*#__PURE__*/forwardRef((props, ref) => {
7796
7941
  });
7797
7942
  });
7798
7943
  LogsPanel.displayName = "LogsPanel";
7799
- const useStyles$6 = tss.create(({
7944
+ const useStyles$9 = tss.create(({
7800
7945
  theme
7801
7946
  }) => ({
7802
7947
  root: {
@@ -7814,7 +7959,7 @@ const SettingsPage = function SettingsPage({
7814
7959
  }) {
7815
7960
  const {
7816
7961
  classes
7817
- } = useStyles$5({
7962
+ } = useStyles$8({
7818
7963
  sidebarWidth
7819
7964
  });
7820
7965
  return jsxs(Box, {
@@ -7831,7 +7976,7 @@ const SettingsPage = function SettingsPage({
7831
7976
  });
7832
7977
  };
7833
7978
  SettingsPage.displayName = "SettingsPage";
7834
- const useStyles$5 = tss.withParams().create(({
7979
+ const useStyles$8 = tss.withParams().create(({
7835
7980
  theme,
7836
7981
  sidebarWidth
7837
7982
  }) => ({
@@ -7877,7 +8022,7 @@ function FileUploadPanel({
7877
8022
  const {
7878
8023
  classes,
7879
8024
  cx
7880
- } = useStyles$4({
8025
+ } = useStyles$7({
7881
8026
  maxHeight
7882
8027
  });
7883
8028
  const {
@@ -7930,7 +8075,7 @@ function FileUploadPanel({
7930
8075
  });
7931
8076
  }
7932
8077
  FileUploadPanel.displayName = "FileUploadPanel";
7933
- const useStyles$4 = tss.withParams().create(({
8078
+ const useStyles$7 = tss.withParams().create(({
7934
8079
  theme,
7935
8080
  maxHeight
7936
8081
  }) => ({
@@ -7981,7 +8126,7 @@ function StepProgressCircle({
7981
8126
  const {
7982
8127
  classes,
7983
8128
  cx
7984
- } = useStyles$3({
8129
+ } = useStyles$6({
7985
8130
  size,
7986
8131
  strokeWidth,
7987
8132
  variant
@@ -8039,7 +8184,7 @@ function StepProgressCircle({
8039
8184
  });
8040
8185
  }
8041
8186
  StepProgressCircle.displayName = "StepProgressCircle";
8042
- const useStyles$3 = tss.withParams().create(({
8187
+ const useStyles$6 = tss.withParams().create(({
8043
8188
  theme,
8044
8189
  size,
8045
8190
  strokeWidth,
@@ -8109,7 +8254,7 @@ const ActionButton = function ActionButton({
8109
8254
  const {
8110
8255
  classes,
8111
8256
  cx
8112
- } = useStyles$2({
8257
+ } = useStyles$5({
8113
8258
  size
8114
8259
  });
8115
8260
  const {
@@ -8141,7 +8286,7 @@ const ActionButton = function ActionButton({
8141
8286
  });
8142
8287
  };
8143
8288
  ActionButton.displayName = "ActionButton";
8144
- const useStyles$2 = tss.withParams().create(({
8289
+ const useStyles$5 = tss.withParams().create(({
8145
8290
  theme,
8146
8291
  size
8147
8292
  }) => ({
@@ -8185,7 +8330,7 @@ const PressButton = function PressButton({
8185
8330
  const {
8186
8331
  classes,
8187
8332
  cx
8188
- } = useStyles$1({
8333
+ } = useStyles$4({
8189
8334
  size
8190
8335
  });
8191
8336
  const {
@@ -8257,7 +8402,7 @@ const PressButton = function PressButton({
8257
8402
  });
8258
8403
  };
8259
8404
  PressButton.displayName = "PressButton";
8260
- const useStyles$1 = tss.withParams().create(({
8405
+ const useStyles$4 = tss.withParams().create(({
8261
8406
  theme,
8262
8407
  size
8263
8408
  }) => ({
@@ -8436,7 +8581,7 @@ function ProductFormListComponent({
8436
8581
  const {
8437
8582
  classes,
8438
8583
  cx
8439
- } = useStyles({
8584
+ } = useStyles$3({
8440
8585
  maxHeight
8441
8586
  });
8442
8587
  useAutoScrollInput(editDialogOpen);
@@ -8656,7 +8801,7 @@ function ProductFormListComponent({
8656
8801
  }
8657
8802
  ProductFormListComponent.displayName = "ProductFormList";
8658
8803
  const ProductFormList = /*#__PURE__*/memo(ProductFormListComponent);
8659
- const useStyles = tss.withParams().create(({
8804
+ const useStyles$3 = tss.withParams().create(({
8660
8805
  theme,
8661
8806
  maxHeight
8662
8807
  }) => ({
@@ -8738,6 +8883,673 @@ const useStyles = tss.withParams().create(({
8738
8883
  }
8739
8884
  }));
8740
8885
 
8886
+ const TIMESTAMP_FORMAT$2 = "MM/DD/YYYY, hh:mm:ss A";
8887
+ const CalibrationFooter = function CalibrationFooter({
8888
+ primaryLabel,
8889
+ onPrimaryAction,
8890
+ isLoading = false,
8891
+ loadingLabel,
8892
+ disabled = false,
8893
+ onCancel,
8894
+ cancelLabel,
8895
+ lastCompletedAt,
8896
+ completedLabelPrefix,
8897
+ neverCompletedLabel,
8898
+ className,
8899
+ sx,
8900
+ "data-testid": dataTestId = "calibration-footer"
8901
+ }) {
8902
+ const {
8903
+ classes,
8904
+ cx
8905
+ } = useStyles$2();
8906
+ const {
8907
+ t
8908
+ } = useTranslation();
8909
+ const resolvedLoadingLabel = loadingLabel !== null && loadingLabel !== void 0 ? loadingLabel : t("calibration.footer.loading", {
8910
+ defaultValue: "Working..."
8911
+ });
8912
+ const resolvedCancelLabel = cancelLabel !== null && cancelLabel !== void 0 ? cancelLabel : t("calibration.footer.cancel", {
8913
+ defaultValue: "Cancel"
8914
+ });
8915
+ const resolvedNeverCompletedLabel = neverCompletedLabel !== null && neverCompletedLabel !== void 0 ? neverCompletedLabel : t("calibration.footer.neverCompleted", {
8916
+ defaultValue: "Not calibrated yet"
8917
+ });
8918
+ const resolvedCompletedPrefix = completedLabelPrefix !== null && completedLabelPrefix !== void 0 ? completedLabelPrefix : t("calibration.footer.lastCompleted", {
8919
+ defaultValue: "Last calibrated"
8920
+ });
8921
+ const showCancel = isLoading && typeof onCancel === "function";
8922
+ return jsxs(Box, {
8923
+ className: cx(classes.root, className),
8924
+ sx: sx,
8925
+ "data-testid": dataTestId,
8926
+ children: [jsxs(Box, {
8927
+ className: classes.buttonRow,
8928
+ children: [showCancel ? jsx(VentionButton, {
8929
+ onClick: onCancel,
8930
+ variant: "outline",
8931
+ size: "large",
8932
+ "data-testid": `${dataTestId}-cancel`,
8933
+ children: resolvedCancelLabel
8934
+ }) : null, jsx(VentionButton, {
8935
+ onClick: onPrimaryAction,
8936
+ disabled: disabled || isLoading,
8937
+ variant: "filled",
8938
+ size: "large",
8939
+ startIcon: isLoading ? jsx(CircularProgress, {
8940
+ size: 16,
8941
+ color: "inherit"
8942
+ }) : undefined,
8943
+ "data-testid": `${dataTestId}-primary`,
8944
+ children: isLoading ? resolvedLoadingLabel : primaryLabel
8945
+ })]
8946
+ }), jsx(Box, {
8947
+ className: classes.statusRow,
8948
+ "data-testid": `${dataTestId}-status`,
8949
+ children: lastCompletedAt ? jsxs(Fragment, {
8950
+ children: [jsx(VentionIcon, {
8951
+ type: "circle-check-filled",
8952
+ size: 20,
8953
+ color: "status.success"
8954
+ }), jsxs(Typography, {
8955
+ variant: "uiText14SemiBold",
8956
+ className: classes.statusText,
8957
+ children: [resolvedCompletedPrefix, " ", dayjs(lastCompletedAt).format(TIMESTAMP_FORMAT$2)]
8958
+ })]
8959
+ }) : jsx(Typography, {
8960
+ variant: "uiText14SemiBold",
8961
+ className: classes.statusTextMuted,
8962
+ children: resolvedNeverCompletedLabel
8963
+ })
8964
+ })]
8965
+ });
8966
+ };
8967
+ CalibrationFooter.displayName = "CalibrationFooter";
8968
+ const useStyles$2 = tss.create(({
8969
+ theme
8970
+ }) => ({
8971
+ root: {
8972
+ display: "flex",
8973
+ flexDirection: "column",
8974
+ alignItems: "center",
8975
+ gap: theme.spacing(2)
8976
+ },
8977
+ buttonRow: {
8978
+ display: "flex",
8979
+ alignItems: "center",
8980
+ gap: theme.spacing(2)
8981
+ },
8982
+ statusRow: {
8983
+ display: "flex",
8984
+ alignItems: "center",
8985
+ gap: theme.spacing(1)
8986
+ },
8987
+ statusText: {
8988
+ color: theme.palette.text.primary
8989
+ },
8990
+ statusTextMuted: {
8991
+ color: theme.palette.text.secondary
8992
+ }
8993
+ }));
8994
+
8995
+ // MQTT topics for calibration progress events.
8996
+ //
8997
+ // These topics are the contract between `griip_sdk` (which publishes via
8998
+ // paho-mqtt) and this React library (which subscribes via @vention/machine-logic-ui-sdk).
8999
+ // Keep this file and `griip_sdk/calibration/mqtt_topics.py` in sync.
9000
+ const HAND_EYE_PROGRESS_TOPIC = "griip/calibration/hand_eye/progress";
9001
+ const ENVIRONMENT_PROGRESS_TOPIC = "griip/calibration/environment/progress";
9002
+
9003
+ const TIMESTAMP_FORMAT$1 = "MM/DD/YYYY, hh:mm:ss A";
9004
+ const MQTT_STATUS_TO_PROGRESS = {
9005
+ in_progress: "running",
9006
+ success: "success",
9007
+ error: "error",
9008
+ cancelled: "cancelled"
9009
+ };
9010
+ function mqttMessageToProgress(message) {
9011
+ return {
9012
+ percent: message.percentage,
9013
+ status: MQTT_STATUS_TO_PROGRESS[message.status],
9014
+ message: message.message
9015
+ };
9016
+ }
9017
+ const STATUS_ALERT = {
9018
+ error: {
9019
+ severity: "error",
9020
+ testId: "calibration-hand-eye-page-error"
9021
+ },
9022
+ success: {
9023
+ severity: "success",
9024
+ testId: "calibration-hand-eye-page-success"
9025
+ },
9026
+ cancelled: {
9027
+ severity: "info",
9028
+ testId: "calibration-hand-eye-page-cancelled"
9029
+ }
9030
+ };
9031
+ const CalibrationHandEyePage = function CalibrationHandEyePage({
9032
+ onCalibrate,
9033
+ onCancel,
9034
+ progress,
9035
+ lastCalibrationAt,
9036
+ forceShowStart = false,
9037
+ disabled = false,
9038
+ error,
9039
+ onError,
9040
+ onVerify,
9041
+ className,
9042
+ sx
9043
+ }) {
9044
+ var _a, _b, _c;
9045
+ const {
9046
+ classes,
9047
+ cx
9048
+ } = useStyles$1();
9049
+ const {
9050
+ t
9051
+ } = useTranslation();
9052
+ const [verifyResult, setVerifyResult] = useState(null);
9053
+ const [isVerifying, setIsVerifying] = useState(false);
9054
+ const [isCancelling, setIsCancelling] = useState(false);
9055
+ const [internalError, setInternalError] = useState(null);
9056
+ // Subscribe to live progress from griip-sdk. If the consumer wraps the app
9057
+ // with <MqttProvider> from @vention/machine-logic-ui-sdk, the SDK's
9058
+ // run_hand_eye_calibration ticks land here automatically. Consumers that
9059
+ // would rather drive progress directly can pass the `progress` prop — it
9060
+ // wins over the MQTT-derived value.
9061
+ const mqttMessage = useMqttSubscription({
9062
+ topic: HAND_EYE_PROGRESS_TOPIC,
9063
+ unsubscribeOnUnmount: true
9064
+ });
9065
+ const effectiveProgress = progress !== null && progress !== void 0 ? progress : mqttMessage ? mqttMessageToProgress(mqttMessage) : undefined;
9066
+ const status = (_a = effectiveProgress === null || effectiveProgress === void 0 ? void 0 : effectiveProgress.status) !== null && _a !== void 0 ? _a : "idle";
9067
+ // `forceShowStart` lets the consumer escape a stale "running" MQTT message
9068
+ // (e.g. on page refresh after a previous run completed but the broker is
9069
+ // retaining the last progress payload).
9070
+ const isRunning = !forceShowStart && status === "running";
9071
+ const isCalibrated = Boolean(lastCalibrationAt);
9072
+ const percent = Math.max(0, Math.min(100, Math.round((_b = effectiveProgress === null || effectiveProgress === void 0 ? void 0 : effectiveProgress.percent) !== null && _b !== void 0 ? _b : 0)));
9073
+ const displayedError = error !== null && error !== void 0 ? error : internalError;
9074
+ const statusAlert = STATUS_ALERT[status];
9075
+ const reportError = raw => {
9076
+ const err = raw instanceof Error ? raw : new Error(String(raw));
9077
+ setInternalError(err.message);
9078
+ onError === null || onError === void 0 ? void 0 : onError(err);
9079
+ };
9080
+ const handleCalibrate = () => __awaiter(this, void 0, void 0, function* () {
9081
+ setInternalError(null);
9082
+ try {
9083
+ yield onCalibrate();
9084
+ } catch (raw) {
9085
+ reportError(raw);
9086
+ }
9087
+ });
9088
+ const handleCancel = () => __awaiter(this, void 0, void 0, function* () {
9089
+ setIsCancelling(true);
9090
+ try {
9091
+ yield onCancel();
9092
+ } catch (raw) {
9093
+ reportError(raw);
9094
+ } finally {
9095
+ setIsCancelling(false);
9096
+ }
9097
+ });
9098
+ const handleVerify = () => __awaiter(this, void 0, void 0, function* () {
9099
+ if (!onVerify) return;
9100
+ setIsVerifying(true);
9101
+ try {
9102
+ const result = yield onVerify();
9103
+ setVerifyResult(result);
9104
+ } catch (raw) {
9105
+ reportError(raw);
9106
+ } finally {
9107
+ setIsVerifying(false);
9108
+ }
9109
+ });
9110
+ const verifyFailing = (verifyResult === null || verifyResult === void 0 ? void 0 : verifyResult.isValid) === false;
9111
+ return jsxs(Box, {
9112
+ className: cx(classes.container, className),
9113
+ sx: sx,
9114
+ "data-testid": "calibration-hand-eye-page",
9115
+ children: [verifyFailing ? jsxs(Box, {
9116
+ className: classes.verificationWarning,
9117
+ "data-testid": "calibration-hand-eye-page-verify-warning",
9118
+ children: [jsx(VentionIcon, {
9119
+ type: "alert-triangle-filled",
9120
+ size: 20,
9121
+ color: "inherit"
9122
+ }), jsx(Typography, {
9123
+ variant: "uiText14SemiBold",
9124
+ children: verifyResult === null || verifyResult === void 0 ? void 0 : verifyResult.message
9125
+ })]
9126
+ }) : null, displayedError ? jsx(Alert, {
9127
+ severity: "error",
9128
+ className: classes.alert,
9129
+ "data-testid": "calibration-hand-eye-page-error-alert",
9130
+ children: displayedError
9131
+ }) : null, isRunning ? jsxs(Fragment, {
9132
+ children: [jsxs(Box, {
9133
+ className: classes.progressBlock,
9134
+ "data-testid": "calibration-hand-eye-page-progress",
9135
+ children: [jsx(LinearProgress, {
9136
+ variant: "determinate",
9137
+ value: percent,
9138
+ className: classes.progressBar
9139
+ }), jsx(Typography, {
9140
+ variant: "hmiText20SemiBold",
9141
+ className: classes.progressLabel,
9142
+ children: (_c = effectiveProgress === null || effectiveProgress === void 0 ? void 0 : effectiveProgress.message) !== null && _c !== void 0 ? _c : t("calibration.handEye.calibrate.running", {
9143
+ defaultValue: "{{percent}}% Completed",
9144
+ percent
9145
+ })
9146
+ })]
9147
+ }), jsx(VentionButton, {
9148
+ variant: "filled",
9149
+ size: "x-large",
9150
+ onClick: handleCancel,
9151
+ className: classes.primaryButton,
9152
+ disabled: isCancelling,
9153
+ startIcon: isCancelling ? jsx(CircularProgress, {
9154
+ size: 16,
9155
+ color: "inherit"
9156
+ }) : undefined,
9157
+ "data-testid": "calibration-hand-eye-page-cancel",
9158
+ children: isCancelling ? t("calibration.handEye.calibrate.cancelling", {
9159
+ defaultValue: "Cancelling..."
9160
+ }) : t("calibration.handEye.calibrate.cancel", {
9161
+ defaultValue: "Cancel calibration"
9162
+ })
9163
+ })]
9164
+ }) : jsxs(Fragment, {
9165
+ children: [jsx(VentionButton, {
9166
+ variant: "filled",
9167
+ size: "x-large",
9168
+ onClick: handleCalibrate,
9169
+ className: classes.primaryButton,
9170
+ disabled: disabled || isVerifying,
9171
+ startIcon: isCalibrated ? jsx(VentionIcon, {
9172
+ type: "refresh",
9173
+ size: 24,
9174
+ color: "white"
9175
+ }) : undefined,
9176
+ "data-testid": "calibration-hand-eye-page-calibrate",
9177
+ children: isCalibrated ? t("calibration.handEye.calibrate.update", {
9178
+ defaultValue: "Update calibration"
9179
+ }) : t("calibration.handEye.calibrate.calibrate", {
9180
+ defaultValue: "Calibrate"
9181
+ })
9182
+ }), onVerify && isCalibrated ? jsx(VentionButton, {
9183
+ variant: "outline",
9184
+ size: "x-large",
9185
+ onClick: handleVerify,
9186
+ className: classes.primaryButton,
9187
+ disabled: disabled || isVerifying,
9188
+ startIcon: isVerifying ? jsx(CircularProgress, {
9189
+ size: 16,
9190
+ color: "inherit"
9191
+ }) : undefined,
9192
+ "data-testid": "calibration-hand-eye-page-verify",
9193
+ children: isVerifying ? t("calibration.handEye.verify.loading", {
9194
+ defaultValue: "Verifying..."
9195
+ }) : t("calibration.handEye.verify.action", {
9196
+ defaultValue: "Verify calibration"
9197
+ })
9198
+ }) : null, statusAlert && (effectiveProgress === null || effectiveProgress === void 0 ? void 0 : effectiveProgress.message) && !(status === "error" && displayedError) ? jsx(Alert, {
9199
+ severity: statusAlert.severity,
9200
+ className: classes.alert,
9201
+ "data-testid": statusAlert.testId,
9202
+ children: effectiveProgress.message
9203
+ }) : null, jsx(Typography, {
9204
+ variant: "hmiText20SemiBold",
9205
+ className: classes.statusText,
9206
+ "data-testid": "calibration-hand-eye-page-status",
9207
+ children: isCalibrated && lastCalibrationAt ? t("calibration.handEye.calibrate.lastCalibratedOn", {
9208
+ defaultValue: "Calibrated on {{date}}",
9209
+ date: dayjs(lastCalibrationAt).format(TIMESTAMP_FORMAT$1)
9210
+ }) : t("calibration.handEye.calibrate.never", {
9211
+ defaultValue: "Not calibrated"
9212
+ })
9213
+ })]
9214
+ })]
9215
+ });
9216
+ };
9217
+ CalibrationHandEyePage.displayName = "CalibrationHandEyePage";
9218
+ const useStyles$1 = tss.create(({
9219
+ theme
9220
+ }) => ({
9221
+ container: {
9222
+ position: "relative",
9223
+ display: "flex",
9224
+ flexDirection: "column",
9225
+ alignItems: "center",
9226
+ justifyContent: "center",
9227
+ height: "100%",
9228
+ minHeight: 480,
9229
+ gap: theme.spacing(2),
9230
+ padding: theme.spacing(4),
9231
+ borderRadius: theme.spacing(2),
9232
+ border: `1px solid ${theme.palette.divider}`,
9233
+ backgroundColor: theme.palette.background.paper
9234
+ },
9235
+ verificationWarning: {
9236
+ position: "absolute",
9237
+ top: theme.spacing(3),
9238
+ left: theme.spacing(3),
9239
+ right: theme.spacing(3),
9240
+ display: "flex",
9241
+ alignItems: "center",
9242
+ gap: theme.spacing(2),
9243
+ padding: theme.spacing(2, 3),
9244
+ borderRadius: theme.spacing(1),
9245
+ backgroundColor: theme.palette.warning.light,
9246
+ color: theme.palette.warning.dark
9247
+ },
9248
+ primaryButton: {
9249
+ width: 400
9250
+ },
9251
+ progressBlock: {
9252
+ display: "flex",
9253
+ flexDirection: "column",
9254
+ gap: theme.spacing(2),
9255
+ width: "100%",
9256
+ maxWidth: 900,
9257
+ marginBottom: theme.spacing(2)
9258
+ },
9259
+ progressBar: {
9260
+ height: 32,
9261
+ borderRadius: 8
9262
+ },
9263
+ progressLabel: {
9264
+ color: theme.palette.text.primary
9265
+ },
9266
+ alert: {
9267
+ width: 400
9268
+ },
9269
+ statusText: {
9270
+ color: theme.palette.text.secondary
9271
+ }
9272
+ }));
9273
+
9274
+ const TIMESTAMP_FORMAT = "MM/DD/YYYY, hh:mm:ss A";
9275
+ const CalibrationEnvironmentPage = function CalibrationEnvironmentPage({
9276
+ onStartSession,
9277
+ onTakePhoto,
9278
+ onEndSession,
9279
+ sessionName,
9280
+ photoCount,
9281
+ lastPhotoAt,
9282
+ isError = false,
9283
+ errorMessage,
9284
+ isBusy = false,
9285
+ illustration,
9286
+ helperText,
9287
+ topAlertTitle,
9288
+ className,
9289
+ sx
9290
+ }) {
9291
+ var _a, _b;
9292
+ const {
9293
+ classes,
9294
+ cx
9295
+ } = useStyles({
9296
+ isError
9297
+ });
9298
+ const {
9299
+ t
9300
+ } = useTranslation();
9301
+ // Subscribe to live progress from griip-sdk. Props win over MQTT-derived
9302
+ // values so consumers can still drive state directly when MQTT isn't in
9303
+ // play (e.g. Storybook, tests).
9304
+ const mqttMessage = useMqttSubscription({
9305
+ topic: ENVIRONMENT_PROGRESS_TOPIC,
9306
+ unsubscribeOnUnmount: true
9307
+ });
9308
+ const effectiveSessionName = (_a = sessionName !== null && sessionName !== void 0 ? sessionName : mqttMessage === null || mqttMessage === void 0 ? void 0 : mqttMessage.sessionName) !== null && _a !== void 0 ? _a : null;
9309
+ const effectivePhotoCount = (_b = photoCount !== null && photoCount !== void 0 ? photoCount : mqttMessage === null || mqttMessage === void 0 ? void 0 : mqttMessage.photoCount) !== null && _b !== void 0 ? _b : 0;
9310
+ const effectiveIsError = isError || (mqttMessage === null || mqttMessage === void 0 ? void 0 : mqttMessage.status) === "error";
9311
+ const effectiveErrorMessage = errorMessage !== null && errorMessage !== void 0 ? errorMessage : (mqttMessage === null || mqttMessage === void 0 ? void 0 : mqttMessage.status) === "error" ? mqttMessage.message : undefined;
9312
+ const sessionActive = Boolean(effectiveSessionName);
9313
+ const resolvedHelperText = helperText !== null && helperText !== void 0 ? helperText : t("calibration.environment.helper", {
9314
+ defaultValue: "Enable free drive and move the robot to take photos covering the entire environment, including walls, bins, machines."
9315
+ });
9316
+ const resolvedTopAlert = topAlertTitle !== null && topAlertTitle !== void 0 ? topAlertTitle : t("calibration.environment.topAlert", {
9317
+ defaultValue: "Before starting environment calibration, please contact Vention's team for assistance."
9318
+ });
9319
+ return jsxs(Box, {
9320
+ className: cx(classes.container, className),
9321
+ sx: sx,
9322
+ "data-testid": "calibration-environment-page",
9323
+ children: [jsx(Alert, {
9324
+ severity: "warning",
9325
+ className: classes.alertBanner,
9326
+ "data-testid": "calibration-environment-page-instructions",
9327
+ children: resolvedTopAlert
9328
+ }), jsx(Box, {
9329
+ className: classes.card,
9330
+ children: effectiveIsError ? jsxs(Box, {
9331
+ className: classes.errorContent,
9332
+ "data-testid": "calibration-environment-page-error",
9333
+ children: [jsx(VentionIcon, {
9334
+ type: "circle-x-filled",
9335
+ size: 48,
9336
+ color: "status.destructive"
9337
+ }), jsx(Typography, {
9338
+ variant: "hmiText28SemiBold",
9339
+ className: classes.errorTitle,
9340
+ children: effectiveErrorMessage !== null && effectiveErrorMessage !== void 0 ? effectiveErrorMessage : t("calibration.environment.error", {
9341
+ defaultValue: "Environment scan failed. Reset the bin and retry."
9342
+ })
9343
+ })]
9344
+ }) : jsxs(Box, {
9345
+ className: classes.normalContent,
9346
+ children: [jsxs(Box, {
9347
+ className: classes.illustrationBlock,
9348
+ children: [illustration !== null && illustration !== void 0 ? illustration : jsx(Box, {
9349
+ className: classes.illustrationPlaceholder,
9350
+ "aria-hidden": true
9351
+ }), jsx(Typography, {
9352
+ variant: "hmiText20SemiBold",
9353
+ className: classes.helperText,
9354
+ children: resolvedHelperText
9355
+ })]
9356
+ }), jsx(Box, {
9357
+ className: classes.buttonColumn,
9358
+ children: !sessionActive ? jsx(VentionButton, {
9359
+ variant: "filled",
9360
+ size: "x-large",
9361
+ fullWidth: true,
9362
+ onClick: onStartSession,
9363
+ disabled: isBusy,
9364
+ startIcon: isBusy ? jsx(CircularProgress, {
9365
+ size: 16,
9366
+ color: "inherit"
9367
+ }) : jsx(VentionIcon, {
9368
+ type: "camera",
9369
+ size: 24,
9370
+ color: "white"
9371
+ }),
9372
+ "data-testid": "calibration-environment-page-start-session",
9373
+ children: isBusy ? t("calibration.environment.starting", {
9374
+ defaultValue: "Starting..."
9375
+ }) : t("calibration.environment.startSession", {
9376
+ defaultValue: "Start new session"
9377
+ })
9378
+ }) : jsxs(Fragment, {
9379
+ children: [jsxs(Box, {
9380
+ className: classes.sessionLine,
9381
+ children: [jsx(VentionIcon, {
9382
+ type: "folder-open",
9383
+ size: 20,
9384
+ color: "status.info"
9385
+ }), jsxs(Typography, {
9386
+ variant: "uiText14SemiBold",
9387
+ className: classes.sessionName,
9388
+ children: [t("calibration.environment.sessionLabel", {
9389
+ defaultValue: "Session"
9390
+ }), ": ", effectiveSessionName]
9391
+ })]
9392
+ }), jsxs(Box, {
9393
+ className: classes.sessionButtonRow,
9394
+ children: [jsx(VentionButton, {
9395
+ variant: "filled",
9396
+ size: "x-large",
9397
+ onClick: onTakePhoto,
9398
+ disabled: isBusy,
9399
+ startIcon: isBusy ? jsx(CircularProgress, {
9400
+ size: 16,
9401
+ color: "inherit"
9402
+ }) : jsx(VentionIcon, {
9403
+ type: "camera",
9404
+ size: 24,
9405
+ color: "white"
9406
+ }),
9407
+ "data-testid": "calibration-environment-page-take-photo",
9408
+ sx: {
9409
+ flex: 2,
9410
+ whiteSpace: "nowrap"
9411
+ },
9412
+ children: t("calibration.environment.takePhoto", {
9413
+ defaultValue: "Take photo"
9414
+ })
9415
+ }), jsx(VentionButton, {
9416
+ variant: "outline",
9417
+ size: "x-large",
9418
+ onClick: onEndSession,
9419
+ disabled: isBusy,
9420
+ "data-testid": "calibration-environment-page-end-session",
9421
+ sx: {
9422
+ flex: 1,
9423
+ whiteSpace: "nowrap"
9424
+ },
9425
+ children: t("calibration.environment.endSession", {
9426
+ defaultValue: "End session"
9427
+ })
9428
+ })]
9429
+ }), jsxs(Box, {
9430
+ className: classes.statusLine,
9431
+ "data-testid": "calibration-environment-page-status",
9432
+ children: [jsx(VentionIcon, {
9433
+ type: "circle-check-filled",
9434
+ size: 20,
9435
+ color: "status.success"
9436
+ }), jsxs(Typography, {
9437
+ variant: "uiText14SemiBold",
9438
+ className: classes.statusText,
9439
+ children: [effectivePhotoCount > 0 ? t("calibration.environment.photoCount", {
9440
+ defaultValue: "{{count}} photo(s) saved",
9441
+ count: effectivePhotoCount
9442
+ }) : t("calibration.environment.noPhotos", {
9443
+ defaultValue: "No photos captured yet"
9444
+ }), lastPhotoAt ? " — " + t("calibration.environment.lastPhotoAt", {
9445
+ defaultValue: "last on {{date}}",
9446
+ date: dayjs(lastPhotoAt).format(TIMESTAMP_FORMAT)
9447
+ }) : ""]
9448
+ })]
9449
+ })]
9450
+ })
9451
+ })]
9452
+ })
9453
+ })]
9454
+ });
9455
+ };
9456
+ CalibrationEnvironmentPage.displayName = "CalibrationEnvironmentPage";
9457
+ const useStyles = tss.withParams().create(({
9458
+ theme,
9459
+ isError
9460
+ }) => ({
9461
+ container: {
9462
+ display: "flex",
9463
+ flexDirection: "column",
9464
+ width: "100%",
9465
+ height: "100%",
9466
+ gap: theme.spacing(3)
9467
+ },
9468
+ alertBanner: {
9469
+ width: "100%",
9470
+ flexShrink: 0
9471
+ },
9472
+ card: {
9473
+ display: "flex",
9474
+ flexDirection: "column",
9475
+ justifyContent: "center",
9476
+ alignItems: "stretch",
9477
+ flex: 1,
9478
+ minHeight: 480,
9479
+ padding: theme.spacing(5),
9480
+ gap: theme.spacing(5),
9481
+ borderRadius: theme.spacing(2),
9482
+ border: `1px solid ${isError ? theme.palette.error.light : theme.palette.divider}`,
9483
+ backgroundColor: isError ? theme.palette.error.light : theme.palette.background.paper
9484
+ },
9485
+ errorContent: {
9486
+ display: "flex",
9487
+ flexDirection: "column",
9488
+ alignItems: "center",
9489
+ justifyContent: "center",
9490
+ gap: theme.spacing(3),
9491
+ height: "100%"
9492
+ },
9493
+ errorTitle: {
9494
+ textAlign: "center",
9495
+ color: theme.palette.text.primary
9496
+ },
9497
+ normalContent: {
9498
+ display: "flex",
9499
+ flexDirection: "column",
9500
+ alignItems: "center",
9501
+ justifyContent: "center",
9502
+ gap: theme.spacing(5)
9503
+ },
9504
+ illustrationBlock: {
9505
+ display: "flex",
9506
+ flexDirection: "column",
9507
+ alignItems: "center",
9508
+ gap: theme.spacing(3),
9509
+ maxWidth: 640
9510
+ },
9511
+ illustrationPlaceholder: {
9512
+ width: 320,
9513
+ height: 180,
9514
+ borderRadius: theme.spacing(1),
9515
+ backgroundColor: theme.palette.action.hover,
9516
+ backgroundImage: `repeating-linear-gradient(45deg, transparent, transparent 12px, ${theme.palette.divider} 12px, ${theme.palette.divider} 13px)`
9517
+ },
9518
+ helperText: {
9519
+ textAlign: "center",
9520
+ color: theme.palette.text.primary
9521
+ },
9522
+ buttonColumn: {
9523
+ display: "flex",
9524
+ flexDirection: "column",
9525
+ alignItems: "center",
9526
+ gap: theme.spacing(2),
9527
+ width: 520,
9528
+ maxWidth: "100%"
9529
+ },
9530
+ sessionLine: {
9531
+ display: "flex",
9532
+ alignItems: "center",
9533
+ gap: theme.spacing(1)
9534
+ },
9535
+ sessionName: {
9536
+ color: theme.palette.primary.main
9537
+ },
9538
+ sessionButtonRow: {
9539
+ display: "flex",
9540
+ gap: theme.spacing(2),
9541
+ width: "100%"
9542
+ },
9543
+ statusLine: {
9544
+ display: "flex",
9545
+ alignItems: "center",
9546
+ gap: theme.spacing(1)
9547
+ },
9548
+ statusText: {
9549
+ color: theme.palette.text.secondary
9550
+ }
9551
+ }));
9552
+
8741
9553
  var UserLevel;
8742
9554
  (function (UserLevel) {
8743
9555
  UserLevel[UserLevel["Operator"] = 1] = "Operator";
@@ -10999,4 +11811,4 @@ function getApiBaseUrl(options) {
10999
11811
  return getExecutionEngineHttpUrl(processName);
11000
11812
  }
11001
11813
 
11002
- export { ActionButton, FileUploadPanel, I18nProvider, I18nSettings, LogFilterForm, LogsPagination, LogsPanel, LogsTable, NavigationBar, NavigationConfirmationModal, PasswordProtectionModal, PressButton, ProductFormList, SettingsPage, Sidebar, StatusTopBar, StepProgressCircle, TimeLabel, UserLevel, Z_INDEX, closeCustomUi, formatDateToInput, getApiBaseUrl, getAvailableTimezones, getLanguageDisplayName, getSupportedLanguages, hasSufficientLevel, isOnEdge, isTouchScreenDevice, navigateControlCenter, parseLogDate, useAutoScrollInput, useI18n };
11814
+ export { ActionButton, CalibrationEnvironmentPage, CalibrationFooter, CalibrationHandEyePage, ENVIRONMENT_PROGRESS_TOPIC, FileUploadPanel, HAND_EYE_PROGRESS_TOPIC, I18nProvider, I18nSettings, LogFilterForm, LogsPagination, LogsPanel, LogsTable, NavigationBar, NavigationConfirmationModal, PasswordProtectionModal, PressButton, ProductFormList, SettingsPage, Sidebar, StatusTopBar, StepProgressCircle, TimeLabel, UserLevel, Z_INDEX, closeCustomUi, formatDateToInput, getApiBaseUrl, getAvailableTimezones, getLanguageDisplayName, getSupportedLanguages, hasSufficientLevel, isOnEdge, isTouchScreenDevice, navigateControlCenter, parseLogDate, useAutoScrollInput, useI18n };