-
-
Notifications
You must be signed in to change notification settings - Fork 777
Expand file tree
/
Copy pathindex.tsx
More file actions
126 lines (113 loc) · 3.3 KB
/
index.tsx
File metadata and controls
126 lines (113 loc) · 3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import * as React from 'react';
import type { OnStartMove } from '../interface';
import { getIndex } from '../util';
import type { HandleProps } from './Handle';
import Handle from './Handle';
export interface HandlesProps {
prefixCls: string;
style?: React.CSSProperties | React.CSSProperties[];
values: number[];
onStartMove: OnStartMove;
onOffsetChange: (value: number | 'min' | 'max', valueIndex: number) => void;
onFocus?: (e: React.FocusEvent<HTMLDivElement>) => void;
onBlur?: (e: React.FocusEvent<HTMLDivElement>) => void;
onDelete: (index: number) => void;
handleRender?: HandleProps['render'];
/**
* When config `activeHandleRender`,
* it will render another hidden handle for active usage.
* This is useful for accessibility or tooltip usage.
*/
activeHandleRender?: HandleProps['render'];
draggingIndex: number;
draggingDelete: boolean;
onChangeComplete?: () => void;
}
export interface HandlesRef {
focus: (index: number) => void;
}
const Handles = React.forwardRef<HandlesRef, HandlesProps>((props, ref) => {
const {
prefixCls,
style,
onStartMove,
onOffsetChange,
values,
handleRender,
activeHandleRender,
draggingIndex,
draggingDelete,
onFocus,
...restProps
} = props;
const handlesRef = React.useRef<Record<number, HTMLDivElement>>({});
React.useImperativeHandle(ref, () => ({
focus: (index: number) => {
handlesRef.current[index]?.focus();
},
}));
// =========================== Active ===========================
const [activeIndex, setActiveIndex] = React.useState<number>(-1);
const onHandleFocus = (e: React.FocusEvent<HTMLDivElement>, index: number) => {
setActiveIndex(index);
onFocus?.(e);
};
const onHandleMouseEnter = (e: React.MouseEvent<HTMLDivElement>, index: number) => {
setActiveIndex(index);
};
// =========================== Render ===========================
// Handle Props
const handleProps = {
prefixCls,
onStartMove,
onOffsetChange,
render: handleRender,
onFocus: onHandleFocus,
onMouseEnter: onHandleMouseEnter,
...restProps,
};
return (
<>
{values.map<React.ReactNode>((value, index) => {
const dragging = draggingIndex === index;
return (
<Handle
ref={(node) => {
if (!node) {
delete handlesRef.current[index];
} else {
handlesRef.current[index] = node;
}
}}
dragging={dragging}
draggingDelete={dragging && draggingDelete}
style={getIndex(style, index)}
key={index}
value={value}
valueIndex={index}
{...handleProps}
/>
);
})}
{/* Used for render tooltip, this is not a real handle */}
{activeHandleRender && (
<Handle
key="a11y"
{...handleProps}
value={values[activeIndex]}
valueIndex={null}
dragging={draggingIndex !== -1}
draggingDelete={draggingDelete}
render={activeHandleRender}
style={{ pointerEvents: 'none' }}
tabIndex={null}
aria-hidden
/>
)}
</>
);
});
if (process.env.NODE_ENV !== 'production') {
Handles.displayName = 'Handles';
}
export default Handles;