@tanem/react-nprogress 6.0.4 → 7.1.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 +114 -108
  2. package/dist/react-nprogress.cjs +124 -0
  3. package/dist/react-nprogress.cjs.map +1 -0
  4. package/dist/react-nprogress.d.cts +26 -0
  5. package/dist/react-nprogress.d.cts.map +1 -0
  6. package/dist/react-nprogress.d.mts +26 -0
  7. package/dist/react-nprogress.d.mts.map +1 -0
  8. package/dist/react-nprogress.mjs +122 -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 +13 -0
  18. package/src/useNProgress.tsx +137 -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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-nprogress.mjs","names":["defaultIncrement","increment"],"sources":["../src/clamp.ts","../src/createTimeout.ts","../src/increment.ts","../src/useNProgress.tsx","../src/NProgress.tsx"],"sourcesContent":["export const clamp = (num: number, lower: number, upper: number): number => {\n num = num <= upper ? num : upper\n num = num >= lower ? num : lower\n return num\n}\n","// Uses requestAnimationFrame rather than setTimeout for smoother animation\n// timing. Note that rAF is throttled or paused in background tabs, so progress\n// will stall when the tab is hidden and resume when it regains focus.\nexport const createTimeout = () => {\n let handle: number | undefined\n\n const cancel = (): void => {\n if (handle !== undefined) {\n window.cancelAnimationFrame(handle)\n }\n }\n\n const schedule = (callback: () => void, delay: number): void => {\n cancel()\n\n let deltaTime\n let start: number | undefined\n const frame: FrameRequestCallback = (time) => {\n start = start || time\n deltaTime = time - start\n if (deltaTime > delay) {\n callback()\n return\n }\n handle = window.requestAnimationFrame(frame)\n }\n\n handle = window.requestAnimationFrame(frame)\n }\n\n return {\n cancel,\n schedule,\n }\n}\n","import { clamp } from './clamp'\n\nexport const increment = (progress: number): number => {\n let amount = 0\n\n if (progress >= 0 && progress < 0.2) {\n amount = 0.1\n } else if (progress >= 0.2 && progress < 0.5) {\n amount = 0.04\n } else if (progress >= 0.5 && progress < 0.8) {\n amount = 0.02\n } else if (progress >= 0.8 && progress < 0.99) {\n amount = 0.005\n }\n\n return clamp(progress + amount, 0, 0.994)\n}\n","import { useEffect, useReducer, useRef } from 'react'\n\nimport { clamp } from './clamp'\nimport { createTimeout } from './createTimeout'\nimport { increment as defaultIncrement } from './increment'\nimport type { NProgressOptions, NProgressState } from './types'\n\n// A four-phase state machine. `idle` and `finished` both report\n// `isFinished: true` and differ only in the progress they hold, so the phase,\n// not `isFinished`, is what decides which transitions and timers apply.\ntype Phase = 'animating' | 'completing' | 'finished' | 'idle'\n\ninterface State {\n phase: Phase\n progress: number\n}\n\ntype Action =\n | {\n increment: (progress: number) => number\n minimum: number\n type: 'trickle'\n }\n | { minimum: number; type: 'start' }\n | { type: 'complete' }\n | { type: 'finish' }\n\nconst initialState: State = {\n phase: 'idle',\n progress: 0,\n}\n\nconst reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case 'complete':\n // The original nprogress `done()` computes a random progress jump before\n // animating to 1, but its queue runs both steps in the same tick, so the\n // jump's CSS is overwritten before paint and never renders. Omitting the\n // jump changes nothing visually.\n //\n // Ignored unless an animation is actually running, which is what makes a\n // StrictMode double-mount a no-op rather than a spurious completion.\n return state.phase === 'animating'\n ? { phase: 'completing', progress: 1 }\n : state\n\n case 'finish':\n return { phase: 'finished', progress: 1 }\n\n case 'start':\n // Matches the original nprogress `start()`, which calls set(0) and so\n // paints first at `minimum` before any trickle runs.\n //\n // Guarded the same way as `complete`, and for the same reason: a repeat\n // dispatch against a running animation must not rewind the bar. That\n // happens whenever `minimum` changes mid-animation, as well as on a\n // StrictMode double-mount.\n return state.phase === 'animating'\n ? state\n : {\n phase: 'animating',\n progress: clamp(0, action.minimum, 1),\n }\n\n case 'trickle':\n // Clamped here rather than trusted from the increment function, so a\n // custom one cannot take the bar outside the documented range. Stopping\n // short of 1 is that function's own business: 1 is what completion\n // means.\n return {\n ...state,\n progress: clamp(action.increment(state.progress), action.minimum, 1),\n }\n }\n}\n\nexport const useNProgress = ({\n animationDuration = 200,\n increment = defaultIncrement,\n incrementDuration = 200,\n isAnimating = false,\n minimum = 0.08,\n}: NProgressOptions = {}): NProgressState => {\n const [{ phase, progress }, dispatch] = useReducer(reducer, initialState)\n\n // Held in a ref so the trickle timer can read the latest increment function\n // without listing it as a dependency. Consumers commonly pass an inline\n // function, whose identity changes every render; depending on it directly\n // would cancel and recreate the timer each time, and a render loop faster\n // than `incrementDuration` would stop the bar advancing altogether.\n const incrementRef = useRef(increment)\n useEffect(() => {\n incrementRef.current = increment\n })\n\n useEffect(() => {\n dispatch(isAnimating ? { minimum, type: 'start' } : { type: 'complete' })\n }, [isAnimating, minimum])\n\n // A timer per running phase, rather than one effect branching over both.\n // Each then depends only on the options its own phase reads, so changing an\n // option the running phase ignores cannot cancel its timer. Both are keyed\n // on the phase rather than on progress, so trickling does not tear down and\n // recreate the timer mid-animation.\n useEffect(() => {\n if (phase !== 'animating') {\n return\n }\n\n const timeout = createTimeout()\n\n const trickle = () => {\n dispatch({ increment: incrementRef.current, minimum, type: 'trickle' })\n timeout.schedule(trickle, incrementDuration)\n }\n timeout.schedule(trickle, incrementDuration)\n\n return () => timeout.cancel()\n }, [incrementDuration, minimum, phase])\n\n useEffect(() => {\n if (phase !== 'completing') {\n return\n }\n\n const timeout = createTimeout()\n timeout.schedule(() => dispatch({ type: 'finish' }), animationDuration)\n\n return () => timeout.cancel()\n }, [animationDuration, phase])\n\n return {\n animationDuration,\n isFinished: phase === 'finished' || phase === 'idle',\n progress,\n }\n}\n","import type { FC, ReactElement } from 'react'\n\nimport type { NProgressOptions, NProgressState } from './types'\nimport { useNProgress } from './useNProgress'\n\ntype Props = NProgressOptions & {\n children: (renderProps: NProgressState) => ReactElement\n}\n\nexport const NProgress: FC<Props> = ({ children, ...restProps }: Props) => {\n const renderProps = useNProgress(restProps)\n return children(renderProps)\n}\n"],"mappings":";;;AAAA,MAAa,SAAS,KAAa,OAAe,UAA0B;CAC1E,MAAM,OAAO,QAAQ,MAAM;CAC3B,MAAM,OAAO,QAAQ,MAAM;CAC3B,OAAO;AACT;;;ACDA,MAAa,sBAAsB;CACjC,IAAI;CAEJ,MAAM,eAAqB;EACzB,IAAI,WAAW,KAAA,GACb,OAAO,qBAAqB,MAAM;CAEtC;CAEA,MAAM,YAAY,UAAsB,UAAwB;EAC9D,OAAO;EAEP,IAAI;EACJ,IAAI;EACJ,MAAM,SAA+B,SAAS;GAC5C,QAAQ,SAAS;GACjB,YAAY,OAAO;GACnB,IAAI,YAAY,OAAO;IACrB,SAAS;IACT;GACF;GACA,SAAS,OAAO,sBAAsB,KAAK;EAC7C;EAEA,SAAS,OAAO,sBAAsB,KAAK;CAC7C;CAEA,OAAO;EACL;EACA;CACF;AACF;;;AChCA,MAAa,aAAa,aAA6B;CACrD,IAAI,SAAS;CAEb,IAAI,YAAY,KAAK,WAAW,IAC9B,SAAS;MACJ,IAAI,YAAY,MAAO,WAAW,IACvC,SAAS;MACJ,IAAI,YAAY,MAAO,WAAW,IACvC,SAAS;MACJ,IAAI,YAAY,MAAO,WAAW,KACvC,SAAS;CAGX,OAAO,MAAM,WAAW,QAAQ,GAAG,IAAK;AAC1C;;;ACWA,MAAM,eAAsB;CAC1B,OAAO;CACP,UAAU;AACZ;AAEA,MAAM,WAAW,OAAc,WAA0B;CACvD,QAAQ,OAAO,MAAf;EACE,KAAK,YAQH,OAAO,MAAM,UAAU,cACnB;GAAE,OAAO;GAAc,UAAU;EAAE,IACnC;EAEN,KAAK,UACH,OAAO;GAAE,OAAO;GAAY,UAAU;EAAE;EAE1C,KAAK,SAQH,OAAO,MAAM,UAAU,cACnB,QACA;GACE,OAAO;GACP,UAAU,MAAM,GAAG,OAAO,SAAS,CAAC;EACtC;EAEN,KAAK,WAKH,OAAO;GACL,GAAG;GACH,UAAU,MAAM,OAAO,UAAU,MAAM,QAAQ,GAAG,OAAO,SAAS,CAAC;EACrE;CACJ;AACF;AAEA,MAAa,gBAAgB,EAC3B,oBAAoB,KACpB,WAAA,cAAYA,WACZ,oBAAoB,KACpB,cAAc,OACd,UAAU,QACU,CAAC,MAAsB;CAC3C,MAAM,CAAC,EAAE,OAAO,YAAY,YAAY,WAAW,SAAS,YAAY;CAOxE,MAAM,eAAe,OAAOC,WAAS;CACrC,gBAAgB;EACd,aAAa,UAAUA;CACzB,CAAC;CAED,gBAAgB;EACd,SAAS,cAAc;GAAE;GAAS,MAAM;EAAQ,IAAI,EAAE,MAAM,WAAW,CAAC;CAC1E,GAAG,CAAC,aAAa,OAAO,CAAC;CAOzB,gBAAgB;EACd,IAAI,UAAU,aACZ;EAGF,MAAM,UAAU,cAAc;EAE9B,MAAM,gBAAgB;GACpB,SAAS;IAAE,WAAW,aAAa;IAAS;IAAS,MAAM;GAAU,CAAC;GACtE,QAAQ,SAAS,SAAS,iBAAiB;EAC7C;EACA,QAAQ,SAAS,SAAS,iBAAiB;EAE3C,aAAa,QAAQ,OAAO;CAC9B,GAAG;EAAC;EAAmB;EAAS;CAAK,CAAC;CAEtC,gBAAgB;EACd,IAAI,UAAU,cACZ;EAGF,MAAM,UAAU,cAAc;EAC9B,QAAQ,eAAe,SAAS,EAAE,MAAM,SAAS,CAAC,GAAG,iBAAiB;EAEtE,aAAa,QAAQ,OAAO;CAC9B,GAAG,CAAC,mBAAmB,KAAK,CAAC;CAE7B,OAAO;EACL;EACA,YAAY,UAAU,cAAc,UAAU;EAC9C;CACF;AACF;;;AC/HA,MAAa,aAAwB,EAAE,UAAU,GAAG,gBAAuB;CAEzE,OAAO,SADa,aAAa,SACP,CAAC;AAC7B"}
package/package.json CHANGED
@@ -1,40 +1,67 @@
1
1
  {
2
2
  "name": "@tanem/react-nprogress",
3
- "version": "6.0.4",
3
+ "version": "7.1.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,13 @@
1
+ export interface NProgressOptions {
2
+ animationDuration?: number
3
+ increment?: (progress: number) => number
4
+ incrementDuration?: number
5
+ isAnimating?: boolean
6
+ minimum?: number
7
+ }
8
+
9
+ export interface NProgressState {
10
+ animationDuration: number
11
+ isFinished: boolean
12
+ progress: number
13
+ }
@@ -0,0 +1,137 @@
1
+ import { useEffect, useReducer, useRef } from 'react'
2
+
3
+ import { clamp } from './clamp'
4
+ import { createTimeout } from './createTimeout'
5
+ import { increment as defaultIncrement } 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
+ | {
20
+ increment: (progress: number) => number
21
+ minimum: number
22
+ type: 'trickle'
23
+ }
24
+ | { minimum: number; type: 'start' }
25
+ | { type: 'complete' }
26
+ | { type: 'finish' }
27
+
28
+ const initialState: State = {
29
+ phase: 'idle',
30
+ progress: 0,
31
+ }
32
+
33
+ const reducer = (state: State, action: Action): State => {
34
+ switch (action.type) {
35
+ case 'complete':
36
+ // The original nprogress `done()` computes a random progress jump before
37
+ // animating to 1, but its queue runs both steps in the same tick, so the
38
+ // jump's CSS is overwritten before paint and never renders. Omitting the
39
+ // jump changes nothing visually.
40
+ //
41
+ // Ignored unless an animation is actually running, which is what makes a
42
+ // StrictMode double-mount a no-op rather than a spurious completion.
43
+ return state.phase === 'animating'
44
+ ? { phase: 'completing', progress: 1 }
45
+ : state
46
+
47
+ case 'finish':
48
+ return { phase: 'finished', progress: 1 }
49
+
50
+ case 'start':
51
+ // Matches the original nprogress `start()`, which calls set(0) and so
52
+ // paints first at `minimum` before any trickle runs.
53
+ //
54
+ // Guarded the same way as `complete`, and for the same reason: a repeat
55
+ // dispatch against a running animation must not rewind the bar. That
56
+ // happens whenever `minimum` changes mid-animation, as well as on a
57
+ // StrictMode double-mount.
58
+ return state.phase === 'animating'
59
+ ? state
60
+ : {
61
+ phase: 'animating',
62
+ progress: clamp(0, action.minimum, 1),
63
+ }
64
+
65
+ case 'trickle':
66
+ // Clamped here rather than trusted from the increment function, so a
67
+ // custom one cannot take the bar outside the documented range. Stopping
68
+ // short of 1 is that function's own business: 1 is what completion
69
+ // means.
70
+ return {
71
+ ...state,
72
+ progress: clamp(action.increment(state.progress), action.minimum, 1),
73
+ }
74
+ }
75
+ }
76
+
77
+ export const useNProgress = ({
78
+ animationDuration = 200,
79
+ increment = defaultIncrement,
80
+ incrementDuration = 200,
81
+ isAnimating = false,
82
+ minimum = 0.08,
83
+ }: NProgressOptions = {}): NProgressState => {
84
+ const [{ phase, progress }, dispatch] = useReducer(reducer, initialState)
85
+
86
+ // Held in a ref so the trickle timer can read the latest increment function
87
+ // without listing it as a dependency. Consumers commonly pass an inline
88
+ // function, whose identity changes every render; depending on it directly
89
+ // would cancel and recreate the timer each time, and a render loop faster
90
+ // than `incrementDuration` would stop the bar advancing altogether.
91
+ const incrementRef = useRef(increment)
92
+ useEffect(() => {
93
+ incrementRef.current = increment
94
+ })
95
+
96
+ useEffect(() => {
97
+ dispatch(isAnimating ? { minimum, type: 'start' } : { type: 'complete' })
98
+ }, [isAnimating, minimum])
99
+
100
+ // A timer per running phase, rather than one effect branching over both.
101
+ // Each then depends only on the options its own phase reads, so changing an
102
+ // option the running phase ignores cannot cancel its timer. Both are keyed
103
+ // on the phase rather than on progress, so trickling does not tear down and
104
+ // recreate the timer mid-animation.
105
+ useEffect(() => {
106
+ if (phase !== 'animating') {
107
+ return
108
+ }
109
+
110
+ const timeout = createTimeout()
111
+
112
+ const trickle = () => {
113
+ dispatch({ increment: incrementRef.current, minimum, type: 'trickle' })
114
+ timeout.schedule(trickle, incrementDuration)
115
+ }
116
+ timeout.schedule(trickle, incrementDuration)
117
+
118
+ return () => timeout.cancel()
119
+ }, [incrementDuration, minimum, phase])
120
+
121
+ useEffect(() => {
122
+ if (phase !== 'completing') {
123
+ return
124
+ }
125
+
126
+ const timeout = createTimeout()
127
+ timeout.schedule(() => dispatch({ type: 'finish' }), animationDuration)
128
+
129
+ return () => timeout.cancel()
130
+ }, [animationDuration, phase])
131
+
132
+ return {
133
+ animationDuration,
134
+ isFinished: phase === 'finished' || phase === 'idle',
135
+ progress,
136
+ }
137
+ }
@@ -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
- }