Add LCM practice

This commit is contained in:
2024-03-02 16:46:08 -05:00
parent 5f95ae4dbf
commit 47a24df21b
12 changed files with 546 additions and 166 deletions

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Preact + TS</title>
<title>Math Practice</title>
</head>
<body data-bs-theme="dark">
<div id="app"></div>

View File

@@ -14,7 +14,10 @@
"bootstrap-react": "^0.5.0-alpha.14",
"preact": "^10.19.5",
"react": "npm:@preact/compat",
"react-dom": "npm:@preact/compat"
"react-bootstrap": "^2.10.1",
"react-dom": "npm:@preact/compat",
"react-router": "^6.22.2",
"react-router-dom": "^6.22.2"
},
"devDependencies": {
"@preact/preset-vite": "^2.8.1",

View File

@@ -1,7 +1,8 @@
#app {
max-width: 1280px;
/*max-width: 1280px;*/
width:100%;
margin: 0 auto;
padding: 2rem;
/*padding: 2rem;*/
text-align: center;
}

View File

@@ -1,132 +1,18 @@
import { useState } from 'preact/hooks'
import { GCF } from './gcf'
import { LCM } from './lcm'
import Navbar from './navbar'
import { BrowserRouter, Navigate, Routes, Route } from 'react-router-dom'
import './app.css'
import { Solution } from './solution'
import type { SolutionKey } from './solution'
import type { JSX } from 'preact'
export function App() {
// choose number between 2 and max inclusive
const getRandomInt = (max : number) : number => Math.floor(Math.random() * (max - 1) + 2)
const chooseFactorsRandom = () : [number, number] => [ getRandomInt(200), getRandomInt(200) ]
const _chooseMultiplesOf = (f : number) : [number, number] => {
const max = Math.floor(200 / f)
return [ f * getRandomInt(max), f * getRandomInt(max) ]
}
const chooseMultiplesOf = (f : number) : () => [ number, number ] => {
return () => _chooseMultiplesOf(f)
}
const chooseMultiples = () : [number, number] => {
const f = getRandomInt(50)
return _chooseMultiplesOf(f)
}
const chooseFactors = () : [number, number] => {
const probabilities : Array<[number, () => [number, number]]>= [
[ 0.2, chooseFactorsRandom ],
[ 0.2, chooseMultiples ],
[ 0.2, chooseMultiplesOf(3) ],
[ 0.2, chooseMultiplesOf(7) ],
[ 0.1, chooseMultiplesOf(11) ],
[ 0.1, chooseMultiplesOf(17) ],
]
const r = Math.random()
var i = 0, accum = 0
for (i = 0; i < probabilities.length; i++) {
console.log([r, i, accum, probabilities[i]])
if ((r > accum) && (r <= accum + probabilities[i][0])) break
accum += probabilities[i][0]
}
if (i >= probabilities.length) i = probabilities.length - 1
return probabilities[i][1]()
}
const gcd = (a : number, b : number) : number => {
if (b > a) return gcd(b, a)
else if (b == 0) return a
else return gcd(b, a % b)
}
const getSolution = (a : number, b : number) : SolutionKey => {
var result : SolutionKey = [ ]
if (b > a) {
var t = b
b = a
a = t
}
while (b != 0) {
result.push([ a, Math.floor(a / b), b, a % b ])
var t = a % b
a = b
b = t
}
return result
}
const doCheck = (e : Event) : void => {
e.preventDefault()
const rightAnswer = gcd(factors[0], factors[1])
const yourAnswer = (document.getElementById("inlineFormInputResponse") as HTMLInputElement).value
if (rightAnswer == Number(yourAnswer)) {
setCorrect(true)
setFeedback(true)
} else {
setFeedback(true)
}
}
const doNext = (e : Event) : void => {
e.preventDefault()
setFeedback(false)
setCorrect(false)
setFactors(chooseFactors())
setSolution(null)
document.forms[0].reset()
}
const doSolution = (e : Event) : void => {
e.preventDefault()
if (solution === null) {
var answerBox = document.getElementById("inlineFormInputResponse") as HTMLInputElement
answerBox.value = String(gcd(factors[0], factors[1]))
setSolution(<Solution rows={getSolution(factors[0], factors[1])} />)
setCorrect(true)
//setFeedback(true)
} else {
setSolution(null)
}
}
const [factors, setFactors] = useState(chooseFactors())
const [correct, setCorrect] = useState(false)
const [feedback, setFeedback] = useState(false)
const [solution, setSolution] = useState<JSX.Element|null>(null)
return (
<div className="px-4 py-5 my-5 text-center">
<h1 className="my-5">Greatest Common Factor Practice</h1>
<p className="fs-3">What is the greatest common factor of <mark>{factors[0]}</mark> and <mark>{factors[1]}</mark>?</p>
<form className="row row-cols-lg-auto g-3 align-items-center justify-content-center">
<div className="col-12">
<label className="visually-hidden" for="inlineFormInputResponse">Response</label>
<div className="input-group">
<input type="text" size={3} autocomplete="off" className="form-control text-center" id="inlineFormInputResponse" />
</div>
</div>
<div className="col-12">
<button type="submit" onClick={correct ? doNext : doCheck} className="btn btn-primary">{correct ? "Next" : "Check"}</button>
<button type="submit" onClick={doSolution} className="ms-2 btn btn-secondary">{solution !== null ? "Hide" : "Solve"}</button>
</div>
</form>
<div className={feedback ? "visible" : "invisible"}>
<div className={correct ? "alert alert-success m-4" : "alert alert-danger m-4"}>{correct ? "Correct" : "Try again!"}</div>
</div>
{solution !== null ? solution : <></>}
</div>
)
return <>
<BrowserRouter>
<Navbar />
<Routes>
<Route path="/" element={<Navigate to="/gcf" />} />
<Route path="/gcf" element={<GCF />} />
<Route path="/lcm" element={<LCM />} />
</Routes>
</BrowserRouter>
</>
}

154
src/gcf.tsx Normal file
View File

@@ -0,0 +1,154 @@
import { useState } from 'preact/hooks'
import './gcf.css'
import { gcf } from './lib'
import type { JSX } from 'preact'
type SolutionRow = [Number, Number, Number, Number]
type SolutionKey = Array<SolutionRow>
type SolutionParams = {
rows : SolutionKey
}
function Solution({rows}:SolutionParams) {
const colors = [
"red",
"blue",
"green",
"brown",
"purple",
"orange"
]
const displayRow = (row : SolutionRow, index : number) => {
let range : number[] = [0, 1, 2]
const styles = range.map((i)=>{return `padding:3px;color:white;background:${colors[(i+index)%colors.length]}`})
return <p>
<span style={styles[0]}>{row[0]}</span>&nbsp;&divide;&nbsp;<span style={styles[1]}>{row[2]}</span>&nbsp;=&nbsp;{row[1]}&nbsp;R&nbsp;<span style={styles[2]}>{row[3]}</span>
</p>
}
return <div className="solution text-center" data-bs-theme="light">
{rows.map(displayRow)}
</div>
}
export function GCF() {
// choose number between 2 and max inclusive
const getRandomInt = (max : number) : number => Math.floor(Math.random() * (max - 1) + 2)
const chooseFactorsRandom = () : [number, number] => [ getRandomInt(200), getRandomInt(200) ]
const _chooseMultiplesOf = (f : number) : [number, number] => {
const max = Math.floor(200 / f)
return [ f * getRandomInt(max), f * getRandomInt(max) ]
}
const chooseMultiplesOf = (f : number) : () => [ number, number ] => {
return () => _chooseMultiplesOf(f)
}
const chooseMultiples = () : [number, number] => {
const f = getRandomInt(50)
return _chooseMultiplesOf(f)
}
const chooseFactors = () : [number, number] => {
const probabilities : Array<[number, () => [number, number]]>= [
[ 0.2, chooseFactorsRandom ],
[ 0.2, chooseMultiples ],
[ 0.2, chooseMultiplesOf(3) ],
[ 0.2, chooseMultiplesOf(7) ],
[ 0.1, chooseMultiplesOf(11) ],
[ 0.1, chooseMultiplesOf(17) ],
]
const r = Math.random()
var i = 0, accum = 0
for (i = 0; i < probabilities.length; i++) {
console.log([r, i, accum, probabilities[i]])
if ((r > accum) && (r <= accum + probabilities[i][0])) break
accum += probabilities[i][0]
}
if (i >= probabilities.length) i = probabilities.length - 1
return probabilities[i][1]()
}
const getSolution = (a : number, b : number) : SolutionKey => {
var result : SolutionKey = [ ]
if (b > a) {
var t = b
b = a
a = t
}
while (b != 0) {
result.push([ a, Math.floor(a / b), b, a % b ])
var t = a % b
a = b
b = t
}
return result
}
const doCheck = (e : Event) : void => {
e.preventDefault()
const rightAnswer = gcf(factors[0], factors[1])
const yourAnswer = (document.getElementById("inlineFormInputResponse") as HTMLInputElement).value
if (rightAnswer == Number(yourAnswer)) {
setCorrect(true)
setFeedback(true)
} else {
setFeedback(true)
}
}
const doNext = (e : Event) : void => {
e.preventDefault()
setFeedback(false)
setCorrect(false)
setFactors(chooseFactors())
setSolution(null)
document.forms[0].reset()
}
const doSolution = (e : Event) : void => {
e.preventDefault()
if (solution === null) {
var answerBox = document.getElementById("inlineFormInputResponse") as HTMLInputElement
answerBox.value = String(gcf(factors[0], factors[1]))
setSolution(<Solution rows={getSolution(factors[0], factors[1])} />)
setCorrect(true)
//setFeedback(true)
} else {
setSolution(null)
}
}
const [factors, setFactors] = useState(chooseFactors())
const [correct, setCorrect] = useState(false)
const [feedback, setFeedback] = useState(false)
const [solution, setSolution] = useState<JSX.Element|null>(null)
return (
<div className="px-4 py-5 my-5 text-center">
<h1 className="my-5">Greatest Common Factor Practice</h1>
<p className="fs-3">What is the greatest common factor of <mark>{factors[0]}</mark> and <mark>{factors[1]}</mark>?</p>
<form className="row row-cols-lg-auto g-3 align-items-center justify-content-center">
<div className="col-12">
<label className="visually-hidden" for="inlineFormInputResponse">Response</label>
<div className="input-group">
<input type="text" size={3} autocomplete="off" className="form-control text-center" id="inlineFormInputResponse" />
</div>
</div>
<div className="col-12">
<button type="submit" onClick={correct ? doNext : doCheck} className="btn btn-primary">{correct ? "Next" : "Check"}</button>
<button type="submit" onClick={doSolution} className="ms-2 btn btn-secondary">{solution !== null ? "Hide" : "Solve"}</button>
</div>
</form>
<div className={feedback ? "visible" : "invisible"}>
<div className={correct ? "alert alert-success m-4" : "alert alert-danger m-4"}>{correct ? "Correct" : "Try again!"}</div>
</div>
{solution !== null ? solution : <></>}
</div>
)
}

View File

@@ -24,7 +24,7 @@ a:hover {
body {
margin: 0;
display: flex;
/*display: flex;*/
place-items: center;
min-width: 320px;
min-height: 100vh;

131
src/lcm.tsx Normal file
View File

@@ -0,0 +1,131 @@
import { useState } from 'preact/hooks'
import { gcf } from './lib'
import type { JSX } from 'preact'
type SolutionParams = {
factors : [ number, number ],
gcf : number,
result : number
}
function Solution({factors, gcf, result}:SolutionParams) {
const multipliers = [
Math.floor(result/factors[0]),
Math.floor(result/factors[1]),
]
return <div className="solution text-center" data-bs-theme="light">
<p>GCF({factors[0]},&nbsp;{factors[1]})&nbsp;=&nbsp;{gcf}</p>
<p>{factors[0]}&nbsp;&times;&nbsp;{factors[1]}&nbsp;&divide;&nbsp;{gcf}&nbsp;=&nbsp;{result}</p>
<p>{factors[0]}&nbsp;&times;&nbsp;{multipliers[0]}&nbsp;=&nbsp;{result}</p>
<p>{factors[1]}&nbsp;&times;&nbsp;{multipliers[1]}&nbsp;=&nbsp;{result}</p>
</div>
}
export function LCM() {
// choose number between 2 and max inclusive
const getRandomInt = (max : number) : number => Math.floor(Math.random() * (max - 1) + 2)
const chooseFactorsRandom = () : [number, number] => {
const f = getRandomInt(15)
const max = Math.floor(200 / f)
return [ f, getRandomInt(max) ]
}
const _chooseMultiplesOf = (f : number) : [number, number] => {
const max = Math.floor(200 / f)
return [ f * getRandomInt(max), f * getRandomInt(max) ]
}
/*
const chooseMultiplesOf = (f : number) : () => [ number, number ] => {
return () => _chooseMultiplesOf(f)
}
*/
const chooseMultiples = () : [number, number] => {
const f = getRandomInt(20)
return _chooseMultiplesOf(f)
}
const chooseFactors = () : [number, number] => {
const probabilities : Array<[number, () => [number, number]]>= [
[ 0.5, chooseFactorsRandom ],
[ 0.5, chooseMultiples ],
]
const r = Math.random()
var i = 0, accum = 0
for (i = 0; i < probabilities.length; i++) {
//console.log([r, i, accum, probabilities[i]])
if ((r > accum) && (r <= accum + probabilities[i][0])) break
accum += probabilities[i][0]
}
if (i >= probabilities.length) i = probabilities.length - 1
return probabilities[i][1]()
}
const doCheck = (e : Event) : void => {
e.preventDefault()
const rightAnswer = Math.floor(factors[0] / gcf(factors[0], factors[1])) * factors[1]
const yourAnswer = (document.getElementById("inlineFormInputResponse") as HTMLInputElement).value
if (rightAnswer == Number(yourAnswer)) {
setCorrect(true)
setFeedback(true)
} else {
setFeedback(true)
}
}
const doNext = (e : Event) : void => {
e.preventDefault()
setFeedback(false)
setCorrect(false)
setFactors(chooseFactors())
setSolution(null)
document.forms[0].reset()
}
const doSolution = (e : Event) : void => {
e.preventDefault()
if (solution === null) {
var answerBox = document.getElementById("inlineFormInputResponse") as HTMLInputElement
const theGCF = gcf(factors[0], factors[1])
const rightAnswer = Math.floor(factors[0] / theGCF) * factors[1]
answerBox.value = String(rightAnswer)
setSolution(<Solution factors={factors} gcf={theGCF} result={rightAnswer} />)
setCorrect(true)
//setFeedback(true)
} else {
setSolution(null)
}
}
const [factors, setFactors] = useState(chooseFactors())
const [correct, setCorrect] = useState(false)
const [feedback, setFeedback] = useState(false)
const [solution, setSolution] = useState<JSX.Element|null>(null)
return (
<div className="px-4 py-5 my-5 text-center">
<h1 className="my-5">Least Common Multiple Practice</h1>
<p className="fs-3">What is the least common multiple of <mark>{factors[0]}</mark> and <mark>{factors[1]}</mark>?</p>
<form className="row row-cols-lg-auto g-3 align-items-center justify-content-center">
<div className="col-12">
<label className="visually-hidden" for="inlineFormInputResponse">Response</label>
<div className="input-group">
<input type="text" size={3} autocomplete="off" className="form-control text-center" id="inlineFormInputResponse" />
</div>
</div>
<div className="col-12">
<button type="submit" onClick={correct ? doNext : doCheck} className="btn btn-primary">{correct ? "Next" : "Check"}</button>
<button type="submit" onClick={doSolution} className="ms-2 btn btn-secondary">{solution !== null ? "Hide" : "Solve"}</button>
</div>
</form>
<div className={feedback ? "visible" : "invisible"}>
<div className={correct ? "alert alert-success m-4" : "alert alert-danger m-4"}>{correct ? "Correct" : "Try again!"}</div>
</div>
{solution !== null ? solution : <></>}
</div>
)
}

5
src/lib.tsx Normal file
View File

@@ -0,0 +1,5 @@
export function gcf(a : number, b : number) : number {
if (b > a) return gcf(b, a)
else if (b == 0) return a
else return gcf(b, a % b)
}

24
src/navbar.tsx Normal file
View File

@@ -0,0 +1,24 @@
import Container from 'react-bootstrap/Container';
import { NavLink } from 'react-router-dom'
import Nav from 'react-bootstrap/Nav';
//import NavItem from 'react-bootstrap/NavItem'
import RBNavbar from 'react-bootstrap/Navbar';
//import NavDropdown from 'react-bootstrap/NavDropdown';
function Navbar() {
return (
<RBNavbar expand="lg" className="bg-body-tertiary" sticky="top">
<Container>
<RBNavbar.Toggle aria-controls="basic-navbar-nav" />
<RBNavbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<NavLink to="/gcf" title="Greatest Common Factor" className={({ isActive, isPending }) => "nav-link " + (isPending ? "" : isActive ? "active" : "")}>GCF</NavLink>
<NavLink to="/lcm" title="Least Common Multiple" className={({ isActive, isPending }) => "nav-link " + (isPending ? "" : isActive ? "active" : "")}>LCM</NavLink>
</Nav>
</RBNavbar.Collapse>
</Container>
</RBNavbar>
);
}
export default Navbar;

View File

@@ -1,29 +0,0 @@
import './solution.css'
type SolutionRow = [Number, Number, Number, Number]
export type SolutionKey = Array<SolutionRow>
type SolutionParams = {
rows : SolutionKey
}
export function Solution({rows}:SolutionParams) {
const colors = [
"red",
"blue",
"green",
"brown",
"purple",
"orange"
]
const displayRow = (row : SolutionRow, index : number) => {
let range : number[] = [0, 1, 2]
const styles = range.map((i)=>{return `padding:3px;color:white;background:${colors[(i+index)%colors.length]}`})
return <p>
<span style={styles[0]}>{row[0]}</span>&nbsp;&divide;&nbsp;<span style={styles[1]}>{row[2]}</span>&nbsp;=&nbsp;{row[1]}&nbsp;R&nbsp;<span style={styles[2]}>{row[3]}</span>
</p>
}
return <div className="solution text-center" data-bs-theme="light">
{rows.map(displayRow)}
</div>
}

213
yarn.lock
View File

@@ -192,6 +192,13 @@
"@babel/plugin-syntax-jsx" "^7.23.3"
"@babel/types" "^7.23.4"
"@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.0.tgz#584c450063ffda59697021430cb47101b085951e"
integrity sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.15", "@babel/template@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
@@ -401,7 +408,7 @@
style-value-types "^3.1.7"
tslib "^1.10.0"
"@popperjs/core@^2.4.4":
"@popperjs/core@^2.11.6", "@popperjs/core@^2.4.4":
version "2.11.8"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
@@ -448,6 +455,40 @@
"@prefresh/utils" "^1.2.0"
"@rollup/pluginutils" "^4.2.1"
"@react-aria/ssr@^3.5.0":
version "3.9.2"
resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.9.2.tgz#01b756965cd6e32b95217f968f513eb3bd6ee44b"
integrity sha512-0gKkgDYdnq1w+ey8KzG9l+H5Z821qh9vVjztk55rUg71vTk/Eaebeir+WtzcLLwTjw3m/asIjx8Y59y1lJZhBw==
dependencies:
"@swc/helpers" "^0.5.0"
"@remix-run/router@1.15.2":
version "1.15.2"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.15.2.tgz#35726510d332ba5349c6398d13259d5da184553d"
integrity sha512-+Rnav+CaoTE5QJc4Jcwh5toUpnVLKYbpU6Ys0zqbakqbaLQHeglLVHPfxOiQqdNmUy5C2lXz5dwC6tQNX2JW2Q==
"@restart/hooks@^0.4.9":
version "0.4.16"
resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.16.tgz#95ae8ac1cc7e2bd4fed5e39800ff85604c6d59fb"
integrity sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==
dependencies:
dequal "^2.0.3"
"@restart/ui@^1.6.6":
version "1.6.6"
resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.6.6.tgz#3481e2eaf15d7cae55bb2f518624e10d19c75800"
integrity sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==
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.1"
warning "^4.0.3"
"@rollup/pluginutils@^4.1.1", "@rollup/pluginutils@^4.2.1":
version "4.2.1"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
@@ -457,6 +498,7 @@
picomatch "^2.2.2"
"@rollup/wasm-node@^4.12.0", rollup@^4.2.0, "rollup@npm:@rollup/wasm-node":
name rollup
version "4.12.0"
resolved "https://registry.yarnpkg.com/@rollup/wasm-node/-/wasm-node-4.12.0.tgz#d131697bbbfca561e57c910841db97e8841a6b02"
integrity sha512-sqy3+YvV/uWX6bPZOR5PlEdH6xyMPXoelllRQ/uZ13tzy9f4pXZTbajnoWN8IHHXwTNKPiLzsePLiDEVmkxMNw==
@@ -465,6 +507,13 @@
optionalDependencies:
fsevents "~2.3.2"
"@swc/helpers@^0.5.0":
version "0.5.6"
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.6.tgz#d16d8566b7aea2bef90d059757e2d77f48224160"
integrity sha512-aYX01Ke9hunpoCexYAgQucEpARGQ5w/cqHFrIR+e9gdKb1QWTsVJuTJ2ozQzIAxLyRQe/m+2RqzkyOOGiMKRQA==
dependencies:
tslib "^2.4.0"
"@types/classnames@^2.2.10":
version "2.3.1"
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.3.1.tgz#3c2467aa0f1a93f1f021e3b9bcf938bd5dfdc0dd"
@@ -477,6 +526,37 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
"@types/prop-types@*":
version "15.7.11"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
integrity sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==
"@types/react-transition-group@^4.4.6":
version "4.4.10"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac"
integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@>=16.9.11":
version "18.2.61"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.61.tgz#5607308495037436779939ec0348a5816c08799d"
integrity sha512-NURTN0qNnJa7O/k4XUkEW2yfygA+NxS0V5h1+kp9jPwhzZy95q3ADoGMP0+JypMhrZBTTgjKAUlTctde1zzeQA==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"
"@types/scheduler@*":
version "0.16.8"
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==
"@types/warning@^3.0.0":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.3.tgz#d1884c8cc4a426d1ac117ca2611bf333834c6798"
integrity sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -535,7 +615,7 @@ chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
classnames@*, classnames@^2.2.6:
classnames@*, classnames@^2.2.6, classnames@^2.3.2:
version "2.5.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
@@ -573,6 +653,11 @@ css-what@^6.1.0:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
csstype@^3.0.2:
version "3.1.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
debug@^4.1.0, debug@^4.3.1, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
@@ -580,6 +665,19 @@ debug@^4.1.0, debug@^4.3.1, debug@^4.3.4:
dependencies:
ms "2.1.2"
dequal@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
dependencies:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
dom-serializer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
@@ -729,6 +827,13 @@ hey-listen@^1.0.5, hey-listen@^1.0.8:
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
dependencies:
loose-envify "^1.0.0"
is-core-module@^2.13.0:
version "2.13.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
@@ -756,7 +861,7 @@ kolorist@^1.8.0:
resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c"
integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==
loose-envify@^1.0.0:
loose-envify@^1.0.0, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
@@ -807,6 +912,11 @@ nth-check@^2.0.1:
dependencies:
boolbase "^1.0.0"
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
@@ -848,6 +958,41 @@ preact@^10.19.5:
resolved "https://registry.yarnpkg.com/preact/-/preact-10.19.6.tgz#66007b67aad4d11899f583df1b0116d94a89b8f5"
integrity sha512-gympg+T2Z1fG1unB8NH29yHJwnEaCH37Z32diPDku316OTnRPeMbiRV9kTrfZpocXjdfnWuFUl/Mj4BHaf6gnw==
prop-types-extra@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b"
integrity sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==
dependencies:
react-is "^16.3.2"
warning "^4.0.0"
prop-types@^15.6.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
dependencies:
loose-envify "^1.4.0"
object-assign "^4.1.1"
react-is "^16.13.1"
react-bootstrap@^2.10.1:
version "2.10.1"
resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.10.1.tgz#48ee28fcd7973ddc0d0ce2161a918785fba4ab2c"
integrity sha512-J3OpRZIvCTQK+Tg/jOkRUvpYLHMdGeU9KqFUBQrV0d/Qr/3nsINpiOJyZMWnM5SJ3ctZdhPA6eCIKpEJR3Ellg==
dependencies:
"@babel/runtime" "^7.22.5"
"@restart/hooks" "^0.4.9"
"@restart/ui" "^1.6.6"
"@types/react-transition-group" "^4.4.6"
classnames "^2.3.2"
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.5"
uncontrollable "^7.2.1"
warning "^4.0.3"
"react-dom@npm:@preact/compat", "react@npm:@preact/compat":
version "17.1.2"
resolved "https://registry.yarnpkg.com/@preact/compat/-/compat-17.1.2.tgz#928756713b07af6faf7812f6a56840d8ce6fed37"
@@ -858,6 +1003,16 @@ react-fast-compare@^3.0.1:
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
react-is@^16.13.1, react-is@^16.3.2:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-popper@^2.2.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba"
@@ -866,6 +1021,36 @@ react-popper@^2.2.3:
react-fast-compare "^3.0.1"
warning "^4.0.2"
react-router-dom@^6.22.2:
version "6.22.2"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.22.2.tgz#8233968a8a576f3006e5549c80f3527d2598fc9c"
integrity sha512-WgqxD2qySEIBPZ3w0sHH+PUAiamDeszls9tzqMPBDA1YYVucTBXLU7+gtRfcSnhe92A3glPnvSxK2dhNoAVOIQ==
dependencies:
"@remix-run/router" "1.15.2"
react-router "6.22.2"
react-router@6.22.2, react-router@^6.22.2:
version "6.22.2"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.22.2.tgz#27e77e4c635a5697693b922d131d773451c98a5b"
integrity sha512-YD3Dzprzpcq+tBMHBS822tCjnWD3iIZbTeSXMY9LPSG541EfoBGyZ3bS25KEnaZjLcmQpw2AVLkFyfgXY8uvcw==
dependencies:
"@remix-run/router" "1.15.2"
react-transition-group@^4.4.5:
version "4.4.5"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
regenerator-runtime@^0.14.0:
version "0.14.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
resize-observer-polyfill@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
@@ -931,11 +1116,31 @@ tslib@^1.10.0:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.4.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
typescript@^5.2.2:
version "5.3.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
uncontrollable@^7.2.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.2.1.tgz#1fa70ba0c57a14d5f78905d533cf63916dc75738"
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"
uncontrollable@^8.0.1:
version "8.0.4"
resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-8.0.4.tgz#a0a8307f638795162fafd0550f4a1efa0f8c5eb6"
integrity sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==
update-browserslist-db@^1.0.13:
version "1.0.13"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
@@ -955,7 +1160,7 @@ vite@^5.1.4:
optionalDependencies:
fsevents "~2.3.3"
warning@^4.0.2:
warning@^4.0.0, warning@^4.0.2, warning@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==