diff --git a/package.json b/package.json index b77b4d9..bd2a7c1 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "kill me", "private": true, "scripts": { - "build": "parcel build --no-source-maps --dist-dir dist --public-url '.' src/html/index.html", + "build": "parcel build --dist-dir dist --public-url '.' src/html/index.html", "serve": "parcel src/html/index.html", "test": "jest", "clean": "run-script-os", @@ -16,7 +16,6 @@ "dependencies": { "@hcaptcha/types": "^1.0.3", "@popperjs/core": "^2.11.8", - "bootstrap": "^5.3.2", "nanoevents": "^7.0.1", "simple-keyboard": "^3.7.53" }, @@ -24,6 +23,7 @@ "@parcel/watcher": "~2.1.0" }, "devDependencies": { + "@parcel/transformer-sass": "2.12.0", "@types/bootstrap": "^5.2.10", "@types/jest": "^29.5.12", "jest": "^29.7.0", diff --git a/src/css/_colors-dark.scss b/src/css/_colors-dark.scss new file mode 100644 index 0000000..9815292 --- /dev/null +++ b/src/css/_colors-dark.scss @@ -0,0 +1,15 @@ +// TODO: Maybe we *should* use CSS variables, so the user can pick any theme +// and maybe put in hooks for that.. but for now this is fine! + +$root-bg-color: rgb(32, 32, 32); +$root-fg-color: rgb(180, 180, 180); + +/** Cards **/ +$card-background-color: rgb(48, 48, 48); +$card-border-color: rgb(58, 58, 58); +$card-box-shadow-color: rgb(0, 0, 0); +/* I have to do different syntax here because you can only do divisors with rgb() ahahah GRRRR */ +$card-image-background-color: #ffffff10; + +$link-color: rgb(100, 140, 200); +$link-visited-color: rgb(160, 140, 200); diff --git a/src/css/cards.scss b/src/css/cards.scss new file mode 100644 index 0000000..fe929ff --- /dev/null +++ b/src/css/cards.scss @@ -0,0 +1,61 @@ +@import 'colors-dark'; + +.cards { + display: grid; + list-style: none; + padding: unset; + gap: 1em; + grid-template-columns: repeat(auto-fit, minmax(0, 20em)); + /* I wish I could do this in certain situations. + * Card sections that need to wrap should be centered, but ones that fit on one line could be left-aligned. */ + /* aah i keep enabling and disabling this i don't know what to dooooo */ + /* justify-content: center; */ + font-size: 0.875rem; +} + +.cards > li > * { + height: 100%; +} + +.cards .card { + display: block; + line-height: 1.5; + overflow: auto; + text-decoration: inherit; + color: inherit; + background-color: $root-fg-color $card-background-color; + border: 4px solid $root-fg-color $card-border-color; + border-radius: 4px; + box-shadow: 0px 0px 1px 0px $root-fg-color $card-box-shadow-color; +} + +.cards .card:hover { + box-shadow: 0px 0px 4px 0px $root-fg-color $card-box-shadow-color; + /* hmm, maybe get a better indication because this isn't the most evident or the best looking */ + outline: 2px solid $root-fg-color $card-border-color; +} + +.cards .card .card-image { + display: block; + width: 100%; + background-color: $root-fg-color $card-image-background-color; + object-fit: contain; + box-sizing: border-box; + margin: auto; + /* this'd be cool if this perfectly fit a square, but then the cards are a bit bigger than i'd like them to be. gah */ + max-height: 15em; +} + +.cards .card .card-body { + padding: 1em; +} + +.cards .card .card-body > * { + margin: unset; +} + +.cards .card .card-heading { + font-size: 1.1em; + font-weight: bold; + margin-bottom: 0.25em; +} diff --git a/src/css/main.scss b/src/css/main.scss new file mode 100644 index 0000000..f8b8f95 --- /dev/null +++ b/src/css/main.scss @@ -0,0 +1,362 @@ +// TODO!!!!!! +@import 'colors-dark'; + +// modules +@import 'cards'; + +html, +body { + background-color: $root-bg-color; + color: $root-fg-color; + font-family: 'Segoe UI', Tahoma, Cantarell, sans-serif; + margin: unset; +} + +.main { + margin: auto; + overflow-wrap: break-word; +} + +/** Prettier links **/ +a { + color: $link-color; + text-decoration: none; +} + +a:visited { + color: $link-visited-color; + text-decoration: none; +} + +// ze webapp + +#vmview { + display: none; +} +/*.vmtile { + text-decoration: none; + color: #FFFFFF; + font-size: 16pt; + border: 2px solid #575757; + border-radius: 15px; + height: fit-content; + width: fit-content; + display: block; + padding: 4px; + }*/ +#vmDisplay, +#btns { + margin-left: auto; + margin-right: auto; + text-align: center; + display: block; + margin-bottom: 10px; +} + +#vmlist > div.row > div { + padding-bottom: 10px; +} +#vmlist div.col-md-3 > div.card:hover { + cursor: pointer; + border-color: rgb(8, 121, 250); +} + +.vmtile > img { + margin-bottom: 2px; +} + +.chat-table, +.username-table { + overflow-y: auto; + border: 1px solid #575757; +} +.chat-table { + height: 30vh; +} + +.username-table { + max-height: 30vh; +} +.username-table > table > thead { + position: sticky; + top: 0; +} + +#turnstatus { + text-align: center; +} +#voteResetPanel { + text-align: center; +} + +.focused { + box-shadow: 0 0 9px 0 rgba(45, 213, 255, 0.75); + -moz-box-shadow: 0 0 9px 0 rgba(45, 213, 255, 0.75); + -webkit-box-shadow: 0 0 9px 0 rgba(45, 213, 255, 0.75); +} + +.waiting { + box-shadow: 0 0 9px 0 rgba(242, 255, 63, 0.75); + -moz-box-shadow: 0 0 9px 0 rgba(242, 255, 63, 0.75); + -webkit-box-shadow: 0 0 9px 0 rgba(242, 255, 63, 0.75); +} + +#staffbtns { + display: none; +} + +#staffbtns > button { + display: none; +} + +#qemuMonitorOutput { + height: 180px; +} + +#xssCheckboxContainer { + display: none; +} + +#forceVotePanel { + display: none; +} + +tr.user-admin > td, +.chat-username-admin, +.username-admin { + color: #ff0000 !important; +} + +tr.user-moderator > td, +.chat-username-moderator, +.username-moderator { + color: #00ff00 !important; +} + +tr.user-turn > td { + background-color: #cfe2ff !important; + --bs-table-bg-state: #cfe2ff !important; + color: #000000; + --bs-table-color: #000000; +} + +tr.user-turn:hover, +tr.user-turn > td:hover { + background-color: #bacbe6 !important; + --bs-table-bg-state: #bacbe6 !important; +} + +tr.user-waiting > td { + background-color: #fff3cd !important; + --bs-table-bg-state: #fff3cd !important; + color: #000000; + --bs-table-color: #000000; +} + +.tr.user-waiting:hover, +tr.user-waiting > td:hover { + background-color: #ece1be !important; + --bs-table-bg-state: #ece1be !important; +} + +.user-current { + font-style: italic; +} + +/* Start OSK */ +.osk-container { + display: flex; + justify-content: center; + width: 1024px; + margin: 0 auto; + margin-bottom: 10px; + border-radius: 5px; +} + +.simple-keyboard.hg-theme-default { + display: inline-block; +} + +.osk-main.simple-keyboard { + width: 640px; + min-width: 640px; + background: none; +} + +.osk-main.simple-keyboard .hg-row:first-child { + margin-bottom: 8.51px; +} + +.osk-arrows.simple-keyboard { + align-self: flex-end; + background: none; +} + +.simple-keyboard .hg-button.selectedButton { + background: rgba(5, 25, 70, 0.53); + color: white; +} + +.simple-keyboard .hg-button.emptySpace { + pointer-events: none; + background: none; + border: none; + box-shadow: none; +} + +.osk-arrows .hg-row { + justify-content: center; +} + +.osk-arrows .hg-button { + width: 50px; + flex-grow: 0 !important; + justify-content: center !important; + display: flex !important; + align-items: center !important; +} + +.controlArrows { + display: flex; + align-items: center; + justify-content: space-between; + flex-flow: column; +} + +.osk-control.simple-keyboard { + background: none; +} + +.osk-control.simple-keyboard .hg-row:first-child { + margin-bottom: 8.51px; +} + +.osk-control .hg-button { + width: 50px; + flex-grow: 0 !important; + justify-content: center !important; + display: flex !important; + align-items: center !important; +} + +.numPad { + display: flex; + align-items: flex-end; +} + +.osk-numpad.simple-keyboard { + background: none; +} + +.osk-numpad.simple-keyboard { + width: 160px; +} + +.osk-numpad.simple-keyboard .hg-button { + width: 50px; + justify-content: center; + display: flex; + align-items: center; +} + +.osk-numpadEnd.simple-keyboard { + width: 50px; + background: none; + margin: 0; + padding: 5px 5px 5px 0; +} + +.osk-numpadEnd.simple-keyboard .hg-button { + align-items: center; + justify-content: center; + display: flex; +} + +.osk-numpadEnd .hg-button.hg-standardBtn.hg-button-plus { + height: 85px; +} + +.osk-numpadEnd.simple-keyboard .hg-button.hg-button-enter { + height: 85px; +} + +.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton { + background: rgba(5, 25, 70, 0.53); + color: white; +} + +.hg-button.hg-functionBtn.hg-button-space { + width: 350px; +} + +/* + Theme: cvmDark + */ + +.simple-keyboard.cvmDark .hg-button { + border-bottom: none; + background: rgba(0, 0, 0, 0.5); + color: white; +} + +.simple-keyboard.cvmDark .hg-button:active { + background: #1c4995; + color: white; +} + +#root .simple-keyboard.cvmDark + .simple-keyboard-preview { + background: #1c4995; +} + +/* + Theme: cvmDisabled + */ +.simple-keyboard.cvmDisabled .hg-button { + border-bottom: none; + pointer-events: none; + background: gray; + color: white; +} + +/* End OSK */ + +#badPasswordAlert { + display: none; +} + +/* VM0 Blur */ +a[data-cvm-node='vm0b0t'] { + img { + filter: blur(40px) !important; + } +} + +// for our new based modals +// This should probably be put into a more uniform file + +/* a bit of a "lazy" curve */ +@keyframes dialogFadeIn { + 0% { + opacity: 0; + } + 35% { + opacity: 0.75; + } + 100% { + opacity: 1; + } +} + +// don't really know how i can animate "out", +// at least without hacks, but oh well +// +// this will also probably be snappier than the mess that is +// the bootstrap modals.. + +dialog::backdrop { + animation: dialogFadeIn 0.7s; +} + +:modal { + animation: dialogFadeIn 0.4s; +} diff --git a/src/css/style.css b/src/css/style.css deleted file mode 100644 index 9cac47e..0000000 --- a/src/css/style.css +++ /dev/null @@ -1,292 +0,0 @@ -#vmview { - display: none; -} -/*.vmtile { - text-decoration: none; - color: #FFFFFF; - font-size: 16pt; - border: 2px solid #575757; - border-radius: 15px; - height: fit-content; - width: fit-content; - display: block; - padding: 4px; -}*/ -#vmDisplay, #btns { - margin-left: auto; - margin-right: auto; - text-align: center; - display: block; - margin-bottom: 10px; -} - -#vmlist > div.row > div { - padding-bottom: 10px; -} -#vmlist div.col-md-3 > div.card:hover { - cursor: pointer; - border-color: rgb(8, 121, 250); -} - -.vmtile > img { - margin-bottom: 2px; -} - -.chat-table, .username-table { - overflow-y: auto; - border: 1px solid #575757; -} -.chat-table { - height: 30vh; -} - -.username-table { - max-height: 30vh; -} -.username-table > table > thead { - position: sticky; - top: 0; -} - -#turnstatus { - text-align: center; -} -#voteResetPanel { - text-align: center; -} - -.focused { - box-shadow: 0 0 9px 0 rgba(45,213,255,.75); - -moz-box-shadow: 0 0 9px 0 rgba(45,213,255,.75); - -webkit-box-shadow: 0 0 9px 0 rgba(45,213,255,.75) -} - -.waiting { - box-shadow: 0 0 9px 0 rgba(242,255,63,.75); - -moz-box-shadow: 0 0 9px 0 rgba(242,255,63,.75); - -webkit-box-shadow: 0 0 9px 0 rgba(242,255,63,.75) -} - -#staffbtns { - display: none; -} - -#staffbtns > button { - display: none; -} - -#qemuMonitorOutput { - height: 180px; -} - -#xssCheckboxContainer { - display: none; -} - -#forceVotePanel { - display: none; -} - -tr.user-admin > td, .chat-username-admin, .username-admin { - color: #FF0000 !important; -} - -tr.user-moderator > td, .chat-username-moderator, .username-moderator { - color: #00FF00 !important; -} - -tr.user-turn > td { - background-color: #cfe2ff !important; - --bs-table-bg-state: #cfe2ff !important; - color: #000000; - --bs-table-color: #000000; -} - -tr.user-turn:hover, tr.user-turn > td:hover { - background-color: #bacbe6 !important; - --bs-table-bg-state: #bacbe6 !important; -} - -tr.user-waiting > td { - background-color: #fff3cd !important; - --bs-table-bg-state: #fff3cd !important; - color: #000000; - --bs-table-color: #000000; -} - -.tr.user-waiting:hover, tr.user-waiting > td:hover { - background-color: #ece1be !important; - --bs-table-bg-state: #ece1be !important; -} - -.user-current { - font-style: italic; -} - -/* Start OSK */ -.osk-container { -display: flex; -justify-content: center; -width: 1024px; -margin: 0 auto; -margin-bottom: 10px; -border-radius: 5px; -} - -.simple-keyboard.hg-theme-default { -display: inline-block; -} - -.osk-main.simple-keyboard { -width: 640px; -min-width: 640px; -background: none; -} - -.osk-main.simple-keyboard .hg-row:first-child { -margin-bottom: 8.51px; -} - -.osk-arrows.simple-keyboard { -align-self: flex-end; -background: none; -} - -.simple-keyboard .hg-button.selectedButton { -background: rgba(5, 25, 70, 0.53); -color: white; -} - -.simple-keyboard .hg-button.emptySpace { -pointer-events: none; -background: none; -border: none; -box-shadow: none; -} - -.osk-arrows .hg-row { -justify-content: center; -} - -.osk-arrows .hg-button { -width: 50px; -flex-grow: 0 !important; -justify-content: center !important; -display: flex !important; -align-items: center !important; -} - -.controlArrows { -display: flex; -align-items: center; -justify-content: space-between; -flex-flow: column; -} - -.osk-control.simple-keyboard { -background: none; -} - -.osk-control.simple-keyboard .hg-row:first-child { -margin-bottom: 8.51px; -} - -.osk-control .hg-button { -width: 50px; -flex-grow: 0 !important; -justify-content: center !important; -display: flex !important; -align-items: center !important; -} - -.numPad { -display: flex; -align-items: flex-end; -} - -.osk-numpad.simple-keyboard { -background: none; -} - -.osk-numpad.simple-keyboard { -width: 160px; -} - -.osk-numpad.simple-keyboard .hg-button { -width: 50px; -justify-content: center; -display: flex; -align-items: center; -} - -.osk-numpadEnd.simple-keyboard { -width: 50px; -background: none; -margin: 0; -padding: 5px 5px 5px 0; -} - -.osk-numpadEnd.simple-keyboard .hg-button { -align-items: center; -justify-content: center; -display: flex; -} - -.osk-numpadEnd .hg-button.hg-standardBtn.hg-button-plus { -height: 85px; -} - -.osk-numpadEnd.simple-keyboard .hg-button.hg-button-enter { -height: 85px; -} - -.simple-keyboard.hg-theme-default .hg-button.hg-selectedButton { -background: rgba(5, 25, 70, 0.53); -color: white; -} - -.hg-button.hg-functionBtn.hg-button-space { -width: 350px; -} - -/* -Theme: cvmDark -*/ - -.simple-keyboard.cvmDark .hg-button { -border-bottom: none; -background: rgba(0, 0, 0, 0.5); -color: white; -} - -.simple-keyboard.cvmDark .hg-button:active { -background: #1c4995; -color: white; -} - -#root .simple-keyboard.cvmDark + .simple-keyboard-preview { -background: #1c4995; -} - -/* -Theme: cvmDisabled -*/ -.simple-keyboard.cvmDisabled .hg-button { -border-bottom: none; -pointer-events: none; -background: gray; -color: white; -} - -/* End OSK */ - -#badPasswordAlert { - display: none; -} - -/* VM0 Blur */ -div[data-cvm-node=vm0b0t] { - img { - filter:blur(40px)!important; - } -} diff --git a/src/html/index.html b/src/html/index.html index e3a7d4d..6dc5fe6 100644 --- a/src/html/index.html +++ b/src/html/index.html @@ -4,8 +4,7 @@ CollabVM - - + @@ -17,95 +16,12 @@ - - -
-
-
+

diff --git a/src/ts/main.ts b/src/ts/main.ts index e2d549d..306c8c9 100644 --- a/src/ts/main.ts +++ b/src/ts/main.ts @@ -8,9 +8,7 @@ import Keyboard from 'simple-keyboard'; import { OSK_buttonToKeysym } from './keyboard'; import 'simple-keyboard/build/css/index.css'; import VoteStatus from './protocol/VoteStatus.js'; -import * as bootstrap from 'bootstrap'; import MuteState from './protocol/MuteState.js'; -import { Unsubscribe } from 'nanoevents'; import { I18nStringKey, TheI18n } from './i18n.js'; import { Format } from './format.js'; @@ -246,7 +244,7 @@ let expectedClose = false; let turn = -1; // Listed VMs const vms: VM[] = []; -const cards: HTMLDivElement[] = []; +const cards: HTMLLIElement[] = []; const users: { user: User; element: HTMLTableRowElement; @@ -282,22 +280,19 @@ async function multicollab(url: string) { // Add to the DOM for (let vm of list) { - let div = document.createElement('div'); - div.classList.add('col-sm-5', 'col-md-3'); - let card = document.createElement('div'); - card.classList.add('card', 'bg-dark', 'text-light'); + // can we have jsx please........ please... i hate thisssss + let div = document.createElement('li'); + + let card = document.createElement('a'); + card.classList.add('card'); card.setAttribute('data-cvm-node', vm.id); - card.addEventListener('click', async () => { - try { - await openVM(vm); - } catch (e) { - alert((e as Error).message); - } - }); - vm.thumbnail.classList.add('card-img-top'); + card.href = `#${vm.id}`; + + vm.thumbnail.classList.add('card-image'); let cardBody = document.createElement('div'); cardBody.classList.add('card-body'); let cardTitle = document.createElement('h5'); + cardTitle.classList.add('card-heading'); cardTitle.innerHTML = vm.displayName; let usersOnline = document.createElement('span'); usersOnline.innerHTML = `( ${online})`; @@ -315,8 +310,7 @@ async function openVM(vm: VM): Promise { // If there's an active VM it must be closed before opening another if (VM !== null) return; expectedClose = false; - // Set hash - location.hash = vm.id; + // Create the client VM = new CollabVMClient(vm.url); @@ -360,7 +354,7 @@ async function openVM(vm: VM): Promise { chatMessage('', `${vm.id}
`); let username = localStorage.getItem('username'); let connected = await VM.connect(vm.id, username); - elements.adminInputVMID.value = vm.id; + //elements.adminInputVMID.value = vm.id; w.VMName = vm.id; if (!connected) { // just give up @@ -368,7 +362,7 @@ async function openVM(vm: VM): Promise { throw new Error('Failed to connect to node'); } // Set the title - document.title = Format("{0} - {1}", vm.id, TheI18n.GetString(I18nStringKey.kGeneric_CollabVM)); + document.title = Format('{0} - {1}', vm.id, TheI18n.GetString(I18nStringKey.kGeneric_CollabVM)); // Append canvas elements.vmDisplay.appendChild(VM!.canvas); // Switch to the VM view @@ -388,7 +382,7 @@ function closeVM() { // Remove the canvas elements.vmDisplay.innerHTML = ''; // Switch to the VM list - elements.vmlist.style.display = 'block'; + elements.vmlist.style.display = ''; elements.vmview.style.display = 'none'; // Clear users users.splice(0, users.length); @@ -415,13 +409,7 @@ function closeVM() { elements.username.classList.add('text-light'); } -async function loadList() { - await Promise.all( - Config.ServerAddresses.map((url) => { - return multicollab(url); - }) - ); - +async function openHash() { // automatically join the vm that's in the url if it exists in the node list let v = vms.find((v) => v.id === window.location.hash.substring(1)); try { @@ -431,12 +419,22 @@ async function loadList() { } } +async function loadList() { + await Promise.all( + Config.ServerAddresses.map((url) => { + return multicollab(url); + }) + ); + + await openHash(); +} + function sortVMList() { cards.sort((a, b) => { return a.children[0].getAttribute('data-cvm-node')! > b.children[0].getAttribute('data-cvm-node')! ? 1 : -1; }); - elements.vmlist.children[0].innerHTML = ''; - cards.forEach((c) => elements.vmlist.children[0].appendChild(c)); + //elements.vmlist.children[0].innerHTML = ''; + cards.forEach((c) => elements.vmlist.appendChild(c)); } function sortUserList() { @@ -667,6 +665,8 @@ elements.voteYesBtn.addEventListener('click', () => VM?.vote(true)); elements.voteNoBtn.addEventListener('click', () => VM?.vote(false)); // Login let usernameClick = false; + +/* const loginModal = new bootstrap.Modal(elements.loginModal); elements.loginModal.addEventListener('shown.bs.modal', () => elements.adminPassword.focus()); elements.username.addEventListener('click', () => { @@ -687,7 +687,7 @@ function doLogin() { elements.adminPassword.value = ''; let u = VM?.on('login', () => { u!(); - loginModal.hide(); + //loginModal.hide(); elements.badPasswordAlert.style.display = 'none'; }); let _u = VM?.on('badpw', () => { @@ -696,6 +696,8 @@ function doLogin() { }); } +*/ + function onLogin(_rank: Rank, _perms: Permissions) { rank = _rank; perms = _perms; @@ -775,6 +777,7 @@ elements.forceVoteNoBtn.addEventListener('click', () => VM?.forceVote(false)); elements.forceVoteYesBtn.addEventListener('click', () => VM?.forceVote(true)); elements.indefTurnBtn.addEventListener('click', () => VM?.indefiniteTurn()); +/* async function sendQEMUCommand() { if (!elements.qemuMonitorInput.value) return; let cmd = elements.qemuMonitorInput.value; @@ -786,6 +789,7 @@ async function sendQEMUCommand() { } elements.qemuMonitorSendBtn.addEventListener('click', () => sendQEMUCommand()); elements.qemuMonitorInput.addEventListener('keypress', (e) => e.key === 'Enter' && sendQEMUCommand()); +*/ elements.osk.addEventListener('click', () => elements.oskContainer.classList.toggle('d-none')); @@ -834,6 +838,11 @@ w.cvmEvents = { }; w.VMName = null; +// could be a neat feature? +window.addEventListener('hashchange', async () => { + await openHash(); +}); + document.addEventListener('DOMContentLoaded', async () => { // Initalize the i18n system await TheI18n.Init(); @@ -843,6 +852,7 @@ document.addEventListener('DOMContentLoaded', async () => { // Load all VMs await loadList(); + /* // Welcome modal let noWelcomeModal = window.localStorage.getItem('no-welcome-modal'); if (noWelcomeModal !== '1') { @@ -857,4 +867,5 @@ document.addEventListener('DOMContentLoaded', async () => { welcomeModalDismissBtn.disabled = false; }, 5000); } + */ }); diff --git a/src/ts/modals/tmp_og_modals.html b/src/ts/modals/tmp_og_modals.html new file mode 100644 index 0000000..a076c25 --- /dev/null +++ b/src/ts/modals/tmp_og_modals.html @@ -0,0 +1,90 @@ + + + + + \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index c40a31e..d49c851 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,6 +14,11 @@ "target": "es2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ // "jsx": "preserve", /* Specify what JSX code is generated. */ + + // for later:tm: + //"jsx": "react-jsx", + //"jsxImportSource": "nano-jsx/esm", + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ diff --git a/yarn.lock b/yarn.lock index abdea45..3ce120d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1150,6 +1150,15 @@ "@parcel/utils" "2.12.0" react-refresh "^0.9.0" +"@parcel/transformer-sass@2.12.0": + version "2.12.0" + resolved "https://registry.yarnpkg.com/@parcel/transformer-sass/-/transformer-sass-2.12.0.tgz#9132ee78197db04baf51d3024a1bf3c35f1df5ef" + integrity sha512-xLLoSLPST+2AHJwFRLl4foArDjjy6P1RChP3TxMU2MVS1sbKGJnfFhFpHAacH8ASjuGtu5rbpfpHRZePlvoZxw== + dependencies: + "@parcel/plugin" "2.12.0" + "@parcel/source-map" "^2.1.1" + sass "^1.38.0" + "@parcel/transformer-svg@2.12.0": version "2.12.0" resolved "https://registry.yarnpkg.com/@parcel/transformer-svg/-/transformer-svg-2.12.0.tgz#0281e89bf0f438ec161c19b59a8a8978434a3621" @@ -1535,7 +1544,7 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -anymatch@^3.0.3: +anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -1627,16 +1636,16 @@ base-x@^3.0.8: dependencies: safe-buffer "^5.0.1" +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -bootstrap@^5.3.2: - version "5.3.3" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38" - integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1645,7 +1654,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1723,6 +1732,21 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +"chokidar@>=3.0.0 <4.0.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chrome-trace-event@^1.0.2, chrome-trace-event@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" @@ -2056,7 +2080,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2: +fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -2091,6 +2115,13 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -2166,6 +2197,11 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +immutable@^4.0.0: + version "4.3.5" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" + integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== + import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -2205,6 +2241,13 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.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" @@ -2227,7 +2270,7 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^4.0.3: +is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -2938,7 +2981,7 @@ node-releases@^2.0.14: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -3081,7 +3124,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -3174,6 +3217,13 @@ react-refresh@^0.9.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf" integrity sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ== +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + regenerator-runtime@^0.13.7: version "0.13.11" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" @@ -3225,6 +3275,15 @@ safe-buffer@^5.0.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +sass@^1.38.0: + version "1.72.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.72.0.tgz#5b9978943fcfb32b25a6a5acb102fc9dabbbf41c" + integrity sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -3269,6 +3328,11 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +"source-map-js@>=0.6.2 <2.0.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932"