Files
cloudbeaver/webapp/packages/plugin-codemirror6/src/ReactCodemirrorPanel.tsx
T
Alexey 6ad148850d refactor: migrate to pure esm CB-5684 (#2929)
* refactor: migrate to pure esm

* chore: revert `useDefineForClassFields` tsconf

* chore: remove patch.js
2024-09-21 07:06:37 +03:00

58 lines
1.6 KiB
TypeScript

/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { Compartment, StateEffect } from '@codemirror/state';
import { showPanel } from '@codemirror/view';
import { observer } from 'mobx-react-lite';
import { useContext, useLayoutEffect, useMemo } from 'react';
import { createPortal } from 'react-dom';
import { ReactCodemirrorContext } from './ReactCodemirrorContext.js';
interface Props extends React.PropsWithChildren {
className?: string;
incomingView?: boolean;
top?: boolean;
}
export const ReactCodemirrorPanel: React.FC<Props> = observer(function ReactCodemirrorPanel({ className, children, incomingView, top }) {
const dom = useMemo(() => document.createElement('div'), []);
const compartment = useMemo(() => new Compartment(), []);
const context = useContext(ReactCodemirrorContext);
const view = incomingView ? context?.incomingView : context?.view;
useLayoutEffect(() => {
if (view) {
view.dispatch({
effects: [StateEffect.appendConfig.of(compartment.of(showPanel.of(() => ({ top, dom }))))],
});
return () => {
view.dispatch({
effects: compartment.reconfigure([]),
});
};
}
return undefined;
}, [view, top]);
useLayoutEffect(() => {
if (className) {
const classes = className.split(' ');
dom.classList.add(...classes);
return () => {
dom.classList.remove(...classes);
};
}
return undefined;
}, [className]);
return createPortal(children, dom) as any;
});