misc_pterodactyl-panel/resources/scripts/components/elements/Editor2.tsx

100 lines
3.1 KiB
TypeScript
Raw Normal View History

import React, { useCallback, useState } from 'react';
import styled from 'styled-components/macro';
import tw, { TwStyle } from 'twin.macro';
import { autocompletion, completionKeymap } from '@codemirror/autocomplete';
import { closeBrackets, closeBracketsKeymap } from '@codemirror/closebrackets';
import { defaultKeymap, defaultTabBinding } from '@codemirror/commands';
import { commentKeymap } from '@codemirror/comment';
import { foldGutter, foldKeymap } from '@codemirror/fold';
import { lineNumbers, highlightActiveLineGutter } from '@codemirror/gutter';
import { defaultHighlightStyle } from '@codemirror/highlight';
import { history, historyKeymap } from '@codemirror/history';
import { indentOnInput, LezerLanguage } from '@codemirror/language';
import { lintKeymap } from '@codemirror/lint';
import { bracketMatching } from '@codemirror/matchbrackets';
import { rectangularSelection } from '@codemirror/rectangular-selection';
import { searchKeymap, highlightSelectionMatches } from '@codemirror/search';
import { Extension, EditorState } from '@codemirror/state';
import { StreamLanguage, StreamParser } from '@codemirror/stream-parser';
import { keymap, highlightSpecialChars, drawSelection, highlightActiveLine, EditorView } from '@codemirror/view';
import { ayuMirage } from '@/components/elements/EditorTheme';
const extensions: Extension = [
ayuMirage,
lineNumbers(),
highlightActiveLineGutter(),
highlightSpecialChars(),
history(),
foldGutter(),
drawSelection(),
EditorState.allowMultipleSelections.of(true),
indentOnInput(),
defaultHighlightStyle.fallback,
bracketMatching(),
closeBrackets(),
autocompletion(),
rectangularSelection(),
highlightActiveLine(),
highlightSelectionMatches(),
keymap.of([
...closeBracketsKeymap,
...defaultKeymap,
...searchKeymap,
...historyKeymap,
...foldKeymap,
...commentKeymap,
...completionKeymap,
...lintKeymap,
defaultTabBinding,
]),
EditorState.tabSize.of(4),
];
const EditorContainer = styled.div<{ overrides?: TwStyle }>`
min-height: 12rem;
${tw`relative`};
& > div {
${props => props.overrides};
&.cm-focused {
outline: none;
}
}
`;
export interface Props {
className?: string;
overrides?: TwStyle;
mode: LezerLanguage | StreamParser<any>;
initialContent?: string;
}
export default ({ className, overrides, mode, initialContent }: Props) => {
const [ state ] = useState<EditorState>(EditorState.create({
doc: initialContent,
extensions: [ ...extensions, (mode instanceof LezerLanguage) ? mode : StreamLanguage.define(mode) ],
}));
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [ view, setView ] = useState<EditorView>();
const ref = useCallback((node) => {
if (!node) {
return;
}
const view = new EditorView({
state: state,
parent: node,
});
setView(view);
}, []);
return (
<EditorContainer className={className} overrides={overrides} ref={ref}/>
);
};