Skip to content

Commit

Permalink
Merge pull request #493 from kitsuyui/refactor-bulma-stopwatch-and-timer
Browse files Browse the repository at this point in the history
Refactor: style-bulma timer and stopwatch components
  • Loading branch information
kitsuyui authored Jul 12, 2024
2 parents 4d4f39c + e316bc0 commit a17b037
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 79 deletions.
110 changes: 110 additions & 0 deletions packages/style-bulma/src/__snapshots__/test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Stopwatch render Stopwatch 1`] = `
<DocumentFragment>
<div
class="card"
>
<div
class="card-content"
>
<p
class="title is-family-monospace has-text-centered"
>
00:00:00.000
</p>
</div>
<footer
class="card-footer"
>
<button
class="card-footer-item is-clickable is-button"
disabled=""
type="button"
>
Reset
</button>
<button
class="card-footer-item is-clickable is-button"
type="button"
>
Start
</button>
</footer>
</div>
</DocumentFragment>
`;

exports[`Timer render Timer 1`] = `
<DocumentFragment>
<div
class="card"
>
<div
class="card-content"
>
<p
class="title is-family-monospace has-text-centered"
>
00:00:00.000
</p>
</div>
<footer
class="card-footer"
>
<span
class="card-footer-item"
>
<button
class="is-button"
type="button"
>
+1h
</button>
</span>
<span
class="card-footer-item"
>
<button
class="is-button"
type="button"
>
+1m
</button>
</span>
<span
class="card-footer-item"
>
<button
class="is-button"
type="button"
>
+1s
</button>
</span>
<span
class="card-footer-item"
>
<button
class="is-button"
disabled=""
type="button"
>
Reset
</button>
</span>
<span
class="card-footer-item"
>
<button
class="is-button"
disabled=""
type="button"
>
Start
</button>
</span>
</footer>
</div>
</DocumentFragment>
`;
1 change: 0 additions & 1 deletion packages/style-bulma/src/clock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import 'bulma/css/bulma.css'

const ClockElement = (props: ClockProps) => {
const { date, timezone } = props

const time = date.toLocaleTimeString('ja-JP', {
timeZone: timezone,
hour12: false,
Expand Down
67 changes: 41 additions & 26 deletions packages/style-bulma/src/stopwatch.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
StopwatchContainer,
StopwatchContext,
utils,
} from '@kitsuyui/react-stopwatch'
import React from 'react'
import React, { useCallback } from 'react'
import { timeLabelString } from './timeLabelString'

import 'bulma/css/bulma.css'

Expand All @@ -14,42 +14,57 @@ interface StopwatchProps {
toggle: () => void
}

export const Stopwatch = () => {
return (
<StopwatchContainer>
<StopwatchContext.Consumer>
{(stopwatch: StopwatchProps) => <StopwatchElement {...stopwatch} />}
</StopwatchContext.Consumer>
</StopwatchContainer>
)
}

export const StopwatchElement = (props: StopwatchProps) => {
const { running, elapsedTime, reset, toggle } = props
const minutes = Math.floor(elapsedTime / 60)
const seconds = (elapsedTime % 60) | 0
const milliseconds = ((elapsedTime % 1) * 1000) | 0
const elapsedTimeStr = `${utils.zeroPad2(minutes)}:${utils.zeroPad2(
seconds
)}.${utils.zeroPad3(milliseconds)}`
const timeLabel = timeLabelString(elapsedTime)
return (
<div className="card">
<div className="card-content">
<p className="title is-family-monospace">{elapsedTimeStr}</p>
<p className="title is-family-monospace has-text-centered">{timeLabel}</p>
</div>
<footer className="card-footer">
{/* biome-ignore lint/a11y/useKeyWithClickEvents: FIXME: TODO: temporary ignore for migration */}
<span
className={`card-footer-item ${running ? 'is-clickable' : 'disable'}`}
onClick={reset}
>
Reset
</span>
{/* biome-ignore lint/a11y/useKeyWithClickEvents: FIXME: TODO: temporary ignore for migration */}
<span className="card-footer-item is-clickable" onClick={toggle}>
{running ? 'Stop' : 'Start'}
</span>
<ResetButton onClick={reset} remaining={elapsedTime} />
<StartStopButton running={running} toggle={toggle} />
</footer>
</div>
)
}

export const Stopwatch = () => {
const ResetButton = (props: { onClick: () => void, remaining: number }) => {
const { onClick, remaining } = props
const disabled = remaining === 0
return (
<StopwatchContainer>
<StopwatchContext.Consumer>
{(stopwatch: StopwatchProps) => <StopwatchElement {...stopwatch} />}
</StopwatchContext.Consumer>
</StopwatchContainer>
<FooterItemButton label="Reset" onClick={onClick} disabled={disabled} />
)
}

const StartStopButton = (props: { running: boolean, toggle: () => void }) => {
const { running, toggle } = props
const label = running ? 'Stop' : 'Start'
return (
<FooterItemButton label={label} onClick={toggle} disabled={false} />
)
}

const FooterItemButton = (props: { label: string, disabled: boolean, onClick: () => void }) => {
const { label, onClick, disabled } = props
const clickHandler = useCallback((e: React.MouseEvent<HTMLSpanElement>) => {
e.preventDefault()
onClick()
}, [onClick])
return (
<button className="card-footer-item is-clickable is-button" onClick={clickHandler} type="button" disabled={disabled}>
{label}
</button>
)
}
24 changes: 21 additions & 3 deletions packages/style-bulma/src/test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
import { render } from '@testing-library/react'
import React from 'react'

import { Clock } from '.'
import { Clock } from './clock'
import { Stopwatch } from './stopwatch'
import { Timer } from './timer'

test('render Clock', () => {
render(<Clock />)
describe('Clock', () => {
test('render Clock', () => {
render(<Clock />)
})
})

describe('Stopwatch', () => {
test('render Stopwatch', () => {
const { asFragment } = render(<Stopwatch />)
expect(asFragment()).toMatchSnapshot()
})
})

describe('Timer', () => {
test('render Timer', () => {
const { asFragment } = render(<Timer />)
expect(asFragment()).toMatchSnapshot()
})
})
12 changes: 12 additions & 0 deletions packages/style-bulma/src/timeLabelString/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const timeLabelString = (total: number): string => {
const hours = Math.floor(total / 3600)
const remaining = total - hours * 3600
const minutes = Math.floor(remaining / 60)
const seconds = (remaining % 60) | 0
const milliseconds = ((remaining % 1) * 1000) | 0
const hoursString = String(hours).padStart(2, '0')
const minutesString = String(minutes).padStart(2, '0')
const secondsString = String(seconds).padStart(2, '0')
const millisecondsString = String(milliseconds).padStart(3, '0')
return `${hoursString}:${minutesString}:${secondsString}.${millisecondsString}`
}
14 changes: 14 additions & 0 deletions packages/style-bulma/src/timeLabelString/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { timeLabelString } from ".";

describe("timeLabelString", () => {
it("should format time", () => {
expect(timeLabelString(0)).toBe("00:00:00.000");
expect(timeLabelString(1)).toBe("00:00:01.000");
expect(timeLabelString(60)).toBe("00:01:00.000");
expect(timeLabelString(61)).toBe("00:01:01.000");
expect(timeLabelString(3600)).toBe("01:00:00.000");
expect(timeLabelString(3601)).toBe("01:00:01.000");
expect(timeLabelString(3661)).toBe("01:01:01.000");
expect(timeLabelString(3661.123)).toBe("01:01:01.123");
});
});
Loading

0 comments on commit a17b037

Please sign in to comment.