@wandelbots/wandelbots-js-react-components 2.38.1 → 2.39.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wandelbots/wandelbots-js-react-components",
3
- "version": "2.38.1",
3
+ "version": "2.39.0",
4
4
  "description": "React UI toolkit for building applications on top of the Wandelbots platform",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -117,7 +117,7 @@ export const DefaultVariant = ({
117
117
  currentState !== "countup" &&
118
118
  currentState !== "success"
119
119
  }
120
- timeout={200}
120
+ timeout={300}
121
121
  >
122
122
  <Typography
123
123
  variant="body2"
@@ -237,7 +237,7 @@ export const DefaultVariant = ({
237
237
  currentState !== "idle" &&
238
238
  currentState !== "success"
239
239
  }
240
- timeout={200}
240
+ timeout={300}
241
241
  >
242
242
  <Typography
243
243
  variant="h1"
@@ -280,7 +280,7 @@ export const DefaultVariant = ({
280
280
  currentState !== "countup" &&
281
281
  currentState !== "success"
282
282
  }
283
- timeout={200}
283
+ timeout={300}
284
284
  >
285
285
  <Typography
286
286
  variant="body2"
@@ -53,10 +53,10 @@ export const useTimerLogic = ({
53
53
  ...prev,
54
54
  currentState: "idle",
55
55
  maxTime: null,
56
- remainingTime: 0,
56
+ // Don't reset remainingTime - keep the last value
57
57
  isRunning: false,
58
58
  isPausedState: false,
59
- currentProgress: 0, // Immediately reset progress to 0
59
+ currentProgress: 0, // Reset progress to 0 for gauge
60
60
  }))
61
61
  pausedTimeRef.current = 0
62
62
  startTimeRef.current = null
@@ -12,7 +12,6 @@ import { useTranslation } from "react-i18next"
12
12
  import type { Group } from "three"
13
13
  import { externalizeComponent } from "../externalizeComponent"
14
14
  import { PresetEnvironment } from "./3d-viewport/PresetEnvironment"
15
- import { CycleTimer } from "./CycleTimer"
16
15
  import type { ProgramState } from "./ProgramControl"
17
16
  import { ProgramStateIndicator } from "./ProgramStateIndicator"
18
17
  import { Robot } from "./robots/Robot"
@@ -58,34 +57,8 @@ export interface RobotCardProps {
58
57
  transparentColor?: string
59
58
  getModel?: (modelFromController: string) => string
60
59
  }>
61
- /** Custom cycle timer component (optional, defaults to CycleTimer) */
62
- cycleTimerComponent?: React.ComponentType<{
63
- variant?: "default" | "small"
64
- compact?: boolean
65
- onCycleComplete: (controls: {
66
- startNewCycle: (maxTimeSeconds?: number, elapsedSeconds?: number) => void
67
- pause: () => void
68
- resume: () => void
69
- isPaused: () => boolean
70
- }) => void
71
- onCycleEnd?: () => void
72
- autoStart?: boolean
73
- hasError?: boolean
74
- className?: string
75
- }>
76
- /** Callback to receive cycle timer controls for external timer management */
77
- onCycleTimerReady?: (controls: {
78
- startNewCycle: (maxTimeSeconds?: number, elapsedSeconds?: number) => void
79
- pause: () => void
80
- resume: () => void
81
- isPaused: () => boolean
82
- }) => void
83
- /** Callback fired when a cycle completes (reaches zero) */
84
- onCycleEnd?: () => void
85
- /** Whether the cycle timer should auto-start when a new cycle is set */
86
- cycleTimerAutoStart?: boolean
87
- /** Whether the cycle timer is in an error state (pauses timer and shows error styling) */
88
- cycleTimerHasError?: boolean
60
+ /** Custom component to render in the content area (optional) */
61
+ customContentComponent?: React.ComponentType<Record<string, unknown>>
89
62
  /** Additional CSS class name */
90
63
  className?: string
91
64
  }
@@ -108,11 +81,31 @@ export interface RobotCardProps {
108
81
  * - Robot name displayed in Typography h6 at top-left
109
82
  * - Program state indicator below the name
110
83
  * - Auto-fitting 3D robot model that scales with container size
111
- * - Compact cycle time component with small variant, error state, and count-up/count-down mode support
84
+ * - Customizable content area for displaying custom React components
112
85
  * - Transparent gray divider line
113
86
  * - "Drive to Home" button with press-and-hold functionality
114
87
  * - Localization support via react-i18next
115
88
  * - Material-UI theming integration
89
+ *
90
+ * Usage with custom content:
91
+ * ```tsx
92
+ * // Example custom timer component
93
+ * const CustomTimer = () => (
94
+ * <Box>
95
+ * <Typography variant="body1" sx={{ color: "text.secondary" }}>
96
+ * Runtime
97
+ * </Typography>
98
+ * <Typography variant="h6">05:23</Typography>
99
+ * </Box>
100
+ * )
101
+ *
102
+ * <RobotCard
103
+ * robotName="UR5e Robot"
104
+ * programState={ProgramState.RUNNING}
105
+ * customContentComponent={CustomTimer}
106
+ * // ... other props
107
+ * />
108
+ * ```
116
109
  */
117
110
  export const RobotCard = externalizeComponent(
118
111
  observer(
@@ -126,11 +119,7 @@ export const RobotCard = externalizeComponent(
126
119
  onDriveToHomeRelease,
127
120
  connectedMotionGroup,
128
121
  robotComponent: RobotComponent = Robot,
129
- cycleTimerComponent: CycleTimerComponent = CycleTimer,
130
- onCycleTimerReady,
131
- onCycleEnd,
132
- cycleTimerAutoStart = true,
133
- cycleTimerHasError = false,
122
+ customContentComponent: CustomContentComponent,
134
123
  className,
135
124
  }: RobotCardProps) => {
136
125
  const theme = useTheme()
@@ -145,17 +134,6 @@ export const RobotCard = externalizeComponent(
145
134
  }>({ width: 400, height: 600 })
146
135
  const [modelRenderTrigger, setModelRenderTrigger] = useState(0)
147
136
 
148
- // Store cycle timer controls for external control
149
- const cycleControlsRef = useRef<{
150
- startNewCycle: (
151
- maxTimeSeconds?: number,
152
- elapsedSeconds?: number,
153
- ) => void
154
- pause: () => void
155
- resume: () => void
156
- isPaused: () => boolean
157
- } | null>(null)
158
-
159
137
  // Hook to detect aspect ratio and size changes
160
138
  useEffect(() => {
161
139
  const checkDimensions = () => {
@@ -204,38 +182,16 @@ export const RobotCard = externalizeComponent(
204
182
  }
205
183
  }, [isDriveToHomePressed, onDriveToHomeRelease])
206
184
 
207
- // Store and provide cycle timer controls for external use
208
- const handleCycleComplete = useCallback(
209
- (controls: {
210
- startNewCycle: (
211
- maxTimeSeconds?: number,
212
- elapsedSeconds?: number,
213
- ) => void
214
- pause: () => void
215
- resume: () => void
216
- isPaused: () => boolean
217
- }) => {
218
- // Store the controls for potential future use
219
- cycleControlsRef.current = controls
220
-
221
- // Notify parent component that timer controls are ready
222
- if (onCycleTimerReady) {
223
- onCycleTimerReady(controls)
224
- }
225
- },
226
- [onCycleTimerReady],
227
- )
228
-
229
185
  // Determine if robot should be hidden at small sizes to save space
230
186
  const shouldHideRobot = isLandscape
231
187
  ? cardSize.width < 350
232
188
  : cardSize.height < 200 // Hide robot at height < 200px in portrait
233
189
 
234
- // Determine if runtime view should be hidden when height is too low
235
- // Runtime should be hidden BEFORE the robot (at higher threshold)
236
- const shouldHideRuntime = isLandscape
237
- ? cardSize.height < 310 // Landscape: hide runtime at height < 350px
238
- : cardSize.height < 450 // Portrait: hide runtime at height < 450px
190
+ // Determine if custom content should be hidden when height is too low
191
+ // Custom content should be hidden BEFORE the robot (at higher threshold)
192
+ const shouldHideCustomContent = isLandscape
193
+ ? cardSize.height < 310 // Landscape: hide custom content at height < 310px
194
+ : cardSize.height < 450 // Portrait: hide custom content at height < 450px
239
195
 
240
196
  return (
241
197
  <Card
@@ -337,7 +293,7 @@ export const RobotCard = externalizeComponent(
337
293
  />
338
294
  </Box>
339
295
 
340
- {/* Bottom section with runtime, cycle time, and button */}
296
+ {/* Bottom section with custom content and button */}
341
297
  <Box
342
298
  sx={{
343
299
  p: { xs: 1.5, sm: 2, md: 3 },
@@ -348,32 +304,10 @@ export const RobotCard = externalizeComponent(
348
304
  justifyContent: "space-between",
349
305
  }}
350
306
  >
351
- {/* Runtime view - hidden if height is too low in landscape mode */}
352
- {!shouldHideRuntime && (
307
+ {/* Custom content section - hidden if height is too low in landscape mode */}
308
+ {!shouldHideCustomContent && CustomContentComponent && (
353
309
  <Box>
354
- {/* Runtime display */}
355
- <Typography
356
- variant="body1"
357
- sx={{
358
- mb: 0,
359
- color: theme.palette.text.secondary,
360
- textAlign: "left",
361
- }}
362
- >
363
- {t("RobotCard.Runtime.lb")}
364
- </Typography>
365
-
366
- {/* Compact cycle time component directly below runtime */}
367
- <Box sx={{ textAlign: "left" }}>
368
- <CycleTimerComponent
369
- variant="small"
370
- compact
371
- onCycleComplete={handleCycleComplete}
372
- onCycleEnd={onCycleEnd}
373
- autoStart={cycleTimerAutoStart}
374
- hasError={cycleTimerHasError}
375
- />
376
- </Box>
310
+ <CustomContentComponent />
377
311
 
378
312
  {/* Divider */}
379
313
  <Divider
@@ -387,7 +321,14 @@ export const RobotCard = externalizeComponent(
387
321
  </Box>
388
322
  )}
389
323
 
390
- <Box sx={{ mt: !shouldHideRuntime ? "auto" : 0 }}>
324
+ <Box
325
+ sx={{
326
+ mt:
327
+ !shouldHideCustomContent && CustomContentComponent
328
+ ? "auto"
329
+ : 0,
330
+ }}
331
+ >
391
332
  {/* Drive to Home button with some space */}
392
333
  <Box
393
334
  sx={{
@@ -488,31 +429,12 @@ export const RobotCard = externalizeComponent(
488
429
  )}
489
430
  </Box>
490
431
 
491
- {/* Bottom section with runtime, cycle time, and button */}
432
+ {/* Bottom section with custom content and button */}
492
433
  <Box>
493
- {/* Runtime view - hidden if height is too low */}
494
- {!shouldHideRuntime && (
434
+ {/* Custom content section - hidden if height is too low */}
435
+ {!shouldHideCustomContent && CustomContentComponent && (
495
436
  <>
496
- {/* Runtime display */}
497
- <Typography
498
- variant="body1"
499
- sx={{
500
- mb: 0,
501
- color: theme.palette.text.secondary,
502
- }}
503
- >
504
- {t("RobotCard.Runtime.lb")}
505
- </Typography>
506
-
507
- {/* Compact cycle time component directly below runtime */}
508
- <CycleTimerComponent
509
- variant="small"
510
- compact
511
- onCycleComplete={handleCycleComplete}
512
- onCycleEnd={onCycleEnd}
513
- autoStart={cycleTimerAutoStart}
514
- hasError={cycleTimerHasError}
515
- />
437
+ <CustomContentComponent />
516
438
 
517
439
  {/* Divider */}
518
440
  <Divider
@@ -531,9 +453,10 @@ export const RobotCard = externalizeComponent(
531
453
  sx={{
532
454
  display: "flex",
533
455
  justifyContent: "flex-start",
534
- mt: !shouldHideRuntime
535
- ? { xs: 1, sm: 2, md: 5 }
536
- : { xs: 0.5, sm: 1, md: 2 },
456
+ mt:
457
+ !shouldHideCustomContent && CustomContentComponent
458
+ ? { xs: 1, sm: 2, md: 5 }
459
+ : { xs: 0.5, sm: 1, md: 2 },
537
460
  mb: { xs: 0.5, sm: 0.75, md: 1 },
538
461
  }}
539
462
  >