├── src
├── vite-env.d.ts
├── index.jsx
├── styles.css
├── App.jsx
├── LegacyClassApp.jsx
└── mini-react.ts
├── .vscode
├── settings.json
└── launch.json
├── .prettierrc.json
├── .editorconfig
├── vite.config.ts
├── .gitignore
├── index.html
├── tsconfig.json
├── package.json
├── README.md
├── LICENSE
└── pnpm-lock.yaml
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.codeActionsOnSave": {
4 | "source.fixAll": "explicit"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "singleQuote": true,
4 | "trailingComma": "all",
5 | "proseWrap": "never",
6 | "endOfLine": "lf"
7 | }
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/src/index.jsx:
--------------------------------------------------------------------------------
1 | // Forked from https://reactjs.org/tutorial/tutorial.html#what-are-we-building
2 |
3 | import React from './mini-react';
4 | import App from './App'; // OR `LegacyClassApp`
5 | import './styles.css';
6 |
7 | React.render(, document.getElementById('root'));
8 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | optimizeDeps: {
7 | include: [],
8 | },
9 | plugins: [
10 | react({
11 | jsxRuntime: 'classic',
12 | }),
13 | ],
14 | });
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .idea
17 | .DS_Store
18 | *.suo
19 | *.ntvs*
20 | *.njsproj
21 | *.sln
22 | *.sw?
23 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Mini React App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "chrome",
9 | "request": "launch",
10 | "name": "Launch Chrome against localhost",
11 | "url": "http://localhost:5173",
12 | "webRoot": "${workspaceFolder}"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "strict": true,
6 | "useDefineForClassFields": true,
7 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
8 | "allowJs": true,
9 | "skipLibCheck": false,
10 | "esModuleInterop": false,
11 | "allowSyntheticDefaultImports": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "moduleResolution": "Bundler",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"]
20 | }
21 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mini-react",
3 | "version": "1.0.0",
4 | "type": "module",
5 | "packageManager": "pnpm@9.1.0",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {},
12 | "devDependencies": {
13 | "@vitejs/plugin-react": "^4.2.1",
14 | "typescript": "^5.4.5",
15 | "vite": "^5.2.11"
16 | },
17 | "keywords": [
18 | "react"
19 | ],
20 | "author": "",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/islizeqiang/mini-react/issues"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "git+https://github.com/islizeqiang/mini-react.git"
28 | },
29 | "homepage": "https://github.com/islizeqiang/mini-react#readme"
30 | }
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Mini-React
4 |
5 | **Implement Mini-React in 400 lines of code, a minimal model with asynchronous interruptible updates.**
6 |
7 | # Demos
8 |
9 | [Online Demo](https://stackblitz.com/~/github.com/ZacharyL2/mini-react)
10 |
11 | A simple running screenshot:
12 |
13 | 
14 |
15 | # Introduce
16 |
17 | I used the [Tic-Tac-Toe](https://react.dev/learn/tutorial-tic-tac-toe) tutorial example provided on the React website, and it works well.
18 |
19 | Additionally, it supports both functional and class components. Its overall logic and function naming are largely consistent with React's fundamentals. If you are interested in the inner workings of React, then this tutorial is suitable for you!
20 |
21 | [**See how to build it.**](https://webdeveloper.beehiiv.com/p/build-react-400-lines-code)
22 |
23 | # License
24 |
25 | [MIT](https://github.com/islizeqiang/mini-react/blob/master/LICENSE)
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Zachary Lee
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | body {
6 | font-family: sans-serif;
7 | margin: 20px;
8 | padding: 0;
9 | }
10 |
11 | h1 {
12 | margin-top: 0;
13 | font-size: 22px;
14 | }
15 |
16 | h2 {
17 | margin-top: 0;
18 | font-size: 20px;
19 | }
20 |
21 | h3 {
22 | margin-top: 0;
23 | font-size: 18px;
24 | }
25 |
26 | h4 {
27 | margin-top: 0;
28 | font-size: 16px;
29 | }
30 |
31 | h5 {
32 | margin-top: 0;
33 | font-size: 14px;
34 | }
35 |
36 | h6 {
37 | margin-top: 0;
38 | font-size: 12px;
39 | }
40 |
41 | code {
42 | font-size: 1.2em;
43 | }
44 |
45 | ul {
46 | padding-inline-start: 20px;
47 | }
48 |
49 | * {
50 | box-sizing: border-box;
51 | }
52 |
53 | body {
54 | font-family: sans-serif;
55 | margin: 20px;
56 | padding: 0;
57 | }
58 |
59 | .square {
60 | background: #fff;
61 | border: 1px solid #999;
62 | float: left;
63 | font-size: 24px;
64 | font-weight: bold;
65 | line-height: 34px;
66 | height: 34px;
67 | margin-right: -1px;
68 | margin-top: -1px;
69 | padding: 0;
70 | text-align: center;
71 | width: 34px;
72 | }
73 |
74 | .board-row:after {
75 | clear: both;
76 | content: '';
77 | display: table;
78 | }
79 |
80 | .status {
81 | margin-bottom: 10px;
82 | }
83 | .game {
84 | display: flex;
85 | flex-direction: row;
86 | }
87 |
88 | .game-info {
89 | margin-left: 20px;
90 | }
91 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from './mini-react';
2 |
3 | const { useState } = React;
4 |
5 | function Square({ value, onSquareClick }) {
6 | return (
7 |
10 | );
11 | }
12 |
13 | function Board({ xIsNext, squares, onPlay }) {
14 | function handleClick(i) {
15 | if (calculateWinner(squares) || squares[i]) {
16 | return;
17 | }
18 | const nextSquares = squares.slice();
19 | if (xIsNext) {
20 | nextSquares[i] = 'X';
21 | } else {
22 | nextSquares[i] = 'O';
23 | }
24 | onPlay(nextSquares);
25 | }
26 |
27 | const winner = calculateWinner(squares);
28 | let status;
29 | if (winner) {
30 | status = 'Winner: ' + winner;
31 | } else {
32 | status = 'Next player: ' + (xIsNext ? 'X' : 'O');
33 | }
34 |
35 | return (
36 | <>
37 | {status}
38 |
39 | handleClick(0)} />
40 | handleClick(1)} />
41 | handleClick(2)} />
42 |
43 |
44 | handleClick(3)} />
45 | handleClick(4)} />
46 | handleClick(5)} />
47 |
48 |
49 | handleClick(6)} />
50 | handleClick(7)} />
51 | handleClick(8)} />
52 |
53 | >
54 | );
55 | }
56 |
57 | export default function Game() {
58 | const [history, setHistory] = useState([Array(9).fill(null)]);
59 | const [currentMove, setCurrentMove] = useState(0);
60 | const xIsNext = currentMove % 2 === 0;
61 | const currentSquares = history[currentMove];
62 |
63 | function handlePlay(nextSquares) {
64 | const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
65 | setHistory(nextHistory);
66 | setCurrentMove(nextHistory.length - 1);
67 | }
68 |
69 | function jumpTo(nextMove) {
70 | setCurrentMove(nextMove);
71 | }
72 |
73 | const moves = history.map((squares, move) => {
74 | let description;
75 | if (move > 0) {
76 | description = 'Go to move #' + move;
77 | } else {
78 | description = 'Go to game start';
79 | }
80 | return (
81 |
82 |
83 |
84 | );
85 | });
86 |
87 | return (
88 |
96 | );
97 | }
98 |
99 | function calculateWinner(squares) {
100 | const lines = [
101 | [0, 1, 2],
102 | [3, 4, 5],
103 | [6, 7, 8],
104 | [0, 3, 6],
105 | [1, 4, 7],
106 | [2, 5, 8],
107 | [0, 4, 8],
108 | [2, 4, 6],
109 | ];
110 | for (let i = 0; i < lines.length; i++) {
111 | const [a, b, c] = lines[i];
112 | if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
113 | return squares[a];
114 | }
115 | }
116 | return null;
117 | }
118 |
--------------------------------------------------------------------------------
/src/LegacyClassApp.jsx:
--------------------------------------------------------------------------------
1 | import React from './mini-react';
2 |
3 | function calculateWinner(squares) {
4 | const lines = [
5 | [0, 1, 2],
6 | [3, 4, 5],
7 | [6, 7, 8],
8 | [0, 3, 6],
9 | [1, 4, 7],
10 | [2, 5, 8],
11 | [0, 4, 8],
12 | [2, 4, 6],
13 | ];
14 | for (let i = 0; i < lines.length; i += 1) {
15 | const [a, b, c] = lines[i];
16 | if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
17 | return squares[a];
18 | }
19 | }
20 | return null;
21 | }
22 |
23 | class Square extends React.Component {
24 | render() {
25 | return (
26 |
29 | );
30 | }
31 | }
32 |
33 | class Board extends React.Component {
34 | renderSquare(i) {
35 | return (
36 | {
39 | this.props.onClick(i);
40 | }}
41 | />
42 | );
43 | }
44 |
45 | render() {
46 | return (
47 |
48 |
49 | {this.renderSquare(0)}
50 | {this.renderSquare(1)}
51 | {this.renderSquare(2)}
52 |
53 |
54 | {this.renderSquare(3)}
55 | {this.renderSquare(4)}
56 | {this.renderSquare(5)}
57 |
58 |
59 | {this.renderSquare(6)}
60 | {this.renderSquare(7)}
61 | {this.renderSquare(8)}
62 |
63 |
64 | );
65 | }
66 | }
67 |
68 | class App extends React.Component {
69 | constructor(props) {
70 | super(props);
71 | this.state = {
72 | history: [
73 | {
74 | squares: Array(9).fill(null),
75 | },
76 | ],
77 | stepNumber: 0,
78 | xIsNext: true,
79 | };
80 | }
81 |
82 | handleClick(i) {
83 | const history = this.state.history.slice(0, this.state.stepNumber + 1);
84 | const current = history[history.length - 1];
85 | const squares = current.squares.slice();
86 | if (calculateWinner(squares) || squares[i]) {
87 | return;
88 | }
89 |
90 | squares[i] = this.state.xIsNext ? 'X' : 'O';
91 | this.setState({
92 | history: history.concat([
93 | {
94 | squares,
95 | },
96 | ]),
97 | stepNumber: history.length,
98 | xIsNext: !this.state.xIsNext,
99 | });
100 | }
101 |
102 | jumpTo(step) {
103 | this.setState({
104 | stepNumber: step,
105 | xIsNext: step % 2 === 0,
106 | });
107 | }
108 |
109 | render() {
110 | const { history } = this.state;
111 | const current = history[this.state.stepNumber];
112 | const winner = calculateWinner(current.squares);
113 |
114 | const moves = history.map((step, move) => {
115 | const desc = move ? `Go to move #${move}` : 'Go to game start';
116 | return (
117 |
118 |
119 |
120 | );
121 | });
122 |
123 | let status;
124 | if (winner) {
125 | status = `Winner: ${winner}`;
126 | } else {
127 | status = `Next player: ${this.state.xIsNext ? 'X' : 'O'}`;
128 | }
129 |
130 | return (
131 |
132 |
133 | {
136 | this.handleClick(i);
137 | }}
138 | />
139 |
140 |
141 |
{status}
142 |
{moves}
143 |
144 |
145 | );
146 | }
147 | }
148 |
149 | export default App;
150 |
--------------------------------------------------------------------------------
/src/mini-react.ts:
--------------------------------------------------------------------------------
1 | // TODO Optimization Type Description
2 |
3 | interface ComponentFunction {
4 | new (props: Record): Component;
5 | (props: Record): VirtualElement | string;
6 | }
7 | type VirtualElementType = ComponentFunction | string;
8 |
9 | interface VirtualElementProps {
10 | children?: VirtualElement[];
11 | [propName: string]: unknown;
12 | }
13 | interface VirtualElement {
14 | type: VirtualElementType;
15 | props: VirtualElementProps;
16 | }
17 |
18 | type FiberNodeDOM = Element | Text | null | undefined;
19 | interface FiberNode extends VirtualElement {
20 | alternate: FiberNode | null;
21 | dom?: FiberNodeDOM;
22 | effectTag?: string;
23 | child?: FiberNode;
24 | return?: FiberNode;
25 | sibling?: FiberNode;
26 | hooks?: {
27 | state: S;
28 | queue: S[];
29 | }[];
30 | }
31 |
32 | let wipRoot: FiberNode | null = null;
33 | let nextUnitOfWork: FiberNode | null = null;
34 | let currentRoot: FiberNode | null = null;
35 | let deletions: FiberNode[] = [];
36 | let wipFiber: FiberNode;
37 | let hookIndex = 0;
38 | // Support React.Fragment syntax.
39 | const Fragment = Symbol.for('react.fragment');
40 |
41 | // Enhanced requestIdleCallback.
42 | ((global: Window) => {
43 | const id = 1;
44 | const fps = 1e3 / 60;
45 | let frameDeadline: number;
46 | let pendingCallback: IdleRequestCallback;
47 | const channel = new MessageChannel();
48 | const timeRemaining = () => frameDeadline - window.performance.now();
49 |
50 | const deadline = {
51 | didTimeout: false,
52 | timeRemaining,
53 | };
54 |
55 | channel.port2.onmessage = () => {
56 | if (typeof pendingCallback === 'function') {
57 | pendingCallback(deadline);
58 | }
59 | };
60 |
61 | global.requestIdleCallback = (callback: IdleRequestCallback) => {
62 | global.requestAnimationFrame((frameTime) => {
63 | frameDeadline = frameTime + fps;
64 | pendingCallback = callback;
65 | channel.port1.postMessage(null);
66 | });
67 | return id;
68 | };
69 | })(window);
70 |
71 | const isDef = (param: T): param is NonNullable =>
72 | param !== void 0 && param !== null;
73 |
74 | const isPlainObject = (val: unknown): val is Record =>
75 | Object.prototype.toString.call(val) === '[object Object]' &&
76 | [Object.prototype, null].includes(Object.getPrototypeOf(val));
77 |
78 | // Simple judgment of virtual elements.
79 | const isVirtualElement = (e: unknown): e is VirtualElement =>
80 | typeof e === 'object';
81 |
82 | // Text elements require special handling.
83 | const createTextElement = (text: string): VirtualElement => ({
84 | type: 'TEXT',
85 | props: {
86 | nodeValue: text,
87 | },
88 | });
89 |
90 | // Create custom JavaScript data structures.
91 | const createElement = (
92 | type: VirtualElementType,
93 | props: Record = {},
94 | ...child: (unknown | VirtualElement)[]
95 | ): VirtualElement => {
96 | const children = child.map((c) =>
97 | isVirtualElement(c) ? c : createTextElement(String(c)),
98 | );
99 |
100 | return {
101 | type,
102 | props: {
103 | ...props,
104 | children,
105 | },
106 | };
107 | };
108 |
109 | // Update DOM properties.
110 | // For simplicity, we remove all the previous properties and add next properties.
111 | const updateDOM = (
112 | DOM: NonNullable,
113 | prevProps: VirtualElementProps,
114 | nextProps: VirtualElementProps,
115 | ) => {
116 | const defaultPropKeys = 'children';
117 |
118 | for (const [removePropKey, removePropValue] of Object.entries(prevProps)) {
119 | if (removePropKey.startsWith('on')) {
120 | DOM.removeEventListener(
121 | removePropKey.slice(2).toLowerCase(),
122 | removePropValue as EventListener,
123 | );
124 | } else if (removePropKey !== defaultPropKeys) {
125 | // @ts-expect-error: Unreachable code error
126 | DOM[removePropKey] = '';
127 | }
128 | }
129 |
130 | for (const [addPropKey, addPropValue] of Object.entries(nextProps)) {
131 | if (addPropKey.startsWith('on')) {
132 | DOM.addEventListener(
133 | addPropKey.slice(2).toLowerCase(),
134 | addPropValue as EventListener,
135 | );
136 | } else if (addPropKey !== defaultPropKeys) {
137 | // @ts-expect-error: Unreachable code error
138 | DOM[addPropKey] = addPropValue;
139 | }
140 | }
141 | };
142 |
143 | // Create DOM based on node type.
144 | const createDOM = (fiberNode: FiberNode): FiberNodeDOM => {
145 | const { type, props } = fiberNode;
146 | let DOM: FiberNodeDOM = null;
147 |
148 | if (type === 'TEXT') {
149 | DOM = document.createTextNode('');
150 | } else if (typeof type === 'string') {
151 | DOM = document.createElement(type);
152 | }
153 |
154 | // Update properties based on props after creation.
155 | if (DOM !== null) {
156 | updateDOM(DOM, {}, props);
157 | }
158 |
159 | return DOM;
160 | };
161 |
162 | // Change the DOM based on fiber node changes.
163 | // Note that we must complete the comparison of all fiber nodes before commitRoot.
164 | // The comparison of fiber nodes can be interrupted, but the commitRoot cannot be interrupted.
165 | const commitRoot = () => {
166 | const findParentFiber = (fiberNode?: FiberNode) => {
167 | if (fiberNode) {
168 | let parentFiber = fiberNode.return;
169 | while (parentFiber && !parentFiber.dom) {
170 | parentFiber = parentFiber.return;
171 | }
172 | return parentFiber;
173 | }
174 |
175 | return null;
176 | };
177 |
178 | const commitDeletion = (
179 | parentDOM: FiberNodeDOM,
180 | DOM: NonNullable,
181 | ) => {
182 | if (isDef(parentDOM)) {
183 | parentDOM.removeChild(DOM);
184 | }
185 | };
186 |
187 | const commitReplacement = (
188 | parentDOM: FiberNodeDOM,
189 | DOM: NonNullable,
190 | ) => {
191 | if (isDef(parentDOM)) {
192 | parentDOM.appendChild(DOM);
193 | }
194 | };
195 |
196 | const commitWork = (fiberNode?: FiberNode) => {
197 | if (fiberNode) {
198 | if (fiberNode.dom) {
199 | const parentFiber = findParentFiber(fiberNode);
200 | const parentDOM = parentFiber?.dom;
201 |
202 | switch (fiberNode.effectTag) {
203 | case 'REPLACEMENT':
204 | commitReplacement(parentDOM, fiberNode.dom);
205 | break;
206 | case 'UPDATE':
207 | updateDOM(
208 | fiberNode.dom,
209 | fiberNode.alternate ? fiberNode.alternate.props : {},
210 | fiberNode.props,
211 | );
212 | break;
213 | default:
214 | break;
215 | }
216 | }
217 |
218 | commitWork(fiberNode.child);
219 | commitWork(fiberNode.sibling);
220 | }
221 | };
222 |
223 | for (const deletion of deletions) {
224 | if (deletion.dom) {
225 | const parentFiber = findParentFiber(deletion);
226 | commitDeletion(parentFiber?.dom, deletion.dom);
227 | }
228 | }
229 |
230 | if (wipRoot !== null) {
231 | commitWork(wipRoot.child);
232 | currentRoot = wipRoot;
233 | }
234 |
235 | wipRoot = null;
236 | };
237 |
238 | // Reconcile the fiber nodes before and after, compare and record the differences.
239 | const reconcileChildren = (
240 | fiberNode: FiberNode,
241 | elements: VirtualElement[] = [],
242 | ) => {
243 | let index = 0;
244 | let oldFiberNode: FiberNode | undefined = void 0;
245 | let prevSibling: FiberNode | undefined = void 0;
246 | const virtualElements = elements.flat(Infinity);
247 |
248 | if (fiberNode.alternate?.child) {
249 | oldFiberNode = fiberNode.alternate.child;
250 | }
251 |
252 | while (
253 | index < virtualElements.length ||
254 | typeof oldFiberNode !== 'undefined'
255 | ) {
256 | const virtualElement = virtualElements[index];
257 | let newFiber: FiberNode | undefined = void 0;
258 |
259 | const isSameType = Boolean(
260 | oldFiberNode &&
261 | virtualElement &&
262 | oldFiberNode.type === virtualElement.type,
263 | );
264 |
265 | if (isSameType && oldFiberNode) {
266 | newFiber = {
267 | type: oldFiberNode.type,
268 | dom: oldFiberNode.dom,
269 | alternate: oldFiberNode,
270 | props: virtualElement.props,
271 | return: fiberNode,
272 | effectTag: 'UPDATE',
273 | };
274 | }
275 | if (!isSameType && Boolean(virtualElement)) {
276 | newFiber = {
277 | type: virtualElement.type,
278 | dom: null,
279 | alternate: null,
280 | props: virtualElement.props,
281 | return: fiberNode,
282 | effectTag: 'REPLACEMENT',
283 | };
284 | }
285 | if (!isSameType && oldFiberNode) {
286 | deletions.push(oldFiberNode);
287 | }
288 |
289 | if (oldFiberNode) {
290 | oldFiberNode = oldFiberNode.sibling;
291 | }
292 |
293 | if (index === 0) {
294 | fiberNode.child = newFiber;
295 | } else if (typeof prevSibling !== 'undefined') {
296 | prevSibling.sibling = newFiber;
297 | }
298 |
299 | prevSibling = newFiber;
300 | index += 1;
301 | }
302 | };
303 |
304 | // Execute each unit task and return to the next unit task.
305 | // Different processing according to the type of fiber node.
306 | const performUnitOfWork = (fiberNode: FiberNode): FiberNode | null => {
307 | const { type } = fiberNode;
308 | switch (typeof type) {
309 | case 'function': {
310 | wipFiber = fiberNode;
311 | wipFiber.hooks = [];
312 | hookIndex = 0;
313 | let children: ReturnType;
314 |
315 | if (Object.getPrototypeOf(type).REACT_COMPONENT) {
316 | const C = type;
317 | const component = new C(fiberNode.props);
318 | const [state, setState] = useState(component.state);
319 | component.props = fiberNode.props;
320 | component.state = state;
321 | component.setState = setState;
322 | children = component.render.bind(component)();
323 | } else {
324 | children = type(fiberNode.props);
325 | }
326 | reconcileChildren(fiberNode, [
327 | isVirtualElement(children)
328 | ? children
329 | : createTextElement(String(children)),
330 | ]);
331 | break;
332 | }
333 |
334 | case 'number':
335 | case 'string':
336 | if (!fiberNode.dom) {
337 | fiberNode.dom = createDOM(fiberNode);
338 | }
339 | reconcileChildren(fiberNode, fiberNode.props.children);
340 | break;
341 | case 'symbol':
342 | if (type === Fragment) {
343 | reconcileChildren(fiberNode, fiberNode.props.children);
344 | }
345 | break;
346 | default:
347 | if (typeof fiberNode.props !== 'undefined') {
348 | reconcileChildren(fiberNode, fiberNode.props.children);
349 | }
350 | break;
351 | }
352 |
353 | if (fiberNode.child) {
354 | return fiberNode.child;
355 | }
356 |
357 | let nextFiberNode: FiberNode | undefined = fiberNode;
358 |
359 | while (typeof nextFiberNode !== 'undefined') {
360 | if (nextFiberNode.sibling) {
361 | return nextFiberNode.sibling;
362 | }
363 |
364 | nextFiberNode = nextFiberNode.return;
365 | }
366 |
367 | return null;
368 | };
369 |
370 | // Use requestIdleCallback to query whether there is currently a unit task
371 | // and determine whether the DOM needs to be updated.
372 | const workLoop: IdleRequestCallback = (deadline) => {
373 | while (nextUnitOfWork && deadline.timeRemaining() > 1) {
374 | nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
375 | }
376 |
377 | if (!nextUnitOfWork && wipRoot) {
378 | commitRoot();
379 | }
380 |
381 | window.requestIdleCallback(workLoop);
382 | };
383 |
384 | // Initial or reset.
385 | const render = (element: VirtualElement, container: Element) => {
386 | currentRoot = null;
387 | wipRoot = {
388 | type: 'div',
389 | dom: container,
390 | props: {
391 | children: [{ ...element }],
392 | },
393 | alternate: currentRoot,
394 | };
395 | nextUnitOfWork = wipRoot;
396 | deletions = [];
397 | };
398 |
399 | abstract class Component {
400 | props: Record;
401 | abstract state: unknown;
402 | abstract setState: (value: unknown) => void;
403 | abstract render: () => VirtualElement;
404 |
405 | constructor(props: Record) {
406 | this.props = props;
407 | }
408 |
409 | // Identify Component.
410 | static REACT_COMPONENT = true;
411 | }
412 |
413 | // Associate the hook with the fiber node.
414 | function useState(initState: S): [S, (value: S) => void] {
415 | const fiberNode: FiberNode = wipFiber;
416 | const hook: {
417 | state: S;
418 | queue: S[];
419 | } = fiberNode?.alternate?.hooks
420 | ? fiberNode.alternate.hooks[hookIndex]
421 | : {
422 | state: initState,
423 | queue: [],
424 | };
425 |
426 | while (hook.queue.length) {
427 | let newState = hook.queue.shift();
428 | if (isPlainObject(hook.state) && isPlainObject(newState)) {
429 | newState = { ...hook.state, ...newState };
430 | }
431 | if (isDef(newState)) {
432 | hook.state = newState;
433 | }
434 | }
435 |
436 | if (typeof fiberNode.hooks === 'undefined') {
437 | fiberNode.hooks = [];
438 | }
439 |
440 | fiberNode.hooks.push(hook);
441 | hookIndex += 1;
442 |
443 | const setState = (value: S) => {
444 | hook.queue.push(value);
445 | if (currentRoot) {
446 | wipRoot = {
447 | type: currentRoot.type,
448 | dom: currentRoot.dom,
449 | props: currentRoot.props,
450 | alternate: currentRoot,
451 | };
452 | nextUnitOfWork = wipRoot;
453 | deletions = [];
454 | currentRoot = null;
455 | }
456 | };
457 |
458 | return [hook.state, setState];
459 | }
460 |
461 | // Start the engine!
462 | void (function main() {
463 | window.requestIdleCallback(workLoop);
464 | })();
465 |
466 | export default {
467 | createElement,
468 | render,
469 | useState,
470 | Component,
471 | Fragment,
472 | };
473 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '9.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | importers:
8 |
9 | .:
10 | devDependencies:
11 | '@vitejs/plugin-react':
12 | specifier: ^4.2.1
13 | version: 4.2.1(vite@5.2.11)
14 | typescript:
15 | specifier: ^5.4.5
16 | version: 5.4.5
17 | vite:
18 | specifier: ^5.2.11
19 | version: 5.2.11
20 |
21 | packages:
22 |
23 | '@ampproject/remapping@2.3.0':
24 | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
25 | engines: {node: '>=6.0.0'}
26 |
27 | '@babel/code-frame@7.24.2':
28 | resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==}
29 | engines: {node: '>=6.9.0'}
30 |
31 | '@babel/compat-data@7.24.4':
32 | resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==}
33 | engines: {node: '>=6.9.0'}
34 |
35 | '@babel/core@7.24.5':
36 | resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==}
37 | engines: {node: '>=6.9.0'}
38 |
39 | '@babel/generator@7.24.5':
40 | resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==}
41 | engines: {node: '>=6.9.0'}
42 |
43 | '@babel/helper-compilation-targets@7.23.6':
44 | resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==}
45 | engines: {node: '>=6.9.0'}
46 |
47 | '@babel/helper-environment-visitor@7.22.20':
48 | resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
49 | engines: {node: '>=6.9.0'}
50 |
51 | '@babel/helper-function-name@7.23.0':
52 | resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
53 | engines: {node: '>=6.9.0'}
54 |
55 | '@babel/helper-hoist-variables@7.22.5':
56 | resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
57 | engines: {node: '>=6.9.0'}
58 |
59 | '@babel/helper-module-imports@7.24.3':
60 | resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==}
61 | engines: {node: '>=6.9.0'}
62 |
63 | '@babel/helper-module-transforms@7.24.5':
64 | resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==}
65 | engines: {node: '>=6.9.0'}
66 | peerDependencies:
67 | '@babel/core': ^7.0.0
68 |
69 | '@babel/helper-plugin-utils@7.24.5':
70 | resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==}
71 | engines: {node: '>=6.9.0'}
72 |
73 | '@babel/helper-simple-access@7.24.5':
74 | resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==}
75 | engines: {node: '>=6.9.0'}
76 |
77 | '@babel/helper-split-export-declaration@7.24.5':
78 | resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==}
79 | engines: {node: '>=6.9.0'}
80 |
81 | '@babel/helper-string-parser@7.24.1':
82 | resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==}
83 | engines: {node: '>=6.9.0'}
84 |
85 | '@babel/helper-validator-identifier@7.24.5':
86 | resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==}
87 | engines: {node: '>=6.9.0'}
88 |
89 | '@babel/helper-validator-option@7.23.5':
90 | resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
91 | engines: {node: '>=6.9.0'}
92 |
93 | '@babel/helpers@7.24.5':
94 | resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==}
95 | engines: {node: '>=6.9.0'}
96 |
97 | '@babel/highlight@7.24.5':
98 | resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==}
99 | engines: {node: '>=6.9.0'}
100 |
101 | '@babel/parser@7.24.5':
102 | resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==}
103 | engines: {node: '>=6.0.0'}
104 | hasBin: true
105 |
106 | '@babel/plugin-transform-react-jsx-self@7.24.5':
107 | resolution: {integrity: sha512-RtCJoUO2oYrYwFPtR1/jkoBEcFuI1ae9a9IMxeyAVa3a1Ap4AnxmyIKG2b2FaJKqkidw/0cxRbWN+HOs6ZWd1w==}
108 | engines: {node: '>=6.9.0'}
109 | peerDependencies:
110 | '@babel/core': ^7.0.0-0
111 |
112 | '@babel/plugin-transform-react-jsx-source@7.24.1':
113 | resolution: {integrity: sha512-1v202n7aUq4uXAieRTKcwPzNyphlCuqHHDcdSNc+vdhoTEZcFMh+L5yZuCmGaIO7bs1nJUNfHB89TZyoL48xNA==}
114 | engines: {node: '>=6.9.0'}
115 | peerDependencies:
116 | '@babel/core': ^7.0.0-0
117 |
118 | '@babel/template@7.24.0':
119 | resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==}
120 | engines: {node: '>=6.9.0'}
121 |
122 | '@babel/traverse@7.24.5':
123 | resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==}
124 | engines: {node: '>=6.9.0'}
125 |
126 | '@babel/types@7.24.5':
127 | resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==}
128 | engines: {node: '>=6.9.0'}
129 |
130 | '@esbuild/aix-ppc64@0.20.2':
131 | resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==}
132 | engines: {node: '>=12'}
133 | cpu: [ppc64]
134 | os: [aix]
135 |
136 | '@esbuild/android-arm64@0.20.2':
137 | resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==}
138 | engines: {node: '>=12'}
139 | cpu: [arm64]
140 | os: [android]
141 |
142 | '@esbuild/android-arm@0.20.2':
143 | resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==}
144 | engines: {node: '>=12'}
145 | cpu: [arm]
146 | os: [android]
147 |
148 | '@esbuild/android-x64@0.20.2':
149 | resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==}
150 | engines: {node: '>=12'}
151 | cpu: [x64]
152 | os: [android]
153 |
154 | '@esbuild/darwin-arm64@0.20.2':
155 | resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==}
156 | engines: {node: '>=12'}
157 | cpu: [arm64]
158 | os: [darwin]
159 |
160 | '@esbuild/darwin-x64@0.20.2':
161 | resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==}
162 | engines: {node: '>=12'}
163 | cpu: [x64]
164 | os: [darwin]
165 |
166 | '@esbuild/freebsd-arm64@0.20.2':
167 | resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==}
168 | engines: {node: '>=12'}
169 | cpu: [arm64]
170 | os: [freebsd]
171 |
172 | '@esbuild/freebsd-x64@0.20.2':
173 | resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==}
174 | engines: {node: '>=12'}
175 | cpu: [x64]
176 | os: [freebsd]
177 |
178 | '@esbuild/linux-arm64@0.20.2':
179 | resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==}
180 | engines: {node: '>=12'}
181 | cpu: [arm64]
182 | os: [linux]
183 |
184 | '@esbuild/linux-arm@0.20.2':
185 | resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==}
186 | engines: {node: '>=12'}
187 | cpu: [arm]
188 | os: [linux]
189 |
190 | '@esbuild/linux-ia32@0.20.2':
191 | resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==}
192 | engines: {node: '>=12'}
193 | cpu: [ia32]
194 | os: [linux]
195 |
196 | '@esbuild/linux-loong64@0.20.2':
197 | resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==}
198 | engines: {node: '>=12'}
199 | cpu: [loong64]
200 | os: [linux]
201 |
202 | '@esbuild/linux-mips64el@0.20.2':
203 | resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==}
204 | engines: {node: '>=12'}
205 | cpu: [mips64el]
206 | os: [linux]
207 |
208 | '@esbuild/linux-ppc64@0.20.2':
209 | resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==}
210 | engines: {node: '>=12'}
211 | cpu: [ppc64]
212 | os: [linux]
213 |
214 | '@esbuild/linux-riscv64@0.20.2':
215 | resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==}
216 | engines: {node: '>=12'}
217 | cpu: [riscv64]
218 | os: [linux]
219 |
220 | '@esbuild/linux-s390x@0.20.2':
221 | resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==}
222 | engines: {node: '>=12'}
223 | cpu: [s390x]
224 | os: [linux]
225 |
226 | '@esbuild/linux-x64@0.20.2':
227 | resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==}
228 | engines: {node: '>=12'}
229 | cpu: [x64]
230 | os: [linux]
231 |
232 | '@esbuild/netbsd-x64@0.20.2':
233 | resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==}
234 | engines: {node: '>=12'}
235 | cpu: [x64]
236 | os: [netbsd]
237 |
238 | '@esbuild/openbsd-x64@0.20.2':
239 | resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==}
240 | engines: {node: '>=12'}
241 | cpu: [x64]
242 | os: [openbsd]
243 |
244 | '@esbuild/sunos-x64@0.20.2':
245 | resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==}
246 | engines: {node: '>=12'}
247 | cpu: [x64]
248 | os: [sunos]
249 |
250 | '@esbuild/win32-arm64@0.20.2':
251 | resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==}
252 | engines: {node: '>=12'}
253 | cpu: [arm64]
254 | os: [win32]
255 |
256 | '@esbuild/win32-ia32@0.20.2':
257 | resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==}
258 | engines: {node: '>=12'}
259 | cpu: [ia32]
260 | os: [win32]
261 |
262 | '@esbuild/win32-x64@0.20.2':
263 | resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==}
264 | engines: {node: '>=12'}
265 | cpu: [x64]
266 | os: [win32]
267 |
268 | '@jridgewell/gen-mapping@0.3.5':
269 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
270 | engines: {node: '>=6.0.0'}
271 |
272 | '@jridgewell/resolve-uri@3.1.2':
273 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
274 | engines: {node: '>=6.0.0'}
275 |
276 | '@jridgewell/set-array@1.2.1':
277 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
278 | engines: {node: '>=6.0.0'}
279 |
280 | '@jridgewell/sourcemap-codec@1.4.15':
281 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
282 |
283 | '@jridgewell/trace-mapping@0.3.25':
284 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
285 |
286 | '@rollup/rollup-android-arm-eabi@4.17.2':
287 | resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==}
288 | cpu: [arm]
289 | os: [android]
290 |
291 | '@rollup/rollup-android-arm64@4.17.2':
292 | resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==}
293 | cpu: [arm64]
294 | os: [android]
295 |
296 | '@rollup/rollup-darwin-arm64@4.17.2':
297 | resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==}
298 | cpu: [arm64]
299 | os: [darwin]
300 |
301 | '@rollup/rollup-darwin-x64@4.17.2':
302 | resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==}
303 | cpu: [x64]
304 | os: [darwin]
305 |
306 | '@rollup/rollup-linux-arm-gnueabihf@4.17.2':
307 | resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==}
308 | cpu: [arm]
309 | os: [linux]
310 |
311 | '@rollup/rollup-linux-arm-musleabihf@4.17.2':
312 | resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==}
313 | cpu: [arm]
314 | os: [linux]
315 |
316 | '@rollup/rollup-linux-arm64-gnu@4.17.2':
317 | resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==}
318 | cpu: [arm64]
319 | os: [linux]
320 |
321 | '@rollup/rollup-linux-arm64-musl@4.17.2':
322 | resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==}
323 | cpu: [arm64]
324 | os: [linux]
325 |
326 | '@rollup/rollup-linux-powerpc64le-gnu@4.17.2':
327 | resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==}
328 | cpu: [ppc64]
329 | os: [linux]
330 |
331 | '@rollup/rollup-linux-riscv64-gnu@4.17.2':
332 | resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==}
333 | cpu: [riscv64]
334 | os: [linux]
335 |
336 | '@rollup/rollup-linux-s390x-gnu@4.17.2':
337 | resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==}
338 | cpu: [s390x]
339 | os: [linux]
340 |
341 | '@rollup/rollup-linux-x64-gnu@4.17.2':
342 | resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==}
343 | cpu: [x64]
344 | os: [linux]
345 |
346 | '@rollup/rollup-linux-x64-musl@4.17.2':
347 | resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==}
348 | cpu: [x64]
349 | os: [linux]
350 |
351 | '@rollup/rollup-win32-arm64-msvc@4.17.2':
352 | resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==}
353 | cpu: [arm64]
354 | os: [win32]
355 |
356 | '@rollup/rollup-win32-ia32-msvc@4.17.2':
357 | resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==}
358 | cpu: [ia32]
359 | os: [win32]
360 |
361 | '@rollup/rollup-win32-x64-msvc@4.17.2':
362 | resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==}
363 | cpu: [x64]
364 | os: [win32]
365 |
366 | '@types/babel__core@7.20.5':
367 | resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
368 |
369 | '@types/babel__generator@7.6.8':
370 | resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==}
371 |
372 | '@types/babel__template@7.4.4':
373 | resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
374 |
375 | '@types/babel__traverse@7.20.5':
376 | resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==}
377 |
378 | '@types/estree@1.0.5':
379 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
380 |
381 | '@vitejs/plugin-react@4.2.1':
382 | resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==}
383 | engines: {node: ^14.18.0 || >=16.0.0}
384 | peerDependencies:
385 | vite: ^4.2.0 || ^5.0.0
386 |
387 | ansi-styles@3.2.1:
388 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
389 | engines: {node: '>=4'}
390 |
391 | browserslist@4.23.0:
392 | resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==}
393 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
394 | hasBin: true
395 |
396 | caniuse-lite@1.0.30001617:
397 | resolution: {integrity: sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==}
398 |
399 | chalk@2.4.2:
400 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
401 | engines: {node: '>=4'}
402 |
403 | color-convert@1.9.3:
404 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
405 |
406 | color-name@1.1.3:
407 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
408 |
409 | convert-source-map@2.0.0:
410 | resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
411 |
412 | debug@4.3.4:
413 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
414 | engines: {node: '>=6.0'}
415 | peerDependencies:
416 | supports-color: '*'
417 | peerDependenciesMeta:
418 | supports-color:
419 | optional: true
420 |
421 | electron-to-chromium@1.4.760:
422 | resolution: {integrity: sha512-xF6AWMVM/QGQseTPgXjUewfNjCW2fgUcV/z5cSG0r+SiYcgtvcmRAL3oH/MSZwHBBD+fyKTXdQ4qGENJMSedEQ==}
423 |
424 | esbuild@0.20.2:
425 | resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==}
426 | engines: {node: '>=12'}
427 | hasBin: true
428 |
429 | escalade@3.1.2:
430 | resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
431 | engines: {node: '>=6'}
432 |
433 | escape-string-regexp@1.0.5:
434 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
435 | engines: {node: '>=0.8.0'}
436 |
437 | fsevents@2.3.3:
438 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
439 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
440 | os: [darwin]
441 |
442 | gensync@1.0.0-beta.2:
443 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
444 | engines: {node: '>=6.9.0'}
445 |
446 | globals@11.12.0:
447 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
448 | engines: {node: '>=4'}
449 |
450 | has-flag@3.0.0:
451 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
452 | engines: {node: '>=4'}
453 |
454 | js-tokens@4.0.0:
455 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
456 |
457 | jsesc@2.5.2:
458 | resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
459 | engines: {node: '>=4'}
460 | hasBin: true
461 |
462 | json5@2.2.3:
463 | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
464 | engines: {node: '>=6'}
465 | hasBin: true
466 |
467 | lru-cache@5.1.1:
468 | resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
469 |
470 | ms@2.1.2:
471 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
472 |
473 | nanoid@3.3.7:
474 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
475 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
476 | hasBin: true
477 |
478 | node-releases@2.0.14:
479 | resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
480 |
481 | picocolors@1.0.0:
482 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
483 |
484 | postcss@8.4.38:
485 | resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
486 | engines: {node: ^10 || ^12 || >=14}
487 |
488 | react-refresh@0.14.2:
489 | resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
490 | engines: {node: '>=0.10.0'}
491 |
492 | rollup@4.17.2:
493 | resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==}
494 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
495 | hasBin: true
496 |
497 | semver@6.3.1:
498 | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
499 | hasBin: true
500 |
501 | source-map-js@1.2.0:
502 | resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
503 | engines: {node: '>=0.10.0'}
504 |
505 | supports-color@5.5.0:
506 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
507 | engines: {node: '>=4'}
508 |
509 | to-fast-properties@2.0.0:
510 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
511 | engines: {node: '>=4'}
512 |
513 | typescript@5.4.5:
514 | resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
515 | engines: {node: '>=14.17'}
516 | hasBin: true
517 |
518 | update-browserslist-db@1.0.15:
519 | resolution: {integrity: sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==}
520 | hasBin: true
521 | peerDependencies:
522 | browserslist: '>= 4.21.0'
523 |
524 | vite@5.2.11:
525 | resolution: {integrity: sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==}
526 | engines: {node: ^18.0.0 || >=20.0.0}
527 | hasBin: true
528 | peerDependencies:
529 | '@types/node': ^18.0.0 || >=20.0.0
530 | less: '*'
531 | lightningcss: ^1.21.0
532 | sass: '*'
533 | stylus: '*'
534 | sugarss: '*'
535 | terser: ^5.4.0
536 | peerDependenciesMeta:
537 | '@types/node':
538 | optional: true
539 | less:
540 | optional: true
541 | lightningcss:
542 | optional: true
543 | sass:
544 | optional: true
545 | stylus:
546 | optional: true
547 | sugarss:
548 | optional: true
549 | terser:
550 | optional: true
551 |
552 | yallist@3.1.1:
553 | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
554 |
555 | snapshots:
556 |
557 | '@ampproject/remapping@2.3.0':
558 | dependencies:
559 | '@jridgewell/gen-mapping': 0.3.5
560 | '@jridgewell/trace-mapping': 0.3.25
561 |
562 | '@babel/code-frame@7.24.2':
563 | dependencies:
564 | '@babel/highlight': 7.24.5
565 | picocolors: 1.0.0
566 |
567 | '@babel/compat-data@7.24.4': {}
568 |
569 | '@babel/core@7.24.5':
570 | dependencies:
571 | '@ampproject/remapping': 2.3.0
572 | '@babel/code-frame': 7.24.2
573 | '@babel/generator': 7.24.5
574 | '@babel/helper-compilation-targets': 7.23.6
575 | '@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5)
576 | '@babel/helpers': 7.24.5
577 | '@babel/parser': 7.24.5
578 | '@babel/template': 7.24.0
579 | '@babel/traverse': 7.24.5
580 | '@babel/types': 7.24.5
581 | convert-source-map: 2.0.0
582 | debug: 4.3.4
583 | gensync: 1.0.0-beta.2
584 | json5: 2.2.3
585 | semver: 6.3.1
586 | transitivePeerDependencies:
587 | - supports-color
588 |
589 | '@babel/generator@7.24.5':
590 | dependencies:
591 | '@babel/types': 7.24.5
592 | '@jridgewell/gen-mapping': 0.3.5
593 | '@jridgewell/trace-mapping': 0.3.25
594 | jsesc: 2.5.2
595 |
596 | '@babel/helper-compilation-targets@7.23.6':
597 | dependencies:
598 | '@babel/compat-data': 7.24.4
599 | '@babel/helper-validator-option': 7.23.5
600 | browserslist: 4.23.0
601 | lru-cache: 5.1.1
602 | semver: 6.3.1
603 |
604 | '@babel/helper-environment-visitor@7.22.20': {}
605 |
606 | '@babel/helper-function-name@7.23.0':
607 | dependencies:
608 | '@babel/template': 7.24.0
609 | '@babel/types': 7.24.5
610 |
611 | '@babel/helper-hoist-variables@7.22.5':
612 | dependencies:
613 | '@babel/types': 7.24.5
614 |
615 | '@babel/helper-module-imports@7.24.3':
616 | dependencies:
617 | '@babel/types': 7.24.5
618 |
619 | '@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5)':
620 | dependencies:
621 | '@babel/core': 7.24.5
622 | '@babel/helper-environment-visitor': 7.22.20
623 | '@babel/helper-module-imports': 7.24.3
624 | '@babel/helper-simple-access': 7.24.5
625 | '@babel/helper-split-export-declaration': 7.24.5
626 | '@babel/helper-validator-identifier': 7.24.5
627 |
628 | '@babel/helper-plugin-utils@7.24.5': {}
629 |
630 | '@babel/helper-simple-access@7.24.5':
631 | dependencies:
632 | '@babel/types': 7.24.5
633 |
634 | '@babel/helper-split-export-declaration@7.24.5':
635 | dependencies:
636 | '@babel/types': 7.24.5
637 |
638 | '@babel/helper-string-parser@7.24.1': {}
639 |
640 | '@babel/helper-validator-identifier@7.24.5': {}
641 |
642 | '@babel/helper-validator-option@7.23.5': {}
643 |
644 | '@babel/helpers@7.24.5':
645 | dependencies:
646 | '@babel/template': 7.24.0
647 | '@babel/traverse': 7.24.5
648 | '@babel/types': 7.24.5
649 | transitivePeerDependencies:
650 | - supports-color
651 |
652 | '@babel/highlight@7.24.5':
653 | dependencies:
654 | '@babel/helper-validator-identifier': 7.24.5
655 | chalk: 2.4.2
656 | js-tokens: 4.0.0
657 | picocolors: 1.0.0
658 |
659 | '@babel/parser@7.24.5':
660 | dependencies:
661 | '@babel/types': 7.24.5
662 |
663 | '@babel/plugin-transform-react-jsx-self@7.24.5(@babel/core@7.24.5)':
664 | dependencies:
665 | '@babel/core': 7.24.5
666 | '@babel/helper-plugin-utils': 7.24.5
667 |
668 | '@babel/plugin-transform-react-jsx-source@7.24.1(@babel/core@7.24.5)':
669 | dependencies:
670 | '@babel/core': 7.24.5
671 | '@babel/helper-plugin-utils': 7.24.5
672 |
673 | '@babel/template@7.24.0':
674 | dependencies:
675 | '@babel/code-frame': 7.24.2
676 | '@babel/parser': 7.24.5
677 | '@babel/types': 7.24.5
678 |
679 | '@babel/traverse@7.24.5':
680 | dependencies:
681 | '@babel/code-frame': 7.24.2
682 | '@babel/generator': 7.24.5
683 | '@babel/helper-environment-visitor': 7.22.20
684 | '@babel/helper-function-name': 7.23.0
685 | '@babel/helper-hoist-variables': 7.22.5
686 | '@babel/helper-split-export-declaration': 7.24.5
687 | '@babel/parser': 7.24.5
688 | '@babel/types': 7.24.5
689 | debug: 4.3.4
690 | globals: 11.12.0
691 | transitivePeerDependencies:
692 | - supports-color
693 |
694 | '@babel/types@7.24.5':
695 | dependencies:
696 | '@babel/helper-string-parser': 7.24.1
697 | '@babel/helper-validator-identifier': 7.24.5
698 | to-fast-properties: 2.0.0
699 |
700 | '@esbuild/aix-ppc64@0.20.2':
701 | optional: true
702 |
703 | '@esbuild/android-arm64@0.20.2':
704 | optional: true
705 |
706 | '@esbuild/android-arm@0.20.2':
707 | optional: true
708 |
709 | '@esbuild/android-x64@0.20.2':
710 | optional: true
711 |
712 | '@esbuild/darwin-arm64@0.20.2':
713 | optional: true
714 |
715 | '@esbuild/darwin-x64@0.20.2':
716 | optional: true
717 |
718 | '@esbuild/freebsd-arm64@0.20.2':
719 | optional: true
720 |
721 | '@esbuild/freebsd-x64@0.20.2':
722 | optional: true
723 |
724 | '@esbuild/linux-arm64@0.20.2':
725 | optional: true
726 |
727 | '@esbuild/linux-arm@0.20.2':
728 | optional: true
729 |
730 | '@esbuild/linux-ia32@0.20.2':
731 | optional: true
732 |
733 | '@esbuild/linux-loong64@0.20.2':
734 | optional: true
735 |
736 | '@esbuild/linux-mips64el@0.20.2':
737 | optional: true
738 |
739 | '@esbuild/linux-ppc64@0.20.2':
740 | optional: true
741 |
742 | '@esbuild/linux-riscv64@0.20.2':
743 | optional: true
744 |
745 | '@esbuild/linux-s390x@0.20.2':
746 | optional: true
747 |
748 | '@esbuild/linux-x64@0.20.2':
749 | optional: true
750 |
751 | '@esbuild/netbsd-x64@0.20.2':
752 | optional: true
753 |
754 | '@esbuild/openbsd-x64@0.20.2':
755 | optional: true
756 |
757 | '@esbuild/sunos-x64@0.20.2':
758 | optional: true
759 |
760 | '@esbuild/win32-arm64@0.20.2':
761 | optional: true
762 |
763 | '@esbuild/win32-ia32@0.20.2':
764 | optional: true
765 |
766 | '@esbuild/win32-x64@0.20.2':
767 | optional: true
768 |
769 | '@jridgewell/gen-mapping@0.3.5':
770 | dependencies:
771 | '@jridgewell/set-array': 1.2.1
772 | '@jridgewell/sourcemap-codec': 1.4.15
773 | '@jridgewell/trace-mapping': 0.3.25
774 |
775 | '@jridgewell/resolve-uri@3.1.2': {}
776 |
777 | '@jridgewell/set-array@1.2.1': {}
778 |
779 | '@jridgewell/sourcemap-codec@1.4.15': {}
780 |
781 | '@jridgewell/trace-mapping@0.3.25':
782 | dependencies:
783 | '@jridgewell/resolve-uri': 3.1.2
784 | '@jridgewell/sourcemap-codec': 1.4.15
785 |
786 | '@rollup/rollup-android-arm-eabi@4.17.2':
787 | optional: true
788 |
789 | '@rollup/rollup-android-arm64@4.17.2':
790 | optional: true
791 |
792 | '@rollup/rollup-darwin-arm64@4.17.2':
793 | optional: true
794 |
795 | '@rollup/rollup-darwin-x64@4.17.2':
796 | optional: true
797 |
798 | '@rollup/rollup-linux-arm-gnueabihf@4.17.2':
799 | optional: true
800 |
801 | '@rollup/rollup-linux-arm-musleabihf@4.17.2':
802 | optional: true
803 |
804 | '@rollup/rollup-linux-arm64-gnu@4.17.2':
805 | optional: true
806 |
807 | '@rollup/rollup-linux-arm64-musl@4.17.2':
808 | optional: true
809 |
810 | '@rollup/rollup-linux-powerpc64le-gnu@4.17.2':
811 | optional: true
812 |
813 | '@rollup/rollup-linux-riscv64-gnu@4.17.2':
814 | optional: true
815 |
816 | '@rollup/rollup-linux-s390x-gnu@4.17.2':
817 | optional: true
818 |
819 | '@rollup/rollup-linux-x64-gnu@4.17.2':
820 | optional: true
821 |
822 | '@rollup/rollup-linux-x64-musl@4.17.2':
823 | optional: true
824 |
825 | '@rollup/rollup-win32-arm64-msvc@4.17.2':
826 | optional: true
827 |
828 | '@rollup/rollup-win32-ia32-msvc@4.17.2':
829 | optional: true
830 |
831 | '@rollup/rollup-win32-x64-msvc@4.17.2':
832 | optional: true
833 |
834 | '@types/babel__core@7.20.5':
835 | dependencies:
836 | '@babel/parser': 7.24.5
837 | '@babel/types': 7.24.5
838 | '@types/babel__generator': 7.6.8
839 | '@types/babel__template': 7.4.4
840 | '@types/babel__traverse': 7.20.5
841 |
842 | '@types/babel__generator@7.6.8':
843 | dependencies:
844 | '@babel/types': 7.24.5
845 |
846 | '@types/babel__template@7.4.4':
847 | dependencies:
848 | '@babel/parser': 7.24.5
849 | '@babel/types': 7.24.5
850 |
851 | '@types/babel__traverse@7.20.5':
852 | dependencies:
853 | '@babel/types': 7.24.5
854 |
855 | '@types/estree@1.0.5': {}
856 |
857 | '@vitejs/plugin-react@4.2.1(vite@5.2.11)':
858 | dependencies:
859 | '@babel/core': 7.24.5
860 | '@babel/plugin-transform-react-jsx-self': 7.24.5(@babel/core@7.24.5)
861 | '@babel/plugin-transform-react-jsx-source': 7.24.1(@babel/core@7.24.5)
862 | '@types/babel__core': 7.20.5
863 | react-refresh: 0.14.2
864 | vite: 5.2.11
865 | transitivePeerDependencies:
866 | - supports-color
867 |
868 | ansi-styles@3.2.1:
869 | dependencies:
870 | color-convert: 1.9.3
871 |
872 | browserslist@4.23.0:
873 | dependencies:
874 | caniuse-lite: 1.0.30001617
875 | electron-to-chromium: 1.4.760
876 | node-releases: 2.0.14
877 | update-browserslist-db: 1.0.15(browserslist@4.23.0)
878 |
879 | caniuse-lite@1.0.30001617: {}
880 |
881 | chalk@2.4.2:
882 | dependencies:
883 | ansi-styles: 3.2.1
884 | escape-string-regexp: 1.0.5
885 | supports-color: 5.5.0
886 |
887 | color-convert@1.9.3:
888 | dependencies:
889 | color-name: 1.1.3
890 |
891 | color-name@1.1.3: {}
892 |
893 | convert-source-map@2.0.0: {}
894 |
895 | debug@4.3.4:
896 | dependencies:
897 | ms: 2.1.2
898 |
899 | electron-to-chromium@1.4.760: {}
900 |
901 | esbuild@0.20.2:
902 | optionalDependencies:
903 | '@esbuild/aix-ppc64': 0.20.2
904 | '@esbuild/android-arm': 0.20.2
905 | '@esbuild/android-arm64': 0.20.2
906 | '@esbuild/android-x64': 0.20.2
907 | '@esbuild/darwin-arm64': 0.20.2
908 | '@esbuild/darwin-x64': 0.20.2
909 | '@esbuild/freebsd-arm64': 0.20.2
910 | '@esbuild/freebsd-x64': 0.20.2
911 | '@esbuild/linux-arm': 0.20.2
912 | '@esbuild/linux-arm64': 0.20.2
913 | '@esbuild/linux-ia32': 0.20.2
914 | '@esbuild/linux-loong64': 0.20.2
915 | '@esbuild/linux-mips64el': 0.20.2
916 | '@esbuild/linux-ppc64': 0.20.2
917 | '@esbuild/linux-riscv64': 0.20.2
918 | '@esbuild/linux-s390x': 0.20.2
919 | '@esbuild/linux-x64': 0.20.2
920 | '@esbuild/netbsd-x64': 0.20.2
921 | '@esbuild/openbsd-x64': 0.20.2
922 | '@esbuild/sunos-x64': 0.20.2
923 | '@esbuild/win32-arm64': 0.20.2
924 | '@esbuild/win32-ia32': 0.20.2
925 | '@esbuild/win32-x64': 0.20.2
926 |
927 | escalade@3.1.2: {}
928 |
929 | escape-string-regexp@1.0.5: {}
930 |
931 | fsevents@2.3.3:
932 | optional: true
933 |
934 | gensync@1.0.0-beta.2: {}
935 |
936 | globals@11.12.0: {}
937 |
938 | has-flag@3.0.0: {}
939 |
940 | js-tokens@4.0.0: {}
941 |
942 | jsesc@2.5.2: {}
943 |
944 | json5@2.2.3: {}
945 |
946 | lru-cache@5.1.1:
947 | dependencies:
948 | yallist: 3.1.1
949 |
950 | ms@2.1.2: {}
951 |
952 | nanoid@3.3.7: {}
953 |
954 | node-releases@2.0.14: {}
955 |
956 | picocolors@1.0.0: {}
957 |
958 | postcss@8.4.38:
959 | dependencies:
960 | nanoid: 3.3.7
961 | picocolors: 1.0.0
962 | source-map-js: 1.2.0
963 |
964 | react-refresh@0.14.2: {}
965 |
966 | rollup@4.17.2:
967 | dependencies:
968 | '@types/estree': 1.0.5
969 | optionalDependencies:
970 | '@rollup/rollup-android-arm-eabi': 4.17.2
971 | '@rollup/rollup-android-arm64': 4.17.2
972 | '@rollup/rollup-darwin-arm64': 4.17.2
973 | '@rollup/rollup-darwin-x64': 4.17.2
974 | '@rollup/rollup-linux-arm-gnueabihf': 4.17.2
975 | '@rollup/rollup-linux-arm-musleabihf': 4.17.2
976 | '@rollup/rollup-linux-arm64-gnu': 4.17.2
977 | '@rollup/rollup-linux-arm64-musl': 4.17.2
978 | '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2
979 | '@rollup/rollup-linux-riscv64-gnu': 4.17.2
980 | '@rollup/rollup-linux-s390x-gnu': 4.17.2
981 | '@rollup/rollup-linux-x64-gnu': 4.17.2
982 | '@rollup/rollup-linux-x64-musl': 4.17.2
983 | '@rollup/rollup-win32-arm64-msvc': 4.17.2
984 | '@rollup/rollup-win32-ia32-msvc': 4.17.2
985 | '@rollup/rollup-win32-x64-msvc': 4.17.2
986 | fsevents: 2.3.3
987 |
988 | semver@6.3.1: {}
989 |
990 | source-map-js@1.2.0: {}
991 |
992 | supports-color@5.5.0:
993 | dependencies:
994 | has-flag: 3.0.0
995 |
996 | to-fast-properties@2.0.0: {}
997 |
998 | typescript@5.4.5: {}
999 |
1000 | update-browserslist-db@1.0.15(browserslist@4.23.0):
1001 | dependencies:
1002 | browserslist: 4.23.0
1003 | escalade: 3.1.2
1004 | picocolors: 1.0.0
1005 |
1006 | vite@5.2.11:
1007 | dependencies:
1008 | esbuild: 0.20.2
1009 | postcss: 8.4.38
1010 | rollup: 4.17.2
1011 | optionalDependencies:
1012 | fsevents: 2.3.3
1013 |
1014 | yallist@3.1.1: {}
1015 |
--------------------------------------------------------------------------------