mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
ui: replace stupid react-split-pane with allotment
This commit is contained in:
9 files changed
+35
-148
No files matched your search
@@ -1,12 +0,0 @@
|
|||||||
diff --git a/index.d.ts b/index.d.ts
|
|
||||||
index d116f54d6da12d24b48e24ff3636c9066059aa58..9d62eac28d5480aa6c2e796d603757d5999ea0af 100644
|
|
||||||
--- a/index.d.ts
|
|
||||||
+++ b/index.d.ts
|
|
||||||
@@ -25,6 +25,7 @@ export type SplitPaneProps = {
|
|
||||||
pane2Style?: React.CSSProperties;
|
|
||||||
resizerClassName?: string;
|
|
||||||
step?: number;
|
|
||||||
+ children: React.ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SplitPaneState = {
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
.splitpane-fill
|
|
||||||
display: flex
|
|
||||||
position: absolute
|
|
||||||
overflow: hidden
|
|
||||||
left: 0
|
|
||||||
width: 100%
|
|
||||||
top: 0
|
|
||||||
height: 100%
|
|
||||||
user-select: none
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
import classNames from 'classnames';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
export default function SplitPaneFillOverlayComponent(props) {
|
|
||||||
const {
|
|
||||||
className,
|
|
||||||
children,
|
|
||||||
...rest
|
|
||||||
} = props;
|
|
||||||
const cn = classNames(className, 'splitpane-fill');
|
|
||||||
return (
|
|
||||||
<div {...rest} className={cn}>{children}</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
SplitPaneFillOverlayComponent.propTypes = {
|
|
||||||
className: PropTypes.string,
|
|
||||||
children: PropTypes.node,
|
|
||||||
};
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
$resizer-extend = 4px
|
|
||||||
$resizer-extend-color = rgba($primary-color, 0.3)
|
|
||||||
|
|
||||||
.Resizer
|
|
||||||
background: #000
|
|
||||||
opacity: .2
|
|
||||||
z-index: 1
|
|
||||||
box-sizing: border-box
|
|
||||||
background-clip: padding-box
|
|
||||||
|
|
||||||
.Resizer.horizontal
|
|
||||||
height: ($resizer-extend * 2 + 1px)
|
|
||||||
margin: -($resizer-extend) 0
|
|
||||||
border-top: $resizer-extend solid transparent
|
|
||||||
border-bottom: $resizer-extend solid transparent
|
|
||||||
cursor: row-resize
|
|
||||||
width: 100%
|
|
||||||
|
|
||||||
.Resizer.vertical
|
|
||||||
width: ($resizer-extend * 2 + 1px)
|
|
||||||
margin: 0 -($resizer-extend)
|
|
||||||
border-left: $resizer-extend solid transparent
|
|
||||||
border-right: $resizer-extend solid transparent
|
|
||||||
cursor: col-resize
|
|
||||||
|
|
||||||
.Resizer:hover
|
|
||||||
border-color: $resizer-extend-color
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SplitPaneFillOverlay from 'vj/components/react-splitpane/SplitPaneFillOverlayComponent';
|
|
||||||
|
|
||||||
export default function PanelComponent(props) {
|
export default function PanelComponent(props) {
|
||||||
const {
|
const {
|
||||||
@@ -12,10 +11,10 @@ export default function PanelComponent(props) {
|
|||||||
} = props;
|
} = props;
|
||||||
const cn = classNames(className, 'flex-col');
|
const cn = classNames(className, 'flex-col');
|
||||||
return (
|
return (
|
||||||
<SplitPaneFillOverlay {...rest} className={cn}>
|
<div {...rest} className={`${cn} splitpane-fill`}>
|
||||||
<div className="scratchpad__panel-title">{title}</div>
|
<div className="scratchpad__panel-title">{title}</div>
|
||||||
<div className="flex-col flex-fill">{children}</div>
|
<div className="flex-col flex-fill">{children}</div>
|
||||||
</SplitPaneFillOverlay>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,17 @@
|
|||||||
import ProblemIcon from '@vscode/codicons/src/icons/file.svg?react';
|
import ProblemIcon from '@vscode/codicons/src/icons/file.svg?react';
|
||||||
|
import { Allotment } from 'allotment';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import type * as monaco from 'monaco-editor';
|
import type * as monaco from 'monaco-editor';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useDispatch, useSelector, useStore } from 'react-redux';
|
import { useDispatch, useSelector, useStore } from 'react-redux';
|
||||||
import SplitPane from 'react-split-pane';
|
|
||||||
import Dom from 'vj/components/react/DomComponent';
|
import Dom from 'vj/components/react/DomComponent';
|
||||||
import SplitPaneFillOverlay from 'vj/components/react-splitpane/SplitPaneFillOverlayComponent';
|
|
||||||
import { Context, ctx, Service } from 'vj/context';
|
import { Context, ctx, Service } from 'vj/context';
|
||||||
import ScratchpadEditor from './ScratchpadEditorContainer';
|
import ScratchpadEditor from './ScratchpadEditorContainer';
|
||||||
import ScratchpadPretest from './ScratchpadPretestContainer';
|
import ScratchpadPretest from './ScratchpadPretestContainer';
|
||||||
import ScratchpadRecords from './ScratchpadRecordsContainer';
|
import ScratchpadRecords from './ScratchpadRecordsContainer';
|
||||||
import ScratchpadToolbar from './ScratchpadToolbarContainer';
|
import ScratchpadToolbar from './ScratchpadToolbarContainer';
|
||||||
|
|
||||||
function buildNestedPane([a, ...panes], mode: 'horizontal' | 'vertical' = 'horizontal') {
|
|
||||||
const elements = [
|
|
||||||
a,
|
|
||||||
...panes.filter((p) => p.props.visible),
|
|
||||||
];
|
|
||||||
if (elements.length === 1) return a;
|
|
||||||
return elements
|
|
||||||
.reduce((prev, curr) => (
|
|
||||||
<SplitPane
|
|
||||||
split={mode}
|
|
||||||
primary="second"
|
|
||||||
defaultSize={curr.props.size}
|
|
||||||
key={curr.element.key}
|
|
||||||
onChange={curr.onChange}
|
|
||||||
>
|
|
||||||
{prev}
|
|
||||||
{curr.element}
|
|
||||||
</SplitPane>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
const pages = {
|
const pages = {
|
||||||
problem: {
|
problem: {
|
||||||
icon: () => <ProblemIcon />,
|
icon: () => <ProblemIcon />,
|
||||||
@@ -88,14 +66,7 @@ export default function ScratchpadContainer() {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const ui = useSelector<any, any>((state) => state.ui, _.isEqual);
|
const ui = useSelector<any, any>((state) => state.ui, _.isEqual);
|
||||||
|
|
||||||
const handleChangeSize = _.debounce((uiElement, size) => {
|
const handleChangeSize = _.debounce(() => {
|
||||||
dispatch({
|
|
||||||
type: 'SCRATCHPAD_UI_CHANGE_SIZE',
|
|
||||||
payload: {
|
|
||||||
uiElement,
|
|
||||||
size,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
$('#scratchpad').trigger('vjScratchpadRelayout');
|
$('#scratchpad').trigger('vjScratchpadRelayout');
|
||||||
forceUpdate();
|
forceUpdate();
|
||||||
}, 500);
|
}, 500);
|
||||||
@@ -109,31 +80,20 @@ export default function ScratchpadContainer() {
|
|||||||
const showSidebar = Object.keys(pages).length > 1;
|
const showSidebar = Object.keys(pages).length > 1;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SplitPane
|
<Allotment onChange={handleChangeSize}>
|
||||||
split="vertical"
|
<Allotment.Pane visible={showSidebar} minSize={50} maxSize={50}>
|
||||||
primary="first"
|
<div className="scratchpad__tablist" style={{ display: showSidebar ? 'block' : 'none' }}>
|
||||||
size={showSidebar ? 50 : 0}
|
{Object.keys(pages).map((key) => {
|
||||||
allowResize={false}
|
const Component = pages[key].icon;
|
||||||
>
|
return (
|
||||||
<div className="scratchpad__tablist" style={{ display: showSidebar ? 'block' : 'none' }}>
|
<div key={key} className={key === ui.activePage ? 'scratchpad__tab-active' : ''} onClick={() => switchToPage(key)}>
|
||||||
{Object.keys(pages).map((key) => {
|
<Component />
|
||||||
const Component = pages[key].icon;
|
</div>
|
||||||
return (
|
);
|
||||||
<div key={key} className={key === ui.activePage ? 'scratchpad__tab-active' : ''} onClick={() => switchToPage(key)}>
|
})}
|
||||||
<Component />
|
</div>
|
||||||
</div>
|
</Allotment.Pane>
|
||||||
);
|
<Allotment.Pane visible={!!ui.activePage}>
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<SplitPane
|
|
||||||
defaultSize={ui.main.size}
|
|
||||||
size={ui.main.size}
|
|
||||||
minSize={ui.activePage !== null ? 250 : 0}
|
|
||||||
split="vertical"
|
|
||||||
primary="first"
|
|
||||||
onChange={(size) => handleChangeSize('main', size)}
|
|
||||||
allowResize={ui.activePage !== null}
|
|
||||||
>
|
|
||||||
<div className="scratchpad__problem">
|
<div className="scratchpad__problem">
|
||||||
{Object.keys(pages).map((key) => {
|
{Object.keys(pages).map((key) => {
|
||||||
const Component = pages[key].component;
|
const Component = pages[key].component;
|
||||||
@@ -144,23 +104,19 @@ export default function ScratchpadContainer() {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{buildNestedPane([
|
</Allotment.Pane>
|
||||||
<SplitPaneFillOverlay key="editor" className="flex-col">
|
<Allotment vertical onChange={handleChangeSize}>
|
||||||
<ScratchpadToolbar />
|
<div key="editor" className="flex-col splitpane-fill">
|
||||||
<ScratchpadEditor />
|
<ScratchpadToolbar />
|
||||||
</SplitPaneFillOverlay>,
|
<ScratchpadEditor />
|
||||||
{
|
</div>
|
||||||
props: ui.pretest,
|
<Allotment.Pane visible={ui.pretest.visible}>
|
||||||
onChange: (size) => handleChangeSize('pretest', size),
|
<ScratchpadPretest key="pretest" />
|
||||||
element: <ScratchpadPretest key="pretest" />,
|
</Allotment.Pane>
|
||||||
},
|
<Allotment.Pane visible={ui.records.visible}>
|
||||||
{
|
<ScratchpadRecords key="records" />
|
||||||
props: ui.records,
|
</Allotment.Pane>
|
||||||
onChange: (size) => handleChangeSize('records', size),
|
</Allotment>
|
||||||
element: <ScratchpadRecords key="records" />,
|
</Allotment>
|
||||||
},
|
|
||||||
])}
|
|
||||||
</SplitPane>
|
|
||||||
</SplitPane>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,6 @@ export interface Context {
|
|||||||
[Context.events]: Events<Context>;
|
[Context.events]: Events<Context>;
|
||||||
setTimeout: typeof setTimeout;
|
setTimeout: typeof setTimeout;
|
||||||
setInterval: typeof setInterval;
|
setInterval: typeof setInterval;
|
||||||
setImmediate: typeof setImmediate;
|
|
||||||
api: ApiMixin;
|
api: ApiMixin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,10 +36,9 @@ const T = <F extends (...args: any[]) => any>(origFunc: F, disposeFunc?) =>
|
|||||||
this.caller?.on('dispose', () => (disposeFunc ? disposeFunc(res) : res()));
|
this.caller?.on('dispose', () => (disposeFunc ? disposeFunc(res) : res()));
|
||||||
};
|
};
|
||||||
export class ApiMixin extends Service {
|
export class ApiMixin extends Service {
|
||||||
static readonly methods = ['addScript', 'setInterval', 'setTimeout', 'setImmediate', 'provideModule', 'inject', 'broadcast'];
|
static readonly methods = ['setInterval', 'setTimeout'];
|
||||||
setInterval = T(setInterval, clearInterval);
|
setInterval = T(setInterval, clearInterval);
|
||||||
setTimeout = T(setTimeout, clearTimeout);
|
setTimeout = T(setTimeout, clearTimeout);
|
||||||
setImmediate = T(setImmediate, clearImmediate);
|
|
||||||
constructor(ctx) {
|
constructor(ctx) {
|
||||||
super(ctx, 'api', true);
|
super(ctx, 'api', true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
"@types/sharedworker": "^0.0.91",
|
"@types/sharedworker": "^0.0.91",
|
||||||
"@types/webpack-env": "^1.18.0",
|
"@types/webpack-env": "^1.18.0",
|
||||||
"@vscode/codicons": "^0.0.32",
|
"@vscode/codicons": "^0.0.32",
|
||||||
|
"allotment": "^1.18.1",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
"browser-update": "^3.3.44",
|
"browser-update": "^3.3.44",
|
||||||
"chalk": "^5.2.0",
|
"chalk": "^5.2.0",
|
||||||
@@ -87,7 +88,6 @@
|
|||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-query": "^3.39.3",
|
"react-query": "^3.39.3",
|
||||||
"react-redux": "^8.0.5",
|
"react-redux": "^8.0.5",
|
||||||
"react-split-pane": "^0.1.92",
|
|
||||||
"reconnecting-websocket": "^4.4.0",
|
"reconnecting-websocket": "^4.4.0",
|
||||||
"redux": "^4.2.1",
|
"redux": "^4.2.1",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'normalize.css/normalize.css';
|
import 'normalize.css/normalize.css';
|
||||||
import 'vditor/dist/index.css';
|
import 'vditor/dist/index.css';
|
||||||
|
import 'allotment/dist/style.css';
|
||||||
import 'pickadate/lib/themes/classic.css';
|
import 'pickadate/lib/themes/classic.css';
|
||||||
import 'pickadate/lib/themes/classic.date.css';
|
import 'pickadate/lib/themes/classic.date.css';
|
||||||
import 'pickadate/lib/themes/classic.time.css';
|
import 'pickadate/lib/themes/classic.time.css';
|
||||||
|
|||||||
Reference in new issue
Block a user