Skip to content

Commit 74746f7

Browse files
authored
Merge pull request #425 from bichikim/dev
Dev
2 parents 9934d4c + 2d50891 commit 74746f7

File tree

13 files changed

+235
-79
lines changed

13 files changed

+235
-79
lines changed

apps/bplan-client/src/components/midi-player/SFileItem.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,22 @@ export const SFileItem = (props: SFileItemProps) => {
112112
innerProps.onSelect?.(innerProps.id)
113113
}
114114

115+
const handleFocusEnter = (event: KeyboardEvent) => {
116+
if (event.key !== 'Enter') {
117+
return
118+
}
119+
120+
if (event.target !== document.activeElement) {
121+
return
122+
}
123+
124+
if (innerProps.selected) {
125+
handlePlayOrSuspend()
126+
} else {
127+
handleSelect()
128+
}
129+
}
130+
115131
const progress = createMemo(
116132
() => ((innerProps.playedTime ?? 0) / (innerProps.totalDuration ?? 1)) * HUNDRED,
117133
)
@@ -158,6 +174,7 @@ export const SFileItem = (props: SFileItemProps) => {
158174
>
159175
<DragButton.Body
160176
{...restProps}
177+
onKeyDown={handleFocusEnter}
161178
class={cx(rootStyle, restProps.class)}
162179
title={innerProps.name}
163180
>

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"storybook:https": "storybook dev --https --ssl-cert .cert/localhost.crt --ssl-key .cert/localhost.key -p 5555",
3232
"test": "vitest run",
3333
"test:storybook": "test-storybook",
34+
"test:storybook:watch": "test-storybook --watch",
3435
"test:vitest": "vitest run",
3536
"test:vitest:watch": "vitest watch"
3637
},

packages/solid-components/src/button/Button.story.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const meta = {
3131
type: 'button',
3232
},
3333
component: Template,
34-
title: 'Solid/Components/Button',
34+
title: 'Solid/Components/button/Button',
3535
} satisfies Meta<typeof Template>
3636

3737
export default meta

packages/solid-components/src/button/ButtonBody.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {ButtonContext} from './context'
22
import {Dynamic} from 'solid-js/web'
3-
import {ComponentProps, useContext} from 'solid-js'
3+
import {ComponentProps, createSignal, useContext} from 'solid-js'
4+
import _ from 'lodash'
45

56
export interface ButtonBodyProps
67
extends Omit<
@@ -11,17 +12,15 @@ export interface ButtonBodyProps
1112
}
1213

1314
export const ButtonBody = (props: ButtonBodyProps) => {
14-
const [
15-
buttonContextValue,
16-
{handleClick, handleDoubleClick, handleTouchEnd, handleTouchStart},
17-
] = useContext(ButtonContext)
15+
const [buttonContextValue, {handleClick, handleTouchEnd, handleTouchStart}] =
16+
useContext(ButtonContext)
1817

1918
return (
2019
<Dynamic
2120
{...props}
2221
component={buttonContextValue().tag}
2322
onClick={handleClick}
24-
onDblClick={handleDoubleClick}
23+
onDblClick={undefined}
2524
onTouchEnd={handleTouchEnd}
2625
onTouchStart={handleTouchStart}
2726
href={buttonContextValue().href}

packages/solid-components/src/button/ButtonProvider.tsx

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface ButtonProviderProps extends ParentProps {
1010
href?: string
1111
onClick?: JSX.EventHandler<HTMLButtonElement, MouseEvent | TouchEvent>
1212
onDoubleClick?: JSX.EventHandler<HTMLButtonElement, MouseEvent | TouchEvent>
13+
onFocusEnter?: (event: KeyboardEvent) => void
1314
onTouchEnd?: JSX.EventHandler<HTMLButtonElement, TouchEvent>
1415
onTouchStart?: JSX.EventHandler<HTMLButtonElement, TouchEvent>
1516
type?: ButtonType
@@ -24,6 +25,7 @@ export const ButtonProvider = (props: ButtonProviderProps) => {
2425

2526
const defaultProps = mergeProps(
2627
{
28+
doubleClickGap: DEFAULT_DOUBLE_CLICK_GAP,
2729
type: 'button',
2830
},
2931
props,
@@ -41,22 +43,34 @@ export const ButtonProvider = (props: ButtonProviderProps) => {
4143
return
4244
}
4345

46+
const _doubleClickGap = defaultProps.doubleClickGap
47+
const newClickTime = now()
48+
49+
if (newClickTime - clickTime < _doubleClickGap) {
50+
defaultProps.onDoubleClick?.(event)
51+
52+
return
53+
}
54+
55+
clickTime = newClickTime
4456
defaultProps.onClick?.(event)
4557
}
4658

4759
/**
4860
* Handles the `doubleClick` event for the button component and forwards it to the parent component.
4961
* @param event The mouse event triggered by user interaction.
5062
*/
51-
const handleDoubleClick: ButtonProviderProps['onDoubleClick'] = (event) => {
52-
// skip anchor event because it will navigate to the href
53-
if (defaultProps.type === 'anchor') {
54-
return
55-
}
63+
// const handleDoubleClick: ButtonProviderProps['onDoubleClick'] = (event) => {
64+
// console.log('handleDoubleClick', event)
5665

57-
// pass original event to parent
58-
defaultProps.onDoubleClick?.(event)
59-
}
66+
// // skip anchor event because it will navigate to the href
67+
// if (defaultProps.type === 'anchor') {
68+
// //
69+
// }
70+
71+
// // pass original event to parent
72+
// // defaultProps.onDoubleClick?.(event)
73+
// }
6074

6175
const handleTouchStart: ButtonProviderProps['onTouchStart'] = (event) => {
6276
touchdown = true
@@ -78,20 +92,20 @@ export const ButtonProvider = (props: ButtonProviderProps) => {
7892
return
7993
}
8094

81-
const doubleClickGap = defaultProps.doubleClickGap ?? DEFAULT_DOUBLE_CLICK_GAP
95+
const _doubleClickGap = defaultProps.doubleClickGap
8296
const newClickTime = now()
8397

8498
if (touchdown) {
8599
defaultProps.onClick?.(event)
86-
touchdown = false
87100
}
88101

89-
if (newClickTime - clickTime < doubleClickGap) {
90-
handleDoubleClick(event)
102+
if (touchdown && newClickTime - clickTime < _doubleClickGap) {
103+
defaultProps.onDoubleClick?.(event)
91104

92105
return
93106
}
94107

108+
touchdown = false
95109
clickTime = newClickTime
96110
}
97111

@@ -129,10 +143,7 @@ export const ButtonProvider = (props: ButtonProviderProps) => {
129143

130144
return (
131145
<ButtonContext.Provider
132-
value={[
133-
buttonContextValue,
134-
{handleClick, handleDoubleClick, handleTouchEnd, handleTouchStart},
135-
]}
146+
value={[buttonContextValue, {handleClick, handleTouchEnd, handleTouchStart}]}
136147
>
137148
{props.children}
138149
</ButtonContext.Provider>

packages/solid-components/src/button/HButton.story.tsx

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {HButton} from './'
22
import {Meta, StoryObj} from 'storybook-solidjs'
3-
import {fn} from '@storybook/test'
3+
import {expect, fireEvent, fn, within} from '@storybook/test'
44

55
const meta = {
66
argTypes: {
@@ -27,7 +27,13 @@ const meta = {
2727
},
2828
},
2929
},
30-
args: {onClick: fn(), onDoubleClick: fn()},
30+
args: {
31+
children: 'Click me',
32+
onClick: fn(),
33+
onDoubleClick: fn(),
34+
onTouchEnd: fn(),
35+
onTouchStart: fn(),
36+
},
3137
component: HButton,
3238
title: 'Solid/Components/Button/HButton',
3339
} satisfies Meta<typeof HButton>
@@ -36,6 +42,65 @@ export default meta
3642

3743
type Story = StoryObj<typeof meta>
3844

39-
export const Default: Story = {
40-
render: (args) => <HButton {...args}>Click me</HButton>,
45+
export const Default: Story = {}
46+
47+
export const Click: Story = {
48+
play: async ({canvasElement, args}) => {
49+
const canvas = within(canvasElement)
50+
const button = canvas.getByRole('button', {name: 'Click me'})
51+
52+
await fireEvent.click(button)
53+
expect(args.onClick).toHaveBeenCalledTimes(1)
54+
},
55+
}
56+
57+
export const TouchStart: Story = {
58+
play: async ({canvasElement, args}) => {
59+
const canvas = within(canvasElement)
60+
const button = canvas.getByRole('button', {name: 'Click me'})
61+
62+
await fireEvent.touchStart(button)
63+
expect(args.onTouchStart).toHaveBeenCalledTimes(1)
64+
},
65+
}
66+
67+
export const TouchEnd: Story = {
68+
play: async ({canvasElement, args}) => {
69+
const canvas = within(canvasElement)
70+
const button = canvas.getByRole('button', {name: 'Click me'})
71+
72+
await fireEvent.touchEnd(button)
73+
expect(args.onTouchEnd).toHaveBeenCalledTimes(1)
74+
},
75+
}
76+
77+
export const DoubleClick: Story = {
78+
play: async ({canvasElement, args}) => {
79+
const canvas = within(canvasElement)
80+
const button = canvas.getByRole('button', {name: 'Click me'})
81+
82+
// first click
83+
await fireEvent.click(button)
84+
// double click
85+
await fireEvent.click(button)
86+
// check double click event
87+
expect(args.onDoubleClick).toHaveBeenCalledTimes(1)
88+
},
89+
}
90+
91+
export const DoubleClickWithTouch: Story = {
92+
play: async ({canvasElement, args}) => {
93+
const canvas = within(canvasElement)
94+
const button = canvas.getByRole('button', {name: 'Click me'})
95+
96+
// first touch start and touch end
97+
// 첫 번째 터치 이벤트 (touchstart)
98+
await fireEvent.touchStart(button)
99+
await fireEvent.touchEnd(button)
100+
// double click
101+
await fireEvent.touchStart(button)
102+
await fireEvent.touchEnd(button)
103+
// check double click event
104+
expect(args.onDoubleClick).toHaveBeenCalledTimes(1)
105+
},
41106
}

packages/solid-components/src/button/context.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ export interface ButtonContextProps {
1010

1111
export interface ButtonContextActions {
1212
handleClick: JSX.EventHandler<HTMLButtonElement, MouseEvent | TouchEvent>
13-
handleDoubleClick: JSX.EventHandler<HTMLButtonElement, MouseEvent | TouchEvent>
1413
handleTouchEnd: JSX.EventHandler<HTMLButtonElement, TouchEvent>
1514
handleTouchStart: JSX.EventHandler<HTMLButtonElement, TouchEvent>
1615
}
@@ -23,9 +22,6 @@ export const ButtonContext = createContext<
2322
handleClick: () => {
2423
throw new Error('not implemented')
2524
},
26-
handleDoubleClick: () => {
27-
throw new Error('not implemented')
28-
},
2925
handleTouchEnd: () => {
3026
throw new Error('not implemented')
3127
},

packages/solid-components/src/drag-button/DragButtonBody.tsx

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1+
import {createMemo, useContext} from 'solid-js'
12
import {Button, ButtonBodyProps} from '../button'
23
import {DragButtonContext} from './context'
3-
import {createMemo, useContext} from 'solid-js'
44

55
export interface DragButtonBodyProps extends ButtonBodyProps {
66
//
77
}
88

99
export const DragButtonBody = (props: DragButtonBodyProps) => {
10-
const [dragContext, {handleMouseDown, handleMouseMove, handleTouchMove}] =
11-
useContext(DragButtonContext)
10+
const [dragContext, {handleMouseDown}] = useContext(DragButtonContext)
1211

1312
const style = createMemo(() => {
1413
const {dragX} = dragContext()
@@ -21,13 +20,7 @@ export const DragButtonBody = (props: DragButtonBodyProps) => {
2120
})
2221

2322
return (
24-
<Button.Body
25-
{...props}
26-
onMouseDown={handleMouseDown}
27-
onMouseMove={handleMouseMove}
28-
onTouchMove={handleTouchMove}
29-
style={style()}
30-
>
23+
<Button.Body {...props} onMouseDown={handleMouseDown} style={style()}>
3124
{props.children}
3225
</Button.Body>
3326
)

packages/solid-components/src/drag-button/DragButtonProvider.tsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {Button, ButtonProviderProps} from '../button'
22
import {createMemo, mergeProps, splitProps} from 'solid-js'
33
import {Position} from '@winter-love/utils'
44
import {DragButtonContext, DragButtonContextProps} from './context'
5-
import {useDrag} from '../use/drag'
5+
import {useDrag} from './drag'
66

77
export interface DragButtonProviderProps extends Omit<ButtonProviderProps, 'onClick'> {
88
allowBottom?: boolean
@@ -84,10 +84,7 @@ export const DragButtonProvider = (props: DragButtonProviderProps) => {
8484
}
8585
}
8686

87-
const [
88-
dragPosition,
89-
{handleMouseDown, handleMouseMove, handleTouchEnd, handleTouchMove, handleTouchStart},
90-
] = useDrag(() => ({
87+
const [dragPosition, {handleMouseDown, handleTouchStart}] = useDrag(() => ({
9188
clickAllowMoveSize: innerProps.clickAllowMoveSize,
9289
dragEndSize: innerProps.dragEndSize,
9390
dragExecuteSize: innerProps.dragExecuteSize,
@@ -131,18 +128,11 @@ export const DragButtonProvider = (props: DragButtonProviderProps) => {
131128
contextValue,
132129
{
133130
handleMouseDown,
134-
handleMouseMove,
135-
handleTouchEnd,
136-
handleTouchMove,
137131
handleTouchStart,
138132
},
139133
]}
140134
>
141-
<Button.Provider
142-
{...restProps}
143-
onTouchEnd={handleTouchEnd}
144-
onTouchStart={handleTouchStart}
145-
>
135+
<Button.Provider {...restProps} onTouchStart={handleTouchStart}>
146136
{props.children}
147137
</Button.Provider>
148138
</DragButtonContext.Provider>

0 commit comments

Comments
 (0)