From 156cdfabe18303f1b3a17aae93e2de1fecbf2499 Mon Sep 17 00:00:00 2001 From: lorikku Date: Sat, 20 Apr 2024 14:25:29 +0200 Subject: [PATCH 1/6] Added manual control possibility over loader --- src/HolyProgress.ts | 2 +- src/constants.ts | 3 +++ src/index.tsx | 60 +++++++++++++++++++++++++++++++++------------ 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/HolyProgress.ts b/src/HolyProgress.ts index 0663e19..fc4de25 100644 --- a/src/HolyProgress.ts +++ b/src/HolyProgress.ts @@ -200,7 +200,7 @@ export class HolyProgress { /** * Performs automatic incrementation of the progress bar. - * This function is recursive and continues to increment the progress at intervals defined by `sppeed`. + * This function is recursive and continues to increment the progress at intervals defined by `speed`. * @private */ private readonly startTrickle = (): void => { diff --git a/src/constants.ts b/src/constants.ts index b276df8..75fee07 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -8,3 +8,6 @@ export const DEFAULTS = { showSpinner: false, boxShadow: undefined, }; + +export const START_HOLY_EVENT = 'holy-progress-start'; +export const STOP_HOLY_EVENT = 'holy-progress-stop'; diff --git a/src/index.tsx b/src/index.tsx index c11ace3..f51441f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { HolyProgress } from './HolyProgress'; -import { DEFAULTS } from './constants'; +import { DEFAULTS, START_HOLY_EVENT, STOP_HOLY_EVENT } from './constants'; export interface HolyLoaderProps { /** @@ -97,6 +97,20 @@ export const isSameHost = (currentUrl: string, newUrl: string): boolean => { ); }; +/** + * Dispatches the event to manually start the HolyLoader progress bar. + */ +export const startHolyProgress = (): void => { + document.dispatchEvent(new Event(START_HOLY_EVENT)); +}; + +/** + * Dispatches the event to manually stop the HolyLoader progress bar. + */ +export const stopHolyProgress = (): void => { + document.dispatchEvent(new Event(STOP_HOLY_EVENT)); +}; + /** * HolyLoader is a React component that provides a customizable top-loading progress bar. * @@ -113,18 +127,26 @@ const HolyLoader = ({ boxShadow = DEFAULTS.boxShadow, showSpinner = DEFAULTS.showSpinner, }: HolyLoaderProps): null => { - React.useEffect(() => { - let holyProgress: HolyProgress; + const holyProgressRef = React.useRef(null); + React.useEffect(() => { const startProgress = (): void => { + if (holyProgressRef.current === null) { + return; + } + try { - holyProgress.start(); + holyProgressRef.current.start(); } catch (error) {} }; const stopProgress = (): void => { + if (holyProgressRef.current === null) { + return; + } + try { - holyProgress.complete(); + holyProgressRef.current.complete(); } catch (error) {} }; @@ -192,25 +214,31 @@ const HolyLoader = ({ }; try { - holyProgress = new HolyProgress({ - color, - height, - initialPosition, - easing, - speed, - zIndex, - boxShadow, - showSpinner, - }); + if (holyProgressRef.current !== null) { + holyProgressRef.current = new HolyProgress({ + color, + height, + initialPosition, + easing, + speed, + zIndex, + boxShadow, + showSpinner, + }); + } document.addEventListener('click', handleClick); + document.addEventListener(START_HOLY_EVENT, startProgress); + document.addEventListener(STOP_HOLY_EVENT, stopProgress); stopProgressOnHistoryUpdate(); } catch (error) {} return () => { document.removeEventListener('click', handleClick); + document.removeEventListener(START_HOLY_EVENT, startProgress); + document.removeEventListener(STOP_HOLY_EVENT, stopProgress); }; - }, []); + }, [holyProgressRef]); return null; }; From 6660abe67e1faf658cb48ab9ef594f20e28db1e5 Mon Sep 17 00:00:00 2001 From: lorikku Date: Sat, 20 Apr 2024 14:25:37 +0200 Subject: [PATCH 2/6] Updated README --- README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/README.md b/README.md index 2fa1c41..b9a7509 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,26 @@ export default function RootLayout({ children }) { } ``` +### Programmatic Control + +Have an async operation before an eventual route change? You might be interested in holy-loader's manual controls: + +```typescript +import { startHolyProgress, stopHolyProgress } from 'holy-loader'; + +try { + startHolyProgress(); // Trigger the loader beforehand + await signOut(); // Example async operation +} catch (error) { + stopHolyProgress(); // Stop the loader on error + // Handle the error +} finally { + stopHolyProgress(); // Stop the loader after the operation, and potentially do something else + /* OR */ + router.push('/'); // Navigate to the desired route, which will automatically stop the loader +} +``` + ## Common issues Prevent triggering the loader when clicking a Button within a Next link: From d958a35205804d26ea2aaea3fb3468ef9bb0c8e7 Mon Sep 17 00:00:00 2001 From: lorikku Date: Sun, 21 Apr 2024 13:44:08 +0200 Subject: [PATCH 3/6] Fixed dumb conditional bug --- src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index f51441f..05b43ba 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -214,7 +214,7 @@ const HolyLoader = ({ }; try { - if (holyProgressRef.current !== null) { + if (holyProgressRef.current === null) { holyProgressRef.current = new HolyProgress({ color, height, From 7737aca7421b6b94f8e02c44d9f1dbfa0bc45c9d Mon Sep 17 00:00:00 2001 From: lorikku Date: Sun, 21 Apr 2024 13:59:22 +0200 Subject: [PATCH 4/6] Updated docs to properly explain it only works on client components only --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b9a7509..d6fa5dc 100644 --- a/README.md +++ b/README.md @@ -85,11 +85,13 @@ export default function RootLayout({ children }) { } ``` -### Programmatic Control +### Programmatic Control (Client Components) -Have an async operation before an eventual route change? You might be interested in holy-loader's manual controls: +Have an async operation before an eventual route change? You might be interested in holy-loader's manual controls. These only work in client components! ```typescript +'use client'; + import { startHolyProgress, stopHolyProgress } from 'holy-loader'; try { From c242c3a7af369c6499e118071d70a2c0f1de6ba7 Mon Sep 17 00:00:00 2001 From: Lorik <56921718+lorikku@users.noreply.github.com> Date: Tue, 23 Apr 2024 10:12:30 +0200 Subject: [PATCH 5/6] Renamed start/stop holyProgress to holyLoader Co-authored-by: Tom Rumpf <35841182+tomcru@users.noreply.github.com> --- README.md | 8 ++++---- src/index.tsx | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d6fa5dc..65ac829 100644 --- a/README.md +++ b/README.md @@ -92,16 +92,16 @@ Have an async operation before an eventual route change? You might be interested ```typescript 'use client'; -import { startHolyProgress, stopHolyProgress } from 'holy-loader'; +import { startHolyLoader, stopHolyLoader } from 'holy-loader'; try { - startHolyProgress(); // Trigger the loader beforehand + startHolyLoader(); // Trigger the loader beforehand await signOut(); // Example async operation } catch (error) { - stopHolyProgress(); // Stop the loader on error + stopHolyLoader(); // Stop the loader on error // Handle the error } finally { - stopHolyProgress(); // Stop the loader after the operation, and potentially do something else + stopHolyLoader(); // Stop the loader after the operation, and potentially do something else /* OR */ router.push('/'); // Navigate to the desired route, which will automatically stop the loader } diff --git a/src/index.tsx b/src/index.tsx index 05b43ba..90c21f3 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -100,14 +100,14 @@ export const isSameHost = (currentUrl: string, newUrl: string): boolean => { /** * Dispatches the event to manually start the HolyLoader progress bar. */ -export const startHolyProgress = (): void => { +export const startHolyLoader = (): void => { document.dispatchEvent(new Event(START_HOLY_EVENT)); }; /** * Dispatches the event to manually stop the HolyLoader progress bar. */ -export const stopHolyProgress = (): void => { +export const stopHolyLoader = (): void => { document.dispatchEvent(new Event(STOP_HOLY_EVENT)); }; From a873138f9dcd2b726b085cf7abb3febf7f70a89f Mon Sep 17 00:00:00 2001 From: lorikku Date: Tue, 23 Apr 2024 11:06:14 +0200 Subject: [PATCH 6/6] Added check to prevent startTrickle from firing multiple times --- src/HolyProgress.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/HolyProgress.ts b/src/HolyProgress.ts index fc4de25..c546dda 100644 --- a/src/HolyProgress.ts +++ b/src/HolyProgress.ts @@ -184,15 +184,15 @@ export class HolyProgress { * @public * @returns {HolyProgress} The current instance for chaining methods. */ - public start = (): HolyProgress => { + public readonly start = (): HolyProgress => { if (this.status === null) { this.setTo(0); - } - this.startTrickle(); + this.startTrickle(); - if (this.settings.showSpinner === true) { - this.createSpinner(); + if (this.settings.showSpinner === true) { + this.createSpinner(); + } } return this; @@ -219,7 +219,7 @@ export class HolyProgress { * @public * @returns {HolyProgress} The current instance for chaining methods. */ - public complete = (): HolyProgress => this.setTo(1); + public readonly complete = (): HolyProgress => this.setTo(1); /** * Calculates an increment value based on the current status of the progress.