@wandelbots/wandelbots-js-react-components 2.37.0 → 2.38.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/CycleTimer.d.ts +3 -0
- package/dist/components/CycleTimer/CycleTimer.d.ts.map +1 -0
- package/dist/components/CycleTimer/DefaultVariant.d.ts +10 -0
- package/dist/components/CycleTimer/DefaultVariant.d.ts.map +1 -0
- package/dist/components/CycleTimer/SmallVariant.d.ts +11 -0
- package/dist/components/CycleTimer/SmallVariant.d.ts.map +1 -0
- package/dist/components/CycleTimer/index.d.ts +28 -0
- package/dist/components/CycleTimer/index.d.ts.map +1 -0
- package/dist/components/CycleTimer/types.d.ts +51 -0
- package/dist/components/CycleTimer/types.d.ts.map +1 -0
- package/dist/components/CycleTimer/useAnimations.d.ts +15 -0
- package/dist/components/CycleTimer/useAnimations.d.ts.map +1 -0
- package/dist/components/CycleTimer/useTimerLogic.d.ts +26 -0
- package/dist/components/CycleTimer/useTimerLogic.d.ts.map +1 -0
- package/dist/components/CycleTimer/utils.d.ts +13 -0
- package/dist/components/CycleTimer/utils.d.ts.map +1 -0
- package/dist/components/CycleTimer.d.ts +2 -96
- package/dist/components/CycleTimer.d.ts.map +1 -1
- package/dist/components/jogging/PoseCartesianValues.d.ts +8 -4
- package/dist/components/jogging/PoseCartesianValues.d.ts.map +1 -1
- package/dist/components/jogging/PoseJointValues.d.ts +8 -4
- package/dist/components/jogging/PoseJointValues.d.ts.map +1 -1
- package/dist/index.cjs +50 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9299 -8800
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CycleTimer/CycleTimer.ts +6 -0
- package/src/components/CycleTimer/DefaultVariant.tsx +327 -0
- package/src/components/CycleTimer/SmallVariant.tsx +230 -0
- package/src/components/CycleTimer/index.tsx +157 -0
- package/src/components/CycleTimer/types.ts +60 -0
- package/src/components/CycleTimer/useAnimations.ts +202 -0
- package/src/components/CycleTimer/useTimerLogic.ts +386 -0
- package/src/components/CycleTimer/utils.ts +53 -0
- package/src/components/CycleTimer.tsx +6 -715
- package/src/components/jogging/PoseCartesianValues.tsx +85 -7
- package/src/components/jogging/PoseJointValues.tsx +86 -8
- package/src/i18n/locales/de/translations.json +4 -0
- package/src/i18n/locales/en/translations.json +4 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { observer } from "mobx-react-lite"
|
|
2
|
+
import { useEffect, useRef } from "react"
|
|
3
|
+
import { externalizeComponent } from "../../externalizeComponent"
|
|
4
|
+
import { DefaultVariant } from "./DefaultVariant"
|
|
5
|
+
import { SmallVariant } from "./SmallVariant"
|
|
6
|
+
import type { CycleTimerProps } from "./types"
|
|
7
|
+
import { useAnimations } from "./useAnimations"
|
|
8
|
+
import { useTimerLogic } from "./useTimerLogic"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A circular gauge timer component that shows the remaining time of a cycle or counts up
|
|
12
|
+
*
|
|
13
|
+
* Features:
|
|
14
|
+
* - Custom SVG circular gauge with 264px diameter and 40px thickness
|
|
15
|
+
* - Multiple states: idle, measuring, measured, countdown, countup, success
|
|
16
|
+
* - Idle state: shows "Waiting for program cycle" with transparent inner circle
|
|
17
|
+
* - Measuring state: counts up with "Cycle Time" / "measuring..." labels
|
|
18
|
+
* - Measured state: shows final time with "Cycle Time" / "determined" labels in pulsating green
|
|
19
|
+
* - Countdown mode: shows remaining time prominently, counts down to zero
|
|
20
|
+
* - Count-up mode: shows elapsed time without special labels
|
|
21
|
+
* - Success state: brief green flash after cycle completion
|
|
22
|
+
* - Displays appropriate labels based on state
|
|
23
|
+
* - Automatically counts down/up and triggers callback when reaching zero (countdown only)
|
|
24
|
+
* - Full timer control: start, pause, resume functionality
|
|
25
|
+
* - Support for starting with elapsed time (resume mid-cycle)
|
|
26
|
+
* - Error state support: pauses timer and shows error styling (red color)
|
|
27
|
+
* - Smooth fade transitions between different text states
|
|
28
|
+
* - Pulsating text animation for completed measuring state
|
|
29
|
+
* - Fully localized with i18next
|
|
30
|
+
* - Material-UI theming integration
|
|
31
|
+
* - Small variant with animated progress icon (gauge border only) next to text or simple text-only mode
|
|
32
|
+
*/
|
|
33
|
+
export const CycleTimer = externalizeComponent(
|
|
34
|
+
observer(
|
|
35
|
+
({
|
|
36
|
+
onCycleComplete,
|
|
37
|
+
onCycleEnd,
|
|
38
|
+
onMeasuringComplete,
|
|
39
|
+
autoStart = true,
|
|
40
|
+
variant = "default",
|
|
41
|
+
compact = false,
|
|
42
|
+
className,
|
|
43
|
+
hasError = false,
|
|
44
|
+
}: CycleTimerProps) => {
|
|
45
|
+
const prevStateRef = useRef<string | undefined>(undefined)
|
|
46
|
+
|
|
47
|
+
// Initialize animation hooks
|
|
48
|
+
const {
|
|
49
|
+
animationState,
|
|
50
|
+
triggerPauseAnimation,
|
|
51
|
+
triggerErrorAnimation,
|
|
52
|
+
clearErrorAnimation,
|
|
53
|
+
startPulsatingAnimation,
|
|
54
|
+
stopPulsatingAnimation,
|
|
55
|
+
startIdleAnimations,
|
|
56
|
+
stopIdleAnimations,
|
|
57
|
+
triggerFadeTransition,
|
|
58
|
+
setInitialAnimationState,
|
|
59
|
+
cleanup,
|
|
60
|
+
} = useAnimations()
|
|
61
|
+
|
|
62
|
+
// Initialize timer logic
|
|
63
|
+
const { timerState, controls } = useTimerLogic({
|
|
64
|
+
autoStart,
|
|
65
|
+
onCycleEnd,
|
|
66
|
+
onMeasuringComplete,
|
|
67
|
+
hasError,
|
|
68
|
+
onPauseAnimation: triggerPauseAnimation,
|
|
69
|
+
onErrorAnimation: triggerErrorAnimation,
|
|
70
|
+
onClearErrorAnimation: clearErrorAnimation,
|
|
71
|
+
onStartPulsating: startPulsatingAnimation,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// Handle state changes with fade transitions
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
const prevState = prevStateRef.current
|
|
77
|
+
|
|
78
|
+
if (
|
|
79
|
+
prevStateRef.current !== undefined &&
|
|
80
|
+
prevState !== timerState.currentState
|
|
81
|
+
) {
|
|
82
|
+
// Stop pulsating animation if leaving measured state
|
|
83
|
+
if (prevState === "measured") {
|
|
84
|
+
stopPulsatingAnimation()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Stop idle animations if leaving idle state
|
|
88
|
+
if (prevState === "idle") {
|
|
89
|
+
stopIdleAnimations()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Trigger fade transition
|
|
93
|
+
triggerFadeTransition()
|
|
94
|
+
} else {
|
|
95
|
+
// No state change or first time - set initial state
|
|
96
|
+
setInitialAnimationState()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Start idle animations if entering idle state
|
|
100
|
+
if (timerState.currentState === "idle") {
|
|
101
|
+
startIdleAnimations()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
prevStateRef.current = timerState.currentState
|
|
105
|
+
}, [
|
|
106
|
+
timerState.currentState,
|
|
107
|
+
stopPulsatingAnimation,
|
|
108
|
+
stopIdleAnimations,
|
|
109
|
+
startIdleAnimations,
|
|
110
|
+
triggerFadeTransition,
|
|
111
|
+
setInitialAnimationState,
|
|
112
|
+
])
|
|
113
|
+
|
|
114
|
+
// Provide controls to parent component
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
let isMounted = true
|
|
117
|
+
const timeoutId = setTimeout(() => {
|
|
118
|
+
if (isMounted) {
|
|
119
|
+
onCycleComplete(controls)
|
|
120
|
+
}
|
|
121
|
+
}, 0)
|
|
122
|
+
|
|
123
|
+
return () => {
|
|
124
|
+
isMounted = false
|
|
125
|
+
clearTimeout(timeoutId)
|
|
126
|
+
}
|
|
127
|
+
}, [onCycleComplete, controls])
|
|
128
|
+
|
|
129
|
+
// Cleanup on unmount
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
return cleanup
|
|
132
|
+
}, [cleanup])
|
|
133
|
+
|
|
134
|
+
// Render appropriate variant
|
|
135
|
+
if (variant === "small") {
|
|
136
|
+
return (
|
|
137
|
+
<SmallVariant
|
|
138
|
+
timerState={timerState}
|
|
139
|
+
animationState={animationState}
|
|
140
|
+
hasError={hasError}
|
|
141
|
+
compact={compact}
|
|
142
|
+
className={className}
|
|
143
|
+
/>
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<DefaultVariant
|
|
149
|
+
timerState={timerState}
|
|
150
|
+
animationState={animationState}
|
|
151
|
+
hasError={hasError}
|
|
152
|
+
className={className}
|
|
153
|
+
/>
|
|
154
|
+
)
|
|
155
|
+
},
|
|
156
|
+
),
|
|
157
|
+
)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type CycleTimerState =
|
|
2
|
+
| "idle" // Initial state showing "Waiting for program cycle"
|
|
3
|
+
| "measuring" // Counting up without max time, showing "Cycle Time" / "measuring..."
|
|
4
|
+
| "measured" // Completed measuring state showing "Cycle Time" / "determined" with pulsating green text
|
|
5
|
+
| "countdown" // Counting down with max time
|
|
6
|
+
| "countup" // Simple count up without special text
|
|
7
|
+
| "success" // Brief success state after cycle completion
|
|
8
|
+
|
|
9
|
+
export interface CycleTimerControls {
|
|
10
|
+
startNewCycle: (maxTimeSeconds?: number, elapsedSeconds?: number) => void
|
|
11
|
+
startMeasuring: (elapsedSeconds?: number) => void
|
|
12
|
+
startCountUp: (elapsedSeconds?: number) => void
|
|
13
|
+
setIdle: () => void
|
|
14
|
+
completeMeasuring: () => void
|
|
15
|
+
pause: () => void
|
|
16
|
+
resume: () => void
|
|
17
|
+
isPaused: () => boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CycleTimerProps {
|
|
21
|
+
/**
|
|
22
|
+
* Callback that receives the timer control functions
|
|
23
|
+
*/
|
|
24
|
+
onCycleComplete: (controls: CycleTimerControls) => void
|
|
25
|
+
/** Callback fired when a cycle actually completes (reaches zero) */
|
|
26
|
+
onCycleEnd?: () => void
|
|
27
|
+
/** Callback fired when measuring cycle completes */
|
|
28
|
+
onMeasuringComplete?: () => void
|
|
29
|
+
/** Whether the timer should start automatically when maxTime is set */
|
|
30
|
+
autoStart?: boolean
|
|
31
|
+
/** Visual variant of the timer */
|
|
32
|
+
variant?: "default" | "small"
|
|
33
|
+
/** For small variant: whether to show remaining time details (compact hides them) */
|
|
34
|
+
compact?: boolean
|
|
35
|
+
/** Additional CSS classes */
|
|
36
|
+
className?: string
|
|
37
|
+
/** Whether the timer is in an error state (pauses timer and shows error styling) */
|
|
38
|
+
hasError?: boolean
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface TimerState {
|
|
42
|
+
currentState: CycleTimerState
|
|
43
|
+
remainingTime: number
|
|
44
|
+
maxTime: number | null
|
|
45
|
+
isRunning: boolean
|
|
46
|
+
isPausedState: boolean
|
|
47
|
+
currentProgress: number
|
|
48
|
+
wasRunningBeforeError: boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface AnimationState {
|
|
52
|
+
showPauseAnimation: boolean
|
|
53
|
+
showErrorAnimation: boolean
|
|
54
|
+
showPulsatingText: boolean
|
|
55
|
+
pulsatingFinished: boolean
|
|
56
|
+
showLabels: boolean
|
|
57
|
+
showMainText: boolean
|
|
58
|
+
showIdlePulsating: boolean
|
|
59
|
+
idleDotsCount: number
|
|
60
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { useCallback, useRef, useState } from "react"
|
|
2
|
+
import type { AnimationState } from "./types"
|
|
3
|
+
|
|
4
|
+
export const useAnimations = () => {
|
|
5
|
+
const [animationState, setAnimationState] = useState<AnimationState>({
|
|
6
|
+
showPauseAnimation: false,
|
|
7
|
+
showErrorAnimation: false,
|
|
8
|
+
showPulsatingText: false,
|
|
9
|
+
pulsatingFinished: false,
|
|
10
|
+
showLabels: true,
|
|
11
|
+
showMainText: true,
|
|
12
|
+
showIdlePulsating: false,
|
|
13
|
+
idleDotsCount: 0,
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
// Refs for managing timeouts and intervals
|
|
17
|
+
const pauseAnimationTimeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
18
|
+
const errorAnimationTimeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
19
|
+
const pulsatingIntervalRef = useRef<NodeJS.Timeout | null>(null)
|
|
20
|
+
const fadeTimeoutRef = useRef<NodeJS.Timeout | null>(null)
|
|
21
|
+
const pulseCountRef = useRef<number>(0)
|
|
22
|
+
const idlePulsatingIntervalRef = useRef<NodeJS.Timeout | null>(null)
|
|
23
|
+
const idleDotsIntervalRef = useRef<NodeJS.Timeout | null>(null)
|
|
24
|
+
|
|
25
|
+
const triggerPauseAnimation = useCallback(() => {
|
|
26
|
+
setAnimationState((prev) => ({ ...prev, showPauseAnimation: true }))
|
|
27
|
+
|
|
28
|
+
if (pauseAnimationTimeoutRef.current) {
|
|
29
|
+
clearTimeout(pauseAnimationTimeoutRef.current)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
pauseAnimationTimeoutRef.current = setTimeout(() => {
|
|
33
|
+
setAnimationState((prev) => ({ ...prev, showPauseAnimation: false }))
|
|
34
|
+
}, 800)
|
|
35
|
+
}, [])
|
|
36
|
+
|
|
37
|
+
const triggerErrorAnimation = useCallback(() => {
|
|
38
|
+
setAnimationState((prev) => ({ ...prev, showErrorAnimation: true }))
|
|
39
|
+
|
|
40
|
+
if (errorAnimationTimeoutRef.current) {
|
|
41
|
+
clearTimeout(errorAnimationTimeoutRef.current)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
errorAnimationTimeoutRef.current = setTimeout(() => {
|
|
45
|
+
setAnimationState((prev) => ({ ...prev, showErrorAnimation: false }))
|
|
46
|
+
}, 600)
|
|
47
|
+
}, [])
|
|
48
|
+
|
|
49
|
+
const clearErrorAnimation = useCallback(() => {
|
|
50
|
+
setAnimationState((prev) => ({ ...prev, showErrorAnimation: false }))
|
|
51
|
+
if (errorAnimationTimeoutRef.current) {
|
|
52
|
+
clearTimeout(errorAnimationTimeoutRef.current)
|
|
53
|
+
}
|
|
54
|
+
}, [])
|
|
55
|
+
|
|
56
|
+
const startPulsatingAnimation = useCallback((onComplete?: () => void) => {
|
|
57
|
+
pulseCountRef.current = 0
|
|
58
|
+
// Start with fade to success color
|
|
59
|
+
setAnimationState((prev) => ({
|
|
60
|
+
...prev,
|
|
61
|
+
showPulsatingText: true,
|
|
62
|
+
pulsatingFinished: false,
|
|
63
|
+
}))
|
|
64
|
+
|
|
65
|
+
// After initial success color fade, start slow pulsating like idle
|
|
66
|
+
setTimeout(() => {
|
|
67
|
+
setAnimationState((prev) => ({
|
|
68
|
+
...prev,
|
|
69
|
+
pulsatingFinished: true, // This will keep the success color and start slow pulsating
|
|
70
|
+
}))
|
|
71
|
+
|
|
72
|
+
// Start slow pulsating animation similar to idle
|
|
73
|
+
pulsatingIntervalRef.current = setInterval(() => {
|
|
74
|
+
setAnimationState((prev) => ({
|
|
75
|
+
...prev,
|
|
76
|
+
showPulsatingText: !prev.showPulsatingText,
|
|
77
|
+
}))
|
|
78
|
+
}, 2000) // Same slow timing as idle pulsating
|
|
79
|
+
|
|
80
|
+
if (onComplete) {
|
|
81
|
+
onComplete()
|
|
82
|
+
}
|
|
83
|
+
}, 800) // Initial success color display duration
|
|
84
|
+
}, [])
|
|
85
|
+
|
|
86
|
+
const stopPulsatingAnimation = useCallback(() => {
|
|
87
|
+
if (pulsatingIntervalRef.current) {
|
|
88
|
+
clearInterval(pulsatingIntervalRef.current)
|
|
89
|
+
pulsatingIntervalRef.current = null
|
|
90
|
+
}
|
|
91
|
+
// Reset all pulsating states to ensure colors are reset
|
|
92
|
+
setAnimationState((prev) => ({
|
|
93
|
+
...prev,
|
|
94
|
+
showPulsatingText: false,
|
|
95
|
+
pulsatingFinished: false,
|
|
96
|
+
}))
|
|
97
|
+
pulseCountRef.current = 0
|
|
98
|
+
}, [])
|
|
99
|
+
|
|
100
|
+
const startIdleAnimations = useCallback(() => {
|
|
101
|
+
// Start pulsating animation for the text
|
|
102
|
+
setAnimationState((prev) => ({
|
|
103
|
+
...prev,
|
|
104
|
+
showIdlePulsating: true,
|
|
105
|
+
}))
|
|
106
|
+
|
|
107
|
+
idlePulsatingIntervalRef.current = setInterval(() => {
|
|
108
|
+
setAnimationState((prev) => ({
|
|
109
|
+
...prev,
|
|
110
|
+
showIdlePulsating: !prev.showIdlePulsating,
|
|
111
|
+
}))
|
|
112
|
+
}, 2000) // Slower pulsate every 2 seconds
|
|
113
|
+
|
|
114
|
+
// Start animated dots
|
|
115
|
+
idleDotsIntervalRef.current = setInterval(() => {
|
|
116
|
+
setAnimationState((prev) => ({
|
|
117
|
+
...prev,
|
|
118
|
+
idleDotsCount: (prev.idleDotsCount + 1) % 4, // Cycle through 0, 1, 2, 3
|
|
119
|
+
}))
|
|
120
|
+
}, 800) // Change dots every 800ms
|
|
121
|
+
}, [])
|
|
122
|
+
|
|
123
|
+
const stopIdleAnimations = useCallback(() => {
|
|
124
|
+
if (idlePulsatingIntervalRef.current) {
|
|
125
|
+
clearInterval(idlePulsatingIntervalRef.current)
|
|
126
|
+
idlePulsatingIntervalRef.current = null
|
|
127
|
+
}
|
|
128
|
+
if (idleDotsIntervalRef.current) {
|
|
129
|
+
clearInterval(idleDotsIntervalRef.current)
|
|
130
|
+
idleDotsIntervalRef.current = null
|
|
131
|
+
}
|
|
132
|
+
setAnimationState((prev) => ({
|
|
133
|
+
...prev,
|
|
134
|
+
showIdlePulsating: false,
|
|
135
|
+
idleDotsCount: 0,
|
|
136
|
+
}))
|
|
137
|
+
}, [])
|
|
138
|
+
|
|
139
|
+
const triggerFadeTransition = useCallback(() => {
|
|
140
|
+
setAnimationState((prev) => ({
|
|
141
|
+
...prev,
|
|
142
|
+
showLabels: false,
|
|
143
|
+
showMainText: false,
|
|
144
|
+
}))
|
|
145
|
+
|
|
146
|
+
if (fadeTimeoutRef.current) {
|
|
147
|
+
clearTimeout(fadeTimeoutRef.current)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
fadeTimeoutRef.current = setTimeout(() => {
|
|
151
|
+
setAnimationState((prev) => ({
|
|
152
|
+
...prev,
|
|
153
|
+
showLabels: true,
|
|
154
|
+
showMainText: true,
|
|
155
|
+
}))
|
|
156
|
+
}, 200)
|
|
157
|
+
}, [])
|
|
158
|
+
|
|
159
|
+
const setInitialAnimationState = useCallback(() => {
|
|
160
|
+
setAnimationState((prev) => ({
|
|
161
|
+
...prev,
|
|
162
|
+
showLabels: true,
|
|
163
|
+
showMainText: true,
|
|
164
|
+
}))
|
|
165
|
+
}, [])
|
|
166
|
+
|
|
167
|
+
// Cleanup function
|
|
168
|
+
const cleanup = useCallback(() => {
|
|
169
|
+
if (pauseAnimationTimeoutRef.current) {
|
|
170
|
+
clearTimeout(pauseAnimationTimeoutRef.current)
|
|
171
|
+
}
|
|
172
|
+
if (errorAnimationTimeoutRef.current) {
|
|
173
|
+
clearTimeout(errorAnimationTimeoutRef.current)
|
|
174
|
+
}
|
|
175
|
+
if (fadeTimeoutRef.current) {
|
|
176
|
+
clearTimeout(fadeTimeoutRef.current)
|
|
177
|
+
}
|
|
178
|
+
if (pulsatingIntervalRef.current) {
|
|
179
|
+
clearInterval(pulsatingIntervalRef.current)
|
|
180
|
+
}
|
|
181
|
+
if (idlePulsatingIntervalRef.current) {
|
|
182
|
+
clearInterval(idlePulsatingIntervalRef.current)
|
|
183
|
+
}
|
|
184
|
+
if (idleDotsIntervalRef.current) {
|
|
185
|
+
clearInterval(idleDotsIntervalRef.current)
|
|
186
|
+
}
|
|
187
|
+
}, [])
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
animationState,
|
|
191
|
+
triggerPauseAnimation,
|
|
192
|
+
triggerErrorAnimation,
|
|
193
|
+
clearErrorAnimation,
|
|
194
|
+
startPulsatingAnimation,
|
|
195
|
+
stopPulsatingAnimation,
|
|
196
|
+
startIdleAnimations,
|
|
197
|
+
stopIdleAnimations,
|
|
198
|
+
triggerFadeTransition,
|
|
199
|
+
setInitialAnimationState,
|
|
200
|
+
cleanup,
|
|
201
|
+
}
|
|
202
|
+
}
|