@wandelbots/wandelbots-js-react-components 2.50.1 → 2.51.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/dist/components/CycleTimer/utils.d.ts +10 -1
- package/dist/components/CycleTimer/utils.d.ts.map +1 -1
- package/dist/index.cjs +28 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1165 -1155
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CycleTimer/DefaultVariant.tsx +3 -3
- package/src/components/CycleTimer/SmallVariant.tsx +11 -11
- package/src/components/CycleTimer/utils.ts +72 -3
- package/src/i18n/locales/de/translations.json +2 -2
- package/src/i18n/locales/en/translations.json +2 -2
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@ import { Box, Fade, Typography, useTheme } from "@mui/material"
|
|
|
2
2
|
import { Gauge } from "@mui/x-charts/Gauge"
|
|
3
3
|
import { useTranslation } from "react-i18next"
|
|
4
4
|
import type { AnimationState, TimerState } from "./types"
|
|
5
|
-
import { formatTime } from "./utils"
|
|
5
|
+
import { formatTime, formatTimeLocalized } from "./utils"
|
|
6
6
|
|
|
7
7
|
interface DefaultVariantProps {
|
|
8
8
|
timerState: TimerState
|
|
@@ -17,7 +17,7 @@ export const DefaultVariant = ({
|
|
|
17
17
|
hasError,
|
|
18
18
|
className,
|
|
19
19
|
}: DefaultVariantProps) => {
|
|
20
|
-
const { t } = useTranslation()
|
|
20
|
+
const { t, i18n } = useTranslation()
|
|
21
21
|
const theme = useTheme()
|
|
22
22
|
const { currentState, remainingTime, maxTime, currentProgress } = timerState
|
|
23
23
|
const {
|
|
@@ -310,7 +310,7 @@ export const DefaultVariant = ({
|
|
|
310
310
|
? t("CycleTimer.Determined.lb", "determined")
|
|
311
311
|
: currentState === "countdown" && maxTime !== null
|
|
312
312
|
? t("CycleTimer.OfTime.lb", {
|
|
313
|
-
time:
|
|
313
|
+
time: formatTimeLocalized(maxTime, i18n.language),
|
|
314
314
|
})
|
|
315
315
|
: ""}
|
|
316
316
|
</span>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box, Typography, useTheme } from "@mui/material"
|
|
2
2
|
import { useTranslation } from "react-i18next"
|
|
3
3
|
import type { AnimationState, TimerState } from "./types"
|
|
4
|
-
import {
|
|
4
|
+
import { formatTimeLocalized } from "./utils"
|
|
5
5
|
|
|
6
6
|
interface SmallVariantProps {
|
|
7
7
|
timerState: TimerState
|
|
@@ -18,7 +18,7 @@ export const SmallVariant = ({
|
|
|
18
18
|
compact,
|
|
19
19
|
className,
|
|
20
20
|
}: SmallVariantProps) => {
|
|
21
|
-
const { t } = useTranslation()
|
|
21
|
+
const { t, i18n } = useTranslation()
|
|
22
22
|
const theme = useTheme()
|
|
23
23
|
const { currentState, remainingTime, maxTime } = timerState
|
|
24
24
|
const {
|
|
@@ -54,8 +54,8 @@ export const SmallVariant = ({
|
|
|
54
54
|
{hasError
|
|
55
55
|
? t("CycleTimer.Error.lb", "Error")
|
|
56
56
|
: currentState === "idle"
|
|
57
|
-
? "
|
|
58
|
-
:
|
|
57
|
+
? "0s"
|
|
58
|
+
: formatTimeLocalized(remainingTime, i18n.language)}
|
|
59
59
|
</Typography>
|
|
60
60
|
</Box>
|
|
61
61
|
)
|
|
@@ -202,24 +202,24 @@ export const SmallVariant = ({
|
|
|
202
202
|
</>
|
|
203
203
|
) : currentState === "measuring" ? (
|
|
204
204
|
compact ? (
|
|
205
|
-
`${
|
|
205
|
+
`${formatTimeLocalized(remainingTime, i18n.language)} ${t("CycleTimer.Time.lb", { time: "" }).replace(/\s*$/, "")}`
|
|
206
206
|
) : (
|
|
207
|
-
`${
|
|
207
|
+
`${formatTimeLocalized(remainingTime, i18n.language)} / ${t("CycleTimer.Measuring.lb", "measuring...")}`
|
|
208
208
|
)
|
|
209
209
|
) : currentState === "measured" ? (
|
|
210
210
|
compact ? (
|
|
211
|
-
`${
|
|
211
|
+
`${formatTimeLocalized(remainingTime, i18n.language)} ${t("CycleTimer.Time.lb", { time: "" }).replace(/\s*$/, "")}`
|
|
212
212
|
) : (
|
|
213
|
-
`${
|
|
213
|
+
`${formatTimeLocalized(remainingTime, i18n.language)} / ${t("CycleTimer.Determined.lb", "determined")}`
|
|
214
214
|
)
|
|
215
215
|
) : currentState === "countdown" && maxTime !== null ? (
|
|
216
216
|
compact ? (
|
|
217
|
-
`${
|
|
217
|
+
`${formatTimeLocalized(remainingTime, i18n.language)} ${t("CycleTimer.Time.lb", { time: "" }).replace(/\s*$/, "")}`
|
|
218
218
|
) : (
|
|
219
|
-
`${
|
|
219
|
+
`${formatTimeLocalized(remainingTime, i18n.language)} / ${t("CycleTimer.Time.lb", { time: formatTimeLocalized(maxTime, i18n.language) })}`
|
|
220
220
|
)
|
|
221
221
|
) : (
|
|
222
|
-
|
|
222
|
+
formatTimeLocalized(remainingTime, i18n.language)
|
|
223
223
|
)}
|
|
224
224
|
</Typography>
|
|
225
225
|
</Box>
|
|
@@ -1,10 +1,79 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Formats time in seconds to MM:SS format
|
|
2
|
+
* Formats time in seconds to D:HH:MM:SS, H:MM:SS or MM:SS format
|
|
3
|
+
* Used for the default (large) timer variant
|
|
4
|
+
* Automatically includes days and hours as needed for clarity
|
|
3
5
|
*/
|
|
4
6
|
export const formatTime = (seconds: number): string => {
|
|
5
|
-
const
|
|
7
|
+
const days = Math.floor(seconds / 86400)
|
|
8
|
+
const hours = Math.floor((seconds % 86400) / 3600)
|
|
9
|
+
const minutes = Math.floor((seconds % 3600) / 60)
|
|
6
10
|
const remainingSeconds = seconds % 60
|
|
7
|
-
|
|
11
|
+
|
|
12
|
+
// Build time parts array
|
|
13
|
+
const parts: string[] = []
|
|
14
|
+
|
|
15
|
+
if (days > 0) {
|
|
16
|
+
parts.push(days.toString())
|
|
17
|
+
parts.push(hours.toString().padStart(2, "0"))
|
|
18
|
+
parts.push(minutes.toString().padStart(2, "0"))
|
|
19
|
+
parts.push(remainingSeconds.toString().padStart(2, "0"))
|
|
20
|
+
} else if (hours > 0) {
|
|
21
|
+
parts.push(hours.toString())
|
|
22
|
+
parts.push(minutes.toString().padStart(2, "0"))
|
|
23
|
+
parts.push(remainingSeconds.toString().padStart(2, "0"))
|
|
24
|
+
} else {
|
|
25
|
+
parts.push(minutes.toString())
|
|
26
|
+
parts.push(remainingSeconds.toString().padStart(2, "0"))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return parts.join(":")
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Formats time in seconds to a localized human-readable format
|
|
34
|
+
* Used for the small timer variant
|
|
35
|
+
* Examples: "2h 30m 15s", "45m 30s", "30s"
|
|
36
|
+
* Falls back to English units if Intl.DurationFormat is not available
|
|
37
|
+
*/
|
|
38
|
+
export const formatTimeLocalized = (
|
|
39
|
+
seconds: number,
|
|
40
|
+
locale?: string,
|
|
41
|
+
): string => {
|
|
42
|
+
const days = Math.floor(seconds / 86400)
|
|
43
|
+
const hours = Math.floor((seconds % 86400) / 3600)
|
|
44
|
+
const minutes = Math.floor((seconds % 3600) / 60)
|
|
45
|
+
const remainingSeconds = seconds % 60
|
|
46
|
+
|
|
47
|
+
// Try using Intl.DurationFormat if available (newer browsers)
|
|
48
|
+
if (typeof Intl !== "undefined" && "DurationFormat" in Intl) {
|
|
49
|
+
try {
|
|
50
|
+
const duration: Record<string, number> = {}
|
|
51
|
+
if (days > 0) duration.days = days
|
|
52
|
+
if (hours > 0) duration.hours = hours
|
|
53
|
+
if (minutes > 0) duration.minutes = minutes
|
|
54
|
+
if (remainingSeconds > 0 || Object.keys(duration).length === 0) {
|
|
55
|
+
duration.seconds = remainingSeconds
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// @ts-expect-error - DurationFormat is not yet in TypeScript types
|
|
59
|
+
const formatter = new Intl.DurationFormat(locale, { style: "narrow" })
|
|
60
|
+
return formatter.format(duration)
|
|
61
|
+
} catch {
|
|
62
|
+
// Fall through to manual formatting
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Manual formatting with compact units
|
|
67
|
+
const parts: string[] = []
|
|
68
|
+
|
|
69
|
+
if (days > 0) parts.push(`${days}d`)
|
|
70
|
+
if (hours > 0) parts.push(`${hours}h`)
|
|
71
|
+
if (minutes > 0) parts.push(`${minutes}m`)
|
|
72
|
+
if (remainingSeconds > 0 || parts.length === 0) {
|
|
73
|
+
parts.push(`${remainingSeconds}s`)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return parts.join(" ")
|
|
8
77
|
}
|
|
9
78
|
|
|
10
79
|
/**
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"Jogging.Joints.bt": "Gelenke",
|
|
46
46
|
"Jogging.Velocity.bt": "Geschwindigkeit",
|
|
47
47
|
"CycleTimer.RemainingTime.lb": "Verbleibende Zeit",
|
|
48
|
-
"CycleTimer.OfTime.lb": "von {{time}}
|
|
49
|
-
"CycleTimer.Time.lb": "{{time}}
|
|
48
|
+
"CycleTimer.OfTime.lb": "von {{time}}",
|
|
49
|
+
"CycleTimer.Time.lb": "{{time}}",
|
|
50
50
|
"CycleTimer.Error.lb": "Fehler",
|
|
51
51
|
"CycleTimer.WaitingForCycle.lb": "Warten auf Programmzyklus",
|
|
52
52
|
"CycleTimer.CycleTime.lb": "Zykluszeit",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"Jogging.Joints.bt": "Joints",
|
|
47
47
|
"Jogging.Velocity.bt": "Velocity",
|
|
48
48
|
"CycleTimer.RemainingTime.lb": "Time remaining",
|
|
49
|
-
"CycleTimer.OfTime.lb": "of {{time}}
|
|
50
|
-
"CycleTimer.Time.lb": "{{time}}
|
|
49
|
+
"CycleTimer.OfTime.lb": "of {{time}}",
|
|
50
|
+
"CycleTimer.Time.lb": "{{time}}",
|
|
51
51
|
"CycleTimer.Error.lb": "Error",
|
|
52
52
|
"CycleTimer.WaitingForCycle.lb": "Waiting for program cycle",
|
|
53
53
|
"CycleTimer.CycleTime.lb": "Cycle Time",
|