@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.
Files changed (41) hide show
  1. package/README.md +78 -116
  2. package/dist/react-nprogress.cjs +119 -0
  3. package/dist/react-nprogress.cjs.map +1 -0
  4. package/dist/react-nprogress.d.cts +25 -0
  5. package/dist/react-nprogress.d.cts.map +1 -0
  6. package/dist/react-nprogress.d.mts +25 -0
  7. package/dist/react-nprogress.d.mts.map +1 -0
  8. package/dist/react-nprogress.mjs +117 -0
  9. package/dist/react-nprogress.mjs.map +1 -0
  10. package/package.json +50 -36
  11. package/src/NProgress.tsx +13 -0
  12. package/src/clamp.ts +5 -0
  13. package/src/createTimeout.ts +35 -0
  14. package/src/env.d.ts +0 -0
  15. package/src/increment.ts +17 -0
  16. package/src/index.tsx +3 -0
  17. package/src/types.ts +12 -0
  18. package/src/useNProgress.tsx +121 -0
  19. package/dist/NProgress.d.ts +0 -8
  20. package/dist/clamp.d.ts +0 -1
  21. package/dist/createQueue.d.ts +0 -7
  22. package/dist/createTimeout.d.ts +0 -4
  23. package/dist/increment.d.ts +0 -1
  24. package/dist/index.d.ts +0 -3
  25. package/dist/index.js +0 -7
  26. package/dist/react-nprogress.cjs.development.js +0 -299
  27. package/dist/react-nprogress.cjs.development.js.map +0 -1
  28. package/dist/react-nprogress.cjs.production.js +0 -2
  29. package/dist/react-nprogress.cjs.production.js.map +0 -1
  30. package/dist/react-nprogress.esm.js +0 -295
  31. package/dist/react-nprogress.esm.js.map +0 -1
  32. package/dist/react-nprogress.umd.development.js +0 -727
  33. package/dist/react-nprogress.umd.development.js.map +0 -1
  34. package/dist/react-nprogress.umd.production.js +0 -2
  35. package/dist/react-nprogress.umd.production.js.map +0 -1
  36. package/dist/types.d.ts +0 -6
  37. package/dist/useEffectOnce.d.ts +0 -2
  38. package/dist/useGetSetState.d.ts +0 -1
  39. package/dist/useNProgress.d.ts +0 -6
  40. package/dist/useUpdateEffect.d.ts +0 -2
  41. 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": "6.0.4",
3
+ "version": "7.0.0",
4
4
  "description": "A React primitive for building slim progress bars.",
5
- "main": "dist/index.js",
6
- "module": "dist/react-nprogress.esm.js",
7
- "types": "dist/index.d.ts",
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 compile bundle",
15
- "bundle": "rollup -c",
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
- "compile": "tsc -p tsconfig.base.json",
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
- "postbundle": "npm run clean:compiled && shx cp ./index.js ./dist/index.js",
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
- "test": "run-s check:* lint build test:*",
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:cjsprod": "jest --config ./scripts/jest/config.cjsprod.js",
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
- "@babel/core": "7.29.7",
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
- "@rollup/plugin-babel": "6.1.0",
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,5 @@
1
+ export const clamp = (num: number, lower: number, upper: number): number => {
2
+ num = num <= upper ? num : upper
3
+ num = num >= lower ? num : lower
4
+ return num
5
+ }
@@ -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
@@ -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
@@ -0,0 +1,3 @@
1
+ export * from './NProgress'
2
+ export type { NProgressOptions, NProgressState } from './types'
3
+ export * from './useNProgress'
package/src/types.ts ADDED
@@ -0,0 +1,12 @@
1
+ export interface NProgressOptions {
2
+ animationDuration?: number
3
+ incrementDuration?: number
4
+ isAnimating?: boolean
5
+ minimum?: number
6
+ }
7
+
8
+ export interface NProgressState {
9
+ animationDuration: number
10
+ isFinished: boolean
11
+ progress: number
12
+ }
@@ -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
+ }
@@ -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;
@@ -1,7 +0,0 @@
1
- type Next = () => void;
2
- type Callback = (next: Next) => void;
3
- export declare const createQueue: () => {
4
- clear: () => void;
5
- enqueue: (cb: Callback) => void;
6
- };
7
- export {};
@@ -1,4 +0,0 @@
1
- export declare const createTimeout: () => {
2
- cancel: () => void;
3
- schedule: (callback: () => void, delay: number) => void;
4
- };
@@ -1 +0,0 @@
1
- export declare const increment: (progress: number) => number;
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './NProgress';
2
- export * from './useNProgress';
3
- export * from './withNProgress';
package/dist/index.js DELETED
@@ -1,7 +0,0 @@
1
- 'use strict'
2
-
3
- if (process.env.NODE_ENV === 'production') {
4
- module.exports = require('./react-nprogress.cjs.production.js')
5
- } else {
6
- module.exports = require('./react-nprogress.cjs.development.js')
7
- }