blob: 1178e6e6a96df2b3a3315a2bab012ed8d0a29b52 [file]
import { EditorView, ViewPlugin, ViewUpdate, Decoration, DecorationSet, WidgetType } from '@codemirror/view';
class LoadingWidget extends WidgetType {
toDOM() {
const wrap = document.createElement('div');
wrap.className = 'cm-loading-overlay';
wrap.style.position = 'absolute';
wrap.style.top = '0';
wrap.style.left = '0';
wrap.style.right = '0';
wrap.style.bottom = '0';
wrap.style.display = 'flex';
wrap.style.alignItems = 'center';
wrap.style.justifyContent = 'center';
wrap.style.backgroundColor = '#272822';
wrap.style.zIndex = '100';
const spinner = document.createElement('div');
spinner.className = 'cm-loading-spinner';
spinner.style.width = '32px';
spinner.style.height = '32px';
spinner.style.border = '4px solid #e13c3c';
spinner.style.borderTopColor = 'transparent';
spinner.style.borderRadius = '50%';
spinner.style.animation = 'spin 1s linear infinite';
const style = document.createElement('style');
style.textContent = `
@keyframes spin {
to { transform: rotate(360deg); }
}
`;
document.head.appendChild(style);
wrap.appendChild(spinner);
return wrap;
}
}
export function loadingOverlay(isLoading: boolean) {
return ViewPlugin.fromClass(
class {
decorations: DecorationSet;
constructor(view: EditorView) {
this.decorations = this.createDecorations(isLoading);
}
update(update: ViewUpdate) {
if (update.docChanged) {
this.decorations = this.createDecorations(isLoading);
}
}
createDecorations(loading: boolean) {
if (!loading) return Decoration.none;
return Decoration.set([
Decoration.widget({
widget: new LoadingWidget(),
side: 1,
}).range(0),
]);
}
},
{
decorations: (v) => {
return v.decorations;
},
},
);
}