From 2dd2b5b79cbf6a63091ed518354b8798a9046698 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Mon, 10 Apr 2023 23:27:14 +0800 Subject: [PATCH 01/22] Add utility functions --- src/Utils/arrayDeepCopy.js | 6 ++ src/Utils/checkBoard.js | 115 +++++++++++++++++++++++++ src/Utils/checkWin.js | 13 +++ src/Utils/createSudokuGrid.js | 157 ++++++++++++++++++++++++++++++++++ src/Utils/getHint.js | 39 +++++++++ src/Utils/solveSudoku.js | 43 ++++++++++ 6 files changed, 373 insertions(+) create mode 100644 src/Utils/arrayDeepCopy.js create mode 100644 src/Utils/checkBoard.js create mode 100644 src/Utils/checkWin.js create mode 100644 src/Utils/createSudokuGrid.js create mode 100644 src/Utils/getHint.js create mode 100644 src/Utils/solveSudoku.js diff --git a/src/Utils/arrayDeepCopy.js b/src/Utils/arrayDeepCopy.js new file mode 100644 index 00000000..35f64601 --- /dev/null +++ b/src/Utils/arrayDeepCopy.js @@ -0,0 +1,6 @@ +const arrayDeepCopy = (arr) => { + let newArray = JSON.parse(JSON.stringify(arr)); + return newArray; +}; + +export default arrayDeepCopy; diff --git a/src/Utils/checkBoard.js b/src/Utils/checkBoard.js new file mode 100644 index 00000000..c9f17f97 --- /dev/null +++ b/src/Utils/checkBoard.js @@ -0,0 +1,115 @@ +// Checks for errors in user input +// If a number appears in a row/col more than once, add row/col index to wrongLines +const getWrongLines = (board, type) => { + let wrongLines = new Set(); + + for (let i = 0; i < 9; i++) { + let dict = {}; + + for (let j = 0; j < 9; j++) { + let key; + if (type === "horizontal") key = board[i][j].value; + else key = board[j][i].value; + + if (key === 0) continue; + + if (Object.hasOwnProperty.call(dict, key)) { + dict[key] += 1; + if (dict[key] > 1) { + wrongLines.add(i); + break; + } + } else dict[key] = 1; + } + } + return wrongLines; +}; + +// Check for errors in 3x3 squares +// If number appears in a square more than once, return false +const isSquareValid = (board, x0, y0) => { + let dict = {}; + + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 3; j++) { + let key = board[x0 + i][y0 + j].value; + if (key === 0) continue; + + if (Object.hasOwnProperty.call(dict, key)) { + dict[key] += 1; + if (dict[key] > 1) { + console.log(x0, y0); + return false; + } + } else dict[key] = 1; + } + } + return true; +}; + +// Return all squares that contain duplicate numbers +const getWrongSquares = (board) => { + let wrongSquares = new Set(); + let squareValues = { + 0: { x: 0, y: 0 }, + 1: { x: 0, y: 3 }, + 2: { x: 0, y: 6 }, + 3: { x: 3, y: 0 }, + 4: { x: 3, y: 3 }, + 5: { x: 3, y: 6 }, + 6: { x: 6, y: 0 }, + 7: { x: 6, y: 3 }, + 8: { x: 6, y: 6 }, + }; + + // We check every box + for (let square = 0; square < 9; square++) { + // Now check all cells of the selected square + let x0 = squareValues[square].x; + let y0 = squareValues[square].y; + + if (!isSquareValid(board, x0, y0)) { + wrongSquares.add(square); + } + } + + return wrongSquares; +}; + +// Numbers squares from 0-8 +const getSquareNumber = (x, y) => { + let x0 = Math.floor(x / 3); + let y0 = Math.floor(y / 3); + let squareNumber = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + ][x0][y0]; + return squareNumber; +}; + +// If there are duplicate numbers in any given row/col/square, the board is not valid +const checkBoard = (board) => { + let wrongHorizontal = getWrongLines(board, "horizontal"); + let wrongVertical = getWrongLines(board, "vertical"); + let wrongSquares = getWrongSquares(board); + + console.log(getSquareNumber(1, 5)); + console.log(wrongSquares); + + for (let i = 0; i < 9; i++) { + for (let j = 0; j < 9; j++) { + if ( + wrongHorizontal.has(i) || + wrongVertical.has(j) || + wrongSquares.has(getSquareNumber(i, j)) + ) { + board[i][j].isValid = false; + } else { + board[i][j].isValid = true; + } + } + } +}; + +export default checkBoard; diff --git a/src/Utils/checkWin.js b/src/Utils/checkWin.js new file mode 100644 index 00000000..58b6b0bd --- /dev/null +++ b/src/Utils/checkWin.js @@ -0,0 +1,13 @@ +// Checks if player has won +const checkWin = (board) => { + for (let i = 0; i < 9; i++) { + for (let j = 0; j < 9; j++) { + if (board[i][j].value === 0 || board[i][j].isValid === false) { + return false; + } + } + } + return true; +}; + +export default checkWin; diff --git a/src/Utils/createSudokuGrid.js b/src/Utils/createSudokuGrid.js new file mode 100644 index 00000000..e64af14c --- /dev/null +++ b/src/Utils/createSudokuGrid.js @@ -0,0 +1,157 @@ +// Check if cell is valid +// It shouldn't match any numbers on the same row, col, or square +const isValidCell = (row, col, value, board) => { + const cellValue = value; + + // Check cells on same row + // If any cell on same row has same value, cell is not valid + for (let i = 0; i < 9; i++) { + if (board[row][i] === cellValue) return false; + } + + // Check cells on same col + // If any cell on same col has same value, cell is not valid + for (let i = 0; i < 9; i++) { + if (board[i][col] === cellValue) return false; + } + + // Check 3x3 squares + // We only have to check the diagonal of the square + // If any cell in same square has same value, cell is not valid + let x0 = Math.floor(row / 3) * 3; + let y0 = Math.floor(col / 3) * 3; + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 3; j++) { + if (board[x0 + i][y0 + j] === cellValue) return false; + } + } + + return true; +}; + +// Count the number of correct numbers on board +const countSudokuSolution = (board) => { + // console.log(board); + for (let i = 0; i < 9; i++) { + for (let j = 0; j < 9; j++) { + if (board[i][j] === 0) { + let count = 0; + for (let k = 1; k <= 9; k++) { + if (isValidCell(i, j, k, board)) { + board[i][j] = k; + count += countSudokuSolution(board); + board[i][j] = 0; + } + } + return count; + } + } + } + return 1; +}; + +// Solve a random board +const solveRandomSudoku = (board) => { + // console.log(board); + for (let i = 0; i < 9; i++) { + for (let j = 0; j < 9; j++) { + if (board[i][j] === 0) { + for (let k = 1; k <= 9; k++) { + let num = Math.floor(Math.random() * 9) + 1; + if (isValidCell(i, j, num, board)) { + board[i][j] = num; + if (solveRandomSudoku(board)) return true; + board[i][j] = 0; + } + } + return false; + } + } + } + return true; +}; + +// Get a sudoku grid +// A sudoku grid is made up of 9 3x3 boxes that together form a 9x9 board +// We can visualise it as an array made up of 9 array "rows" (a 2D array) +const getSudokuGrid = (maxEmptyCellsCount) => { + let sudokuGrid = [ + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + ]; + + solveRandomSudoku(sudokuGrid); + + // The min number of filled cells so that a unique solution exists is 17 + let emptyCells = 0; + let shuffledCells = []; + for (let i = 0; i < 81; i++) { + shuffledCells.push(i); + } + + // Shuffle the array to get random ordering of elements + shuffledCells.sort(() => Math.random() - 0.5); + + let index = 0; + while (emptyCells <= maxEmptyCellsCount && index < 81) { + if (shuffledCells.length === 0) break; + + let cell = shuffledCells[index]; + index++; + + let i = Math.floor(cell / 9); + let j = cell % 9; + + let value = sudokuGrid[i][j]; + sudokuGrid[i][j] = 0; + + let count = countSudokuSolution(sudokuGrid); + + if (count === 1) emptyCells++; + else sudokuGrid[i][j] = value; + } + + return sudokuGrid; +}; + +// Get a valid cell +const getCell = (row, column, value, isEditable) => { + return { + row: row, + column: column, + value: value, + isValid: true, + isEditable: isEditable, + isHinted: false, + }; +}; + +// Creates random sudoku grid with 9 inner "row" arrays in a single array and min 17 empty cells +// If cell is empty, let it be editable so users can input a value +const createSudokuGrid = (maxEmptyCellsCount) => { + const numberGrid = getSudokuGrid(maxEmptyCellsCount); + let sudokuGrid = []; + + for (let i = 0; i < 9; i++) { + let row = []; + for (let j = 0; j < 9; j++) { + let isEditable = numberGrid[i][j] === 0; + let cell = getCell(i, j, numberGrid[i][j], isEditable); + row.push(cell); + } + sudokuGrid.push(row); + } + + return sudokuGrid; +}; + +export default createSudokuGrid; diff --git a/src/Utils/getHint.js b/src/Utils/getHint.js new file mode 100644 index 00000000..37595d54 --- /dev/null +++ b/src/Utils/getHint.js @@ -0,0 +1,39 @@ +import arrayDeepCopy from "./arrayDeepCopy"; +import solveSudoku from "./solveSudoku"; + +const getHint = (board) => { + let solvedBoard = arrayDeepCopy(board); + let solvedStatus = solveSudoku(solvedBoard); + + // If no solution is found + if (solvedStatus === false) { + return { board: null, solvedStatus: false }; + } + + // If solution is found + // Find all empty cells from the orginal given board + let emptyCellPositionList = []; + for (let i = 0; i < 9; i++) { + for (let j = 0; j < 9; j++) { + if (board[i][j].value === 0) { + emptyCellPositionList.push([i, j]); + } + } + } + + // Select random element from the empty cells list + const randomIndex = Math.floor(Math.random() * emptyCellPositionList.length); + let row = emptyCellPositionList[randomIndex][0]; + let col = emptyCellPositionList[randomIndex][1]; + + // Create new board from the data + // Make new cell and replace the empty value with the hint + let result = arrayDeepCopy(board); + result[row][col].value = solvedBoard[row][col].value; + result[row][col].isHinted = true; + result[row][col].isEditable = false; + + return { board: result, solvedStatus: true }; +}; + +export default getHint; diff --git a/src/Utils/solveSudoku.js b/src/Utils/solveSudoku.js new file mode 100644 index 00000000..726da45a --- /dev/null +++ b/src/Utils/solveSudoku.js @@ -0,0 +1,43 @@ +const isValidCell = (row, col, value, board) => { + const cellValue = value; + + for (let i = 0; i < 9; i++) { + if (board[row][i].value === cellValue) return false; + } + + for (let i = 0; i < 9; i++) { + if (board[i][col].value === cellValue) return false; + } + + let x0 = Math.floor(row / 3) * 3; + let y0 = Math.floor(col / 3) * 3; + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 3; j++) { + if (board[x0 + i][y0 + j].value === cellValue) return false; + } + } + + return true; +}; + +// Users have option to "give up" if they can't solve the puzzle by clicking the Solve button +const solveSudoku = (board) => { + // console.log(board); + for (let i = 0; i < 9; i++) { + for (let j = 0; j < 9; j++) { + if (board[i][j].value === 0) { + for (let k = 1; k <= 9; k++) { + if (isValidCell(i, j, k, board)) { + board[i][j].value = k; + if (solveSudoku(board)) return true; + board[i][j].value = 0; + } + } + return false; + } + } + } + return true; +}; + +export default solveSudoku; From 012477fd90f9f6531d82b854a68f9d184a06825c Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:29:32 +0800 Subject: [PATCH 02/22] Add styles to components --- src/App.css | 458 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 450 insertions(+), 8 deletions(-) diff --git a/src/App.css b/src/App.css index 97b7c578..c3e9d270 100644 --- a/src/App.css +++ b/src/App.css @@ -1,19 +1,461 @@ +*, +*:before, +*:after { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: "Montserrat", sans-serif; +} + .App { text-align: center; + height: 100vh; + color: #5d97b9; + overflow: hidden; +} + +#accent { + color: #141c3a; +} + +.game-ctn { + position: relative; + height: 100%; + min-width: 600px; + margin: 0 auto; + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + font-size: 24px; +} + +.info-modal-ctn, +.gameoutcome-ctn, +.nosolutionmodal-ctn, +.difficultymodal-ctn { + position: fixed; + display: flex; + justify-content: center; + align-items: center; + top: 0; + right: 0; + left: 0; + bottom: 0; + padding: 1rem; + background: rgba(0, 0, 0, 0.7); + z-index: 9999; + opacity: 1; + animation: show 0.5s ease; + overflow-x: hidden; + overflow-y: auto; +} + +"@keyframes show": { + "0%": { + display: "none"; + opacity: 0; + } + , + "1%": { + display: "flex"; + opacity: 0; + } + , + "100%": { + opacity: 1; + } +} + +.modal-ctn { + border-radius: 10px; + background: white; + box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px; + padding: 1rem; + position: relative; +} + +@media (min-width: 576px) { + .modal-ctn { + width: 32rem; + } + .choiceboard-ctn { + width: 32rem; + overflow: visible; + } +} + +.modal-title { + text-align: center; + margin-top: 10px; +} + +.modal-close-btn-ctn button { + position: absolute; + z-index: 1; + top: 0; + right: 0; + background: transparent; + width: 2.5rem; + height: 2.5rem; + border: none; + font-size: 24px; + cursor: pointer; + padding: 0; + outline: 0; + color: lightgrey; + box-shadow: 0, 0, 0.625rem, rgba(0, 0, 0, 0.1); +} + +.modal-close-btn-ctn button:hover { + transition: 0.3s; + color: #141c3a; + font-weight: bold; + filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4)); + cursor: pointer; +} + +#stats-title { + margin: 0 20px; +} + +.modal-body { + display: flex; + justify-content: center; + align-items: center; + text-align: center; + gap: 20px; + margin-top: 10px; +} + +.modal-body p { + margin-top: 10px; + font-size: 20px; +} + +.modal-body p:last-of-type { + margin-bottom: 16px; } -.App-logo { - height: 40vmin; - pointer-events: none; +#sudoku-rules { + margin-top: 10px; + display: flex; + flex-direction: column; + font-size: 16px; + justify-content: center; + align-items: center; +} + +#sudoku-rules p { + padding: 0; + margin: 10px 0 0 0; +} + +.links a { + text-decoration: underline; + color: #3c3661; + font-size: 18px; + padding: 5px; +} + +a:hover { + text-decoration: none; + transition: 0.3s; + background-color: #ffc809; + filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4)); + cursor: pointer; } -.App-header { - background-color: #282c34; - min-height: 100vh; +.header-ctn { + display: flex; + justify-content: center; + align-items: center; +} + +h1:hover { + cursor: pointer; +} + +.main-title { + font-family: "Montserrat", sans-serif; + font-weight: bold; + font-size: 60px; +} + +.grid-ctn { display: flex; flex-direction: column; + padding: 0; +} + +table.grid-table { + width: 500px; + height: 100%; + margin: 0 auto; + border-collapse: collapse; + display: flex; + justify-content: center; + align-items: center; +} + +.rows-ctn { + display: flex; + flex-direction: column; +} + +tr.row { + width: 560px; + margin: 0 auto; +} + +td.cell { + display: flex; align-items: center; justify-content: center; - font-size: calc(10px + 2vmin); - color: white; + border: 1px solid #027da2; + width: 62px; + height: 60px; + text-align: center; + user-select: none; + font-weight: bold; + background: white; +} + +td.right-border { + border-right: 3px solid #027da2; +} + +td.bottom-border { + border-bottom: 3px solid #027da2; +} + +td.cell-editable { + cursor: pointer; + color: #141c3a; + background: #dadada; +} + +td.cell-editable:hover { + background-color: #bbdf32; +} + +td.cell-filled { + background: white; +} + +td.cell-invalid { + background-color: #fbd2d8; + animation-name: invalidAnimation; + animation-duration: 2s; + animation-timing-function: ease-out; +} + +@keyframes invalidAnimation { + from { + background-color: #ffa8b5; + } + to { + background-color: #fbd2d8; + } +} + +td.cell-hinted { + color: #c62368; /* Maybe #a0b147 */ + animation-name: hintAnimation; + animation-duration: 2s; + animation-timing-function: ease-out; +} + +@keyframes hintAnimation { + from { + background-color: #ffc809; + } + to { + background-color: initial; + } +} + +.choiceboard-ctn { + display: flex; + justify-content: space-around; + align-items: center; + max-height: fit-content; +} + +.choice-ctn { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + gap: 30px; +} + +.choice { + display: flex; + justify-content: center; + align-items: center; + font-weight: 500; + margin: 5px; + cursor: pointer; +} + +.eraser-ctn { + padding: 0; + margin-bottom: 16px; +} + +.eraser-icon { + color: #c62368; + padding: 3px; + border-radius: 50%; +} + +.eraser-icon:hover { + background: #bbdf32; + color: #141c3a; + padding: 3px; + border-radius: 50%; +} + +.choice:hover { + transition: 0.3s; + font-weight: bold; + filter: drop-shadow(3px 5px 2px rgba(0, 0, 0, 0.4)); + cursor: pointer; + transform: translateY(-5px); +} + +.selected, +.selected-eraser, +.selected p { + color: #ff4e00; + font-weight: 900; + filter: drop-shadow(3px 5px 2px #dadada); +} + +.choice-text { + display: flex; + align-items: center; + color: #027da2; +} + +.noSelect:focus { + outline: none; +} + +.action-ctn { + width: 40%; + display: flex; + flex-wrap: nowrap; + justify-content: space-between; + align-items: center; + gap: 10px; + margin: 10px; +} + +.left-action-ctn { + display: flex; + justify-content: flex-start; + align-items: center; +} + +.right-action-ctn { + display: flex; + justify-content: flex-end; + align-items: center; +} + +.easy, +.medium, +.hard { + font-weight: 400; + border-radius: 10px; + cursor: pointer; + transition: transform 0.3s ease; + padding: 10px 20px; + font-size: 30px; +} + +.easy:hover { + color: #a0b147; + font-weight: bold; + transform: translateY(-5px); +} + +.medium:hover { + color: #f78854; + font-weight: bold; + transform: translateY(-5px); +} + +.hard:hover { + color: #c62368; + font-weight: bold; + transform: translateY(-5px); +} + +/* Button colors and styles */ +/* .btn-primary { + background: #ffc809; + color: #3c3661; + border: none; +} */ + +.btn-hint, +.btn-solve, +.btn-newgame, +.btn-clear { + display: flex; + justify-content: flex-start; +} + +.btn, +.btn-hint, +.btn-clear, +.btn-solve, +.btn-newgame, +.btn-info { + font-family: "Montserrat", sans-serif; + font-weight: 400; + border-radius: 10px; + cursor: pointer; + transition: transform 0.3s ease; + padding: 10px 30px; + font-size: 18px; +} + +.btn-info { + padding-right: 0; +} + +.btn-info { + display: flex; + justify-content: flex-end; + margin: 10px 20px; + background-color: transparent; + border: none; + font-size: 30px; + font-weight: lighter; + cursor: pointer; +} + +.btn:hover, +.btn-hint:hover, +.btn-clear:hover, +.btn-solve:hover, +.btn-newgame:hover, +.btn-info:hover { + transform: translateY(-5px); + filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4)); + color: #027da2; + transition: 0.3s; +} + +.solve-icon:hover, +.hint-icon:hover, +.clear-icon:hover, +.newgame-icon:hover, +.info-icon:hover { + color: #c62368; } From f512bbcdbced9b5218ec377b2ebc2d3c195f09f7 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:30:41 +0800 Subject: [PATCH 03/22] Import Game.js --- src/App.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/App.js b/src/App.js index 4a6f800f..298546e9 100644 --- a/src/App.js +++ b/src/App.js @@ -1,17 +1,12 @@ import React from "react"; -import logo from "./logo.png"; import "./App.css"; +import Game from "./Components/Game"; class App extends React.Component { render() { return (
-
- logo -

- Edit src/App.js and save to reload. -

-
+
); } From a1f7b5430cba09704189d2904cf02a06142ea6e1 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:32:27 +0800 Subject: [PATCH 04/22] Add function to check for incorrect inputs --- src/Utils/checkBoard.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Utils/checkBoard.js b/src/Utils/checkBoard.js index c9f17f97..0277f0d5 100644 --- a/src/Utils/checkBoard.js +++ b/src/Utils/checkBoard.js @@ -9,7 +9,7 @@ const getWrongLines = (board, type) => { for (let j = 0; j < 9; j++) { let key; if (type === "horizontal") key = board[i][j].value; - else key = board[j][i].value; + else if (type === "vertical") key = board[j][i].value; if (key === 0) continue; @@ -76,7 +76,7 @@ const getWrongSquares = (board) => { return wrongSquares; }; -// Numbers squares from 0-8 +// Number squares from 0-8 const getSquareNumber = (x, y) => { let x0 = Math.floor(x / 3); let y0 = Math.floor(y / 3); @@ -94,8 +94,8 @@ const checkBoard = (board) => { let wrongVertical = getWrongLines(board, "vertical"); let wrongSquares = getWrongSquares(board); - console.log(getSquareNumber(1, 5)); - console.log(wrongSquares); + // console.log(getSquareNumber(1, 5)); + // console.log(wrongSquares); for (let i = 0; i < 9; i++) { for (let j = 0; j < 9; j++) { From e5ad77c2c5847f6d72057cf8fec457f42fb577f3 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:33:54 +0800 Subject: [PATCH 05/22] Add component for buttons --- src/Components/Button.js | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/Components/Button.js diff --git a/src/Components/Button.js b/src/Components/Button.js new file mode 100644 index 00000000..1e376826 --- /dev/null +++ b/src/Components/Button.js @@ -0,0 +1,49 @@ +import React from "react"; +import { Check2 } from "react-bootstrap-icons"; +import { Lightbulb } from "react-bootstrap-icons"; +import { Trash3 } from "react-bootstrap-icons"; +import { PlusCircle } from "react-bootstrap-icons"; +import { ArrowCounterclockwise } from "react-bootstrap-icons"; + +class Button extends React.Component { + render() { + const { text, type, onClickAction, buttonStyle } = this.props; + + const styles = [ + "btn-primary", + "btn-hint", + "btn-solve", + "btn-newgame", + "btn-clear", + "btn-undo", + ]; + + const checkButtonStyle = styles.includes(buttonStyle) + ? buttonStyle + : styles[0]; + + return ( + + ); + } +} + +export default Button; From e2751db67e550b579d1e199dd872e257dda683bd Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:34:50 +0800 Subject: [PATCH 06/22] Add Cell component --- src/Components/Cell.js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/Components/Cell.js diff --git a/src/Components/Cell.js b/src/Components/Cell.js new file mode 100644 index 00000000..89686a9e --- /dev/null +++ b/src/Components/Cell.js @@ -0,0 +1,33 @@ +import React from "react"; + +class Cell extends React.Component { + getCellClassName = () => { + const { cell } = this.props; + let { row, column } = cell; + let className = `cell + ${row === 2 || row === 5 ? "bottom-border" : ""} + ${column === 2 || column === 5 ? "right-border" : ""} + ${cell.isValid ? "" : "cell-invalid"} + ${cell.isEditable ? "cell-editable" : ""} + ${cell.isHinted ? "cell-hinted" : ""} + ${cell.isEditable && cell.value !== 0 ? "cell-filled" : ""} + `; + return className; + }; + + render() { + const { cell, handleClickCallback } = this.props; + return ( + + handleClickCallback(cell.row, cell.column, cell.isEditable) + } + > + {cell.value !== 0 ? cell.value : ""} + + ); + } +} + +export default Cell; From 8bf266b6fbe18569fe9f34643b7a5aae749bb761 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:35:23 +0800 Subject: [PATCH 07/22] Add modal to choose difficulty level --- src/Components/DifficultyModal.js | 51 +++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/Components/DifficultyModal.js diff --git a/src/Components/DifficultyModal.js b/src/Components/DifficultyModal.js new file mode 100644 index 00000000..de883281 --- /dev/null +++ b/src/Components/DifficultyModal.js @@ -0,0 +1,51 @@ +import React from "react"; + +class DifficultyModal extends React.Component { + render() { + const { + closeModal, + handleNewGame, + easyMaxEmptyCells, + mediumMaxEmptyCells, + hardMaxEmptyCells, + } = this.props; + return ( +
+
+
+ +
+
+

Select your difficulty level

+
+
+
+
handleNewGame(easyMaxEmptyCells)} + > +

Easy

+
+ +
handleNewGame(mediumMaxEmptyCells)} + > +

Medium

+
+ +
handleNewGame(hardMaxEmptyCells)} + > +

Hard

+
+
+
+
+
+ ); + } +} + +export default DifficultyModal; From a8114c7488c0dcf269d9e456e4a7b0ce3ad11a50 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:36:20 +0800 Subject: [PATCH 08/22] Add modal to keep track of game stats --- src/Components/GameOutcome.js | 62 +++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/Components/GameOutcome.js diff --git a/src/Components/GameOutcome.js b/src/Components/GameOutcome.js new file mode 100644 index 00000000..45c947fe --- /dev/null +++ b/src/Components/GameOutcome.js @@ -0,0 +1,62 @@ +import React from "react"; +import { TrophyFill } from "react-bootstrap-icons"; + +class GameOutcome extends React.Component { + render() { + const { + closeModal, + movesTaken, + hintsTaken, + mistakesMade, + hasPlayerWon, + clickSolve, + gameMode, + mediumMaxEmptyCells, + hardMaxEmptyCells, + } = this.props; + + let gameModeName = "Easy"; + if (gameMode === mediumMaxEmptyCells) gameModeName = "Medium"; + else if (gameMode === hardMaxEmptyCells) gameModeName = "Hard"; + + return ( +
+
+
+ +
+
+ {movesTaken === 0 && ""} + {movesTaken > 0 && !hasPlayerWon && !clickSolve && ( +

You can do it!

+ )} + {clickSolve &&

Better luck next time.

} + {hasPlayerWon && !clickSolve &&

Genius! You did it!

} +
+

+ + Your Stats + +

+
+
+

+ Difficulty: {gameModeName} +

+

+ Moves: {movesTaken} +

+

+ Mistakes: {mistakesMade} +

+

+ Hints: {hintsTaken} +

+
+
+
+ ); + } +} + +export default GameOutcome; From cceb87e20396c6460fd5b95c5a1d6d0bba524c28 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:37:22 +0800 Subject: [PATCH 09/22] Add component as parent of Cell.js to create grid --- src/Components/Grid.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/Components/Grid.js diff --git a/src/Components/Grid.js b/src/Components/Grid.js new file mode 100644 index 00000000..d0b9e59b --- /dev/null +++ b/src/Components/Grid.js @@ -0,0 +1,34 @@ +import React from "react"; +import Cell from "./Cell"; + +class Grid extends React.Component { + render() { + const { grid, handleCellClick } = this.props; + return ( + + + {grid && + grid.map((row, rowIndex) => { + return ( +
+
+ {row.map((cell, columnIndex) => { + return ( + + ); + })} + + + ); + })} + +
+ ); + } +} + +export default Grid; From 3c3528fbdc1cea277ec1e172644aedca009ef390 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:38:00 +0800 Subject: [PATCH 10/22] Add modal to explain game rules --- src/Components/InformationModal.js | 39 ++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/Components/InformationModal.js diff --git a/src/Components/InformationModal.js b/src/Components/InformationModal.js new file mode 100644 index 00000000..ea6378ed --- /dev/null +++ b/src/Components/InformationModal.js @@ -0,0 +1,39 @@ +import React from "react"; + +class InformationModal extends React.Component { + render() { + const { closeModal } = this.props; + return ( +
+
+
+ +
+
+

How to Play Sudoku

+
+
+

+ A Sudoku board consists of 9 rows, 9 columns and 9 squares. All + you need to do is place the numbers 1 to 9 on the grid without + repeating the same number on the same row, column, or square. + That's it! +

+

For further information, check out:

+

+ + Official Sudoku rules + +

+
+
+
+ ); + } +} + +export default InformationModal; From a64d32720c9c0b7dda51493b8ab8390b5eba9241 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:42:25 +0800 Subject: [PATCH 11/22] Add modal to alert when board can't be solved --- src/Components/NoSolutionModal.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/Components/NoSolutionModal.js diff --git a/src/Components/NoSolutionModal.js b/src/Components/NoSolutionModal.js new file mode 100644 index 00000000..fd309b57 --- /dev/null +++ b/src/Components/NoSolutionModal.js @@ -0,0 +1,27 @@ +import React from "react"; + +class NoSolutionModal extends React.Component { + render() { + const { closeModal } = this.props; + return ( +
+
+
+ +
+
+

No Solution Found

+
+
+

+ Uh-oh! The current grid has no solution. Please select New Game to + load a new board. +

+
+
+
+ ); + } +} + +export default NoSolutionModal; From 05ee4b785661483118b66064457a9d9827eb1448 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:43:31 +0800 Subject: [PATCH 12/22] Add component for number buttons and erase button --- src/Components/NumberBar.js | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/Components/NumberBar.js diff --git a/src/Components/NumberBar.js b/src/Components/NumberBar.js new file mode 100644 index 00000000..2ec0ce9c --- /dev/null +++ b/src/Components/NumberBar.js @@ -0,0 +1,38 @@ +import React from "react"; +import { Eraser } from "react-bootstrap-icons"; + +const numberRow = [1, 2, 3, 4, 5, 6, 7, 8, 9]; + +const NumberBar = ({ setClickValue, selected }) => { + return ( +
+
+ {numberRow.map((choice) => { + let selectedClass = choice === selected ? "selected" : ""; + return ( +
setClickValue(choice)} + > +

{choice}

+
+ ); + })} +
setClickValue(0)} + > + + + +
+
+
+ ); +}; + +export default NumberBar; From 4537b95248cc8a379b2e75401bc63c0b55fbf7de Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:44:32 +0800 Subject: [PATCH 13/22] Add hook to use local storage --- src/Hooks/useLocalStorage.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/Hooks/useLocalStorage.js diff --git a/src/Hooks/useLocalStorage.js b/src/Hooks/useLocalStorage.js new file mode 100644 index 00000000..730628f6 --- /dev/null +++ b/src/Hooks/useLocalStorage.js @@ -0,0 +1,26 @@ +import { useState, useEffect } from "react"; + +const getSavedValue = (key, initialValue) => { + const savedValue = JSON.parse(localStorage.getItem(key)); + + if (savedValue) return savedValue; + + console.log("Saved value"); + if (initialValue instanceof Function) return initialValue(); + + return initialValue; +}; + +const useLocalStorage = (key, initialValue) => { + const [value, setValue] = useState(() => { + return getSavedValue(key, initialValue); + }); + + useEffect(() => { + localStorage.setItem(key, JSON.stringify(value)); + }, [key, value]); + + return [value, setValue]; +}; + +export default useLocalStorage; From a5eb39624dee213f739653c89a44e733a3d24c90 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:45:21 +0800 Subject: [PATCH 14/22] Add main Game component that manages state --- src/Components/Game.js | 244 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 src/Components/Game.js diff --git a/src/Components/Game.js b/src/Components/Game.js new file mode 100644 index 00000000..2bcf2391 --- /dev/null +++ b/src/Components/Game.js @@ -0,0 +1,244 @@ +import React, { useState } from "react"; +import useLocalStorage from "../Hooks/useLocalStorage"; + +import arrayDeepCopy from "../Utils/arrayDeepCopy"; +import getHint from "../Utils/getHint"; +import solveSudoku from "../Utils/solveSudoku"; +import createSudokuGrid from "../Utils/createSudokuGrid"; +import checkWin from "../Utils/checkWin"; +import checkBoard from "../Utils/checkBoard"; + +import NumberBar from "./NumberBar"; +import Button from "./Button"; +import DifficultyModal from "./DifficultyModal"; +import GameOutcome from "./GameOutcome"; +import Grid from "./Grid"; +import InformationModal from "./InformationModal"; +import NoSolutionModal from "./NoSolutionModal"; + +import { Trophy } from "react-bootstrap-icons"; + +const easyMaxEmptyCells = 30; +const mediumMaxEmptyCells = 40; +const hardMaxEmptyCells = 50; + +const Game = () => { + const [grid, setGrid] = useLocalStorage("currentGrid", null); + const [startingGrid, setStartingGrid] = useLocalStorage("startingGrid", null); + const [clickValue, setClickValue] = useLocalStorage("clickValue", 1); + + // Game Score logic + const [gameMode, setGameMode] = useLocalStorage( + "gameMode", + mediumMaxEmptyCells + ); + const [movesTaken, setMovesTaken] = useLocalStorage("movesTaken", 0); + const [hintsTaken, setHintsTaken] = useLocalStorage("hintsTaken", 0); + const [mistakesMade, setMistakesMade] = useLocalStorage("mistakesMade", 0); + const [hasPlayerWon, setHasPlayerWon] = useLocalStorage("playerWon", false); + const [clickSolve, setClickSolve] = useLocalStorage("clickSolve", false); + + // Logic for modal + const [showInformationModal, setShowInformationModal] = useState(false); + const [showNoSolutionModal, setShowNoSolutionModal] = useState(false); + const [showGameOutcome, setShowGameOutcome] = useState(false); + const [showDifficultyModal, setShowDifficultyModal] = useState(false); + + const handleSolve = () => { + let solvedBoard = arrayDeepCopy(grid); + let solvedStatus = solveSudoku(solvedBoard); + if (solvedStatus === false) { + showNoSolutionModal((show) => !show); + return; + } + + let newHints = 0; + for (let i = 0; i < 9; i++) { + for (let j = 0; j < 9; j++) { + if (grid[i][j].value === 0) { + newHints++; + solvedBoard[i][j].isHinted = true; + solvedBoard[i][j].isEditable = false; + } + } + } + + setHintsTaken((hints) => hints + newHints); + setHasPlayerWon(false); + setShowGameOutcome(true); + setClickSolve(true); + setGrid(solvedBoard); + }; + + const handleHint = () => { + // Check if player has won + if (hasPlayerWon) return; + + // Get hint + let hintResponse = getHint(grid); + + // Check if the grid cannot be solved + if (hintResponse.solvedStatus === false) { + setShowNoSolutionModal((show) => !show); + return; + } + + // Set the result board + setGrid(hintResponse.board); + + // Increment number of hints taken + setHintsTaken((hints) => hints + 1); + + // Check if the player has won + let playerWon = checkWin(hintResponse.board); + if (playerWon) { + setHasPlayerWon(true); + setShowGameOutcome(true); + } + }; + + const handleNewGame = (maxEmptyCellsCount) => { + // Wait for the function to return the grid + let newSudokuGrid = createSudokuGrid(maxEmptyCellsCount); + + setStartingGrid(arrayDeepCopy(newSudokuGrid)); + setGrid(arrayDeepCopy(newSudokuGrid)); + + // Set the game mode with maxEmptyCellsCount + setGameMode(maxEmptyCellsCount); + + // Reset the values + setMovesTaken(0); + setHintsTaken(0); + setMistakesMade(0); + setHasPlayerWon(false); + setClickSolve(false); + + // Close the difficulty modal + setShowDifficultyModal((show) => !show); + }; + + const handleClearBoard = () => { + setHasPlayerWon(false); + setGrid(arrayDeepCopy(startingGrid)); + }; + + const handleCellClick = (row, column, isEditable) => { + if (!isEditable) return; + + // moves registered when the value is not 0 + if (clickValue !== 0) { + setMovesTaken((moves) => moves + 1); + } + + // Count mistakes made + if (!clickValue.isValid) setMistakesMade((mistakes) => mistakes + 1); + + let newGrid = arrayDeepCopy(grid); + newGrid[row][column].value = clickValue; + + // Marking the cell valid or invalid depending on the grid + checkBoard(newGrid); + + // Checking if the player has won + let playerWon = checkWin(newGrid); + if (playerWon) { + setHasPlayerWon(true); + setShowGameOutcome(true); + } + + // setting the value to the grid and also to the local storage + setGrid(newGrid); + }; + + console.log("...."); + + // If we do not have anything in the local storage + if (grid == null && startingGrid == null) handleNewGame(gameMode); + + return ( +
+
+

setShowInformationModal((show) => !show)} + className="main-title" + > + SUDOKU +

+
+ {showInformationModal && ( + setShowInformationModal((show) => !show)} + /> + )} + + {showNoSolutionModal && ( + setShowNoSolutionModal((show) => !show)} + /> + )} + + {showDifficultyModal && ( + setShowDifficultyModal((show) => !show)} + handleNewGame={handleNewGame} + easyMaxEmptyCells={easyMaxEmptyCells} + mediumMaxEmptyCells={mediumMaxEmptyCells} + hardMaxEmptyCells={hardMaxEmptyCells} + /> + )} + + {showGameOutcome && ( + setShowGameOutcome((show) => !show)} + movesTaken={movesTaken} + hintsTaken={hintsTaken} + mistakesMade={mistakesMade} + hasPlayerWon={hasPlayerWon} + clickSolve={clickSolve} + gameMode={gameMode} + mediumMaxEmptyCells={mediumMaxEmptyCells} + hardMaxEmptyCells={hardMaxEmptyCells} + /> + )} +
+
+ + + + +
+
+ +
+
+
+ +
+ +
+ ); +}; + +export default Game; From 8d790a9cbffff90bb6111a01381bd6ef71ed71ab Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:47:18 +0800 Subject: [PATCH 15/22] Add Google fonts and change title element --- public/index.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index bd669818..1992bd94 100644 --- a/public/index.html +++ b/public/index.html @@ -24,7 +24,14 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - Rocket Bootcamp Project + + + + + Play Sudoku From 4c1eb6a5557b20c239de5153c4bbe81a92320cdc Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:48:07 +0800 Subject: [PATCH 16/22] Import bootstrap-icons --- src/index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.js b/src/index.js index 31508db1..422ae0b2 100644 --- a/src/index.js +++ b/src/index.js @@ -2,6 +2,8 @@ import React from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; +import "bootstrap/dist/css/bootstrap.min.css"; +import "bootstrap-icons/font/bootstrap-icons.css"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( From 615d17598c08dca32895924b9690511814f0f7b5 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:48:53 +0800 Subject: [PATCH 17/22] Install bootstrap --- package-lock.json | 1259 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 11 +- 2 files changed, 1254 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index c205fc57..d3915627 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,18 @@ "name": "project1-bootcamp", "version": "0.1.0", "dependencies": { + "@emotion/react": "^11.10.6", + "@emotion/styled": "^11.10.6", + "@mui/icons-material": "^5.11.16", + "@mui/material": "^5.11.16", + "bootstrap": "^5.2.3", + "bootstrap-icons": "^1.10.4", "react": "^18.1.0", + "react-bootstrap": "^2.7.2", + "react-bootstrap-icons": "^1.10.3", "react-dom": "^18.1.0", - "react-scripts": "5.0.1" + "react-scripts": "5.0.1", + "reactjs-popup": "^2.0.5" } }, "node_modules/@ampproject/remapping": { @@ -1764,11 +1773,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" @@ -1997,6 +2006,158 @@ "postcss": "^8.3" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", + "integrity": "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/serialize": "^1.1.1", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.1.3" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.10.7", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.7.tgz", + "integrity": "sha512-VLl1/2D6LOjH57Y8Vem1RoZ9haWF4jesHDGiHtKozDQuBIkJm2gimVo0I02sWCuzZtVACeixTVB4jeE8qvCBoQ==", + "dependencies": { + "@emotion/memoize": "^0.8.0", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "stylis": "4.1.3" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", + "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "dependencies": { + "@emotion/memoize": "^0.8.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "node_modules/@emotion/react": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz", + "integrity": "sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", + "dependencies": { + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/unitless": "^0.8.0", + "@emotion/utils": "^1.2.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" + }, + "node_modules/@emotion/styled": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz", + "integrity": "sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/is-prop-valid": "^1.2.0", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", + "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + }, "node_modules/@eslint/eslintrc": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz", @@ -2785,6 +2946,262 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz", "integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==" }, + "node_modules/@mui/base": { + "version": "5.0.0-alpha.124", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.124.tgz", + "integrity": "sha512-I6M+FrjRCybQCr8I8JTu6L2MkUobSQFgNIpOJyDNKL5zq/73LvZIQXvsKumAzthVGvI1PYaarM9vGDrDYbumKA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@emotion/is-prop-valid": "^1.2.0", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "@popperjs/core": "^2.11.7", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/base/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.16.tgz", + "integrity": "sha512-GxRfZ/HquQ/1nUc9qQVGReP6oOMS8/3QjPJ+23a7TMrxl2wjlmXrMNn7tRa30vZcGcDgEG+J0aseefUN0AoawQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.16.tgz", + "integrity": "sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.16.tgz", + "integrity": "sha512-++glQqbZ3rMzOWB77yOvqRG+k8+scYTUKVWZpWff+GWsf6L10g9L2wgRhhAS8bDLuxCbXZlPNbSZowXDDw6z6Q==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@mui/base": "5.0.0-alpha.124", + "@mui/core-downloads-tracker": "^5.11.16", + "@mui/system": "^5.11.16", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "@types/react-transition-group": "^4.4.5", + "clsx": "^1.2.1", + "csstype": "^3.1.2", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/@mui/private-theming": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.13.tgz", + "integrity": "sha512-PJnYNKzW5LIx3R+Zsp6WZVPs6w5sEKJ7mgLNnUXuYB1zo5aX71FVLtV7geyPXRcaN2tsoRNK7h444ED0t7cIjA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@mui/utils": "^5.11.13", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.16.tgz", + "integrity": "sha512-8dJRR/LqtGGaZN21p1vU9euwrKERlgtQIWyuzBKZ8/cuSlW5rIzlp46liP+Uh0+7d9NcHU0H4hBMoPt3ax64PA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@emotion/cache": "^11.10.5", + "csstype": "^3.1.2", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.16.tgz", + "integrity": "sha512-JY7CNm7ik2Gr4kQpz1+C9N/f4ET3QjVBo/iaHcmlSOgjdxnOzFbv+vCdb1DMzBGew+UbqckppZpZwbgbrBE2Rw==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@mui/private-theming": "^5.11.13", + "@mui/styled-engine": "^5.11.16", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "clsx": "^1.2.1", + "csstype": "^3.1.2", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.3.tgz", + "integrity": "sha512-tZ+CQggbe9Ol7e/Fs5RcKwg/woU+o8DCtOnccX6KmbBc7YrfqMYEYuaIcXHuhpT880QwNkZZ3wQwvtlDFA2yOw==", + "peerDependencies": { + "@types/react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.13.tgz", + "integrity": "sha512-5ltA58MM9euOuUcnvwFJqpLdEugc9XFsRR8Gt4zZNb31XzMfSKJPR4eumulyhsOTK1rWf7K4D63NKFPfX0AxqA==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@types/prop-types": "^15.7.5", + "@types/react-is": "^16.7.1 || ^17.0.0", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0" + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2866,6 +3283,68 @@ } } }, + "node_modules/@popperjs/core": { + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz", + "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz", + "integrity": "sha512-OFiYQdv+Yk7AO7IsQu/fAEPijbeTwrrEYvdNoJ3sblBBedD5j5fBTNWrUPNVlwC4XWWnWTCMaRIVsJujsFiWXg==", + "dependencies": { + "@swc/helpers": "^0.4.14" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" + } + }, + "node_modules/@restart/hooks": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz", + "integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==", + "dependencies": { + "dequal": "^2.0.2" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@restart/ui": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.2.tgz", + "integrity": "sha512-hcYs8PwpmHEtwjihLVn2Jr89yrYajfhxN5HtTq3HA9U3+feg1SC3swBM8/qibMTCFsXWToEEtzJMV+LWE+Qjpg==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.4.9", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.0", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + } + }, + "node_modules/@restart/ui/node_modules/uncontrollable": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.0.tgz", + "integrity": "sha512-a954G/0JyXoZdpt0YIzTfoQyWtRS1VvygOBsHttCtZL8jDTKd6vQlUo811y46XnWoXIqQ36QKi3cSEdPuFADkA==", + "dependencies": { + "@types/react": ">=18.0.28" + }, + "peerDependencies": { + "react": ">=17.0.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -3184,6 +3663,14 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -3387,6 +3874,11 @@ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==" }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, "node_modules/@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -3402,6 +3894,32 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, + "node_modules/@types/react": { + "version": "18.0.34", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.34.tgz", + "integrity": "sha512-NO1UO8941541CJl1BeOXi8a9dNKFK09Gnru5ZJqkm4Q3/WoQJtHvmwt0VX0SB9YCEwe7TfSSxDuaNmx6H2BAIQ==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-is": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", + "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -3415,6 +3933,11 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, + "node_modules/@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, "node_modules/@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -3450,6 +3973,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, + "node_modules/@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, "node_modules/@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -4635,6 +5163,29 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, + "node_modules/bootstrap": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", + "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.6" + } + }, + "node_modules/bootstrap-icons": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.10.4.tgz", + "integrity": "sha512-eI3HyIUmpGKRiRv15FCZccV+2sreGE2NnmH8mtxV/nPOzQVu0sPEj8HhF1MwjJ31IhjF0rgMvtYOX5VqIzcb/A==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4891,6 +5442,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/clean-css": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", @@ -4920,6 +5476,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -5586,6 +6150,11 @@ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -5698,6 +6267,14 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -5829,6 +6406,15 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -7138,6 +7724,11 @@ "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -7705,6 +8296,19 @@ "he": "bin/he" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -8057,6 +8661,14 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -12790,6 +13402,23 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "dependencies": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/prop-types-extra/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -12965,6 +13594,46 @@ "node": ">=14" } }, + "node_modules/react-bootstrap": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.7.2.tgz", + "integrity": "sha512-WDSln+mG4RLLFO01stkj2bEx/3MF4YihK9D/dWnHaSxOiQZLbhhlf95D2Jb20X3t2m7vMxRe888FVrfLJoGmmA==", + "dependencies": { + "@babel/runtime": "^7.17.2", + "@restart/hooks": "^0.4.6", + "@restart/ui": "^1.4.1", + "@types/react-transition-group": "^4.4.4", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + }, + "peerDependencies": { + "@types/react": ">=16.14.8", + "react": ">=16.14.0", + "react-dom": ">=16.14.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-bootstrap-icons": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/react-bootstrap-icons/-/react-bootstrap-icons-1.10.3.tgz", + "integrity": "sha512-j4hSby6gT9/enhl3ybB1tfr1slZNAYXDVntcRrmVjxB3//2WwqrzpESVqKhyayYVaWpEtnwf9wgUQ03cuziwrw==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": ">=16.8.6" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -13104,6 +13773,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -13184,6 +13858,33 @@ } } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/reactjs-popup": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/reactjs-popup/-/reactjs-popup-2.0.5.tgz", + "integrity": "sha512-b5hv9a6aGsHEHXFAgPO5s1Jw1eSkopueyUVxQewGdLgqk2eW0IVXZrPRpHR629YcgIpC2oxtX8OOZ8a7bQJbxA==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -13247,9 +13948,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regenerator-transform": { "version": "0.15.0", @@ -14246,6 +14947,11 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -14816,6 +15522,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "dependencies": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + }, + "peerDependencies": { + "react": ">=15.0.0" + } + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -14994,6 +15714,14 @@ "makeerror": "1.0.12" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", @@ -17044,11 +17772,11 @@ } }, "@babel/runtime": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", - "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" } }, "@babel/runtime-corejs3": { @@ -17187,6 +17915,132 @@ "integrity": "sha512-T5ZyNSw9G0x0UDFiXV40a7VjKw2b+l4G+S0sctKqxhx8cg9QtMUAGwJBVU9mHPDPoZEmwm0tEoukjl4zb9MU7Q==", "requires": {} }, + "@emotion/babel-plugin": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz", + "integrity": "sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/serialize": "^1.1.1", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.1.3" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + } + } + }, + "@emotion/cache": { + "version": "11.10.7", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.7.tgz", + "integrity": "sha512-VLl1/2D6LOjH57Y8Vem1RoZ9haWF4jesHDGiHtKozDQuBIkJm2gimVo0I02sWCuzZtVACeixTVB4jeE8qvCBoQ==", + "requires": { + "@emotion/memoize": "^0.8.0", + "@emotion/sheet": "^1.2.1", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "stylis": "4.1.3" + } + }, + "@emotion/hash": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", + "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + }, + "@emotion/is-prop-valid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz", + "integrity": "sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==", + "requires": { + "@emotion/memoize": "^0.8.0" + } + }, + "@emotion/memoize": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", + "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" + }, + "@emotion/react": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.6.tgz", + "integrity": "sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/cache": "^11.10.5", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0", + "@emotion/weak-memoize": "^0.3.0", + "hoist-non-react-statics": "^3.3.1" + } + }, + "@emotion/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==", + "requires": { + "@emotion/hash": "^0.9.0", + "@emotion/memoize": "^0.8.0", + "@emotion/unitless": "^0.8.0", + "@emotion/utils": "^1.2.0", + "csstype": "^3.0.2" + } + }, + "@emotion/sheet": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.1.tgz", + "integrity": "sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==" + }, + "@emotion/styled": { + "version": "11.10.6", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.10.6.tgz", + "integrity": "sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.10.6", + "@emotion/is-prop-valid": "^1.2.0", + "@emotion/serialize": "^1.1.1", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", + "@emotion/utils": "^1.2.0" + } + }, + "@emotion/unitless": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", + "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + }, + "@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", + "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "requires": {} + }, + "@emotion/utils": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", + "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + }, + "@emotion/weak-memoize": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", + "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + }, "@eslint/eslintrc": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz", @@ -17771,6 +18625,128 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz", "integrity": "sha512-nkalE/f1RvRGChwBnEIoBfSEYOXnCRdleKuv6+lePbMDrMZXeDQnqak5XDOeBgrPPyPfAdcCu/B5z+v3VhplGg==" }, + "@mui/base": { + "version": "5.0.0-alpha.124", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-alpha.124.tgz", + "integrity": "sha512-I6M+FrjRCybQCr8I8JTu6L2MkUobSQFgNIpOJyDNKL5zq/73LvZIQXvsKumAzthVGvI1PYaarM9vGDrDYbumKA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@emotion/is-prop-valid": "^1.2.0", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "@popperjs/core": "^2.11.7", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "dependencies": { + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + } + } + }, + "@mui/core-downloads-tracker": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.16.tgz", + "integrity": "sha512-GxRfZ/HquQ/1nUc9qQVGReP6oOMS8/3QjPJ+23a7TMrxl2wjlmXrMNn7tRa30vZcGcDgEG+J0aseefUN0AoawQ==" + }, + "@mui/icons-material": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.11.16.tgz", + "integrity": "sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A==", + "requires": { + "@babel/runtime": "^7.21.0" + } + }, + "@mui/material": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.11.16.tgz", + "integrity": "sha512-++glQqbZ3rMzOWB77yOvqRG+k8+scYTUKVWZpWff+GWsf6L10g9L2wgRhhAS8bDLuxCbXZlPNbSZowXDDw6z6Q==", + "requires": { + "@babel/runtime": "^7.21.0", + "@mui/base": "5.0.0-alpha.124", + "@mui/core-downloads-tracker": "^5.11.16", + "@mui/system": "^5.11.16", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "@types/react-transition-group": "^4.4.5", + "clsx": "^1.2.1", + "csstype": "^3.1.2", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" + }, + "dependencies": { + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + } + } + }, + "@mui/private-theming": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.11.13.tgz", + "integrity": "sha512-PJnYNKzW5LIx3R+Zsp6WZVPs6w5sEKJ7mgLNnUXuYB1zo5aX71FVLtV7geyPXRcaN2tsoRNK7h444ED0t7cIjA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@mui/utils": "^5.11.13", + "prop-types": "^15.8.1" + } + }, + "@mui/styled-engine": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.11.16.tgz", + "integrity": "sha512-8dJRR/LqtGGaZN21p1vU9euwrKERlgtQIWyuzBKZ8/cuSlW5rIzlp46liP+Uh0+7d9NcHU0H4hBMoPt3ax64PA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@emotion/cache": "^11.10.5", + "csstype": "^3.1.2", + "prop-types": "^15.8.1" + } + }, + "@mui/system": { + "version": "5.11.16", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.11.16.tgz", + "integrity": "sha512-JY7CNm7ik2Gr4kQpz1+C9N/f4ET3QjVBo/iaHcmlSOgjdxnOzFbv+vCdb1DMzBGew+UbqckppZpZwbgbrBE2Rw==", + "requires": { + "@babel/runtime": "^7.21.0", + "@mui/private-theming": "^5.11.13", + "@mui/styled-engine": "^5.11.16", + "@mui/types": "^7.2.3", + "@mui/utils": "^5.11.13", + "clsx": "^1.2.1", + "csstype": "^3.1.2", + "prop-types": "^15.8.1" + } + }, + "@mui/types": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.3.tgz", + "integrity": "sha512-tZ+CQggbe9Ol7e/Fs5RcKwg/woU+o8DCtOnccX6KmbBc7YrfqMYEYuaIcXHuhpT880QwNkZZ3wQwvtlDFA2yOw==", + "requires": {} + }, + "@mui/utils": { + "version": "5.11.13", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.11.13.tgz", + "integrity": "sha512-5ltA58MM9euOuUcnvwFJqpLdEugc9XFsRR8Gt4zZNb31XzMfSKJPR4eumulyhsOTK1rWf7K4D63NKFPfX0AxqA==", + "requires": { + "@babel/runtime": "^7.21.0", + "@types/prop-types": "^15.7.5", + "@types/react-is": "^16.7.1 || ^17.0.0", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "dependencies": { + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -17810,6 +18786,53 @@ "source-map": "^0.7.3" } }, + "@popperjs/core": { + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz", + "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==" + }, + "@react-aria/ssr": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz", + "integrity": "sha512-OFiYQdv+Yk7AO7IsQu/fAEPijbeTwrrEYvdNoJ3sblBBedD5j5fBTNWrUPNVlwC4XWWnWTCMaRIVsJujsFiWXg==", + "requires": { + "@swc/helpers": "^0.4.14" + } + }, + "@restart/hooks": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz", + "integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==", + "requires": { + "dequal": "^2.0.2" + } + }, + "@restart/ui": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.2.tgz", + "integrity": "sha512-hcYs8PwpmHEtwjihLVn2Jr89yrYajfhxN5HtTq3HA9U3+feg1SC3swBM8/qibMTCFsXWToEEtzJMV+LWE+Qjpg==", + "requires": { + "@babel/runtime": "^7.21.0", + "@popperjs/core": "^2.11.6", + "@react-aria/ssr": "^3.5.0", + "@restart/hooks": "^0.4.9", + "@types/warning": "^3.0.0", + "dequal": "^2.0.3", + "dom-helpers": "^5.2.0", + "uncontrollable": "^8.0.0", + "warning": "^4.0.3" + }, + "dependencies": { + "uncontrollable": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.0.tgz", + "integrity": "sha512-a954G/0JyXoZdpt0YIzTfoQyWtRS1VvygOBsHttCtZL8jDTKd6vQlUo811y46XnWoXIqQ36QKi3cSEdPuFADkA==", + "requires": { + "@types/react": ">=18.0.28" + } + } + } + }, "@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -18004,6 +19027,14 @@ "loader-utils": "^2.0.0" } }, + "@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "requires": { + "tslib": "^2.4.0" + } + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -18201,6 +19232,11 @@ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==" }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, "@types/q": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", @@ -18216,6 +19252,32 @@ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, + "@types/react": { + "version": "18.0.34", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.34.tgz", + "integrity": "sha512-NO1UO8941541CJl1BeOXi8a9dNKFK09Gnru5ZJqkm4Q3/WoQJtHvmwt0VX0SB9YCEwe7TfSSxDuaNmx6H2BAIQ==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-is": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz", + "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==", + "requires": { + "@types/react": "*" + } + }, + "@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "requires": { + "@types/react": "*" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -18229,6 +19291,11 @@ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" }, + "@types/scheduler": { + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" + }, "@types/serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", @@ -18264,6 +19331,11 @@ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" }, + "@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA==" + }, "@types/ws": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", @@ -19142,6 +20214,17 @@ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, + "bootstrap": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz", + "integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==", + "requires": {} + }, + "bootstrap-icons": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.10.4.tgz", + "integrity": "sha512-eI3HyIUmpGKRiRv15FCZccV+2sreGE2NnmH8mtxV/nPOzQVu0sPEj8HhF1MwjJ31IhjF0rgMvtYOX5VqIzcb/A==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -19318,6 +20401,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "clean-css": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", @@ -19343,6 +20431,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -19809,6 +20902,11 @@ } } }, + "csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, "damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -19889,6 +20987,11 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -19990,6 +21093,15 @@ "utila": "~0.4" } }, + "dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -20961,6 +22073,11 @@ "pkg-dir": "^4.1.0" } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -21341,6 +22458,21 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, "hoopy": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", @@ -21600,6 +22732,14 @@ "side-channel": "^1.0.4" } }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -24892,6 +26032,22 @@ } } }, + "prop-types-extra": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz", + "integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==", + "requires": { + "react-is": "^16.3.2", + "warning": "^4.0.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -25009,6 +26165,33 @@ "whatwg-fetch": "^3.6.2" } }, + "react-bootstrap": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.7.2.tgz", + "integrity": "sha512-WDSln+mG4RLLFO01stkj2bEx/3MF4YihK9D/dWnHaSxOiQZLbhhlf95D2Jb20X3t2m7vMxRe888FVrfLJoGmmA==", + "requires": { + "@babel/runtime": "^7.17.2", + "@restart/hooks": "^0.4.6", + "@restart/ui": "^1.4.1", + "@types/react-transition-group": "^4.4.4", + "classnames": "^2.3.1", + "dom-helpers": "^5.2.1", + "invariant": "^2.2.4", + "prop-types": "^15.8.1", + "prop-types-extra": "^1.1.0", + "react-transition-group": "^4.4.2", + "uncontrollable": "^7.2.1", + "warning": "^4.0.3" + } + }, + "react-bootstrap-icons": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/react-bootstrap-icons/-/react-bootstrap-icons-1.10.3.tgz", + "integrity": "sha512-j4hSby6gT9/enhl3ybB1tfr1slZNAYXDVntcRrmVjxB3//2WwqrzpESVqKhyayYVaWpEtnwf9wgUQ03cuziwrw==", + "requires": { + "prop-types": "^15.7.2" + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -25114,6 +26297,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -25174,6 +26362,23 @@ "workbox-webpack-plugin": "^6.4.1" } }, + "react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, + "reactjs-popup": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/reactjs-popup/-/reactjs-popup-2.0.5.tgz", + "integrity": "sha512-b5hv9a6aGsHEHXFAgPO5s1Jw1eSkopueyUVxQewGdLgqk2eW0IVXZrPRpHR629YcgIpC2oxtX8OOZ8a7bQJbxA==", + "requires": {} + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -25224,9 +26429,9 @@ } }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regenerator-transform": { "version": "0.15.0", @@ -25955,6 +27160,11 @@ "postcss-selector-parser": "^6.0.4" } }, + "stylis": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.3.tgz", + "integrity": "sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==" + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -26389,6 +27599,17 @@ "which-boxed-primitive": "^1.0.2" } }, + "uncontrollable": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz", + "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==", + "requires": { + "@babel/runtime": "^7.6.3", + "@types/react": ">=16.9.11", + "invariant": "^2.2.4", + "react-lifecycles-compat": "^3.0.4" + } + }, "unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -26524,6 +27745,14 @@ "makeerror": "1.0.12" } }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "watchpack": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", diff --git a/package.json b/package.json index a100866d..2317274d 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,18 @@ "version": "0.1.0", "private": true, "dependencies": { + "@emotion/react": "^11.10.6", + "@emotion/styled": "^11.10.6", + "@mui/icons-material": "^5.11.16", + "@mui/material": "^5.11.16", + "bootstrap": "^5.2.3", + "bootstrap-icons": "^1.10.4", "react": "^18.1.0", + "react-bootstrap": "^2.7.2", + "react-bootstrap-icons": "^1.10.3", "react-dom": "^18.1.0", - "react-scripts": "5.0.1" + "react-scripts": "5.0.1", + "reactjs-popup": "^2.0.5" }, "scripts": { "start": "react-scripts start", From 02537dd13dc4c8203140457b1b3bb8ccf6ac3525 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 18:58:39 +0800 Subject: [PATCH 18/22] Describe main features of game --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index e273017e..3438fec6 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,25 @@ https://bc.rocketacademy.co/1-frontend/1.p-frontend-app +## Sudoku Game + +Welcome to my Sudoku game! I made this game as part of learning React using HTML, CSS, and JavaScript. State is managed in the Game component, which passes props to the other components. + +Here are the main features of my game: + +1. Choose from three levels: Easy, Medium, and Hard. +2. Add numbers to the board by clicking the number button and then clicking a square on the grid. +3. Entering the wrong number will highlight the square, column, and/or row where the conflict is. +4. Clear the board and start again by clicking the trash icon. +5. Give up? Click the tick icon to solve the board. +6. Stuck? Click the lightbulb icon to get a hint that will populate a random empty cell on the board. +7. Click the plus icon to change difficulty levels and start a new game. +8. The trophy icon holds your game stats - difficulty level, number of moves made, number of mistakes made, and number of hints used. These reset when you start a new game. +9. Click the Sudoku title at the top of the page for instructions on how to play the game. +10. Click the eraser icon to delete an input on the board. + +This game was built for Project 1 of Rocket Academy's Coding Bootcamp. + ## Available Scripts This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). In the project directory, you can run: From d83443a99bacde846b7fdcda3bf08efabd886344 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 19:01:42 +0800 Subject: [PATCH 19/22] Correct syntax errors --- src/App.css | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/App.css b/src/App.css index c3e9d270..e81f80cf 100644 --- a/src/App.css +++ b/src/App.css @@ -52,18 +52,18 @@ overflow-y: auto; } -"@keyframes show": { - "0%": { - display: "none"; +@keyframes show { + 0% { + display: none; opacity: 0; } - , - "1%": { - display: "flex"; + + 1% { + display: flex; opacity: 0; } - , - "100%": { + + 100% { opacity: 1; } } @@ -261,7 +261,7 @@ td.cell-invalid { } td.cell-hinted { - color: #c62368; /* Maybe #a0b147 */ + color: #c62368; animation-name: hintAnimation; animation-duration: 2s; animation-timing-function: ease-out; @@ -395,12 +395,11 @@ td.cell-hinted { transform: translateY(-5px); } -/* Button colors and styles */ -/* .btn-primary { +.btn-primary { background: #ffc809; color: #3c3661; border: none; -} */ +} .btn-hint, .btn-solve, From 79faeb9d2ab29f3fcaa6ef0f5ca97b17dbef5fd2 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Wed, 12 Apr 2023 20:49:06 +0800 Subject: [PATCH 20/22] Deploy to GitHub Pages --- package-lock.json | 337 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 6 + 2 files changed, 343 insertions(+) diff --git a/package-lock.json b/package-lock.json index d3915627..0fa3c8c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,9 @@ "react-dom": "^18.1.0", "react-scripts": "5.0.1", "reactjs-popup": "^2.0.5" + }, + "devDependencies": { + "gh-pages": "^5.0.0" } }, "node_modules/@ampproject/remapping": { @@ -4649,6 +4652,15 @@ "node": ">=8" } }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -6536,6 +6548,12 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.131.tgz", "integrity": "sha512-oi3YPmaP87hiHn0c4ePB67tXaF+ldGhxvZnT19tW9zX6/Ej+pLN0Afja5rQ6S+TND7I9EuwQTT8JYn1k7R7rrw==" }, + "node_modules/email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", + "dev": true + }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -7659,6 +7677,32 @@ "node": ">=10" } }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dev": true, + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -8099,6 +8143,100 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gh-pages": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", + "integrity": "sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==", + "dev": true, + "dependencies": { + "async": "^3.2.4", + "commander": "^2.18.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gh-pages/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/gh-pages/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/gh-pages/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/gh-pages/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gh-pages/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/gh-pages/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -12082,6 +12220,36 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -14917,6 +15085,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -15386,6 +15566,18 @@ "node": ">=8" } }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -19822,6 +20014,12 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true + }, "array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -21192,6 +21390,12 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.131.tgz", "integrity": "sha512-oi3YPmaP87hiHn0c4ePB67tXaF+ldGhxvZnT19tW9zX6/Ej+pLN0Afja5rQ6S+TND7I9EuwQTT8JYn1k7R7rrw==" }, + "email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", + "dev": true + }, "emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -22021,6 +22225,23 @@ } } }, + "filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true + }, + "filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dev": true, + "requires": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + } + }, "filesize": { "version": "8.0.7", "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", @@ -22319,6 +22540,83 @@ "get-intrinsic": "^1.1.1" } }, + "gh-pages": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", + "integrity": "sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==", + "dev": true, + "requires": { + "async": "^3.2.4", + "commander": "^2.18.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^8.1.0", + "globby": "^6.1.0" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -25208,6 +25506,27 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -27145,6 +27464,15 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", @@ -27496,6 +27824,15 @@ "punycode": "^2.1.1" } }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", diff --git a/package.json b/package.json index 2317274d..9cdac41c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "project1-bootcamp", "version": "0.1.0", + "homepage": "https://prettykaur.github.io/project1-bootcamp", "private": true, "dependencies": { "@emotion/react": "^11.10.6", @@ -17,6 +18,8 @@ "reactjs-popup": "^2.0.5" }, "scripts": { + "predeploy": "npm run build", + "deploy": "gh-pages -d build", "start": "react-scripts start", "build": "react-scripts build" }, @@ -36,5 +39,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "gh-pages": "^5.0.0" } } From 57e46d991d5596950d8c3c033971dafde9696b91 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Thu, 13 Apr 2023 08:22:24 +0800 Subject: [PATCH 21/22] Fix bug incrementing mistakes made --- src/Components/Game.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Components/Game.js b/src/Components/Game.js index 2bcf2391..8ecb1444 100644 --- a/src/Components/Game.js +++ b/src/Components/Game.js @@ -129,11 +129,9 @@ const Game = () => { // moves registered when the value is not 0 if (clickValue !== 0) { setMovesTaken((moves) => moves + 1); + if (!clickValue.isValid) setMistakesMade((mistakes) => mistakes + 1); } - // Count mistakes made - if (!clickValue.isValid) setMistakesMade((mistakes) => mistakes + 1); - let newGrid = arrayDeepCopy(grid); newGrid[row][column].value = clickValue; From 18b1673c979767ed21d10edf2604c7c9bc326351 Mon Sep 17 00:00:00 2001 From: prettykaur Date: Thu, 13 Apr 2023 08:23:28 +0800 Subject: [PATCH 22/22] Add comments --- src/Components/Game.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Components/Game.js b/src/Components/Game.js index 8ecb1444..adb0218a 100644 --- a/src/Components/Game.js +++ b/src/Components/Game.js @@ -126,7 +126,8 @@ const Game = () => { const handleCellClick = (row, column, isEditable) => { if (!isEditable) return; - // moves registered when the value is not 0 + // Moves registered when the value is not 0 + // Increment mistakes made if (clickValue !== 0) { setMovesTaken((moves) => moves + 1); if (!clickValue.isValid) setMistakesMade((mistakes) => mistakes + 1);