@wandelbots/wandelbots-js-react-components 2.37.0 → 2.38.0-pr.bugfix-add-bg-to-cycle-timer.380.f7d61ae

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.
Files changed (40) hide show
  1. package/dist/components/CycleTimer/CycleTimer.d.ts +3 -0
  2. package/dist/components/CycleTimer/CycleTimer.d.ts.map +1 -0
  3. package/dist/components/CycleTimer/DefaultVariant.d.ts +10 -0
  4. package/dist/components/CycleTimer/DefaultVariant.d.ts.map +1 -0
  5. package/dist/components/CycleTimer/SmallVariant.d.ts +11 -0
  6. package/dist/components/CycleTimer/SmallVariant.d.ts.map +1 -0
  7. package/dist/components/CycleTimer/index.d.ts +28 -0
  8. package/dist/components/CycleTimer/index.d.ts.map +1 -0
  9. package/dist/components/CycleTimer/types.d.ts +51 -0
  10. package/dist/components/CycleTimer/types.d.ts.map +1 -0
  11. package/dist/components/CycleTimer/useAnimations.d.ts +15 -0
  12. package/dist/components/CycleTimer/useAnimations.d.ts.map +1 -0
  13. package/dist/components/CycleTimer/useTimerLogic.d.ts +26 -0
  14. package/dist/components/CycleTimer/useTimerLogic.d.ts.map +1 -0
  15. package/dist/components/CycleTimer/utils.d.ts +13 -0
  16. package/dist/components/CycleTimer/utils.d.ts.map +1 -0
  17. package/dist/components/CycleTimer.d.ts +2 -96
  18. package/dist/components/CycleTimer.d.ts.map +1 -1
  19. package/dist/components/jogging/PoseCartesianValues.d.ts +8 -4
  20. package/dist/components/jogging/PoseCartesianValues.d.ts.map +1 -1
  21. package/dist/components/jogging/PoseJointValues.d.ts +8 -4
  22. package/dist/components/jogging/PoseJointValues.d.ts.map +1 -1
  23. package/dist/index.cjs +50 -50
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.js +9302 -8800
  26. package/dist/index.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/components/CycleTimer/CycleTimer.ts +6 -0
  29. package/src/components/CycleTimer/DefaultVariant.tsx +325 -0
  30. package/src/components/CycleTimer/SmallVariant.tsx +230 -0
  31. package/src/components/CycleTimer/index.tsx +157 -0
  32. package/src/components/CycleTimer/types.ts +60 -0
  33. package/src/components/CycleTimer/useAnimations.ts +202 -0
  34. package/src/components/CycleTimer/useTimerLogic.ts +386 -0
  35. package/src/components/CycleTimer/utils.ts +53 -0
  36. package/src/components/CycleTimer.tsx +6 -715
  37. package/src/components/jogging/PoseCartesianValues.tsx +85 -7
  38. package/src/components/jogging/PoseJointValues.tsx +86 -8
  39. package/src/i18n/locales/de/translations.json +4 -0
  40. package/src/i18n/locales/en/translations.json +4 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wandelbots/wandelbots-js-react-components",
3
- "version": "2.37.0",
3
+ "version": "2.38.0-pr.bugfix-add-bg-to-cycle-timer.380.f7d61ae",
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,6 @@
1
+ export { CycleTimer } from "./index"
2
+ export type {
3
+ CycleTimerControls,
4
+ CycleTimerProps,
5
+ CycleTimerState,
6
+ } from "./types"
@@ -0,0 +1,325 @@
1
+ import { Box, Fade, Typography, useTheme } from "@mui/material"
2
+ import { Gauge } from "@mui/x-charts/Gauge"
3
+ import { useTranslation } from "react-i18next"
4
+ import type { AnimationState, TimerState } from "./types"
5
+ import { formatTime } from "./utils"
6
+
7
+ interface DefaultVariantProps {
8
+ timerState: TimerState
9
+ animationState: AnimationState
10
+ hasError: boolean
11
+ className?: string
12
+ }
13
+
14
+ export const DefaultVariant = ({
15
+ timerState,
16
+ animationState,
17
+ hasError,
18
+ className,
19
+ }: DefaultVariantProps) => {
20
+ const { t } = useTranslation()
21
+ const theme = useTheme()
22
+ const { currentState, remainingTime, maxTime, currentProgress } = timerState
23
+ const {
24
+ showErrorAnimation,
25
+ showPauseAnimation,
26
+ showPulsatingText,
27
+ pulsatingFinished,
28
+ showLabels,
29
+ showMainText,
30
+ showIdlePulsating,
31
+ idleDotsCount,
32
+ } = animationState
33
+
34
+ return (
35
+ <Box
36
+ className={className}
37
+ sx={{
38
+ position: "relative",
39
+ width: 264,
40
+ height: 264,
41
+ display: "flex",
42
+ alignItems: "center",
43
+ justifyContent: "center",
44
+ }}
45
+ >
46
+ <Gauge
47
+ width={264}
48
+ height={264}
49
+ value={currentState === "idle" ? 0 : currentProgress}
50
+ valueMin={0}
51
+ valueMax={100}
52
+ innerRadius="85%"
53
+ outerRadius="100%"
54
+ margin={0}
55
+ skipAnimation={true}
56
+ text={() => ""}
57
+ sx={{
58
+ opacity: showPauseAnimation || showErrorAnimation ? 0.6 : 1,
59
+ transition: "opacity 0.5s ease-out",
60
+ [`& .MuiGauge-valueArc`]: {
61
+ fill: hasError
62
+ ? theme.palette.error.light
63
+ : theme.palette.success.main,
64
+ transition: "fill 0.5s ease-out",
65
+ },
66
+ [`& .MuiGauge-referenceArc`]: {
67
+ fill: currentState === "idle" ? "#171927" : "#171927",
68
+ stroke: "transparent",
69
+ strokeWidth: 0,
70
+ transition:
71
+ "fill 0.5s ease-out, stroke 0.5s ease-out, stroke-width 0.5s ease-out",
72
+ },
73
+ [`& .MuiGauge-valueText`]: {
74
+ display: "none",
75
+ },
76
+ [`& .MuiGauge-text`]: {
77
+ display: "none",
78
+ },
79
+ }}
80
+ />
81
+
82
+ {/* Center content overlay */}
83
+ <Box
84
+ sx={{
85
+ position: "absolute",
86
+ top: "50%",
87
+ left: "50%",
88
+ transform: "translate(-50%, -50%)",
89
+ width: 225,
90
+ height: 225,
91
+ borderRadius: "50%",
92
+ backgroundColor: "#292B3F",
93
+ display: "flex",
94
+ flexDirection: "column",
95
+ alignItems: "center",
96
+ justifyContent: "center",
97
+ textAlign: "center",
98
+ gap: 1,
99
+ transition: "background-color 0.5s ease-out",
100
+ }}
101
+ >
102
+ {/* Top label */}
103
+ <Box
104
+ sx={{
105
+ height: "16px",
106
+ display: "flex",
107
+ alignItems: "center",
108
+ justifyContent: "center",
109
+ marginBottom: 1,
110
+ }}
111
+ >
112
+ <Fade
113
+ in={
114
+ showLabels &&
115
+ !hasError &&
116
+ currentState !== "idle" &&
117
+ currentState !== "countup" &&
118
+ currentState !== "success"
119
+ }
120
+ timeout={200}
121
+ >
122
+ <Typography
123
+ variant="body2"
124
+ sx={{
125
+ fontSize: "12px",
126
+ color:
127
+ currentState === "measured"
128
+ ? showPulsatingText || pulsatingFinished
129
+ ? theme.palette.success.main
130
+ : theme.palette.text.secondary
131
+ : theme.palette.text.secondary,
132
+ transition: "color 0.8s ease-in-out",
133
+ }}
134
+ >
135
+ <span
136
+ style={{
137
+ opacity:
138
+ currentState === "measured" && pulsatingFinished
139
+ ? showPulsatingText
140
+ ? 1
141
+ : 0.6
142
+ : 1,
143
+ transition: "opacity 2s ease-in-out",
144
+ }}
145
+ >
146
+ {currentState === "measuring"
147
+ ? t("CycleTimer.CycleTime.lb", "Cycle Time")
148
+ : currentState === "measured"
149
+ ? t("CycleTimer.CycleTime.lb", "Cycle Time")
150
+ : currentState === "countdown"
151
+ ? t("CycleTimer.RemainingTime.lb", "Remaining Time")
152
+ : ""}
153
+ </span>
154
+ </Typography>
155
+ </Fade>
156
+ </Box>
157
+
158
+ {/* Main display */}
159
+ <Box
160
+ sx={{
161
+ position: "relative",
162
+ height: "48px",
163
+ display: "flex",
164
+ alignItems: "center",
165
+ justifyContent: "center",
166
+ marginBottom: 0.5,
167
+ }}
168
+ >
169
+ {/* Idle state text */}
170
+ <Fade
171
+ in={showMainText && currentState === "idle" && !hasError}
172
+ timeout={200}
173
+ >
174
+ <Typography
175
+ variant="body2"
176
+ sx={{
177
+ position: "absolute",
178
+ fontSize: "12px",
179
+ fontWeight: 400,
180
+ color: "rgba(255, 255, 255, 0.7)",
181
+ lineHeight: "166%",
182
+ letterSpacing: "0.17px",
183
+ textAlign: "center",
184
+ width: "200px",
185
+ height: "20px",
186
+ display: "flex",
187
+ alignItems: "center",
188
+ justifyContent: "center",
189
+ }}
190
+ >
191
+ <span
192
+ style={{
193
+ opacity: showIdlePulsating ? 1 : 0.6,
194
+ transition: "opacity 2s ease-in-out",
195
+ }}
196
+ >
197
+ {t(
198
+ "CycleTimer.WaitingForCycle.lb",
199
+ "Waiting for program cycle",
200
+ )}
201
+ </span>
202
+ <span
203
+ style={{
204
+ display: "inline-block",
205
+ width: "18px",
206
+ textAlign: "left",
207
+ opacity: showIdlePulsating ? 1 : 0.6,
208
+ transition: "opacity 2s ease-in-out",
209
+ }}
210
+ >
211
+ {".".repeat(idleDotsCount)}
212
+ </span>
213
+ </Typography>
214
+ </Fade>
215
+
216
+ {/* Error text */}
217
+ <Fade in={showMainText && hasError} timeout={200}>
218
+ <Typography
219
+ variant="h3"
220
+ sx={{
221
+ position: "absolute",
222
+ fontSize: "40px",
223
+ fontWeight: 400,
224
+ color: "#FFFFFF",
225
+ lineHeight: "116.7%",
226
+ }}
227
+ >
228
+ {t("CycleTimer.Error.lb", "Error")}
229
+ </Typography>
230
+ </Fade>
231
+
232
+ {/* Normal timer text */}
233
+ <Fade
234
+ in={
235
+ showMainText &&
236
+ !hasError &&
237
+ currentState !== "idle" &&
238
+ currentState !== "success"
239
+ }
240
+ timeout={200}
241
+ >
242
+ <Typography
243
+ variant="h1"
244
+ sx={{
245
+ position: "absolute",
246
+ fontSize: "48px",
247
+ fontWeight: 500,
248
+ color: theme.palette.text.primary,
249
+ lineHeight: 1,
250
+ transition: "color 0.8s ease-in-out",
251
+ }}
252
+ >
253
+ <span
254
+ style={{
255
+ opacity: 1,
256
+ transition: "opacity 2s ease-in-out",
257
+ }}
258
+ >
259
+ {formatTime(remainingTime)}
260
+ </span>
261
+ </Typography>
262
+ </Fade>
263
+ </Box>
264
+
265
+ {/* Bottom label */}
266
+ <Box
267
+ sx={{
268
+ height: "16px",
269
+ display: "flex",
270
+ marginTop: 0.5,
271
+ alignItems: "center",
272
+ justifyContent: "center",
273
+ }}
274
+ >
275
+ <Fade
276
+ in={
277
+ showLabels &&
278
+ !hasError &&
279
+ currentState !== "idle" &&
280
+ currentState !== "countup" &&
281
+ currentState !== "success"
282
+ }
283
+ timeout={200}
284
+ >
285
+ <Typography
286
+ variant="body2"
287
+ sx={{
288
+ fontSize: "12px",
289
+ color:
290
+ currentState === "measured"
291
+ ? showPulsatingText || pulsatingFinished
292
+ ? theme.palette.success.main
293
+ : theme.palette.text.secondary
294
+ : theme.palette.text.secondary,
295
+ transition: "color 0.8s ease-in-out",
296
+ }}
297
+ >
298
+ <span
299
+ style={{
300
+ opacity:
301
+ currentState === "measured" && pulsatingFinished
302
+ ? showPulsatingText
303
+ ? 1
304
+ : 0.6
305
+ : 1,
306
+ transition: "opacity 2s ease-in-out",
307
+ }}
308
+ >
309
+ {currentState === "measuring"
310
+ ? t("CycleTimer.Measuring.lb", "measuring...")
311
+ : currentState === "measured"
312
+ ? t("CycleTimer.Determined.lb", "determined")
313
+ : currentState === "countdown" && maxTime !== null
314
+ ? t("CycleTimer.OfTime.lb", {
315
+ time: formatTime(maxTime),
316
+ })
317
+ : ""}
318
+ </span>
319
+ </Typography>
320
+ </Fade>
321
+ </Box>
322
+ </Box>
323
+ </Box>
324
+ )
325
+ }
@@ -0,0 +1,230 @@
1
+ import { Box, Typography, useTheme } from "@mui/material"
2
+ import { useTranslation } from "react-i18next"
3
+ import type { AnimationState, TimerState } from "./types"
4
+ import { formatTime } from "./utils"
5
+
6
+ interface SmallVariantProps {
7
+ timerState: TimerState
8
+ animationState: AnimationState
9
+ hasError: boolean
10
+ compact: boolean
11
+ className?: string
12
+ }
13
+
14
+ export const SmallVariant = ({
15
+ timerState,
16
+ animationState,
17
+ hasError,
18
+ compact,
19
+ className,
20
+ }: SmallVariantProps) => {
21
+ const { t } = useTranslation()
22
+ const theme = useTheme()
23
+ const { currentState, remainingTime, maxTime } = timerState
24
+ const {
25
+ showErrorAnimation,
26
+ showPauseAnimation,
27
+ showPulsatingText,
28
+ pulsatingFinished,
29
+ showIdlePulsating,
30
+ idleDotsCount,
31
+ } = animationState
32
+
33
+ // Simple text-only mode for compact variant in certain states
34
+ if (compact && (currentState === "countup" || currentState === "idle")) {
35
+ return (
36
+ <Box
37
+ className={className}
38
+ sx={{
39
+ display: "flex",
40
+ alignItems: "center",
41
+ m: 0,
42
+ }}
43
+ >
44
+ <Typography
45
+ variant="body2"
46
+ sx={{
47
+ color: hasError
48
+ ? theme.palette.error.light
49
+ : theme.palette.text.primary,
50
+ fontSize: "14px",
51
+ transition: "color 0.5s ease-out",
52
+ }}
53
+ >
54
+ {hasError
55
+ ? t("CycleTimer.Error.lb", "Error")
56
+ : currentState === "idle"
57
+ ? "0:00"
58
+ : formatTime(remainingTime)}
59
+ </Typography>
60
+ </Box>
61
+ )
62
+ }
63
+
64
+ return (
65
+ <Box
66
+ className={className}
67
+ sx={{
68
+ display: "flex",
69
+ alignItems: "center",
70
+ m: 0,
71
+ gap: 1,
72
+ }}
73
+ >
74
+ {/* Animated progress ring icon */}
75
+ {!(
76
+ currentState === "countup" ||
77
+ (currentState === "idle" && compact)
78
+ ) && (
79
+ <Box
80
+ sx={{
81
+ width: 20,
82
+ height: 20,
83
+ display: "flex",
84
+ alignItems: "center",
85
+ justifyContent: "center",
86
+ opacity: showPauseAnimation || showErrorAnimation ? 0.6 : 1,
87
+ transition: "opacity 0.5s ease-out",
88
+ }}
89
+ >
90
+ <svg
91
+ width="20"
92
+ height="20"
93
+ viewBox="0 0 20 20"
94
+ style={{ transform: "rotate(-90deg)" }}
95
+ role="img"
96
+ aria-label="Timer progress"
97
+ >
98
+ {/* Background ring */}
99
+ <circle
100
+ cx="10"
101
+ cy="10"
102
+ r="8"
103
+ fill="none"
104
+ stroke={
105
+ hasError
106
+ ? theme.palette.error.light
107
+ : currentState === "measured"
108
+ ? showPulsatingText || pulsatingFinished
109
+ ? theme.palette.success.main
110
+ : theme.palette.text.secondary
111
+ : theme.palette.success.main
112
+ }
113
+ strokeWidth="2"
114
+ opacity={
115
+ currentState === "measured" && pulsatingFinished
116
+ ? showPulsatingText
117
+ ? 1
118
+ : 0.6
119
+ : 0.3
120
+ }
121
+ style={{
122
+ transition: "stroke 0.8s ease-in-out, opacity 2s ease-in-out",
123
+ }}
124
+ />
125
+ {/* Progress ring */}
126
+ <circle
127
+ cx="10"
128
+ cy="10"
129
+ r="8"
130
+ fill="none"
131
+ stroke={
132
+ hasError
133
+ ? theme.palette.error.light
134
+ : currentState === "measured"
135
+ ? showPulsatingText || pulsatingFinished
136
+ ? theme.palette.success.main
137
+ : theme.palette.text.secondary
138
+ : theme.palette.success.main
139
+ }
140
+ strokeWidth="2"
141
+ strokeLinecap="round"
142
+ strokeDasharray={`${2 * Math.PI * 8}`}
143
+ strokeDashoffset={`${2 * Math.PI * 8 * (1 - (currentState === "idle" ? 0 : timerState.currentProgress) / 100)}`}
144
+ style={{
145
+ opacity:
146
+ currentState === "measured" && pulsatingFinished
147
+ ? showPulsatingText
148
+ ? 1
149
+ : 0.6
150
+ : 1,
151
+ transition:
152
+ "stroke-dashoffset 0.1s ease-out, stroke 0.8s ease-in-out, opacity 2s ease-in-out",
153
+ }}
154
+ />
155
+ </svg>
156
+ </Box>
157
+ )}
158
+
159
+ {/* Timer text display */}
160
+ <Typography
161
+ variant="body2"
162
+ sx={{
163
+ color: hasError
164
+ ? theme.palette.error.light
165
+ : currentState === "idle"
166
+ ? "rgba(255, 255, 255, 0.7)"
167
+ : currentState === "measured"
168
+ ? showPulsatingText || pulsatingFinished
169
+ ? theme.palette.success.main
170
+ : theme.palette.text.secondary
171
+ : theme.palette.text.primary,
172
+ fontSize: "14px",
173
+ lineHeight: "normal",
174
+ letterSpacing: "normal",
175
+ opacity:
176
+ currentState === "idle"
177
+ ? showIdlePulsating
178
+ ? 1
179
+ : 0.6
180
+ : currentState === "measured" && pulsatingFinished
181
+ ? showPulsatingText
182
+ ? 1
183
+ : 0.6
184
+ : 1,
185
+ transition:
186
+ "color 0.8s ease-in-out, font-size 0.3s ease-out, opacity 2s ease-in-out",
187
+ }}
188
+ >
189
+ {hasError ? (
190
+ t("CycleTimer.Error.lb", "Error")
191
+ ) : currentState === "idle" ? (
192
+ <>
193
+ <span>
194
+ {t("CycleTimer.WaitingForCycle.lb", "Waiting for program cycle")}
195
+ </span>
196
+ <span
197
+ style={{
198
+ display: "inline-block",
199
+ width: "18px",
200
+ textAlign: "left",
201
+ }}
202
+ >
203
+ {".".repeat(idleDotsCount)}
204
+ </span>
205
+ </>
206
+ ) : currentState === "measuring" ? (
207
+ compact ? (
208
+ `${formatTime(remainingTime)} ${t("CycleTimer.Time.lb", { time: "" }).replace(/\s*$/, "")}`
209
+ ) : (
210
+ `${formatTime(remainingTime)} / ${t("CycleTimer.Measuring.lb", "measuring...")}`
211
+ )
212
+ ) : currentState === "measured" ? (
213
+ compact ? (
214
+ `${formatTime(remainingTime)} ${t("CycleTimer.Time.lb", { time: "" }).replace(/\s*$/, "")}`
215
+ ) : (
216
+ `${formatTime(remainingTime)} / ${t("CycleTimer.Determined.lb", "determined")}`
217
+ )
218
+ ) : currentState === "countdown" && maxTime !== null ? (
219
+ compact ? (
220
+ `${formatTime(remainingTime)} ${t("CycleTimer.Time.lb", { time: "" }).replace(/\s*$/, "")}`
221
+ ) : (
222
+ `${formatTime(remainingTime)} / ${t("CycleTimer.Time.lb", { time: formatTime(maxTime) })}`
223
+ )
224
+ ) : (
225
+ formatTime(remainingTime)
226
+ )}
227
+ </Typography>
228
+ </Box>
229
+ )
230
+ }