@wandelbots/wandelbots-js-react-components 2.27.0 → 2.27.1-pr.feature-add-program-control-component.367.9154db9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wandelbots/wandelbots-js-react-components",
3
- "version": "2.27.0",
3
+ "version": "2.27.1-pr.feature-add-program-control-component.367.9154db9",
4
4
  "description": "React UI toolkit for building applications on top of the Wandelbots platform",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -0,0 +1,212 @@
1
+ import { Pause, PlayArrow, Stop } from "@mui/icons-material"
2
+ import { Box, Button, Typography, useTheme } from "@mui/material"
3
+ import { observer } from "mobx-react-lite"
4
+ import { externalizeComponent } from "../externalizeComponent"
5
+
6
+ export type ProgramState = "idle" | "running" | "paused" | "stopping"
7
+
8
+ export interface ProgramControlProps {
9
+ /** The current state of the program control */
10
+ state: ProgramState
11
+ /** Callback fired when the run/resume button is clicked */
12
+ onRun: () => void
13
+ /** Callback fired when the pause button is clicked (only available in 'with_pause' variant) */
14
+ onPause?: () => void
15
+ /** Callback fired when the stop button is clicked */
16
+ onStop: () => void
17
+ /**
18
+ * Function to reset the component from 'stopping' state back to 'idle'.
19
+ * This must be called manually by the user when requiresManualReset is true.
20
+ */
21
+ onReset?: () => void
22
+ /**
23
+ * When true, the component will stay in 'stopping' state until onReset is called manually.
24
+ * When false (default), auto-resets to 'idle' after 2 seconds.
25
+ */
26
+ requiresManualReset?: boolean
27
+ /**
28
+ * Variant of the component:
29
+ * - 'with_pause': Shows run/pause/stop buttons (default)
30
+ * - 'without_pause': Shows only run/stop buttons
31
+ */
32
+ variant?: "with_pause" | "without_pause"
33
+ /** Additional CSS class name */
34
+ className?: string
35
+ }
36
+
37
+ interface ButtonConfig {
38
+ enabled: boolean
39
+ label: string
40
+ color: string
41
+ onClick: () => void
42
+ }
43
+
44
+ /**
45
+ * A control component for program execution with run, pause, and stop functionality.
46
+ *
47
+ * Features:
48
+ * - State machine with idle, running, paused, and stopping states
49
+ * - Two variants: with_pause (3 buttons) and without_pause (2 buttons)
50
+ * - Optional manual reset functionality
51
+ * - Responsive design with 110px circular buttons
52
+ * - Material-UI theming integration
53
+ */
54
+ export const ProgramControl = externalizeComponent(
55
+ observer(
56
+ ({
57
+ state,
58
+ onRun,
59
+ onPause,
60
+ onStop,
61
+ onReset,
62
+ requiresManualReset = false,
63
+ variant = "with_pause",
64
+ className,
65
+ }: ProgramControlProps) => {
66
+ const theme = useTheme()
67
+
68
+ const getButtonConfigs = (): ButtonConfig[] => {
69
+ const baseConfigs: Record<string, ButtonConfig> = {
70
+ run: {
71
+ enabled: state === "idle" || state === "paused",
72
+ label: state === "paused" ? "Resume" : "Run",
73
+ color: theme.palette.success.main,
74
+ onClick: onRun,
75
+ },
76
+ pause: {
77
+ enabled: state === "running",
78
+ label: "Pause",
79
+ color: "#FFFFFF33",
80
+ onClick: onPause || (() => {}),
81
+ },
82
+ stop: {
83
+ enabled: state === "running" || state === "paused",
84
+ label: "Stop",
85
+ color: theme.palette.error.main,
86
+ onClick: onStop,
87
+ },
88
+ }
89
+
90
+ if (variant === "without_pause") {
91
+ return [baseConfigs.run, baseConfigs.stop]
92
+ }
93
+
94
+ return [baseConfigs.run, baseConfigs.pause, baseConfigs.stop]
95
+ }
96
+
97
+ const getButtonIcon = (index: number) => {
98
+ const iconProps = { sx: { fontSize: "55px" } }
99
+
100
+ if (variant === "without_pause") {
101
+ return index === 0 ? (
102
+ <PlayArrow {...iconProps} />
103
+ ) : (
104
+ <Stop {...iconProps} />
105
+ )
106
+ }
107
+
108
+ switch (index) {
109
+ case 0:
110
+ return <PlayArrow {...iconProps} />
111
+ case 1:
112
+ return <Pause {...iconProps} />
113
+ case 2:
114
+ return <Stop {...iconProps} />
115
+ default:
116
+ return null
117
+ }
118
+ }
119
+
120
+ const buttonConfigs = getButtonConfigs()
121
+
122
+ return (
123
+ <Box
124
+ className={className}
125
+ sx={{
126
+ display: "flex",
127
+ flexDirection: "column",
128
+ alignItems: "center",
129
+ gap: 2,
130
+ }}
131
+ >
132
+ <Box
133
+ sx={{
134
+ display: "flex",
135
+ gap: "40px",
136
+ flexWrap: "wrap",
137
+ justifyContent: "center",
138
+ alignItems: "center",
139
+ }}
140
+ >
141
+ {buttonConfigs.map((config, index) => (
142
+ <Box
143
+ key={config.label}
144
+ sx={{
145
+ display: "flex",
146
+ flexDirection: "column",
147
+ alignItems: "center",
148
+ gap: 1,
149
+ }}
150
+ >
151
+ <Button
152
+ variant="contained"
153
+ disabled={
154
+ !config.enabled ||
155
+ (state === "stopping" && !requiresManualReset)
156
+ }
157
+ onClick={config.onClick}
158
+ sx={{
159
+ width: "110px",
160
+ height: "110px",
161
+ borderRadius: "110px",
162
+ backgroundColor: config.color,
163
+ opacity:
164
+ config.enabled &&
165
+ !(state === "stopping" && !requiresManualReset)
166
+ ? 1
167
+ : 0.3,
168
+ "&:hover": {
169
+ backgroundColor: config.color,
170
+ opacity:
171
+ config.enabled &&
172
+ !(state === "stopping" && !requiresManualReset)
173
+ ? 0.8
174
+ : 0.3,
175
+ },
176
+ "&:disabled": {
177
+ backgroundColor: config.color,
178
+ opacity: 0.3,
179
+ },
180
+ minWidth: "110px",
181
+ flexShrink: 0,
182
+ }}
183
+ >
184
+ {getButtonIcon(index)}
185
+ </Button>
186
+
187
+ <Typography
188
+ variant="body1"
189
+ sx={{
190
+ color:
191
+ config.enabled &&
192
+ !(state === "stopping" && !requiresManualReset)
193
+ ? config.color
194
+ : theme.palette.text.disabled,
195
+ textAlign: "center",
196
+ opacity:
197
+ config.enabled &&
198
+ !(state === "stopping" && !requiresManualReset)
199
+ ? 1
200
+ : 0.3,
201
+ }}
202
+ >
203
+ {config.label}
204
+ </Typography>
205
+ </Box>
206
+ ))}
207
+ </Box>
208
+ </Box>
209
+ )
210
+ },
211
+ ),
212
+ )
@@ -19,7 +19,7 @@ export const OperationModeIndicator = observer(
19
19
  operationMode,
20
20
  anchorOrigin,
21
21
  transformOrigin,
22
- compact
22
+ compact,
23
23
  }: OperationModeIndicatorProps) => {
24
24
  const { t } = useTranslation()
25
25
  const theme = useTheme()
@@ -33,7 +33,7 @@ export const OperationModeIndicator = observer(
33
33
  title={t("SafetyBar.OperationMode.ti")}
34
34
  name={t("SafetyBar.OperationMode.Automatic.ti")}
35
35
  label={compact ? null : t("SafetyBar.OperationMode.Automatic.ti")}
36
- color={"rgba(255, 255, 255, 0.57)"}
36
+ color={theme.palette.text.secondary}
37
37
  explanation={
38
38
  <Trans i18nKey="SafetyBar.OperationMode.Auto.Explanation.lb">
39
39
  The robot controller is in automatic operation mode. Automated
@@ -35,16 +35,15 @@ export const SafetyStateIndicator = observer(
35
35
  id="safety-state-normal"
36
36
  title={t("SafetyBar.SafetyState.ti")}
37
37
  name={t("SafetyBar.SafetyState.Normal.lb")}
38
- label={compact ? null : t("SafetyBar.SafetyState.Normal.lb")}
38
+ label={compact ? null : t("SafetyBar.SafetyState.Normal.lb")}
39
39
  icon={SafetyStateNormalIcon}
40
- color={"rgba(255, 255, 255, 0.57)"}
40
+ color={theme.palette.text.secondary}
41
41
  explanation={
42
42
  <Trans i18nKey="SafetyBar.SafetyState.Normal.Explanation.lb">
43
43
  The robot controller is in a normal safety state. Movement is
44
44
  not prevented by this state.
45
45
  </Trans>
46
46
  }
47
-
48
47
  anchorOrigin={anchorOrigin}
49
48
  transformOrigin={transformOrigin}
50
49
  />
@@ -114,7 +113,11 @@ export const SafetyStateIndicator = observer(
114
113
  color={theme.palette.warning.main}
115
114
  title={t("SafetyBar.SafetyState.ti")}
116
115
  name={t("SafetyBar.SafetyState.ManualActionRequired.lb")}
117
- label={compact ? null : t("SafetyBar.SafetyState.ManualActionRequired.lb")}
116
+ label={
117
+ compact
118
+ ? null
119
+ : t("SafetyBar.SafetyState.ManualActionRequired.lb")
120
+ }
118
121
  explanation={
119
122
  <Trans i18nKey="SafetyBar.SafetyState.ManualActionRequired.Explanation.lb">
120
123
  The robot controller has entered a safety state requiring manual
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export * from "./components/jogging/PoseCartesianValues"
9
9
  export * from "./components/jogging/PoseJointValues"
10
10
  export * from "./components/LoadingCover"
11
11
  export * from "./components/modal/NoMotionGroupModal"
12
+ export * from "./components/ProgramControl"
12
13
  export * from "./components/robots/AxisConfig"
13
14
  export * from "./components/robots/Robot"
14
15
  export { defaultGetModel } from "./components/robots/robotModelLogic"