Skip to content

Commit 8691459

Browse files
committed
feat: add Scrollable component
1 parent 0dab5a8 commit 8691459

File tree

7 files changed

+211
-10
lines changed

7 files changed

+211
-10
lines changed

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@
3131
"loadsh": "^0.0.4",
3232
"monaco-editor": "^0.21.2",
3333
"rc-collapse": "^2.0.1",
34+
"rc-tabs": "11.7.0",
3435
"rc-tree": "^3.10.0",
3536
"react": "^16.13.1",
3637
"react-dnd": "^9.3.4",
3738
"react-dnd-html5-backend": "^9.3.4",
38-
"rc-tabs": "11.7.0",
3939
"react-dom": "^16.13.1",
40+
"react-scrollbars-custom": "^4.0.25",
4041
"react-split-pane": "^0.1.92",
4142
"reflect-metadata": "^0.1.13",
4243
"tsyringe": "^4.3.0",

src/components/scrollable/index.tsx

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import './style.scss';
2+
import * as React from 'react';
3+
import { useCallback, useMemo, useState } from 'react';
4+
import { Scrollbar, ScrollbarProps } from 'react-scrollbars-custom';
5+
import { prefixClaName, classNames } from 'mo/common/className';
6+
7+
interface IScrollbar extends ScrollbarProps {
8+
autoHideThumb?: boolean;
9+
}
10+
11+
const defaultSrollableClassName = 'scrollable';
12+
13+
/**
14+
* The react-scrollbars-custom component default not supports auto hide thumb option,
15+
* the below implementation from this issue:
16+
* https://github.com/xobotyi/react-scrollbars-custom/issues/46
17+
*/
18+
export function Scrollable(props: IScrollbar) {
19+
const { className, children, ...custom } = props;
20+
21+
const [isScrolling, setIsScrolling] = useState(false);
22+
const [isMouseOver, setIsMouseOver] = useState(false);
23+
const isShow = isScrolling || isMouseOver;
24+
25+
const claNames = classNames(
26+
prefixClaName(defaultSrollableClassName),
27+
className
28+
);
29+
30+
const onScrollStart = useCallback(() => {
31+
setIsScrolling(true);
32+
}, []);
33+
const onScrollStop = useCallback(() => {
34+
setIsScrolling(false);
35+
}, []);
36+
const onMouseEnter = useCallback(() => {
37+
setIsMouseOver(true);
38+
}, []);
39+
const onMouseLeave = useCallback(() => {
40+
setIsMouseOver(false);
41+
}, []);
42+
43+
const trackProps = useMemo(() => ({
44+
renderer: ({ elementRef, style, ...restProps }: any) => (
45+
<span
46+
{...restProps}
47+
ref={elementRef}
48+
style={{
49+
...style, opacity: isShow ? 1 : 0,
50+
transition: "opacity 0.4s ease-in-out",
51+
}}
52+
onMouseEnter={onMouseEnter}
53+
onMouseLeave={onMouseLeave}/>
54+
)
55+
}), [isShow, onMouseEnter, onMouseLeave]);
56+
57+
return (
58+
<Scrollbar
59+
className={claNames} {...custom as any}
60+
wrapperProps={{
61+
renderer: ({ elementRef, style, ...restProps }: any) => (
62+
<div {...restProps} ref={elementRef} style={{ ...style, right: 0 }} />
63+
),
64+
}}
65+
trackXProps={trackProps}
66+
trackYProps={trackProps}
67+
onScrollStart={onScrollStart}
68+
onScrollStop={onScrollStop}
69+
scrollDetectionThreshold={500} // ms
70+
>
71+
{ children }
72+
</Scrollbar>
73+
)
74+
}

src/components/scrollable/style.scss

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@import 'mo/style/common';
2+
$scrollbar: 'scrollbar';
3+
4+
// #{prefix($scrollbar)} {
5+
// pointer-events: none;
6+
// }

src/components/scroller/style.scss

-4
This file was deleted.

src/workbench/activityBar/activityBar.tsx

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import * as React from 'react';
33
import { prefixClaName } from 'mo/common/className';
44
import { ID_ACTIVITY_BAR } from 'mo/common/id';
55
import { IActivityBar, IActivityBarItem } from 'mo/model/workbench/activityBar';
6+
67
import ActivityBarItem from './activityBarItem';
8+
import { Scrollable } from 'mo/components/scrollable';
79

810
export function ActivityBar(props: IActivityBar) {
911
const { data = [], render, selected, onClick, onSelect } = props;
@@ -43,9 +45,11 @@ export function ActivityBar(props: IActivityBar) {
4345
return (
4446
<div className={prefixClaName(ID_ACTIVITY_BAR)} id={ID_ACTIVITY_BAR}>
4547
<div className={prefixClaName('container', ID_ACTIVITY_BAR)}>
46-
<ul className={'normal-items'}>
47-
{normalBarItems.map(renderItems)}
48-
</ul>
48+
<Scrollable className={'normal-items'}>
49+
<ul>
50+
{normalBarItems.map(renderItems)}
51+
</ul>
52+
</Scrollable>
4953
<ul className={'global-items'}>
5054
{globalBarItems.map(renderItems)}
5155
</ul>
@@ -54,4 +58,4 @@ export function ActivityBar(props: IActivityBar) {
5458
);
5559
}
5660

57-
export default ActivityBar;
61+
export default ActivityBar;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import * as React from 'react';
2+
import { storiesOf } from '@storybook/react';
3+
import { withKnobs } from '@storybook/addon-knobs';
4+
import { propsTable } from '../common/propsTable';
5+
6+
import { Menu, MenuItem } from 'mo/components/menu';
7+
import { Scrollable } from 'mo/components/scrollable';
8+
9+
const stories = storiesOf('Scrollable', module);
10+
stories.addDecorator(withKnobs);
11+
12+
const propDefinitions = [
13+
{
14+
property: 'render',
15+
propType: '() => React.ReactNode',
16+
required: false,
17+
description: 'Default render content',
18+
defaultValue: null,
19+
},
20+
];
21+
22+
stories.add(
23+
'Basic Usage',
24+
() => {
25+
const items: any[] = [];
26+
for (let i = 0; i < 100; i++) {
27+
items.push(<MenuItem key={i}>{i}</MenuItem>)
28+
}
29+
return (
30+
<div>
31+
<h2>简述</h2>
32+
<p>
33+
Scrollable, custom scrollbar component based on [react-scrollbars-custom](https://xobotyi.github.io/react-scrollbars-custom/),
34+
More usage, please [visit](https://github.com/xobotyi/react-scrollbars-custom).
35+
</p>
36+
<div>
37+
<h3>使用示例 1</h3>
38+
<Menu
39+
style={{
40+
width: 100,
41+
height: 200,
42+
color: 'rgba(255, 255, 255, 0.4)',
43+
background: '#252526',
44+
}}
45+
>
46+
<Scrollable>
47+
{ items }
48+
</Scrollable>
49+
</Menu>
50+
</div>
51+
</div>
52+
);
53+
},
54+
{
55+
info: {
56+
inline: true,
57+
TableComponent: () => propsTable({ propDefinitions }),
58+
// propTablesExclude: [],
59+
text: `
60+
代码示例:
61+
~~~js
62+
import { useContextView } from 'mo/components/contextview';
63+
64+
const contextView = useContextView();
65+
66+
const mouseMove = (event: React.MouseEvent): void => {
67+
contextView.show({
68+
x: event.clientX,
69+
y: event.clientY,
70+
}, () => {
71+
return (
72+
<h1>Hello World</h1>
73+
);
74+
});
75+
};
76+
77+
return (
78+
<div>
79+
<div id="topLeft"
80+
onMouseMove={mouseMove}
81+
style={
82+
{
83+
position: 'absolute',
84+
width: 200,
85+
height: 200,
86+
top: 0,
87+
left: 0,
88+
right: 0,
89+
bottom: 0,
90+
background: '#dddddd',
91+
}
92+
}>
93+
Hover me!
94+
</div>
95+
</div>
96+
);
97+
~~
98+
`,
99+
},
100+
}
101+
);

yarn.lock

+20-1
Original file line numberDiff line numberDiff line change
@@ -4369,6 +4369,11 @@ clone-regexp@^2.1.0:
43694369
dependencies:
43704370
is-regexp "^2.0.0"
43714371

4372+
cnbuilder@^2.5.0:
4373+
version "2.6.0"
4374+
resolved "http://registry.npm.dtstack.com/cnbuilder/-/cnbuilder-2.6.0.tgz#309b4f34371be80ad5452f983b7bac1af4f09ac8"
4375+
integrity sha1-MJtPNDcb6ArVRS+YO3usGvTwmsg=
4376+
43724377
co@^4.6.0:
43734378
version "4.6.0"
43744379
resolved "http://registry.npm.dtstack.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@@ -11122,7 +11127,7 @@ react-dom@^16.13.1, react-dom@^16.8.3:
1112211127
prop-types "^15.6.2"
1112311128
scheduler "^0.19.1"
1112411129

11125-
react-draggable@^4.0.3:
11130+
react-draggable@^4.0.3, react-draggable@^4.4.2:
1112611131
version "4.4.3"
1112711132
resolved "http://registry.npm.dtstack.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3"
1112811133
integrity sha1-ByfyyuWBPjaw5JYr8RsvnvK0BvM=
@@ -11244,6 +11249,15 @@ react-refresh@^0.8.3:
1124411249
resolved "http://registry.npm.dtstack.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
1124511250
integrity sha1-ch1GV2ctQAxePHXQY8SoX7LV1o8=
1124611251

11252+
react-scrollbars-custom@^4.0.25:
11253+
version "4.0.25"
11254+
resolved "http://registry.npm.dtstack.com/react-scrollbars-custom/-/react-scrollbars-custom-4.0.25.tgz#64c1390fc04fe2b90373d5d142bd129a3d46e394"
11255+
integrity sha1-ZME5D8BP4rkDc9XRQr0Smj1G45Q=
11256+
dependencies:
11257+
cnbuilder "^2.5.0"
11258+
react-draggable "^4.4.2"
11259+
zoom-level "^2.5.0"
11260+
1124711261
react-select@^3.0.8:
1124811262
version "3.1.0"
1124911263
resolved "http://registry.npm.dtstack.com/react-select/-/react-select-3.1.0.tgz#ab098720b2e9fe275047c993f0d0caf5ded17c27"
@@ -14242,6 +14256,11 @@ yargs@^15.1.0, yargs@^15.3.1, yargs@^15.4.1:
1424214256
y18n "^4.0.0"
1424314257
yargs-parser "^18.1.2"
1424414258

14259+
zoom-level@^2.5.0:
14260+
version "2.5.0"
14261+
resolved "http://registry.npm.dtstack.com/zoom-level/-/zoom-level-2.5.0.tgz#286ec16f247b8bb7a900df6612567688eeef498a"
14262+
integrity sha1-KG7BbyR7i7epAN9mElZ2iO7vSYo=
14263+
1424514264
zwitch@^1.0.0:
1424614265
version "1.0.5"
1424714266
resolved "http://registry.npm.dtstack.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"

0 commit comments

Comments
 (0)