@gm-pc/keyboard 1.25.0-beta.0 → 1.25.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/package.json +4 -4
- package/src/cell/auto_complete.tsx +79 -79
- package/src/cell/cell.tsx +27 -27
- package/src/cell/date_picker.tsx +73 -73
- package/src/cell/input.tsx +75 -75
- package/src/cell/input_number.tsx +92 -92
- package/src/cell/level_select.tsx +70 -70
- package/src/cell/more_select.tsx +83 -83
- package/src/cell/select.tsx +70 -70
- package/src/cell/table_select.tsx +70 -70
- package/src/core/cell.tsx +96 -96
- package/src/core/wrap.tsx +253 -253
- package/src/hoc/keyboard_table_x.tsx +121 -121
- package/src/index.ts +22 -22
- package/src/stories.tsx +308 -308
- package/src/types.ts +87 -87
- package/src/utils/constant.ts +21 -21
- package/src/utils/context.ts +4 -4
- package/src/utils/do_focus.ts +14 -14
- package/src/utils/get_column_key.ts +11 -11
- package/src/utils/get_key.ts +8 -8
- package/src/utils/index.ts +8 -8
- package/src/utils/is_input_un_boundary.ts +29 -29
- package/src/utils/scroll_into_view_fixed_width.ts +71 -71
- package/src/utils/use_context_data.ts +12 -12
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
import React, { useRef, KeyboardEvent } from 'react'
|
|
2
|
-
import { MoreSelect, TableSelect, TableSelectProps } from '@gm-pc/react'
|
|
3
|
-
import { findDOMNode } from 'react-dom'
|
|
4
|
-
|
|
5
|
-
import KeyboardCell from '../core/cell'
|
|
6
|
-
import { isInputUnBoundary, scrollIntoViewFixedWidth, useContextData } from '../utils'
|
|
7
|
-
import { KeyboardWrapData } from '../types'
|
|
8
|
-
|
|
9
|
-
function KCTableSelect<V = any>({ disabled, onKeyDown, ...rest }: TableSelectProps<V>) {
|
|
10
|
-
const cellRef = useRef<KeyboardCell>(null)
|
|
11
|
-
const targetRef = useRef<MoreSelect>(null)
|
|
12
|
-
const { wrapData, cellKey } = useContextData()
|
|
13
|
-
|
|
14
|
-
const handleScroll = (fixedWidths: KeyboardWrapData['fixedWidths']) => {
|
|
15
|
-
scrollIntoViewFixedWidth(findDOMNode(targetRef.current!) as HTMLElement, fixedWidths)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const handleFocus = () => {
|
|
19
|
-
// eslint-disable-next-line
|
|
20
|
-
targetRef.current?.apiDoFocus()
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const handleKeyDown = (event: KeyboardEvent<HTMLElement>) => {
|
|
24
|
-
onKeyDown && onKeyDown(event)
|
|
25
|
-
if (isInputUnBoundary(event)) return
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
event.key === 'ArrowUp' ||
|
|
29
|
-
event.key === 'ArrowDown' ||
|
|
30
|
-
event.key === 'ArrowLeft' ||
|
|
31
|
-
event.key === 'ArrowRight'
|
|
32
|
-
) {
|
|
33
|
-
event.preventDefault()
|
|
34
|
-
// eslint-disable-next-line
|
|
35
|
-
cellRef.current?.apiDoDirectionByEventKey(event.key)
|
|
36
|
-
} else if (event.key === 'Tab') {
|
|
37
|
-
event.preventDefault()
|
|
38
|
-
// eslint-disable-next-line
|
|
39
|
-
cellRef.current?.apiDoTab()
|
|
40
|
-
} else if (event.key === 'Enter') {
|
|
41
|
-
event.preventDefault()
|
|
42
|
-
// @ts-ignore
|
|
43
|
-
targetRef.current.apiDoSelectWillActive()
|
|
44
|
-
// eslint-disable-next-line
|
|
45
|
-
cellRef.current?.apiDoEnter()
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<KeyboardCell
|
|
51
|
-
disabled={disabled}
|
|
52
|
-
ref={cellRef}
|
|
53
|
-
wrapData={wrapData}
|
|
54
|
-
cellKey={cellKey}
|
|
55
|
-
onFocus={handleFocus}
|
|
56
|
-
onScroll={handleScroll}
|
|
57
|
-
>
|
|
58
|
-
<TableSelect
|
|
59
|
-
{...(rest as any)}
|
|
60
|
-
ref={targetRef}
|
|
61
|
-
popoverType='realFocus'
|
|
62
|
-
onKeyDown={handleKeyDown}
|
|
63
|
-
isKeyboard
|
|
64
|
-
disabled={disabled}
|
|
65
|
-
/>
|
|
66
|
-
</KeyboardCell>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export default KCTableSelect
|
|
1
|
+
import React, { useRef, KeyboardEvent } from 'react'
|
|
2
|
+
import { MoreSelect, TableSelect, TableSelectProps } from '@gm-pc/react'
|
|
3
|
+
import { findDOMNode } from 'react-dom'
|
|
4
|
+
|
|
5
|
+
import KeyboardCell from '../core/cell'
|
|
6
|
+
import { isInputUnBoundary, scrollIntoViewFixedWidth, useContextData } from '../utils'
|
|
7
|
+
import { KeyboardWrapData } from '../types'
|
|
8
|
+
|
|
9
|
+
function KCTableSelect<V = any>({ disabled, onKeyDown, ...rest }: TableSelectProps<V>) {
|
|
10
|
+
const cellRef = useRef<KeyboardCell>(null)
|
|
11
|
+
const targetRef = useRef<MoreSelect>(null)
|
|
12
|
+
const { wrapData, cellKey } = useContextData()
|
|
13
|
+
|
|
14
|
+
const handleScroll = (fixedWidths: KeyboardWrapData['fixedWidths']) => {
|
|
15
|
+
scrollIntoViewFixedWidth(findDOMNode(targetRef.current!) as HTMLElement, fixedWidths)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const handleFocus = () => {
|
|
19
|
+
// eslint-disable-next-line
|
|
20
|
+
targetRef.current?.apiDoFocus()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const handleKeyDown = (event: KeyboardEvent<HTMLElement>) => {
|
|
24
|
+
onKeyDown && onKeyDown(event)
|
|
25
|
+
if (isInputUnBoundary(event)) return
|
|
26
|
+
|
|
27
|
+
if (
|
|
28
|
+
event.key === 'ArrowUp' ||
|
|
29
|
+
event.key === 'ArrowDown' ||
|
|
30
|
+
event.key === 'ArrowLeft' ||
|
|
31
|
+
event.key === 'ArrowRight'
|
|
32
|
+
) {
|
|
33
|
+
event.preventDefault()
|
|
34
|
+
// eslint-disable-next-line
|
|
35
|
+
cellRef.current?.apiDoDirectionByEventKey(event.key)
|
|
36
|
+
} else if (event.key === 'Tab') {
|
|
37
|
+
event.preventDefault()
|
|
38
|
+
// eslint-disable-next-line
|
|
39
|
+
cellRef.current?.apiDoTab()
|
|
40
|
+
} else if (event.key === 'Enter') {
|
|
41
|
+
event.preventDefault()
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
targetRef.current.apiDoSelectWillActive()
|
|
44
|
+
// eslint-disable-next-line
|
|
45
|
+
cellRef.current?.apiDoEnter()
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<KeyboardCell
|
|
51
|
+
disabled={disabled}
|
|
52
|
+
ref={cellRef}
|
|
53
|
+
wrapData={wrapData}
|
|
54
|
+
cellKey={cellKey}
|
|
55
|
+
onFocus={handleFocus}
|
|
56
|
+
onScroll={handleScroll}
|
|
57
|
+
>
|
|
58
|
+
<TableSelect
|
|
59
|
+
{...(rest as any)}
|
|
60
|
+
ref={targetRef}
|
|
61
|
+
popoverType='realFocus'
|
|
62
|
+
onKeyDown={handleKeyDown}
|
|
63
|
+
isKeyboard
|
|
64
|
+
disabled={disabled}
|
|
65
|
+
/>
|
|
66
|
+
</KeyboardCell>
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export default KCTableSelect
|
package/src/core/cell.tsx
CHANGED
|
@@ -1,96 +1,96 @@
|
|
|
1
|
-
import { cloneElement, Component, ReactElement } from 'react'
|
|
2
|
-
import {
|
|
3
|
-
KEYBOARD_DIRECTION,
|
|
4
|
-
KEYBOARD_ENTER,
|
|
5
|
-
KEYBOARD_ONFOCUS,
|
|
6
|
-
KEYBOARD_TAB,
|
|
7
|
-
} from '../utils'
|
|
8
|
-
import { KeyboardCustomEvent, KeyboardDirection, KeyboardCellProps } from '../types'
|
|
9
|
-
|
|
10
|
-
// 缓存起来,方便 Cell 不可用时把命令传给下一个响应者
|
|
11
|
-
const dispatchCache: {
|
|
12
|
-
[id: string]: { eventName: string; detail?: Partial<KeyboardCustomEvent> }
|
|
13
|
-
} = {}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Cell 和 Wrap 配合使用,使单元格具有响应键盘能力
|
|
17
|
-
*
|
|
18
|
-
* 使用:
|
|
19
|
-
* - 实现 onFocus
|
|
20
|
-
* - 监听 keydown,并根据自身需要处理 keydown 事件,每个组件都会不太一样
|
|
21
|
-
* - 把动作 方向、Tab、Enter 通过 Cell 提供的方法 refCell.current.apiDoXXX 反馈给 Cell。具体方法见代码
|
|
22
|
-
*/
|
|
23
|
-
class KeyboardCell extends Component<KeyboardCellProps> {
|
|
24
|
-
apiDoDirection = (direction: KeyboardDirection) => {
|
|
25
|
-
this._dispatch(KEYBOARD_DIRECTION, { direction })
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
apiDoDirectionByEventKey = (eventKey: string) => {
|
|
29
|
-
this.apiDoDirection(eventKey.slice(5).toLowerCase() as KeyboardDirection)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
apiDoTab = () => {
|
|
33
|
-
this._dispatch(KEYBOARD_TAB)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
apiDoEnter = () => {
|
|
37
|
-
this._dispatch(KEYBOARD_ENTER)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
private _dispatch = (eventName: string, detail?: Partial<KeyboardCustomEvent>) => {
|
|
41
|
-
const { wrapData, cellKey } = this.props
|
|
42
|
-
dispatchCache[wrapData.id] = {
|
|
43
|
-
eventName,
|
|
44
|
-
detail,
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
window.dispatchEvent(
|
|
48
|
-
new CustomEvent(`${eventName}${wrapData.id}`, { detail: { ...detail, cellKey } })
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private _handleFocus = (event: CustomEvent<KeyboardCustomEvent>) => {
|
|
53
|
-
const { wrapData, onFocus, onScroll, cellKey, disabled } = this.props
|
|
54
|
-
|
|
55
|
-
if (event.detail.cellKey !== cellKey) {
|
|
56
|
-
return
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (!disabled) {
|
|
60
|
-
onFocus()
|
|
61
|
-
onScroll(wrapData.fixedWidths)
|
|
62
|
-
}
|
|
63
|
-
// 不可响应,则抛给下一个响应者
|
|
64
|
-
else {
|
|
65
|
-
this._dispatch(
|
|
66
|
-
dispatchCache[wrapData.id].eventName,
|
|
67
|
-
dispatchCache[wrapData.id].detail
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
componentDidMount() {
|
|
73
|
-
const { wrapData } = this.props
|
|
74
|
-
window.addEventListener(
|
|
75
|
-
`${KEYBOARD_ONFOCUS}${wrapData.id}`,
|
|
76
|
-
(this._handleFocus as any) as EventListener
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
componentWillUnmount() {
|
|
81
|
-
const { wrapData } = this.props
|
|
82
|
-
window.removeEventListener(
|
|
83
|
-
`${KEYBOARD_ONFOCUS}${wrapData.id}`,
|
|
84
|
-
(this._handleFocus as any) as EventListener
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
render() {
|
|
89
|
-
const { children, cellKey } = this.props
|
|
90
|
-
return cloneElement(children as ReactElement, {
|
|
91
|
-
'data-cell-key': cellKey,
|
|
92
|
-
})
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export default KeyboardCell
|
|
1
|
+
import { cloneElement, Component, ReactElement } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
KEYBOARD_DIRECTION,
|
|
4
|
+
KEYBOARD_ENTER,
|
|
5
|
+
KEYBOARD_ONFOCUS,
|
|
6
|
+
KEYBOARD_TAB,
|
|
7
|
+
} from '../utils'
|
|
8
|
+
import { KeyboardCustomEvent, KeyboardDirection, KeyboardCellProps } from '../types'
|
|
9
|
+
|
|
10
|
+
// 缓存起来,方便 Cell 不可用时把命令传给下一个响应者
|
|
11
|
+
const dispatchCache: {
|
|
12
|
+
[id: string]: { eventName: string; detail?: Partial<KeyboardCustomEvent> }
|
|
13
|
+
} = {}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Cell 和 Wrap 配合使用,使单元格具有响应键盘能力
|
|
17
|
+
*
|
|
18
|
+
* 使用:
|
|
19
|
+
* - 实现 onFocus
|
|
20
|
+
* - 监听 keydown,并根据自身需要处理 keydown 事件,每个组件都会不太一样
|
|
21
|
+
* - 把动作 方向、Tab、Enter 通过 Cell 提供的方法 refCell.current.apiDoXXX 反馈给 Cell。具体方法见代码
|
|
22
|
+
*/
|
|
23
|
+
class KeyboardCell extends Component<KeyboardCellProps> {
|
|
24
|
+
apiDoDirection = (direction: KeyboardDirection) => {
|
|
25
|
+
this._dispatch(KEYBOARD_DIRECTION, { direction })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
apiDoDirectionByEventKey = (eventKey: string) => {
|
|
29
|
+
this.apiDoDirection(eventKey.slice(5).toLowerCase() as KeyboardDirection)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
apiDoTab = () => {
|
|
33
|
+
this._dispatch(KEYBOARD_TAB)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
apiDoEnter = () => {
|
|
37
|
+
this._dispatch(KEYBOARD_ENTER)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private _dispatch = (eventName: string, detail?: Partial<KeyboardCustomEvent>) => {
|
|
41
|
+
const { wrapData, cellKey } = this.props
|
|
42
|
+
dispatchCache[wrapData.id] = {
|
|
43
|
+
eventName,
|
|
44
|
+
detail,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
window.dispatchEvent(
|
|
48
|
+
new CustomEvent(`${eventName}${wrapData.id}`, { detail: { ...detail, cellKey } })
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private _handleFocus = (event: CustomEvent<KeyboardCustomEvent>) => {
|
|
53
|
+
const { wrapData, onFocus, onScroll, cellKey, disabled } = this.props
|
|
54
|
+
|
|
55
|
+
if (event.detail.cellKey !== cellKey) {
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!disabled) {
|
|
60
|
+
onFocus()
|
|
61
|
+
onScroll(wrapData.fixedWidths)
|
|
62
|
+
}
|
|
63
|
+
// 不可响应,则抛给下一个响应者
|
|
64
|
+
else {
|
|
65
|
+
this._dispatch(
|
|
66
|
+
dispatchCache[wrapData.id].eventName,
|
|
67
|
+
dispatchCache[wrapData.id].detail
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
componentDidMount() {
|
|
73
|
+
const { wrapData } = this.props
|
|
74
|
+
window.addEventListener(
|
|
75
|
+
`${KEYBOARD_ONFOCUS}${wrapData.id}`,
|
|
76
|
+
(this._handleFocus as any) as EventListener
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
componentWillUnmount() {
|
|
81
|
+
const { wrapData } = this.props
|
|
82
|
+
window.removeEventListener(
|
|
83
|
+
`${KEYBOARD_ONFOCUS}${wrapData.id}`,
|
|
84
|
+
(this._handleFocus as any) as EventListener
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
render() {
|
|
89
|
+
const { children, cellKey } = this.props
|
|
90
|
+
return cloneElement(children as ReactElement, {
|
|
91
|
+
'data-cell-key': cellKey,
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default KeyboardCell
|