feat: yaml editor
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
import { Collapse, CollapseProps } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const CollapseInner = styled(Collapse)`
|
||||
.ant-collapse-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px !important;
|
||||
padding-inline: 5px !important;
|
||||
padding-block: 8px !important;
|
||||
border-radius: var(--border-radius-base) !important;
|
||||
font-size: 14px !important;
|
||||
font-weight: 600 !important;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--ant-color-fill-tertiary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-collapse-content-box {
|
||||
padding-inline: 0 !important;
|
||||
padding-block: 0 !important;
|
||||
}
|
||||
.ant-collapse-header-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 24px;
|
||||
}
|
||||
`;
|
||||
|
||||
const CollapsePanel: React.FC<{ items: CollapseProps['items'] }> = ({
|
||||
items
|
||||
}) => {
|
||||
return (
|
||||
<CollapseInner
|
||||
expandIconPosition="start"
|
||||
bordered={false}
|
||||
ghost
|
||||
accordion
|
||||
destroyOnHidden={false}
|
||||
expandIcon={({ isActive }) => (
|
||||
<IconFont
|
||||
type="icon-down"
|
||||
rotate={isActive ? 0 : -90}
|
||||
style={{ fontSize: '14px' }}
|
||||
></IconFont>
|
||||
)}
|
||||
items={items}
|
||||
></CollapseInner>
|
||||
);
|
||||
};
|
||||
|
||||
export default CollapsePanel;
|
||||
@@ -0,0 +1,51 @@
|
||||
import useOverlayScroller from '@/hooks/use-overlay-scroller';
|
||||
import React from 'react';
|
||||
import './style.less';
|
||||
|
||||
const ColumnWrapper: React.FC<any> = ({
|
||||
children,
|
||||
footer,
|
||||
maxHeight,
|
||||
paddingBottom = 50
|
||||
}) => {
|
||||
const scroller = React.useRef<any>(null);
|
||||
const { initialize } = useOverlayScroller({
|
||||
options: {
|
||||
scrollbars: {
|
||||
autoHide: 'move'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
if (scroller.current) {
|
||||
initialize(scroller.current);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="column-wrapper-footer"
|
||||
style={{ height: maxHeight || '100%' }}
|
||||
>
|
||||
<div
|
||||
className="column-wrapper"
|
||||
ref={scroller}
|
||||
style={{ padding: '16px 24px' }}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
paddingBottom: footer ? paddingBottom : 0
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
{footer && <div className="footer">{footer}</div>}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ColumnWrapper;
|
||||
@@ -0,0 +1,31 @@
|
||||
.column-wrapper {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.simplebar-scrollbar::before {
|
||||
width: var(--scrollbar-size);
|
||||
background: var(--scrollbar-handle-bg);
|
||||
}
|
||||
|
||||
.column-wrapper-footer {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.column-wrapper {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
padding-block: 0;
|
||||
background-color: var(--ant-color-bg-elevated);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import CopyButton from '@/components/copy-button';
|
||||
import EditorWrap from '@/components/editor-wrap';
|
||||
import HighlightCode from '@/components/highlight-code';
|
||||
import SegmentLine from '@/components/segment-line';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface ViewerProps {
|
||||
code: string;
|
||||
copyText?: string;
|
||||
options?: Global.BaseOption<string>[];
|
||||
defaultValue?: string;
|
||||
headerHeight?: number;
|
||||
lang?: string;
|
||||
onChange?: (value: string | number) => void;
|
||||
}
|
||||
|
||||
const Header = styled.div`
|
||||
width: 100%;
|
||||
padding-inline: 12px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: var(--color-editor-header-bg);
|
||||
`;
|
||||
|
||||
const CommandViewer: React.FC<ViewerProps> = (props) => {
|
||||
const {
|
||||
code,
|
||||
copyText = '',
|
||||
defaultValue,
|
||||
options = [],
|
||||
headerHeight = 40,
|
||||
lang,
|
||||
onChange
|
||||
} = props || {};
|
||||
|
||||
const [value, setValue] = React.useState<string>(defaultValue || '');
|
||||
|
||||
const handlOnChange = (value: string | number) => {
|
||||
setValue(value as string);
|
||||
onChange?.(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<EditorWrap
|
||||
header={
|
||||
<Header>
|
||||
<SegmentLine
|
||||
height={headerHeight}
|
||||
defaultValue={defaultValue}
|
||||
value={value}
|
||||
size="small"
|
||||
options={options}
|
||||
onChange={handlOnChange}
|
||||
></SegmentLine>
|
||||
|
||||
<CopyButton
|
||||
text={copyText || code}
|
||||
size="small"
|
||||
style={{
|
||||
color: 'rgba(255,255,255,.7)'
|
||||
}}
|
||||
/>
|
||||
</Header>
|
||||
}
|
||||
>
|
||||
<HighlightCode
|
||||
height={380}
|
||||
theme="dark"
|
||||
code={code}
|
||||
lang={lang || value}
|
||||
copyable={false}
|
||||
></HighlightCode>
|
||||
</EditorWrap>
|
||||
);
|
||||
};
|
||||
|
||||
export default CommandViewer;
|
||||
Reference in New Issue
Block a user