diff --git a/docs/3.api/2.composables/use-loading-indicator.md b/docs/3.api/2.composables/use-loading-indicator.md index 357c260bbd..9d112ed764 100644 --- a/docs/3.api/2.composables/use-loading-indicator.md +++ b/docs/3.api/2.composables/use-loading-indicator.md @@ -40,7 +40,11 @@ It hooks into [`page:loading:start`](/docs/api/advanced/hooks#app-hooks-runtime) ### `start()` -Set `isLoading` to true and start to increase the `progress` value. +Set `isLoading` to true and start to increase the `progress` value. `start` accepts a `{ force: true }` option to skip the interval and show the loading state immediately. + +### `set()` + +Set the `progress` value to a specific value. `set` accepts a `{ force: true }` option to skip the interval and show the loading state immediately. ### `finish()` @@ -62,3 +66,12 @@ Used by `finish()`. Clear all timers and intervals used by the composable. }) ``` + +```vue + +``` diff --git a/packages/nuxt/src/app/composables/loading-indicator.ts b/packages/nuxt/src/app/composables/loading-indicator.ts index b3c0a86455..e3d1031d79 100644 --- a/packages/nuxt/src/app/composables/loading-indicator.ts +++ b/packages/nuxt/src/app/composables/loading-indicator.ts @@ -24,8 +24,8 @@ export type LoadingIndicator = { progress: Ref isLoading: Ref error: Ref - start: () => void - set: (value: number) => void + start: (opts?: { force?: boolean }) => void + set: (value: number, opts?: { force?: boolean }) => void finish: (opts?: { force?: boolean, error?: boolean }) => void clear: () => void } @@ -49,23 +49,24 @@ function createLoadingIndicator (opts: Partial = {}) { let hideTimeout: number | NodeJS.Timeout let resetTimeout: number | NodeJS.Timeout - const start = () => { + const start = (opts: { force?: boolean } = {}) => { error.value = false - set(0) + set(0, opts) } - function set (at = 0) { + function set (at = 0, opts: { force?: boolean } = {}) { if (nuxtApp.isHydrating) { return } - if (at >= 100) { return finish() } + if (at >= 100) { return finish({ force: opts.force }) } clear() progress.value = at < 0 ? 0 : at - if (throttle && import.meta.client) { + const throttleTime = opts.force ? 0 : throttle + if (throttleTime && import.meta.client) { throttleTimeout = setTimeout(() => { isLoading.value = true _startProgress() - }, throttle) + }, throttleTime) } else { isLoading.value = true _startProgress() diff --git a/test/nuxt/composables.test.ts b/test/nuxt/composables.test.ts index 425660839d..97a600b762 100644 --- a/test/nuxt/composables.test.ts +++ b/test/nuxt/composables.test.ts @@ -530,6 +530,23 @@ describe('loading state', () => { }) }) +describe('loading state', () => { + it('expect state from set opts: { force: true }', async () => { + vi.stubGlobal('setTimeout', vi.fn((cb: () => void) => cb())) + const nuxtApp = useNuxtApp() + const { isLoading, start, finish, set } = useLoadingIndicator() + await nuxtApp.callHook('page:loading:start') + start({ force: true }) + expect(isLoading.value).toBeTruthy() + finish() + expect(isLoading.value).toBeFalsy() + set(0, { force: true }) + expect(isLoading.value).toBeTruthy() + set(100, { force: true }) + expect(isLoading.value).toBeFalsy() + }) +}) + describe.skipIf(process.env.TEST_MANIFEST === 'manifest-off')('app manifests', () => { it('getAppManifest', async () => { const manifest = await getAppManifest()