@tanem/react-nprogress 6.0.4 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -116
- package/dist/react-nprogress.cjs +119 -0
- package/dist/react-nprogress.cjs.map +1 -0
- package/dist/react-nprogress.d.cts +25 -0
- package/dist/react-nprogress.d.cts.map +1 -0
- package/dist/react-nprogress.d.mts +25 -0
- package/dist/react-nprogress.d.mts.map +1 -0
- package/dist/react-nprogress.mjs +117 -0
- package/dist/react-nprogress.mjs.map +1 -0
- package/package.json +50 -36
- package/src/NProgress.tsx +13 -0
- package/src/clamp.ts +5 -0
- package/src/createTimeout.ts +35 -0
- package/src/env.d.ts +0 -0
- package/src/increment.ts +17 -0
- package/src/index.tsx +3 -0
- package/src/types.ts +12 -0
- package/src/useNProgress.tsx +121 -0
- package/dist/NProgress.d.ts +0 -8
- package/dist/clamp.d.ts +0 -1
- package/dist/createQueue.d.ts +0 -7
- package/dist/createTimeout.d.ts +0 -4
- package/dist/increment.d.ts +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -7
- package/dist/react-nprogress.cjs.development.js +0 -299
- package/dist/react-nprogress.cjs.development.js.map +0 -1
- package/dist/react-nprogress.cjs.production.js +0 -2
- package/dist/react-nprogress.cjs.production.js.map +0 -1
- package/dist/react-nprogress.esm.js +0 -295
- package/dist/react-nprogress.esm.js.map +0 -1
- package/dist/react-nprogress.umd.development.js +0 -727
- package/dist/react-nprogress.umd.development.js.map +0 -1
- package/dist/react-nprogress.umd.production.js +0 -2
- package/dist/react-nprogress.umd.production.js.map +0 -1
- package/dist/types.d.ts +0 -6
- package/dist/useEffectOnce.d.ts +0 -2
- package/dist/useGetSetState.d.ts +0 -1
- package/dist/useNProgress.d.ts +0 -6
- package/dist/useUpdateEffect.d.ts +0 -2
- package/dist/withNProgress.d.ts +0 -7
package/package.json
CHANGED
|
@@ -1,40 +1,67 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanem/react-nprogress",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "A React primitive for building slim progress bars.",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": {
|
|
9
|
+
"types": "./dist/react-nprogress.d.mts",
|
|
10
|
+
"default": "./dist/react-nprogress.mjs"
|
|
11
|
+
},
|
|
12
|
+
"default": {
|
|
13
|
+
"types": "./dist/react-nprogress.d.cts",
|
|
14
|
+
"default": "./dist/react-nprogress.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"./package.json": "./package.json"
|
|
18
|
+
},
|
|
19
|
+
"main": "dist/react-nprogress.cjs",
|
|
20
|
+
"module": "dist/react-nprogress.mjs",
|
|
21
|
+
"types": "dist/react-nprogress.d.cts",
|
|
8
22
|
"sideEffects": false,
|
|
23
|
+
"size-limit": [
|
|
24
|
+
{
|
|
25
|
+
"name": "ESM bundle",
|
|
26
|
+
"path": "dist/react-nprogress.mjs",
|
|
27
|
+
"gzip": true,
|
|
28
|
+
"limit": "1.2 kB"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "CJS bundle",
|
|
32
|
+
"path": "dist/react-nprogress.cjs",
|
|
33
|
+
"gzip": true,
|
|
34
|
+
"limit": "1.3 kB"
|
|
35
|
+
}
|
|
36
|
+
],
|
|
9
37
|
"files": [
|
|
10
|
-
"dist"
|
|
38
|
+
"dist",
|
|
39
|
+
"src"
|
|
11
40
|
],
|
|
12
41
|
"scripts": {
|
|
13
42
|
"authors": "tanem-scripts authors > AUTHORS",
|
|
14
|
-
"build": "run-s clean
|
|
15
|
-
"bundle": "
|
|
43
|
+
"build": "run-s clean bundle",
|
|
44
|
+
"bundle": "tsdown",
|
|
16
45
|
"changelog": "tanem-scripts changelog -f v$npm_package_version > CHANGELOG.md",
|
|
17
|
-
"check:format": "prettier --list-different \"**/*.{js,ts,tsx}\"",
|
|
46
|
+
"check:format": "prettier --list-different \"**/*.{cjs,cts,js,mjs,mts,ts,tsx}\"",
|
|
18
47
|
"check:types": "tsc --noEmit",
|
|
19
48
|
"clean": "run-p clean:*",
|
|
20
|
-
"clean:compiled": "shx rm -rf compiled",
|
|
21
49
|
"clean:coverage": "shx rm -rf coverage",
|
|
22
|
-
"clean:dist": "shx rm -rf dist",
|
|
23
50
|
"clean:react": "node ./scripts/clean-react.js",
|
|
24
|
-
"
|
|
25
|
-
"format": "eslint . --fix && prettier --write \"**/*.{js,ts,tsx}\"",
|
|
51
|
+
"format": "eslint . --fix && prettier --write \"**/*.{cjs,cts,js,mjs,mts,ts,tsx}\"",
|
|
26
52
|
"lint": "eslint . --max-warnings=0",
|
|
27
|
-
"
|
|
53
|
+
"package:attw": "node ./scripts/attw.js",
|
|
54
|
+
"package:publint": "publint",
|
|
55
|
+
"postbuild": "run-s package:*",
|
|
28
56
|
"prepare": "npm run build",
|
|
29
57
|
"release": "tanem-scripts release",
|
|
30
|
-
"
|
|
58
|
+
"size": "size-limit",
|
|
59
|
+
"test": "run-s check:* lint build size test:*",
|
|
60
|
+
"test:bundles": "jest --config ./scripts/jest/config.bundles.js",
|
|
31
61
|
"test:cjs": "jest --config ./scripts/jest/config.cjs.js",
|
|
32
|
-
"test:
|
|
33
|
-
"test:es": "jest --config ./scripts/jest/config.es.js",
|
|
62
|
+
"test:es": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js --config ./scripts/jest/config.es.js",
|
|
34
63
|
"test:react": "node ./scripts/test-react.js",
|
|
35
64
|
"test:src": "jest --config ./scripts/jest/config.src.js",
|
|
36
|
-
"test:umd": "jest --config ./scripts/jest/config.umd.js",
|
|
37
|
-
"test:umdprod": "jest --config ./scripts/jest/config.umdprod.js",
|
|
38
65
|
"version": "run-s test changelog authors && git add ."
|
|
39
66
|
},
|
|
40
67
|
"repository": {
|
|
@@ -44,8 +71,6 @@
|
|
|
44
71
|
"keywords": [
|
|
45
72
|
"animation",
|
|
46
73
|
"component",
|
|
47
|
-
"higher-order-component",
|
|
48
|
-
"hoc",
|
|
49
74
|
"hook",
|
|
50
75
|
"hooks",
|
|
51
76
|
"javascript",
|
|
@@ -70,25 +95,12 @@
|
|
|
70
95
|
"overrides": {
|
|
71
96
|
"brace-expansion": "^5.0.8"
|
|
72
97
|
},
|
|
73
|
-
"dependencies": {
|
|
74
|
-
"@babel/runtime": "^7.28.6",
|
|
75
|
-
"hoist-non-react-statics": "^3.3.2"
|
|
76
|
-
},
|
|
77
98
|
"devDependencies": {
|
|
78
|
-
"@
|
|
79
|
-
"@babel/plugin-transform-runtime": "7.29.0",
|
|
80
|
-
"@babel/preset-env": "7.29.0",
|
|
81
|
-
"@babel/preset-react": "7.28.5",
|
|
82
|
-
"@babel/preset-typescript": "7.28.5",
|
|
99
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
83
100
|
"@eslint-react/eslint-plugin": "5.18.0",
|
|
84
101
|
"@eslint/js": "10.0.1",
|
|
85
|
-
"@
|
|
86
|
-
"@rollup/plugin-commonjs": "29.0.0",
|
|
87
|
-
"@rollup/plugin-node-resolve": "16.0.3",
|
|
88
|
-
"@rollup/plugin-replace": "6.0.3",
|
|
89
|
-
"@rollup/plugin-terser": "1.0.0",
|
|
102
|
+
"@size-limit/file": "13.0.2",
|
|
90
103
|
"@testing-library/react": "16.3.2",
|
|
91
|
-
"@types/hoist-non-react-statics": "3.3.7",
|
|
92
104
|
"@types/jest": "30.0.0",
|
|
93
105
|
"@types/mock-raf": "1.0.6",
|
|
94
106
|
"@types/node": "24.11.0",
|
|
@@ -105,12 +117,14 @@
|
|
|
105
117
|
"mock-raf": "1.0.1",
|
|
106
118
|
"npm-run-all2": "8.0.4",
|
|
107
119
|
"prettier": "3.8.1",
|
|
120
|
+
"publint": "0.3.22",
|
|
108
121
|
"react": "19.2.4",
|
|
109
122
|
"react-dom": "19.2.4",
|
|
110
|
-
"rollup": "4.59.0",
|
|
111
123
|
"shx": "0.4.0",
|
|
124
|
+
"size-limit": "13.0.2",
|
|
112
125
|
"tanem-scripts": "8.0.4",
|
|
113
126
|
"ts-jest": "29.4.6",
|
|
127
|
+
"tsdown": "0.22.14",
|
|
114
128
|
"typescript": "5.9.3",
|
|
115
129
|
"typescript-eslint": "8.56.1"
|
|
116
130
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FC, ReactElement } from 'react'
|
|
2
|
+
|
|
3
|
+
import type { NProgressOptions, NProgressState } from './types'
|
|
4
|
+
import { useNProgress } from './useNProgress'
|
|
5
|
+
|
|
6
|
+
type Props = NProgressOptions & {
|
|
7
|
+
children: (renderProps: NProgressState) => ReactElement
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const NProgress: FC<Props> = ({ children, ...restProps }: Props) => {
|
|
11
|
+
const renderProps = useNProgress(restProps)
|
|
12
|
+
return children(renderProps)
|
|
13
|
+
}
|
package/src/clamp.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Uses requestAnimationFrame rather than setTimeout for smoother animation
|
|
2
|
+
// timing. Note that rAF is throttled or paused in background tabs, so progress
|
|
3
|
+
// will stall when the tab is hidden and resume when it regains focus.
|
|
4
|
+
export const createTimeout = () => {
|
|
5
|
+
let handle: number | undefined
|
|
6
|
+
|
|
7
|
+
const cancel = (): void => {
|
|
8
|
+
if (handle !== undefined) {
|
|
9
|
+
window.cancelAnimationFrame(handle)
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const schedule = (callback: () => void, delay: number): void => {
|
|
14
|
+
cancel()
|
|
15
|
+
|
|
16
|
+
let deltaTime
|
|
17
|
+
let start: number | undefined
|
|
18
|
+
const frame: FrameRequestCallback = (time) => {
|
|
19
|
+
start = start || time
|
|
20
|
+
deltaTime = time - start
|
|
21
|
+
if (deltaTime > delay) {
|
|
22
|
+
callback()
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
handle = window.requestAnimationFrame(frame)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
handle = window.requestAnimationFrame(frame)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
cancel,
|
|
33
|
+
schedule,
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/env.d.ts
ADDED
|
File without changes
|
package/src/increment.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { clamp } from './clamp'
|
|
2
|
+
|
|
3
|
+
export const increment = (progress: number): number => {
|
|
4
|
+
let amount = 0
|
|
5
|
+
|
|
6
|
+
if (progress >= 0 && progress < 0.2) {
|
|
7
|
+
amount = 0.1
|
|
8
|
+
} else if (progress >= 0.2 && progress < 0.5) {
|
|
9
|
+
amount = 0.04
|
|
10
|
+
} else if (progress >= 0.5 && progress < 0.8) {
|
|
11
|
+
amount = 0.02
|
|
12
|
+
} else if (progress >= 0.8 && progress < 0.99) {
|
|
13
|
+
amount = 0.005
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return clamp(progress + amount, 0, 0.994)
|
|
17
|
+
}
|
package/src/index.tsx
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { useEffect, useReducer } from 'react'
|
|
2
|
+
|
|
3
|
+
import { clamp } from './clamp'
|
|
4
|
+
import { createTimeout } from './createTimeout'
|
|
5
|
+
import { increment } from './increment'
|
|
6
|
+
import type { NProgressOptions, NProgressState } from './types'
|
|
7
|
+
|
|
8
|
+
// A four-phase state machine. `idle` and `finished` both report
|
|
9
|
+
// `isFinished: true` and differ only in the progress they hold, so the phase,
|
|
10
|
+
// not `isFinished`, is what decides which transitions and timers apply.
|
|
11
|
+
type Phase = 'animating' | 'completing' | 'finished' | 'idle'
|
|
12
|
+
|
|
13
|
+
interface State {
|
|
14
|
+
phase: Phase
|
|
15
|
+
progress: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type Action =
|
|
19
|
+
| { minimum: number; type: 'start' }
|
|
20
|
+
| { minimum: number; type: 'trickle' }
|
|
21
|
+
| { type: 'complete' }
|
|
22
|
+
| { type: 'finish' }
|
|
23
|
+
|
|
24
|
+
const initialState: State = {
|
|
25
|
+
phase: 'idle',
|
|
26
|
+
progress: 0,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const reducer = (state: State, action: Action): State => {
|
|
30
|
+
switch (action.type) {
|
|
31
|
+
case 'complete':
|
|
32
|
+
// Unlike the original nprogress `done()`, completion does not include a
|
|
33
|
+
// random progress jump before animating to 1. This keeps the primitive
|
|
34
|
+
// predictable; consumers can set a higher progress value before stopping
|
|
35
|
+
// the animation if they want that effect.
|
|
36
|
+
//
|
|
37
|
+
// Ignored unless an animation is actually running, which is what makes a
|
|
38
|
+
// StrictMode double-mount a no-op rather than a spurious completion.
|
|
39
|
+
return state.phase === 'animating'
|
|
40
|
+
? { phase: 'completing', progress: 1 }
|
|
41
|
+
: state
|
|
42
|
+
|
|
43
|
+
case 'finish':
|
|
44
|
+
return { phase: 'finished', progress: 1 }
|
|
45
|
+
|
|
46
|
+
case 'start':
|
|
47
|
+
// The original nprogress calls set(0) - which clamps to `minimum` -
|
|
48
|
+
// before the first trickle. Here, the first trickle starts from
|
|
49
|
+
// increment(0) = 0.1, so the bar appears at max(0.1, minimum) rather
|
|
50
|
+
// than exactly `minimum`. The difference is negligible at the default
|
|
51
|
+
// minimum of 0.08.
|
|
52
|
+
//
|
|
53
|
+
// Guarded the same way as `complete`, and for the same reason: a repeat
|
|
54
|
+
// dispatch against a running animation must not rewind the bar. That
|
|
55
|
+
// happens whenever `minimum` changes mid-animation, as well as on a
|
|
56
|
+
// StrictMode double-mount.
|
|
57
|
+
return state.phase === 'animating'
|
|
58
|
+
? state
|
|
59
|
+
: {
|
|
60
|
+
phase: 'animating',
|
|
61
|
+
progress: clamp(increment(0), action.minimum, 1),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
case 'trickle':
|
|
65
|
+
return {
|
|
66
|
+
...state,
|
|
67
|
+
progress: clamp(increment(state.progress), action.minimum, 1),
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const useNProgress = ({
|
|
73
|
+
animationDuration = 200,
|
|
74
|
+
incrementDuration = 200,
|
|
75
|
+
isAnimating = false,
|
|
76
|
+
minimum = 0.08,
|
|
77
|
+
}: NProgressOptions = {}): NProgressState => {
|
|
78
|
+
const [{ phase, progress }, dispatch] = useReducer(reducer, initialState)
|
|
79
|
+
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
dispatch(isAnimating ? { minimum, type: 'start' } : { type: 'complete' })
|
|
82
|
+
}, [isAnimating, minimum])
|
|
83
|
+
|
|
84
|
+
// A timer per running phase, rather than one effect branching over both.
|
|
85
|
+
// Each then depends only on the options its own phase reads, so changing an
|
|
86
|
+
// option the running phase ignores cannot cancel its timer. Both are keyed
|
|
87
|
+
// on the phase rather than on progress, so trickling does not tear down and
|
|
88
|
+
// recreate the timer mid-animation.
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (phase !== 'animating') {
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const timeout = createTimeout()
|
|
95
|
+
|
|
96
|
+
const trickle = () => {
|
|
97
|
+
dispatch({ minimum, type: 'trickle' })
|
|
98
|
+
timeout.schedule(trickle, incrementDuration)
|
|
99
|
+
}
|
|
100
|
+
timeout.schedule(trickle, incrementDuration)
|
|
101
|
+
|
|
102
|
+
return () => timeout.cancel()
|
|
103
|
+
}, [incrementDuration, minimum, phase])
|
|
104
|
+
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
if (phase !== 'completing') {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const timeout = createTimeout()
|
|
111
|
+
timeout.schedule(() => dispatch({ type: 'finish' }), animationDuration)
|
|
112
|
+
|
|
113
|
+
return () => timeout.cancel()
|
|
114
|
+
}, [animationDuration, phase])
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
animationDuration,
|
|
118
|
+
isFinished: phase === 'finished' || phase === 'idle',
|
|
119
|
+
progress,
|
|
120
|
+
}
|
|
121
|
+
}
|
package/dist/NProgress.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { FC, ReactElement } from 'react';
|
|
2
|
-
import type { Options } from './types';
|
|
3
|
-
import { useNProgress } from './useNProgress';
|
|
4
|
-
type Props = Options & {
|
|
5
|
-
children: (renderProps: ReturnType<typeof useNProgress>) => ReactElement;
|
|
6
|
-
};
|
|
7
|
-
export declare const NProgress: FC<Props>;
|
|
8
|
-
export {};
|
package/dist/clamp.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const clamp: (num: number, lower: number, upper: number) => number;
|
package/dist/createQueue.d.ts
DELETED
package/dist/createTimeout.d.ts
DELETED
package/dist/increment.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const increment: (progress: number) => number;
|
package/dist/index.d.ts
DELETED