@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/README.md CHANGED
@@ -8,22 +8,28 @@
8
8
 
9
9
  > A React primitive for building slim progress bars.
10
10
 
11
- [Background](#background) | [Usage](#usage) | [Live Examples](#live-examples) | [API](#api) | [Installation](#installation) | [License](#license)
11
+ [Background](#background) | [When to Use This](#when-to-use-this) | [Usage](#usage) | [API](#api) | [Live Examples](#live-examples) | [Installation](#installation) | [Contributing](#contributing) | [License](#license)
12
12
 
13
13
  ## Background
14
14
 
15
15
  This is a React port of [rstacruz](https://github.com/rstacruz)'s [`nprogress`](https://github.com/rstacruz/nprogress) module. It exposes an API that encapsulates the logic of `nprogress` and renders nothing, allowing consumers to implement their own rendering.
16
16
 
17
+ ## When to Use This
18
+
19
+ This package is a headless primitive. It renders no markup and ships no CSS, supplying only the pacing state: a `progress` value that trickles towards completion, an `isFinished` flag, and the `animationDuration` to transition with. The bar itself is yours to write.
20
+
21
+ - Use a drop-in bar such as [`nextjs-toploader`](https://github.com/TheSGJ/nextjs-toploader), [`next-nprogress-bar`](https://github.com/Skyleen77/next-nprogress-bar), or [`nprogress`](https://github.com/rstacruz/nprogress) itself when you want a styled bar wired up to your router with no rendering work.
22
+ - Use this package when you render the bar yourself, for example with design-system components or custom containers and spinners, and want only the trickle and completion logic handled for you.
23
+ - Use this package when you need several progress bars on one page, each tracking its own state.
24
+
17
25
  ## Usage
18
26
 
19
- In the following examples, `Container`, `Bar` and `Spinner` are custom components.
27
+ `Container`, `Bar` and `Spinner` are components you write: this package renders nothing itself. Every entry in [Live Examples](#live-examples) contains a working implementation of all three.
20
28
 
21
29
  **Hook**
22
30
 
23
31
  ```jsx
24
32
  import { useNProgress } from '@tanem/react-nprogress'
25
- import React from 'react'
26
- import { render } from 'react-dom'
27
33
 
28
34
  import Bar from './Bar'
29
35
  import Container from './Container'
@@ -41,113 +47,53 @@ const Progress = ({ isAnimating }) => {
41
47
  </Container>
42
48
  )
43
49
  }
44
-
45
- render(<Progress isAnimating />, document.getElementById('root'))
46
50
  ```
47
51
 
48
52
  **Render Props**
49
53
 
50
54
  ```jsx
51
55
  import { NProgress } from '@tanem/react-nprogress'
52
- import React from 'react'
53
- import { render } from 'react-dom'
54
56
 
55
57
  import Bar from './Bar'
56
58
  import Container from './Container'
57
59
  import Spinner from './Spinner'
58
60
 
59
- render(
60
- <NProgress isAnimating>
61
+ const Progress = ({ isAnimating }) => (
62
+ <NProgress isAnimating={isAnimating}>
61
63
  {({ animationDuration, isFinished, progress }) => (
62
64
  <Container animationDuration={animationDuration} isFinished={isFinished}>
63
65
  <Bar animationDuration={animationDuration} progress={progress} />
64
66
  <Spinner />
65
67
  </Container>
66
68
  )}
67
- </NProgress>,
68
- document.getElementById('root')
69
+ </NProgress>
69
70
  )
70
71
  ```
71
72
 
72
- **HOC**
73
-
74
- ```jsx
75
- import { withNProgress } from '@tanem/react-nprogress'
76
- import React from 'react'
77
- import { render } from 'react-dom'
78
-
79
- import Bar from './Bar'
80
- import Container from './Container'
81
- import Spinner from './Spinner'
82
-
83
- const Inner = ({ animationDuration, isFinished, progress }) => (
84
- <Container animationDuration={animationDuration} isFinished={isFinished}>
85
- <Bar animationDuration={animationDuration} progress={progress} />
86
- <Spinner />
87
- </Container>
88
- )
73
+ ## API
89
74
 
90
- const Enhanced = withNProgress(Inner)
75
+ The package exports one hook and one component. Both take the same [options](#options) and produce the same [values](#return-value), so the choice between them is a matter of which pattern suits the calling code. Both shapes are exported as types, for typing code that wraps either entry point:
91
76
 
92
- render(<Enhanced isAnimating />, document.getElementById('root'))
77
+ ```ts
78
+ import type { NProgressOptions, NProgressState } from '@tanem/react-nprogress'
93
79
  ```
94
80
 
95
- ## Live Examples
96
-
97
- - HOC: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/hoc) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/hoc)
98
- - Material UI: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/material-ui) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/material-ui)
99
- - Multiple Instances: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/multiple-instances) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/multiple-instances)
100
- - Next App Router: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/next-app-router) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/next-app-router)
101
- - Next Pages Router: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/next-pages-router) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/next-pages-router)
102
- - Original Design: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/original-design) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/original-design)
103
- - Plain JS: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/plain-js) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/plain-js)
104
- - React Router: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/react-router) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/react-router)
105
- - Render Props: [Source](https://github.com/tanem/react-nprogress/tree/master/examples/render-props) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/render-props)
106
- - UMD Build (Development): [Source](https://github.com/tanem/react-nprogress/tree/master/examples/umd-dev) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/umd-dev)
107
- - UMD Build (Production): [Source](https://github.com/tanem/react-nprogress/tree/master/examples/umd-prod) | [Sandbox](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/umd-prod)
81
+ ### `useNProgress`
108
82
 
109
- ## API
110
-
111
- **Props**
112
-
113
- - `animationDuration` - _Optional_ Number indicating the animation duration in `ms`. Defaults to `200`.
114
- - `incrementDuration` - _Optional_ Number indicating the length of time between progress bar increments in `ms`. Defaults to `200`.
115
- - `isAnimating` - _Optional_ Boolean indicating if the progress bar is animating. Defaults to `false`.
116
- - `minimum` - _Optional_ Number between `0` and `1` indicating the minimum value of the progress bar. Defaults to `0.08`.
117
-
118
- **Hook Example**
83
+ Returns the state of one progress bar. Call it once per bar: two calls, or two mounted `NProgress` components, track their progress independently.
119
84
 
120
85
  ```jsx
121
- const Progress = ({
122
- animationDuration,
123
- incrementDuration,
124
- isAnimating,
125
- minimum
126
- }) => {
127
- const { isFinished, progress } = useNProgress({
128
- animationDuration,
129
- incrementDuration,
130
- isAnimating,
131
- minimum
132
- })
133
-
134
- return (
135
- <Container animationDuration={animationDuration} isFinished={isFinished}>
136
- <Bar animationDuration={animationDuration} progress={progress} />
137
- <Spinner />
138
- </Container>
139
- )
140
- }
141
-
142
- <Progress
143
- animationDuration={300}
144
- incrementDuration={500}
145
- isAnimating
146
- minimum={0.1}
147
- />
86
+ const { animationDuration, isFinished, progress } = useNProgress({
87
+ animationDuration: 300,
88
+ incrementDuration: 500,
89
+ isAnimating: true,
90
+ minimum: 0.1,
91
+ })
148
92
  ```
149
93
 
150
- **Render Props Example**
94
+ ### `NProgress`
95
+
96
+ Takes the options as props and calls `children` with the values the hook returns. `children` is required and must return a React element.
151
97
 
152
98
  ```jsx
153
99
  <NProgress
@@ -156,55 +102,71 @@ const Progress = ({
156
102
  isAnimating
157
103
  minimum={0.1}
158
104
  >
159
- {({ animationDuration, isFinished, progress }) => (
160
- <Container animationDuration={animationDuration} isFinished={isFinished}>
161
- <Bar animationDuration={animationDuration} progress={progress} />
162
- <Spinner />
163
- </Container>
105
+ {({ animationDuration, progress }) => (
106
+ <Bar animationDuration={animationDuration} progress={progress} />
164
107
  )}
165
108
  </NProgress>
166
109
  ```
167
110
 
168
- **HOC Example**
111
+ ### Options
169
112
 
170
- ```jsx
171
- const Inner = ({ animationDuration, isFinished, progress }) => (
172
- <Container animationDuration={animationDuration} isFinished={isFinished}>
173
- <Bar animationDuration={animationDuration} progress={progress} />
174
- <Spinner />
175
- </Container>
176
- )
113
+ All four options are optional. The type is `NProgressOptions`.
177
114
 
178
- const Enhanced = withNProgress(Inner)
115
+ | Option | Type | Default |
116
+ | ----------------------------------------- | --------- | ------- |
117
+ | [`animationDuration`](#animationduration) | `number` | `200` |
118
+ | [`incrementDuration`](#incrementduration) | `number` | `200` |
119
+ | [`isAnimating`](#isanimating) | `boolean` | `false` |
120
+ | [`minimum`](#minimum) | `number` | `0.08` |
179
121
 
180
- <Enhanced
181
- animationDuration={300}
182
- incrementDuration={500}
183
- isAnimating
184
- minimum={0.1}
185
- />
186
- ```
122
+ #### `animationDuration`
187
123
 
188
- ## Installation
124
+ Milliseconds the bar is given to animate out once it completes. `progress` reaches `1` as soon as `isAnimating` goes `false`, and `isFinished` follows this many milliseconds later, leaving that window for the exit transition. The value is also returned unchanged, so a single number drives both the timing and the CSS transitions.
189
125
 
190
- ```
191
- $ npm install @tanem/react-nprogress
192
- ```
126
+ #### `incrementDuration`
127
+
128
+ Milliseconds between increments while the bar is animating. It controls the trickle pacing only: the size of each increment is not configurable, and shrinks as `progress` grows.
129
+
130
+ #### `isAnimating`
131
+
132
+ Whether the bar is running. Going `true` starts it, going `false` completes it. Completion is what drives the final state: `progress` is set to `1`, and `isFinished` becomes `true` `animationDuration` milliseconds later.
133
+
134
+ #### `minimum`
135
+
136
+ Lower bound for `progress`, between `0` and `1`. The first increment starts from `0.1` rather than from `0`, so the bar appears at `max(0.1, minimum)` and the option only shows through when it is set above `0.1`. Changing it while the bar is animating does not rewind the bar. Progress holds where it is, and the new bound applies from the next increment.
193
137
 
194
- UMD builds are also available for use with pre-React 19 via [unpkg](https://unpkg.com/):
138
+ ### Return Value
195
139
 
196
- - https://unpkg.com/@tanem/react-nprogress/dist/react-nprogress.umd.development.js
197
- - https://unpkg.com/@tanem/react-nprogress/dist/react-nprogress.umd.production.js
140
+ `useNProgress` returns these values, and `NProgress` passes the same object to `children`. The type is `NProgressState`.
198
141
 
199
- For the non-minified development version, make sure you have already included:
142
+ | Value | Type | Description |
143
+ | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
144
+ | `animationDuration` | `number` | The `animationDuration` option, passed through so rendering code can transition with it. |
145
+ | `isFinished` | `boolean` | `true` before the bar starts and again once it has animated out. `false` from when `isAnimating` goes `true` until `animationDuration` after it goes `false`. |
146
+ | `progress` | `number` | Starts at `0` and trickles up in shrinking steps to a ceiling of `0.994`, then goes to `1` on completion. |
200
147
 
201
- - [`React`](https://unpkg.com/react@18/umd/react.development.js)
202
- - [`ReactDOM`](https://unpkg.com/react-dom@18/umd/react-dom.development.js)
148
+ ## Live Examples
149
+
150
+ | Example | Sandbox |
151
+ | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
152
+ | [Material UI](https://github.com/tanem/react-nprogress/tree/master/examples/material-ui) | [Open](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/material-ui) |
153
+ | [Multiple Instances](https://github.com/tanem/react-nprogress/tree/master/examples/multiple-instances) | [Open](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/multiple-instances) |
154
+ | [Next App Router](https://github.com/tanem/react-nprogress/tree/master/examples/next-app-router) | [Open](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/next-app-router) |
155
+ | [Next Pages Router](https://github.com/tanem/react-nprogress/tree/master/examples/next-pages-router) | [Open](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/next-pages-router) |
156
+ | [Original Design](https://github.com/tanem/react-nprogress/tree/master/examples/original-design) | [Open](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/original-design) |
157
+ | [Plain JS](https://github.com/tanem/react-nprogress/tree/master/examples/plain-js) | [Open](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/plain-js) |
158
+ | [React Router](https://github.com/tanem/react-nprogress/tree/master/examples/react-router) | [Open](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/react-router) |
159
+ | [Render Props](https://github.com/tanem/react-nprogress/tree/master/examples/render-props) | [Open](https://codesandbox.io/p/devbox/github/tanem/react-nprogress/tree/master/examples/render-props) |
160
+
161
+ ## Installation
162
+
163
+ ```
164
+ $ npm install @tanem/react-nprogress
165
+ ```
203
166
 
204
- For the minified production version, make sure you have already included:
167
+ ## Contributing
205
168
 
206
- - [`React`](https://unpkg.com/react@18/umd/react.production.min.js)
207
- - [`ReactDOM`](https://unpkg.com/react-dom@18/umd/react-dom.production.min.js)
169
+ Issues and pull requests are welcome. The development loop is `npm run test:src`, and `npm test` runs the full suite. Repository conventions, for humans and coding agents alike, live in [`AGENTS.md`](AGENTS.md).
208
170
 
209
171
  ## License
210
172
 
@@ -0,0 +1,119 @@
1
+ "use client";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ let react = require("react");
4
+ //#region src/clamp.ts
5
+ const clamp = (num, lower, upper) => {
6
+ num = num <= upper ? num : upper;
7
+ num = num >= lower ? num : lower;
8
+ return num;
9
+ };
10
+ //#endregion
11
+ //#region src/createTimeout.ts
12
+ const createTimeout = () => {
13
+ let handle;
14
+ const cancel = () => {
15
+ if (handle !== void 0) window.cancelAnimationFrame(handle);
16
+ };
17
+ const schedule = (callback, delay) => {
18
+ cancel();
19
+ let deltaTime;
20
+ let start;
21
+ const frame = (time) => {
22
+ start = start || time;
23
+ deltaTime = time - start;
24
+ if (deltaTime > delay) {
25
+ callback();
26
+ return;
27
+ }
28
+ handle = window.requestAnimationFrame(frame);
29
+ };
30
+ handle = window.requestAnimationFrame(frame);
31
+ };
32
+ return {
33
+ cancel,
34
+ schedule
35
+ };
36
+ };
37
+ //#endregion
38
+ //#region src/increment.ts
39
+ const increment = (progress) => {
40
+ let amount = 0;
41
+ if (progress >= 0 && progress < .2) amount = .1;
42
+ else if (progress >= .2 && progress < .5) amount = .04;
43
+ else if (progress >= .5 && progress < .8) amount = .02;
44
+ else if (progress >= .8 && progress < .99) amount = .005;
45
+ return clamp(progress + amount, 0, .994);
46
+ };
47
+ //#endregion
48
+ //#region src/useNProgress.tsx
49
+ const initialState = {
50
+ phase: "idle",
51
+ progress: 0
52
+ };
53
+ const reducer = (state, action) => {
54
+ switch (action.type) {
55
+ case "complete": return state.phase === "animating" ? {
56
+ phase: "completing",
57
+ progress: 1
58
+ } : state;
59
+ case "finish": return {
60
+ phase: "finished",
61
+ progress: 1
62
+ };
63
+ case "start": return state.phase === "animating" ? state : {
64
+ phase: "animating",
65
+ progress: clamp(increment(0), action.minimum, 1)
66
+ };
67
+ case "trickle": return {
68
+ ...state,
69
+ progress: clamp(increment(state.progress), action.minimum, 1)
70
+ };
71
+ }
72
+ };
73
+ const useNProgress = ({ animationDuration = 200, incrementDuration = 200, isAnimating = false, minimum = .08 } = {}) => {
74
+ const [{ phase, progress }, dispatch] = (0, react.useReducer)(reducer, initialState);
75
+ (0, react.useEffect)(() => {
76
+ dispatch(isAnimating ? {
77
+ minimum,
78
+ type: "start"
79
+ } : { type: "complete" });
80
+ }, [isAnimating, minimum]);
81
+ (0, react.useEffect)(() => {
82
+ if (phase !== "animating") return;
83
+ const timeout = createTimeout();
84
+ const trickle = () => {
85
+ dispatch({
86
+ minimum,
87
+ type: "trickle"
88
+ });
89
+ timeout.schedule(trickle, incrementDuration);
90
+ };
91
+ timeout.schedule(trickle, incrementDuration);
92
+ return () => timeout.cancel();
93
+ }, [
94
+ incrementDuration,
95
+ minimum,
96
+ phase
97
+ ]);
98
+ (0, react.useEffect)(() => {
99
+ if (phase !== "completing") return;
100
+ const timeout = createTimeout();
101
+ timeout.schedule(() => dispatch({ type: "finish" }), animationDuration);
102
+ return () => timeout.cancel();
103
+ }, [animationDuration, phase]);
104
+ return {
105
+ animationDuration,
106
+ isFinished: phase === "finished" || phase === "idle",
107
+ progress
108
+ };
109
+ };
110
+ //#endregion
111
+ //#region src/NProgress.tsx
112
+ const NProgress = ({ children, ...restProps }) => {
113
+ return children(useNProgress(restProps));
114
+ };
115
+ //#endregion
116
+ exports.NProgress = NProgress;
117
+ exports.useNProgress = useNProgress;
118
+
119
+ //# sourceMappingURL=react-nprogress.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-nprogress.cjs","names":["useReducer"],"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 } from 'react'\n\nimport { clamp } from './clamp'\nimport { createTimeout } from './createTimeout'\nimport { increment } 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 | { minimum: number; type: 'start' }\n | { minimum: number; type: 'trickle' }\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 // Unlike the original nprogress `done()`, completion does not include a\n // random progress jump before animating to 1. This keeps the primitive\n // predictable; consumers can set a higher progress value before stopping\n // the animation if they want that effect.\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 // The original nprogress calls set(0) - which clamps to `minimum` -\n // before the first trickle. Here, the first trickle starts from\n // increment(0) = 0.1, so the bar appears at max(0.1, minimum) rather\n // than exactly `minimum`. The difference is negligible at the default\n // minimum of 0.08.\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(increment(0), action.minimum, 1),\n }\n\n case 'trickle':\n return {\n ...state,\n progress: clamp(increment(state.progress), action.minimum, 1),\n }\n }\n}\n\nexport const useNProgress = ({\n animationDuration = 200,\n incrementDuration = 200,\n isAnimating = false,\n minimum = 0.08,\n}: NProgressOptions = {}): NProgressState => {\n const [{ phase, progress }, dispatch] = useReducer(reducer, initialState)\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({ 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;;;ACOA,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,SAWH,OAAO,MAAM,UAAU,cACnB,QACA;GACE,OAAO;GACP,UAAU,MAAM,UAAU,CAAC,GAAG,OAAO,SAAS,CAAC;EACjD;EAEN,KAAK,WACH,OAAO;GACL,GAAG;GACH,UAAU,MAAM,UAAU,MAAM,QAAQ,GAAG,OAAO,SAAS,CAAC;EAC9D;CACJ;AACF;AAEA,MAAa,gBAAgB,EAC3B,oBAAoB,KACpB,oBAAoB,KACpB,cAAc,OACd,UAAU,QACU,CAAC,MAAsB;CAC3C,MAAM,CAAC,EAAE,OAAO,YAAY,aAAA,GAAYA,MAAAA,WAAAA,CAAW,SAAS,YAAY;CAExE,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,SAAS,cAAc;GAAE;GAAS,MAAM;EAAQ,IAAI,EAAE,MAAM,WAAW,CAAC;CAC1E,GAAG,CAAC,aAAa,OAAO,CAAC;CAOzB,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,UAAU,aACZ;EAGF,MAAM,UAAU,cAAc;EAE9B,MAAM,gBAAgB;GACpB,SAAS;IAAE;IAAS,MAAM;GAAU,CAAC;GACrC,QAAQ,SAAS,SAAS,iBAAiB;EAC7C;EACA,QAAQ,SAAS,SAAS,iBAAiB;EAE3C,aAAa,QAAQ,OAAO;CAC9B,GAAG;EAAC;EAAmB;EAAS;CAAK,CAAC;CAEtC,CAAA,GAAA,MAAA,UAAA,OAAgB;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/GA,MAAa,aAAwB,EAAE,UAAU,GAAG,gBAAuB;CAEzE,OAAO,SADa,aAAa,SACP,CAAC;AAC7B"}
@@ -0,0 +1,25 @@
1
+ import { FC, ReactElement } from "react";
2
+ //#region src/types.d.ts
3
+ interface NProgressOptions {
4
+ animationDuration?: number;
5
+ incrementDuration?: number;
6
+ isAnimating?: boolean;
7
+ minimum?: number;
8
+ }
9
+ interface NProgressState {
10
+ animationDuration: number;
11
+ isFinished: boolean;
12
+ progress: number;
13
+ }
14
+ //#endregion
15
+ //#region src/NProgress.d.ts
16
+ type Props = NProgressOptions & {
17
+ children: (renderProps: NProgressState) => ReactElement;
18
+ };
19
+ declare const NProgress: FC<Props>;
20
+ //#endregion
21
+ //#region src/useNProgress.d.ts
22
+ declare const useNProgress: ({ animationDuration, incrementDuration, isAnimating, minimum }?: NProgressOptions) => NProgressState;
23
+ //#endregion
24
+ export { NProgress, type NProgressOptions, type NProgressState, useNProgress };
25
+ //# sourceMappingURL=react-nprogress.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-nprogress.d.cts","names":[],"sources":["../src/types.ts","../src/NProgress.tsx","../src/useNProgress.tsx"],"mappings":";;UAAiB;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;;;KCLG,QAAQ;EACX,WAAW,aAAa,mBAAmB;;cAGhC,WAAW,GAAG;;;cC8Dd,iBAAgB,mBAAA,mBAAA,aAAA,YAK1B,qBAAwB"}
@@ -0,0 +1,25 @@
1
+ import { FC, ReactElement } from "react";
2
+ //#region src/types.d.ts
3
+ interface NProgressOptions {
4
+ animationDuration?: number;
5
+ incrementDuration?: number;
6
+ isAnimating?: boolean;
7
+ minimum?: number;
8
+ }
9
+ interface NProgressState {
10
+ animationDuration: number;
11
+ isFinished: boolean;
12
+ progress: number;
13
+ }
14
+ //#endregion
15
+ //#region src/NProgress.d.ts
16
+ type Props = NProgressOptions & {
17
+ children: (renderProps: NProgressState) => ReactElement;
18
+ };
19
+ declare const NProgress: FC<Props>;
20
+ //#endregion
21
+ //#region src/useNProgress.d.ts
22
+ declare const useNProgress: ({ animationDuration, incrementDuration, isAnimating, minimum }?: NProgressOptions) => NProgressState;
23
+ //#endregion
24
+ export { NProgress, type NProgressOptions, type NProgressState, useNProgress };
25
+ //# sourceMappingURL=react-nprogress.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-nprogress.d.mts","names":[],"sources":["../src/types.ts","../src/NProgress.tsx","../src/useNProgress.tsx"],"mappings":";;UAAiB;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;;;KCLG,QAAQ;EACX,WAAW,aAAa,mBAAmB;;cAGhC,WAAW,GAAG;;;cC8Dd,iBAAgB,mBAAA,mBAAA,aAAA,YAK1B,qBAAwB"}
@@ -0,0 +1,117 @@
1
+ "use client";
2
+ import { useEffect, useReducer } from "react";
3
+ //#region src/clamp.ts
4
+ const clamp = (num, lower, upper) => {
5
+ num = num <= upper ? num : upper;
6
+ num = num >= lower ? num : lower;
7
+ return num;
8
+ };
9
+ //#endregion
10
+ //#region src/createTimeout.ts
11
+ const createTimeout = () => {
12
+ let handle;
13
+ const cancel = () => {
14
+ if (handle !== void 0) window.cancelAnimationFrame(handle);
15
+ };
16
+ const schedule = (callback, delay) => {
17
+ cancel();
18
+ let deltaTime;
19
+ let start;
20
+ const frame = (time) => {
21
+ start = start || time;
22
+ deltaTime = time - start;
23
+ if (deltaTime > delay) {
24
+ callback();
25
+ return;
26
+ }
27
+ handle = window.requestAnimationFrame(frame);
28
+ };
29
+ handle = window.requestAnimationFrame(frame);
30
+ };
31
+ return {
32
+ cancel,
33
+ schedule
34
+ };
35
+ };
36
+ //#endregion
37
+ //#region src/increment.ts
38
+ const increment = (progress) => {
39
+ let amount = 0;
40
+ if (progress >= 0 && progress < .2) amount = .1;
41
+ else if (progress >= .2 && progress < .5) amount = .04;
42
+ else if (progress >= .5 && progress < .8) amount = .02;
43
+ else if (progress >= .8 && progress < .99) amount = .005;
44
+ return clamp(progress + amount, 0, .994);
45
+ };
46
+ //#endregion
47
+ //#region src/useNProgress.tsx
48
+ const initialState = {
49
+ phase: "idle",
50
+ progress: 0
51
+ };
52
+ const reducer = (state, action) => {
53
+ switch (action.type) {
54
+ case "complete": return state.phase === "animating" ? {
55
+ phase: "completing",
56
+ progress: 1
57
+ } : state;
58
+ case "finish": return {
59
+ phase: "finished",
60
+ progress: 1
61
+ };
62
+ case "start": return state.phase === "animating" ? state : {
63
+ phase: "animating",
64
+ progress: clamp(increment(0), action.minimum, 1)
65
+ };
66
+ case "trickle": return {
67
+ ...state,
68
+ progress: clamp(increment(state.progress), action.minimum, 1)
69
+ };
70
+ }
71
+ };
72
+ const useNProgress = ({ animationDuration = 200, incrementDuration = 200, isAnimating = false, minimum = .08 } = {}) => {
73
+ const [{ phase, progress }, dispatch] = useReducer(reducer, initialState);
74
+ useEffect(() => {
75
+ dispatch(isAnimating ? {
76
+ minimum,
77
+ type: "start"
78
+ } : { type: "complete" });
79
+ }, [isAnimating, minimum]);
80
+ useEffect(() => {
81
+ if (phase !== "animating") return;
82
+ const timeout = createTimeout();
83
+ const trickle = () => {
84
+ dispatch({
85
+ minimum,
86
+ type: "trickle"
87
+ });
88
+ timeout.schedule(trickle, incrementDuration);
89
+ };
90
+ timeout.schedule(trickle, incrementDuration);
91
+ return () => timeout.cancel();
92
+ }, [
93
+ incrementDuration,
94
+ minimum,
95
+ phase
96
+ ]);
97
+ useEffect(() => {
98
+ if (phase !== "completing") return;
99
+ const timeout = createTimeout();
100
+ timeout.schedule(() => dispatch({ type: "finish" }), animationDuration);
101
+ return () => timeout.cancel();
102
+ }, [animationDuration, phase]);
103
+ return {
104
+ animationDuration,
105
+ isFinished: phase === "finished" || phase === "idle",
106
+ progress
107
+ };
108
+ };
109
+ //#endregion
110
+ //#region src/NProgress.tsx
111
+ const NProgress = ({ children, ...restProps }) => {
112
+ return children(useNProgress(restProps));
113
+ };
114
+ //#endregion
115
+ export { NProgress, useNProgress };
116
+
117
+ //# sourceMappingURL=react-nprogress.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-nprogress.mjs","names":[],"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 } from 'react'\n\nimport { clamp } from './clamp'\nimport { createTimeout } from './createTimeout'\nimport { increment } 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 | { minimum: number; type: 'start' }\n | { minimum: number; type: 'trickle' }\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 // Unlike the original nprogress `done()`, completion does not include a\n // random progress jump before animating to 1. This keeps the primitive\n // predictable; consumers can set a higher progress value before stopping\n // the animation if they want that effect.\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 // The original nprogress calls set(0) - which clamps to `minimum` -\n // before the first trickle. Here, the first trickle starts from\n // increment(0) = 0.1, so the bar appears at max(0.1, minimum) rather\n // than exactly `minimum`. The difference is negligible at the default\n // minimum of 0.08.\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(increment(0), action.minimum, 1),\n }\n\n case 'trickle':\n return {\n ...state,\n progress: clamp(increment(state.progress), action.minimum, 1),\n }\n }\n}\n\nexport const useNProgress = ({\n animationDuration = 200,\n incrementDuration = 200,\n isAnimating = false,\n minimum = 0.08,\n}: NProgressOptions = {}): NProgressState => {\n const [{ phase, progress }, dispatch] = useReducer(reducer, initialState)\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({ 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;;;ACOA,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,SAWH,OAAO,MAAM,UAAU,cACnB,QACA;GACE,OAAO;GACP,UAAU,MAAM,UAAU,CAAC,GAAG,OAAO,SAAS,CAAC;EACjD;EAEN,KAAK,WACH,OAAO;GACL,GAAG;GACH,UAAU,MAAM,UAAU,MAAM,QAAQ,GAAG,OAAO,SAAS,CAAC;EAC9D;CACJ;AACF;AAEA,MAAa,gBAAgB,EAC3B,oBAAoB,KACpB,oBAAoB,KACpB,cAAc,OACd,UAAU,QACU,CAAC,MAAsB;CAC3C,MAAM,CAAC,EAAE,OAAO,YAAY,YAAY,WAAW,SAAS,YAAY;CAExE,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;IAAS,MAAM;GAAU,CAAC;GACrC,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/GA,MAAa,aAAwB,EAAE,UAAU,GAAG,gBAAuB;CAEzE,OAAO,SADa,aAAa,SACP,CAAC;AAC7B"}