@marcoschulte/vue3-progress
Version:
A fully customizable vue3 plugin to display a progress bar while waiting for something, e.g. http requests
73 lines (60 loc) • 1.74 kB
text/typescript
import {App, Plugin, reactive} from 'vue';
import {holder} from './GlobalInstanceHolder';
import {injectionKey} from './Injector';
import ProgressBar from './ProgressBar.vue';
import {ProgressControls, ProgressFinisher} from './ProgressControls';
import {ProgressState} from './ProgressState';
export interface ProgressOptions {
disableGlobalInstance: boolean;
}
const state = reactive({
active: false,
} as ProgressState);
const createPlugin = (): ProgressControls => {
const internalState = {inflight: 0};
const updateActive = () => {
state.active = internalState.inflight > 0;
};
const createFinisher = (finishState: { used: boolean }) => {
return {
finish: () => {
if (!finishState.used) {
finishState.used = true;
internalState.inflight--;
updateActive();
}
},
};
};
return {
start(): ProgressFinisher {
internalState.inflight++;
updateActive();
return createFinisher({used: false});
},
attach(promise) {
const finisher = this.start();
promise.then(() => finisher.finish(), () => finisher.finish());
return promise;
},
state(): ProgressState {
return state;
},
};
};
export const Vue3ProgressPlugin: Plugin = {
install: (app: App, options?: ProgressOptions) => {
const instance = createPlugin();
app.provide(injectionKey, instance);
app.config.globalProperties.$progress = instance;
if (!options || !options.disableGlobalInstance) {
holder.instance = instance;
}
app.component('Vue3ProgressBar', ProgressBar);
},
};
declare module '@vue/runtime-core' {
export interface ComponentCustomProperties {
$progress: ProgressControls;
}
}