Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Events: onStart, onStop, onComplete for Timer and Stopwatch #52

Merged
merged 6 commits into from
May 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions examples/simple/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ const Clock = () => {

const Timer = () => {
return (
<TimerContainer>
<TimerContainer
onStart={(e) => console.log('start', e)}
onStop={(e) => console.log('stop', e)}
onComplete={(e) => console.log('complete', e)}
onReset={(e) => console.log('reset', e)}
>
<TimerContext.Consumer>
{(timer: TimerProps) => <MinimalTimer {...timer} />}
</TimerContext.Consumer>
Expand All @@ -49,7 +54,11 @@ const Timer = () => {

const Stopwatch = () => {
return (
<StopwatchContainer>
<StopwatchContainer
onStart={(e) => console.log('start', e)}
onStop={(e) => console.log('stop', e)}
onReset={(e) => console.log('reset', e)}
>
<StopwatchContext.Consumer>
{(props: StopwatchProps) => <MinimalStopwatch {...props} />}
</StopwatchContext.Consumer>
Expand Down
9 changes: 9 additions & 0 deletions packages/stopwatch/src/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ export const StopwatchContainer: React.FunctionComponent<
StopwatchContainerProps
> = (props): JSX.Element => {
const { children } = props
const emptyFn = (_event: CustomEvent) => {
/* do nothing */
}
const onStart = props.onStart ?? emptyFn
const onStop = props.onStop ?? emptyFn
const onReset = props.onReset ?? emptyFn
const [running, setRunning] = useState(false)
const [elapsedTimeInLap, setElapsedTimeInLap] = useState(0)
const [elapsedTimeTotal, setElapsedTimeTotal] = useState(0)
Expand All @@ -61,6 +67,7 @@ export const StopwatchContainer: React.FunctionComponent<
if (running) {
return
}
onStart(new CustomEvent('start', {}))
setStartTime(new Date())
setRunning(true)
}
Expand All @@ -69,6 +76,7 @@ export const StopwatchContainer: React.FunctionComponent<
if (!running) {
return
}
onStop(new CustomEvent('stop', {}))
updateElapsedTime()
setRunning(false)
moveLapToTotal()
Expand All @@ -86,6 +94,7 @@ export const StopwatchContainer: React.FunctionComponent<
if (running) {
stop()
}
onReset(new CustomEvent('reset', {}))
setElapsedTimeInLap(0)
setElapsedTimeTotal(0)
}
Expand Down
3 changes: 3 additions & 0 deletions packages/stopwatch/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ export type StopwatchProps = StopwatchValue & StopwatchActions
export interface StopwatchContainerProps {
refreshInterval?: number
children: React.ReactElement | React.ReactElement[]
onStart?(event: CustomEvent): void
onStop?(event: CustomEvent): void
onReset?(event: CustomEvent): void
}
31 changes: 30 additions & 1 deletion packages/timer/src/container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,35 @@ export const TimerContainer: React.FunctionComponent<TimerContainerProps> = (
props
): JSX.Element => {
const { children } = props
const emptyFn = (_event: CustomEvent) => {
/* do nothing */
}
const onStart = props.onStart ?? emptyFn
const onStop = props.onStop ?? emptyFn
const onComplete = props.onComplete ?? emptyFn
const onReset = props.onReset ?? emptyFn
const [running, setRunning] = useState(false)
const [targetDate, setTargetDate] = useState(new Date())
const [remaining, setRemaining] = useState(0)

const refreshInterval = props.refreshInterval || 10 // default 10ms

useInterval(() => {
tick()
}, refreshInterval)

function tick() {
// It can't be ticked if it is not running.
if (running) {
const remaining = calcRemaining(targetDate)
setRemaining(remaining)
if (remaining <= 0) {
setRemaining(0)
setRunning(false)
onComplete(new CustomEvent('complete', {}))
}
}
}, refreshInterval)
}

function toggle() {
if (running) {
Expand All @@ -63,19 +76,35 @@ export const TimerContainer: React.FunctionComponent<TimerContainerProps> = (
}

function reset() {
// First, stop the timer if it is running.
if (running) {
stop()
}
setRemaining(0)
onReset(new CustomEvent('reset', {}))
}

function start() {
// It can't be started if the remaining time is 0.
if (remaining <= 0) {
return
}
// It can't be started if it is already running.
if (running) {
return
}
setTargetDate(new Date(Date.now() + remaining * 1000))
setRunning(true)
onStart(new CustomEvent('start', {}))
}

function stop() {
// It can't be stopped if it is not running.
if (!running) {
return
}
setRunning(false)
onStop(new CustomEvent('stop', {}))
}

return (
Expand Down
4 changes: 4 additions & 0 deletions packages/timer/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ export type TimerProps = TimerValue & TimerActions
export interface TimerContainerProps {
refreshInterval?: number
children: React.ReactElement | React.ReactElement[]
onStart?(event: CustomEvent): void
onStop?(event: CustomEvent): void
onComplete?(event: CustomEvent): void
onReset?(event: CustomEvent): void
}