├── public ├── shipGroup.png └── favicon.svg ├── vite.config.js ├── src ├── components │ ├── Game │ │ ├── Ship.jsx │ │ ├── Tip.jsx │ │ ├── Harbour.jsx │ │ ├── game.css │ │ ├── Board.jsx │ │ ├── AttackBoard.jsx │ │ └── Game.jsx │ ├── Header.jsx │ ├── GameOver │ │ ├── MiniBoard.jsx │ │ ├── over.css │ │ ├── DataCard.jsx │ │ └── GameOver.jsx │ ├── Wrapper.jsx │ └── Welcome │ │ ├── welcome.css │ │ └── Welcome.jsx ├── utils │ ├── ships.js │ ├── blockStates.js │ ├── gameState.js │ ├── computerTools.js │ └── boardTools.js ├── App.css ├── main.jsx ├── lang │ ├── zh-CN.json │ └── en-US.json ├── App.jsx └── index.css ├── .gitignore ├── package.json ├── index.html ├── LICENSE ├── README.md └── yarn.lock /public/shipGroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KelvinQiu802/battleship/HEAD/public/shipGroup.png -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | base: './', 8 | }); 9 | -------------------------------------------------------------------------------- /src/components/Game/Ship.jsx: -------------------------------------------------------------------------------- 1 | const Ship = ({ length }) => { 2 | return ( 3 |
4 | {[...new Array(length)].map((item, index) => ( 5 |
6 | ))} 7 |
8 | ); 9 | }; 10 | 11 | export default Ship; 12 | -------------------------------------------------------------------------------- /src/components/Header.jsx: -------------------------------------------------------------------------------- 1 | import logo from '/favicon.svg'; 2 | 3 | const Header = () => { 4 | return ( 5 |
6 | logo 7 |

Battleship

8 |
9 | ); 10 | }; 11 | 12 | export default Header; 13 | -------------------------------------------------------------------------------- /.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 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/utils/ships.js: -------------------------------------------------------------------------------- 1 | // 船基本属性 2 | export const CARRIER = { name: 'Carrier', zh: '航空母舰', length: 5 }; 3 | export const BATTLESHIP = { name: 'Battleship', zh: '战舰', length: 4 }; 4 | export const DESTROYER = { name: 'Destroyer', zh: '驱逐舰', length: 3 }; 5 | export const SUBMARINE = { name: 'Submarine', zh: '潜水艇', length: 3 }; 6 | export const PATROL = { name: 'Patrol', zh: '巡逻舰', length: 2 }; 7 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .area { 2 | width: 1200px; 3 | margin: 0 auto; 4 | } 5 | 6 | .header { 7 | display: flex; 8 | width: 30px; 9 | background-color: #f4f4f5b2; 10 | width: 100%; 11 | padding: 6px 0; 12 | box-shadow: rgba(0, 0, 0, 0.15) 1.95px 1.95px 2.6px; 13 | } 14 | 15 | .header img { 16 | width: 50px; 17 | margin-left: 80px; 18 | } 19 | 20 | .header-title { 21 | position: relative; 22 | top: 10px; 23 | margin-left: 20px; 24 | font-size: 2em; 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/blockStates.js: -------------------------------------------------------------------------------- 1 | export const EMTPY = 'empty'; 2 | export const SHIP = 'ship'; 3 | export const CARRIER = 'Carrier'; 4 | export const BATTLESHIP = 'Battleship'; 5 | export const DESTROYER = 'Destroyer'; 6 | export const SUBMARINE = 'Submarine'; 7 | export const PATROL = 'Patrol'; 8 | export const FORBIDDEN = 'forbidden'; 9 | export const PLACING = 'placing'; 10 | export const HIT = 'hit'; 11 | export const MISS = 'miss'; 12 | export const SELECTING = 'selecting'; 13 | export const SANK = 'sank'; 14 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App'; 4 | import Wrapper from './components/Wrapper'; 5 | import './index.css'; 6 | import './components/Welcome/welcome.css'; 7 | import './components/Game/game.css'; 8 | import './components/GameOver/over.css'; 9 | 10 | ReactDOM.createRoot(document.getElementById('root')).render( 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /src/utils/gameState.js: -------------------------------------------------------------------------------- 1 | export const WELCOME = 'welcome'; 2 | export const P1PLACING = 'p1placing'; 3 | export const P2PLACING = 'p2placing'; 4 | export const COMPUTER_PLACING = 'computerPlacing'; 5 | export const READY = 'ready'; 6 | export const START = 'start'; 7 | export const P1ATTACK = 'p1attack'; 8 | export const P2ATTACK = 'p2attack'; 9 | export const COMPUTER_ATTACK = 'computerAttack'; 10 | export const P1WIN = 'p1win'; 11 | export const P2WIN = 'p2win'; 12 | export const COMPUTER_WIN = 'computerWin'; 13 | -------------------------------------------------------------------------------- /src/components/GameOver/MiniBoard.jsx: -------------------------------------------------------------------------------- 1 | const MiniBoard = ({ finalBoard, name, player }) => { 2 | return ( 3 |
4 |
e.preventDefault()} 9 | > 10 | {finalBoard.current.map((state, index) => ( 11 |
16 | ))} 17 |
18 |
19 | ); 20 | }; 21 | 22 | export default MiniBoard; 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "battleship", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11.10.0", 13 | "@emotion/styled": "^11.10.0", 14 | "@mui/icons-material": "^5.8.4", 15 | "@mui/material": "^5.10.1", 16 | "react": "^18.2.0", 17 | "react-dom": "^18.2.0", 18 | "react-intl": "^6.0.5" 19 | }, 20 | "devDependencies": { 21 | "@types/react": "^18.0.15", 22 | "@types/react-dom": "^18.0.6", 23 | "@vitejs/plugin-react": "^2.0.0", 24 | "vite": "^3.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | Battleship 14 | 15 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/components/Game/Tip.jsx: -------------------------------------------------------------------------------- 1 | import * as GAME_STATE from '../../utils/gameState'; 2 | import { FormattedMessage } from 'react-intl'; 3 | 4 | const Tip = ({ gameState }) => { 5 | let message; 6 | switch (gameState) { 7 | case GAME_STATE.P1PLACING: 8 | case GAME_STATE.P2PLACING: 9 | message = 10 | 13 | break; 14 | case GAME_STATE.P1ATTACK: 15 | message = 16 | 19 | break; 20 | case GAME_STATE.P2ATTACK: 21 | message = 22 | 25 | } 26 | return

{message}

; 27 | }; 28 | 29 | export default Tip; 30 | -------------------------------------------------------------------------------- /src/lang/zh-CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": "欢迎!", 3 | "welcome.introduction": "海战棋(Battleship)是一款双人游玩的猜谜游戏", 4 | "welcome.p1Name": "玩家一名称: ", 5 | "welcome.p2Name": "玩家二名称: ", 6 | "welcome.difficulty": "难度: ", 7 | "welcome.difficulty.easy": "简单", 8 | "welcome.difficulty.normal": "普通", 9 | "welcome.mode": "模式: ", 10 | "welcome.mode.one": "单人", 11 | "welcome.mode.two": "双人", 12 | "welcome.lang": "语言: ", 13 | "welcome.start": "开始游戏", 14 | "board.title": "{name}的棋盘", 15 | "board.waitMessage": "等待玩家{isP1}放置", 16 | "tip.placing": "选择船只后在棋盘上放置,右键旋转方向", 17 | "tip.p1Attack": "玩家一: 在右侧棋盘上选择坐标进行攻击⬆", 18 | "tip.p2Attack": "⬆玩家二: 在左侧棋盘上选择坐标进行攻击", 19 | "over.title": "游戏结束", 20 | "over.winner": "赢家是:{winner}", 21 | "over.numberOfAttack": "攻击次数: ", 22 | "over.numberOfHit":"命中次数: ", 23 | "over.numberOfMiss":"脱靶次数: ", 24 | "over.hitRate": "命中率: " 25 | } -------------------------------------------------------------------------------- /src/components/Wrapper.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { IntlProvider } from 'react-intl'; 3 | import Chinese from '../lang/zh-CN.json'; 4 | import English from '../lang/en-US.json'; 5 | 6 | export const Context = React.createContext(); 7 | 8 | export const local = navigator.language; 9 | 10 | let lang; 11 | if (local === 'zh-CN') { 12 | lang = Chinese; 13 | } else { 14 | lang = English; 15 | } 16 | 17 | 18 | const Wrapper = ({ children }) => { 19 | const [locale, setLocale] = useState(local); 20 | const [messages, setMessages] = useState(lang); 21 | 22 | // 切换语言 23 | const selectLanguage = (e) => { 24 | setLocale(e.target.value); 25 | if (e.target.value === 'zh-CN') { 26 | setMessages(Chinese); 27 | } else { 28 | setMessages(English); 29 | } 30 | }; 31 | 32 | return ( 33 | 34 | 35 | {children} 36 | 37 | 38 | ); 39 | }; 40 | 41 | export default Wrapper; 42 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import React from 'react'; 3 | import * as GAME_STATE from './utils/gameState'; 4 | import Game from './components/Game/Game'; 5 | import Welcome from './components/Welcome/Welcome'; 6 | 7 | const App = () => { 8 | // 游戏状态,游戏阶段 9 | const [gameState, setGameState] = React.useState(GAME_STATE.WELCOME); 10 | // 表单数据 11 | const [formData, setFormData] = React.useState({ 12 | p1Name: 'Kelvin', 13 | p2Name: 'Lydia', 14 | // playMode: 'multiPlayer', 15 | playMode: 'singlePlayer', 16 | // language: 'chinese', 17 | difficulty: 'normal', 18 | }); 19 | 20 | return ( 21 |
22 | {gameState === GAME_STATE.WELCOME ? ( 23 | 28 | ) : ( 29 | 34 | )} 35 |
36 | ); 37 | }; 38 | 39 | export default App; 40 | -------------------------------------------------------------------------------- /src/components/GameOver/over.css: -------------------------------------------------------------------------------- 1 | .over { 2 | position: relative; 3 | text-align: center; 4 | margin-top: 80px; 5 | } 6 | 7 | .over-title { 8 | font-size: 4em; 9 | margin-top: -20px; 10 | } 11 | 12 | .over-winner { 13 | font-size: 3em; 14 | margin-top: 10px; 15 | } 16 | 17 | .over-show { 18 | display: flex; 19 | justify-content: center; 20 | margin-top: 45px; 21 | } 22 | 23 | .show-data { 24 | width: 400px; 25 | margin-left: 53px; 26 | margin-right: 40px; 27 | } 28 | 29 | .show-board { 30 | width: 400px; 31 | margin-left: 50px; 32 | } 33 | 34 | .mini-board { 35 | margin: 0 auto; 36 | display: flex; 37 | flex-wrap: wrap; 38 | width: 278px; 39 | margin-bottom: 30px; 40 | } 41 | 42 | .block.mini { 43 | width: 30px; 44 | height: 30px; 45 | } 46 | 47 | .mini-name { 48 | font-size: 1.5em; 49 | } 50 | 51 | .show-data .data-card { 52 | width: 350px; 53 | } 54 | 55 | .show-board .data-card { 56 | width: 350px; 57 | } 58 | 59 | .data-player { 60 | font-size: 2em; 61 | margin-bottom: 10px; 62 | } 63 | 64 | .data-card p { 65 | font-size: 1.3em; 66 | line-height: 1.6em; 67 | } 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 KelvinQiu 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/lang/en-US.json: -------------------------------------------------------------------------------- 1 | { 2 | "welcome": "Welcome!", 3 | "welcome.introduction": "Battleship is a strategy type guessing game for two players.", 4 | "welcome.p1Name": "Player 1 Name: ", 5 | "welcome.p2Name": "Player 2 Name: ", 6 | "welcome.difficulty": "Difficulty: ", 7 | "welcome.difficulty.easy": "Easy", 8 | "welcome.difficulty.normal": "Normal", 9 | "welcome.mode": "Mode: ", 10 | "welcome.mode.one": "One Player", 11 | "welcome.mode.two": "Two Player", 12 | "welcome.lang": "Language: ", 13 | "welcome.start": "START", 14 | "board.title": "{name}'s Board", 15 | "board.waitMessage": "Wait for player {isP1} to place", 16 | "tip.placing": "After selecting the ship, place it on the board and right click to rotate the direction.", 17 | "tip.p1Attack": "Player1: Select coordinates on the right board to attack.⬆", 18 | "tip.p2Attack": "⬆Player2: Select coordinates on the left board to attack.", 19 | "over.title": "Game Over", 20 | "over.winner": "The winner is: {winner}", 21 | "over.numberOfAttack": "Number of Attack: ", 22 | "over.numberOfHit":"Number of Hit: ", 23 | "over.numberOfMiss":"Number of Miss: ", 24 | "over.hitRate": "Hit Rate: " 25 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Battleship 海战棋 2 | 3 | 4 |

5 | 6 |

7 | 8 | ## 项目背景 9 | 10 | 来自我大一下的大作业,使用Python完成,有两个版本:命令行版和GUI版。由于时间原因,只完成了基础部分,希望能把它重新在Web上展现出来。 11 | 12 | ### 已完成功能 13 | 14 | - [x] 基本游戏逻辑和规则判定 15 | - [x] 本地双人对战模式 16 | - [x] 简单UI设计 17 | - [x] 单人游戏(与脚本对战) 18 | - [x] 单人游戏(增加难度设定) 19 | - [x] 多语言,国际化 20 | 21 | ### 未完成功能 22 | 23 | - [ ] 双人联网对战 24 | - [ ] 战局缓存 25 | - [ ] 黑暗模式 26 | 27 | ## 游戏介绍 28 | 29 | > **海战**(英语:**Battleship**,又名**海战棋**是双人玩的猜谜游戏。 30 | 31 | **玩法概括:** 32 | 33 | 1. 玩家A放置船只 34 | 2. 玩家B放置船只 35 | 3. 玩家A选择玩家B地图上一点进行攻击 36 | 4. 玩家B选择玩家A地图上一点进行攻击 37 | 5. 重复3和4,直到一方船只全部被击沉 38 | 6. 游戏结束 39 | 40 | ***具体规则参考[维基百科](https://zh.wikipedia.org/wiki/%E6%B5%B7%E6%88%98_(%E6%B8%B8%E6%88%8F))*** 41 | 42 | ## 项目细节 43 | 44 | ### 技术栈 45 | 46 | - HTML + CSS + JavaScript 47 | - Vite 48 | - React 49 | - MUI 50 | 51 | ### 基本目标 52 | 53 | 1. 在Web上搭建一个可以双人游玩的海战棋 54 | 2. 重新设计UI,简洁,明亮风格 55 | 3. 优化用户交互体验(拖放操作) 56 | 4. 中、英双语言 57 | 58 | ### 进阶目标 59 | 60 | 1. *单人模式(与电脑对战)* 61 | 2. *在单人模式基础上,设置不同难度等级* 62 | 3. *添加黑暗模式(Dark Mode)* 63 | 4. *战局缓存功能* 64 | 5. *一键随机放置船只* 65 | 6. *加入些动画,美化页面* 66 | -------------------------------------------------------------------------------- /src/components/GameOver/DataCard.jsx: -------------------------------------------------------------------------------- 1 | import * as BLOCK_STATE from '../../utils/blockStates'; 2 | import { FormattedMessage } from 'react-intl'; 3 | import { Paper } from '@mui/material'; 4 | 5 | const DataCatd = ({ name, attack }) => { 6 | const numberOfAttack = attack.length - 1; 7 | const numberOfHit = 8 | attack.filter((item) => item.state !== BLOCK_STATE.MISS).length - 1; 9 | const numberOfMiss = attack.filter( 10 | (item) => item.state === BLOCK_STATE.MISS 11 | ).length; 12 | const hitRate = ((numberOfHit / numberOfAttack) * 100).toFixed(0); 13 | 14 | return ( 15 | 16 |
17 |

{name}

18 |

19 | 20 | {numberOfAttack} 21 |

22 |

23 | 24 | {numberOfHit} 25 |

26 |

27 | 28 | {numberOfMiss} 29 |

30 |

31 | 32 | {hitRate}% 33 |

34 |
35 |
36 | ); 37 | }; 38 | 39 | export default DataCatd; 40 | -------------------------------------------------------------------------------- /src/components/GameOver/GameOver.jsx: -------------------------------------------------------------------------------- 1 | import MiniBoard from './MiniBoard'; 2 | import DataCatd from './DataCard'; 3 | import { FormattedMessage } from 'react-intl'; 4 | 5 | const GameOver = ({ 6 | gameState, 7 | formData, 8 | p1FinalBoard, 9 | p2FinalBoard, 10 | p1Attack, 11 | p2Attack, 12 | }) => { 13 | const winner = gameState.includes('p1') ? formData.p1Name : formData.p2Name; 14 | return ( 15 |
16 |

17 | 18 |

19 |

20 | {winner} }} 23 | /> 24 |

25 |
26 |
27 | 28 | 33 |
34 | 35 |
36 | 37 | 42 |
43 |
44 |
45 | ); 46 | }; 47 | 48 | export default GameOver; 49 | -------------------------------------------------------------------------------- /src/components/Game/Harbour.jsx: -------------------------------------------------------------------------------- 1 | import Ship from './Ship'; 2 | import React from 'react'; 3 | import { Context } from '../Wrapper'; 4 | 5 | const Harbour = ({ 6 | gameState, 7 | p1PlacingShip, 8 | p1AvaliableShips, 9 | setP1PlacingShip, 10 | p2PlacingShip, 11 | p2AvaliableShips, 12 | setP2PlacingShip, 13 | }) => { 14 | const context = React.useContext(Context); 15 | 16 | const isP1 = gameState.includes('p1'); 17 | const placingShip = isP1 ? p1PlacingShip : p2PlacingShip; 18 | const setPlacingShip = isP1 ? setP1PlacingShip : setP2PlacingShip; 19 | const avaliableShips = isP1 ? p1AvaliableShips : p2AvaliableShips; 20 | 21 | // 选择正在放置的船只 22 | const handleSelect = (ship) => { 23 | setPlacingShip({ 24 | ...ship, 25 | direction: 'HORIZONTAL', 26 | position: { 27 | row: null, 28 | col: null, 29 | }, 30 | }); 31 | }; 32 | 33 | return ( 34 |
35 | {avaliableShips.map((ship) => ( 36 |
handleSelect(ship)} 42 | > 43 |

44 | {context.locale === 'zh-CN' ? ship.zh : ship.name} 45 |

46 | 47 |
48 | ))} 49 |
50 | ); 51 | }; 52 | 53 | export default Harbour; 54 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | div, 4 | span, 5 | applet, 6 | object, 7 | iframe, 8 | h1, 9 | h2, 10 | h3, 11 | h4, 12 | h5, 13 | h6, 14 | p, 15 | blockquote, 16 | pre, 17 | a, 18 | abbr, 19 | acronym, 20 | address, 21 | big, 22 | cite, 23 | code, 24 | del, 25 | dfn, 26 | em, 27 | img, 28 | ins, 29 | kbd, 30 | q, 31 | s, 32 | samp, 33 | small, 34 | strike, 35 | strong, 36 | sub, 37 | sup, 38 | tt, 39 | var, 40 | b, 41 | u, 42 | i, 43 | center, 44 | dl, 45 | dt, 46 | dd, 47 | ol, 48 | ul, 49 | li, 50 | fieldset, 51 | form, 52 | label, 53 | legend, 54 | table, 55 | caption, 56 | tbody, 57 | tfoot, 58 | thead, 59 | tr, 60 | th, 61 | td, 62 | article, 63 | aside, 64 | canvas, 65 | details, 66 | embed, 67 | figure, 68 | figcaption, 69 | footer, 70 | header, 71 | hgroup, 72 | menu, 73 | nav, 74 | output, 75 | ruby, 76 | section, 77 | summary, 78 | time, 79 | mark, 80 | audio, 81 | video { 82 | margin: 0; 83 | padding: 0; 84 | border: 0; 85 | font-size: 100%; 86 | font: inherit; 87 | vertical-align: baseline; 88 | } 89 | /* HTML5 display-role reset for older browsers */ 90 | article, 91 | aside, 92 | details, 93 | figcaption, 94 | figure, 95 | footer, 96 | header, 97 | hgroup, 98 | menu, 99 | nav, 100 | section { 101 | display: block; 102 | } 103 | body { 104 | line-height: 1; 105 | font-family: 'Roboto', sans-serif; 106 | } 107 | ol, 108 | ul { 109 | list-style: none; 110 | } 111 | blockquote, 112 | q { 113 | quotes: none; 114 | } 115 | blockquote:before, 116 | blockquote:after, 117 | q:before, 118 | q:after { 119 | content: ''; 120 | content: none; 121 | } 122 | table { 123 | border-collapse: collapse; 124 | border-spacing: 0; 125 | } 126 | -------------------------------------------------------------------------------- /src/components/Welcome/welcome.css: -------------------------------------------------------------------------------- 1 | .welcome-body { 2 | display: flex; 3 | justify-content: space-evenly; 4 | align-items: center; 5 | margin-top: 50px; 6 | } 7 | .welcome-title { 8 | font-size: 2.8em; 9 | letter-spacing: 1px; 10 | margin-bottom: 10px; 11 | } 12 | 13 | .welcome-intro { 14 | font-size: 1.1em; 15 | margin-top: 10px; 16 | margin-bottom: 30px; 17 | width: 500px; 18 | } 19 | 20 | .welcome-form label { 21 | font-size: 1em; 22 | font-weight: 550; 23 | color: #676669; 24 | padding: 5px; 25 | } 26 | 27 | .welcome-form input { 28 | vertical-align: baseline; 29 | height: 25px; 30 | font-size: 20px; 31 | font-weight: 600; 32 | margin: 15px; 33 | border-color: #c4d0e8; 34 | background-color: #c4d0e8; 35 | border-radius: 10px; 36 | } 37 | .button-start { 38 | font-size: 2em; 39 | padding: 20px 30px; 40 | margin: 10px 0px 10px 0px; 41 | border-radius: 30px; 42 | border: 0px; 43 | color: #d8dee7; 44 | background-color: #4576e7; 45 | } 46 | .welcome-div { 47 | border-radius: 30px; 48 | background-color: #e9eaed; 49 | } 50 | 51 | h1 { 52 | letter-spacing: 2px; 53 | font-size: 40px; 54 | font-weight: 900; 55 | } 56 | img { 57 | width: 300px; 58 | } 59 | .welcome-lastdiv { 60 | display: flex; 61 | justify-content: space-between; 62 | background-color: #ffffff; 63 | } 64 | .welcome-lastdiv select { 65 | background-color: #c4d0e8; 66 | height: 25px; 67 | font-size: 20px; 68 | font-weight: 600; 69 | margin: 15px; 70 | border-radius: 10px; 71 | } 72 | .div-language { 73 | margin-top: 10px; 74 | height: 50px; 75 | padding: 15px; 76 | background-color: #e9eaed; 77 | border-radius: 30px; 78 | } 79 | 80 | .wrapper { 81 | height: calc(100vh - 200px); 82 | min-height: 462px; 83 | display: flex; 84 | justify-content: center; 85 | align-items: center; 86 | } 87 | -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/computerTools.js: -------------------------------------------------------------------------------- 1 | import { 2 | canBePlaced, 3 | coordinateToIndex, 4 | createEmptyBoard, 5 | indexToCoordinate, 6 | placeShipOnBoard, 7 | } from './boardTools'; 8 | 9 | export const getRandInt = (min, max) => { 10 | return Math.floor((max - min + 1) * Math.random() + min); 11 | }; 12 | 13 | // 随机坐标 14 | export const getRandCoordinate = () => { 15 | return { 16 | row: getRandInt(0, 7), 17 | col: getRandInt(0, 7), 18 | }; 19 | }; 20 | 21 | // 随机方向 22 | export const getRandDirection = () => { 23 | return getRandInt(0, 1) ? 'HORIZONTAL' : 'VERTICAL'; 24 | }; 25 | 26 | // 电脑自动放船 27 | export const computerPlacingShip = (avaliableShips) => { 28 | let board = createEmptyBoard(); 29 | const shipsCopy = [...avaliableShips]; 30 | shipsCopy.forEach((ship) => { 31 | while (true) { 32 | const position = getRandCoordinate(); 33 | const direction = getRandDirection(); 34 | const length = ship.length; 35 | if ( 36 | canBePlaced(board, length, direction, position.row, position.col) === 37 | 'OK' 38 | ) { 39 | // 放船 40 | board = placeShipOnBoard(board, { 41 | ...ship, 42 | direction: direction, 43 | position: position, 44 | }); 45 | break; 46 | } 47 | } 48 | }); 49 | return board; 50 | }; 51 | 52 | // 检查是否可以攻击 53 | export const canAttack = (attack, row, col) => { 54 | const attackCopy = [...attack]; 55 | attackCopy.shift(); 56 | // 是否已经被攻击过 57 | const isAttacked = attackCopy.find( 58 | (item) => item.position.row === row && item.position.col === col 59 | ); 60 | // 已经攻击过的不能重复被攻击 61 | return isAttacked ? false : true; 62 | }; 63 | 64 | // 随机攻击 65 | export const randomAttack = (attack) => { 66 | while (true) { 67 | const row = getRandInt(0, 7); 68 | const col = getRandInt(0, 7); 69 | if (canAttack(attack, row, col)) { 70 | return { row: row, col: col }; 71 | } 72 | } 73 | }; 74 | 75 | // 添加潜在目标 76 | export const addPotentialTarget = (position, attack, potentialTarget) => { 77 | const { row, col } = position; 78 | if (row + 1 <= 7 && canAttack(attack, row + 1, col)) { 79 | potentialTarget.current.push(coordinateToIndex(row + 1, col)); 80 | } 81 | if (row - 1 >= 0 && canAttack(attack, row - 1, col)) { 82 | potentialTarget.current.push(coordinateToIndex(row - 1, col)); 83 | } 84 | if (col + 1 <= 7 && canAttack(attack, row, col + 1)) { 85 | potentialTarget.current.push(coordinateToIndex(row, col + 1)); 86 | } 87 | if (col - 1 >= 0 && canAttack(attack, row, col - 1)) { 88 | potentialTarget.current.push(coordinateToIndex(row, col - 1)); 89 | } 90 | return potentialTarget.current; 91 | }; 92 | 93 | // 攻击潜在目标 94 | export const attackPotentialTarget = (potentialTarget, attack) => { 95 | while (true) { 96 | const randIndex = getRandInt(0, potentialTarget.current.length - 1); 97 | const { row, col } = indexToCoordinate(potentialTarget.current[randIndex]); 98 | if (canAttack(attack, row, col)) { 99 | // 删除这个要被攻击的潜在目标 100 | potentialTarget.current.splice(randIndex, 1); 101 | return { 102 | row: row, 103 | col: col, 104 | }; 105 | } else { 106 | // 删除无法攻击的目标 107 | potentialTarget.current.splice(randIndex, 1); 108 | } 109 | } 110 | }; 111 | -------------------------------------------------------------------------------- /src/components/Game/game.css: -------------------------------------------------------------------------------- 1 | .game-area { 2 | display: flex; 3 | margin-top: 80px; 4 | justify-content: space-evenly; 5 | } 6 | 7 | .board { 8 | display: flex; 9 | width: 350px; 10 | flex-wrap: wrap; 11 | cursor: pointer; 12 | } 13 | 14 | .board.disabled { 15 | cursor: not-allowed; 16 | } 17 | 18 | .board-container { 19 | text-align: center; 20 | } 21 | 22 | .board-title-p1 { 23 | font-size: 1.5em; 24 | width: 345px; 25 | height: 40px; 26 | margin-bottom: 1.5em; 27 | background-color: #ff0054; 28 | line-height: 40px; 29 | color: #fff9ff; 30 | border-radius: 5px; 31 | } 32 | 33 | .board-title-p2 { 34 | font-size: 1.5em; 35 | width: 345px; 36 | height: 40px; 37 | margin-bottom: 1.5em; 38 | background-color: #717d97; 39 | line-height: 40px; 40 | color: #fff9ff; 41 | border-radius: 5px; 42 | } 43 | 44 | .block { 45 | width: 40px; 46 | height: 40px; 47 | margin: 1.5px 1.5px 1.5px 1.5px; 48 | border-radius: 5px; 49 | background-color: #cbedff; 50 | } 51 | 52 | .block-p1 .block { 53 | width: 40px; 54 | height: 40px; 55 | margin: 1.5px 1.5px 1.5px 1.5px; 56 | border-radius: 5px; 57 | background-color: #cbedff; 58 | } 59 | 60 | .board-p2 .block { 61 | width: 40px; 62 | height: 40px; 63 | margin: 1.5px 1.5px 1.5px 1.5px; 64 | border-radius: 5px; 65 | background-color: #d7edec; 66 | } 67 | 68 | .block.placing { 69 | background-color: rgba(255, 166, 0, 0.31); 70 | } 71 | 72 | .block.ship { 73 | background-color: rgba(0, 0, 255, 0.299); 74 | } 75 | 76 | .block.Carrier { 77 | background-color: #1cd4d4; 78 | } 79 | 80 | .block.Battleship { 81 | background-color: #fe9910; 82 | } 83 | 84 | .block.Destroyer { 85 | background-color: chartreuse; 86 | } 87 | 88 | .block.Submarine { 89 | background-color: #ffd581; 90 | } 91 | 92 | .block.Patrol { 93 | background-color: #fd6b51; 94 | } 95 | 96 | .block.sank { 97 | background-color: rgba(0, 0, 0, 0.549); 98 | } 99 | 100 | .block.forbidden { 101 | background-color: rgba(255, 0, 0, 0.294); 102 | } 103 | 104 | .block.selecting { 105 | background-color: skyblue; 106 | } 107 | 108 | .block.hit { 109 | background-color: red; 110 | } 111 | 112 | .block.miss { 113 | background-color: rgba(255, 221, 0, 0.647); 114 | } 115 | 116 | .harbour { 117 | width: 200px; 118 | border: 5px solid #c2762182; 119 | padding: 15px 20px; 120 | border-radius: 10px; 121 | } 122 | 123 | .ship-container { 124 | border: 3px solid #d6c638c7; 125 | margin-bottom: 20px; 126 | padding: 7px 14px; 127 | cursor: pointer; 128 | user-select: none; 129 | border-radius: 10px; 130 | } 131 | 132 | .ship-container:hover { 133 | background-color: rgba(135, 207, 235, 0.244); 134 | } 135 | 136 | .harbour-ship { 137 | display: flex; 138 | margin-bottom: 5px; 139 | } 140 | 141 | .ship-unit { 142 | width: 10px; 143 | height: 10px; 144 | border: 1px solid black; 145 | margin: 0 -1px -1px 0; 146 | } 147 | 148 | .ship-selected { 149 | background-color: rgba(135, 207, 235, 0.244); 150 | } 151 | 152 | .ship-name { 153 | margin: 0; 154 | padding: 0; 155 | border: 0; 156 | font-size: 100%; 157 | font: inherit; 158 | vertical-align: baseline; 159 | margin-bottom: 3px; 160 | } 161 | 162 | .waiting-title { 163 | font-size: 2em; 164 | margin-top: 100px; 165 | } 166 | 167 | .tip { 168 | font-size: 2em; 169 | text-align: center; 170 | margin-top: 60px; 171 | } 172 | 173 | .game-wrapper { 174 | height: calc(100vh - 200px); 175 | min-height: 512px; 176 | display: flex; 177 | flex-direction: column; 178 | justify-content: center; 179 | align-items: center; 180 | } 181 | 182 | .gameover-wrapper { 183 | height: calc(100vh - 200px); 184 | min-height: 688px; 185 | display: flex; 186 | flex-direction: column; 187 | justify-content: center; 188 | align-items: center; 189 | } 190 | -------------------------------------------------------------------------------- /src/components/Game/Board.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | createEmptyBoard, 3 | indexToCoordinate, 4 | placeShipOnBoard, 5 | coordinateToIndex, 6 | } from '../../utils/boardTools.js'; 7 | import { computerPlacingShip } from '../../utils/computerTools'; 8 | import * as BLOCK_STATE from '../../utils/blockStates'; 9 | import * as GAME_STATE from '../../utils/gameState'; 10 | import { FormattedMessage } from 'react-intl'; 11 | 12 | const Board = ({ 13 | gameState, 14 | setGameState, 15 | formData, 16 | player, 17 | name, 18 | placingShip, 19 | setPlacingShip, 20 | placedShips, 21 | setPlacedShips, 22 | avaliableShips, 23 | setAvaliableShips, 24 | finalBoard, 25 | comBoard, 26 | }) => { 27 | // 是否是单人模式 28 | const isSingleMode = formData.playMode === 'singlePlayer'; 29 | const isP1 = gameState.includes('p1'); 30 | 31 | let board; 32 | 33 | if (isSingleMode && !isP1) { 34 | // 电脑自动放船 35 | board = computerPlacingShip(avaliableShips); 36 | comBoard.current = board; 37 | setGameState(GAME_STATE.P1ATTACK); 38 | } else { 39 | // 空棋盘 40 | board = createEmptyBoard(); 41 | 42 | // 渲染已经放置的船 43 | if (placedShips.length) { 44 | placedShips.forEach((ship) => { 45 | board = placeShipOnBoard(board, ship); 46 | }); 47 | } 48 | 49 | // 渲染正在放置的船 50 | board = placeShipOnBoard(board, placingShip, true); 51 | 52 | // 更新游戏状态 53 | if (!avaliableShips.length) { 54 | finalBoard.current = board; 55 | player === 'p1' 56 | ? setGameState(GAME_STATE.P2PLACING) 57 | : setGameState(GAME_STATE.P1ATTACK); 58 | } 59 | } 60 | 61 | // 移动时更新坐标 62 | const handleMove = (index) => { 63 | if (!placingShip) return; 64 | const { row, col } = indexToCoordinate(index); 65 | setPlacingShip((prev) => { 66 | return { 67 | ...prev, 68 | position: { 69 | row: row, 70 | col: col, 71 | }, 72 | }; 73 | }); 74 | }; 75 | 76 | // 放置船 77 | const handleClick = () => { 78 | if (placingShip) { 79 | const { 80 | name, 81 | length, 82 | direction, 83 | position: { row, col }, 84 | } = placingShip; 85 | if (board[coordinateToIndex(row, col)] !== BLOCK_STATE.FORBIDDEN) { 86 | // 放船 87 | setPlacedShips((prev) => [...prev, placingShip]); 88 | // 移出可用船 89 | setAvaliableShips((prev) => 90 | prev.filter((ship) => ship.name !== placingShip.name) 91 | ); 92 | // 重制正在放置的船 93 | setPlacingShip(null); 94 | } 95 | } 96 | }; 97 | 98 | // 右键旋转 99 | const handleTurn = (e) => { 100 | // 右键 101 | if (e.button === 2 && placingShip) { 102 | setPlacingShip((prev) => { 103 | return { 104 | ...prev, 105 | direction: 106 | prev.direction === 'HORIZONTAL' ? 'VERTICAL' : 'HORIZONTAL', 107 | }; 108 | }); 109 | } 110 | }; 111 | 112 | return ( 113 |
114 |

119 | {name} }} /> 120 |

121 | {!gameState.includes(player) ? ( 122 |

123 | {isP1 ? '1' : '2'} }} 126 | defaultMessage={`Wait for player ${isP1 ? 'one' : 'two'} to place`} 127 | /> 128 |

129 | ) : ( 130 |
e.preventDefault()} 133 | > 134 | {board.map((state, index) => ( 135 |
handleMove(index)} 140 | onMouseDown={handleTurn} 141 | onClick={handleClick} 142 | >
143 | ))} 144 |
145 | )} 146 |
147 | ); 148 | }; 149 | 150 | export default Board; 151 | -------------------------------------------------------------------------------- /src/components/Game/AttackBoard.jsx: -------------------------------------------------------------------------------- 1 | import { 2 | createEmptyBoard, 3 | indexToCoordinate, 4 | coordinateToIndex, 5 | showSelectiongBlock, 6 | canAttack, 7 | checkAttack, 8 | showAttack, 9 | checkSunk, 10 | } from '../../utils/boardTools.js'; 11 | import { 12 | randomAttack, 13 | addPotentialTarget, 14 | attackPotentialTarget, 15 | } from '../../utils/computerTools'; 16 | import React from 'react'; 17 | import * as BLOCK_STATE from '../../utils/blockStates'; 18 | import * as GAME_STATE from '../../utils/gameState'; 19 | import { FormattedMessage } from 'react-intl'; 20 | 21 | const AttackBoard = ({ 22 | player, 23 | name, 24 | formData, 25 | gameState, 26 | setGameState, 27 | attack, 28 | setAttack, 29 | finalBoard, 30 | comAttack, 31 | setComAttack, 32 | p1FinalBoard, 33 | }) => { 34 | // 通过Ref在一次快照内,记录游戏状态的更新 35 | const state = React.useRef(gameState); 36 | const isMyTurn = gameState.includes(player); 37 | const isSingleMode = formData.playMode === 'singlePlayer'; 38 | const potentialTargets = React.useRef([]); // 记录潜在的打击目标 39 | 40 | // 创建空棋盘 41 | let board = createEmptyBoard(); 42 | 43 | // 渲染正在选择方块 44 | board = showSelectiongBlock(board, attack[0].position); 45 | 46 | // 渲染已经进行的攻击 47 | board = showAttack(board, attack); 48 | 49 | // 电脑攻击 50 | React.useEffect(() => { 51 | if (isSingleMode && state.current === GAME_STATE.P2ATTACK) { 52 | let attackPosition; 53 | 54 | if (!potentialTargets.current.length || formData.difficulty === 'easy') { 55 | // 没有潜在打击目标,随机进攻 56 | attackPosition = randomAttack(comAttack); 57 | } else { 58 | // 随机攻击潜在目标 59 | attackPosition = attackPotentialTarget(potentialTargets, comAttack); 60 | } 61 | 62 | const isHit = checkAttack(p1FinalBoard.current, attackPosition); 63 | if (isHit) { 64 | // 如果击中,添加潜在目标 65 | potentialTargets.current = addPotentialTarget( 66 | attackPosition, 67 | comAttack, 68 | potentialTargets 69 | ); 70 | } 71 | 72 | const { row, col } = attackPosition; 73 | setComAttack((prev) => [ 74 | ...prev, 75 | { 76 | position: { 77 | row: row, 78 | col: col, 79 | }, 80 | state: isHit ? BLOCK_STATE.HIT : BLOCK_STATE.MISS, 81 | // miss时,ship的值为empty 82 | ship: p1FinalBoard.current[coordinateToIndex(row, col)], 83 | }, 84 | ]); 85 | // 判断是否沉船 86 | setComAttack((prev) => 87 | checkSunk(prev, p1FinalBoard.current, row, col, potentialTargets) 88 | ); 89 | // 交换攻击 90 | setGameState(GAME_STATE.P1ATTACK); 91 | state.current = GAME_STATE.P1ATTACK; 92 | } 93 | }, [gameState]); 94 | 95 | // 判断输赢 96 | if (attack.filter((item) => item.state === BLOCK_STATE.SANK).length === 17) { 97 | setGameState(player === 'p1' ? GAME_STATE.P2WIN : GAME_STATE.P1WIN); 98 | } 99 | 100 | // 正在选择要攻击的坐标 101 | const handleMove = (index) => { 102 | const { row, col } = indexToCoordinate(index); 103 | setAttack((prev) => { 104 | const copy = [...prev]; 105 | copy[0].position = { row: row, col: col }; 106 | return copy; 107 | }); 108 | }; 109 | 110 | const hanldeAttack = () => { 111 | const { row, col } = attack[0].position; 112 | if (!canAttack(attack)) return; 113 | // 可以攻击 114 | const isHit = checkAttack(finalBoard.current, attack[0].position); 115 | // 添加一次进攻数据 116 | setAttack((prev) => [ 117 | ...prev, 118 | { 119 | position: { 120 | row: row, 121 | col: col, 122 | }, 123 | state: isHit ? BLOCK_STATE.HIT : BLOCK_STATE.MISS, 124 | // miss时,ship的值为empty 125 | ship: finalBoard.current[coordinateToIndex(row, col)], 126 | }, 127 | ]); 128 | // 判断是否沉船, 并更新状态 129 | setAttack((prev) => checkSunk(prev, finalBoard.current, row, col)); 130 | // 交换进攻 131 | setGameState( 132 | gameState.includes('p1') ? GAME_STATE.P2ATTACK : GAME_STATE.P1ATTACK 133 | ); 134 | state.current = gameState.includes('p1') 135 | ? GAME_STATE.P2ATTACK 136 | : GAME_STATE.P1ATTACK; 137 | }; 138 | 139 | return ( 140 |
141 |

146 | {name} }} /> 147 |

148 |
e.preventDefault()} 153 | > 154 | {board.map((state, index) => ( 155 |
{} : () => handleMove(index)} 160 | onClick={isMyTurn ? () => {} : hanldeAttack} 161 | >
162 | ))} 163 |
164 |
165 | ); 166 | }; 167 | 168 | export default AttackBoard; 169 | -------------------------------------------------------------------------------- /src/components/Game/Game.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Header from '../Header'; 3 | import Board from './Board'; 4 | import Harbour from './Harbour'; 5 | import AttackBoard from './AttackBoard'; 6 | import GameOver from '../GameOver/GameOver'; 7 | import Tip from './Tip'; 8 | import * as SHIPS from '../../utils/ships'; 9 | import * as BLOCK_STATE from '../../utils/blockStates'; 10 | 11 | const Game = ({ gameState, setGameState, formData }) => { 12 | // 玩家数据 13 | const [p1AvaliableShips, setP1AvaliableShips] = React.useState([ 14 | SHIPS.CARRIER, 15 | SHIPS.BATTLESHIP, 16 | SHIPS.DESTROYER, 17 | SHIPS.SUBMARINE, 18 | SHIPS.PATROL, 19 | ]); 20 | const [p1PlacingShip, setP1PlacingShip] = React.useState(null); 21 | const [p1PlacedShips, setP1PlacedShips] = React.useState([]); 22 | const [p2AvaliableShips, setP2AvaliableShips] = React.useState([ 23 | SHIPS.CARRIER, 24 | SHIPS.BATTLESHIP, 25 | SHIPS.DESTROYER, 26 | SHIPS.SUBMARINE, 27 | SHIPS.PATROL, 28 | ]); 29 | const [p2PlacingShip, setP2PlacingShip] = React.useState(null); 30 | const [p2PlacedShips, setP2PlacedShips] = React.useState([]); 31 | const [p1Attack, setP1Attack] = React.useState([ 32 | { position: { row: null, col: null }, state: BLOCK_STATE.SELECTING }, 33 | ]); 34 | const [p2Attack, setP2Attack] = React.useState([ 35 | { position: { row: null, col: null }, state: BLOCK_STATE.SELECTING }, 36 | ]); 37 | const p1FinalBoard = React.useRef(null); 38 | const p2FinalBoard = React.useRef(null); 39 | 40 | // 判断游戏阶段 41 | const isPlacing = gameState.includes('placing'); 42 | const gameOver = gameState.includes('win'); 43 | 44 | return ( 45 |
46 |
47 | {gameOver ? ( 48 |
49 | 57 |
58 | ) : ( 59 |
60 |
61 | {isPlacing ? ( 62 | 77 | ) : ( 78 | 91 | )} 92 | {isPlacing && ( 93 | 102 | )} 103 | {isPlacing ? ( 104 | 119 | ) : ( 120 | 133 | )} 134 |
135 | 136 |
137 | )} 138 |
139 | ); 140 | }; 141 | 142 | export default Game; 143 | -------------------------------------------------------------------------------- /src/utils/boardTools.js: -------------------------------------------------------------------------------- 1 | import * as BLOCK_STATE from './blockStates'; 2 | import * as SHIPS from './ships'; 3 | 4 | const ROWS = 8; 5 | const COLS = 8; 6 | 7 | export const createEmptyBoard = () => { 8 | return [...new Array(64)].fill(BLOCK_STATE.EMTPY); 9 | }; 10 | 11 | // Index转坐标 12 | export const coordinateToIndex = (row, col) => row * COLS + col; 13 | 14 | // 坐标转Index 15 | export const indexToCoordinate = (index) => { 16 | return { 17 | row: Math.floor(index / COLS), 18 | col: index % COLS, 19 | }; 20 | }; 21 | 22 | // 放置船 23 | export const placeShipOnBoard = (board, ship, placing = false) => { 24 | let boardCopy = [...board]; 25 | if (ship?.position.row != null) { 26 | const { 27 | name, 28 | length, 29 | direction, 30 | position: { row, col }, 31 | } = ship; 32 | 33 | switch (direction) { 34 | case 'HORIZONTAL': 35 | switch (canBePlaced(boardCopy, length, direction, row, col)) { 36 | case 'OK': 37 | for (let i = 0; i < length; i++) { 38 | boardCopy[coordinateToIndex(row, col + i)] = placing 39 | ? BLOCK_STATE.PLACING 40 | : name; 41 | } 42 | break; 43 | case 'OVERFLOW': 44 | for (let i = 0; i < COLS - col; i++) { 45 | boardCopy[coordinateToIndex(row, col + i)] = 46 | BLOCK_STATE.FORBIDDEN; 47 | } 48 | break; 49 | case 'OCCUPIED': 50 | for (let i = 0; i < length; i++) { 51 | boardCopy[coordinateToIndex(row, col + i)] = 52 | BLOCK_STATE.FORBIDDEN; 53 | } 54 | } 55 | break; 56 | case 'VERTICAL': 57 | switch (canBePlaced(boardCopy, length, direction, row, col)) { 58 | case 'OK': 59 | for (let i = 0; i < length; i++) { 60 | boardCopy[coordinateToIndex(row + i, col)] = placing 61 | ? BLOCK_STATE.PLACING 62 | : name; 63 | } 64 | break; 65 | case 'OVERFLOW': 66 | for (let i = 0; i < ROWS - row; i++) { 67 | boardCopy[coordinateToIndex(row + i, col)] = 68 | BLOCK_STATE.FORBIDDEN; 69 | } 70 | break; 71 | case 'OCCUPIED': 72 | for (let i = 0; i < length; i++) { 73 | boardCopy[coordinateToIndex(row + i, col)] = 74 | BLOCK_STATE.FORBIDDEN; 75 | } 76 | } 77 | } 78 | } 79 | return boardCopy; 80 | }; 81 | 82 | // 检查是否可以在此放置船只 83 | export const canBePlaced = (board, length, direction, row, col) => { 84 | switch (direction) { 85 | case 'HORIZONTAL': 86 | // 没出界 87 | if (col + length <= COLS) { 88 | // 没其他船 89 | for (let i = 0; i < length; i++) { 90 | if (board[coordinateToIndex(row, +col + i)] !== BLOCK_STATE.EMTPY) 91 | // 有其他船 92 | return 'OCCUPIED'; 93 | } 94 | return 'OK'; 95 | } 96 | // 出界 97 | return 'OVERFLOW'; 98 | case 'VERTICAL': 99 | if (row + length <= ROWS) { 100 | for (let i = 0; i < length; i++) { 101 | if (board[coordinateToIndex(row + i, col)] !== BLOCK_STATE.EMTPY) 102 | return 'OCCUPIED'; 103 | } 104 | return 'OK'; 105 | } 106 | return 'OVERFLOW'; 107 | } 108 | }; 109 | 110 | // 渲染正在选择的攻击位置 111 | // selecting是attack数组的第一个元素 112 | export const showSelectiongBlock = (board, position) => { 113 | if (position.row === null) return board; 114 | const boardCopy = [...board]; 115 | const index = coordinateToIndex(position.row, position.col); 116 | if (boardCopy[index] === BLOCK_STATE.EMTPY) { 117 | boardCopy[index] = BLOCK_STATE.SELECTING; 118 | } 119 | return boardCopy; 120 | }; 121 | 122 | // 检查是否可以攻击 123 | export const canAttack = (attack) => { 124 | const { row, col } = attack[0].position; 125 | const attackCopy = [...attack]; 126 | attackCopy.shift(); 127 | // 是否已经被攻击过 128 | const isAttacked = attackCopy.find( 129 | (item) => item.position.row === row && item.position.col === col 130 | ); 131 | // 已经攻击过的不能重复被攻击 132 | return isAttacked ? false : true; 133 | }; 134 | 135 | // 检查是否击中 136 | export const checkAttack = (finalBoard, position) => { 137 | const index = coordinateToIndex(position.row, position.col); 138 | return finalBoard[index] !== BLOCK_STATE.EMTPY; 139 | }; 140 | 141 | // 渲染攻击结果 142 | export const showAttack = (board, attack) => { 143 | const boardCopy = [...board]; 144 | attack.forEach((item) => { 145 | const index = coordinateToIndex(item.position.row, item.position.col); 146 | if (item.state != BLOCK_STATE.SELECTING) { 147 | boardCopy[index] = item.state; 148 | } 149 | }); 150 | return boardCopy; 151 | }; 152 | 153 | // 判断是否沉船 154 | export const checkSunk = ( 155 | attack, 156 | finalBoard, 157 | row, 158 | col, 159 | potentialTarget = null 160 | ) => { 161 | const ship = finalBoard[coordinateToIndex(row, col)]; 162 | if (ship === 'empty') return attack; // 没打中 163 | const attackCopy = [...attack]; 164 | const length = SHIPS[ship.toUpperCase()].length; 165 | const amount = attack.filter((item) => item.ship === ship).length; 166 | if (amount === length) { 167 | // 沉了 168 | attackCopy.forEach((item) => { 169 | if (item.ship === ship) { 170 | item.state = BLOCK_STATE.SANK; 171 | } 172 | }); 173 | 174 | // 如果是电脑攻击,则删除所有潜在目标 175 | if (potentialTarget) { 176 | potentialTarget.current = []; 177 | } 178 | return attackCopy; 179 | } 180 | return attack; 181 | }; 182 | -------------------------------------------------------------------------------- /src/components/Welcome/Welcome.jsx: -------------------------------------------------------------------------------- 1 | import * as GAME_STATE from '../../utils/gameState'; 2 | import React from 'react'; 3 | import Header from '../Header'; 4 | import { FormattedMessage } from 'react-intl'; 5 | import { Context } from '../Wrapper'; 6 | import { 7 | Box, 8 | Button, 9 | FormControl, 10 | FormControlLabel, 11 | FormLabel, 12 | InputLabel, 13 | MenuItem, 14 | Paper, 15 | Radio, 16 | RadioGroup, 17 | Select, 18 | TextField, 19 | } from '@mui/material'; 20 | import rightImg from '/shipGroup.png'; 21 | 22 | const Welcome = ({ setGameState, formData, setFormData }) => { 23 | const context = React.useContext(Context); 24 | 25 | const handleSubmit = (e) => { 26 | e.preventDefault(); 27 | if (formData.playMode === 'singlePlayer') { 28 | setFormData((prev) => { 29 | return { ...prev, p2Name: 'Computer' }; 30 | }); 31 | } 32 | if ( 33 | formData.p1Name && 34 | formData.p2Name && 35 | formData.p1Name !== formData.p2Name 36 | ) { 37 | setGameState(GAME_STATE.P1PLACING); 38 | } 39 | }; 40 | 41 | const handleChange = (e) => { 42 | const { value, name, type, checked } = e.target; 43 | setFormData((prev) => { 44 | return { 45 | ...prev, 46 | [name]: type === 'checkbox' ? checked : value, 47 | }; 48 | }); 49 | }; 50 | 51 | return ( 52 |
53 |
54 |
55 |
56 |
57 |

Play Battleship

58 |

59 | 60 |

61 | handleSubmit(e)}> 62 | } 69 | size='big' 70 | fullWidth 71 | sx={{ mb: 2 }} 72 | /> 73 |
74 | {formData.playMode === 'multiPlayer' ? ( 75 | } 82 | sx={{ mb: 2 }} 83 | /> 84 | ) : ( 85 | 86 | 87 | {} 88 | 89 | 90 | } 96 | control={} 97 | /> 98 | 105 | } 106 | control={} 107 | /> 108 | 109 | 110 | )} 111 |
112 | 113 | 114 | 115 | 116 | 117 | } 123 | control={} 124 | /> 125 | } 131 | control={} 132 | /> 133 | 134 | 135 |
136 | 137 | 138 | 139 | 140 | 150 | 151 |
152 | 161 |
162 |
163 |
164 | 165 |
166 |
167 |
168 |
169 | ); 170 | }; 171 | 172 | export default Welcome; 173 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@ampproject/remapping@^2.1.0": 6 | version "2.2.0" 7 | resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" 8 | integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== 9 | dependencies: 10 | "@jridgewell/gen-mapping" "^0.1.0" 11 | "@jridgewell/trace-mapping" "^0.3.9" 12 | 13 | "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": 14 | version "7.18.6" 15 | resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" 16 | integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== 17 | dependencies: 18 | "@babel/highlight" "^7.18.6" 19 | 20 | "@babel/compat-data@^7.18.8": 21 | version "7.18.8" 22 | resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz" 23 | integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== 24 | 25 | "@babel/core@^7.18.6": 26 | version "7.18.9" 27 | resolved "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz" 28 | integrity sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g== 29 | dependencies: 30 | "@ampproject/remapping" "^2.1.0" 31 | "@babel/code-frame" "^7.18.6" 32 | "@babel/generator" "^7.18.9" 33 | "@babel/helper-compilation-targets" "^7.18.9" 34 | "@babel/helper-module-transforms" "^7.18.9" 35 | "@babel/helpers" "^7.18.9" 36 | "@babel/parser" "^7.18.9" 37 | "@babel/template" "^7.18.6" 38 | "@babel/traverse" "^7.18.9" 39 | "@babel/types" "^7.18.9" 40 | convert-source-map "^1.7.0" 41 | debug "^4.1.0" 42 | gensync "^1.0.0-beta.2" 43 | json5 "^2.2.1" 44 | semver "^6.3.0" 45 | 46 | "@babel/generator@^7.18.9": 47 | version "7.18.9" 48 | resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz" 49 | integrity sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug== 50 | dependencies: 51 | "@babel/types" "^7.18.9" 52 | "@jridgewell/gen-mapping" "^0.3.2" 53 | jsesc "^2.5.1" 54 | 55 | "@babel/helper-annotate-as-pure@^7.18.6": 56 | version "7.18.6" 57 | resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" 58 | integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== 59 | dependencies: 60 | "@babel/types" "^7.18.6" 61 | 62 | "@babel/helper-compilation-targets@^7.18.9": 63 | version "7.18.9" 64 | resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz" 65 | integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== 66 | dependencies: 67 | "@babel/compat-data" "^7.18.8" 68 | "@babel/helper-validator-option" "^7.18.6" 69 | browserslist "^4.20.2" 70 | semver "^6.3.0" 71 | 72 | "@babel/helper-environment-visitor@^7.18.9": 73 | version "7.18.9" 74 | resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" 75 | integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== 76 | 77 | "@babel/helper-function-name@^7.18.9": 78 | version "7.18.9" 79 | resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz" 80 | integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A== 81 | dependencies: 82 | "@babel/template" "^7.18.6" 83 | "@babel/types" "^7.18.9" 84 | 85 | "@babel/helper-hoist-variables@^7.18.6": 86 | version "7.18.6" 87 | resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" 88 | integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== 89 | dependencies: 90 | "@babel/types" "^7.18.6" 91 | 92 | "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": 93 | version "7.18.6" 94 | resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" 95 | integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== 96 | dependencies: 97 | "@babel/types" "^7.18.6" 98 | 99 | "@babel/helper-module-transforms@^7.18.9": 100 | version "7.18.9" 101 | resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz" 102 | integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g== 103 | dependencies: 104 | "@babel/helper-environment-visitor" "^7.18.9" 105 | "@babel/helper-module-imports" "^7.18.6" 106 | "@babel/helper-simple-access" "^7.18.6" 107 | "@babel/helper-split-export-declaration" "^7.18.6" 108 | "@babel/helper-validator-identifier" "^7.18.6" 109 | "@babel/template" "^7.18.6" 110 | "@babel/traverse" "^7.18.9" 111 | "@babel/types" "^7.18.9" 112 | 113 | "@babel/helper-plugin-utils@^7.18.6": 114 | version "7.18.9" 115 | resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz" 116 | integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w== 117 | 118 | "@babel/helper-simple-access@^7.18.6": 119 | version "7.18.6" 120 | resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz" 121 | integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== 122 | dependencies: 123 | "@babel/types" "^7.18.6" 124 | 125 | "@babel/helper-split-export-declaration@^7.18.6": 126 | version "7.18.6" 127 | resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" 128 | integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== 129 | dependencies: 130 | "@babel/types" "^7.18.6" 131 | 132 | "@babel/helper-validator-identifier@^7.18.6": 133 | version "7.18.6" 134 | resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz" 135 | integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== 136 | 137 | "@babel/helper-validator-option@^7.18.6": 138 | version "7.18.6" 139 | resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz" 140 | integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== 141 | 142 | "@babel/helpers@^7.18.9": 143 | version "7.18.9" 144 | resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz" 145 | integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ== 146 | dependencies: 147 | "@babel/template" "^7.18.6" 148 | "@babel/traverse" "^7.18.9" 149 | "@babel/types" "^7.18.9" 150 | 151 | "@babel/highlight@^7.18.6": 152 | version "7.18.6" 153 | resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" 154 | integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== 155 | dependencies: 156 | "@babel/helper-validator-identifier" "^7.18.6" 157 | chalk "^2.0.0" 158 | js-tokens "^4.0.0" 159 | 160 | "@babel/parser@^7.18.6", "@babel/parser@^7.18.9": 161 | version "7.18.9" 162 | resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz" 163 | integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg== 164 | 165 | "@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.18.6": 166 | version "7.18.6" 167 | resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz" 168 | integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== 169 | dependencies: 170 | "@babel/helper-plugin-utils" "^7.18.6" 171 | 172 | "@babel/plugin-transform-react-jsx-development@^7.18.6": 173 | version "7.18.6" 174 | resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz" 175 | integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== 176 | dependencies: 177 | "@babel/plugin-transform-react-jsx" "^7.18.6" 178 | 179 | "@babel/plugin-transform-react-jsx-self@^7.18.6": 180 | version "7.18.6" 181 | resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz" 182 | integrity sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig== 183 | dependencies: 184 | "@babel/helper-plugin-utils" "^7.18.6" 185 | 186 | "@babel/plugin-transform-react-jsx-source@^7.18.6": 187 | version "7.18.6" 188 | resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.18.6.tgz" 189 | integrity sha512-utZmlASneDfdaMh0m/WausbjUjEdGrQJz0vFK93d7wD3xf5wBtX219+q6IlCNZeguIcxS2f/CvLZrlLSvSHQXw== 190 | dependencies: 191 | "@babel/helper-plugin-utils" "^7.18.6" 192 | 193 | "@babel/plugin-transform-react-jsx@^7.18.6": 194 | version "7.18.6" 195 | resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.6.tgz" 196 | integrity sha512-Mz7xMPxoy9kPS/JScj6fJs03TZ/fZ1dJPlMjRAgTaxaS0fUBk8FV/A2rRgfPsVCZqALNwMexD+0Uaf5zlcKPpw== 197 | dependencies: 198 | "@babel/helper-annotate-as-pure" "^7.18.6" 199 | "@babel/helper-module-imports" "^7.18.6" 200 | "@babel/helper-plugin-utils" "^7.18.6" 201 | "@babel/plugin-syntax-jsx" "^7.18.6" 202 | "@babel/types" "^7.18.6" 203 | 204 | "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": 205 | version "7.18.9" 206 | resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a" 207 | integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== 208 | dependencies: 209 | regenerator-runtime "^0.13.4" 210 | 211 | "@babel/template@^7.18.6": 212 | version "7.18.6" 213 | resolved "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz" 214 | integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== 215 | dependencies: 216 | "@babel/code-frame" "^7.18.6" 217 | "@babel/parser" "^7.18.6" 218 | "@babel/types" "^7.18.6" 219 | 220 | "@babel/traverse@^7.18.9": 221 | version "7.18.9" 222 | resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz" 223 | integrity sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg== 224 | dependencies: 225 | "@babel/code-frame" "^7.18.6" 226 | "@babel/generator" "^7.18.9" 227 | "@babel/helper-environment-visitor" "^7.18.9" 228 | "@babel/helper-function-name" "^7.18.9" 229 | "@babel/helper-hoist-variables" "^7.18.6" 230 | "@babel/helper-split-export-declaration" "^7.18.6" 231 | "@babel/parser" "^7.18.9" 232 | "@babel/types" "^7.18.9" 233 | debug "^4.1.0" 234 | globals "^11.1.0" 235 | 236 | "@babel/types@^7.18.6", "@babel/types@^7.18.9": 237 | version "7.18.9" 238 | resolved "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz" 239 | integrity sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg== 240 | dependencies: 241 | "@babel/helper-validator-identifier" "^7.18.6" 242 | to-fast-properties "^2.0.0" 243 | 244 | "@emotion/babel-plugin@^11.10.0": 245 | version "11.10.0" 246 | resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.0.tgz#ae545b8faa6b42d3a50ec86b70b758296f3c4467" 247 | integrity sha512-xVnpDAAbtxL1dsuSelU5A7BnY/lftws0wUexNJZTPsvX/1tM4GZJbclgODhvW4E+NH7E5VFcH0bBn30NvniPJA== 248 | dependencies: 249 | "@babel/helper-module-imports" "^7.16.7" 250 | "@babel/plugin-syntax-jsx" "^7.17.12" 251 | "@babel/runtime" "^7.18.3" 252 | "@emotion/hash" "^0.9.0" 253 | "@emotion/memoize" "^0.8.0" 254 | "@emotion/serialize" "^1.1.0" 255 | babel-plugin-macros "^3.1.0" 256 | convert-source-map "^1.5.0" 257 | escape-string-regexp "^4.0.0" 258 | find-root "^1.1.0" 259 | source-map "^0.5.7" 260 | stylis "4.0.13" 261 | 262 | "@emotion/cache@^11.10.0", "@emotion/cache@^11.9.3": 263 | version "11.10.1" 264 | resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.1.tgz#75a157c2a6bb9220450f73ebef1df2e1467dc65d" 265 | integrity sha512-uZTj3Yz5D69GE25iFZcIQtibnVCFsc/6+XIozyL3ycgWvEdif2uEw9wlUt6umjLr4Keg9K6xRPHmD8LGi+6p1A== 266 | dependencies: 267 | "@emotion/memoize" "^0.8.0" 268 | "@emotion/sheet" "^1.2.0" 269 | "@emotion/utils" "^1.2.0" 270 | "@emotion/weak-memoize" "^0.3.0" 271 | stylis "4.0.13" 272 | 273 | "@emotion/hash@^0.9.0": 274 | version "0.9.0" 275 | resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7" 276 | integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ== 277 | 278 | "@emotion/is-prop-valid@^1.1.3", "@emotion/is-prop-valid@^1.2.0": 279 | version "1.2.0" 280 | resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83" 281 | integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg== 282 | dependencies: 283 | "@emotion/memoize" "^0.8.0" 284 | 285 | "@emotion/memoize@^0.8.0": 286 | version "0.8.0" 287 | resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" 288 | integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== 289 | 290 | "@emotion/react@^11.10.0": 291 | version "11.10.0" 292 | resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.0.tgz#53c577f063f26493f68a05188fb87528d912ff2e" 293 | integrity sha512-K6z9zlHxxBXwN8TcpwBKcEsBsOw4JWCCmR+BeeOWgqp8GIU1yA2Odd41bwdAAr0ssbQrbJbVnndvv7oiv1bZeQ== 294 | dependencies: 295 | "@babel/runtime" "^7.18.3" 296 | "@emotion/babel-plugin" "^11.10.0" 297 | "@emotion/cache" "^11.10.0" 298 | "@emotion/serialize" "^1.1.0" 299 | "@emotion/utils" "^1.2.0" 300 | "@emotion/weak-memoize" "^0.3.0" 301 | hoist-non-react-statics "^3.3.1" 302 | 303 | "@emotion/serialize@^1.1.0": 304 | version "1.1.0" 305 | resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.0.tgz#b1f97b1011b09346a40e9796c37a3397b4ea8ea8" 306 | integrity sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA== 307 | dependencies: 308 | "@emotion/hash" "^0.9.0" 309 | "@emotion/memoize" "^0.8.0" 310 | "@emotion/unitless" "^0.8.0" 311 | "@emotion/utils" "^1.2.0" 312 | csstype "^3.0.2" 313 | 314 | "@emotion/sheet@^1.2.0": 315 | version "1.2.0" 316 | resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.0.tgz#771b1987855839e214fc1741bde43089397f7be5" 317 | integrity sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w== 318 | 319 | "@emotion/styled@^11.10.0": 320 | version "11.10.0" 321 | resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.0.tgz#c19484dab4206ae46727c07efb4316423dd21312" 322 | integrity sha512-V9oaEH6V4KePeQpgUE83i8ht+4Ri3E8Djp/ZPJ4DQlqWhSKITvgzlR3/YQE2hdfP4Jw3qVRkANJz01LLqK9/TA== 323 | dependencies: 324 | "@babel/runtime" "^7.18.3" 325 | "@emotion/babel-plugin" "^11.10.0" 326 | "@emotion/is-prop-valid" "^1.2.0" 327 | "@emotion/serialize" "^1.1.0" 328 | "@emotion/utils" "^1.2.0" 329 | 330 | "@emotion/unitless@^0.8.0": 331 | version "0.8.0" 332 | resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" 333 | integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== 334 | 335 | "@emotion/utils@^1.2.0": 336 | version "1.2.0" 337 | resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" 338 | integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== 339 | 340 | "@emotion/weak-memoize@^0.3.0": 341 | version "0.3.0" 342 | resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb" 343 | integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg== 344 | 345 | "@formatjs/ecma402-abstract@1.11.8": 346 | version "1.11.8" 347 | resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.8.tgz#f4015dfb6a837369d94c6ba82455c609e45bce20" 348 | integrity sha512-fgLqyWlwmTEuqV/TSLEL/t9JOmHNLFvCdgzXB0jc2w+WOItPCOJ1T0eyN6fQBQKRPfSqqNlu+kWj7ijcOVTVVQ== 349 | dependencies: 350 | "@formatjs/intl-localematcher" "0.2.28" 351 | tslib "2.4.0" 352 | 353 | "@formatjs/fast-memoize@1.2.4": 354 | version "1.2.4" 355 | resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-1.2.4.tgz#4b5ddce9eb7803ff0bd4052387672151a8b7f8a0" 356 | integrity sha512-9ARYoLR8AEzXvj2nYrOVHY/h1dDMDWGTnKDLXSISF1uoPakSmfcZuSqjiqZX2wRkEUimPxdwTu/agyozBtZRHA== 357 | dependencies: 358 | tslib "2.4.0" 359 | 360 | "@formatjs/icu-messageformat-parser@2.1.4": 361 | version "2.1.4" 362 | resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.4.tgz#f1e32b9937f151c1dd5c30536ce3e920b7f23813" 363 | integrity sha512-3PqMvKWV1oyok0BuiXUAHIaotdhdTJw6OICqCZbfUgKT+ZRwRWO4IlCgvXJeCITaKS5p+PY0XXKjf/vUyIpWjQ== 364 | dependencies: 365 | "@formatjs/ecma402-abstract" "1.11.8" 366 | "@formatjs/icu-skeleton-parser" "1.3.10" 367 | tslib "2.4.0" 368 | 369 | "@formatjs/icu-skeleton-parser@1.3.10": 370 | version "1.3.10" 371 | resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.10.tgz#2f504e56ac80137ee2baad55c7fa0b5dc7f4e4df" 372 | integrity sha512-kXJmtLDqFF5aLTf8IxdJXnhrIX1Qb4Qp3a9jqRecGDYfzOa9hMhi9U0nKyhrJJ4cXxBzptcgb+LWkyeHL6nlBQ== 373 | dependencies: 374 | "@formatjs/ecma402-abstract" "1.11.8" 375 | tslib "2.4.0" 376 | 377 | "@formatjs/intl-displaynames@6.0.3": 378 | version "6.0.3" 379 | resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-6.0.3.tgz#e648a91bccd9fb21519090eaafece3be9d15f480" 380 | integrity sha512-Mxh6W1VOlmiEvO/QPBrBQHlXrIn5VxjJWyyEI0V7ZHNGl0ee8AjSlq7vIJG8GodRJqGUuutF6N3OB/6qFv0YWg== 381 | dependencies: 382 | "@formatjs/ecma402-abstract" "1.11.8" 383 | "@formatjs/intl-localematcher" "0.2.28" 384 | tslib "2.4.0" 385 | 386 | "@formatjs/intl-listformat@7.0.3": 387 | version "7.0.3" 388 | resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-7.0.3.tgz#8627969b77849559d148bc9536d0884c2271e6de" 389 | integrity sha512-ampNLRGZl/08epHa3i5sRmcHGLneC6JrknexbbgnexYFNSmJ6AbL/dCzgrQzw2Efl+5AZK7UbNFxcDYY3RePvw== 390 | dependencies: 391 | "@formatjs/ecma402-abstract" "1.11.8" 392 | "@formatjs/intl-localematcher" "0.2.28" 393 | tslib "2.4.0" 394 | 395 | "@formatjs/intl-localematcher@0.2.28": 396 | version "0.2.28" 397 | resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.2.28.tgz#412ea7fefbfc7ed33cd6b43aa304fc14d816e564" 398 | integrity sha512-FLsc6Gifs1np/8HnCn/7Q+lHMmenrD5fuDhRT82yj0gi9O19kfaFwjQUw1gZsyILuRyT93GuzdifHj7TKRhBcw== 399 | dependencies: 400 | tslib "2.4.0" 401 | 402 | "@formatjs/intl@2.3.1": 403 | version "2.3.1" 404 | resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.3.1.tgz#eccd6d03e4db18c256181f235b1d0a7f7aaebf5a" 405 | integrity sha512-f06qZ/ukpeN24gc01qFjh3P+r3FU/ikY4yG+fDJu6dPNvpUQzDy98lYogA1dr6ig2UtrnoEk3xncyFPL1e9cZw== 406 | dependencies: 407 | "@formatjs/ecma402-abstract" "1.11.8" 408 | "@formatjs/fast-memoize" "1.2.4" 409 | "@formatjs/icu-messageformat-parser" "2.1.4" 410 | "@formatjs/intl-displaynames" "6.0.3" 411 | "@formatjs/intl-listformat" "7.0.3" 412 | intl-messageformat "10.1.1" 413 | tslib "2.4.0" 414 | 415 | "@jridgewell/gen-mapping@^0.1.0": 416 | version "0.1.1" 417 | resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" 418 | integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== 419 | dependencies: 420 | "@jridgewell/set-array" "^1.0.0" 421 | "@jridgewell/sourcemap-codec" "^1.4.10" 422 | 423 | "@jridgewell/gen-mapping@^0.3.2": 424 | version "0.3.2" 425 | resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" 426 | integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== 427 | dependencies: 428 | "@jridgewell/set-array" "^1.0.1" 429 | "@jridgewell/sourcemap-codec" "^1.4.10" 430 | "@jridgewell/trace-mapping" "^0.3.9" 431 | 432 | "@jridgewell/resolve-uri@^3.0.3": 433 | version "3.1.0" 434 | resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" 435 | integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== 436 | 437 | "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": 438 | version "1.1.2" 439 | resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" 440 | integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== 441 | 442 | "@jridgewell/sourcemap-codec@^1.4.10": 443 | version "1.4.14" 444 | resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" 445 | integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== 446 | 447 | "@jridgewell/trace-mapping@^0.3.9": 448 | version "0.3.14" 449 | resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz" 450 | integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== 451 | dependencies: 452 | "@jridgewell/resolve-uri" "^3.0.3" 453 | "@jridgewell/sourcemap-codec" "^1.4.10" 454 | 455 | "@mui/base@5.0.0-alpha.93": 456 | version "5.0.0-alpha.93" 457 | resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.93.tgz#b13310ee4bbf423ae74f1a82befd57469778fa9f" 458 | integrity sha512-IVUWO0NNlELDc9FD7mM+fWTS1/6n5sJYdIbXpLQ00NjWdVEYmTyRgUAZDlJJJrz+tbF0eeffx0kOsvJvyTZlsA== 459 | dependencies: 460 | "@babel/runtime" "^7.17.2" 461 | "@emotion/is-prop-valid" "^1.1.3" 462 | "@mui/types" "^7.1.5" 463 | "@mui/utils" "^5.9.3" 464 | "@popperjs/core" "^2.11.6" 465 | clsx "^1.2.1" 466 | prop-types "^15.8.1" 467 | react-is "^18.2.0" 468 | 469 | "@mui/core-downloads-tracker@^5.10.1": 470 | version "5.10.1" 471 | resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.1.tgz#6a04d559b51e78186486122d3de28d18517ddacb" 472 | integrity sha512-zyzLkVSqi+WuxG8UZrrOaWbhHkDK+MlHFjLpL+vqUVU6iSUaDYREu1xoLWEQsWOznT4oT2iEiGZLpQLgkn+WiA== 473 | 474 | "@mui/icons-material@^5.8.4": 475 | version "5.8.4" 476 | resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.8.4.tgz#3f2907c9f8f5ce4d754cb8fb4b68b5a1abf4d095" 477 | integrity sha512-9Z/vyj2szvEhGWDvb+gG875bOGm8b8rlHBKOD1+nA3PcgC3fV6W1AU6pfOorPeBfH2X4mb9Boe97vHvaSndQvA== 478 | dependencies: 479 | "@babel/runtime" "^7.17.2" 480 | 481 | "@mui/material@^5.10.1": 482 | version "5.10.1" 483 | resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.10.1.tgz#4a980c1fc34e2853d674dd0eff2723618402a4f4" 484 | integrity sha512-E9fhskX6TwUdAzpL5+yoAzRxb6wY4oBqmBVlgUuLndSwPRYxXoGu+z74NxbDEkxUoHdb7vrDcRTswpB6ykDITQ== 485 | dependencies: 486 | "@babel/runtime" "^7.17.2" 487 | "@mui/base" "5.0.0-alpha.93" 488 | "@mui/core-downloads-tracker" "^5.10.1" 489 | "@mui/system" "^5.10.1" 490 | "@mui/types" "^7.1.5" 491 | "@mui/utils" "^5.9.3" 492 | "@types/react-transition-group" "^4.4.5" 493 | clsx "^1.2.1" 494 | csstype "^3.1.0" 495 | prop-types "^15.8.1" 496 | react-is "^18.2.0" 497 | react-transition-group "^4.4.5" 498 | 499 | "@mui/private-theming@^5.9.3": 500 | version "5.9.3" 501 | resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.9.3.tgz#8ea06dbe0522b0cf4ba5ee19b1a4d7f74539ae1c" 502 | integrity sha512-Ys3WO39WqoGciGX9k5AIi/k2zJhlydv4FzlEEwtw9OqdMaV0ydK/TdZekKzjP9sTI/JcdAP3H5DWtUaPLQJjWg== 503 | dependencies: 504 | "@babel/runtime" "^7.17.2" 505 | "@mui/utils" "^5.9.3" 506 | prop-types "^15.8.1" 507 | 508 | "@mui/styled-engine@^5.10.1": 509 | version "5.10.1" 510 | resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.10.1.tgz#2f04fb95d73c2cb417b60d86539ddbfbab3a82e9" 511 | integrity sha512-xiQp6wvSLpMcRCOExbRSvkHf6gIQ/eeK7mx/Re6BtPPYIx6OerPwia+23uVIop/k4Bs5D+w7Rv2yXYJxo5rMSQ== 512 | dependencies: 513 | "@babel/runtime" "^7.17.2" 514 | "@emotion/cache" "^11.9.3" 515 | csstype "^3.1.0" 516 | prop-types "^15.8.1" 517 | 518 | "@mui/system@^5.10.1": 519 | version "5.10.1" 520 | resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.10.1.tgz#737cc9c703083ff14b4434ba72227522be4659bf" 521 | integrity sha512-Ix8LVAMtVrNtmncK0yc5llHWlZKCm9okbw8QMnWbI5UH+nI9qhtf+Aure4p5ei6dGKdil++lukar/GxCjfzRSg== 522 | dependencies: 523 | "@babel/runtime" "^7.17.2" 524 | "@mui/private-theming" "^5.9.3" 525 | "@mui/styled-engine" "^5.10.1" 526 | "@mui/types" "^7.1.5" 527 | "@mui/utils" "^5.9.3" 528 | clsx "^1.2.1" 529 | csstype "^3.1.0" 530 | prop-types "^15.8.1" 531 | 532 | "@mui/types@^7.1.5": 533 | version "7.1.5" 534 | resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.1.5.tgz#5e5cc49d719bc86522983359bc1f90eddcff0624" 535 | integrity sha512-HnRXrxgHJYJcT8ZDdDCQIlqk0s0skOKD7eWs9mJgBUu70hyW4iA6Kiv3yspJR474RFH8hysKR65VVSzUSzkuwA== 536 | 537 | "@mui/utils@^5.9.3": 538 | version "5.9.3" 539 | resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.9.3.tgz#a11e0824f00b7ea40257b390060ce167fe861d02" 540 | integrity sha512-l0N5bcrenE9hnwZ/jPecpIRqsDFHkPXoFUcmkgysaJwVZzJ3yQkGXB47eqmXX5yyGrSc6HksbbqXEaUya+siew== 541 | dependencies: 542 | "@babel/runtime" "^7.17.2" 543 | "@types/prop-types" "^15.7.5" 544 | "@types/react-is" "^16.7.1 || ^17.0.0" 545 | prop-types "^15.8.1" 546 | react-is "^18.2.0" 547 | 548 | "@popperjs/core@^2.11.6": 549 | version "2.11.6" 550 | resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" 551 | integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== 552 | 553 | "@types/hoist-non-react-statics@^3.3.1": 554 | version "3.3.1" 555 | resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" 556 | integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== 557 | dependencies: 558 | "@types/react" "*" 559 | hoist-non-react-statics "^3.3.0" 560 | 561 | "@types/parse-json@^4.0.0": 562 | version "4.0.0" 563 | resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" 564 | integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== 565 | 566 | "@types/prop-types@*", "@types/prop-types@^15.7.5": 567 | version "15.7.5" 568 | resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz" 569 | integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== 570 | 571 | "@types/react-dom@^18.0.6": 572 | version "18.0.6" 573 | resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz" 574 | integrity sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA== 575 | dependencies: 576 | "@types/react" "*" 577 | 578 | "@types/react-is@^16.7.1 || ^17.0.0": 579 | version "17.0.3" 580 | resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.3.tgz#2d855ba575f2fc8d17ef9861f084acc4b90a137a" 581 | integrity sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw== 582 | dependencies: 583 | "@types/react" "*" 584 | 585 | "@types/react-transition-group@^4.4.5": 586 | version "4.4.5" 587 | resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" 588 | integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== 589 | dependencies: 590 | "@types/react" "*" 591 | 592 | "@types/react@*", "@types/react@^18.0.15": 593 | version "18.0.15" 594 | resolved "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz" 595 | integrity sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow== 596 | dependencies: 597 | "@types/prop-types" "*" 598 | "@types/scheduler" "*" 599 | csstype "^3.0.2" 600 | 601 | "@types/react@16 || 17 || 18": 602 | version "18.0.17" 603 | resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.17.tgz#4583d9c322d67efe4b39a935d223edcc7050ccf4" 604 | integrity sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ== 605 | dependencies: 606 | "@types/prop-types" "*" 607 | "@types/scheduler" "*" 608 | csstype "^3.0.2" 609 | 610 | "@types/scheduler@*": 611 | version "0.16.2" 612 | resolved "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" 613 | integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== 614 | 615 | "@vitejs/plugin-react@^2.0.0": 616 | version "2.0.0" 617 | resolved "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-2.0.0.tgz" 618 | integrity sha512-zHkRR+X4zqEPNBbKV2FvWSxK7Q6crjMBVIAYroSU8Nbb4M3E5x4qOiLoqJBHtXgr27kfednXjkwr3lr8jS6Wrw== 619 | dependencies: 620 | "@babel/core" "^7.18.6" 621 | "@babel/plugin-transform-react-jsx" "^7.18.6" 622 | "@babel/plugin-transform-react-jsx-development" "^7.18.6" 623 | "@babel/plugin-transform-react-jsx-self" "^7.18.6" 624 | "@babel/plugin-transform-react-jsx-source" "^7.18.6" 625 | magic-string "^0.26.2" 626 | react-refresh "^0.14.0" 627 | 628 | ansi-styles@^3.2.1: 629 | version "3.2.1" 630 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" 631 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 632 | dependencies: 633 | color-convert "^1.9.0" 634 | 635 | babel-plugin-macros@^3.1.0: 636 | version "3.1.0" 637 | resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" 638 | integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== 639 | dependencies: 640 | "@babel/runtime" "^7.12.5" 641 | cosmiconfig "^7.0.0" 642 | resolve "^1.19.0" 643 | 644 | browserslist@^4.20.2: 645 | version "4.21.3" 646 | resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz" 647 | integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ== 648 | dependencies: 649 | caniuse-lite "^1.0.30001370" 650 | electron-to-chromium "^1.4.202" 651 | node-releases "^2.0.6" 652 | update-browserslist-db "^1.0.5" 653 | 654 | callsites@^3.0.0: 655 | version "3.1.0" 656 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 657 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 658 | 659 | caniuse-lite@^1.0.30001370: 660 | version "1.0.30001370" 661 | resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001370.tgz" 662 | integrity sha512-3PDmaP56wz/qz7G508xzjx8C+MC2qEm4SYhSEzC9IBROo+dGXFWRuaXkWti0A9tuI00g+toiriVqxtWMgl350g== 663 | 664 | chalk@^2.0.0: 665 | version "2.4.2" 666 | resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" 667 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 668 | dependencies: 669 | ansi-styles "^3.2.1" 670 | escape-string-regexp "^1.0.5" 671 | supports-color "^5.3.0" 672 | 673 | clsx@^1.2.1: 674 | version "1.2.1" 675 | resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" 676 | integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== 677 | 678 | color-convert@^1.9.0: 679 | version "1.9.3" 680 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" 681 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 682 | dependencies: 683 | color-name "1.1.3" 684 | 685 | color-name@1.1.3: 686 | version "1.1.3" 687 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" 688 | integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== 689 | 690 | convert-source-map@^1.5.0, convert-source-map@^1.7.0: 691 | version "1.8.0" 692 | resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" 693 | integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== 694 | dependencies: 695 | safe-buffer "~5.1.1" 696 | 697 | cosmiconfig@^7.0.0: 698 | version "7.0.1" 699 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" 700 | integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== 701 | dependencies: 702 | "@types/parse-json" "^4.0.0" 703 | import-fresh "^3.2.1" 704 | parse-json "^5.0.0" 705 | path-type "^4.0.0" 706 | yaml "^1.10.0" 707 | 708 | csstype@^3.0.2, csstype@^3.1.0: 709 | version "3.1.0" 710 | resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz" 711 | integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== 712 | 713 | debug@^4.1.0: 714 | version "4.3.4" 715 | resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" 716 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 717 | dependencies: 718 | ms "2.1.2" 719 | 720 | dom-helpers@^5.0.1: 721 | version "5.2.1" 722 | resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902" 723 | integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA== 724 | dependencies: 725 | "@babel/runtime" "^7.8.7" 726 | csstype "^3.0.2" 727 | 728 | electron-to-chromium@^1.4.202: 729 | version "1.4.202" 730 | resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.202.tgz" 731 | integrity sha512-JYsK2ex9lmQD27kj19fhXYxzFJ/phLAkLKHv49A5UY6kMRV2xED3qMMLg/voW/+0AR6wMiI+VxlmK9NDtdxlPA== 732 | 733 | error-ex@^1.3.1: 734 | version "1.3.2" 735 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 736 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 737 | dependencies: 738 | is-arrayish "^0.2.1" 739 | 740 | esbuild-android-64@0.14.50: 741 | version "0.14.50" 742 | resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.50.tgz#a46fc80fa2007690e647680d837483a750a3097f" 743 | integrity sha512-H7iUEm7gUJHzidsBlFPGF6FTExazcgXL/46xxLo6i6bMtPim6ZmXyTccS8yOMpy6HAC6dPZ/JCQqrkkin69n6Q== 744 | 745 | esbuild-android-arm64@0.14.50: 746 | version "0.14.50" 747 | resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.50.tgz#bdda7851fa7f5f770d6ff0ad593a8945d3a0fcdd" 748 | integrity sha512-NFaoqEwa+OYfoYVpQWDMdKII7wZZkAjtJFo1WdnBeCYlYikvUhTnf2aPwPu5qEAw/ie1NYK0yn3cafwP+kP+OQ== 749 | 750 | esbuild-darwin-64@0.14.50: 751 | version "0.14.50" 752 | resolved "https://registry.yarnpkg.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.50.tgz#f0535435f9760766f30db14a991ee5ca94c022a4" 753 | integrity sha512-gDQsCvGnZiJv9cfdO48QqxkRV8oKAXgR2CGp7TdIpccwFdJMHf8hyIJhMW/05b/HJjET/26Us27Jx91BFfEVSA== 754 | 755 | esbuild-darwin-arm64@0.14.50: 756 | version "0.14.50" 757 | resolved "https://registry.yarnpkg.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.50.tgz#76a41a40e8947a15ae62970e9ed2853883c4b16c" 758 | integrity sha512-36nNs5OjKIb/Q50Sgp8+rYW/PqirRiFN0NFc9hEvgPzNJxeJedktXwzfJSln4EcRFRh5Vz4IlqFRScp+aiBBzA== 759 | 760 | esbuild-freebsd-64@0.14.50: 761 | version "0.14.50" 762 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.50.tgz#2ed6633c17ed42c20a1bd68e82c4bbc75ea4fb57" 763 | integrity sha512-/1pHHCUem8e/R86/uR+4v5diI2CtBdiWKiqGuPa9b/0x3Nwdh5AOH7lj+8823C6uX1e0ufwkSLkS+aFZiBCWxA== 764 | 765 | esbuild-freebsd-arm64@0.14.50: 766 | version "0.14.50" 767 | resolved "https://registry.yarnpkg.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.50.tgz#cb115f4cdafe9cdbe58875ba482fccc54d32aa43" 768 | integrity sha512-iKwUVMQztnPZe5pUYHdMkRc9aSpvoV1mkuHlCoPtxZA3V+Kg/ptpzkcSY+fKd0kuom+l6Rc93k0UPVkP7xoqrw== 769 | 770 | esbuild-linux-32@0.14.50: 771 | version "0.14.50" 772 | resolved "https://registry.yarnpkg.com/esbuild-linux-32/-/esbuild-linux-32-0.14.50.tgz#fe2b724994dcf1d4e48dc4832ff008ad7d00bcfd" 773 | integrity sha512-sWUwvf3uz7dFOpLzYuih+WQ7dRycrBWHCdoXJ4I4XdMxEHCECd8b7a9N9u7FzT6XR2gHPk9EzvchQUtiEMRwqw== 774 | 775 | esbuild-linux-64@0.14.50: 776 | version "0.14.50" 777 | resolved "https://registry.yarnpkg.com/esbuild-linux-64/-/esbuild-linux-64-0.14.50.tgz#7851ab5151df9501a2187bd4909c594ad232b623" 778 | integrity sha512-u0PQxPhaeI629t4Y3EEcQ0wmWG+tC/LpP2K7yDFvwuPq0jSQ8SIN+ARNYfRjGW15O2we3XJvklbGV0wRuUCPig== 779 | 780 | esbuild-linux-arm64@0.14.50: 781 | version "0.14.50" 782 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.50.tgz#76a76afef484a0512f1fbbcc762edd705dee8892" 783 | integrity sha512-ZyfoNgsTftD7Rp5S7La5auomKdNeB3Ck+kSKXC4pp96VnHyYGjHHXWIlcbH8i+efRn9brszo1/Thl1qn8RqmhQ== 784 | 785 | esbuild-linux-arm@0.14.50: 786 | version "0.14.50" 787 | resolved "https://registry.yarnpkg.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.50.tgz#6d7a8c0712091b0c3a668dd5d8b5c924adbaeb12" 788 | integrity sha512-VALZq13bhmFJYFE/mLEb+9A0w5vo8z+YDVOWeaf9vOTrSC31RohRIwtxXBnVJ7YKLYfEMzcgFYf+OFln3Y0cWg== 789 | 790 | esbuild-linux-mips64le@0.14.50: 791 | version "0.14.50" 792 | resolved "https://registry.yarnpkg.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.50.tgz#43426909c1884c5dc6b40765673a08a7ec1d2064" 793 | integrity sha512-ygo31Vxn/WrmjKCHkBoutOlFG5yM9J2UhzHb0oWD9O61dGg+Hzjz9hjf5cmM7FBhAzdpOdEWHIrVOg2YAi6rTw== 794 | 795 | esbuild-linux-ppc64le@0.14.50: 796 | version "0.14.50" 797 | resolved "https://registry.yarnpkg.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.50.tgz#c754ea3da1dd180c6e9b6b508dc18ce983d92b11" 798 | integrity sha512-xWCKU5UaiTUT6Wz/O7GKP9KWdfbsb7vhfgQzRfX4ahh5NZV4ozZ4+SdzYG8WxetsLy84UzLX3Pi++xpVn1OkFQ== 799 | 800 | esbuild-linux-riscv64@0.14.50: 801 | version "0.14.50" 802 | resolved "https://registry.yarnpkg.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.50.tgz#f3b2dd3c4c2b91bf191d3b98a9819c8aa6f5ad7f" 803 | integrity sha512-0+dsneSEihZTopoO9B6Z6K4j3uI7EdxBP7YSF5rTwUgCID+wHD3vM1gGT0m+pjCW+NOacU9kH/WE9N686FHAJg== 804 | 805 | esbuild-linux-s390x@0.14.50: 806 | version "0.14.50" 807 | resolved "https://registry.yarnpkg.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.50.tgz#3dfbc4578b2a81995caabb79df2b628ea86a5390" 808 | integrity sha512-tVjqcu8o0P9H4StwbIhL1sQYm5mWATlodKB6dpEZFkcyTI8kfIGWiWcrGmkNGH2i1kBUOsdlBafPxR3nzp3TDA== 809 | 810 | esbuild-netbsd-64@0.14.50: 811 | version "0.14.50" 812 | resolved "https://registry.yarnpkg.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.50.tgz#17dbf51eaa48d983e794b588d195415410ef8c85" 813 | integrity sha512-0R/glfqAQ2q6MHDf7YJw/TulibugjizBxyPvZIcorH0Mb7vSimdHy0XF5uCba5CKt+r4wjax1mvO9lZ4jiAhEg== 814 | 815 | esbuild-openbsd-64@0.14.50: 816 | version "0.14.50" 817 | resolved "https://registry.yarnpkg.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.50.tgz#cf6b1a50c8cf67b0725aaa4bce9773976168c50e" 818 | integrity sha512-7PAtmrR5mDOFubXIkuxYQ4bdNS6XCK8AIIHUiZxq1kL8cFIH5731jPcXQ4JNy/wbj1C9sZ8rzD8BIM80Tqk29w== 819 | 820 | esbuild-sunos-64@0.14.50: 821 | version "0.14.50" 822 | resolved "https://registry.yarnpkg.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.50.tgz#f705ae0dd914c3b45dc43319c4f532216c3d841f" 823 | integrity sha512-gBxNY/wyptvD7PkHIYcq7se6SQEXcSC8Y7mE0FJB+CGgssEWf6vBPfTTZ2b6BWKnmaP6P6qb7s/KRIV5T2PxsQ== 824 | 825 | esbuild-windows-32@0.14.50: 826 | version "0.14.50" 827 | resolved "https://registry.yarnpkg.com/esbuild-windows-32/-/esbuild-windows-32-0.14.50.tgz#6364905a99c1e6c1e2fe7bfccebd958131b1cd6c" 828 | integrity sha512-MOOe6J9cqe/iW1qbIVYSAqzJFh0p2LBLhVUIWdMVnNUNjvg2/4QNX4oT4IzgDeldU+Bym9/Tn6+DxvUHJXL5Zw== 829 | 830 | esbuild-windows-64@0.14.50: 831 | version "0.14.50" 832 | resolved "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.50.tgz" 833 | integrity sha512-r/qE5Ex3w1jjGv/JlpPoWB365ldkppUlnizhMxJgojp907ZF1PgLTuW207kgzZcSCXyquL9qJkMsY+MRtaZ5yQ== 834 | 835 | esbuild-windows-arm64@0.14.50: 836 | version "0.14.50" 837 | resolved "https://registry.yarnpkg.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.50.tgz#e7ddde6a97194051a5a4ac05f4f5900e922a7ea5" 838 | integrity sha512-EMS4lQnsIe12ZyAinOINx7eq2mjpDdhGZZWDwPZE/yUTN9cnc2Ze/xUTYIAyaJqrqQda3LnDpADKpvLvol6ENQ== 839 | 840 | esbuild@^0.14.47: 841 | version "0.14.50" 842 | resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.14.50.tgz" 843 | integrity sha512-SbC3k35Ih2IC6trhbMYW7hYeGdjPKf9atTKwBUHqMCYFZZ9z8zhuvfnZihsnJypl74FjiAKjBRqFkBkAd0rS/w== 844 | optionalDependencies: 845 | esbuild-android-64 "0.14.50" 846 | esbuild-android-arm64 "0.14.50" 847 | esbuild-darwin-64 "0.14.50" 848 | esbuild-darwin-arm64 "0.14.50" 849 | esbuild-freebsd-64 "0.14.50" 850 | esbuild-freebsd-arm64 "0.14.50" 851 | esbuild-linux-32 "0.14.50" 852 | esbuild-linux-64 "0.14.50" 853 | esbuild-linux-arm "0.14.50" 854 | esbuild-linux-arm64 "0.14.50" 855 | esbuild-linux-mips64le "0.14.50" 856 | esbuild-linux-ppc64le "0.14.50" 857 | esbuild-linux-riscv64 "0.14.50" 858 | esbuild-linux-s390x "0.14.50" 859 | esbuild-netbsd-64 "0.14.50" 860 | esbuild-openbsd-64 "0.14.50" 861 | esbuild-sunos-64 "0.14.50" 862 | esbuild-windows-32 "0.14.50" 863 | esbuild-windows-64 "0.14.50" 864 | esbuild-windows-arm64 "0.14.50" 865 | 866 | escalade@^3.1.1: 867 | version "3.1.1" 868 | resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" 869 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== 870 | 871 | escape-string-regexp@^1.0.5: 872 | version "1.0.5" 873 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" 874 | integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== 875 | 876 | escape-string-regexp@^4.0.0: 877 | version "4.0.0" 878 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 879 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 880 | 881 | find-root@^1.1.0: 882 | version "1.1.0" 883 | resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" 884 | integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== 885 | 886 | fsevents@~2.3.2: 887 | version "2.3.2" 888 | resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" 889 | integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== 890 | 891 | function-bind@^1.1.1: 892 | version "1.1.1" 893 | resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" 894 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 895 | 896 | gensync@^1.0.0-beta.2: 897 | version "1.0.0-beta.2" 898 | resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" 899 | integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== 900 | 901 | globals@^11.1.0: 902 | version "11.12.0" 903 | resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" 904 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== 905 | 906 | has-flag@^3.0.0: 907 | version "3.0.0" 908 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" 909 | integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== 910 | 911 | has@^1.0.3: 912 | version "1.0.3" 913 | resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" 914 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 915 | dependencies: 916 | function-bind "^1.1.1" 917 | 918 | hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: 919 | version "3.3.2" 920 | resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" 921 | integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== 922 | dependencies: 923 | react-is "^16.7.0" 924 | 925 | import-fresh@^3.2.1: 926 | version "3.3.0" 927 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" 928 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 929 | dependencies: 930 | parent-module "^1.0.0" 931 | resolve-from "^4.0.0" 932 | 933 | intl-messageformat@10.1.1: 934 | version "10.1.1" 935 | resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.1.1.tgz#226767e7921fa86cef2cbe4a13911050716720bc" 936 | integrity sha512-FeJne2oooYW6shLPbrqyjRX6hTELVrQ90Dn88z7NomLk/xZBCLxLPAkgaYaTQJBRBV78nZ933d8APHHkTQrD9Q== 937 | dependencies: 938 | "@formatjs/ecma402-abstract" "1.11.8" 939 | "@formatjs/fast-memoize" "1.2.4" 940 | "@formatjs/icu-messageformat-parser" "2.1.4" 941 | tslib "2.4.0" 942 | 943 | is-arrayish@^0.2.1: 944 | version "0.2.1" 945 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 946 | integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== 947 | 948 | is-core-module@^2.9.0: 949 | version "2.9.0" 950 | resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz" 951 | integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== 952 | dependencies: 953 | has "^1.0.3" 954 | 955 | "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: 956 | version "4.0.0" 957 | resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" 958 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 959 | 960 | jsesc@^2.5.1: 961 | version "2.5.2" 962 | resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" 963 | integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== 964 | 965 | json-parse-even-better-errors@^2.3.0: 966 | version "2.3.1" 967 | resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" 968 | integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== 969 | 970 | json5@^2.2.1: 971 | version "2.2.1" 972 | resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" 973 | integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== 974 | 975 | lines-and-columns@^1.1.6: 976 | version "1.2.4" 977 | resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" 978 | integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== 979 | 980 | loose-envify@^1.1.0, loose-envify@^1.4.0: 981 | version "1.4.0" 982 | resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" 983 | integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== 984 | dependencies: 985 | js-tokens "^3.0.0 || ^4.0.0" 986 | 987 | magic-string@^0.26.2: 988 | version "0.26.2" 989 | resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz" 990 | integrity sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A== 991 | dependencies: 992 | sourcemap-codec "^1.4.8" 993 | 994 | ms@2.1.2: 995 | version "2.1.2" 996 | resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" 997 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 998 | 999 | nanoid@^3.3.4: 1000 | version "3.3.4" 1001 | resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz" 1002 | integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== 1003 | 1004 | node-releases@^2.0.6: 1005 | version "2.0.6" 1006 | resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz" 1007 | integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== 1008 | 1009 | object-assign@^4.1.1: 1010 | version "4.1.1" 1011 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1012 | integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== 1013 | 1014 | parent-module@^1.0.0: 1015 | version "1.0.1" 1016 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 1017 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 1018 | dependencies: 1019 | callsites "^3.0.0" 1020 | 1021 | parse-json@^5.0.0: 1022 | version "5.2.0" 1023 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" 1024 | integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== 1025 | dependencies: 1026 | "@babel/code-frame" "^7.0.0" 1027 | error-ex "^1.3.1" 1028 | json-parse-even-better-errors "^2.3.0" 1029 | lines-and-columns "^1.1.6" 1030 | 1031 | path-parse@^1.0.7: 1032 | version "1.0.7" 1033 | resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" 1034 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 1035 | 1036 | path-type@^4.0.0: 1037 | version "4.0.0" 1038 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" 1039 | integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== 1040 | 1041 | picocolors@^1.0.0: 1042 | version "1.0.0" 1043 | resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" 1044 | integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== 1045 | 1046 | postcss@^8.4.14: 1047 | version "8.4.14" 1048 | resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz" 1049 | integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== 1050 | dependencies: 1051 | nanoid "^3.3.4" 1052 | picocolors "^1.0.0" 1053 | source-map-js "^1.0.2" 1054 | 1055 | prop-types@^15.6.2, prop-types@^15.8.1: 1056 | version "15.8.1" 1057 | resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" 1058 | integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== 1059 | dependencies: 1060 | loose-envify "^1.4.0" 1061 | object-assign "^4.1.1" 1062 | react-is "^16.13.1" 1063 | 1064 | react-dom@^18.2.0: 1065 | version "18.2.0" 1066 | resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz" 1067 | integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== 1068 | dependencies: 1069 | loose-envify "^1.1.0" 1070 | scheduler "^0.23.0" 1071 | 1072 | react-intl@^6.0.5: 1073 | version "6.0.5" 1074 | resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-6.0.5.tgz#8adcb9108682c82e625a8ce7826283afd3537f62" 1075 | integrity sha512-nDZ3BosuE8WdovcGxsrjj1aIgJZklSL5aORs5oah+5tLQTzUdOEstzJEYQPM+sxl1dkDOu7RCuw0z9oI9ENf9g== 1076 | dependencies: 1077 | "@formatjs/ecma402-abstract" "1.11.8" 1078 | "@formatjs/icu-messageformat-parser" "2.1.4" 1079 | "@formatjs/intl" "2.3.1" 1080 | "@formatjs/intl-displaynames" "6.0.3" 1081 | "@formatjs/intl-listformat" "7.0.3" 1082 | "@types/hoist-non-react-statics" "^3.3.1" 1083 | "@types/react" "16 || 17 || 18" 1084 | hoist-non-react-statics "^3.3.2" 1085 | intl-messageformat "10.1.1" 1086 | tslib "2.4.0" 1087 | 1088 | react-is@^16.13.1, react-is@^16.7.0: 1089 | version "16.13.1" 1090 | resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" 1091 | integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== 1092 | 1093 | react-is@^18.2.0: 1094 | version "18.2.0" 1095 | resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" 1096 | integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== 1097 | 1098 | react-refresh@^0.14.0: 1099 | version "0.14.0" 1100 | resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz" 1101 | integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== 1102 | 1103 | react-transition-group@^4.4.5: 1104 | version "4.4.5" 1105 | resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" 1106 | integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== 1107 | dependencies: 1108 | "@babel/runtime" "^7.5.5" 1109 | dom-helpers "^5.0.1" 1110 | loose-envify "^1.4.0" 1111 | prop-types "^15.6.2" 1112 | 1113 | react@^18.2.0: 1114 | version "18.2.0" 1115 | resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" 1116 | integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== 1117 | dependencies: 1118 | loose-envify "^1.1.0" 1119 | 1120 | regenerator-runtime@^0.13.4: 1121 | version "0.13.9" 1122 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" 1123 | integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== 1124 | 1125 | resolve-from@^4.0.0: 1126 | version "4.0.0" 1127 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1128 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1129 | 1130 | resolve@^1.19.0, resolve@^1.22.1: 1131 | version "1.22.1" 1132 | resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz" 1133 | integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== 1134 | dependencies: 1135 | is-core-module "^2.9.0" 1136 | path-parse "^1.0.7" 1137 | supports-preserve-symlinks-flag "^1.0.0" 1138 | 1139 | rollup@^2.75.6: 1140 | version "2.77.2" 1141 | resolved "https://registry.npmjs.org/rollup/-/rollup-2.77.2.tgz" 1142 | integrity sha512-m/4YzYgLcpMQbxX3NmAqDvwLATZzxt8bIegO78FZLl+lAgKJBd1DRAOeEiZcKOIOPjxE6ewHWHNgGEalFXuz1g== 1143 | optionalDependencies: 1144 | fsevents "~2.3.2" 1145 | 1146 | safe-buffer@~5.1.1: 1147 | version "5.1.2" 1148 | resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" 1149 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 1150 | 1151 | scheduler@^0.23.0: 1152 | version "0.23.0" 1153 | resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz" 1154 | integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== 1155 | dependencies: 1156 | loose-envify "^1.1.0" 1157 | 1158 | semver@^6.3.0: 1159 | version "6.3.0" 1160 | resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" 1161 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== 1162 | 1163 | source-map-js@^1.0.2: 1164 | version "1.0.2" 1165 | resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz" 1166 | integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== 1167 | 1168 | source-map@^0.5.7: 1169 | version "0.5.7" 1170 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 1171 | integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== 1172 | 1173 | sourcemap-codec@^1.4.8: 1174 | version "1.4.8" 1175 | resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" 1176 | integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== 1177 | 1178 | stylis@4.0.13: 1179 | version "4.0.13" 1180 | resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" 1181 | integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== 1182 | 1183 | supports-color@^5.3.0: 1184 | version "5.5.0" 1185 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" 1186 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1187 | dependencies: 1188 | has-flag "^3.0.0" 1189 | 1190 | supports-preserve-symlinks-flag@^1.0.0: 1191 | version "1.0.0" 1192 | resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" 1193 | integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== 1194 | 1195 | to-fast-properties@^2.0.0: 1196 | version "2.0.0" 1197 | resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" 1198 | integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== 1199 | 1200 | tslib@2.4.0: 1201 | version "2.4.0" 1202 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" 1203 | integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== 1204 | 1205 | update-browserslist-db@^1.0.5: 1206 | version "1.0.5" 1207 | resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz" 1208 | integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q== 1209 | dependencies: 1210 | escalade "^3.1.1" 1211 | picocolors "^1.0.0" 1212 | 1213 | vite@^3.0.0: 1214 | version "3.0.3" 1215 | resolved "https://registry.npmjs.org/vite/-/vite-3.0.3.tgz" 1216 | integrity sha512-sDIpIcl3mv1NUaSzZwiXGEy1ZoWwwC2vkxUHY6yiDacR6zf//ZFuBJrozO62gedpE43pmxnLATNR5IYUdAEkMQ== 1217 | dependencies: 1218 | esbuild "^0.14.47" 1219 | postcss "^8.4.14" 1220 | resolve "^1.22.1" 1221 | rollup "^2.75.6" 1222 | optionalDependencies: 1223 | fsevents "~2.3.2" 1224 | 1225 | yaml@^1.10.0: 1226 | version "1.10.2" 1227 | resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" 1228 | integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== 1229 | --------------------------------------------------------------------------------