Skip to content

Commit

Permalink
breaking: moved to v1.0.0 + new features to ease setup
Browse files Browse the repository at this point in the history
  • Loading branch information
ndungtse committed Aug 1, 2023
1 parent 656edac commit 56175bc
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 109 deletions.
27 changes: 7 additions & 20 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
{
"plugins": [
"@typescript-eslint"
],
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
],
"eol-last": [
"error",
"always"
],
"quotes": ["error", "single"],
"semi": ["error", "always"],
"eol-last": ["error", "always"],
"comma-dangle": [
"error",
{
Expand All @@ -30,10 +19,7 @@
"functions": "never"
}
],
"arrow-parens": [
"error",
"always"
],
"arrow-parens": ["error", "always"],
"no-trailing-spaces": [
"error",
{
Expand All @@ -46,6 +32,7 @@
"no-unused-vars": "off",
"node/no-missing-require": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-explicit-any": "off",
"no-console": "warn"
}
}
}
66 changes: 32 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,26 @@ npm i next13-progressbar

## How to use?

After installing the package, create `providers.tsx` file in app directory to handle contexts and mark it `use client`. see [contexts in app dir](https://nextjs.org/docs/getting-started/react-essentials#context) and import `NProvider;
⚠️ **_Note_** : This docs are for versions `>=1.0.0` only. For the older versions check branch versions's Readme.

After installing the package, create `providers.tsx` file in app directory to handle contexts and mark it `use client`. see [contexts in app dir](https://nextjs.org/docs/getting-started/react-essentials#context) and import `Next13ProgressBar;

```jsx
'use client';
import React from 'react';
import { NProvider } from 'next13-progressbar';
import { Next13ProgressBar } from 'next13-progressbar';

const Providers = ({ children }: { children: React.ReactNode }) => {
return <NProvider color="#fff">{children}</NProvider>;
return (
<>
{children}
return (<>
{children}
<Next13ProgressBar height="4px" color="#0A2FFF" options={{ showSpinner: true }} showOnShallow />
</>
);
</>
);
};

export default Providers;
Expand All @@ -48,41 +59,32 @@ By default all `a` tags are handled by `next/link` so you don't need to do anyth

```jsx
import Link from 'next/link';
import { useRouter } from 'next13-progressbar';

export default function NavBar() {
const NavBar = () => {
const router = useRouter();
return (
<div className="navbar">
<Link href={'/'}>Home</Link>
<Link href={'/about'}>About</Link>
<Link href={'/contact'}>Contact</Link>
<button onClick={() => router.push('/button-link')}>ButtonLink</button>
</div>
);
}
```

But if you want to use `Link` component from `next13-progressbar` you can do it by importing it from `next13-progressbar` and use it as you would use `next/link` component.

```jsx
'use client';
import { Link } from 'next13-progressbar';

// use it as you would use next/link
};
```

And you are done. You can now customize you progress bar as you need!

⚠️ Note: You must use `next13-progressbar` `Link` component inside client components only.

### Default Config

If no props are passed to `<NProvider />`, below is the default configuration applied.
If no props are passed to `<Next13ProgressBar />`, below is the default configuration applied.

```jsx
<NProvider color="#29D" startPosition={0.3} stopDelayMs={200} height={3} showOnShallow={true} />
<Next13ProgressBar color="#29D" startPosition={0.3} stopDelayMs={200} height={3} showOnShallow={true} />
```

- `color`: to change the default color of progressbar. You can also use `rgb(,,)` or `rgba(,,,)`.
- `startPosition`: to set the default starting position : `0.3 = 30%`.
- `delay`: time for delay to start progressbar in `ms`.
- `stopDelayMs`: time for delay to stop progressbar in `ms`.
- `height`: height of progressbar in `px`.
- `showOnShallow`: You can choose whether you want the progressbar to be displayed if you're using shallow routing. It takes a boolean. Learn more about shallow routing [in Next.js docs](https://nextjs.org/docs/routing/shallow-routing).
Expand All @@ -94,30 +96,26 @@ If no props are passed to `<NProvider />`, below is the default configuration ap
We use internal css in this package. If you are using csp, you can add nonce to the `<style>` tag by providing `nonce` prop to `<NProvider />` component.

```jsx
<NProvider nonce="my-nonce" />
<Next13ProgressBar nonce="my-nonce" />
```

#### Custom CSS

You can use `transformCSS` prop to pass custom css.
**Note:** You must return a `JSX.Element` from the function.
You can pass custom css to the progressbar by using `style` prop.

```jsx
<NProvider
transformCSS={(css) => {
// css is the default css string. You can modify it and return it or return your own css.
return <style>{css}</style>;
}}
<Next13ProgressBar
style={`
#nprogress {
pointer-events: none;
}
`}
/>
```

#### Other Configs

You can use [other configurations](https://github.com/rstacruz/nprogress#configuration) which NProgress provides by adding a JSON in `options` props.
### Older Versions

```jsx
<NProvider options={{ easing: 'ease', speed: 500 }} />
```
Check Branches with `v` prefix for older docs of the package.

## Contributing

Expand Down
7 changes: 7 additions & 0 deletions example/src/app/button-link/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React from 'react';

const ButtonLink = () => {
return <div>ButtonLink</div>;
};

export default ButtonLink;
11 changes: 8 additions & 3 deletions example/src/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
'use client';
import React from 'react';
import { NProvider } from 'next13-progressbar';

import { Next13ProgressBar } from '../../../dist';

const Providers = ({ children }: { children: React.ReactNode }) => {
return <NProvider color="#fff">{children}</NProvider>;
return (
<>
{children}
<Next13ProgressBar height="4px" color="#0A2FFF" options={{ showSpinner: true }} showOnShallow />
</>
);
};

export default Providers;
3 changes: 3 additions & 0 deletions example/src/components/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
'use client';
import React from 'react';
import Link from 'next/link';
import { useRouter } from '../../../dist';

const NavBar = () => {
const router = useRouter();
return (
<div className="navbar">
<Link href={'/'}>Home</Link>
<Link href={'/about'}>About</Link>
<Link href={'/contact'}>Contact</Link>
<button onClick={() => router.push('/button-link')}>ButtonLink</button>
</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next13-progressbar",
"version": "0.1.2",
"version": "1.0.0",
"description": "A ProgressBar for next.js 13 with app directory ",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
159 changes: 159 additions & 0 deletions src/AppProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import React, { useEffect } from 'react';
import NProgress from 'nprogress';
import { usePathname, useSearchParams, useRouter as useNextRouter } from 'next/navigation';
import { NavigateOptions } from 'next/dist/shared/lib/app-router-context';
import { Next13ProgressProps } from '.';

type PushStateInput = [data: any, unused: string, url?: string | URL | null | undefined];

export const Next13ProgressBar = React.memo(
({ color = '#0A2FFF', height = '2px', options, showOnShallow = false, delay = 0, style }: Next13ProgressProps) => {
const styles = (
<style>
{style ||
`
#nprogress {
pointer-events: none;
}
#nprogress .bar {
background: ${color};
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: ${height};
}
/* Fancy blur effect */
#nprogress .peg {
display: block;
position: absolute;
right: 0px;
width: 100px;
height: 100%;
box-shadow: 0 0 10px ${color}, 0 0 5px ${color};
opacity: 1.0;
-webkit-transform: rotate(3deg) translate(0px, -4px);
-ms-transform: rotate(3deg) translate(0px, -4px);
transform: rotate(3deg) translate(0px, -4px);
}
/* Remove these to get rid of the spinner */
#nprogress .spinner {
display: block;
position: fixed;
z-index: 1031;
top: 15px;
right: 15px;
}
#nprogress .spinner-icon {
width: 18px;
height: 18px;
box-sizing: border-box;
border: solid 2px transparent;
border-top-color: ${color};
border-left-color: ${color};
border-radius: 50%;
-webkit-animation: nprogress-spinner 400ms linear infinite;
animation: nprogress-spinner 400ms linear infinite;
}
.nprogress-custom-parent {
overflow: hidden;
position: relative;
}
.nprogress-custom-parent #nprogress .spinner,
.nprogress-custom-parent #nprogress .bar {
position: absolute;
}
@-webkit-keyframes nprogress-spinner {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes nprogress-spinner {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
`}
</style>
);

NProgress.configure(options || {});

const pathname = usePathname();
const searchParams = useSearchParams();

useEffect(() => {
NProgress.done();
}, [pathname, searchParams]);

useEffect(() => {
let timer: NodeJS.Timeout;

const startProgress = () => {
timer = setTimeout(NProgress.start, delay);
};

const stopProgress = () => {
clearTimeout(timer);
NProgress.done();
};

const handleAnchorClick = (event: MouseEvent) => {
const anchorElement = event.currentTarget as HTMLAnchorElement;

// Skip anchors with target="_blank"
if (anchorElement.target === '_blank') return;

const targetUrl = new URL(anchorElement.href);
const currentUrl = new URL(location.href);

if (showOnShallow && targetUrl?.href === currentUrl?.href) return;
if (targetUrl?.href === currentUrl?.href) return;

startProgress();
};

const handleMutation: MutationCallback = () => {
const anchorElements = document.querySelectorAll('a');
// Skip anchors with target="_blank" and anchors without href
const validAnchorELes = Array.from(anchorElements).filter((anchor) => anchor.href);
validAnchorELes.forEach((anchor) => anchor.addEventListener('click', handleAnchorClick));
};

const mutationObserver = new MutationObserver(handleMutation);
mutationObserver.observe(document, { childList: true, subtree: true });

window.history.pushState = new Proxy(window.history.pushState, {
apply: (target, thisArg, argArray: PushStateInput) => {
stopProgress();
return target.apply(thisArg, argArray);
},
});
}, []);

return styles;
},
() => true
);

export function useRouter() {
const router = useNextRouter();

function push(href: string, options?: NavigateOptions) {
NProgress.start();
return router.push(href, options);
}

return { ...router, push };
}
Loading

0 comments on commit 56175bc

Please sign in to comment.