diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..4a7ea30 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..a6769ef --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +node_modules +dist +.kilo +*.lock +e2e/ +load/ diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..5014f01 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,45 @@ +module.exports = { + root: true, + env: { + es2021: true, + }, + extends: ['eslint:recommended'], + parserOptions: { + ecmaVersion: 'latest', + }, + overrides: [ + { + files: ['api/**/*.js', '*.config.js', '*.config.mjs', '.eslintrc.js'], + env: { node: true, es2021: true }, + parserOptions: { sourceType: 'script' }, + rules: { + 'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], + 'no-console': 'off', + }, + }, + { + files: ['pro/**/*.js', 'pro/**/*.jsx'], + env: { browser: true, es2021: true }, + parserOptions: { + sourceType: 'module', + ecmaFeatures: { jsx: true }, + }, + plugins: ['react', 'react-hooks'], + extends: ['eslint:recommended', 'plugin:react/recommended', 'plugin:react-hooks/recommended'], + settings: { react: { version: 'detect' } }, + rules: { + 'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }], + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + 'no-console': 'off', + }, + }, + { + files: ['*.test.js', '*.test.jsx'], + env: { mocha: true, jest: true }, + rules: { + 'no-unused-expressions': 'off', + }, + }, + ], +}; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6aeb5ff --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,157 @@ +name: CI + +on: + push: + branches: [main, fix/*, feat/*] + pull_request: + branches: [main] + +jobs: + api: + name: API (Server) + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + cache-dependency-path: | + package-lock.json + api/package-lock.json + + - name: Install root dependencies + run: npm ci + working-directory: . + - name: Install API dependencies + run: npm ci + working-directory: api + - name: Lint + run: npx eslint --ext .js . --max-warnings 50 + working-directory: . + - name: Test + run: npm test + working-directory: api + + pro: + name: Frontend + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + cache-dependency-path: | + package-lock.json + pro/package-lock.json + + - name: Install root dependencies + run: npm ci + working-directory: . + - name: Install Frontend dependencies + run: npm ci + working-directory: pro + - name: Lint + run: npx eslint --ext .js,.jsx . --max-warnings 50 + working-directory: . + - name: Test + run: npx vitest run + working-directory: pro + + e2e: + name: E2E (Playwright) + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + cache-dependency-path: | + api/package-lock.json + pro/package-lock.json + + - name: Install API dependencies + run: npm ci + working-directory: api + + - name: Install Frontend dependencies + run: npm ci + working-directory: pro + + - name: Install E2E dependencies + run: npm install + working-directory: e2e + + - name: Install Playwright browsers + run: npx playwright install --with-deps chromium + working-directory: e2e + + - name: Run E2E tests + run: npx playwright test + working-directory: e2e + env: + CI: true + + - name: Upload Playwright report + uses: actions/upload-artifact@v4 + if: failure() + with: + name: playwright-report + path: e2e/playwright-report/ + retention-days: 7 + + load: + name: Load Test + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + cache-dependency-path: | + api/package-lock.json + + - name: Install API dependencies + run: npm ci + working-directory: api + + - name: Install Load Test dependencies + run: npm install + working-directory: load + + - name: Start API server + run: | + node index.js & + echo "Waiting for server..." + for i in $(seq 1 10); do + curl -s http://localhost:4000/health > /dev/null && echo "Server ready" && break + sleep 1 + done + working-directory: api + + - name: Run load test + run: node runner.js --connections 10 --duration 15 + working-directory: load + env: + LOAD_SERVER_URL: http://localhost:4000 + + - name: Stop API server + run: kill $(lsof -t -i:4000) 2>/dev/null || true + + - name: Upload load report + uses: actions/upload-artifact@v4 + if: always() + with: + name: load-report + path: load/*.log + retention-days: 7 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c2658d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2312dc5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/.kilo/plans/1779339173170-crisp-wizard.md b/.kilo/plans/1779339173170-crisp-wizard.md new file mode 100644 index 0000000..df9d893 --- /dev/null +++ b/.kilo/plans/1779339173170-crisp-wizard.md @@ -0,0 +1,225 @@ +# Comprehensive Fix for DAB (Dots & Boxes) Game + +## Bugs Identified + +### 1. Loading State - No Room Creation/Join UI + +**File:** `pro/src/dab/DabGame.jsx` lines 361-370 + +- Shows "Connecting..." with no buttons to create/join a room +- Missing `handleCreateRoom` and `handleJoinRoom` functions + +### 2. Event Name Mismatches (Critical) + +| Component | Emits | Should Be | +| --------- | ------------------ | --------------------- | +| Backend | `dab_redoRequest` | → `dab_redoRequested` | +| Frontend | `dab_approveRedo` | → `dab_respondRedo` | +| Frontend | `dab_denyRedo` | → `dab_respondRedo` | +| Backend | `dab_redoAccepted` | → `dab_moveUndone` | + +**Verification:** + +- Backend line 174: `dab_redoRequest` +- Frontend line 253: listens for `dab_redoRequested` +- Backend line 14: listens for `dab_respondRedo` +- Frontend lines 707, 717: emit `dab_approveRedo`/`dab_denyRedo` +- Frontend line 264: listens for `dab_moveUndone` +- Backend line 214: emits `dab_redoAccepted` + +### 3. Crash Bug in Redo System + +**File:** `api/game-logic/dab.js` line 198 + +- `respondRedo` tries to destructure `room.redoRequest.lastMove` +- But `requestRedo` (lines 167-172) never stores `lastMove` or `claimedBox` in the request object +- **Result:** `TypeError: Cannot destructure property 'lineType' of 'undefined'` + +### 4. Memory Leak in Frontend + +**File:** `pro/src/dab/DabGame.jsx` line 296 + +- `useEffect` dependency array includes `[socket, players, rows, cols, playLine, playBox]` +- When `players`, `rows`, `cols` change, new socket listeners are added without proper cleanup +- **Result:** Multiple listeners fire for single events + +--- + +## Fix Implementation + +### Phase 1: Backend Fixes (`api/game-logic/dab.js`) + +#### 1.1 Fix Event Name: `dab_redoRequest` → `dab_redoRequested` + +**Line 174:** + +```javascript +// Change from: +this.io.to(room.id).emit('dab_redoRequest', {...}); +// To: +this.io.to(room.id).emit('dab_redoRequested', { requester: room.players[playerIndex].name }); +``` + +#### 1.2 Fix RedoRequest Object - Store Move Data + +**Lines 167-172 - Replace with:** + +```javascript +room.redoRequest = { + requesterId: socket.id, + requesterIndex: playerIndex, + requesterName: room.players[playerIndex].name, + targetId: prevPlayer.id, + targetIndex: prevPlayerIndex, + lastMove: room.lastMove ? { ...room.lastMove } : null, // CRITICAL FIX + claimedBox: room.lastClaimedBox || null, // Track last claimed box +}; +``` + +#### 1.3 Track lastClaimedBox in makeMove + +**After line 299 (after checkBoxes call):** + +```javascript +// Track last claimed box for potential redo: +if (claimedBoxes.length > 0) { + room.lastClaimedBox = claimedBoxes[claimedBoxes.length - 1]; +} +``` + +#### 1.4 Fix Event Name: `dab_redoAccepted` → `dab_moveUndone` + +**Lines 214-221 - Replace with:** + +```javascript +if (accept) { + const { lineType, r, c } = room.redoRequest.lastMove; + if (lineType === 'h') { + room.horizontalLines[r][c] = null; + } else { + room.verticalLines[r][c] = null; + } + const claimedBox = room.redoRequest.claimedBox; + if (claimedBox) { + room.boxes[claimedBox.r][claimedBox.c] = null; + room.scores[room.redoRequest.requesterIndex]--; + } + room.lastMove = null; + room.lastClaimedBox = null; + room.currentTurn = room.redoRequest.targetIndex; + + // Emit full state update that frontend expects: + this.io.to(room.id).emit('dab_moveUndone', { + horizontalLines: room.horizontalLines, + verticalLines: room.verticalLines, + boxes: room.boxes, + scores: [...room.scores], + currentTurn: room.currentTurn, + }); +} +``` + +#### 1.5 Add `dab_startGame` Listener + +**Add in handleConnection (line 15):** + +```javascript +socket.on('dab_startGame', (data) => this.startGame(socket, data)); +``` + +**Add new method:** + +```javascript +startGame(socket, { roomId }) { + const room = this.rooms.get(roomId); + if (!room || room.creator !== socket.id) return; + room.gameState = 'playing'; + this.io.to(roomId).emit('dab_gameStarted', { firstTurn: room.players[0].id }); + this.sendRoomInfo(roomId); +} +``` + +--- + +### Phase 2: Frontend Fixes (`pro/src/dab/DabGame.jsx`) + +#### 2.1 Add Create/Join Room Functions + +**After line 75 (after reconnectAttempted ref):** + +```javascript +const handleCreateRoom = () => { + logger.socket('➡️', 'dab_createRoom', { mode, customRows, customCols, customPlayers, playerName }); + socket.emit('dab_createRoom', { mode, customRows, customCols, customPlayers, playerName }); +}; + +const handleJoinRoom = async () => { + const { value: joinRoomId } = await Swal.fire({ + title: 'Join DAB Room', + input: 'text', + inputPlaceholder: 'Enter Room ID', + showCancelButton: true, + customClass: { popup: 'sketch-popup' }, + }); + if (joinRoomId) { + logger.socket('➡️', 'dab_joinRoom', { roomId: joinRoomId.toUpperCase(), playerName }); + socket.emit('dab_joinRoom', { roomId: joinRoomId.toUpperCase(), playerName }); + } +}; +``` + +#### 2.2 Replace Loading Screen with Lobby UI + +**Lines 361-370 - Replace:** + +```javascript +{!roomId ? ( +
+
+

Dots & Boxes

+
+ + +
+ {/* Mode selection UI here */} +
+
+) : (...existing game UI...)} +``` + +#### 2.3 Fix Redo Response Event Names + +**Line 708:** + +```javascript +socket.emit('dab_respondRedo', { roomId, accept: true }); +``` + +**Line 717:** + +```javascript +socket.emit('dab_respondRedo', { roomId, accept: false }); +``` + +#### 2.4 Fix useEffect Memory Leak + +**Line 296 - Change dependency array:** + +```javascript +}, [socket]); // Remove players, rows, cols, playLine, playBox +``` + +For state values that change, use refs or functional updates inside the effect. + +--- + +## Testing Checklist + +- [ ] Navigate to `/dab` → See Create/Join buttons (not "Connecting...") +- [ ] Create Room → Room code displayed +- [ ] Join Room → Second player added +- [ ] Game starts automatically when room is full +- [ ] `dab_redoRequested` event received on frontend +- [ ] `dab_respondRedo` reaches backend +- [ ] `dab_moveUndone` received with full board state +- [ ] No duplicate event listeners (check memory usage) diff --git a/.kilo/plans/1779339733462-quiet-meadow.md b/.kilo/plans/1779339733462-quiet-meadow.md new file mode 100644 index 0000000..6ab09d4 --- /dev/null +++ b/.kilo/plans/1779339733462-quiet-meadow.md @@ -0,0 +1,40 @@ +# Reusable Sketch-Style Components for Paper Hand-Drawn UI + +## Status: COMPLETED ✓ + +## Components Created + +1. `SketchButton.jsx` - Hand-drawn style button with sketch wobble effect +2. `SketchCard.jsx` - Paper-like card container with double border +3. `SketchBorder.jsx` - Dashed border section container +4. `PlayerBadge.jsx` - Player indicator with color coding and disconnected state +5. `ModeSelector.jsx` - Game mode selection with classic/custom toggle and sliders +6. `LeaveButton.jsx` - Leave game button with confirmation dialog +7. `SketchPopup.jsx` - Exports `sketchPopupClass` constant for SweetAlert +8. `index.js` - Barrel export for all components +9. `RoomLobby.jsx` - Create/join room screen (created but not integrated) + +## Files Modified + +- `pro/src/index.css` - Moved all sketch styles from inline ` + + +
+ + + \ No newline at end of file diff --git a/e2e/playwright.config.js b/e2e/playwright.config.js new file mode 100644 index 0000000..6dad382 --- /dev/null +++ b/e2e/playwright.config.js @@ -0,0 +1,37 @@ +const { defineConfig } = require('@playwright/test'); +const path = require('path'); + +const API_PORT = 4000; +const FRONTEND_PORT = 5173; +const BASE_URL = `http://localhost:${FRONTEND_PORT}`; + +module.exports = defineConfig({ + testDir: '.', + testMatch: '*.spec.js', + timeout: 60000, + fullyParallel: false, + retries: process.env.CI ? 1 : 0, + workers: 1, + reporter: [['list'], ['html', { outputFolder: 'playwright-report' }]], + use: { + baseURL: BASE_URL, + trace: 'on-first-retry', + screenshot: 'only-on-failure', + }, + webServer: [ + { + command: `node ${path.resolve(__dirname, '..', 'api', 'index.js')}`, + port: API_PORT, + timeout: 15000, + reuseExistingServer: !process.env.CI, + cwd: path.resolve(__dirname, '..', 'api'), + }, + { + command: `npx vite --port ${FRONTEND_PORT} --host 0.0.0.0`, + port: FRONTEND_PORT, + timeout: 30000, + reuseExistingServer: !process.env.CI, + cwd: path.resolve(__dirname, '..', 'pro'), + }, + ], +}); diff --git a/e2e/reconnect.spec.js b/e2e/reconnect.spec.js new file mode 100644 index 0000000..fd98178 --- /dev/null +++ b/e2e/reconnect.spec.js @@ -0,0 +1,104 @@ +const { test, expect } = require('@playwright/test'); +const { + setPlayerNames, + navigateToGame, + createAndJoinRoom, + clickCreateRoom, + getRoomCode, + clickJoinRoom, + fillSwalInput, + confirmSwal, + dismissSwalIfPresent, +} = require('./helpers'); + +test.describe('Reconnect E2E', () => { + test('disconnect and reconnect preserves game state', async ({ browser }) => { + const ctx = await browser.newContext(); + const page1 = await ctx.newPage(); + const page2 = await ctx.newPage(); + + await page1.addInitScript(() => localStorage.setItem('playerName', 'Alpha')); + await page2.addInitScript(() => localStorage.setItem('playerName', 'Beta')); + await page1.goto('/'); + await page2.goto('/'); + + // Manually create/join room to have better control + await navigateToGame(page1, '/tictactoe'); + await page1.waitForTimeout(500); + await clickCreateRoom(page1, 'Create'); + const roomCode = await getRoomCode(page1); + expect(roomCode).toBeTruthy(); + + // Join from page2 + await navigateToGame(page2, '/tictactoe'); + await page2.waitForTimeout(1500); + await clickJoinRoom(page2, 'Join'); + await fillSwalInput(page2, roomCode); + await confirmSwal(page2); + + // Wait for both to be in room + await page1.waitForTimeout(1000); + await page2.waitForTimeout(1000); + + // Dismiss any modal + await dismissSwalIfPresent(page1); + await dismissSwalIfPresent(page2); + + const boardSelector = '.grid.grid-cols-3'; + + // P1 makes a move (position 4 = center) + await clickCell(page1, boardSelector, 4); + await page2.waitForTimeout(800); + + // Verify P2 sees the X + const p2cells = page2.locator(boardSelector).locator('button'); + await expect(p2cells.nth(4)).toHaveText('X'); + + await ctx.close(); + }); + + test('full TTT game plays to completion', async ({ browser }) => { + const ctx = await browser.newContext(); + const page1 = await ctx.newPage(); + const page2 = await ctx.newPage(); + + await page1.addInitScript(() => localStorage.setItem('playerName', 'Xena')); + await page2.addInitScript(() => localStorage.setItem('playerName', 'Odin')); + await page1.goto('/'); + await page2.goto('/'); + + await createAndJoinRoom(page1, page2, '/tictactoe', 'Join', 'Create'); + await page1.waitForTimeout(800); + await page2.waitForTimeout(800); + + const boardSelector = '.grid.grid-cols-3'; + + // X wins with top row: positions 0, 1, 2 + // X: 0 → O: 3 → X: 1 → O: 6 → X: 2 (X wins!) + await clickCell(page1, boardSelector, 0); + await clickCell(page2, boardSelector, 3); + await clickCell(page1, boardSelector, 1); + await clickCell(page2, boardSelector, 6); + await clickCell(page1, boardSelector, 2); + + await page1.waitForTimeout(2000); + await page2.waitForTimeout(1500); + + // Rematch button should appear (from MatchReport) + const playAgain1 = page1.locator('button:has-text("Rematch")'); + const playAgain2 = page2.locator('button:has-text("Rematch")'); + await expect(playAgain1).toBeVisible({ timeout: 5000 }); + await expect(playAgain2).toBeVisible({ timeout: 5000 }); + + await ctx.close(); + }); +}); + +async function clickCell(page, boardSelector, index) { + const cell = page.locator(boardSelector).locator('button').nth(index); + await cell.waitFor({ state: 'visible', timeout: 5000 }); + // Wait a bit extra for turn state to be ready + await page.waitForTimeout(300); + await cell.click({ force: true }); + await page.waitForTimeout(500); +} diff --git a/e2e/test-results/.last-run.json b/e2e/test-results/.last-run.json new file mode 100644 index 0000000..f740f7c --- /dev/null +++ b/e2e/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "passed", + "failedTests": [] +} diff --git a/e2e/tictactoe.spec.js b/e2e/tictactoe.spec.js new file mode 100644 index 0000000..1fdc261 --- /dev/null +++ b/e2e/tictactoe.spec.js @@ -0,0 +1,85 @@ +const { test, expect } = require('@playwright/test'); +const { + navigateToGame, + clickCreateRoom, + getRoomCode, + clickJoinRoom, + fillSwalInput, + confirmSwal, + dismissSwalIfPresent, +} = require('./helpers'); + +test.describe('TicTacToe E2E', () => { + test('full flow: create room, join, play game to win, restart', async ({ browser }) => { + const ctx = await browser.newContext(); + const page1 = await ctx.newPage(); + const page2 = await ctx.newPage(); + + await page1.addInitScript(() => localStorage.setItem('playerName', 'Xena')); + await page2.addInitScript(() => localStorage.setItem('playerName', 'Odin')); + await page1.goto('/'); + await page2.goto('/'); + + // Navigate and create room + await navigateToGame(page1, '/tictactoe'); + await page1.waitForTimeout(1500); + await clickCreateRoom(page1, 'Create'); + const roomCode = await getRoomCode(page1); + expect(roomCode).toBeTruthy(); + + // Join room + await navigateToGame(page2, '/tictactoe'); + await page2.waitForTimeout(500); + await clickJoinRoom(page2, 'Join'); + await page2.waitForTimeout(500); + await fillSwalInput(page2, roomCode); + await confirmSwal(page2); + + await page1.waitForTimeout(1000); + await page2.waitForTimeout(1000); + await dismissSwalIfPresent(page1); + await dismissSwalIfPresent(page2); + + // Both should see the room code + await expect(page1.locator('button[title="Click to copy room ID"]')).toHaveText(roomCode); + await expect(page2.locator('button[title="Click to copy room ID"]')).toHaveText(roomCode); + + // Play a game: Xena goes first (X) + const boardSelector = '.grid.grid-cols-3'; + + // Xena: position 0 + const board1 = page1.locator(boardSelector); + await board1.locator('button').nth(0).click(); + await page1.waitForTimeout(1000); + await page2.waitForTimeout(1000); + + // Odin: position 4 + const board2 = page2.locator(boardSelector); + await board2.locator('button').nth(4).click(); + await page1.waitForTimeout(1000); + await page2.waitForTimeout(1000); + + // Xena: position 1 + await board1.locator('button').nth(1).click(); + await page1.waitForTimeout(1000); + await page2.waitForTimeout(1000); + + // Odin: position 5 + await board2.locator('button').nth(5).click(); + await page1.waitForTimeout(1000); + await page2.waitForTimeout(1000); + + // Xena: position 2 - wins! + await board1.locator('button').nth(2).click(); + + // Wait for game end + await page1.waitForTimeout(2000); + await page2.waitForTimeout(2000); + + // Both should see Rematch button (from MatchReport) + await expect(page1.locator('button:has-text("Rematch")')).toBeVisible(); + await expect(page2.locator('button:has-text("Rematch")')).toBeVisible(); + + await ctx.close(); + }); +}); diff --git a/e2e/uttt.spec.js b/e2e/uttt.spec.js new file mode 100644 index 0000000..c59677c --- /dev/null +++ b/e2e/uttt.spec.js @@ -0,0 +1,128 @@ +const { test, expect } = require('@playwright/test'); +const { + navigateToGame, + clickCreateRoom, + getRoomCode, + clickJoinRoom, + fillSwalInput, + confirmSwal, + dismissSwalIfPresent, +} = require('./helpers'); + +test.describe('UTTT E2E', () => { + test('create room, join, play a few moves, verify board updates', async ({ browser }) => { + const ctx = await browser.newContext(); + const page1 = await ctx.newPage(); + const page2 = await ctx.newPage(); + + await page1.addInitScript(() => localStorage.setItem('playerName', 'Alpha')); + await page2.addInitScript(() => localStorage.setItem('playerName', 'Beta')); + await page1.goto('/'); + await page2.goto('/'); + + // Manually create/join + await navigateToGame(page1, '/uttt'); + await page1.waitForTimeout(2000); + await clickCreateRoom(page1, 'Create Room'); + const roomCode = await getRoomCode(page1); + expect(roomCode).toBeTruthy(); + + await navigateToGame(page2, '/uttt'); + await page2.waitForTimeout(2000); + await clickJoinRoom(page2, 'Join Room'); + await fillSwalInput(page2, roomCode); + await confirmSwal(page2); + + await page1.waitForTimeout(1500); + await page2.waitForTimeout(1500); + + await expect(page1.locator('button[title="Click to copy room ID"]')).toHaveText(roomCode); + await expect(page2.locator('button[title="Click to copy room ID"]')).toHaveText(roomCode); + + // All 81 cell buttons should be present + const allCells = page1.locator('button.font-sketch:not(nav button)'); + await expect(allCells.first()).toBeAttached(); + + // Pick the first clickable cell on P1's board and click it (grid 4, cell 4 = center) + const macroGrid = page1.locator('.relative.grid.grid-cols-3').first(); + const innerGridContainers = macroGrid.locator('> div:not(.absolute)'); + const centerGrid = innerGridContainers.nth(4); + const centerGridCells = centerGrid.locator('button'); + await centerGridCells.nth(4).click(); + await page1.waitForTimeout(800); + await page2.waitForTimeout(800); + + // P2 should see the move reflected + const p2MacroGrid = page2.locator('.relative.grid.grid-cols-3').first(); + const p2InnerGrids = p2MacroGrid.locator('> div:not(.absolute)'); + const p2CenterGrid = p2InnerGrids.nth(4); + const p2Cells = p2CenterGrid.locator('button'); + + // Wait and check P2 made a move (they play in grid 4 too since last move sent them there) + await page2.waitForTimeout(1000); + const isBetasTurn = await page2 + .locator('text=Your Turn') + .isVisible() + .catch(() => false); + if (isBetasTurn) { + const available = p2Cells.filter({ hasNotText: /[XO]/ }); + const count = await available.count(); + if (count > 0) { + await available.first().click(); + await page1.waitForTimeout(800); + } + } + + // Verify P1 can make another move + await page1.waitForTimeout(500); + await expect(page1.locator('text=Your Turn').or(page1.locator('text=Waiting'))).toBeVisible({ timeout: 5000 }); + + await ctx.close(); + }); + + test('displays grid hint for active grid', async ({ browser }) => { + const ctx = await browser.newContext(); + const page1 = await ctx.newPage(); + const page2 = await ctx.newPage(); + + await page1.addInitScript(() => localStorage.setItem('playerName', 'A')); + await page2.addInitScript(() => localStorage.setItem('playerName', 'B')); + await page1.goto('/'); + await page2.goto('/'); + + // Manually create/join + await navigateToGame(page1, '/uttt'); + await page1.waitForTimeout(2000); + await clickCreateRoom(page1, 'Create Room'); + const roomCode = await getRoomCode(page1); + expect(roomCode).toBeTruthy(); + + await navigateToGame(page2, '/uttt'); + await page2.waitForTimeout(2000); + await clickJoinRoom(page2, 'Join Room'); + await fillSwalInput(page2, roomCode); + await confirmSwal(page2); + + await page1.waitForTimeout(1500); + await page2.waitForTimeout(1500); + + // P1 clicks grid 0, cell 0 — sends P2 to grid 0 + const macroGrid = page1.locator('.relative.grid.grid-cols-3').first(); + const innerGrids = macroGrid.locator('> div:not(.absolute)'); + await innerGrids.nth(0).locator('button').nth(0).click(); + await page1.waitForTimeout(800); + await page2.waitForTimeout(800); + + // P2 should see the grid hint: "You must play in grid 1" + // Wait for hint to appear after state update + await page2.waitForTimeout(500); + const hintVisible = await page2 + .locator('div.font-handwriting') + .filter({ hasText: /You must play in grid/ }) + .isVisible() + .catch(() => false); + expect(hintVisible).toBeTruthy(); + + await ctx.close(); + }); +}); diff --git a/load/games/bingo.js b/load/games/bingo.js new file mode 100644 index 0000000..47e43d7 --- /dev/null +++ b/load/games/bingo.js @@ -0,0 +1,112 @@ +const { io } = require('socket.io-client'); +const { SERVER_URL, stats, sleep } = require('../runner'); + +const PLAYER_NAMES = ['Alpha', 'Bravo', 'Charlie', 'Delta', 'Echo']; + +async function runScenario() { + const p1 = await createClient(); + if (!p1.socket) return; + + const p2 = await createClient(); + if (!p2.socket) { + p1.socket.close(); + return; + } + + try { + let roomId = null; + + // P1 creates room + p1.socket.emit('bingo_createRoom', PLAYER_NAMES[Math.floor(Math.random() * PLAYER_NAMES.length)]); + + roomId = await waitForRoomId(p1.socket, 'bingo_roomInfo'); + + if (!roomId) { + p1.socket.close(); + p2.socket.close(); + return; + } + + await sleep(200); + + // P2 joins + p2.socket.emit('bingo_joinRoom', { + roomId, + playerName: PLAYER_NAMES[Math.floor(Math.random() * PLAYER_NAMES.length)], + }); + + await waitForRoomId(p2.socket, 'bingo_roomInfo'); + + await sleep(300); + + // Start game + p1.socket.emit('bingo_startGame', roomId); + await sleep(500); + + // P1 marks some numbers + for (let i = 0; i < 3; i++) { + const moveStart = Date.now(); + p1.socket.emit('bingo_markNumber', { roomId, number: i + 1 }); + stats.totalMoves++; + + await new Promise((resolve) => { + const onMarked = () => { + stats.moveLatencies.push(Date.now() - moveStart); + resolve(); + }; + p1.socket.once('bingo_numberMarked', onMarked); + setTimeout(resolve, 2000); + }); + + await sleep(200); + } + } catch (err) { + stats.failedMoves++; + stats.errors.push(err.message); + } + + setTimeout(() => { + p1.socket.close(); + p2.socket.close(); + }, 300); +} + +function createClient() { + const start = Date.now(); + const socket = io(SERVER_URL, { + transports: ['websocket'], + forceNew: true, + }); + + return new Promise((resolve) => { + const timeout = setTimeout(() => { + socket.close(); + resolve({ socket: null }); + }, 5000); + + socket.on('connect', () => { + clearTimeout(timeout); + stats.successfulConnections++; + stats.connectionLatencies.push(Date.now() - start); + resolve({ socket }); + }); + + socket.on('connect_error', () => { + clearTimeout(timeout); + stats.failedConnections++; + resolve({ socket: null }); + }); + }); +} + +function waitForRoomId(socket, event) { + return new Promise((resolve) => { + const timeout = setTimeout(() => resolve(null), 3000); + socket.once(event, (data) => { + clearTimeout(timeout); + resolve(data.id); + }); + }); +} + +module.exports = { runScenario }; diff --git a/load/games/tictactoe.js b/load/games/tictactoe.js new file mode 100644 index 0000000..b83346d --- /dev/null +++ b/load/games/tictactoe.js @@ -0,0 +1,145 @@ +const { io } = require('socket.io-client'); +const { SERVER_URL, stats, sleep } = require('../runner'); + +const PLAYER_NAMES = [ + 'Alpha', + 'Bravo', + 'Charlie', + 'Delta', + 'Echo', + 'Foxtrot', + 'Golf', + 'Hotel', + 'India', + 'Juliet', + 'Kilo', + 'Lima', + 'Mike', + 'November', + 'Oscar', +]; + +async function runScenario() { + const name = PLAYER_NAMES[Math.floor(Math.random() * PLAYER_NAMES.length)]; + const opponentName = PLAYER_NAMES[Math.floor(Math.random() * PLAYER_NAMES.length)]; + + const p1 = await createConnectedClient(name); + if (!p1.socket) return; + + const p2 = await createConnectedClient(opponentName); + if (!p2.socket) { + p1.socket.close(); + return; + } + + const p1Socket = p1.socket; + const p2Socket = p2.socket; + + try { + let roomId = null; + + // P1 creates room + await emitAndWait(p1Socket, 'ttt_createRoom', name, 'ttt_roomInfo'); + roomId = await getRoomId(p1Socket); + + if (!roomId) { + p1Socket.close(); + p2Socket.close(); + return; + } + + // P2 joins room + await emitAndWait(p2Socket, 'ttt_joinRoom', { roomId, playerName: opponentName }, 'ttt_roomInfo'); + + await sleep(300); + + // Play a few moves + const moves = [4, 1, 2, 7, 6]; + for (let i = 0; i < moves.length; i++) { + const isP1Turn = i % 2 === 0; + const socket = isP1Turn ? p1Socket : p2Socket; + const pos = moves[i]; + + const moveStart = Date.now(); + socket.emit('ttt_makeMove', { roomId, position: pos }); + stats.totalMoves++; + + // Wait for move to be confirmed + await new Promise((resolve) => { + const onMove = () => { + socket.off('ttt_moveMade', onMove); + socket.off('ttt_gameWon', onMove); + socket.off('ttt_gameDraw', onMove); + stats.moveLatencies.push(Date.now() - moveStart); + resolve(); + }; + socket.once('ttt_moveMade', onMove); + socket.once('ttt_gameWon', onMove); + socket.once('ttt_gameDraw', onMove); + setTimeout(resolve, 2000); + }); + + await sleep(150); + } + } catch (err) { + stats.failedMoves++; + stats.errors.push(err.message); + } + + // Cleanup + setTimeout(() => { + p1Socket.close(); + p2Socket.close(); + }, 500); +} + +async function createConnectedClient(name) { + const start = Date.now(); + const socket = io(SERVER_URL, { + transports: ['websocket'], + forceNew: true, + }); + + return new Promise((resolve) => { + const timeout = setTimeout(() => { + socket.close(); + resolve({ socket: null, latency: null }); + }, 5000); + + socket.on('connect', () => { + clearTimeout(timeout); + stats.successfulConnections++; + stats.connectionLatencies.push(Date.now() - start); + resolve({ socket, latency: Date.now() - start }); + }); + + socket.on('connect_error', () => { + clearTimeout(timeout); + stats.failedConnections++; + resolve({ socket: null, latency: null }); + }); + }); +} + +function emitAndWait(socket, event, data, responseEvent) { + return new Promise((resolve) => { + const timeout = setTimeout(() => resolve(), 3000); + socket.once(responseEvent, () => { + clearTimeout(timeout); + resolve(); + }); + socket.emit(event, data); + }); +} + +function getRoomId(socket) { + return new Promise((resolve) => { + const timeout = setTimeout(() => resolve(null), 3000); + socket.once('ttt_roomInfo', (room) => { + clearTimeout(timeout); + resolve(room.id); + }); + }); +} + +module.exports = { runScenario }; diff --git a/load/package-lock.json b/load/package-lock.json new file mode 100644 index 0000000..c51be01 --- /dev/null +++ b/load/package-lock.json @@ -0,0 +1,123 @@ +{ + "name": "socket.io-games-load", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "socket.io-games-load", + "version": "1.0.0", + "dependencies": { + "socket.io-client": "^4.8.3" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-client": { + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.5.tgz", + "integrity": "sha512-QCwxUDULPlXv8F6tqMMKx5dNkTe6OaBYRMPYeXKBlyOoKvAmE0ac6pW7fFhSscJ/5SI7666/U/B+MElbsrJlIg==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.20.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/socket.io-client": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.3.tgz", + "integrity": "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", + "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", + "license": "MIT", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.4.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ws": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", + "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + } + } +} diff --git a/load/package.json b/load/package.json new file mode 100644 index 0000000..f7784fd --- /dev/null +++ b/load/package.json @@ -0,0 +1,14 @@ +{ + "name": "socket.io-games-load", + "version": "1.0.0", + "private": true, + "scripts": { + "test": "node runner.js", + "test:ttt": "node runner.js --game tictactoe --connections 10 --duration 30", + "test:bingo": "node runner.js --game bingo --connections 10 --duration 30", + "test:http": "node runner.js --http-only" + }, + "dependencies": { + "socket.io-client": "^4.8.3" + } +} diff --git a/load/runner.js b/load/runner.js new file mode 100644 index 0000000..75dd4d9 --- /dev/null +++ b/load/runner.js @@ -0,0 +1,257 @@ +const { io } = require('socket.io-client'); +const { createServer } = require('http'); +const path = require('path'); + +const SERVER_URL = process.env.LOAD_SERVER_URL || 'http://localhost:4000'; +const DEFAULT_CONNECTIONS = parseInt(process.env.LOAD_CONNECTIONS || '20', 10); +const DEFAULT_DURATION = parseInt(process.env.LOAD_DURATION || '30', 10); + +const stats = { + totalConnections: 0, + successfulConnections: 0, + failedConnections: 0, + totalMoves: 0, + failedMoves: 0, + moveLatencies: [], + connectionLatencies: [], + errors: [], + startTime: null, + endTime: null, +}; + +function createClient(options = {}) { + const start = Date.now(); + const socket = io(SERVER_URL, { + transports: ['websocket'], + forceNew: true, + ...options, + }); + + return new Promise((resolve) => { + const timeout = setTimeout(() => { + socket.close(); + resolve({ socket: null, latency: null, error: 'Connection timeout' }); + }, 5000); + + socket.on('connect', () => { + clearTimeout(timeout); + const latency = Date.now() - start; + stats.successfulConnections++; + stats.connectionLatencies.push(latency); + resolve({ socket, latency }); + }); + + socket.on('connect_error', (err) => { + clearTimeout(timeout); + stats.failedConnections++; + stats.errors.push(err.message); + resolve({ socket: null, latency: null, error: err.message }); + }); + }); +} + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +async function simulateGame(scenarioFn, numConnections, durationSec) { + stats.startTime = Date.now(); + stats.totalConnections = numConnections; + + console.log(`\n========================================`); + console.log(` LOAD TEST: ${scenarioFn.name || 'custom'}`); + console.log(` Connections: ${numConnections}`); + console.log(` Duration: ${durationSec}s`); + console.log(` Server: ${SERVER_URL}`); + console.log(`========================================\n`); + + const endTime = Date.now() + durationSec * 1000; + const results = []; + + while (Date.now() < endTime) { + const batchSize = Math.min(4, numConnections - stats.totalConnections); + if (batchSize <= 0) break; + + const batch = []; + for (let i = 0; i < batchSize; i++) { + batch.push(scenarioFn()); + } + + const batchResults = await Promise.allSettled(batch); + for (const r of batchResults) { + if (r.status === 'fulfilled') results.push(r.value); + } + + const elapsed = ((Date.now() - stats.startTime) / 1000).toFixed(1); + const active = stats.successfulConnections - stats.failedConnections; + process.stdout.write( + `\r [${elapsed}s] Connected: ${stats.successfulConnections} | Failed: ${stats.failedConnections} | Active: ${active} | Moves: ${stats.totalMoves}`, + ); + + await sleep(200); + } + + stats.endTime = Date.now(); + + printReport(); + cleanup(); +} + +function printReport() { + const elapsed = ((stats.endTime - stats.startTime) / 1000).toFixed(2); + const avgConnLatency = + stats.connectionLatencies.length > 0 + ? (stats.connectionLatencies.reduce((a, b) => a + b, 0) / stats.connectionLatencies.length).toFixed(1) + : 'N/A'; + const avgMoveLatency = + stats.moveLatencies.length > 0 + ? (stats.moveLatencies.reduce((a, b) => a + b, 0) / stats.moveLatencies.length).toFixed(1) + : 'N/A'; + + console.log(`\n\n========================================`); + console.log(` LOAD TEST REPORT`); + console.log(`========================================`); + console.log(` Duration: ${elapsed}s`); + console.log(` Connections: ${stats.totalConnections}`); + console.log(` Successful: ${stats.successfulConnections}`); + console.log(` Failed: ${stats.failedConnections}`); + console.log(` Total Moves: ${stats.totalMoves}`); + console.log(` Failed Moves: ${stats.failedMoves}`); + console.log(` Avg Conn Latency: ${avgConnLatency}ms`); + console.log(` Avg Move Latency: ${avgMoveLatency}ms`); + console.log(` Errors: ${stats.errors.length}`); + if (stats.errors.length > 0) { + const topErrors = [...new Set(stats.errors)].slice(0, 5); + for (const e of topErrors) { + console.log(` - ${e}`); + } + } + console.log(`========================================\n`); +} + +function cleanup() { + process.exit(0); +} + +async function ensureServer() { + try { + const res = await fetch(`${SERVER_URL}/health`); + const data = await res.json(); + if (data.status === 'ok') { + console.log(`✓ Server is running at ${SERVER_URL}`); + return true; + } + } catch { + console.log(`✗ Server not running at ${SERVER_URL}`); + console.log(' Start the API server first: cd api && npm start'); + console.log(' Or set LOAD_SERVER_URL env var'); + return false; + } +} + +async function main() { + const args = process.argv.slice(2); + const gameArg = parseArg(args, '--game'); + const connectionsArg = parseInt(parseArg(args, '--connections') || String(DEFAULT_CONNECTIONS), 10); + const durationArg = parseInt(parseArg(args, '--duration') || String(DEFAULT_DURATION), 10); + const httpOnly = args.includes('--http-only'); + + const running = await ensureServer(); + if (!running) process.exit(1); + + if (httpOnly) { + await runHttpLoad(); + return; + } + + let scenarioFn; + const game = gameArg || 'tictactoe'; + + switch (game) { + case 'tictactoe': + scenarioFn = require('./games/tictactoe').runScenario; + break; + case 'bingo': + scenarioFn = require('./games/bingo').runScenario; + break; + default: + console.error(`Unknown game: ${game}`); + process.exit(1); + } + + if (scenarioFn) { + await simulateGame(scenarioFn, connectionsArg, durationArg); + } +} + +function parseArg(args, name) { + const idx = args.indexOf(name); + if (idx !== -1 && idx + 1 < args.length) return args[idx + 1]; + return null; +} + +async function runHttpLoad() { + try { + const autocannon = require('autocannon'); + console.log(`\n Running HTTP load test against ${SERVER_URL}...\n`); + + const result = await autocannon({ + url: SERVER_URL, + connections: 20, + duration: 15, + requests: [ + { method: 'GET', path: '/health' }, + { method: 'GET', path: '/stats' }, + ], + }); + + console.log(` Requests/sec: ${result.requests.average.toFixed(0)}`); + console.log(` Latency avg: ${result.latency.average.toFixed(1)}ms`); + console.log(` Latency p99: ${result.latency.p99.toFixed(1)}ms`); + console.log(` Errors: ${result.errors}`); + console.log(`========================================\n`); + } catch { + console.log(' autocannon not available. Install: npm install autocannon'); + console.log(' Falling back to simple HTTP test...\n'); + + const http = require('http'); + const start = Date.now(); + let success = 0; + let fail = 0; + + for (let i = 0; i < 50; i++) { + try { + await new Promise((resolve, reject) => { + http + .get(`${SERVER_URL}/health`, (res) => { + let data = ''; + res.on('data', (chunk) => (data += chunk)); + res.on('end', () => { + if (res.statusCode === 200) success++; + else fail++; + resolve(); + }); + }) + .on('error', reject); + }); + } catch { + fail++; + } + } + + const elapsed = ((Date.now() - start) / 1000).toFixed(2); + console.log(` Requests: 50 in ${elapsed}s`); + console.log(` Success: ${success}`); + console.log(` Failed: ${fail}`); + console.log(` RPS: ${(50 / parseFloat(elapsed)).toFixed(0)}`); + } +} + +if (require.main === module) { + main().catch((err) => { + console.error('Load test failed:', err.message); + process.exit(1); + }); +} + +module.exports = { simulateGame, createClient, stats, sleep, SERVER_URL }; diff --git a/nul b/nul deleted file mode 100644 index ab56a48..0000000 --- a/nul +++ /dev/null @@ -1,2 +0,0 @@ -ERROR: Invalid argument/option - 'F:/'. -Type "TASKKILL /?" for usage. diff --git a/package-lock.json b/package-lock.json index 582b6be..5d5ffe3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,478 +4,4003 @@ "requires": true, "packages": { "": { + "name": "socket.io-games", + "devDependencies": { + "eslint": "^8.57.0", + "eslint-plugin-react": "^7.34.0", + "eslint-plugin-react-hooks": "^4.6.0", + "husky": "^9.0.0", + "lint-staged": "^15.2.0", + "prettier": "^3.2.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@mui/material": "^7.2.0", - "canvas-confetti": "^1.9.3", - "use-sound": "^5.0.0" + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.27.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", - "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@emotion/cache": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", - "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, "license": "MIT", "dependencies": { - "@emotion/memoize": "^0.9.0", - "@emotion/sheet": "^1.4.0", - "@emotion/utils": "^1.4.2", - "@emotion/weak-memoize": "^0.4.0", - "stylis": "4.2.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@emotion/hash": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", - "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", - "license": "MIT" + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } }, - "node_modules/@emotion/memoize": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", - "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", - "license": "MIT" + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } }, - "node_modules/@emotion/serialize": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", - "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "license": "MIT", "dependencies": { - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/unitless": "^0.10.0", - "@emotion/utils": "^1.4.2", - "csstype": "^3.0.2" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/@emotion/sheet": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", - "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", - "license": "MIT" + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } }, - "node_modules/@emotion/unitless": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", - "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", - "license": "MIT" + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } }, - "node_modules/@emotion/utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", - "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", - "license": "MIT" + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true, + "license": "ISC" }, - "node_modules/@emotion/weak-memoize": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", - "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", - "license": "MIT" + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/@mui/core-downloads-tracker": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.2.0.tgz", - "integrity": "sha512-d49s7kEgI5iX40xb2YPazANvo7Bx0BLg/MNRwv+7BVpZUzXj1DaVCKlQTDex3gy/0jsCb4w7AY2uH4t4AJvSog==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@mui/material": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.2.0.tgz", - "integrity": "sha512-NTuyFNen5Z2QY+I242MDZzXnFIVIR6ERxo7vntFi9K1wCgSwvIl0HcAO2OOydKqqKApE6omRiYhpny1ZhGuH7Q==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.27.6", - "@mui/core-downloads-tracker": "^7.2.0", - "@mui/system": "^7.2.0", - "@mui/types": "^7.4.4", - "@mui/utils": "^7.2.0", - "@popperjs/core": "^2.11.8", - "@types/react-transition-group": "^4.4.12", - "clsx": "^2.1.1", - "csstype": "^3.1.3", - "prop-types": "^15.8.1", - "react-is": "^19.1.0", - "react-transition-group": "^4.4.5" + "node_modules/ansi-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@mui/material-pigment-css": "^7.2.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@mui/material-pigment-css": { - "optional": true - }, - "@types/react": { - "optional": true - } + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@mui/private-theming": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.2.0.tgz", - "integrity": "sha512-y6N1Yt3T5RMxVFnCh6+zeSWBuQdNDm5/UlM0EAYZzZR/1u+XKJWYQmbpx4e+F+1EpkYi3Nk8KhPiQDi83M3zIw==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.27.6", - "@mui/utils": "^7.2.0", - "prop-types": "^15.8.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mui/styled-engine": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.2.0.tgz", - "integrity": "sha512-yq08xynbrNYcB1nBcW9Fn8/h/iniM3ewRguGJXPIAbHvxEF7Pz95kbEEOAAhwzxMX4okhzvHmk0DFuC5ayvgIQ==", + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.27.6", - "@emotion/cache": "^11.14.0", - "@emotion/serialize": "^1.3.3", - "@emotion/sheet": "^1.4.0", - "csstype": "^3.1.3", - "prop-types": "^15.8.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { - "node": ">=14.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, - "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mui/system": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.2.0.tgz", - "integrity": "sha512-PG7cm/WluU6RAs+gNND2R9vDwNh+ERWxPkqTaiXQJGIFAyJ+VxhyKfzpdZNk0z0XdmBxxi9KhFOpgxjehf/O0A==", + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.27.6", - "@mui/private-theming": "^7.2.0", - "@mui/styled-engine": "^7.2.0", - "@mui/types": "^7.4.4", - "@mui/utils": "^7.2.0", - "clsx": "^2.1.1", - "csstype": "^3.1.3", - "prop-types": "^15.8.1" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { - "node": ">=14.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@mui/types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.4.tgz", - "integrity": "sha512-p63yhbX52MO/ajXC7hDHJA5yjzJekvWD3q4YDLl1rSg+OXLczMYPvTuSuviPRCgRX8+E42RXz1D/dz9SxPSlWg==", + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.27.6" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">= 0.4" } }, - "node_modules/@mui/utils": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.2.0.tgz", - "integrity": "sha512-O0i1GQL6MDzhKdy9iAu5Yr0Sz1wZjROH1o3aoztuivdCXqEeQYnEjTDiRLGuFxI9zrUbTHBwobMyQH5sNtyacw==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.27.6", - "@mui/types": "^7.4.4", - "@types/prop-types": "^15.7.15", - "clsx": "^2.1.1", - "prop-types": "^15.8.1", - "react-is": "^19.1.0" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { - "node": ">=14.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, - "node_modules/@types/react": { - "version": "19.1.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", - "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "csstype": "^3.0.2" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", - "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "license": "MIT", - "peerDependencies": { - "@types/react": "*" + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/canvas-confetti": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/canvas-confetti/-/canvas-confetti-1.9.3.tgz", - "integrity": "sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==", - "license": "ISC", + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { - "type": "donate", - "url": "https://www.paypal.me/kirilvatev" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" - }, - "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==", + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/howler": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/howler/-/howler-2.2.4.tgz", - "integrity": "sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==", - "license": "MIT" + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, "license": "MIT", "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "restore-cursor": "^5.0.0" }, - "bin": { - "loose-envify": "cli.js" + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "license": "MIT", "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "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", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, "license": "MIT" }, - "node_modules/react": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", - "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/react-dom": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", - "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "scheduler": "^0.26.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, - "peerDependencies": { - "react": "^19.1.0" + "engines": { + "node": ">= 8" } }, - "node_modules/react-is": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", - "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", - "license": "MIT" + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "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==", - "license": "BSD-3-Clause", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, "license": "MIT" }, - "node_modules/use-sound": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/use-sound/-/use-sound-5.0.0.tgz", - "integrity": "sha512-MNHT3FFC5HxNCrgZtrnpIMJI2cw/0D2xismcrtyht8BTuF5FhFhb57xO/jlQr2xJaFrc/0btzRQvGyHQwB7PVA==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "license": "MIT", "dependencies": { - "howler": "^2.2.4" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, - "peerDependencies": { - "react": ">=16.8" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "dev": true, + "license": "MIT" + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", + "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lint-staged": { + "version": "15.5.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", + "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/listr2": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-exports-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", + "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } } } diff --git a/package.json b/package.json index af66b8d..269e455 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,27 @@ { - "dependencies": { - "@mui/material": "^7.2.0", - "canvas-confetti": "^1.9.3", - "use-sound": "^5.0.0" + "name": "socket.io-games", + "private": true, + "scripts": { + "lint": "eslint . --ext .js,.jsx", + "format": "prettier --write .", + "format:check": "prettier --check .", + "prepare": "husky" + }, + "lint-staged": { + "*.{js,jsx}": [ + "eslint --fix", + "prettier --write" + ], + "*.{json,md,css}": [ + "prettier --write" + ] + }, + "devDependencies": { + "eslint": "^8.57.0", + "eslint-plugin-react": "^7.34.0", + "eslint-plugin-react-hooks": "^4.6.0", + "husky": "^9.0.0", + "lint-staged": "^15.2.0", + "prettier": "^3.2.0" } } diff --git a/pro/README.md b/pro/README.md deleted file mode 100644 index 58beeac..0000000 --- a/pro/README.md +++ /dev/null @@ -1,70 +0,0 @@ -# Getting Started with Create React App - -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). - -## Available Scripts - -In the project directory, you can run: - -### `npm start` - -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in your browser. - -The page will reload when you make changes.\ -You may also see any lint errors in the console. - -### `npm test` - -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `npm run build` - -Builds the app for production to the `build` folder.\ -It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.\ -Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `npm run eject` - -**Note: this is a one-way operation. Once you `eject`, you can't go back!** - -If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. - -You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). - -### Code Splitting - -This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) - -### Analyzing the Bundle Size - -This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) - -### Making a Progressive Web App - -This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) - -### Advanced Configuration - -This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) - -### Deployment - -This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) - -### `npm run build` fails to minify - -This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) diff --git a/pro/dist/assets/howler-CESL1Llt.js b/pro/dist/assets/howler-CESL1Llt.js deleted file mode 100644 index a9e968d..0000000 --- a/pro/dist/assets/howler-CESL1Llt.js +++ /dev/null @@ -1 +0,0 @@ -import{t as e}from"./index-BqANBEcr.js";var t=e((e=>{(function(){var t=function(){this.init()};t.prototype={init:function(){var e=this||n;return e._counter=1e3,e._html5AudioPool=[],e.html5PoolSize=10,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent=`canplaythrough`,e._navigator=typeof window<`u`&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.autoUnlock=!0,e._setup(),e},volume:function(e){var t=this||n;if(e=parseFloat(e),t.ctx||u(),e!==void 0&&e>=0&&e<=1){if(t._volume=e,t._muted)return t;t.usingWebAudio&&t.masterGain.gain.setValueAtTime(e,n.ctx.currentTime);for(var r=0;r=0;t--)e._howls[t].unload();return e.usingWebAudio&&e.ctx&&e.ctx.close!==void 0&&(e.ctx.close(),e.ctx=null,u()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,``)]},_setup:function(){var e=this||n;if(e.state=e.ctx&&e.ctx.state||`suspended`,e._autoSuspend(),!e.usingWebAudio)if(typeof Audio<`u`)try{var t=new Audio;t.oncanplaythrough===void 0&&(e._canPlayEvent=`canplay`)}catch{e.noAudio=!0}else e.noAudio=!0;try{var t=new Audio;t.muted&&(e.noAudio=!0)}catch{}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,t=null;try{t=typeof Audio<`u`?new Audio:null}catch{return e}if(!t||typeof t.canPlayType!=`function`)return e;var r=t.canPlayType(`audio/mpeg;`).replace(/^no$/,``),i=e._navigator?e._navigator.userAgent:``,a=i.match(/OPR\/(\d+)/g),o=a&&parseInt(a[0].split(`/`)[1],10)<33,s=i.indexOf(`Safari`)!==-1&&i.indexOf(`Chrome`)===-1,c=i.match(/Version\/(.*?) /),l=s&&c&&parseInt(c[1],10)<15;return e._codecs={mp3:!!(!o&&(r||t.canPlayType(`audio/mp3;`).replace(/^no$/,``))),mpeg:!!r,opus:!!t.canPlayType(`audio/ogg; codecs="opus"`).replace(/^no$/,``),ogg:!!t.canPlayType(`audio/ogg; codecs="vorbis"`).replace(/^no$/,``),oga:!!t.canPlayType(`audio/ogg; codecs="vorbis"`).replace(/^no$/,``),wav:!!(t.canPlayType(`audio/wav; codecs="1"`)||t.canPlayType(`audio/wav`)).replace(/^no$/,``),aac:!!t.canPlayType(`audio/aac;`).replace(/^no$/,``),caf:!!t.canPlayType(`audio/x-caf;`).replace(/^no$/,``),m4a:!!(t.canPlayType(`audio/x-m4a;`)||t.canPlayType(`audio/m4a;`)||t.canPlayType(`audio/aac;`)).replace(/^no$/,``),m4b:!!(t.canPlayType(`audio/x-m4b;`)||t.canPlayType(`audio/m4b;`)||t.canPlayType(`audio/aac;`)).replace(/^no$/,``),mp4:!!(t.canPlayType(`audio/x-mp4;`)||t.canPlayType(`audio/mp4;`)||t.canPlayType(`audio/aac;`)).replace(/^no$/,``),weba:!!(!l&&t.canPlayType(`audio/webm; codecs="vorbis"`).replace(/^no$/,``)),webm:!!(!l&&t.canPlayType(`audio/webm; codecs="vorbis"`).replace(/^no$/,``)),dolby:!!t.canPlayType(`audio/mp4; codecs="ec-3"`).replace(/^no$/,``),flac:!!(t.canPlayType(`audio/x-flac;`)||t.canPlayType(`audio/flac;`)).replace(/^no$/,``)},e},_unlockAudio:function(){var e=this||n;if(!(e._audioUnlocked||!e.ctx)){e._audioUnlocked=!1,e.autoUnlock=!1,!e._mobileUnloaded&&e.ctx.sampleRate!==44100&&(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var t=function(n){for(;e._html5AudioPool.length0?s._seek:r._sprite[e][0]/1e3),u=Math.max(0,(r._sprite[e][0]+r._sprite[e][1])/1e3-l),d=u*1e3/Math.abs(s._rate),f=r._sprite[e][0]/1e3,p=(r._sprite[e][0]+r._sprite[e][1])/1e3;s._sprite=e,s._ended=!1;var m=function(){s._paused=!1,s._seek=l,s._start=f,s._stop=p,s._loop=!!(s._loop||r._sprite[e][2])};if(l>=p){r._ended(s);return}var h=s._node;if(r._webAudio){var g=function(){r._playLock=!1,m(),r._refreshBuffer(s);var e=s._muted||r._muted?0:s._volume;h.gain.setValueAtTime(e,n.ctx.currentTime),s._playStart=n.ctx.currentTime,h.bufferSource.start===void 0?s._loop?h.bufferSource.noteGrainOn(0,l,86400):h.bufferSource.noteGrainOn(0,l,u):s._loop?h.bufferSource.start(0,l,86400):h.bufferSource.start(0,l,u),d!==1/0&&(r._endTimers[s._id]=setTimeout(r._ended.bind(r,s),d)),t||setTimeout(function(){r._emit(`play`,s._id),r._loadQueue()},0)};n.state===`running`&&n.ctx.state!==`interrupted`?g():(r._playLock=!0,r.once(`resume`,g),r._clearTimer(s._id))}else{var _=function(){h.currentTime=l,h.muted=s._muted||r._muted||n._muted||h.muted,h.volume=s._volume*n.volume(),h.playbackRate=s._rate;try{var i=h.play();if(i&&typeof Promise<`u`&&(i instanceof Promise||typeof i.then==`function`)?(r._playLock=!0,m(),i.then(function(){r._playLock=!1,h._unlocked=!0,t?r._loadQueue():r._emit(`play`,s._id)}).catch(function(){r._playLock=!1,r._emit(`playerror`,s._id,`Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.`),s._ended=!0,s._paused=!0})):t||(r._playLock=!1,m(),r._emit(`play`,s._id)),h.playbackRate=s._rate,h.paused){r._emit(`playerror`,s._id,`Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.`);return}e!==`__default`||s._loop?r._endTimers[s._id]=setTimeout(r._ended.bind(r,s),d):(r._endTimers[s._id]=function(){r._ended(s),h.removeEventListener(`ended`,r._endTimers[s._id],!1)},h.addEventListener(`ended`,r._endTimers[s._id],!1))}catch(e){r._emit(`playerror`,s._id,e)}};h.src===`data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA`&&(h.src=r._src,h.load());var v=window&&window.ejecta||!h.readyState&&n._navigator.isCocoonJS;if(h.readyState>=3||v)_();else{r._playLock=!0,r._state=`loading`;var y=function(){r._state=`loaded`,_(),h.removeEventListener(n._canPlayEvent,y,!1)};h.addEventListener(n._canPlayEvent,y,!1),r._clearTimer(s._id)}}return s._id},pause:function(e){var t=this;if(t._state!==`loaded`||t._playLock)return t._queue.push({event:`pause`,action:function(){t.pause(e)}}),t;for(var n=t._getSoundIds(e),r=0;r=0?i=parseInt(t[0],10):r=parseFloat(t[0]):t.length>=2&&(r=parseFloat(t[0]),i=parseInt(t[1],10));var a;if(r!==void 0&&r>=0&&r<=1){if(e._state!==`loaded`||e._playLock)return e._queue.push({event:`volume`,action:function(){e.volume.apply(e,t)}}),e;i===void 0&&(e._volume=r),i=e._getSoundIds(i);for(var o=0;o0?r/l:r),d=Date.now();e._fadeTo=n,e._interval=setInterval(function(){var i=(Date.now()-d)/r;d=Date.now(),s+=c*i,s=Math.round(s*100)/100,s=c<0?Math.max(n,s):Math.min(n,s),o._webAudio?e._volume=s:o.volume(s,e._id,!0),a&&(o._volume=s),(nt&&s>=n)&&(clearInterval(e._interval),e._interval=null,e._fadeTo=null,o.volume(n,e._id),o._emit(`fade`,e._id))},u)},_stopFade:function(e){var t=this,r=t._soundById(e);return r&&r._interval&&(t._webAudio&&r._node.gain.cancelScheduledValues(n.ctx.currentTime),clearInterval(r._interval),r._interval=null,t.volume(r._fadeTo,e),r._fadeTo=null,t._emit(`fade`,e)),t},loop:function(){var e=this,t=arguments,n,r,i;if(t.length===0)return e._loop;if(t.length===1)if(typeof t[0]==`boolean`)n=t[0],e._loop=n;else return i=e._soundById(parseInt(t[0],10)),i?i._loop:!1;else t.length===2&&(n=t[0],r=parseInt(t[1],10));for(var a=e._getSoundIds(r),o=0;o=0?i=parseInt(t[0],10):r=parseFloat(t[0]):t.length===2&&(r=parseFloat(t[0]),i=parseInt(t[1],10));var a;if(typeof r==`number`){if(e._state!==`loaded`||e._playLock)return e._queue.push({event:`rate`,action:function(){e.rate.apply(e,t)}}),e;i===void 0&&(e._rate=r),i=e._getSoundIds(i);for(var o=0;o=0?i=parseInt(t[0],10):e._sounds.length&&(i=e._sounds[0]._id,r=parseFloat(t[0])):t.length===2&&(r=parseFloat(t[0]),i=parseInt(t[1],10)),i===void 0)return 0;if(typeof r==`number`&&(e._state!==`loaded`||e._playLock))return e._queue.push({event:`seek`,action:function(){e.seek.apply(e,t)}}),e;var a=e._soundById(i);if(a)if(typeof r==`number`&&r>=0){var o=e.playing(i);o&&e.pause(i,!0),a._seek=r,a._ended=!1,e._clearTimer(i),!e._webAudio&&a._node&&!isNaN(a._node.duration)&&(a._node.currentTime=r);var s=function(){o&&e.play(i,!0),e._emit(`seek`,i)};if(o&&!e._webAudio){var c=function(){e._playLock?setTimeout(c,0):s()};setTimeout(c,0)}else s()}else if(e._webAudio){var l=e.playing(i)?n.ctx.currentTime-a._playStart:0,u=a._rateSeek?a._rateSeek-a._seek:0;return a._seek+(u+l*Math.abs(a._rate))}else return a._node.currentTime;return e},playing:function(e){var t=this;if(typeof e==`number`){var n=t._soundById(e);return n?!n._paused:!1}for(var r=0;r=0&&n._howls.splice(i,1);var o=!0;for(r=0;r=0){o=!1;break}return a&&o&&delete a[e._src],n.noAudio=!1,e._state=`unloaded`,e._sounds=[],e=null,null},on:function(e,t,n,r){var i=this,a=i[`_on`+e];return typeof t==`function`&&a.push(r?{id:n,fn:t,once:r}:{id:n,fn:t}),i},off:function(e,t,n){var r=this,i=r[`_on`+e],a=0;if(typeof t==`number`&&(n=t,t=null),t||n)for(a=0;a=0;a--)(!i[a].id||i[a].id===t||e===`load`)&&(setTimeout(function(e){e.call(this,t,n)}.bind(r,i[a].fn),0),i[a].once&&r.off(e,i[a].fn,i[a].id));return r._loadQueue(e),r},_loadQueue:function(e){var t=this;if(t._queue.length>0){var n=t._queue[0];n.event===e&&(t._queue.shift(),t._loadQueue()),e||n.action()}return t},_ended:function(e){var t=this,r=e._sprite;if(!t._webAudio&&e._node&&!e._node.paused&&!e._node.ended&&e._node.currentTime=0;r--){if(n<=t)return;e._sounds[r]._ended&&(e._webAudio&&e._sounds[r]._node&&e._sounds[r]._node.disconnect(0),e._sounds.splice(r,1),n--)}}},_getSoundIds:function(e){var t=this;if(e===void 0){for(var n=[],r=0;r=0;if(!e.bufferSource)return t;if(n._scratchBuffer&&e.bufferSource&&(e.bufferSource.onended=null,e.bufferSource.disconnect(0),r))try{e.bufferSource.buffer=n._scratchBuffer}catch{}return e.bufferSource=null,t},_clearSound:function(e){/MSIE |Trident\//.test(n._navigator&&n._navigator.userAgent)||(e.src=`data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA`)}};var i=function(e){this._parent=e,this.init()};i.prototype={init:function(){var e=this,t=e._parent;return e._muted=t._muted,e._loop=t._loop,e._volume=t._volume,e._rate=t._rate,e._seek=0,e._paused=!0,e._ended=!0,e._sprite=`__default`,e._id=++n._counter,t._sounds.push(e),e.create(),e},create:function(){var e=this,t=e._parent,r=n._muted||e._muted||e._parent._muted?0:e._volume;return t._webAudio?(e._node=n.ctx.createGain===void 0?n.ctx.createGainNode():n.ctx.createGain(),e._node.gain.setValueAtTime(r,n.ctx.currentTime),e._node.paused=!0,e._node.connect(n.masterGain)):n.noAudio||(e._node=n._obtainHtml5Audio(),e._errorFn=e._errorListener.bind(e),e._node.addEventListener(`error`,e._errorFn,!1),e._loadFn=e._loadListener.bind(e),e._node.addEventListener(n._canPlayEvent,e._loadFn,!1),e._endFn=e._endListener.bind(e),e._node.addEventListener(`ended`,e._endFn,!1),e._node.src=t._src,e._node.preload=t._preload===!0?`auto`:t._preload,e._node.volume=r*n.volume(),e._node.load()),e},reset:function(){var e=this,t=e._parent;return e._muted=t._muted,e._loop=t._loop,e._volume=t._volume,e._rate=t._rate,e._seek=0,e._rateSeek=0,e._paused=!0,e._ended=!0,e._sprite=`__default`,e._id=++n._counter,e},_errorListener:function(){var e=this;e._parent._emit(`loaderror`,e._id,e._node.error?e._node.error.code:0),e._node.removeEventListener(`error`,e._errorFn,!1)},_loadListener:function(){var e=this,t=e._parent;t._duration=Math.ceil(e._node.duration*10)/10,Object.keys(t._sprite).length===0&&(t._sprite={__default:[0,t._duration*1e3]}),t._state!==`loaded`&&(t._state=`loaded`,t._emit(`load`),t._loadQueue()),e._node.removeEventListener(n._canPlayEvent,e._loadFn,!1)},_endListener:function(){var e=this,t=e._parent;t._duration===1/0&&(t._duration=Math.ceil(e._node.duration*10)/10,t._sprite.__default[1]===1/0&&(t._sprite.__default[1]=t._duration*1e3),t._ended(e)),e._node.removeEventListener(`ended`,e._endFn,!1)}};var a={},o=function(e){var t=e._src;if(a[t]){e._duration=a[t].duration,l(e);return}if(/^data:[^;]+;base64,/.test(t)){for(var n=atob(t.split(`,`)[1]),r=new Uint8Array(n.length),i=0;i0?(a[t._src]=e,l(t,e)):r()};typeof Promise<`u`&&n.ctx.decodeAudioData.length===1?n.ctx.decodeAudioData(e).then(i).catch(r):n.ctx.decodeAudioData(e,i,r)},l=function(e,t){t&&!e._duration&&(e._duration=t.duration),Object.keys(e._sprite).length===0&&(e._sprite={__default:[0,e._duration*1e3]}),e._state!==`loaded`&&(e._state=`loaded`,e._emit(`load`),e._loadQueue())},u=function(){if(n.usingWebAudio){try{typeof AudioContext<`u`?n.ctx=new AudioContext:typeof webkitAudioContext<`u`?n.ctx=new webkitAudioContext:n.usingWebAudio=!1}catch{n.usingWebAudio=!1}n.ctx||(n.usingWebAudio=!1);var e=/iP(hone|od|ad)/.test(n._navigator&&n._navigator.platform),t=n._navigator&&n._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/),r=t?parseInt(t[1],10):null;if(e&&r&&r<9){var i=/safari/.test(n._navigator&&n._navigator.userAgent.toLowerCase());n._navigator&&!i&&(n.usingWebAudio=!1)}n.usingWebAudio&&(n.masterGain=n.ctx.createGain===void 0?n.ctx.createGainNode():n.ctx.createGain(),n.masterGain.gain.setValueAtTime(n._muted?0:n._volume,n.ctx.currentTime),n.masterGain.connect(n.ctx.destination)),n._setup()}};typeof define==`function`&&define.amd&&define([],function(){return{Howler:n,Howl:r}}),e!==void 0&&(e.Howler=n,e.Howl=r),typeof global<`u`?(global.HowlerGlobal=t,global.Howler=n,global.Howl=r,global.Sound=i):typeof window<`u`&&(window.HowlerGlobal=t,window.Howler=n,window.Howl=r,window.Sound=i)})(),(function(){HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){var t=this;if(!t.ctx||!t.ctx.listener)return t;for(var n=t._howls.length-1;n>=0;n--)t._howls[n].stereo(e);return t},HowlerGlobal.prototype.pos=function(e,t,n){var r=this;if(!r.ctx||!r.ctx.listener)return r;if(t=typeof t==`number`?t:r._pos[1],n=typeof n==`number`?n:r._pos[2],typeof e==`number`)r._pos=[e,t,n],r.ctx.listener.positionX===void 0?r.ctx.listener.setPosition(r._pos[0],r._pos[1],r._pos[2]):(r.ctx.listener.positionX.setTargetAtTime(r._pos[0],Howler.ctx.currentTime,.1),r.ctx.listener.positionY.setTargetAtTime(r._pos[1],Howler.ctx.currentTime,.1),r.ctx.listener.positionZ.setTargetAtTime(r._pos[2],Howler.ctx.currentTime,.1));else return r._pos;return r},HowlerGlobal.prototype.orientation=function(e,t,n,r,i,a){var o=this;if(!o.ctx||!o.ctx.listener)return o;var s=o._orientation;if(t=typeof t==`number`?t:s[1],n=typeof n==`number`?n:s[2],r=typeof r==`number`?r:s[3],i=typeof i==`number`?i:s[4],a=typeof a==`number`?a:s[5],typeof e==`number`)o._orientation=[e,t,n,r,i,a],o.ctx.listener.forwardX===void 0?o.ctx.listener.setOrientation(e,t,n,r,i,a):(o.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),o.ctx.listener.forwardY.setTargetAtTime(t,Howler.ctx.currentTime,.1),o.ctx.listener.forwardZ.setTargetAtTime(n,Howler.ctx.currentTime,.1),o.ctx.listener.upX.setTargetAtTime(r,Howler.ctx.currentTime,.1),o.ctx.listener.upY.setTargetAtTime(i,Howler.ctx.currentTime,.1),o.ctx.listener.upZ.setTargetAtTime(a,Howler.ctx.currentTime,.1));else return s;return o},Howl.prototype.init=(function(e){return function(t){var n=this;return n._orientation=t.orientation||[1,0,0],n._stereo=t.stereo||null,n._pos=t.pos||null,n._pannerAttr={coneInnerAngle:t.coneInnerAngle===void 0?360:t.coneInnerAngle,coneOuterAngle:t.coneOuterAngle===void 0?360:t.coneOuterAngle,coneOuterGain:t.coneOuterGain===void 0?0:t.coneOuterGain,distanceModel:t.distanceModel===void 0?`inverse`:t.distanceModel,maxDistance:t.maxDistance===void 0?1e4:t.maxDistance,panningModel:t.panningModel===void 0?`HRTF`:t.panningModel,refDistance:t.refDistance===void 0?1:t.refDistance,rolloffFactor:t.rolloffFactor===void 0?1:t.rolloffFactor},n._onstereo=t.onstereo?[{fn:t.onstereo}]:[],n._onpos=t.onpos?[{fn:t.onpos}]:[],n._onorientation=t.onorientation?[{fn:t.onorientation}]:[],e.call(this,t)}})(Howl.prototype.init),Howl.prototype.stereo=function(t,n){var r=this;if(!r._webAudio)return r;if(r._state!==`loaded`)return r._queue.push({event:`stereo`,action:function(){r.stereo(t,n)}}),r;var i=Howler.ctx.createStereoPanner===void 0?`spatial`:`stereo`;if(n===void 0)if(typeof t==`number`)r._stereo=t,r._pos=[t,0,0];else return r._stereo;for(var a=r._getSoundIds(n),o=0;o { + ((function () { + var t = function () { + this.init(); + }; + t.prototype = { + init: function () { + var e = this || n; + return ( + (e._counter = 1e3), + (e._html5AudioPool = []), + (e.html5PoolSize = 10), + (e._codecs = {}), + (e._howls = []), + (e._muted = !1), + (e._volume = 1), + (e._canPlayEvent = `canplaythrough`), + (e._navigator = typeof window < `u` && window.navigator ? window.navigator : null), + (e.masterGain = null), + (e.noAudio = !1), + (e.usingWebAudio = !0), + (e.autoSuspend = !0), + (e.ctx = null), + (e.autoUnlock = !0), + e._setup(), + e + ); + }, + volume: function (e) { + var t = this || n; + if (((e = parseFloat(e)), t.ctx || u(), e !== void 0 && e >= 0 && e <= 1)) { + if (((t._volume = e), t._muted)) return t; + t.usingWebAudio && t.masterGain.gain.setValueAtTime(e, n.ctx.currentTime); + for (var r = 0; r < t._howls.length; r++) + if (!t._howls[r]._webAudio) + for (var i = t._howls[r]._getSoundIds(), a = 0; a < i.length; a++) { + var o = t._howls[r]._soundById(i[a]); + o && o._node && (o._node.volume = o._volume * e); + } + return t; + } + return t._volume; + }, + mute: function (e) { + var t = this || n; + (t.ctx || u(), + (t._muted = e), + t.usingWebAudio && t.masterGain.gain.setValueAtTime(e ? 0 : t._volume, n.ctx.currentTime)); + for (var r = 0; r < t._howls.length; r++) + if (!t._howls[r]._webAudio) + for (var i = t._howls[r]._getSoundIds(), a = 0; a < i.length; a++) { + var o = t._howls[r]._soundById(i[a]); + o && o._node && (o._node.muted = e ? !0 : o._muted); + } + return t; + }, + stop: function () { + for (var e = this || n, t = 0; t < e._howls.length; t++) e._howls[t].stop(); + return e; + }, + unload: function () { + for (var e = this || n, t = e._howls.length - 1; t >= 0; t--) e._howls[t].unload(); + return (e.usingWebAudio && e.ctx && e.ctx.close !== void 0 && (e.ctx.close(), (e.ctx = null), u()), e); + }, + codecs: function (e) { + return (this || n)._codecs[e.replace(/^x-/, ``)]; + }, + _setup: function () { + var e = this || n; + if (((e.state = (e.ctx && e.ctx.state) || `suspended`), e._autoSuspend(), !e.usingWebAudio)) + if (typeof Audio < `u`) + try { + var t = new Audio(); + t.oncanplaythrough === void 0 && (e._canPlayEvent = `canplay`); + } catch { + e.noAudio = !0; + } + else e.noAudio = !0; + try { + var t = new Audio(); + t.muted && (e.noAudio = !0); + } catch {} + return (e.noAudio || e._setupCodecs(), e); + }, + _setupCodecs: function () { + var e = this || n, + t = null; + try { + t = typeof Audio < `u` ? new Audio() : null; + } catch { + return e; + } + if (!t || typeof t.canPlayType != `function`) return e; + var r = t.canPlayType(`audio/mpeg;`).replace(/^no$/, ``), + i = e._navigator ? e._navigator.userAgent : ``, + a = i.match(/OPR\/(\d+)/g), + o = a && parseInt(a[0].split(`/`)[1], 10) < 33, + s = i.indexOf(`Safari`) !== -1 && i.indexOf(`Chrome`) === -1, + c = i.match(/Version\/(.*?) /), + l = s && c && parseInt(c[1], 10) < 15; + return ( + (e._codecs = { + mp3: !!(!o && (r || t.canPlayType(`audio/mp3;`).replace(/^no$/, ``))), + mpeg: !!r, + opus: !!t.canPlayType(`audio/ogg; codecs="opus"`).replace(/^no$/, ``), + ogg: !!t.canPlayType(`audio/ogg; codecs="vorbis"`).replace(/^no$/, ``), + oga: !!t.canPlayType(`audio/ogg; codecs="vorbis"`).replace(/^no$/, ``), + wav: !!(t.canPlayType(`audio/wav; codecs="1"`) || t.canPlayType(`audio/wav`)).replace(/^no$/, ``), + aac: !!t.canPlayType(`audio/aac;`).replace(/^no$/, ``), + caf: !!t.canPlayType(`audio/x-caf;`).replace(/^no$/, ``), + m4a: !!( + t.canPlayType(`audio/x-m4a;`) || + t.canPlayType(`audio/m4a;`) || + t.canPlayType(`audio/aac;`) + ).replace(/^no$/, ``), + m4b: !!( + t.canPlayType(`audio/x-m4b;`) || + t.canPlayType(`audio/m4b;`) || + t.canPlayType(`audio/aac;`) + ).replace(/^no$/, ``), + mp4: !!( + t.canPlayType(`audio/x-mp4;`) || + t.canPlayType(`audio/mp4;`) || + t.canPlayType(`audio/aac;`) + ).replace(/^no$/, ``), + weba: !!(!l && t.canPlayType(`audio/webm; codecs="vorbis"`).replace(/^no$/, ``)), + webm: !!(!l && t.canPlayType(`audio/webm; codecs="vorbis"`).replace(/^no$/, ``)), + dolby: !!t.canPlayType(`audio/mp4; codecs="ec-3"`).replace(/^no$/, ``), + flac: !!(t.canPlayType(`audio/x-flac;`) || t.canPlayType(`audio/flac;`)).replace(/^no$/, ``), + }), + e + ); + }, + _unlockAudio: function () { + var e = this || n; + if (!(e._audioUnlocked || !e.ctx)) { + ((e._audioUnlocked = !1), + (e.autoUnlock = !1), + !e._mobileUnloaded && e.ctx.sampleRate !== 44100 && ((e._mobileUnloaded = !0), e.unload()), + (e._scratchBuffer = e.ctx.createBuffer(1, 1, 22050))); + var t = function (n) { + for (; e._html5AudioPool.length < e.html5PoolSize; ) + try { + var r = new Audio(); + ((r._unlocked = !0), e._releaseHtml5Audio(r)); + } catch { + e.noAudio = !0; + break; + } + for (var i = 0; i < e._howls.length; i++) + if (!e._howls[i]._webAudio) + for (var a = e._howls[i]._getSoundIds(), o = 0; o < a.length; o++) { + var s = e._howls[i]._soundById(a[o]); + s && s._node && !s._node._unlocked && ((s._node._unlocked = !0), s._node.load()); + } + e._autoResume(); + var c = e.ctx.createBufferSource(); + ((c.buffer = e._scratchBuffer), + c.connect(e.ctx.destination), + c.start === void 0 ? c.noteOn(0) : c.start(0), + typeof e.ctx.resume == `function` && e.ctx.resume(), + (c.onended = function () { + (c.disconnect(0), + (e._audioUnlocked = !0), + document.removeEventListener(`touchstart`, t, !0), + document.removeEventListener(`touchend`, t, !0), + document.removeEventListener(`click`, t, !0), + document.removeEventListener(`keydown`, t, !0)); + for (var n = 0; n < e._howls.length; n++) e._howls[n]._emit(`unlock`); + })); + }; + return ( + document.addEventListener(`touchstart`, t, !0), + document.addEventListener(`touchend`, t, !0), + document.addEventListener(`click`, t, !0), + document.addEventListener(`keydown`, t, !0), + e + ); + } + }, + _obtainHtml5Audio: function () { + var e = this || n; + if (e._html5AudioPool.length) return e._html5AudioPool.pop(); + var t = new Audio().play(); + return ( + t && + typeof Promise < `u` && + (t instanceof Promise || typeof t.then == `function`) && + t.catch(function () { + console.warn(`HTML5 Audio pool exhausted, returning potentially locked audio object.`); + }), + new Audio() + ); + }, + _releaseHtml5Audio: function (e) { + var t = this || n; + return (e._unlocked && t._html5AudioPool.push(e), t); + }, + _autoSuspend: function () { + var e = this; + if (!(!e.autoSuspend || !e.ctx || e.ctx.suspend === void 0 || !n.usingWebAudio)) { + for (var t = 0; t < e._howls.length; t++) + if (e._howls[t]._webAudio) { + for (var r = 0; r < e._howls[t]._sounds.length; r++) if (!e._howls[t]._sounds[r]._paused) return e; + } + return ( + e._suspendTimer && clearTimeout(e._suspendTimer), + (e._suspendTimer = setTimeout(function () { + if (e.autoSuspend) { + ((e._suspendTimer = null), (e.state = `suspending`)); + var t = function () { + ((e.state = `suspended`), e._resumeAfterSuspend && (delete e._resumeAfterSuspend, e._autoResume())); + }; + e.ctx.suspend().then(t, t); + } + }, 3e4)), + e + ); + } + }, + _autoResume: function () { + var e = this; + if (!(!e.ctx || e.ctx.resume === void 0 || !n.usingWebAudio)) + return ( + e.state === `running` && e.ctx.state !== `interrupted` && e._suspendTimer + ? (clearTimeout(e._suspendTimer), (e._suspendTimer = null)) + : e.state === `suspended` || (e.state === `running` && e.ctx.state === `interrupted`) + ? (e.ctx.resume().then(function () { + e.state = `running`; + for (var t = 0; t < e._howls.length; t++) e._howls[t]._emit(`resume`); + }), + (e._suspendTimer &&= (clearTimeout(e._suspendTimer), null))) + : e.state === `suspending` && (e._resumeAfterSuspend = !0), + e + ); + }, + }; + var n = new t(), + r = function (e) { + var t = this; + if (!e.src || e.src.length === 0) { + console.error(`An array of source files must be passed with any new Howl.`); + return; + } + t.init(e); + }; + r.prototype = { + init: function (e) { + var t = this; + return ( + n.ctx || u(), + (t._autoplay = e.autoplay || !1), + (t._format = typeof e.format == `string` ? [e.format] : e.format), + (t._html5 = e.html5 || !1), + (t._muted = e.mute || !1), + (t._loop = e.loop || !1), + (t._pool = e.pool || 5), + (t._preload = typeof e.preload == `boolean` || e.preload === `metadata` ? e.preload : !0), + (t._rate = e.rate || 1), + (t._sprite = e.sprite || {}), + (t._src = typeof e.src == `string` ? [e.src] : e.src), + (t._volume = e.volume === void 0 ? 1 : e.volume), + (t._xhr = { + method: e.xhr && e.xhr.method ? e.xhr.method : `GET`, + headers: e.xhr && e.xhr.headers ? e.xhr.headers : null, + withCredentials: e.xhr && e.xhr.withCredentials ? e.xhr.withCredentials : !1, + }), + (t._duration = 0), + (t._state = `unloaded`), + (t._sounds = []), + (t._endTimers = {}), + (t._queue = []), + (t._playLock = !1), + (t._onend = e.onend ? [{ fn: e.onend }] : []), + (t._onfade = e.onfade ? [{ fn: e.onfade }] : []), + (t._onload = e.onload ? [{ fn: e.onload }] : []), + (t._onloaderror = e.onloaderror ? [{ fn: e.onloaderror }] : []), + (t._onplayerror = e.onplayerror ? [{ fn: e.onplayerror }] : []), + (t._onpause = e.onpause ? [{ fn: e.onpause }] : []), + (t._onplay = e.onplay ? [{ fn: e.onplay }] : []), + (t._onstop = e.onstop ? [{ fn: e.onstop }] : []), + (t._onmute = e.onmute ? [{ fn: e.onmute }] : []), + (t._onvolume = e.onvolume ? [{ fn: e.onvolume }] : []), + (t._onrate = e.onrate ? [{ fn: e.onrate }] : []), + (t._onseek = e.onseek ? [{ fn: e.onseek }] : []), + (t._onunlock = e.onunlock ? [{ fn: e.onunlock }] : []), + (t._onresume = []), + (t._webAudio = n.usingWebAudio && !t._html5), + n.ctx !== void 0 && n.ctx && n.autoUnlock && n._unlockAudio(), + n._howls.push(t), + t._autoplay && + t._queue.push({ + event: `play`, + action: function () { + t.play(); + }, + }), + t._preload && t._preload !== `none` && t.load(), + t + ); + }, + load: function () { + var e = this, + t = null; + if (n.noAudio) { + e._emit(`loaderror`, null, `No audio support.`); + return; + } + typeof e._src == `string` && (e._src = [e._src]); + for (var r = 0; r < e._src.length; r++) { + var a, s; + if (e._format && e._format[r]) a = e._format[r]; + else { + if (((s = e._src[r]), typeof s != `string`)) { + e._emit(`loaderror`, null, `Non-string found in selected audio sources - ignoring.`); + continue; + } + ((a = /^data:audio\/([^;,]+);/i.exec(s)), + (a ||= /\.([^.]+)$/.exec(s.split(`?`, 1)[0])), + (a &&= a[1].toLowerCase())); + } + if ( + (a || + console.warn( + `No file extension was found. Consider using the "format" property or specify an extension.`, + ), + a && n.codecs(a)) + ) { + t = e._src[r]; + break; + } + } + if (!t) { + e._emit(`loaderror`, null, `No codec support for selected audio sources.`); + return; + } + return ( + (e._src = t), + (e._state = `loading`), + window.location.protocol === `https:` && t.slice(0, 5) === `http:` && ((e._html5 = !0), (e._webAudio = !1)), + new i(e), + e._webAudio && o(e), + e + ); + }, + play: function (e, t) { + var r = this, + i = null; + if (typeof e == `number`) ((i = e), (e = null)); + else if (typeof e == `string` && r._state === `loaded` && !r._sprite[e]) return null; + else if (e === void 0 && ((e = `__default`), !r._playLock)) { + for (var a = 0, o = 0; o < r._sounds.length; o++) + r._sounds[o]._paused && !r._sounds[o]._ended && (a++, (i = r._sounds[o]._id)); + a === 1 ? (e = null) : (i = null); + } + var s = i ? r._soundById(i) : r._inactiveSound(); + if (!s) return null; + if ((i && !e && (e = s._sprite || `__default`), r._state !== `loaded`)) { + ((s._sprite = e), (s._ended = !1)); + var c = s._id; + return ( + r._queue.push({ + event: `play`, + action: function () { + r.play(c); + }, + }), + c + ); + } + if (i && !s._paused) return (t || r._loadQueue(`play`), s._id); + r._webAudio && n._autoResume(); + var l = Math.max(0, s._seek > 0 ? s._seek : r._sprite[e][0] / 1e3), + u = Math.max(0, (r._sprite[e][0] + r._sprite[e][1]) / 1e3 - l), + d = (u * 1e3) / Math.abs(s._rate), + f = r._sprite[e][0] / 1e3, + p = (r._sprite[e][0] + r._sprite[e][1]) / 1e3; + ((s._sprite = e), (s._ended = !1)); + var m = function () { + ((s._paused = !1), (s._seek = l), (s._start = f), (s._stop = p), (s._loop = !!(s._loop || r._sprite[e][2]))); + }; + if (l >= p) { + r._ended(s); + return; + } + var h = s._node; + if (r._webAudio) { + var g = function () { + ((r._playLock = !1), m(), r._refreshBuffer(s)); + var e = s._muted || r._muted ? 0 : s._volume; + (h.gain.setValueAtTime(e, n.ctx.currentTime), + (s._playStart = n.ctx.currentTime), + h.bufferSource.start === void 0 + ? s._loop + ? h.bufferSource.noteGrainOn(0, l, 86400) + : h.bufferSource.noteGrainOn(0, l, u) + : s._loop + ? h.bufferSource.start(0, l, 86400) + : h.bufferSource.start(0, l, u), + d !== 1 / 0 && (r._endTimers[s._id] = setTimeout(r._ended.bind(r, s), d)), + t || + setTimeout(function () { + (r._emit(`play`, s._id), r._loadQueue()); + }, 0)); + }; + n.state === `running` && n.ctx.state !== `interrupted` + ? g() + : ((r._playLock = !0), r.once(`resume`, g), r._clearTimer(s._id)); + } else { + var _ = function () { + ((h.currentTime = l), + (h.muted = s._muted || r._muted || n._muted || h.muted), + (h.volume = s._volume * n.volume()), + (h.playbackRate = s._rate)); + try { + var i = h.play(); + if ( + (i && typeof Promise < `u` && (i instanceof Promise || typeof i.then == `function`) + ? ((r._playLock = !0), + m(), + i + .then(function () { + ((r._playLock = !1), (h._unlocked = !0), t ? r._loadQueue() : r._emit(`play`, s._id)); + }) + .catch(function () { + ((r._playLock = !1), + r._emit( + `playerror`, + s._id, + `Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.`, + ), + (s._ended = !0), + (s._paused = !0)); + })) + : t || ((r._playLock = !1), m(), r._emit(`play`, s._id)), + (h.playbackRate = s._rate), + h.paused) + ) { + r._emit( + `playerror`, + s._id, + `Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.`, + ); + return; + } + e !== `__default` || s._loop + ? (r._endTimers[s._id] = setTimeout(r._ended.bind(r, s), d)) + : ((r._endTimers[s._id] = function () { + (r._ended(s), h.removeEventListener(`ended`, r._endTimers[s._id], !1)); + }), + h.addEventListener(`ended`, r._endTimers[s._id], !1)); + } catch (e) { + r._emit(`playerror`, s._id, e); + } + }; + h.src === `data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA` && + ((h.src = r._src), h.load()); + var v = (window && window.ejecta) || (!h.readyState && n._navigator.isCocoonJS); + if (h.readyState >= 3 || v) _(); + else { + ((r._playLock = !0), (r._state = `loading`)); + var y = function () { + ((r._state = `loaded`), _(), h.removeEventListener(n._canPlayEvent, y, !1)); + }; + (h.addEventListener(n._canPlayEvent, y, !1), r._clearTimer(s._id)); + } + } + return s._id; + }, + pause: function (e) { + var t = this; + if (t._state !== `loaded` || t._playLock) + return ( + t._queue.push({ + event: `pause`, + action: function () { + t.pause(e); + }, + }), + t + ); + for (var n = t._getSoundIds(e), r = 0; r < n.length; r++) { + t._clearTimer(n[r]); + var i = t._soundById(n[r]); + if ( + i && + !i._paused && + ((i._seek = t.seek(n[r])), (i._rateSeek = 0), (i._paused = !0), t._stopFade(n[r]), i._node) + ) + if (t._webAudio) { + if (!i._node.bufferSource) continue; + (i._node.bufferSource.stop === void 0 ? i._node.bufferSource.noteOff(0) : i._node.bufferSource.stop(0), + t._cleanBuffer(i._node)); + } else (!isNaN(i._node.duration) || i._node.duration === 1 / 0) && i._node.pause(); + arguments[1] || t._emit(`pause`, i ? i._id : null); + } + return t; + }, + stop: function (e, t) { + var n = this; + if (n._state !== `loaded` || n._playLock) + return ( + n._queue.push({ + event: `stop`, + action: function () { + n.stop(e); + }, + }), + n + ); + for (var r = n._getSoundIds(e), i = 0; i < r.length; i++) { + n._clearTimer(r[i]); + var a = n._soundById(r[i]); + a && + ((a._seek = a._start || 0), + (a._rateSeek = 0), + (a._paused = !0), + (a._ended = !0), + n._stopFade(r[i]), + a._node && + (n._webAudio + ? a._node.bufferSource && + (a._node.bufferSource.stop === void 0 + ? a._node.bufferSource.noteOff(0) + : a._node.bufferSource.stop(0), + n._cleanBuffer(a._node)) + : (!isNaN(a._node.duration) || a._node.duration === 1 / 0) && + ((a._node.currentTime = a._start || 0), + a._node.pause(), + a._node.duration === 1 / 0 && n._clearSound(a._node))), + t || n._emit(`stop`, a._id)); + } + return n; + }, + mute: function (e, t) { + var r = this; + if (r._state !== `loaded` || r._playLock) + return ( + r._queue.push({ + event: `mute`, + action: function () { + r.mute(e, t); + }, + }), + r + ); + if (t === void 0) + if (typeof e == `boolean`) r._muted = e; + else return r._muted; + for (var i = r._getSoundIds(t), a = 0; a < i.length; a++) { + var o = r._soundById(i[a]); + o && + ((o._muted = e), + o._interval && r._stopFade(o._id), + r._webAudio && o._node + ? o._node.gain.setValueAtTime(e ? 0 : o._volume, n.ctx.currentTime) + : o._node && (o._node.muted = n._muted ? !0 : e), + r._emit(`mute`, o._id)); + } + return r; + }, + volume: function () { + var e = this, + t = arguments, + r, + i; + if (t.length === 0) return e._volume; + t.length === 1 || (t.length === 2 && t[1] === void 0) + ? e._getSoundIds().indexOf(t[0]) >= 0 + ? (i = parseInt(t[0], 10)) + : (r = parseFloat(t[0])) + : t.length >= 2 && ((r = parseFloat(t[0])), (i = parseInt(t[1], 10))); + var a; + if (r !== void 0 && r >= 0 && r <= 1) { + if (e._state !== `loaded` || e._playLock) + return ( + e._queue.push({ + event: `volume`, + action: function () { + e.volume.apply(e, t); + }, + }), + e + ); + (i === void 0 && (e._volume = r), (i = e._getSoundIds(i))); + for (var o = 0; o < i.length; o++) + ((a = e._soundById(i[o])), + a && + ((a._volume = r), + t[2] || e._stopFade(i[o]), + e._webAudio && a._node && !a._muted + ? a._node.gain.setValueAtTime(r, n.ctx.currentTime) + : a._node && !a._muted && (a._node.volume = r * n.volume()), + e._emit(`volume`, a._id))); + } else return ((a = i ? e._soundById(i) : e._sounds[0]), a ? a._volume : 0); + return e; + }, + fade: function (e, t, r, i) { + var a = this; + if (a._state !== `loaded` || a._playLock) + return ( + a._queue.push({ + event: `fade`, + action: function () { + a.fade(e, t, r, i); + }, + }), + a + ); + ((e = Math.min(Math.max(0, parseFloat(e)), 1)), + (t = Math.min(Math.max(0, parseFloat(t)), 1)), + (r = parseFloat(r)), + a.volume(e, i)); + for (var o = a._getSoundIds(i), s = 0; s < o.length; s++) { + var c = a._soundById(o[s]); + if (c) { + if ((i || a._stopFade(o[s]), a._webAudio && !c._muted)) { + var l = n.ctx.currentTime, + u = l + r / 1e3; + ((c._volume = e), c._node.gain.setValueAtTime(e, l), c._node.gain.linearRampToValueAtTime(t, u)); + } + a._startFadeInterval(c, e, t, r, o[s], i === void 0); + } + } + return a; + }, + _startFadeInterval: function (e, t, n, r, i, a) { + var o = this, + s = t, + c = n - t, + l = Math.abs(c / 0.01), + u = Math.max(4, l > 0 ? r / l : r), + d = Date.now(); + ((e._fadeTo = n), + (e._interval = setInterval(function () { + var i = (Date.now() - d) / r; + ((d = Date.now()), + (s += c * i), + (s = Math.round(s * 100) / 100), + (s = c < 0 ? Math.max(n, s) : Math.min(n, s)), + o._webAudio ? (e._volume = s) : o.volume(s, e._id, !0), + a && (o._volume = s), + ((n < t && s <= n) || (n > t && s >= n)) && + (clearInterval(e._interval), + (e._interval = null), + (e._fadeTo = null), + o.volume(n, e._id), + o._emit(`fade`, e._id))); + }, u))); + }, + _stopFade: function (e) { + var t = this, + r = t._soundById(e); + return ( + r && + r._interval && + (t._webAudio && r._node.gain.cancelScheduledValues(n.ctx.currentTime), + clearInterval(r._interval), + (r._interval = null), + t.volume(r._fadeTo, e), + (r._fadeTo = null), + t._emit(`fade`, e)), + t + ); + }, + loop: function () { + var e = this, + t = arguments, + n, + r, + i; + if (t.length === 0) return e._loop; + if (t.length === 1) + if (typeof t[0] == `boolean`) ((n = t[0]), (e._loop = n)); + else return ((i = e._soundById(parseInt(t[0], 10))), i ? i._loop : !1); + else t.length === 2 && ((n = t[0]), (r = parseInt(t[1], 10))); + for (var a = e._getSoundIds(r), o = 0; o < a.length; o++) + ((i = e._soundById(a[o])), + i && + ((i._loop = n), + e._webAudio && + i._node && + i._node.bufferSource && + ((i._node.bufferSource.loop = n), + n && + ((i._node.bufferSource.loopStart = i._start || 0), + (i._node.bufferSource.loopEnd = i._stop), + e.playing(a[o]) && (e.pause(a[o], !0), e.play(a[o], !0)))))); + return e; + }, + rate: function () { + var e = this, + t = arguments, + r, + i; + t.length === 0 + ? (i = e._sounds[0]._id) + : t.length === 1 + ? e._getSoundIds().indexOf(t[0]) >= 0 + ? (i = parseInt(t[0], 10)) + : (r = parseFloat(t[0])) + : t.length === 2 && ((r = parseFloat(t[0])), (i = parseInt(t[1], 10))); + var a; + if (typeof r == `number`) { + if (e._state !== `loaded` || e._playLock) + return ( + e._queue.push({ + event: `rate`, + action: function () { + e.rate.apply(e, t); + }, + }), + e + ); + (i === void 0 && (e._rate = r), (i = e._getSoundIds(i))); + for (var o = 0; o < i.length; o++) + if (((a = e._soundById(i[o])), a)) { + (e.playing(i[o]) && + ((a._rateSeek = e.seek(i[o])), (a._playStart = e._webAudio ? n.ctx.currentTime : a._playStart)), + (a._rate = r), + e._webAudio && a._node && a._node.bufferSource + ? a._node.bufferSource.playbackRate.setValueAtTime(r, n.ctx.currentTime) + : a._node && (a._node.playbackRate = r)); + var s = e.seek(i[o]), + c = (((e._sprite[a._sprite][0] + e._sprite[a._sprite][1]) / 1e3 - s) * 1e3) / Math.abs(a._rate); + ((e._endTimers[i[o]] || !a._paused) && + (e._clearTimer(i[o]), (e._endTimers[i[o]] = setTimeout(e._ended.bind(e, a), c))), + e._emit(`rate`, a._id)); + } + } else return ((a = e._soundById(i)), a ? a._rate : e._rate); + return e; + }, + seek: function () { + var e = this, + t = arguments, + r, + i; + if ( + (t.length === 0 + ? e._sounds.length && (i = e._sounds[0]._id) + : t.length === 1 + ? e._getSoundIds().indexOf(t[0]) >= 0 + ? (i = parseInt(t[0], 10)) + : e._sounds.length && ((i = e._sounds[0]._id), (r = parseFloat(t[0]))) + : t.length === 2 && ((r = parseFloat(t[0])), (i = parseInt(t[1], 10))), + i === void 0) + ) + return 0; + if (typeof r == `number` && (e._state !== `loaded` || e._playLock)) + return ( + e._queue.push({ + event: `seek`, + action: function () { + e.seek.apply(e, t); + }, + }), + e + ); + var a = e._soundById(i); + if (a) + if (typeof r == `number` && r >= 0) { + var o = e.playing(i); + (o && e.pause(i, !0), + (a._seek = r), + (a._ended = !1), + e._clearTimer(i), + !e._webAudio && a._node && !isNaN(a._node.duration) && (a._node.currentTime = r)); + var s = function () { + (o && e.play(i, !0), e._emit(`seek`, i)); + }; + if (o && !e._webAudio) { + var c = function () { + e._playLock ? setTimeout(c, 0) : s(); + }; + setTimeout(c, 0); + } else s(); + } else if (e._webAudio) { + var l = e.playing(i) ? n.ctx.currentTime - a._playStart : 0, + u = a._rateSeek ? a._rateSeek - a._seek : 0; + return a._seek + (u + l * Math.abs(a._rate)); + } else return a._node.currentTime; + return e; + }, + playing: function (e) { + var t = this; + if (typeof e == `number`) { + var n = t._soundById(e); + return n ? !n._paused : !1; + } + for (var r = 0; r < t._sounds.length; r++) if (!t._sounds[r]._paused) return !0; + return !1; + }, + duration: function (e) { + var t = this, + n = t._duration, + r = t._soundById(e); + return (r && (n = t._sprite[r._sprite][1] / 1e3), n); + }, + state: function () { + return this._state; + }, + unload: function () { + for (var e = this, t = e._sounds, r = 0; r < t.length; r++) + (t[r]._paused || e.stop(t[r]._id), + e._webAudio || + (e._clearSound(t[r]._node), + t[r]._node.removeEventListener(`error`, t[r]._errorFn, !1), + t[r]._node.removeEventListener(n._canPlayEvent, t[r]._loadFn, !1), + t[r]._node.removeEventListener(`ended`, t[r]._endFn, !1), + n._releaseHtml5Audio(t[r]._node)), + delete t[r]._node, + e._clearTimer(t[r]._id)); + var i = n._howls.indexOf(e); + i >= 0 && n._howls.splice(i, 1); + var o = !0; + for (r = 0; r < n._howls.length; r++) + if (n._howls[r]._src === e._src || e._src.indexOf(n._howls[r]._src) >= 0) { + o = !1; + break; + } + return ( + a && o && delete a[e._src], + (n.noAudio = !1), + (e._state = `unloaded`), + (e._sounds = []), + (e = null), + null + ); + }, + on: function (e, t, n, r) { + var i = this, + a = i[`_on` + e]; + return (typeof t == `function` && a.push(r ? { id: n, fn: t, once: r } : { id: n, fn: t }), i); + }, + off: function (e, t, n) { + var r = this, + i = r[`_on` + e], + a = 0; + if ((typeof t == `number` && ((n = t), (t = null)), t || n)) + for (a = 0; a < i.length; a++) { + var o = n === i[a].id; + if ((t === i[a].fn && o) || (!t && o)) { + i.splice(a, 1); + break; + } + } + else if (e) r[`_on` + e] = []; + else { + var s = Object.keys(r); + for (a = 0; a < s.length; a++) s[a].indexOf(`_on`) === 0 && Array.isArray(r[s[a]]) && (r[s[a]] = []); + } + return r; + }, + once: function (e, t, n) { + var r = this; + return (r.on(e, t, n, 1), r); + }, + _emit: function (e, t, n) { + for (var r = this, i = r[`_on` + e], a = i.length - 1; a >= 0; a--) + (!i[a].id || i[a].id === t || e === `load`) && + (setTimeout( + function (e) { + e.call(this, t, n); + }.bind(r, i[a].fn), + 0, + ), + i[a].once && r.off(e, i[a].fn, i[a].id)); + return (r._loadQueue(e), r); + }, + _loadQueue: function (e) { + var t = this; + if (t._queue.length > 0) { + var n = t._queue[0]; + (n.event === e && (t._queue.shift(), t._loadQueue()), e || n.action()); + } + return t; + }, + _ended: function (e) { + var t = this, + r = e._sprite; + if (!t._webAudio && e._node && !e._node.paused && !e._node.ended && e._node.currentTime < e._stop) + return (setTimeout(t._ended.bind(t, e), 100), t); + var i = !!(e._loop || t._sprite[r][2]); + if ((t._emit(`end`, e._id), !t._webAudio && i && t.stop(e._id, !0).play(e._id), t._webAudio && i)) { + (t._emit(`play`, e._id), (e._seek = e._start || 0), (e._rateSeek = 0), (e._playStart = n.ctx.currentTime)); + var a = ((e._stop - e._start) * 1e3) / Math.abs(e._rate); + t._endTimers[e._id] = setTimeout(t._ended.bind(t, e), a); + } + return ( + t._webAudio && + !i && + ((e._paused = !0), + (e._ended = !0), + (e._seek = e._start || 0), + (e._rateSeek = 0), + t._clearTimer(e._id), + t._cleanBuffer(e._node), + n._autoSuspend()), + !t._webAudio && !i && t.stop(e._id, !0), + t + ); + }, + _clearTimer: function (e) { + var t = this; + if (t._endTimers[e]) { + if (typeof t._endTimers[e] != `function`) clearTimeout(t._endTimers[e]); + else { + var n = t._soundById(e); + n && n._node && n._node.removeEventListener(`ended`, t._endTimers[e], !1); + } + delete t._endTimers[e]; + } + return t; + }, + _soundById: function (e) { + for (var t = this, n = 0; n < t._sounds.length; n++) if (e === t._sounds[n]._id) return t._sounds[n]; + return null; + }, + _inactiveSound: function () { + var e = this; + e._drain(); + for (var t = 0; t < e._sounds.length; t++) if (e._sounds[t]._ended) return e._sounds[t].reset(); + return new i(e); + }, + _drain: function () { + var e = this, + t = e._pool, + n = 0, + r = 0; + if (!(e._sounds.length < t)) { + for (r = 0; r < e._sounds.length; r++) e._sounds[r]._ended && n++; + for (r = e._sounds.length - 1; r >= 0; r--) { + if (n <= t) return; + e._sounds[r]._ended && + (e._webAudio && e._sounds[r]._node && e._sounds[r]._node.disconnect(0), e._sounds.splice(r, 1), n--); + } + } + }, + _getSoundIds: function (e) { + var t = this; + if (e === void 0) { + for (var n = [], r = 0; r < t._sounds.length; r++) n.push(t._sounds[r]._id); + return n; + } else return [e]; + }, + _refreshBuffer: function (e) { + var t = this; + return ( + (e._node.bufferSource = n.ctx.createBufferSource()), + (e._node.bufferSource.buffer = a[t._src]), + e._panner ? e._node.bufferSource.connect(e._panner) : e._node.bufferSource.connect(e._node), + (e._node.bufferSource.loop = e._loop), + e._loop && ((e._node.bufferSource.loopStart = e._start || 0), (e._node.bufferSource.loopEnd = e._stop || 0)), + e._node.bufferSource.playbackRate.setValueAtTime(e._rate, n.ctx.currentTime), + t + ); + }, + _cleanBuffer: function (e) { + var t = this, + r = n._navigator && n._navigator.vendor.indexOf(`Apple`) >= 0; + if (!e.bufferSource) return t; + if (n._scratchBuffer && e.bufferSource && ((e.bufferSource.onended = null), e.bufferSource.disconnect(0), r)) + try { + e.bufferSource.buffer = n._scratchBuffer; + } catch {} + return ((e.bufferSource = null), t); + }, + _clearSound: function (e) { + /MSIE |Trident\//.test(n._navigator && n._navigator.userAgent) || + (e.src = `data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA`); + }, + }; + var i = function (e) { + ((this._parent = e), this.init()); + }; + i.prototype = { + init: function () { + var e = this, + t = e._parent; + return ( + (e._muted = t._muted), + (e._loop = t._loop), + (e._volume = t._volume), + (e._rate = t._rate), + (e._seek = 0), + (e._paused = !0), + (e._ended = !0), + (e._sprite = `__default`), + (e._id = ++n._counter), + t._sounds.push(e), + e.create(), + e + ); + }, + create: function () { + var e = this, + t = e._parent, + r = n._muted || e._muted || e._parent._muted ? 0 : e._volume; + return ( + t._webAudio + ? ((e._node = n.ctx.createGain === void 0 ? n.ctx.createGainNode() : n.ctx.createGain()), + e._node.gain.setValueAtTime(r, n.ctx.currentTime), + (e._node.paused = !0), + e._node.connect(n.masterGain)) + : n.noAudio || + ((e._node = n._obtainHtml5Audio()), + (e._errorFn = e._errorListener.bind(e)), + e._node.addEventListener(`error`, e._errorFn, !1), + (e._loadFn = e._loadListener.bind(e)), + e._node.addEventListener(n._canPlayEvent, e._loadFn, !1), + (e._endFn = e._endListener.bind(e)), + e._node.addEventListener(`ended`, e._endFn, !1), + (e._node.src = t._src), + (e._node.preload = t._preload === !0 ? `auto` : t._preload), + (e._node.volume = r * n.volume()), + e._node.load()), + e + ); + }, + reset: function () { + var e = this, + t = e._parent; + return ( + (e._muted = t._muted), + (e._loop = t._loop), + (e._volume = t._volume), + (e._rate = t._rate), + (e._seek = 0), + (e._rateSeek = 0), + (e._paused = !0), + (e._ended = !0), + (e._sprite = `__default`), + (e._id = ++n._counter), + e + ); + }, + _errorListener: function () { + var e = this; + (e._parent._emit(`loaderror`, e._id, e._node.error ? e._node.error.code : 0), + e._node.removeEventListener(`error`, e._errorFn, !1)); + }, + _loadListener: function () { + var e = this, + t = e._parent; + ((t._duration = Math.ceil(e._node.duration * 10) / 10), + Object.keys(t._sprite).length === 0 && (t._sprite = { __default: [0, t._duration * 1e3] }), + t._state !== `loaded` && ((t._state = `loaded`), t._emit(`load`), t._loadQueue()), + e._node.removeEventListener(n._canPlayEvent, e._loadFn, !1)); + }, + _endListener: function () { + var e = this, + t = e._parent; + (t._duration === 1 / 0 && + ((t._duration = Math.ceil(e._node.duration * 10) / 10), + t._sprite.__default[1] === 1 / 0 && (t._sprite.__default[1] = t._duration * 1e3), + t._ended(e)), + e._node.removeEventListener(`ended`, e._endFn, !1)); + }, + }; + var a = {}, + o = function (e) { + var t = e._src; + if (a[t]) { + ((e._duration = a[t].duration), l(e)); + return; + } + if (/^data:[^;]+;base64,/.test(t)) { + for (var n = atob(t.split(`,`)[1]), r = new Uint8Array(n.length), i = 0; i < n.length; ++i) + r[i] = n.charCodeAt(i); + c(r.buffer, e); + } else { + var o = new XMLHttpRequest(); + (o.open(e._xhr.method, t, !0), + (o.withCredentials = e._xhr.withCredentials), + (o.responseType = `arraybuffer`), + e._xhr.headers && + Object.keys(e._xhr.headers).forEach(function (t) { + o.setRequestHeader(t, e._xhr.headers[t]); + }), + (o.onload = function () { + var t = (o.status + ``)[0]; + if (t !== `0` && t !== `2` && t !== `3`) { + e._emit(`loaderror`, null, `Failed loading audio file with status: ` + o.status + `.`); + return; + } + c(o.response, e); + }), + (o.onerror = function () { + e._webAudio && ((e._html5 = !0), (e._webAudio = !1), (e._sounds = []), delete a[t], e.load()); + }), + s(o)); + } + }, + s = function (e) { + try { + e.send(); + } catch { + e.onerror(); + } + }, + c = function (e, t) { + var r = function () { + t._emit(`loaderror`, null, `Decoding audio data failed.`); + }, + i = function (e) { + e && t._sounds.length > 0 ? ((a[t._src] = e), l(t, e)) : r(); + }; + typeof Promise < `u` && n.ctx.decodeAudioData.length === 1 + ? n.ctx.decodeAudioData(e).then(i).catch(r) + : n.ctx.decodeAudioData(e, i, r); + }, + l = function (e, t) { + (t && !e._duration && (e._duration = t.duration), + Object.keys(e._sprite).length === 0 && (e._sprite = { __default: [0, e._duration * 1e3] }), + e._state !== `loaded` && ((e._state = `loaded`), e._emit(`load`), e._loadQueue())); + }, + u = function () { + if (n.usingWebAudio) { + try { + typeof AudioContext < `u` + ? (n.ctx = new AudioContext()) + : typeof webkitAudioContext < `u` + ? (n.ctx = new webkitAudioContext()) + : (n.usingWebAudio = !1); + } catch { + n.usingWebAudio = !1; + } + n.ctx || (n.usingWebAudio = !1); + var e = /iP(hone|od|ad)/.test(n._navigator && n._navigator.platform), + t = n._navigator && n._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/), + r = t ? parseInt(t[1], 10) : null; + if (e && r && r < 9) { + var i = /safari/.test(n._navigator && n._navigator.userAgent.toLowerCase()); + n._navigator && !i && (n.usingWebAudio = !1); + } + (n.usingWebAudio && + ((n.masterGain = n.ctx.createGain === void 0 ? n.ctx.createGainNode() : n.ctx.createGain()), + n.masterGain.gain.setValueAtTime(n._muted ? 0 : n._volume, n.ctx.currentTime), + n.masterGain.connect(n.ctx.destination)), + n._setup()); + } + }; + (typeof define == `function` && + define.amd && + define([], function () { + return { Howler: n, Howl: r }; + }), + e !== void 0 && ((e.Howler = n), (e.Howl = r)), + typeof global < `u` + ? ((global.HowlerGlobal = t), (global.Howler = n), (global.Howl = r), (global.Sound = i)) + : typeof window < `u` && + ((window.HowlerGlobal = t), (window.Howler = n), (window.Howl = r), (window.Sound = i))); + })(), + (function () { + ((HowlerGlobal.prototype._pos = [0, 0, 0]), + (HowlerGlobal.prototype._orientation = [0, 0, -1, 0, 1, 0]), + (HowlerGlobal.prototype.stereo = function (e) { + var t = this; + if (!t.ctx || !t.ctx.listener) return t; + for (var n = t._howls.length - 1; n >= 0; n--) t._howls[n].stereo(e); + return t; + }), + (HowlerGlobal.prototype.pos = function (e, t, n) { + var r = this; + if (!r.ctx || !r.ctx.listener) return r; + if ( + ((t = typeof t == `number` ? t : r._pos[1]), + (n = typeof n == `number` ? n : r._pos[2]), + typeof e == `number`) + ) + ((r._pos = [e, t, n]), + r.ctx.listener.positionX === void 0 + ? r.ctx.listener.setPosition(r._pos[0], r._pos[1], r._pos[2]) + : (r.ctx.listener.positionX.setTargetAtTime(r._pos[0], Howler.ctx.currentTime, 0.1), + r.ctx.listener.positionY.setTargetAtTime(r._pos[1], Howler.ctx.currentTime, 0.1), + r.ctx.listener.positionZ.setTargetAtTime(r._pos[2], Howler.ctx.currentTime, 0.1))); + else return r._pos; + return r; + }), + (HowlerGlobal.prototype.orientation = function (e, t, n, r, i, a) { + var o = this; + if (!o.ctx || !o.ctx.listener) return o; + var s = o._orientation; + if ( + ((t = typeof t == `number` ? t : s[1]), + (n = typeof n == `number` ? n : s[2]), + (r = typeof r == `number` ? r : s[3]), + (i = typeof i == `number` ? i : s[4]), + (a = typeof a == `number` ? a : s[5]), + typeof e == `number`) + ) + ((o._orientation = [e, t, n, r, i, a]), + o.ctx.listener.forwardX === void 0 + ? o.ctx.listener.setOrientation(e, t, n, r, i, a) + : (o.ctx.listener.forwardX.setTargetAtTime(e, Howler.ctx.currentTime, 0.1), + o.ctx.listener.forwardY.setTargetAtTime(t, Howler.ctx.currentTime, 0.1), + o.ctx.listener.forwardZ.setTargetAtTime(n, Howler.ctx.currentTime, 0.1), + o.ctx.listener.upX.setTargetAtTime(r, Howler.ctx.currentTime, 0.1), + o.ctx.listener.upY.setTargetAtTime(i, Howler.ctx.currentTime, 0.1), + o.ctx.listener.upZ.setTargetAtTime(a, Howler.ctx.currentTime, 0.1))); + else return s; + return o; + }), + (Howl.prototype.init = (function (e) { + return function (t) { + var n = this; + return ( + (n._orientation = t.orientation || [1, 0, 0]), + (n._stereo = t.stereo || null), + (n._pos = t.pos || null), + (n._pannerAttr = { + coneInnerAngle: t.coneInnerAngle === void 0 ? 360 : t.coneInnerAngle, + coneOuterAngle: t.coneOuterAngle === void 0 ? 360 : t.coneOuterAngle, + coneOuterGain: t.coneOuterGain === void 0 ? 0 : t.coneOuterGain, + distanceModel: t.distanceModel === void 0 ? `inverse` : t.distanceModel, + maxDistance: t.maxDistance === void 0 ? 1e4 : t.maxDistance, + panningModel: t.panningModel === void 0 ? `HRTF` : t.panningModel, + refDistance: t.refDistance === void 0 ? 1 : t.refDistance, + rolloffFactor: t.rolloffFactor === void 0 ? 1 : t.rolloffFactor, + }), + (n._onstereo = t.onstereo ? [{ fn: t.onstereo }] : []), + (n._onpos = t.onpos ? [{ fn: t.onpos }] : []), + (n._onorientation = t.onorientation ? [{ fn: t.onorientation }] : []), + e.call(this, t) + ); + }; + })(Howl.prototype.init)), + (Howl.prototype.stereo = function (t, n) { + var r = this; + if (!r._webAudio) return r; + if (r._state !== `loaded`) + return ( + r._queue.push({ + event: `stereo`, + action: function () { + r.stereo(t, n); + }, + }), + r + ); + var i = Howler.ctx.createStereoPanner === void 0 ? `spatial` : `stereo`; + if (n === void 0) + if (typeof t == `number`) ((r._stereo = t), (r._pos = [t, 0, 0])); + else return r._stereo; + for (var a = r._getSoundIds(n), o = 0; o < a.length; o++) { + var s = r._soundById(a[o]); + if (s) + if (typeof t == `number`) + ((s._stereo = t), + (s._pos = [t, 0, 0]), + s._node && + ((s._pannerAttr.panningModel = `equalpower`), + (!s._panner || !s._panner.pan) && e(s, i), + i === `spatial` + ? s._panner.positionX === void 0 + ? s._panner.setPosition(t, 0, 0) + : (s._panner.positionX.setValueAtTime(t, Howler.ctx.currentTime), + s._panner.positionY.setValueAtTime(0, Howler.ctx.currentTime), + s._panner.positionZ.setValueAtTime(0, Howler.ctx.currentTime)) + : s._panner.pan.setValueAtTime(t, Howler.ctx.currentTime)), + r._emit(`stereo`, s._id)); + else return s._stereo; + } + return r; + }), + (Howl.prototype.pos = function (t, n, r, i) { + var a = this; + if (!a._webAudio) return a; + if (a._state !== `loaded`) + return ( + a._queue.push({ + event: `pos`, + action: function () { + a.pos(t, n, r, i); + }, + }), + a + ); + if (((n = typeof n == `number` ? n : 0), (r = typeof r == `number` ? r : -0.5), i === void 0)) + if (typeof t == `number`) a._pos = [t, n, r]; + else return a._pos; + for (var o = a._getSoundIds(i), s = 0; s < o.length; s++) { + var c = a._soundById(o[s]); + if (c) + if (typeof t == `number`) + ((c._pos = [t, n, r]), + c._node && + ((!c._panner || c._panner.pan) && e(c, `spatial`), + c._panner.positionX === void 0 + ? c._panner.setPosition(t, n, r) + : (c._panner.positionX.setValueAtTime(t, Howler.ctx.currentTime), + c._panner.positionY.setValueAtTime(n, Howler.ctx.currentTime), + c._panner.positionZ.setValueAtTime(r, Howler.ctx.currentTime))), + a._emit(`pos`, c._id)); + else return c._pos; + } + return a; + }), + (Howl.prototype.orientation = function (t, n, r, i) { + var a = this; + if (!a._webAudio) return a; + if (a._state !== `loaded`) + return ( + a._queue.push({ + event: `orientation`, + action: function () { + a.orientation(t, n, r, i); + }, + }), + a + ); + if ( + ((n = typeof n == `number` ? n : a._orientation[1]), + (r = typeof r == `number` ? r : a._orientation[2]), + i === void 0) + ) + if (typeof t == `number`) a._orientation = [t, n, r]; + else return a._orientation; + for (var o = a._getSoundIds(i), s = 0; s < o.length; s++) { + var c = a._soundById(o[s]); + if (c) + if (typeof t == `number`) + ((c._orientation = [t, n, r]), + c._node && + (c._panner || ((c._pos ||= a._pos || [0, 0, -0.5]), e(c, `spatial`)), + c._panner.orientationX === void 0 + ? c._panner.setOrientation(t, n, r) + : (c._panner.orientationX.setValueAtTime(t, Howler.ctx.currentTime), + c._panner.orientationY.setValueAtTime(n, Howler.ctx.currentTime), + c._panner.orientationZ.setValueAtTime(r, Howler.ctx.currentTime))), + a._emit(`orientation`, c._id)); + else return c._orientation; + } + return a; + }), + (Howl.prototype.pannerAttr = function () { + var t = this, + n = arguments, + r, + i, + a; + if (!t._webAudio) return t; + if (n.length === 0) return t._pannerAttr; + if (n.length === 1) + if (typeof n[0] == `object`) + ((r = n[0]), + i === void 0 && + ((r.pannerAttr ||= { + coneInnerAngle: r.coneInnerAngle, + coneOuterAngle: r.coneOuterAngle, + coneOuterGain: r.coneOuterGain, + distanceModel: r.distanceModel, + maxDistance: r.maxDistance, + refDistance: r.refDistance, + rolloffFactor: r.rolloffFactor, + panningModel: r.panningModel, + }), + (t._pannerAttr = { + coneInnerAngle: + r.pannerAttr.coneInnerAngle === void 0 ? t._coneInnerAngle : r.pannerAttr.coneInnerAngle, + coneOuterAngle: + r.pannerAttr.coneOuterAngle === void 0 ? t._coneOuterAngle : r.pannerAttr.coneOuterAngle, + coneOuterGain: + r.pannerAttr.coneOuterGain === void 0 ? t._coneOuterGain : r.pannerAttr.coneOuterGain, + distanceModel: + r.pannerAttr.distanceModel === void 0 ? t._distanceModel : r.pannerAttr.distanceModel, + maxDistance: r.pannerAttr.maxDistance === void 0 ? t._maxDistance : r.pannerAttr.maxDistance, + refDistance: r.pannerAttr.refDistance === void 0 ? t._refDistance : r.pannerAttr.refDistance, + rolloffFactor: + r.pannerAttr.rolloffFactor === void 0 ? t._rolloffFactor : r.pannerAttr.rolloffFactor, + panningModel: r.pannerAttr.panningModel === void 0 ? t._panningModel : r.pannerAttr.panningModel, + }))); + else return ((a = t._soundById(parseInt(n[0], 10))), a ? a._pannerAttr : t._pannerAttr); + else n.length === 2 && ((r = n[0]), (i = parseInt(n[1], 10))); + for (var o = t._getSoundIds(i), s = 0; s < o.length; s++) + if (((a = t._soundById(o[s])), a)) { + var c = a._pannerAttr; + c = { + coneInnerAngle: r.coneInnerAngle === void 0 ? c.coneInnerAngle : r.coneInnerAngle, + coneOuterAngle: r.coneOuterAngle === void 0 ? c.coneOuterAngle : r.coneOuterAngle, + coneOuterGain: r.coneOuterGain === void 0 ? c.coneOuterGain : r.coneOuterGain, + distanceModel: r.distanceModel === void 0 ? c.distanceModel : r.distanceModel, + maxDistance: r.maxDistance === void 0 ? c.maxDistance : r.maxDistance, + refDistance: r.refDistance === void 0 ? c.refDistance : r.refDistance, + rolloffFactor: r.rolloffFactor === void 0 ? c.rolloffFactor : r.rolloffFactor, + panningModel: r.panningModel === void 0 ? c.panningModel : r.panningModel, + }; + var l = a._panner; + ((l ||= ((a._pos ||= t._pos || [0, 0, -0.5]), e(a, `spatial`), a._panner)), + (l.coneInnerAngle = c.coneInnerAngle), + (l.coneOuterAngle = c.coneOuterAngle), + (l.coneOuterGain = c.coneOuterGain), + (l.distanceModel = c.distanceModel), + (l.maxDistance = c.maxDistance), + (l.refDistance = c.refDistance), + (l.rolloffFactor = c.rolloffFactor), + (l.panningModel = c.panningModel)); + } + return t; + }), + (Sound.prototype.init = (function (e) { + return function () { + var t = this, + n = t._parent; + ((t._orientation = n._orientation), + (t._stereo = n._stereo), + (t._pos = n._pos), + (t._pannerAttr = n._pannerAttr), + e.call(this), + t._stereo ? n.stereo(t._stereo) : t._pos && n.pos(t._pos[0], t._pos[1], t._pos[2], t._id)); + }; + })(Sound.prototype.init)), + (Sound.prototype.reset = (function (e) { + return function () { + var t = this, + n = t._parent; + return ( + (t._orientation = n._orientation), + (t._stereo = n._stereo), + (t._pos = n._pos), + (t._pannerAttr = n._pannerAttr), + t._stereo + ? n.stereo(t._stereo) + : t._pos + ? n.pos(t._pos[0], t._pos[1], t._pos[2], t._id) + : t._panner && (t._panner.disconnect(0), (t._panner = void 0), n._refreshBuffer(t)), + e.call(this) + ); + }; + })(Sound.prototype.reset))); + var e = function (e, t) { + ((t ||= `spatial`), + t === `spatial` + ? ((e._panner = Howler.ctx.createPanner()), + (e._panner.coneInnerAngle = e._pannerAttr.coneInnerAngle), + (e._panner.coneOuterAngle = e._pannerAttr.coneOuterAngle), + (e._panner.coneOuterGain = e._pannerAttr.coneOuterGain), + (e._panner.distanceModel = e._pannerAttr.distanceModel), + (e._panner.maxDistance = e._pannerAttr.maxDistance), + (e._panner.refDistance = e._pannerAttr.refDistance), + (e._panner.rolloffFactor = e._pannerAttr.rolloffFactor), + (e._panner.panningModel = e._pannerAttr.panningModel), + e._panner.positionX === void 0 + ? e._panner.setPosition(e._pos[0], e._pos[1], e._pos[2]) + : (e._panner.positionX.setValueAtTime(e._pos[0], Howler.ctx.currentTime), + e._panner.positionY.setValueAtTime(e._pos[1], Howler.ctx.currentTime), + e._panner.positionZ.setValueAtTime(e._pos[2], Howler.ctx.currentTime)), + e._panner.orientationX === void 0 + ? e._panner.setOrientation(e._orientation[0], e._orientation[1], e._orientation[2]) + : (e._panner.orientationX.setValueAtTime(e._orientation[0], Howler.ctx.currentTime), + e._panner.orientationY.setValueAtTime(e._orientation[1], Howler.ctx.currentTime), + e._panner.orientationZ.setValueAtTime(e._orientation[2], Howler.ctx.currentTime))) + : ((e._panner = Howler.ctx.createStereoPanner()), + e._panner.pan.setValueAtTime(e._stereo, Howler.ctx.currentTime)), + e._panner.connect(e._node), + e._paused || e._parent.pause(e._id, !0).play(e._id, !0)); + }; + })()); +}); +export default t(); diff --git a/pro/dist/assets/index-B2cVy8T8.js b/pro/dist/assets/index-B2cVy8T8.js new file mode 100644 index 0000000..8033096 --- /dev/null +++ b/pro/dist/assets/index-B2cVy8T8.js @@ -0,0 +1,18396 @@ +var e = Object.create, + t = Object.defineProperty, + n = Object.getOwnPropertyDescriptor, + r = Object.getOwnPropertyNames, + i = Object.getPrototypeOf, + a = Object.prototype.hasOwnProperty, + o = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), (e = null)), t.exports), + s = (e, n) => { + let r = {}; + for (var i in e) t(r, i, { get: e[i], enumerable: !0 }); + return (n || t(r, Symbol.toStringTag, { value: `Module` }), r); + }, + c = (e, i, o, s) => { + if ((i && typeof i == `object`) || typeof i == `function`) + for (var c = r(i), l = 0, u = c.length, d; l < u; l++) + ((d = c[l]), + !a.call(e, d) && + d !== o && + t(e, d, { get: ((e) => i[e]).bind(null, d), enumerable: !(s = n(i, d)) || s.enumerable })); + return e; + }, + l = (n, r, a) => ( + (a = n == null ? {} : e(i(n))), + c(r || !n || !n.__esModule ? t(a, `default`, { value: n, enumerable: !0 }) : a, n) + ); +(function () { + let e = document.createElement(`link`).relList; + if (e && e.supports && e.supports(`modulepreload`)) return; + for (let e of document.querySelectorAll(`link[rel="modulepreload"]`)) n(e); + new MutationObserver((e) => { + for (let t of e) + if (t.type === `childList`) for (let e of t.addedNodes) e.tagName === `LINK` && e.rel === `modulepreload` && n(e); + }).observe(document, { childList: !0, subtree: !0 }); + function t(e) { + let t = {}; + return ( + e.integrity && (t.integrity = e.integrity), + e.referrerPolicy && (t.referrerPolicy = e.referrerPolicy), + e.crossOrigin === `use-credentials` + ? (t.credentials = `include`) + : e.crossOrigin === `anonymous` + ? (t.credentials = `omit`) + : (t.credentials = `same-origin`), + t + ); + } + function n(e) { + if (e.ep) return; + e.ep = !0; + let n = t(e); + fetch(e.href, n); + } +})(); +var u = o((e) => { + var t = Symbol.for(`react.element`), + n = Symbol.for(`react.portal`), + r = Symbol.for(`react.fragment`), + i = Symbol.for(`react.strict_mode`), + a = Symbol.for(`react.profiler`), + o = Symbol.for(`react.provider`), + s = Symbol.for(`react.context`), + c = Symbol.for(`react.forward_ref`), + l = Symbol.for(`react.suspense`), + u = Symbol.for(`react.memo`), + d = Symbol.for(`react.lazy`), + f = Symbol.iterator; + function p(e) { + return typeof e != `object` || !e + ? null + : ((e = (f && e[f]) || e[`@@iterator`]), typeof e == `function` ? e : null); + } + var m = { + isMounted: function () { + return !1; + }, + enqueueForceUpdate: function () {}, + enqueueReplaceState: function () {}, + enqueueSetState: function () {}, + }, + h = Object.assign, + g = {}; + function _(e, t, n) { + ((this.props = e), (this.context = t), (this.refs = g), (this.updater = n || m)); + } + ((_.prototype.isReactComponent = {}), + (_.prototype.setState = function (e, t) { + if (typeof e != `object` && typeof e != `function` && e != null) + throw Error( + `setState(...): takes an object of state variables to update or a function which returns an object of state variables.`, + ); + this.updater.enqueueSetState(this, e, t, `setState`); + }), + (_.prototype.forceUpdate = function (e) { + this.updater.enqueueForceUpdate(this, e, `forceUpdate`); + })); + function v() {} + v.prototype = _.prototype; + function y(e, t, n) { + ((this.props = e), (this.context = t), (this.refs = g), (this.updater = n || m)); + } + var b = (y.prototype = new v()); + ((b.constructor = y), h(b, _.prototype), (b.isPureReactComponent = !0)); + var x = Array.isArray, + S = Object.prototype.hasOwnProperty, + C = { current: null }, + w = { key: !0, ref: !0, __self: !0, __source: !0 }; + function T(e, n, r) { + var i, + a = {}, + o = null, + s = null; + if (n != null) + for (i in (n.ref !== void 0 && (s = n.ref), n.key !== void 0 && (o = `` + n.key), n)) + S.call(n, i) && !w.hasOwnProperty(i) && (a[i] = n[i]); + var c = arguments.length - 2; + if (c === 1) a.children = r; + else if (1 < c) { + for (var l = Array(c), u = 0; u < c; u++) l[u] = arguments[u + 2]; + a.children = l; + } + if (e && e.defaultProps) for (i in ((c = e.defaultProps), c)) a[i] === void 0 && (a[i] = c[i]); + return { $$typeof: t, type: e, key: o, ref: s, props: a, _owner: C.current }; + } + function E(e, n) { + return { $$typeof: t, type: e.type, key: n, ref: e.ref, props: e.props, _owner: e._owner }; + } + function D(e) { + return typeof e == `object` && !!e && e.$$typeof === t; + } + function ee(e) { + var t = { '=': `=0`, ':': `=2` }; + return ( + `$` + + e.replace(/[=:]/g, function (e) { + return t[e]; + }) + ); + } + var O = /\/+/g; + function te(e, t) { + return typeof e == `object` && e && e.key != null ? ee(`` + e.key) : t.toString(36); + } + function k(e, r, i, a, o) { + var s = typeof e; + (s === `undefined` || s === `boolean`) && (e = null); + var c = !1; + if (e === null) c = !0; + else + switch (s) { + case `string`: + case `number`: + c = !0; + break; + case `object`: + switch (e.$$typeof) { + case t: + case n: + c = !0; + } + } + if (c) + return ( + (c = e), + (o = o(c)), + (e = a === `` ? `.` + te(c, 0) : a), + x(o) + ? ((i = ``), + e != null && (i = e.replace(O, `$&/`) + `/`), + k(o, r, i, ``, function (e) { + return e; + })) + : o != null && + (D(o) && + (o = E(o, i + (!o.key || (c && c.key === o.key) ? `` : (`` + o.key).replace(O, `$&/`) + `/`) + e)), + r.push(o)), + 1 + ); + if (((c = 0), (a = a === `` ? `.` : a + `:`), x(e))) + for (var l = 0; l < e.length; l++) { + s = e[l]; + var u = a + te(s, l); + c += k(s, r, i, u, o); + } + else if (((u = p(e)), typeof u == `function`)) + for (e = u.call(e), l = 0; !(s = e.next()).done; ) + ((s = s.value), (u = a + te(s, l++)), (c += k(s, r, i, u, o))); + else if (s === `object`) + throw ( + (r = String(e)), + Error( + `Objects are not valid as a React child (found: ` + + (r === `[object Object]` ? `object with keys {` + Object.keys(e).join(`, `) + `}` : r) + + `). If you meant to render a collection of children, use an array instead.`, + ) + ); + return c; + } + function ne(e, t, n) { + if (e == null) return e; + var r = [], + i = 0; + return ( + k(e, r, ``, ``, function (e) { + return t.call(n, e, i++); + }), + r + ); + } + function re(e) { + if (e._status === -1) { + var t = e._result; + ((t = t()), + t.then( + function (t) { + (e._status === 0 || e._status === -1) && ((e._status = 1), (e._result = t)); + }, + function (t) { + (e._status === 0 || e._status === -1) && ((e._status = 2), (e._result = t)); + }, + ), + e._status === -1 && ((e._status = 0), (e._result = t))); + } + if (e._status === 1) return e._result.default; + throw e._result; + } + var A = { current: null }, + j = { transition: null }, + ie = { ReactCurrentDispatcher: A, ReactCurrentBatchConfig: j, ReactCurrentOwner: C }; + function ae() { + throw Error(`act(...) is not supported in production builds of React.`); + } + ((e.Children = { + map: ne, + forEach: function (e, t, n) { + ne( + e, + function () { + t.apply(this, arguments); + }, + n, + ); + }, + count: function (e) { + var t = 0; + return ( + ne(e, function () { + t++; + }), + t + ); + }, + toArray: function (e) { + return ( + ne(e, function (e) { + return e; + }) || [] + ); + }, + only: function (e) { + if (!D(e)) throw Error(`React.Children.only expected to receive a single React element child.`); + return e; + }, + }), + (e.Component = _), + (e.Fragment = r), + (e.Profiler = a), + (e.PureComponent = y), + (e.StrictMode = i), + (e.Suspense = l), + (e.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = ie), + (e.act = ae), + (e.cloneElement = function (e, n, r) { + if (e == null) + throw Error(`React.cloneElement(...): The argument must be a React element, but you passed ` + e + `.`); + var i = h({}, e.props), + a = e.key, + o = e.ref, + s = e._owner; + if (n != null) { + if ( + (n.ref !== void 0 && ((o = n.ref), (s = C.current)), + n.key !== void 0 && (a = `` + n.key), + e.type && e.type.defaultProps) + ) + var c = e.type.defaultProps; + for (l in n) S.call(n, l) && !w.hasOwnProperty(l) && (i[l] = n[l] === void 0 && c !== void 0 ? c[l] : n[l]); + } + var l = arguments.length - 2; + if (l === 1) i.children = r; + else if (1 < l) { + c = Array(l); + for (var u = 0; u < l; u++) c[u] = arguments[u + 2]; + i.children = c; + } + return { $$typeof: t, type: e.type, key: a, ref: o, props: i, _owner: s }; + }), + (e.createContext = function (e) { + return ( + (e = { + $$typeof: s, + _currentValue: e, + _currentValue2: e, + _threadCount: 0, + Provider: null, + Consumer: null, + _defaultValue: null, + _globalName: null, + }), + (e.Provider = { $$typeof: o, _context: e }), + (e.Consumer = e) + ); + }), + (e.createElement = T), + (e.createFactory = function (e) { + var t = T.bind(null, e); + return ((t.type = e), t); + }), + (e.createRef = function () { + return { current: null }; + }), + (e.forwardRef = function (e) { + return { $$typeof: c, render: e }; + }), + (e.isValidElement = D), + (e.lazy = function (e) { + return { $$typeof: d, _payload: { _status: -1, _result: e }, _init: re }; + }), + (e.memo = function (e, t) { + return { $$typeof: u, type: e, compare: t === void 0 ? null : t }; + }), + (e.startTransition = function (e) { + var t = j.transition; + j.transition = {}; + try { + e(); + } finally { + j.transition = t; + } + }), + (e.unstable_act = ae), + (e.useCallback = function (e, t) { + return A.current.useCallback(e, t); + }), + (e.useContext = function (e) { + return A.current.useContext(e); + }), + (e.useDebugValue = function () {}), + (e.useDeferredValue = function (e) { + return A.current.useDeferredValue(e); + }), + (e.useEffect = function (e, t) { + return A.current.useEffect(e, t); + }), + (e.useId = function () { + return A.current.useId(); + }), + (e.useImperativeHandle = function (e, t, n) { + return A.current.useImperativeHandle(e, t, n); + }), + (e.useInsertionEffect = function (e, t) { + return A.current.useInsertionEffect(e, t); + }), + (e.useLayoutEffect = function (e, t) { + return A.current.useLayoutEffect(e, t); + }), + (e.useMemo = function (e, t) { + return A.current.useMemo(e, t); + }), + (e.useReducer = function (e, t, n) { + return A.current.useReducer(e, t, n); + }), + (e.useRef = function (e) { + return A.current.useRef(e); + }), + (e.useState = function (e) { + return A.current.useState(e); + }), + (e.useSyncExternalStore = function (e, t, n) { + return A.current.useSyncExternalStore(e, t, n); + }), + (e.useTransition = function () { + return A.current.useTransition(); + }), + (e.version = `18.3.1`)); + }), + d = o((e, t) => { + t.exports = u(); + }), + f = o((e) => { + function t(e, t) { + var n = e.length; + e.push(t); + a: for (; 0 < n; ) { + var r = (n - 1) >>> 1, + a = e[r]; + if (0 < i(a, t)) ((e[r] = t), (e[n] = a), (n = r)); + else break a; + } + } + function n(e) { + return e.length === 0 ? null : e[0]; + } + function r(e) { + if (e.length === 0) return null; + var t = e[0], + n = e.pop(); + if (n !== t) { + e[0] = n; + a: for (var r = 0, a = e.length, o = a >>> 1; r < o; ) { + var s = 2 * (r + 1) - 1, + c = e[s], + l = s + 1, + u = e[l]; + if (0 > i(c, n)) l < a && 0 > i(u, c) ? ((e[r] = u), (e[l] = n), (r = l)) : ((e[r] = c), (e[s] = n), (r = s)); + else if (l < a && 0 > i(u, n)) ((e[r] = u), (e[l] = n), (r = l)); + else break a; + } + } + return t; + } + function i(e, t) { + var n = e.sortIndex - t.sortIndex; + return n === 0 ? e.id - t.id : n; + } + if (typeof performance == `object` && typeof performance.now == `function`) { + var a = performance; + e.unstable_now = function () { + return a.now(); + }; + } else { + var o = Date, + s = o.now(); + e.unstable_now = function () { + return o.now() - s; + }; + } + var c = [], + l = [], + u = 1, + d = null, + f = 3, + p = !1, + m = !1, + h = !1, + g = typeof setTimeout == `function` ? setTimeout : null, + _ = typeof clearTimeout == `function` ? clearTimeout : null, + v = typeof setImmediate < `u` ? setImmediate : null; + typeof navigator < `u` && + navigator.scheduling !== void 0 && + navigator.scheduling.isInputPending !== void 0 && + navigator.scheduling.isInputPending.bind(navigator.scheduling); + function y(e) { + for (var i = n(l); i !== null; ) { + if (i.callback === null) r(l); + else if (i.startTime <= e) (r(l), (i.sortIndex = i.expirationTime), t(c, i)); + else break; + i = n(l); + } + } + function b(e) { + if (((h = !1), y(e), !m)) + if (n(c) !== null) ((m = !0), ne(x)); + else { + var t = n(l); + t !== null && re(b, t.startTime - e); + } + } + function x(t, i) { + ((m = !1), h && ((h = !1), _(w), (w = -1)), (p = !0)); + var a = f; + try { + for (y(i), d = n(c); d !== null && (!(d.expirationTime > i) || (t && !D())); ) { + var o = d.callback; + if (typeof o == `function`) { + ((d.callback = null), (f = d.priorityLevel)); + var s = o(d.expirationTime <= i); + ((i = e.unstable_now()), typeof s == `function` ? (d.callback = s) : d === n(c) && r(c), y(i)); + } else r(c); + d = n(c); + } + if (d !== null) var u = !0; + else { + var g = n(l); + (g !== null && re(b, g.startTime - i), (u = !1)); + } + return u; + } finally { + ((d = null), (f = a), (p = !1)); + } + } + var S = !1, + C = null, + w = -1, + T = 5, + E = -1; + function D() { + return !(e.unstable_now() - E < T); + } + function ee() { + if (C !== null) { + var t = e.unstable_now(); + E = t; + var n = !0; + try { + n = C(!0, t); + } finally { + n ? O() : ((S = !1), (C = null)); + } + } else S = !1; + } + var O; + if (typeof v == `function`) + O = function () { + v(ee); + }; + else if (typeof MessageChannel < `u`) { + var te = new MessageChannel(), + k = te.port2; + ((te.port1.onmessage = ee), + (O = function () { + k.postMessage(null); + })); + } else + O = function () { + g(ee, 0); + }; + function ne(e) { + ((C = e), S || ((S = !0), O())); + } + function re(t, n) { + w = g(function () { + t(e.unstable_now()); + }, n); + } + ((e.unstable_IdlePriority = 5), + (e.unstable_ImmediatePriority = 1), + (e.unstable_LowPriority = 4), + (e.unstable_NormalPriority = 3), + (e.unstable_Profiling = null), + (e.unstable_UserBlockingPriority = 2), + (e.unstable_cancelCallback = function (e) { + e.callback = null; + }), + (e.unstable_continueExecution = function () { + m || p || ((m = !0), ne(x)); + }), + (e.unstable_forceFrameRate = function (e) { + 0 > e || 125 < e + ? console.error( + `forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported`, + ) + : (T = 0 < e ? Math.floor(1e3 / e) : 5); + }), + (e.unstable_getCurrentPriorityLevel = function () { + return f; + }), + (e.unstable_getFirstCallbackNode = function () { + return n(c); + }), + (e.unstable_next = function (e) { + switch (f) { + case 1: + case 2: + case 3: + var t = 3; + break; + default: + t = f; + } + var n = f; + f = t; + try { + return e(); + } finally { + f = n; + } + }), + (e.unstable_pauseExecution = function () {}), + (e.unstable_requestPaint = function () {}), + (e.unstable_runWithPriority = function (e, t) { + switch (e) { + case 1: + case 2: + case 3: + case 4: + case 5: + break; + default: + e = 3; + } + var n = f; + f = e; + try { + return t(); + } finally { + f = n; + } + }), + (e.unstable_scheduleCallback = function (r, i, a) { + var o = e.unstable_now(); + switch ( + (typeof a == `object` && a ? ((a = a.delay), (a = typeof a == `number` && 0 < a ? o + a : o)) : (a = o), r) + ) { + case 1: + var s = -1; + break; + case 2: + s = 250; + break; + case 5: + s = 1073741823; + break; + case 4: + s = 1e4; + break; + default: + s = 5e3; + } + return ( + (s = a + s), + (r = { id: u++, callback: i, priorityLevel: r, startTime: a, expirationTime: s, sortIndex: -1 }), + a > o + ? ((r.sortIndex = a), + t(l, r), + n(c) === null && r === n(l) && (h ? (_(w), (w = -1)) : (h = !0), re(b, a - o))) + : ((r.sortIndex = s), t(c, r), m || p || ((m = !0), ne(x))), + r + ); + }), + (e.unstable_shouldYield = D), + (e.unstable_wrapCallback = function (e) { + var t = f; + return function () { + var n = f; + f = t; + try { + return e.apply(this, arguments); + } finally { + f = n; + } + }; + })); + }), + p = o((e, t) => { + t.exports = f(); + }), + m = o((e) => { + var t = d(), + n = p(); + function r(e) { + for (var t = `https://reactjs.org/docs/error-decoder.html?invariant=` + e, n = 1; n < arguments.length; n++) + t += `&args[]=` + encodeURIComponent(arguments[n]); + return ( + `Minified React error #` + + e + + `; visit ` + + t + + ` for the full message or use the non-minified dev environment for full errors and additional helpful warnings.` + ); + } + var i = new Set(), + a = {}; + function o(e, t) { + (s(e, t), s(e + `Capture`, t)); + } + function s(e, t) { + for (a[e] = t, e = 0; e < t.length; e++) i.add(t[e]); + } + var c = !(typeof window > `u` || window.document === void 0 || window.document.createElement === void 0), + l = Object.prototype.hasOwnProperty, + u = + /^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/, + f = {}, + m = {}; + function h(e) { + return l.call(m, e) ? !0 : l.call(f, e) ? !1 : u.test(e) ? (m[e] = !0) : ((f[e] = !0), !1); + } + function g(e, t, n, r) { + if (n !== null && n.type === 0) return !1; + switch (typeof t) { + case `function`: + case `symbol`: + return !0; + case `boolean`: + return r + ? !1 + : n === null + ? ((e = e.toLowerCase().slice(0, 5)), e !== `data-` && e !== `aria-`) + : !n.acceptsBooleans; + default: + return !1; + } + } + function _(e, t, n, r) { + if (t == null || g(e, t, n, r)) return !0; + if (r) return !1; + if (n !== null) + switch (n.type) { + case 3: + return !t; + case 4: + return !1 === t; + case 5: + return isNaN(t); + case 6: + return isNaN(t) || 1 > t; + } + return !1; + } + function v(e, t, n, r, i, a, o) { + ((this.acceptsBooleans = t === 2 || t === 3 || t === 4), + (this.attributeName = r), + (this.attributeNamespace = i), + (this.mustUseProperty = n), + (this.propertyName = e), + (this.type = t), + (this.sanitizeURL = a), + (this.removeEmptyString = o)); + } + var y = {}; + (`children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style` + .split(` `) + .forEach(function (e) { + y[e] = new v(e, 0, !1, e, null, !1, !1); + }), + [ + [`acceptCharset`, `accept-charset`], + [`className`, `class`], + [`htmlFor`, `for`], + [`httpEquiv`, `http-equiv`], + ].forEach(function (e) { + var t = e[0]; + y[t] = new v(t, 1, !1, e[1], null, !1, !1); + }), + [`contentEditable`, `draggable`, `spellCheck`, `value`].forEach(function (e) { + y[e] = new v(e, 2, !1, e.toLowerCase(), null, !1, !1); + }), + [`autoReverse`, `externalResourcesRequired`, `focusable`, `preserveAlpha`].forEach(function (e) { + y[e] = new v(e, 2, !1, e, null, !1, !1); + }), + `allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope` + .split(` `) + .forEach(function (e) { + y[e] = new v(e, 3, !1, e.toLowerCase(), null, !1, !1); + }), + [`checked`, `multiple`, `muted`, `selected`].forEach(function (e) { + y[e] = new v(e, 3, !0, e, null, !1, !1); + }), + [`capture`, `download`].forEach(function (e) { + y[e] = new v(e, 4, !1, e, null, !1, !1); + }), + [`cols`, `rows`, `size`, `span`].forEach(function (e) { + y[e] = new v(e, 6, !1, e, null, !1, !1); + }), + [`rowSpan`, `start`].forEach(function (e) { + y[e] = new v(e, 5, !1, e.toLowerCase(), null, !1, !1); + })); + var b = /[\-:]([a-z])/g; + function x(e) { + return e[1].toUpperCase(); + } + (`accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height` + .split(` `) + .forEach(function (e) { + var t = e.replace(b, x); + y[t] = new v(t, 1, !1, e, null, !1, !1); + }), + `xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type`.split(` `).forEach(function (e) { + var t = e.replace(b, x); + y[t] = new v(t, 1, !1, e, `http://www.w3.org/1999/xlink`, !1, !1); + }), + [`xml:base`, `xml:lang`, `xml:space`].forEach(function (e) { + var t = e.replace(b, x); + y[t] = new v(t, 1, !1, e, `http://www.w3.org/XML/1998/namespace`, !1, !1); + }), + [`tabIndex`, `crossOrigin`].forEach(function (e) { + y[e] = new v(e, 1, !1, e.toLowerCase(), null, !1, !1); + }), + (y.xlinkHref = new v(`xlinkHref`, 1, !1, `xlink:href`, `http://www.w3.org/1999/xlink`, !0, !1)), + [`src`, `href`, `action`, `formAction`].forEach(function (e) { + y[e] = new v(e, 1, !1, e.toLowerCase(), null, !0, !0); + })); + function S(e, t, n, r) { + var i = y.hasOwnProperty(t) ? y[t] : null; + (i === null + ? r || !(2 < t.length) || (t[0] !== `o` && t[0] !== `O`) || (t[1] !== `n` && t[1] !== `N`) + : i.type !== 0) && + (_(t, n, i, r) && (n = null), + r || i === null + ? h(t) && (n === null ? e.removeAttribute(t) : e.setAttribute(t, `` + n)) + : i.mustUseProperty + ? (e[i.propertyName] = n === null ? (i.type === 3 ? !1 : ``) : n) + : ((t = i.attributeName), + (r = i.attributeNamespace), + n === null + ? e.removeAttribute(t) + : ((i = i.type), + (n = i === 3 || (i === 4 && !0 === n) ? `` : `` + n), + r ? e.setAttributeNS(r, t, n) : e.setAttribute(t, n)))); + } + var C = t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + w = Symbol.for(`react.element`), + T = Symbol.for(`react.portal`), + E = Symbol.for(`react.fragment`), + D = Symbol.for(`react.strict_mode`), + ee = Symbol.for(`react.profiler`), + O = Symbol.for(`react.provider`), + te = Symbol.for(`react.context`), + k = Symbol.for(`react.forward_ref`), + ne = Symbol.for(`react.suspense`), + re = Symbol.for(`react.suspense_list`), + A = Symbol.for(`react.memo`), + j = Symbol.for(`react.lazy`), + ie = Symbol.for(`react.offscreen`), + ae = Symbol.iterator; + function oe(e) { + return typeof e != `object` || !e + ? null + : ((e = (ae && e[ae]) || e[`@@iterator`]), typeof e == `function` ? e : null); + } + var M = Object.assign, + se; + function ce(e) { + if (se === void 0) + try { + throw Error(); + } catch (e) { + var t = e.stack.trim().match(/\n( *(at )?)/); + se = (t && t[1]) || ``; + } + return ( + ` +` + + se + + e + ); + } + var le = !1; + function ue(e, t) { + if (!e || le) return ``; + le = !0; + var n = Error.prepareStackTrace; + Error.prepareStackTrace = void 0; + try { + if (t) + if ( + ((t = function () { + throw Error(); + }), + Object.defineProperty(t.prototype, `props`, { + set: function () { + throw Error(); + }, + }), + typeof Reflect == `object` && Reflect.construct) + ) { + try { + Reflect.construct(t, []); + } catch (e) { + var r = e; + } + Reflect.construct(e, [], t); + } else { + try { + t.call(); + } catch (e) { + r = e; + } + e.call(t.prototype); + } + else { + try { + throw Error(); + } catch (e) { + r = e; + } + e(); + } + } catch (t) { + if (t && r && typeof t.stack == `string`) { + for ( + var i = t.stack.split(` +`), + a = r.stack.split(` +`), + o = i.length - 1, + s = a.length - 1; + 1 <= o && 0 <= s && i[o] !== a[s]; + ) + s--; + for (; 1 <= o && 0 <= s; o--, s--) + if (i[o] !== a[s]) { + if (o !== 1 || s !== 1) + do + if ((o--, s--, 0 > s || i[o] !== a[s])) { + var c = + ` +` + i[o].replace(` at new `, ` at `); + return ( + e.displayName && c.includes(``) && (c = c.replace(``, e.displayName)), + c + ); + } + while (1 <= o && 0 <= s); + break; + } + } + } finally { + ((le = !1), (Error.prepareStackTrace = n)); + } + return (e = e ? e.displayName || e.name : ``) ? ce(e) : ``; + } + function de(e) { + switch (e.tag) { + case 5: + return ce(e.type); + case 16: + return ce(`Lazy`); + case 13: + return ce(`Suspense`); + case 19: + return ce(`SuspenseList`); + case 0: + case 2: + case 15: + return ((e = ue(e.type, !1)), e); + case 11: + return ((e = ue(e.type.render, !1)), e); + case 1: + return ((e = ue(e.type, !0)), e); + default: + return ``; + } + } + function fe(e) { + if (e == null) return null; + if (typeof e == `function`) return e.displayName || e.name || null; + if (typeof e == `string`) return e; + switch (e) { + case E: + return `Fragment`; + case T: + return `Portal`; + case ee: + return `Profiler`; + case D: + return `StrictMode`; + case ne: + return `Suspense`; + case re: + return `SuspenseList`; + } + if (typeof e == `object`) + switch (e.$$typeof) { + case te: + return (e.displayName || `Context`) + `.Consumer`; + case O: + return (e._context.displayName || `Context`) + `.Provider`; + case k: + var t = e.render; + return ( + (e = e.displayName), + (e ||= ((e = t.displayName || t.name || ``), e === `` ? `ForwardRef` : `ForwardRef(` + e + `)`)), + e + ); + case A: + return ((t = e.displayName || null), t === null ? fe(e.type) || `Memo` : t); + case j: + ((t = e._payload), (e = e._init)); + try { + return fe(e(t)); + } catch {} + } + return null; + } + function pe(e) { + var t = e.type; + switch (e.tag) { + case 24: + return `Cache`; + case 9: + return (t.displayName || `Context`) + `.Consumer`; + case 10: + return (t._context.displayName || `Context`) + `.Provider`; + case 18: + return `DehydratedFragment`; + case 11: + return ( + (e = t.render), + (e = e.displayName || e.name || ``), + t.displayName || (e === `` ? `ForwardRef` : `ForwardRef(` + e + `)`) + ); + case 7: + return `Fragment`; + case 5: + return t; + case 4: + return `Portal`; + case 3: + return `Root`; + case 6: + return `Text`; + case 16: + return fe(t); + case 8: + return t === D ? `StrictMode` : `Mode`; + case 22: + return `Offscreen`; + case 12: + return `Profiler`; + case 21: + return `Scope`; + case 13: + return `Suspense`; + case 19: + return `SuspenseList`; + case 25: + return `TracingMarker`; + case 1: + case 0: + case 17: + case 2: + case 14: + case 15: + if (typeof t == `function`) return t.displayName || t.name || null; + if (typeof t == `string`) return t; + } + return null; + } + function N(e) { + switch (typeof e) { + case `boolean`: + case `number`: + case `string`: + case `undefined`: + return e; + case `object`: + return e; + default: + return ``; + } + } + function me(e) { + var t = e.type; + return (e = e.nodeName) && e.toLowerCase() === `input` && (t === `checkbox` || t === `radio`); + } + function he(e) { + var t = me(e) ? `checked` : `value`, + n = Object.getOwnPropertyDescriptor(e.constructor.prototype, t), + r = `` + e[t]; + if (!e.hasOwnProperty(t) && n !== void 0 && typeof n.get == `function` && typeof n.set == `function`) { + var i = n.get, + a = n.set; + return ( + Object.defineProperty(e, t, { + configurable: !0, + get: function () { + return i.call(this); + }, + set: function (e) { + ((r = `` + e), a.call(this, e)); + }, + }), + Object.defineProperty(e, t, { enumerable: n.enumerable }), + { + getValue: function () { + return r; + }, + setValue: function (e) { + r = `` + e; + }, + stopTracking: function () { + ((e._valueTracker = null), delete e[t]); + }, + } + ); + } + } + function ge(e) { + e._valueTracker ||= he(e); + } + function _e(e) { + if (!e) return !1; + var t = e._valueTracker; + if (!t) return !0; + var n = t.getValue(), + r = ``; + return (e && (r = me(e) ? (e.checked ? `true` : `false`) : e.value), (e = r), e === n ? !1 : (t.setValue(e), !0)); + } + function ve(e) { + if (((e ||= typeof document < `u` ? document : void 0), e === void 0)) return null; + try { + return e.activeElement || e.body; + } catch { + return e.body; + } + } + function ye(e, t) { + var n = t.checked; + return M({}, t, { + defaultChecked: void 0, + defaultValue: void 0, + value: void 0, + checked: n ?? e._wrapperState.initialChecked, + }); + } + function P(e, t) { + var n = t.defaultValue == null ? `` : t.defaultValue, + r = t.checked == null ? t.defaultChecked : t.checked; + ((n = N(t.value == null ? n : t.value)), + (e._wrapperState = { + initialChecked: r, + initialValue: n, + controlled: t.type === `checkbox` || t.type === `radio` ? t.checked != null : t.value != null, + })); + } + function be(e, t) { + ((t = t.checked), t != null && S(e, `checked`, t, !1)); + } + function xe(e, t) { + be(e, t); + var n = N(t.value), + r = t.type; + if (n != null) + r === `number` + ? ((n === 0 && e.value === ``) || e.value != n) && (e.value = `` + n) + : e.value !== `` + n && (e.value = `` + n); + else if (r === `submit` || r === `reset`) { + e.removeAttribute(`value`); + return; + } + (t.hasOwnProperty(`value`) + ? Ce(e, t.type, n) + : t.hasOwnProperty(`defaultValue`) && Ce(e, t.type, N(t.defaultValue)), + t.checked == null && t.defaultChecked != null && (e.defaultChecked = !!t.defaultChecked)); + } + function Se(e, t, n) { + if (t.hasOwnProperty(`value`) || t.hasOwnProperty(`defaultValue`)) { + var r = t.type; + if (!((r !== `submit` && r !== `reset`) || (t.value !== void 0 && t.value !== null))) return; + ((t = `` + e._wrapperState.initialValue), n || t === e.value || (e.value = t), (e.defaultValue = t)); + } + ((n = e.name), + n !== `` && (e.name = ``), + (e.defaultChecked = !!e._wrapperState.initialChecked), + n !== `` && (e.name = n)); + } + function Ce(e, t, n) { + (t !== `number` || ve(e.ownerDocument) !== e) && + (n == null + ? (e.defaultValue = `` + e._wrapperState.initialValue) + : e.defaultValue !== `` + n && (e.defaultValue = `` + n)); + } + var F = Array.isArray; + function we(e, t, n, r) { + if (((e = e.options), t)) { + t = {}; + for (var i = 0; i < n.length; i++) t[`$` + n[i]] = !0; + for (n = 0; n < e.length; n++) + ((i = t.hasOwnProperty(`$` + e[n].value)), + e[n].selected !== i && (e[n].selected = i), + i && r && (e[n].defaultSelected = !0)); + } else { + for (n = `` + N(n), t = null, i = 0; i < e.length; i++) { + if (e[i].value === n) { + ((e[i].selected = !0), r && (e[i].defaultSelected = !0)); + return; + } + t !== null || e[i].disabled || (t = e[i]); + } + t !== null && (t.selected = !0); + } + } + function Te(e, t) { + if (t.dangerouslySetInnerHTML != null) throw Error(r(91)); + return M({}, t, { value: void 0, defaultValue: void 0, children: `` + e._wrapperState.initialValue }); + } + function Ee(e, t) { + var n = t.value; + if (n == null) { + if (((n = t.children), (t = t.defaultValue), n != null)) { + if (t != null) throw Error(r(92)); + if (F(n)) { + if (1 < n.length) throw Error(r(93)); + n = n[0]; + } + t = n; + } + ((t ??= ``), (n = t)); + } + e._wrapperState = { initialValue: N(n) }; + } + function De(e, t) { + var n = N(t.value), + r = N(t.defaultValue); + (n != null && + ((n = `` + n), + n !== e.value && (e.value = n), + t.defaultValue == null && e.defaultValue !== n && (e.defaultValue = n)), + r != null && (e.defaultValue = `` + r)); + } + function Oe(e) { + var t = e.textContent; + t === e._wrapperState.initialValue && t !== `` && t !== null && (e.value = t); + } + function ke(e) { + switch (e) { + case `svg`: + return `http://www.w3.org/2000/svg`; + case `math`: + return `http://www.w3.org/1998/Math/MathML`; + default: + return `http://www.w3.org/1999/xhtml`; + } + } + function Ae(e, t) { + return e == null || e === `http://www.w3.org/1999/xhtml` + ? ke(t) + : e === `http://www.w3.org/2000/svg` && t === `foreignObject` + ? `http://www.w3.org/1999/xhtml` + : e; + } + var je, + Me = (function (e) { + return typeof MSApp < `u` && MSApp.execUnsafeLocalFunction + ? function (t, n, r, i) { + MSApp.execUnsafeLocalFunction(function () { + return e(t, n, r, i); + }); + } + : e; + })(function (e, t) { + if (e.namespaceURI !== `http://www.w3.org/2000/svg` || `innerHTML` in e) e.innerHTML = t; + else { + for ( + je ||= document.createElement(`div`), + je.innerHTML = `` + t.valueOf().toString() + ``, + t = je.firstChild; + e.firstChild; + ) + e.removeChild(e.firstChild); + for (; t.firstChild; ) e.appendChild(t.firstChild); + } + }); + function Ne(e, t) { + if (t) { + var n = e.firstChild; + if (n && n === e.lastChild && n.nodeType === 3) { + n.nodeValue = t; + return; + } + } + e.textContent = t; + } + var Pe = { + animationIterationCount: !0, + aspectRatio: !0, + borderImageOutset: !0, + borderImageSlice: !0, + borderImageWidth: !0, + boxFlex: !0, + boxFlexGroup: !0, + boxOrdinalGroup: !0, + columnCount: !0, + columns: !0, + flex: !0, + flexGrow: !0, + flexPositive: !0, + flexShrink: !0, + flexNegative: !0, + flexOrder: !0, + gridArea: !0, + gridRow: !0, + gridRowEnd: !0, + gridRowSpan: !0, + gridRowStart: !0, + gridColumn: !0, + gridColumnEnd: !0, + gridColumnSpan: !0, + gridColumnStart: !0, + fontWeight: !0, + lineClamp: !0, + lineHeight: !0, + opacity: !0, + order: !0, + orphans: !0, + tabSize: !0, + widows: !0, + zIndex: !0, + zoom: !0, + fillOpacity: !0, + floodOpacity: !0, + stopOpacity: !0, + strokeDasharray: !0, + strokeDashoffset: !0, + strokeMiterlimit: !0, + strokeOpacity: !0, + strokeWidth: !0, + }, + Fe = [`Webkit`, `ms`, `Moz`, `O`]; + Object.keys(Pe).forEach(function (e) { + Fe.forEach(function (t) { + ((t = t + e.charAt(0).toUpperCase() + e.substring(1)), (Pe[t] = Pe[e])); + }); + }); + function Ie(e, t, n) { + return t == null || typeof t == `boolean` || t === `` + ? `` + : n || typeof t != `number` || t === 0 || (Pe.hasOwnProperty(e) && Pe[e]) + ? (`` + t).trim() + : t + `px`; + } + function Le(e, t) { + for (var n in ((e = e.style), t)) + if (t.hasOwnProperty(n)) { + var r = n.indexOf(`--`) === 0, + i = Ie(n, t[n], r); + (n === `float` && (n = `cssFloat`), r ? e.setProperty(n, i) : (e[n] = i)); + } + } + var Re = M( + { menuitem: !0 }, + { + area: !0, + base: !0, + br: !0, + col: !0, + embed: !0, + hr: !0, + img: !0, + input: !0, + keygen: !0, + link: !0, + meta: !0, + param: !0, + source: !0, + track: !0, + wbr: !0, + }, + ); + function ze(e, t) { + if (t) { + if (Re[e] && (t.children != null || t.dangerouslySetInnerHTML != null)) throw Error(r(137, e)); + if (t.dangerouslySetInnerHTML != null) { + if (t.children != null) throw Error(r(60)); + if (typeof t.dangerouslySetInnerHTML != `object` || !(`__html` in t.dangerouslySetInnerHTML)) + throw Error(r(61)); + } + if (t.style != null && typeof t.style != `object`) throw Error(r(62)); + } + } + function Be(e, t) { + if (e.indexOf(`-`) === -1) return typeof t.is == `string`; + switch (e) { + case `annotation-xml`: + case `color-profile`: + case `font-face`: + case `font-face-src`: + case `font-face-uri`: + case `font-face-format`: + case `font-face-name`: + case `missing-glyph`: + return !1; + default: + return !0; + } + } + var Ve = null; + function He(e) { + return ( + (e = e.target || e.srcElement || window), + e.correspondingUseElement && (e = e.correspondingUseElement), + e.nodeType === 3 ? e.parentNode : e + ); + } + var Ue = null, + We = null, + Ge = null; + function Ke(e) { + if ((e = Fi(e))) { + if (typeof Ue != `function`) throw Error(r(280)); + var t = e.stateNode; + t && ((t = Li(t)), Ue(e.stateNode, e.type, t)); + } + } + function qe(e) { + We ? (Ge ? Ge.push(e) : (Ge = [e])) : (We = e); + } + function Je() { + if (We) { + var e = We, + t = Ge; + if (((Ge = We = null), Ke(e), t)) for (e = 0; e < t.length; e++) Ke(t[e]); + } + } + function Ye(e, t) { + return e(t); + } + function Xe() {} + var Ze = !1; + function Qe(e, t, n) { + if (Ze) return e(t, n); + Ze = !0; + try { + return Ye(e, t, n); + } finally { + ((Ze = !1), (We !== null || Ge !== null) && (Xe(), Je())); + } + } + function $e(e, t) { + var n = e.stateNode; + if (n === null) return null; + var i = Li(n); + if (i === null) return null; + n = i[t]; + a: switch (t) { + case `onClick`: + case `onClickCapture`: + case `onDoubleClick`: + case `onDoubleClickCapture`: + case `onMouseDown`: + case `onMouseDownCapture`: + case `onMouseMove`: + case `onMouseMoveCapture`: + case `onMouseUp`: + case `onMouseUpCapture`: + case `onMouseEnter`: + ((i = !i.disabled) || + ((e = e.type), (i = !(e === `button` || e === `input` || e === `select` || e === `textarea`))), + (e = !i)); + break a; + default: + e = !1; + } + if (e) return null; + if (n && typeof n != `function`) throw Error(r(231, t, typeof n)); + return n; + } + var et = !1; + if (c) + try { + var tt = {}; + (Object.defineProperty(tt, `passive`, { + get: function () { + et = !0; + }, + }), + window.addEventListener(`test`, tt, tt), + window.removeEventListener(`test`, tt, tt)); + } catch { + et = !1; + } + function I(e, t, n, r, i, a, o, s, c) { + var l = Array.prototype.slice.call(arguments, 3); + try { + t.apply(n, l); + } catch (e) { + this.onError(e); + } + } + var nt = !1, + rt = null, + it = !1, + at = null, + ot = { + onError: function (e) { + ((nt = !0), (rt = e)); + }, + }; + function st(e, t, n, r, i, a, o, s, c) { + ((nt = !1), (rt = null), I.apply(ot, arguments)); + } + function ct(e, t, n, i, a, o, s, c, l) { + if ((st.apply(this, arguments), nt)) { + if (nt) { + var u = rt; + ((nt = !1), (rt = null)); + } else throw Error(r(198)); + it || ((it = !0), (at = u)); + } + } + function lt(e) { + var t = e, + n = e; + if (e.alternate) for (; t.return; ) t = t.return; + else { + e = t; + do ((t = e), t.flags & 4098 && (n = t.return), (e = t.return)); + while (e); + } + return t.tag === 3 ? n : null; + } + function ut(e) { + if (e.tag === 13) { + var t = e.memoizedState; + if ((t === null && ((e = e.alternate), e !== null && (t = e.memoizedState)), t !== null)) return t.dehydrated; + } + return null; + } + function dt(e) { + if (lt(e) !== e) throw Error(r(188)); + } + function ft(e) { + var t = e.alternate; + if (!t) { + if (((t = lt(e)), t === null)) throw Error(r(188)); + return t === e ? e : null; + } + for (var n = e, i = t; ; ) { + var a = n.return; + if (a === null) break; + var o = a.alternate; + if (o === null) { + if (((i = a.return), i !== null)) { + n = i; + continue; + } + break; + } + if (a.child === o.child) { + for (o = a.child; o; ) { + if (o === n) return (dt(a), e); + if (o === i) return (dt(a), t); + o = o.sibling; + } + throw Error(r(188)); + } + if (n.return !== i.return) ((n = a), (i = o)); + else { + for (var s = !1, c = a.child; c; ) { + if (c === n) { + ((s = !0), (n = a), (i = o)); + break; + } + if (c === i) { + ((s = !0), (i = a), (n = o)); + break; + } + c = c.sibling; + } + if (!s) { + for (c = o.child; c; ) { + if (c === n) { + ((s = !0), (n = o), (i = a)); + break; + } + if (c === i) { + ((s = !0), (i = o), (n = a)); + break; + } + c = c.sibling; + } + if (!s) throw Error(r(189)); + } + } + if (n.alternate !== i) throw Error(r(190)); + } + if (n.tag !== 3) throw Error(r(188)); + return n.stateNode.current === n ? e : t; + } + function pt(e) { + return ((e = ft(e)), e === null ? null : mt(e)); + } + function mt(e) { + if (e.tag === 5 || e.tag === 6) return e; + for (e = e.child; e !== null; ) { + var t = mt(e); + if (t !== null) return t; + e = e.sibling; + } + return null; + } + var ht = n.unstable_scheduleCallback, + gt = n.unstable_cancelCallback, + _t = n.unstable_shouldYield, + vt = n.unstable_requestPaint, + yt = n.unstable_now, + bt = n.unstable_getCurrentPriorityLevel, + xt = n.unstable_ImmediatePriority, + St = n.unstable_UserBlockingPriority, + Ct = n.unstable_NormalPriority, + wt = n.unstable_LowPriority, + Tt = n.unstable_IdlePriority, + Et = null, + Dt = null; + function Ot(e) { + if (Dt && typeof Dt.onCommitFiberRoot == `function`) + try { + Dt.onCommitFiberRoot(Et, e, void 0, (e.current.flags & 128) == 128); + } catch {} + } + var kt = Math.clz32 ? Math.clz32 : Mt, + At = Math.log, + jt = Math.LN2; + function Mt(e) { + return ((e >>>= 0), e === 0 ? 32 : (31 - ((At(e) / jt) | 0)) | 0); + } + var Nt = 64, + Pt = 4194304; + function Ft(e) { + switch (e & -e) { + case 1: + return 1; + case 2: + return 2; + case 4: + return 4; + case 8: + return 8; + case 16: + return 16; + case 32: + return 32; + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + case 262144: + case 524288: + case 1048576: + case 2097152: + return e & 4194240; + case 4194304: + case 8388608: + case 16777216: + case 33554432: + case 67108864: + return e & 130023424; + case 134217728: + return 134217728; + case 268435456: + return 268435456; + case 536870912: + return 536870912; + case 1073741824: + return 1073741824; + default: + return e; + } + } + function It(e, t) { + var n = e.pendingLanes; + if (n === 0) return 0; + var r = 0, + i = e.suspendedLanes, + a = e.pingedLanes, + o = n & 268435455; + if (o !== 0) { + var s = o & ~i; + s === 0 ? ((a &= o), a !== 0 && (r = Ft(a))) : (r = Ft(s)); + } else ((o = n & ~i), o === 0 ? a !== 0 && (r = Ft(a)) : (r = Ft(o))); + if (r === 0) return 0; + if (t !== 0 && t !== r && (t & i) === 0 && ((i = r & -r), (a = t & -t), i >= a || (i === 16 && a & 4194240))) + return t; + if ((r & 4 && (r |= n & 16), (t = e.entangledLanes), t !== 0)) + for (e = e.entanglements, t &= r; 0 < t; ) ((n = 31 - kt(t)), (i = 1 << n), (r |= e[n]), (t &= ~i)); + return r; + } + function Lt(e, t) { + switch (e) { + case 1: + case 2: + case 4: + return t + 250; + case 8: + case 16: + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + case 262144: + case 524288: + case 1048576: + case 2097152: + return t + 5e3; + case 4194304: + case 8388608: + case 16777216: + case 33554432: + case 67108864: + return -1; + case 134217728: + case 268435456: + case 536870912: + case 1073741824: + return -1; + default: + return -1; + } + } + function Rt(e, t) { + for (var n = e.suspendedLanes, r = e.pingedLanes, i = e.expirationTimes, a = e.pendingLanes; 0 < a; ) { + var o = 31 - kt(a), + s = 1 << o, + c = i[o]; + (c === -1 ? ((s & n) === 0 || (s & r) !== 0) && (i[o] = Lt(s, t)) : c <= t && (e.expiredLanes |= s), (a &= ~s)); + } + } + function zt(e) { + return ((e = e.pendingLanes & -1073741825), e === 0 ? (e & 1073741824 ? 1073741824 : 0) : e); + } + function Bt() { + var e = Nt; + return ((Nt <<= 1), !(Nt & 4194240) && (Nt = 64), e); + } + function Vt(e) { + for (var t = [], n = 0; 31 > n; n++) t.push(e); + return t; + } + function L(e, t, n) { + ((e.pendingLanes |= t), + t !== 536870912 && ((e.suspendedLanes = 0), (e.pingedLanes = 0)), + (e = e.eventTimes), + (t = 31 - kt(t)), + (e[t] = n)); + } + function Ht(e, t) { + var n = e.pendingLanes & ~t; + ((e.pendingLanes = t), + (e.suspendedLanes = 0), + (e.pingedLanes = 0), + (e.expiredLanes &= t), + (e.mutableReadLanes &= t), + (e.entangledLanes &= t), + (t = e.entanglements)); + var r = e.eventTimes; + for (e = e.expirationTimes; 0 < n; ) { + var i = 31 - kt(n), + a = 1 << i; + ((t[i] = 0), (r[i] = -1), (e[i] = -1), (n &= ~a)); + } + } + function Ut(e, t) { + var n = (e.entangledLanes |= t); + for (e = e.entanglements; n; ) { + var r = 31 - kt(n), + i = 1 << r; + ((i & t) | (e[r] & t) && (e[r] |= t), (n &= ~i)); + } + } + var R = 0; + function Wt(e) { + return ((e &= -e), 1 < e ? (4 < e ? (e & 268435455 ? 16 : 536870912) : 4) : 1); + } + var Gt, + Kt, + qt, + Jt, + Yt, + Xt = !1, + Zt = [], + Qt = null, + $t = null, + en = null, + tn = new Map(), + nn = new Map(), + rn = [], + an = + `mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset submit`.split( + ` `, + ); + function on(e, t) { + switch (e) { + case `focusin`: + case `focusout`: + Qt = null; + break; + case `dragenter`: + case `dragleave`: + $t = null; + break; + case `mouseover`: + case `mouseout`: + en = null; + break; + case `pointerover`: + case `pointerout`: + tn.delete(t.pointerId); + break; + case `gotpointercapture`: + case `lostpointercapture`: + nn.delete(t.pointerId); + } + } + function sn(e, t, n, r, i, a) { + return e === null || e.nativeEvent !== a + ? ((e = { blockedOn: t, domEventName: n, eventSystemFlags: r, nativeEvent: a, targetContainers: [i] }), + t !== null && ((t = Fi(t)), t !== null && Kt(t)), + e) + : ((e.eventSystemFlags |= r), (t = e.targetContainers), i !== null && t.indexOf(i) === -1 && t.push(i), e); + } + function cn(e, t, n, r, i) { + switch (t) { + case `focusin`: + return ((Qt = sn(Qt, e, t, n, r, i)), !0); + case `dragenter`: + return (($t = sn($t, e, t, n, r, i)), !0); + case `mouseover`: + return ((en = sn(en, e, t, n, r, i)), !0); + case `pointerover`: + var a = i.pointerId; + return (tn.set(a, sn(tn.get(a) || null, e, t, n, r, i)), !0); + case `gotpointercapture`: + return ((a = i.pointerId), nn.set(a, sn(nn.get(a) || null, e, t, n, r, i)), !0); + } + return !1; + } + function ln(e) { + var t = Pi(e.target); + if (t !== null) { + var n = lt(t); + if (n !== null) { + if (((t = n.tag), t === 13)) { + if (((t = ut(n)), t !== null)) { + ((e.blockedOn = t), + Yt(e.priority, function () { + qt(n); + })); + return; + } + } else if (t === 3 && n.stateNode.current.memoizedState.isDehydrated) { + e.blockedOn = n.tag === 3 ? n.stateNode.containerInfo : null; + return; + } + } + } + e.blockedOn = null; + } + function un(e) { + if (e.blockedOn !== null) return !1; + for (var t = e.targetContainers; 0 < t.length; ) { + var n = xn(e.domEventName, e.eventSystemFlags, t[0], e.nativeEvent); + if (n === null) { + n = e.nativeEvent; + var r = new n.constructor(n.type, n); + ((Ve = r), n.target.dispatchEvent(r), (Ve = null)); + } else return ((t = Fi(n)), t !== null && Kt(t), (e.blockedOn = n), !1); + t.shift(); + } + return !0; + } + function dn(e, t, n) { + un(e) && n.delete(t); + } + function fn() { + ((Xt = !1), + Qt !== null && un(Qt) && (Qt = null), + $t !== null && un($t) && ($t = null), + en !== null && un(en) && (en = null), + tn.forEach(dn), + nn.forEach(dn)); + } + function pn(e, t) { + e.blockedOn === t && + ((e.blockedOn = null), Xt || ((Xt = !0), n.unstable_scheduleCallback(n.unstable_NormalPriority, fn))); + } + function mn(e) { + function t(t) { + return pn(t, e); + } + if (0 < Zt.length) { + pn(Zt[0], e); + for (var n = 1; n < Zt.length; n++) { + var r = Zt[n]; + r.blockedOn === e && (r.blockedOn = null); + } + } + for ( + Qt !== null && pn(Qt, e), + $t !== null && pn($t, e), + en !== null && pn(en, e), + tn.forEach(t), + nn.forEach(t), + n = 0; + n < rn.length; + n++ + ) + ((r = rn[n]), r.blockedOn === e && (r.blockedOn = null)); + for (; 0 < rn.length && ((n = rn[0]), n.blockedOn === null); ) (ln(n), n.blockedOn === null && rn.shift()); + } + var hn = C.ReactCurrentBatchConfig, + gn = !0; + function _n(e, t, n, r) { + var i = R, + a = hn.transition; + hn.transition = null; + try { + ((R = 1), yn(e, t, n, r)); + } finally { + ((R = i), (hn.transition = a)); + } + } + function vn(e, t, n, r) { + var i = R, + a = hn.transition; + hn.transition = null; + try { + ((R = 4), yn(e, t, n, r)); + } finally { + ((R = i), (hn.transition = a)); + } + } + function yn(e, t, n, r) { + if (gn) { + var i = xn(e, t, n, r); + if (i === null) (ci(e, t, r, bn, n), on(e, r)); + else if (cn(i, e, t, n, r)) r.stopPropagation(); + else if ((on(e, r), t & 4 && -1 < an.indexOf(e))) { + for (; i !== null; ) { + var a = Fi(i); + if ((a !== null && Gt(a), (a = xn(e, t, n, r)), a === null && ci(e, t, r, bn, n), a === i)) break; + i = a; + } + i !== null && r.stopPropagation(); + } else ci(e, t, r, null, n); + } + } + var bn = null; + function xn(e, t, n, r) { + if (((bn = null), (e = He(r)), (e = Pi(e)), e !== null)) + if (((t = lt(e)), t === null)) e = null; + else if (((n = t.tag), n === 13)) { + if (((e = ut(t)), e !== null)) return e; + e = null; + } else if (n === 3) { + if (t.stateNode.current.memoizedState.isDehydrated) return t.tag === 3 ? t.stateNode.containerInfo : null; + e = null; + } else t !== e && (e = null); + return ((bn = e), null); + } + function Sn(e) { + switch (e) { + case `cancel`: + case `click`: + case `close`: + case `contextmenu`: + case `copy`: + case `cut`: + case `auxclick`: + case `dblclick`: + case `dragend`: + case `dragstart`: + case `drop`: + case `focusin`: + case `focusout`: + case `input`: + case `invalid`: + case `keydown`: + case `keypress`: + case `keyup`: + case `mousedown`: + case `mouseup`: + case `paste`: + case `pause`: + case `play`: + case `pointercancel`: + case `pointerdown`: + case `pointerup`: + case `ratechange`: + case `reset`: + case `resize`: + case `seeked`: + case `submit`: + case `touchcancel`: + case `touchend`: + case `touchstart`: + case `volumechange`: + case `change`: + case `selectionchange`: + case `textInput`: + case `compositionstart`: + case `compositionend`: + case `compositionupdate`: + case `beforeblur`: + case `afterblur`: + case `beforeinput`: + case `blur`: + case `fullscreenchange`: + case `focus`: + case `hashchange`: + case `popstate`: + case `select`: + case `selectstart`: + return 1; + case `drag`: + case `dragenter`: + case `dragexit`: + case `dragleave`: + case `dragover`: + case `mousemove`: + case `mouseout`: + case `mouseover`: + case `pointermove`: + case `pointerout`: + case `pointerover`: + case `scroll`: + case `toggle`: + case `touchmove`: + case `wheel`: + case `mouseenter`: + case `mouseleave`: + case `pointerenter`: + case `pointerleave`: + return 4; + case `message`: + switch (bt()) { + case xt: + return 1; + case St: + return 4; + case Ct: + case wt: + return 16; + case Tt: + return 536870912; + default: + return 16; + } + default: + return 16; + } + } + var Cn = null, + wn = null, + Tn = null; + function En() { + if (Tn) return Tn; + var e, + t = wn, + n = t.length, + r, + i = `value` in Cn ? Cn.value : Cn.textContent, + a = i.length; + for (e = 0; e < n && t[e] === i[e]; e++); + var o = n - e; + for (r = 1; r <= o && t[n - r] === i[a - r]; r++); + return (Tn = i.slice(e, 1 < r ? 1 - r : void 0)); + } + function Dn(e) { + var t = e.keyCode; + return ( + `charCode` in e ? ((e = e.charCode), e === 0 && t === 13 && (e = 13)) : (e = t), + e === 10 && (e = 13), + 32 <= e || e === 13 ? e : 0 + ); + } + function On() { + return !0; + } + function kn() { + return !1; + } + function An(e) { + function t(t, n, r, i, a) { + for (var o in ((this._reactName = t), + (this._targetInst = r), + (this.type = n), + (this.nativeEvent = i), + (this.target = a), + (this.currentTarget = null), + e)) + e.hasOwnProperty(o) && ((t = e[o]), (this[o] = t ? t(i) : i[o])); + return ( + (this.isDefaultPrevented = (i.defaultPrevented == null ? !1 === i.returnValue : i.defaultPrevented) + ? On + : kn), + (this.isPropagationStopped = kn), + this + ); + } + return ( + M(t.prototype, { + preventDefault: function () { + this.defaultPrevented = !0; + var e = this.nativeEvent; + e && + (e.preventDefault ? e.preventDefault() : typeof e.returnValue != `unknown` && (e.returnValue = !1), + (this.isDefaultPrevented = On)); + }, + stopPropagation: function () { + var e = this.nativeEvent; + e && + (e.stopPropagation ? e.stopPropagation() : typeof e.cancelBubble != `unknown` && (e.cancelBubble = !0), + (this.isPropagationStopped = On)); + }, + persist: function () {}, + isPersistent: On, + }), + t + ); + } + var jn = { + eventPhase: 0, + bubbles: 0, + cancelable: 0, + timeStamp: function (e) { + return e.timeStamp || Date.now(); + }, + defaultPrevented: 0, + isTrusted: 0, + }, + Mn = An(jn), + Nn = M({}, jn, { view: 0, detail: 0 }), + Pn = An(Nn), + Fn, + In, + Ln, + Rn = M({}, Nn, { + screenX: 0, + screenY: 0, + clientX: 0, + clientY: 0, + pageX: 0, + pageY: 0, + ctrlKey: 0, + shiftKey: 0, + altKey: 0, + metaKey: 0, + getModifierState: Jn, + button: 0, + buttons: 0, + relatedTarget: function (e) { + return e.relatedTarget === void 0 + ? e.fromElement === e.srcElement + ? e.toElement + : e.fromElement + : e.relatedTarget; + }, + movementX: function (e) { + return `movementX` in e + ? e.movementX + : (e !== Ln && + (Ln && e.type === `mousemove` + ? ((Fn = e.screenX - Ln.screenX), (In = e.screenY - Ln.screenY)) + : (In = Fn = 0), + (Ln = e)), + Fn); + }, + movementY: function (e) { + return `movementY` in e ? e.movementY : In; + }, + }), + zn = An(Rn), + Bn = An(M({}, Rn, { dataTransfer: 0 })), + Vn = An(M({}, Nn, { relatedTarget: 0 })), + z = An(M({}, jn, { animationName: 0, elapsedTime: 0, pseudoElement: 0 })), + Hn = An( + M({}, jn, { + clipboardData: function (e) { + return `clipboardData` in e ? e.clipboardData : window.clipboardData; + }, + }), + ), + Un = An(M({}, jn, { data: 0 })), + Wn = { + Esc: `Escape`, + Spacebar: ` `, + Left: `ArrowLeft`, + Up: `ArrowUp`, + Right: `ArrowRight`, + Down: `ArrowDown`, + Del: `Delete`, + Win: `OS`, + Menu: `ContextMenu`, + Apps: `ContextMenu`, + Scroll: `ScrollLock`, + MozPrintableKey: `Unidentified`, + }, + Gn = { + 8: `Backspace`, + 9: `Tab`, + 12: `Clear`, + 13: `Enter`, + 16: `Shift`, + 17: `Control`, + 18: `Alt`, + 19: `Pause`, + 20: `CapsLock`, + 27: `Escape`, + 32: ` `, + 33: `PageUp`, + 34: `PageDown`, + 35: `End`, + 36: `Home`, + 37: `ArrowLeft`, + 38: `ArrowUp`, + 39: `ArrowRight`, + 40: `ArrowDown`, + 45: `Insert`, + 46: `Delete`, + 112: `F1`, + 113: `F2`, + 114: `F3`, + 115: `F4`, + 116: `F5`, + 117: `F6`, + 118: `F7`, + 119: `F8`, + 120: `F9`, + 121: `F10`, + 122: `F11`, + 123: `F12`, + 144: `NumLock`, + 145: `ScrollLock`, + 224: `Meta`, + }, + Kn = { Alt: `altKey`, Control: `ctrlKey`, Meta: `metaKey`, Shift: `shiftKey` }; + function qn(e) { + var t = this.nativeEvent; + return t.getModifierState ? t.getModifierState(e) : (e = Kn[e]) ? !!t[e] : !1; + } + function Jn() { + return qn; + } + var Yn = An( + M({}, Nn, { + key: function (e) { + if (e.key) { + var t = Wn[e.key] || e.key; + if (t !== `Unidentified`) return t; + } + return e.type === `keypress` + ? ((e = Dn(e)), e === 13 ? `Enter` : String.fromCharCode(e)) + : e.type === `keydown` || e.type === `keyup` + ? Gn[e.keyCode] || `Unidentified` + : ``; + }, + code: 0, + location: 0, + ctrlKey: 0, + shiftKey: 0, + altKey: 0, + metaKey: 0, + repeat: 0, + locale: 0, + getModifierState: Jn, + charCode: function (e) { + return e.type === `keypress` ? Dn(e) : 0; + }, + keyCode: function (e) { + return e.type === `keydown` || e.type === `keyup` ? e.keyCode : 0; + }, + which: function (e) { + return e.type === `keypress` ? Dn(e) : e.type === `keydown` || e.type === `keyup` ? e.keyCode : 0; + }, + }), + ), + Xn = An( + M({}, Rn, { + pointerId: 0, + width: 0, + height: 0, + pressure: 0, + tangentialPressure: 0, + tiltX: 0, + tiltY: 0, + twist: 0, + pointerType: 0, + isPrimary: 0, + }), + ), + Zn = An( + M({}, Nn, { + touches: 0, + targetTouches: 0, + changedTouches: 0, + altKey: 0, + metaKey: 0, + ctrlKey: 0, + shiftKey: 0, + getModifierState: Jn, + }), + ), + Qn = An(M({}, jn, { propertyName: 0, elapsedTime: 0, pseudoElement: 0 })), + $n = An( + M({}, Rn, { + deltaX: function (e) { + return `deltaX` in e ? e.deltaX : `wheelDeltaX` in e ? -e.wheelDeltaX : 0; + }, + deltaY: function (e) { + return `deltaY` in e + ? e.deltaY + : `wheelDeltaY` in e + ? -e.wheelDeltaY + : `wheelDelta` in e + ? -e.wheelDelta + : 0; + }, + deltaZ: 0, + deltaMode: 0, + }), + ), + er = [9, 13, 27, 32], + tr = c && `CompositionEvent` in window, + B = null; + c && `documentMode` in document && (B = document.documentMode); + var V = c && `TextEvent` in window && !B, + nr = c && (!tr || (B && 8 < B && 11 >= B)), + H = ` `, + rr = !1; + function ir(e, t) { + switch (e) { + case `keyup`: + return er.indexOf(t.keyCode) !== -1; + case `keydown`: + return t.keyCode !== 229; + case `keypress`: + case `mousedown`: + case `focusout`: + return !0; + default: + return !1; + } + } + function ar(e) { + return ((e = e.detail), typeof e == `object` && `data` in e ? e.data : null); + } + var or = !1; + function sr(e, t) { + switch (e) { + case `compositionend`: + return ar(t); + case `keypress`: + return t.which === 32 ? ((rr = !0), H) : null; + case `textInput`: + return ((e = t.data), e === H && rr ? null : e); + default: + return null; + } + } + function cr(e, t) { + if (or) + return e === `compositionend` || (!tr && ir(e, t)) ? ((e = En()), (Tn = wn = Cn = null), (or = !1), e) : null; + switch (e) { + case `paste`: + return null; + case `keypress`: + if (!(t.ctrlKey || t.altKey || t.metaKey) || (t.ctrlKey && t.altKey)) { + if (t.char && 1 < t.char.length) return t.char; + if (t.which) return String.fromCharCode(t.which); + } + return null; + case `compositionend`: + return nr && t.locale !== `ko` ? null : t.data; + default: + return null; + } + } + var lr = { + color: !0, + date: !0, + datetime: !0, + 'datetime-local': !0, + email: !0, + month: !0, + number: !0, + password: !0, + range: !0, + search: !0, + tel: !0, + text: !0, + time: !0, + url: !0, + week: !0, + }; + function ur(e) { + var t = e && e.nodeName && e.nodeName.toLowerCase(); + return t === `input` ? !!lr[e.type] : t === `textarea`; + } + function dr(e, t, n, r) { + (qe(r), + (t = li(t, `onChange`)), + 0 < t.length && ((n = new Mn(`onChange`, `change`, null, n, r)), e.push({ event: n, listeners: t }))); + } + var fr = null, + pr = null; + function mr(e) { + ri(e, 0); + } + function hr(e) { + if (_e(Ii(e))) return e; + } + function gr(e, t) { + if (e === `change`) return t; + } + var _r = !1; + if (c) { + var vr; + if (c) { + var yr = `oninput` in document; + if (!yr) { + var br = document.createElement(`div`); + (br.setAttribute(`oninput`, `return;`), (yr = typeof br.oninput == `function`)); + } + vr = yr; + } else vr = !1; + _r = vr && (!document.documentMode || 9 < document.documentMode); + } + function xr() { + fr && (fr.detachEvent(`onpropertychange`, Sr), (pr = fr = null)); + } + function Sr(e) { + if (e.propertyName === `value` && hr(pr)) { + var t = []; + (dr(t, pr, e, He(e)), Qe(mr, t)); + } + } + function Cr(e, t, n) { + e === `focusin` ? (xr(), (fr = t), (pr = n), fr.attachEvent(`onpropertychange`, Sr)) : e === `focusout` && xr(); + } + function wr(e) { + if (e === `selectionchange` || e === `keyup` || e === `keydown`) return hr(pr); + } + function Tr(e, t) { + if (e === `click`) return hr(t); + } + function Er(e, t) { + if (e === `input` || e === `change`) return hr(t); + } + function Dr(e, t) { + return (e === t && (e !== 0 || 1 / e == 1 / t)) || (e !== e && t !== t); + } + var Or = typeof Object.is == `function` ? Object.is : Dr; + function kr(e, t) { + if (Or(e, t)) return !0; + if (typeof e != `object` || !e || typeof t != `object` || !t) return !1; + var n = Object.keys(e), + r = Object.keys(t); + if (n.length !== r.length) return !1; + for (r = 0; r < n.length; r++) { + var i = n[r]; + if (!l.call(t, i) || !Or(e[i], t[i])) return !1; + } + return !0; + } + function Ar(e) { + for (; e && e.firstChild; ) e = e.firstChild; + return e; + } + function jr(e, t) { + var n = Ar(e); + e = 0; + for (var r; n; ) { + if (n.nodeType === 3) { + if (((r = e + n.textContent.length), e <= t && r >= t)) return { node: n, offset: t - e }; + e = r; + } + a: { + for (; n; ) { + if (n.nextSibling) { + n = n.nextSibling; + break a; + } + n = n.parentNode; + } + n = void 0; + } + n = Ar(n); + } + } + function Mr(e, t) { + return e && t + ? e === t + ? !0 + : e && e.nodeType === 3 + ? !1 + : t && t.nodeType === 3 + ? Mr(e, t.parentNode) + : `contains` in e + ? e.contains(t) + : e.compareDocumentPosition + ? !!(e.compareDocumentPosition(t) & 16) + : !1 + : !1; + } + function Nr() { + for (var e = window, t = ve(); t instanceof e.HTMLIFrameElement; ) { + try { + var n = typeof t.contentWindow.location.href == `string`; + } catch { + n = !1; + } + if (n) e = t.contentWindow; + else break; + t = ve(e.document); + } + return t; + } + function Pr(e) { + var t = e && e.nodeName && e.nodeName.toLowerCase(); + return ( + t && + ((t === `input` && + (e.type === `text` || + e.type === `search` || + e.type === `tel` || + e.type === `url` || + e.type === `password`)) || + t === `textarea` || + e.contentEditable === `true`) + ); + } + function U(e) { + var t = Nr(), + n = e.focusedElem, + r = e.selectionRange; + if (t !== n && n && n.ownerDocument && Mr(n.ownerDocument.documentElement, n)) { + if (r !== null && Pr(n)) { + if (((t = r.start), (e = r.end), e === void 0 && (e = t), `selectionStart` in n)) + ((n.selectionStart = t), (n.selectionEnd = Math.min(e, n.value.length))); + else if (((e = ((t = n.ownerDocument || document) && t.defaultView) || window), e.getSelection)) { + e = e.getSelection(); + var i = n.textContent.length, + a = Math.min(r.start, i); + ((r = r.end === void 0 ? a : Math.min(r.end, i)), + !e.extend && a > r && ((i = r), (r = a), (a = i)), + (i = jr(n, a))); + var o = jr(n, r); + i && + o && + (e.rangeCount !== 1 || + e.anchorNode !== i.node || + e.anchorOffset !== i.offset || + e.focusNode !== o.node || + e.focusOffset !== o.offset) && + ((t = t.createRange()), + t.setStart(i.node, i.offset), + e.removeAllRanges(), + a > r ? (e.addRange(t), e.extend(o.node, o.offset)) : (t.setEnd(o.node, o.offset), e.addRange(t))); + } + } + for (t = [], e = n; (e = e.parentNode); ) + e.nodeType === 1 && t.push({ element: e, left: e.scrollLeft, top: e.scrollTop }); + for (typeof n.focus == `function` && n.focus(), n = 0; n < t.length; n++) + ((e = t[n]), (e.element.scrollLeft = e.left), (e.element.scrollTop = e.top)); + } + } + var Fr = c && `documentMode` in document && 11 >= document.documentMode, + Ir = null, + Lr = null, + Rr = null, + zr = !1; + function Br(e, t, n) { + var r = n.window === n ? n.document : n.nodeType === 9 ? n : n.ownerDocument; + zr || + Ir == null || + Ir !== ve(r) || + ((r = Ir), + `selectionStart` in r && Pr(r) + ? (r = { start: r.selectionStart, end: r.selectionEnd }) + : ((r = ((r.ownerDocument && r.ownerDocument.defaultView) || window).getSelection()), + (r = { + anchorNode: r.anchorNode, + anchorOffset: r.anchorOffset, + focusNode: r.focusNode, + focusOffset: r.focusOffset, + })), + (Rr && kr(Rr, r)) || + ((Rr = r), + (r = li(Lr, `onSelect`)), + 0 < r.length && + ((t = new Mn(`onSelect`, `select`, null, t, n)), e.push({ event: t, listeners: r }), (t.target = Ir)))); + } + function Vr(e, t) { + var n = {}; + return ((n[e.toLowerCase()] = t.toLowerCase()), (n[`Webkit` + e] = `webkit` + t), (n[`Moz` + e] = `moz` + t), n); + } + var Hr = { + animationend: Vr(`Animation`, `AnimationEnd`), + animationiteration: Vr(`Animation`, `AnimationIteration`), + animationstart: Vr(`Animation`, `AnimationStart`), + transitionend: Vr(`Transition`, `TransitionEnd`), + }, + Ur = {}, + Wr = {}; + c && + ((Wr = document.createElement(`div`).style), + `AnimationEvent` in window || + (delete Hr.animationend.animation, delete Hr.animationiteration.animation, delete Hr.animationstart.animation), + `TransitionEvent` in window || delete Hr.transitionend.transition); + function W(e) { + if (Ur[e]) return Ur[e]; + if (!Hr[e]) return e; + var t = Hr[e], + n; + for (n in t) if (t.hasOwnProperty(n) && n in Wr) return (Ur[e] = t[n]); + return e; + } + var Gr = W(`animationend`), + Kr = W(`animationiteration`), + qr = W(`animationstart`), + Jr = W(`transitionend`), + Yr = new Map(), + Xr = + `abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel`.split( + ` `, + ); + function Zr(e, t) { + (Yr.set(e, t), o(t, [e])); + } + for (var Qr = 0; Qr < Xr.length; Qr++) { + var $r = Xr[Qr]; + Zr($r.toLowerCase(), `on` + ($r[0].toUpperCase() + $r.slice(1))); + } + (Zr(Gr, `onAnimationEnd`), + Zr(Kr, `onAnimationIteration`), + Zr(qr, `onAnimationStart`), + Zr(`dblclick`, `onDoubleClick`), + Zr(`focusin`, `onFocus`), + Zr(`focusout`, `onBlur`), + Zr(Jr, `onTransitionEnd`), + s(`onMouseEnter`, [`mouseout`, `mouseover`]), + s(`onMouseLeave`, [`mouseout`, `mouseover`]), + s(`onPointerEnter`, [`pointerout`, `pointerover`]), + s(`onPointerLeave`, [`pointerout`, `pointerover`]), + o(`onChange`, `change click focusin focusout input keydown keyup selectionchange`.split(` `)), + o(`onSelect`, `focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange`.split(` `)), + o(`onBeforeInput`, [`compositionend`, `keypress`, `textInput`, `paste`]), + o(`onCompositionEnd`, `compositionend focusout keydown keypress keyup mousedown`.split(` `)), + o(`onCompositionStart`, `compositionstart focusout keydown keypress keyup mousedown`.split(` `)), + o(`onCompositionUpdate`, `compositionupdate focusout keydown keypress keyup mousedown`.split(` `))); + var ei = + `abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting`.split( + ` `, + ), + ti = new Set(`cancel close invalid load scroll toggle`.split(` `).concat(ei)); + function ni(e, t, n) { + var r = e.type || `unknown-event`; + ((e.currentTarget = n), ct(r, t, void 0, e), (e.currentTarget = null)); + } + function ri(e, t) { + t = (t & 4) != 0; + for (var n = 0; n < e.length; n++) { + var r = e[n], + i = r.event; + r = r.listeners; + a: { + var a = void 0; + if (t) + for (var o = r.length - 1; 0 <= o; o--) { + var s = r[o], + c = s.instance, + l = s.currentTarget; + if (((s = s.listener), c !== a && i.isPropagationStopped())) break a; + (ni(i, s, l), (a = c)); + } + else + for (o = 0; o < r.length; o++) { + if ( + ((s = r[o]), + (c = s.instance), + (l = s.currentTarget), + (s = s.listener), + c !== a && i.isPropagationStopped()) + ) + break a; + (ni(i, s, l), (a = c)); + } + } + } + if (it) throw ((e = at), (it = !1), (at = null), e); + } + function G(e, t) { + var n = t[ji]; + n === void 0 && (n = t[ji] = new Set()); + var r = e + `__bubble`; + n.has(r) || (si(t, e, 2, !1), n.add(r)); + } + function ii(e, t, n) { + var r = 0; + (t && (r |= 4), si(n, e, r, t)); + } + var ai = `_reactListening` + Math.random().toString(36).slice(2); + function oi(e) { + if (!e[ai]) { + ((e[ai] = !0), + i.forEach(function (t) { + t !== `selectionchange` && (ti.has(t) || ii(t, !1, e), ii(t, !0, e)); + })); + var t = e.nodeType === 9 ? e : e.ownerDocument; + t === null || t[ai] || ((t[ai] = !0), ii(`selectionchange`, !1, t)); + } + } + function si(e, t, n, r) { + switch (Sn(t)) { + case 1: + var i = _n; + break; + case 4: + i = vn; + break; + default: + i = yn; + } + ((n = i.bind(null, t, n, e)), + (i = void 0), + !et || (t !== `touchstart` && t !== `touchmove` && t !== `wheel`) || (i = !0), + r + ? i === void 0 + ? e.addEventListener(t, n, !0) + : e.addEventListener(t, n, { capture: !0, passive: i }) + : i === void 0 + ? e.addEventListener(t, n, !1) + : e.addEventListener(t, n, { passive: i })); + } + function ci(e, t, n, r, i) { + var a = r; + if (!(t & 1) && !(t & 2) && r !== null) + a: for (;;) { + if (r === null) return; + var o = r.tag; + if (o === 3 || o === 4) { + var s = r.stateNode.containerInfo; + if (s === i || (s.nodeType === 8 && s.parentNode === i)) break; + if (o === 4) + for (o = r.return; o !== null; ) { + var c = o.tag; + if ( + (c === 3 || c === 4) && + ((c = o.stateNode.containerInfo), c === i || (c.nodeType === 8 && c.parentNode === i)) + ) + return; + o = o.return; + } + for (; s !== null; ) { + if (((o = Pi(s)), o === null)) return; + if (((c = o.tag), c === 5 || c === 6)) { + r = a = o; + continue a; + } + s = s.parentNode; + } + } + r = r.return; + } + Qe(function () { + var r = a, + i = He(n), + o = []; + a: { + var s = Yr.get(e); + if (s !== void 0) { + var c = Mn, + l = e; + switch (e) { + case `keypress`: + if (Dn(n) === 0) break a; + case `keydown`: + case `keyup`: + c = Yn; + break; + case `focusin`: + ((l = `focus`), (c = Vn)); + break; + case `focusout`: + ((l = `blur`), (c = Vn)); + break; + case `beforeblur`: + case `afterblur`: + c = Vn; + break; + case `click`: + if (n.button === 2) break a; + case `auxclick`: + case `dblclick`: + case `mousedown`: + case `mousemove`: + case `mouseup`: + case `mouseout`: + case `mouseover`: + case `contextmenu`: + c = zn; + break; + case `drag`: + case `dragend`: + case `dragenter`: + case `dragexit`: + case `dragleave`: + case `dragover`: + case `dragstart`: + case `drop`: + c = Bn; + break; + case `touchcancel`: + case `touchend`: + case `touchmove`: + case `touchstart`: + c = Zn; + break; + case Gr: + case Kr: + case qr: + c = z; + break; + case Jr: + c = Qn; + break; + case `scroll`: + c = Pn; + break; + case `wheel`: + c = $n; + break; + case `copy`: + case `cut`: + case `paste`: + c = Hn; + break; + case `gotpointercapture`: + case `lostpointercapture`: + case `pointercancel`: + case `pointerdown`: + case `pointermove`: + case `pointerout`: + case `pointerover`: + case `pointerup`: + c = Xn; + } + var u = (t & 4) != 0, + d = !u && e === `scroll`, + f = u ? (s === null ? null : s + `Capture`) : s; + u = []; + for (var p = r, m; p !== null; ) { + m = p; + var h = m.stateNode; + if ( + (m.tag === 5 && + h !== null && + ((m = h), f !== null && ((h = $e(p, f)), h != null && u.push(K(p, h, m)))), + d) + ) + break; + p = p.return; + } + 0 < u.length && ((s = new c(s, l, null, n, i)), o.push({ event: s, listeners: u })); + } + } + if (!(t & 7)) { + a: { + if ( + ((s = e === `mouseover` || e === `pointerover`), + (c = e === `mouseout` || e === `pointerout`), + s && n !== Ve && (l = n.relatedTarget || n.fromElement) && (Pi(l) || l[Ai])) + ) + break a; + if ( + (c || s) && + ((s = i.window === i ? i : (s = i.ownerDocument) ? s.defaultView || s.parentWindow : window), + c + ? ((l = n.relatedTarget || n.toElement), + (c = r), + (l = l ? Pi(l) : null), + l !== null && ((d = lt(l)), l !== d || (l.tag !== 5 && l.tag !== 6)) && (l = null)) + : ((c = null), (l = r)), + c !== l) + ) { + if ( + ((u = zn), + (h = `onMouseLeave`), + (f = `onMouseEnter`), + (p = `mouse`), + (e === `pointerout` || e === `pointerover`) && + ((u = Xn), (h = `onPointerLeave`), (f = `onPointerEnter`), (p = `pointer`)), + (d = c == null ? s : Ii(c)), + (m = l == null ? s : Ii(l)), + (s = new u(h, p + `leave`, c, n, i)), + (s.target = d), + (s.relatedTarget = m), + (h = null), + Pi(i) === r && ((u = new u(f, p + `enter`, l, n, i)), (u.target = m), (u.relatedTarget = d), (h = u)), + (d = h), + c && l) + ) + b: { + for (u = c, f = l, p = 0, m = u; m; m = ui(m)) p++; + for (m = 0, h = f; h; h = ui(h)) m++; + for (; 0 < p - m; ) ((u = ui(u)), p--); + for (; 0 < m - p; ) ((f = ui(f)), m--); + for (; p--; ) { + if (u === f || (f !== null && u === f.alternate)) break b; + ((u = ui(u)), (f = ui(f))); + } + u = null; + } + else u = null; + (c !== null && q(o, s, c, u, !1), l !== null && d !== null && q(o, d, l, u, !0)); + } + } + a: { + if ( + ((s = r ? Ii(r) : window), + (c = s.nodeName && s.nodeName.toLowerCase()), + c === `select` || (c === `input` && s.type === `file`)) + ) + var g = gr; + else if (ur(s)) + if (_r) g = Er; + else { + g = wr; + var _ = Cr; + } + else + (c = s.nodeName) && + c.toLowerCase() === `input` && + (s.type === `checkbox` || s.type === `radio`) && + (g = Tr); + if ((g &&= g(e, r))) { + dr(o, g, n, i); + break a; + } + (_ && _(e, s, r), + e === `focusout` && + (_ = s._wrapperState) && + _.controlled && + s.type === `number` && + Ce(s, `number`, s.value)); + } + switch (((_ = r ? Ii(r) : window), e)) { + case `focusin`: + (ur(_) || _.contentEditable === `true`) && ((Ir = _), (Lr = r), (Rr = null)); + break; + case `focusout`: + Rr = Lr = Ir = null; + break; + case `mousedown`: + zr = !0; + break; + case `contextmenu`: + case `mouseup`: + case `dragend`: + ((zr = !1), Br(o, n, i)); + break; + case `selectionchange`: + if (Fr) break; + case `keydown`: + case `keyup`: + Br(o, n, i); + } + var v; + if (tr) + b: { + switch (e) { + case `compositionstart`: + var y = `onCompositionStart`; + break b; + case `compositionend`: + y = `onCompositionEnd`; + break b; + case `compositionupdate`: + y = `onCompositionUpdate`; + break b; + } + y = void 0; + } + else + or + ? ir(e, n) && (y = `onCompositionEnd`) + : e === `keydown` && n.keyCode === 229 && (y = `onCompositionStart`); + (y && + (nr && + n.locale !== `ko` && + (or || y !== `onCompositionStart` + ? y === `onCompositionEnd` && or && (v = En()) + : ((Cn = i), (wn = `value` in Cn ? Cn.value : Cn.textContent), (or = !0))), + (_ = li(r, y)), + 0 < _.length && + ((y = new Un(y, e, null, n, i)), + o.push({ event: y, listeners: _ }), + v ? (y.data = v) : ((v = ar(n)), v !== null && (y.data = v)))), + (v = V ? sr(e, n) : cr(e, n)) && + ((r = li(r, `onBeforeInput`)), + 0 < r.length && + ((i = new Un(`onBeforeInput`, `beforeinput`, null, n, i)), + o.push({ event: i, listeners: r }), + (i.data = v)))); + } + ri(o, t); + }); + } + function K(e, t, n) { + return { instance: e, listener: t, currentTarget: n }; + } + function li(e, t) { + for (var n = t + `Capture`, r = []; e !== null; ) { + var i = e, + a = i.stateNode; + (i.tag === 5 && + a !== null && + ((i = a), + (a = $e(e, n)), + a != null && r.unshift(K(e, a, i)), + (a = $e(e, t)), + a != null && r.push(K(e, a, i))), + (e = e.return)); + } + return r; + } + function ui(e) { + if (e === null) return null; + do e = e.return; + while (e && e.tag !== 5); + return e || null; + } + function q(e, t, n, r, i) { + for (var a = t._reactName, o = []; n !== null && n !== r; ) { + var s = n, + c = s.alternate, + l = s.stateNode; + if (c !== null && c === r) break; + (s.tag === 5 && + l !== null && + ((s = l), + i + ? ((c = $e(n, a)), c != null && o.unshift(K(n, c, s))) + : i || ((c = $e(n, a)), c != null && o.push(K(n, c, s)))), + (n = n.return)); + } + o.length !== 0 && e.push({ event: t, listeners: o }); + } + var di = /\r\n?/g, + fi = /\u0000|\uFFFD/g; + function pi(e) { + return (typeof e == `string` ? e : `` + e) + .replace( + di, + ` +`, + ) + .replace(fi, ``); + } + function mi(e, t, n) { + if (((t = pi(t)), pi(e) !== t && n)) throw Error(r(425)); + } + function hi() {} + var gi = null, + _i = null; + function vi(e, t) { + return ( + e === `textarea` || + e === `noscript` || + typeof t.children == `string` || + typeof t.children == `number` || + (typeof t.dangerouslySetInnerHTML == `object` && + t.dangerouslySetInnerHTML !== null && + t.dangerouslySetInnerHTML.__html != null) + ); + } + var yi = typeof setTimeout == `function` ? setTimeout : void 0, + bi = typeof clearTimeout == `function` ? clearTimeout : void 0, + xi = typeof Promise == `function` ? Promise : void 0, + Si = + typeof queueMicrotask == `function` + ? queueMicrotask + : xi === void 0 + ? yi + : function (e) { + return xi.resolve(null).then(e).catch(Ci); + }; + function Ci(e) { + setTimeout(function () { + throw e; + }); + } + function wi(e, t) { + var n = t, + r = 0; + do { + var i = n.nextSibling; + if ((e.removeChild(n), i && i.nodeType === 8)) + if (((n = i.data), n === `/$`)) { + if (r === 0) { + (e.removeChild(i), mn(t)); + return; + } + r--; + } else (n !== `$` && n !== `$?` && n !== `$!`) || r++; + n = i; + } while (n); + mn(t); + } + function Ti(e) { + for (; e != null; e = e.nextSibling) { + var t = e.nodeType; + if (t === 1 || t === 3) break; + if (t === 8) { + if (((t = e.data), t === `$` || t === `$!` || t === `$?`)) break; + if (t === `/$`) return null; + } + } + return e; + } + function Ei(e) { + e = e.previousSibling; + for (var t = 0; e; ) { + if (e.nodeType === 8) { + var n = e.data; + if (n === `$` || n === `$!` || n === `$?`) { + if (t === 0) return e; + t--; + } else n === `/$` && t++; + } + e = e.previousSibling; + } + return null; + } + var Di = Math.random().toString(36).slice(2), + Oi = `__reactFiber$` + Di, + ki = `__reactProps$` + Di, + Ai = `__reactContainer$` + Di, + ji = `__reactEvents$` + Di, + Mi = `__reactListeners$` + Di, + Ni = `__reactHandles$` + Di; + function Pi(e) { + var t = e[Oi]; + if (t) return t; + for (var n = e.parentNode; n; ) { + if ((t = n[Ai] || n[Oi])) { + if (((n = t.alternate), t.child !== null || (n !== null && n.child !== null))) + for (e = Ei(e); e !== null; ) { + if ((n = e[Oi])) return n; + e = Ei(e); + } + return t; + } + ((e = n), (n = e.parentNode)); + } + return null; + } + function Fi(e) { + return ((e = e[Oi] || e[Ai]), !e || (e.tag !== 5 && e.tag !== 6 && e.tag !== 13 && e.tag !== 3) ? null : e); + } + function Ii(e) { + if (e.tag === 5 || e.tag === 6) return e.stateNode; + throw Error(r(33)); + } + function Li(e) { + return e[ki] || null; + } + var Ri = [], + zi = -1; + function Bi(e) { + return { current: e }; + } + function J(e) { + 0 > zi || ((e.current = Ri[zi]), (Ri[zi] = null), zi--); + } + function Y(e, t) { + (zi++, (Ri[zi] = e.current), (e.current = t)); + } + var Vi = {}, + Hi = Bi(Vi), + Ui = Bi(!1), + Wi = Vi; + function Gi(e, t) { + var n = e.type.contextTypes; + if (!n) return Vi; + var r = e.stateNode; + if (r && r.__reactInternalMemoizedUnmaskedChildContext === t) return r.__reactInternalMemoizedMaskedChildContext; + var i = {}, + a; + for (a in n) i[a] = t[a]; + return ( + r && + ((e = e.stateNode), + (e.__reactInternalMemoizedUnmaskedChildContext = t), + (e.__reactInternalMemoizedMaskedChildContext = i)), + i + ); + } + function Ki(e) { + return ((e = e.childContextTypes), e != null); + } + function qi() { + (J(Ui), J(Hi)); + } + function Ji(e, t, n) { + if (Hi.current !== Vi) throw Error(r(168)); + (Y(Hi, t), Y(Ui, n)); + } + function Yi(e, t, n) { + var i = e.stateNode; + if (((t = t.childContextTypes), typeof i.getChildContext != `function`)) return n; + for (var a in ((i = i.getChildContext()), i)) if (!(a in t)) throw Error(r(108, pe(e) || `Unknown`, a)); + return M({}, n, i); + } + function Xi(e) { + return ( + (e = ((e = e.stateNode) && e.__reactInternalMemoizedMergedChildContext) || Vi), + (Wi = Hi.current), + Y(Hi, e), + Y(Ui, Ui.current), + !0 + ); + } + function Zi(e, t, n) { + var i = e.stateNode; + if (!i) throw Error(r(169)); + (n ? ((e = Yi(e, t, Wi)), (i.__reactInternalMemoizedMergedChildContext = e), J(Ui), J(Hi), Y(Hi, e)) : J(Ui), + Y(Ui, n)); + } + var Qi = null, + $i = !1, + ea = !1; + function ta(e) { + Qi === null ? (Qi = [e]) : Qi.push(e); + } + function na(e) { + (($i = !0), ta(e)); + } + function ra() { + if (!ea && Qi !== null) { + ea = !0; + var e = 0, + t = R; + try { + var n = Qi; + for (R = 1; e < n.length; e++) { + var r = n[e]; + do r = r(!0); + while (r !== null); + } + ((Qi = null), ($i = !1)); + } catch (t) { + throw (Qi !== null && (Qi = Qi.slice(e + 1)), ht(xt, ra), t); + } finally { + ((R = t), (ea = !1)); + } + } + return null; + } + var ia = [], + aa = 0, + oa = null, + sa = 0, + ca = [], + la = 0, + ua = null, + da = 1, + fa = ``; + function X(e, t) { + ((ia[aa++] = sa), (ia[aa++] = oa), (oa = e), (sa = t)); + } + function pa(e, t, n) { + ((ca[la++] = da), (ca[la++] = fa), (ca[la++] = ua), (ua = e)); + var r = da; + e = fa; + var i = 32 - kt(r) - 1; + ((r &= ~(1 << i)), (n += 1)); + var a = 32 - kt(t) + i; + if (30 < a) { + var o = i - (i % 5); + ((a = (r & ((1 << o) - 1)).toString(32)), + (r >>= o), + (i -= o), + (da = (1 << (32 - kt(t) + i)) | (n << i) | r), + (fa = a + e)); + } else ((da = (1 << a) | (n << i) | r), (fa = e)); + } + function ma(e) { + e.return !== null && (X(e, 1), pa(e, 1, 0)); + } + function ha(e) { + for (; e === oa; ) ((oa = ia[--aa]), (ia[aa] = null), (sa = ia[--aa]), (ia[aa] = null)); + for (; e === ua; ) + ((ua = ca[--la]), (ca[la] = null), (fa = ca[--la]), (ca[la] = null), (da = ca[--la]), (ca[la] = null)); + } + var ga = null, + _a = null, + Z = !1, + va = null; + function ya(e, t) { + var n = Kl(5, null, null, 0); + ((n.elementType = `DELETED`), + (n.stateNode = t), + (n.return = e), + (t = e.deletions), + t === null ? ((e.deletions = [n]), (e.flags |= 16)) : t.push(n)); + } + function ba(e, t) { + switch (e.tag) { + case 5: + var n = e.type; + return ( + (t = t.nodeType !== 1 || n.toLowerCase() !== t.nodeName.toLowerCase() ? null : t), + t === null ? !1 : ((e.stateNode = t), (ga = e), (_a = Ti(t.firstChild)), !0) + ); + case 6: + return ( + (t = e.pendingProps === `` || t.nodeType !== 3 ? null : t), + t === null ? !1 : ((e.stateNode = t), (ga = e), (_a = null), !0) + ); + case 13: + return ( + (t = t.nodeType === 8 ? t : null), + t === null + ? !1 + : ((n = ua === null ? null : { id: da, overflow: fa }), + (e.memoizedState = { dehydrated: t, treeContext: n, retryLane: 1073741824 }), + (n = Kl(18, null, null, 0)), + (n.stateNode = t), + (n.return = e), + (e.child = n), + (ga = e), + (_a = null), + !0) + ); + default: + return !1; + } + } + function xa(e) { + return (e.mode & 1) != 0 && (e.flags & 128) == 0; + } + function Sa(e) { + if (Z) { + var t = _a; + if (t) { + var n = t; + if (!ba(e, t)) { + if (xa(e)) throw Error(r(418)); + t = Ti(n.nextSibling); + var i = ga; + t && ba(e, t) ? ya(i, n) : ((e.flags = (e.flags & -4097) | 2), (Z = !1), (ga = e)); + } + } else { + if (xa(e)) throw Error(r(418)); + ((e.flags = (e.flags & -4097) | 2), (Z = !1), (ga = e)); + } + } + } + function Ca(e) { + for (e = e.return; e !== null && e.tag !== 5 && e.tag !== 3 && e.tag !== 13; ) e = e.return; + ga = e; + } + function wa(e) { + if (e !== ga) return !1; + if (!Z) return (Ca(e), (Z = !0), !1); + var t; + if ( + ((t = e.tag !== 3) && + !(t = e.tag !== 5) && + ((t = e.type), (t = t !== `head` && t !== `body` && !vi(e.type, e.memoizedProps))), + (t &&= _a)) + ) { + if (xa(e)) throw (Ta(), Error(r(418))); + for (; t; ) (ya(e, t), (t = Ti(t.nextSibling))); + } + if ((Ca(e), e.tag === 13)) { + if (((e = e.memoizedState), (e = e === null ? null : e.dehydrated), !e)) throw Error(r(317)); + a: { + for (e = e.nextSibling, t = 0; e; ) { + if (e.nodeType === 8) { + var n = e.data; + if (n === `/$`) { + if (t === 0) { + _a = Ti(e.nextSibling); + break a; + } + t--; + } else (n !== `$` && n !== `$!` && n !== `$?`) || t++; + } + e = e.nextSibling; + } + _a = null; + } + } else _a = ga ? Ti(e.stateNode.nextSibling) : null; + return !0; + } + function Ta() { + for (var e = _a; e; ) e = Ti(e.nextSibling); + } + function Ea() { + ((_a = ga = null), (Z = !1)); + } + function Da(e) { + va === null ? (va = [e]) : va.push(e); + } + var Oa = C.ReactCurrentBatchConfig; + function ka(e, t, n) { + if (((e = n.ref), e !== null && typeof e != `function` && typeof e != `object`)) { + if (n._owner) { + if (((n = n._owner), n)) { + if (n.tag !== 1) throw Error(r(309)); + var i = n.stateNode; + } + if (!i) throw Error(r(147, e)); + var a = i, + o = `` + e; + return t !== null && t.ref !== null && typeof t.ref == `function` && t.ref._stringRef === o + ? t.ref + : ((t = function (e) { + var t = a.refs; + e === null ? delete t[o] : (t[o] = e); + }), + (t._stringRef = o), + t); + } + if (typeof e != `string`) throw Error(r(284)); + if (!n._owner) throw Error(r(290, e)); + } + return e; + } + function Aa(e, t) { + throw ( + (e = Object.prototype.toString.call(t)), + Error(r(31, e === `[object Object]` ? `object with keys {` + Object.keys(t).join(`, `) + `}` : e)) + ); + } + function ja(e) { + var t = e._init; + return t(e._payload); + } + function Ma(e) { + function t(t, n) { + if (e) { + var r = t.deletions; + r === null ? ((t.deletions = [n]), (t.flags |= 16)) : r.push(n); + } + } + function n(n, r) { + if (!e) return null; + for (; r !== null; ) (t(n, r), (r = r.sibling)); + return null; + } + function i(e, t) { + for (e = new Map(); t !== null; ) (t.key === null ? e.set(t.index, t) : e.set(t.key, t), (t = t.sibling)); + return e; + } + function a(e, t) { + return ((e = Yl(e, t)), (e.index = 0), (e.sibling = null), e); + } + function o(t, n, r) { + return ( + (t.index = r), + e + ? ((r = t.alternate), r === null ? ((t.flags |= 2), n) : ((r = r.index), r < n ? ((t.flags |= 2), n) : r)) + : ((t.flags |= 1048576), n) + ); + } + function s(t) { + return (e && t.alternate === null && (t.flags |= 2), t); + } + function c(e, t, n, r) { + return t === null || t.tag !== 6 + ? ((t = $l(n, e.mode, r)), (t.return = e), t) + : ((t = a(t, n)), (t.return = e), t); + } + function l(e, t, n, r) { + var i = n.type; + return i === E + ? d(e, t, n.props.children, r, n.key) + : t !== null && (t.elementType === i || (typeof i == `object` && i && i.$$typeof === j && ja(i) === t.type)) + ? ((r = a(t, n.props)), (r.ref = ka(e, t, n)), (r.return = e), r) + : ((r = Xl(n.type, n.key, n.props, null, e.mode, r)), (r.ref = ka(e, t, n)), (r.return = e), r); + } + function u(e, t, n, r) { + return t === null || + t.tag !== 4 || + t.stateNode.containerInfo !== n.containerInfo || + t.stateNode.implementation !== n.implementation + ? ((t = eu(n, e.mode, r)), (t.return = e), t) + : ((t = a(t, n.children || [])), (t.return = e), t); + } + function d(e, t, n, r, i) { + return t === null || t.tag !== 7 + ? ((t = Zl(n, e.mode, r, i)), (t.return = e), t) + : ((t = a(t, n)), (t.return = e), t); + } + function f(e, t, n) { + if ((typeof t == `string` && t !== ``) || typeof t == `number`) + return ((t = $l(`` + t, e.mode, n)), (t.return = e), t); + if (typeof t == `object` && t) { + switch (t.$$typeof) { + case w: + return ((n = Xl(t.type, t.key, t.props, null, e.mode, n)), (n.ref = ka(e, null, t)), (n.return = e), n); + case T: + return ((t = eu(t, e.mode, n)), (t.return = e), t); + case j: + var r = t._init; + return f(e, r(t._payload), n); + } + if (F(t) || oe(t)) return ((t = Zl(t, e.mode, n, null)), (t.return = e), t); + Aa(e, t); + } + return null; + } + function p(e, t, n, r) { + var i = t === null ? null : t.key; + if ((typeof n == `string` && n !== ``) || typeof n == `number`) return i === null ? c(e, t, `` + n, r) : null; + if (typeof n == `object` && n) { + switch (n.$$typeof) { + case w: + return n.key === i ? l(e, t, n, r) : null; + case T: + return n.key === i ? u(e, t, n, r) : null; + case j: + return ((i = n._init), p(e, t, i(n._payload), r)); + } + if (F(n) || oe(n)) return i === null ? d(e, t, n, r, null) : null; + Aa(e, n); + } + return null; + } + function m(e, t, n, r, i) { + if ((typeof r == `string` && r !== ``) || typeof r == `number`) + return ((e = e.get(n) || null), c(t, e, `` + r, i)); + if (typeof r == `object` && r) { + switch (r.$$typeof) { + case w: + return ((e = e.get(r.key === null ? n : r.key) || null), l(t, e, r, i)); + case T: + return ((e = e.get(r.key === null ? n : r.key) || null), u(t, e, r, i)); + case j: + var a = r._init; + return m(e, t, n, a(r._payload), i); + } + if (F(r) || oe(r)) return ((e = e.get(n) || null), d(t, e, r, i, null)); + Aa(t, r); + } + return null; + } + function h(r, a, s, c) { + for (var l = null, u = null, d = a, h = (a = 0), g = null; d !== null && h < s.length; h++) { + d.index > h ? ((g = d), (d = null)) : (g = d.sibling); + var _ = p(r, d, s[h], c); + if (_ === null) { + d === null && (d = g); + break; + } + (e && d && _.alternate === null && t(r, d), + (a = o(_, a, h)), + u === null ? (l = _) : (u.sibling = _), + (u = _), + (d = g)); + } + if (h === s.length) return (n(r, d), Z && X(r, h), l); + if (d === null) { + for (; h < s.length; h++) + ((d = f(r, s[h], c)), d !== null && ((a = o(d, a, h)), u === null ? (l = d) : (u.sibling = d), (u = d))); + return (Z && X(r, h), l); + } + for (d = i(r, d); h < s.length; h++) + ((g = m(d, r, h, s[h], c)), + g !== null && + (e && g.alternate !== null && d.delete(g.key === null ? h : g.key), + (a = o(g, a, h)), + u === null ? (l = g) : (u.sibling = g), + (u = g))); + return ( + e && + d.forEach(function (e) { + return t(r, e); + }), + Z && X(r, h), + l + ); + } + function g(a, s, c, l) { + var u = oe(c); + if (typeof u != `function`) throw Error(r(150)); + if (((c = u.call(c)), c == null)) throw Error(r(151)); + for (var d = (u = null), h = s, g = (s = 0), _ = null, v = c.next(); h !== null && !v.done; g++, v = c.next()) { + h.index > g ? ((_ = h), (h = null)) : (_ = h.sibling); + var y = p(a, h, v.value, l); + if (y === null) { + h === null && (h = _); + break; + } + (e && h && y.alternate === null && t(a, h), + (s = o(y, s, g)), + d === null ? (u = y) : (d.sibling = y), + (d = y), + (h = _)); + } + if (v.done) return (n(a, h), Z && X(a, g), u); + if (h === null) { + for (; !v.done; g++, v = c.next()) + ((v = f(a, v.value, l)), v !== null && ((s = o(v, s, g)), d === null ? (u = v) : (d.sibling = v), (d = v))); + return (Z && X(a, g), u); + } + for (h = i(a, h); !v.done; g++, v = c.next()) + ((v = m(h, a, g, v.value, l)), + v !== null && + (e && v.alternate !== null && h.delete(v.key === null ? g : v.key), + (s = o(v, s, g)), + d === null ? (u = v) : (d.sibling = v), + (d = v))); + return ( + e && + h.forEach(function (e) { + return t(a, e); + }), + Z && X(a, g), + u + ); + } + function _(e, r, i, o) { + if ( + (typeof i == `object` && i && i.type === E && i.key === null && (i = i.props.children), + typeof i == `object` && i) + ) { + switch (i.$$typeof) { + case w: + a: { + for (var c = i.key, l = r; l !== null; ) { + if (l.key === c) { + if (((c = i.type), c === E)) { + if (l.tag === 7) { + (n(e, l.sibling), (r = a(l, i.props.children)), (r.return = e), (e = r)); + break a; + } + } else if ( + l.elementType === c || + (typeof c == `object` && c && c.$$typeof === j && ja(c) === l.type) + ) { + (n(e, l.sibling), (r = a(l, i.props)), (r.ref = ka(e, l, i)), (r.return = e), (e = r)); + break a; + } + n(e, l); + break; + } else t(e, l); + l = l.sibling; + } + i.type === E + ? ((r = Zl(i.props.children, e.mode, o, i.key)), (r.return = e), (e = r)) + : ((o = Xl(i.type, i.key, i.props, null, e.mode, o)), (o.ref = ka(e, r, i)), (o.return = e), (e = o)); + } + return s(e); + case T: + a: { + for (l = i.key; r !== null; ) { + if (r.key === l) + if ( + r.tag === 4 && + r.stateNode.containerInfo === i.containerInfo && + r.stateNode.implementation === i.implementation + ) { + (n(e, r.sibling), (r = a(r, i.children || [])), (r.return = e), (e = r)); + break a; + } else { + n(e, r); + break; + } + else t(e, r); + r = r.sibling; + } + ((r = eu(i, e.mode, o)), (r.return = e), (e = r)); + } + return s(e); + case j: + return ((l = i._init), _(e, r, l(i._payload), o)); + } + if (F(i)) return h(e, r, i, o); + if (oe(i)) return g(e, r, i, o); + Aa(e, i); + } + return (typeof i == `string` && i !== ``) || typeof i == `number` + ? ((i = `` + i), + r !== null && r.tag === 6 + ? (n(e, r.sibling), (r = a(r, i)), (r.return = e), (e = r)) + : (n(e, r), (r = $l(i, e.mode, o)), (r.return = e), (e = r)), + s(e)) + : n(e, r); + } + return _; + } + var Na = Ma(!0), + Pa = Ma(!1), + Fa = Bi(null), + Ia = null, + La = null, + Ra = null; + function za() { + Ra = La = Ia = null; + } + function Ba(e) { + var t = Fa.current; + (J(Fa), (e._currentValue = t)); + } + function Va(e, t, n) { + for (; e !== null; ) { + var r = e.alternate; + if ( + ((e.childLanes & t) === t + ? r !== null && (r.childLanes & t) !== t && (r.childLanes |= t) + : ((e.childLanes |= t), r !== null && (r.childLanes |= t)), + e === n) + ) + break; + e = e.return; + } + } + function Ha(e, t) { + ((Ia = e), + (Ra = La = null), + (e = e.dependencies), + e !== null && e.firstContext !== null && ((e.lanes & t) !== 0 && (Ms = !0), (e.firstContext = null))); + } + function Ua(e) { + var t = e._currentValue; + if (Ra !== e) + if (((e = { context: e, memoizedValue: t, next: null }), La === null)) { + if (Ia === null) throw Error(r(308)); + ((La = e), (Ia.dependencies = { lanes: 0, firstContext: e })); + } else La = La.next = e; + return t; + } + var Wa = null; + function Ga(e) { + Wa === null ? (Wa = [e]) : Wa.push(e); + } + function Ka(e, t, n, r) { + var i = t.interleaved; + return (i === null ? ((n.next = n), Ga(t)) : ((n.next = i.next), (i.next = n)), (t.interleaved = n), qa(e, r)); + } + function qa(e, t) { + e.lanes |= t; + var n = e.alternate; + for (n !== null && (n.lanes |= t), n = e, e = e.return; e !== null; ) + ((e.childLanes |= t), (n = e.alternate), n !== null && (n.childLanes |= t), (n = e), (e = e.return)); + return n.tag === 3 ? n.stateNode : null; + } + var Ja = !1; + function Ya(e) { + e.updateQueue = { + baseState: e.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { pending: null, interleaved: null, lanes: 0 }, + effects: null, + }; + } + function Xa(e, t) { + ((e = e.updateQueue), + t.updateQueue === e && + (t.updateQueue = { + baseState: e.baseState, + firstBaseUpdate: e.firstBaseUpdate, + lastBaseUpdate: e.lastBaseUpdate, + shared: e.shared, + effects: e.effects, + })); + } + function Za(e, t) { + return { eventTime: e, lane: t, tag: 0, payload: null, callback: null, next: null }; + } + function Qa(e, t, n) { + var r = e.updateQueue; + if (r === null) return null; + if (((r = r.shared), $ & 2)) { + var i = r.pending; + return (i === null ? (t.next = t) : ((t.next = i.next), (i.next = t)), (r.pending = t), qa(e, n)); + } + return ( + (i = r.interleaved), + i === null ? ((t.next = t), Ga(r)) : ((t.next = i.next), (i.next = t)), + (r.interleaved = t), + qa(e, n) + ); + } + function $a(e, t, n) { + if (((t = t.updateQueue), t !== null && ((t = t.shared), n & 4194240))) { + var r = t.lanes; + ((r &= e.pendingLanes), (n |= r), (t.lanes = n), Ut(e, n)); + } + } + function eo(e, t) { + var n = e.updateQueue, + r = e.alternate; + if (r !== null && ((r = r.updateQueue), n === r)) { + var i = null, + a = null; + if (((n = n.firstBaseUpdate), n !== null)) { + do { + var o = { + eventTime: n.eventTime, + lane: n.lane, + tag: n.tag, + payload: n.payload, + callback: n.callback, + next: null, + }; + (a === null ? (i = a = o) : (a = a.next = o), (n = n.next)); + } while (n !== null); + a === null ? (i = a = t) : (a = a.next = t); + } else i = a = t; + ((n = { baseState: r.baseState, firstBaseUpdate: i, lastBaseUpdate: a, shared: r.shared, effects: r.effects }), + (e.updateQueue = n)); + return; + } + ((e = n.lastBaseUpdate), e === null ? (n.firstBaseUpdate = t) : (e.next = t), (n.lastBaseUpdate = t)); + } + function to(e, t, n, r) { + var i = e.updateQueue; + Ja = !1; + var a = i.firstBaseUpdate, + o = i.lastBaseUpdate, + s = i.shared.pending; + if (s !== null) { + i.shared.pending = null; + var c = s, + l = c.next; + ((c.next = null), o === null ? (a = l) : (o.next = l), (o = c)); + var u = e.alternate; + u !== null && + ((u = u.updateQueue), + (s = u.lastBaseUpdate), + s !== o && (s === null ? (u.firstBaseUpdate = l) : (s.next = l), (u.lastBaseUpdate = c))); + } + if (a !== null) { + var d = i.baseState; + ((o = 0), (u = l = c = null), (s = a)); + do { + var f = s.lane, + p = s.eventTime; + if ((r & f) === f) { + u !== null && + (u = u.next = + { eventTime: p, lane: 0, tag: s.tag, payload: s.payload, callback: s.callback, next: null }); + a: { + var m = e, + h = s; + switch (((f = t), (p = n), h.tag)) { + case 1: + if (((m = h.payload), typeof m == `function`)) { + d = m.call(p, d, f); + break a; + } + d = m; + break a; + case 3: + m.flags = (m.flags & -65537) | 128; + case 0: + if (((m = h.payload), (f = typeof m == `function` ? m.call(p, d, f) : m), f == null)) break a; + d = M({}, d, f); + break a; + case 2: + Ja = !0; + } + } + s.callback !== null && + s.lane !== 0 && + ((e.flags |= 64), (f = i.effects), f === null ? (i.effects = [s]) : f.push(s)); + } else + ((p = { eventTime: p, lane: f, tag: s.tag, payload: s.payload, callback: s.callback, next: null }), + u === null ? ((l = u = p), (c = d)) : (u = u.next = p), + (o |= f)); + if (((s = s.next), s === null)) { + if (((s = i.shared.pending), s === null)) break; + ((f = s), (s = f.next), (f.next = null), (i.lastBaseUpdate = f), (i.shared.pending = null)); + } + } while (1); + if ( + (u === null && (c = d), + (i.baseState = c), + (i.firstBaseUpdate = l), + (i.lastBaseUpdate = u), + (t = i.shared.interleaved), + t !== null) + ) { + i = t; + do ((o |= i.lane), (i = i.next)); + while (i !== t); + } else a === null && (i.shared.lanes = 0); + ((Jc |= o), (e.lanes = o), (e.memoizedState = d)); + } + } + function no(e, t, n) { + if (((e = t.effects), (t.effects = null), e !== null)) + for (t = 0; t < e.length; t++) { + var i = e[t], + a = i.callback; + if (a !== null) { + if (((i.callback = null), (i = n), typeof a != `function`)) throw Error(r(191, a)); + a.call(i); + } + } + } + var ro = {}, + io = Bi(ro), + ao = Bi(ro), + oo = Bi(ro); + function so(e) { + if (e === ro) throw Error(r(174)); + return e; + } + function co(e, t) { + switch ((Y(oo, t), Y(ao, e), Y(io, ro), (e = t.nodeType), e)) { + case 9: + case 11: + t = (t = t.documentElement) ? t.namespaceURI : Ae(null, ``); + break; + default: + ((e = e === 8 ? t.parentNode : t), (t = e.namespaceURI || null), (e = e.tagName), (t = Ae(t, e))); + } + (J(io), Y(io, t)); + } + function lo() { + (J(io), J(ao), J(oo)); + } + function uo(e) { + so(oo.current); + var t = so(io.current), + n = Ae(t, e.type); + t !== n && (Y(ao, e), Y(io, n)); + } + function fo(e) { + ao.current === e && (J(io), J(ao)); + } + var po = Bi(0); + function mo(e) { + for (var t = e; t !== null; ) { + if (t.tag === 13) { + var n = t.memoizedState; + if (n !== null && ((n = n.dehydrated), n === null || n.data === `$?` || n.data === `$!`)) return t; + } else if (t.tag === 19 && t.memoizedProps.revealOrder !== void 0) { + if (t.flags & 128) return t; + } else if (t.child !== null) { + ((t.child.return = t), (t = t.child)); + continue; + } + if (t === e) break; + for (; t.sibling === null; ) { + if (t.return === null || t.return === e) return null; + t = t.return; + } + ((t.sibling.return = t.return), (t = t.sibling)); + } + return null; + } + var ho = []; + function go() { + for (var e = 0; e < ho.length; e++) ho[e]._workInProgressVersionPrimary = null; + ho.length = 0; + } + var _o = C.ReactCurrentDispatcher, + vo = C.ReactCurrentBatchConfig, + yo = 0, + bo = null, + xo = null, + So = null, + Co = !1, + wo = !1, + To = 0, + Eo = 0; + function Do() { + throw Error(r(321)); + } + function Oo(e, t) { + if (t === null) return !1; + for (var n = 0; n < t.length && n < e.length; n++) if (!Or(e[n], t[n])) return !1; + return !0; + } + function ko(e, t, n, i, a, o) { + if ( + ((yo = o), + (bo = t), + (t.memoizedState = null), + (t.updateQueue = null), + (t.lanes = 0), + (_o.current = e === null || e.memoizedState === null ? fs : ps), + (e = n(i, a)), + wo) + ) { + o = 0; + do { + if (((wo = !1), (To = 0), 25 <= o)) throw Error(r(301)); + ((o += 1), (So = xo = null), (t.updateQueue = null), (_o.current = ms), (e = n(i, a))); + } while (wo); + } + if (((_o.current = ds), (t = xo !== null && xo.next !== null), (yo = 0), (So = xo = bo = null), (Co = !1), t)) + throw Error(r(300)); + return e; + } + function Ao() { + var e = To !== 0; + return ((To = 0), e); + } + function jo() { + var e = { memoizedState: null, baseState: null, baseQueue: null, queue: null, next: null }; + return (So === null ? (bo.memoizedState = So = e) : (So = So.next = e), So); + } + function Mo() { + if (xo === null) { + var e = bo.alternate; + e = e === null ? null : e.memoizedState; + } else e = xo.next; + var t = So === null ? bo.memoizedState : So.next; + if (t !== null) ((So = t), (xo = e)); + else { + if (e === null) throw Error(r(310)); + ((xo = e), + (e = { + memoizedState: xo.memoizedState, + baseState: xo.baseState, + baseQueue: xo.baseQueue, + queue: xo.queue, + next: null, + }), + So === null ? (bo.memoizedState = So = e) : (So = So.next = e)); + } + return So; + } + function No(e, t) { + return typeof t == `function` ? t(e) : t; + } + function Po(e) { + var t = Mo(), + n = t.queue; + if (n === null) throw Error(r(311)); + n.lastRenderedReducer = e; + var i = xo, + a = i.baseQueue, + o = n.pending; + if (o !== null) { + if (a !== null) { + var s = a.next; + ((a.next = o.next), (o.next = s)); + } + ((i.baseQueue = a = o), (n.pending = null)); + } + if (a !== null) { + ((o = a.next), (i = i.baseState)); + var c = (s = null), + l = null, + u = o; + do { + var d = u.lane; + if ((yo & d) === d) + (l !== null && + (l = l.next = + { lane: 0, action: u.action, hasEagerState: u.hasEagerState, eagerState: u.eagerState, next: null }), + (i = u.hasEagerState ? u.eagerState : e(i, u.action))); + else { + var f = { lane: d, action: u.action, hasEagerState: u.hasEagerState, eagerState: u.eagerState, next: null }; + (l === null ? ((c = l = f), (s = i)) : (l = l.next = f), (bo.lanes |= d), (Jc |= d)); + } + u = u.next; + } while (u !== null && u !== o); + (l === null ? (s = i) : (l.next = c), + Or(i, t.memoizedState) || (Ms = !0), + (t.memoizedState = i), + (t.baseState = s), + (t.baseQueue = l), + (n.lastRenderedState = i)); + } + if (((e = n.interleaved), e !== null)) { + a = e; + do ((o = a.lane), (bo.lanes |= o), (Jc |= o), (a = a.next)); + while (a !== e); + } else a === null && (n.lanes = 0); + return [t.memoizedState, n.dispatch]; + } + function Fo(e) { + var t = Mo(), + n = t.queue; + if (n === null) throw Error(r(311)); + n.lastRenderedReducer = e; + var i = n.dispatch, + a = n.pending, + o = t.memoizedState; + if (a !== null) { + n.pending = null; + var s = (a = a.next); + do ((o = e(o, s.action)), (s = s.next)); + while (s !== a); + (Or(o, t.memoizedState) || (Ms = !0), + (t.memoizedState = o), + t.baseQueue === null && (t.baseState = o), + (n.lastRenderedState = o)); + } + return [o, i]; + } + function Io() {} + function Lo(e, t) { + var n = bo, + i = Mo(), + a = t(), + o = !Or(i.memoizedState, a); + if ( + (o && ((i.memoizedState = a), (Ms = !0)), + (i = i.queue), + Yo(Bo.bind(null, n, i, e), [e]), + i.getSnapshot !== t || o || (So !== null && So.memoizedState.tag & 1)) + ) { + if (((n.flags |= 2048), Wo(9, zo.bind(null, n, i, a, t), void 0, null), Vc === null)) throw Error(r(349)); + yo & 30 || Ro(n, t, a); + } + return a; + } + function Ro(e, t, n) { + ((e.flags |= 16384), + (e = { getSnapshot: t, value: n }), + (t = bo.updateQueue), + t === null + ? ((t = { lastEffect: null, stores: null }), (bo.updateQueue = t), (t.stores = [e])) + : ((n = t.stores), n === null ? (t.stores = [e]) : n.push(e))); + } + function zo(e, t, n, r) { + ((t.value = n), (t.getSnapshot = r), Vo(t) && Ho(e)); + } + function Bo(e, t, n) { + return n(function () { + Vo(t) && Ho(e); + }); + } + function Vo(e) { + var t = e.getSnapshot; + e = e.value; + try { + var n = t(); + return !Or(e, n); + } catch { + return !0; + } + } + function Ho(e) { + var t = qa(e, 1); + t !== null && ml(t, e, 1, -1); + } + function Uo(e) { + var t = jo(); + return ( + typeof e == `function` && (e = e()), + (t.memoizedState = t.baseState = e), + (e = { + pending: null, + interleaved: null, + lanes: 0, + dispatch: null, + lastRenderedReducer: No, + lastRenderedState: e, + }), + (t.queue = e), + (e = e.dispatch = ss.bind(null, bo, e)), + [t.memoizedState, e] + ); + } + function Wo(e, t, n, r) { + return ( + (e = { tag: e, create: t, destroy: n, deps: r, next: null }), + (t = bo.updateQueue), + t === null + ? ((t = { lastEffect: null, stores: null }), (bo.updateQueue = t), (t.lastEffect = e.next = e)) + : ((n = t.lastEffect), + n === null ? (t.lastEffect = e.next = e) : ((r = n.next), (n.next = e), (e.next = r), (t.lastEffect = e))), + e + ); + } + function Go() { + return Mo().memoizedState; + } + function Ko(e, t, n, r) { + var i = jo(); + ((bo.flags |= e), (i.memoizedState = Wo(1 | t, n, void 0, r === void 0 ? null : r))); + } + function qo(e, t, n, r) { + var i = Mo(); + r = r === void 0 ? null : r; + var a = void 0; + if (xo !== null) { + var o = xo.memoizedState; + if (((a = o.destroy), r !== null && Oo(r, o.deps))) { + i.memoizedState = Wo(t, n, a, r); + return; + } + } + ((bo.flags |= e), (i.memoizedState = Wo(1 | t, n, a, r))); + } + function Jo(e, t) { + return Ko(8390656, 8, e, t); + } + function Yo(e, t) { + return qo(2048, 8, e, t); + } + function Xo(e, t) { + return qo(4, 2, e, t); + } + function Zo(e, t) { + return qo(4, 4, e, t); + } + function Qo(e, t) { + if (typeof t == `function`) + return ( + (e = e()), + t(e), + function () { + t(null); + } + ); + if (t != null) + return ( + (e = e()), + (t.current = e), + function () { + t.current = null; + } + ); + } + function $o(e, t, n) { + return ((n = n == null ? null : n.concat([e])), qo(4, 4, Qo.bind(null, t, e), n)); + } + function es() {} + function ts(e, t) { + var n = Mo(); + t = t === void 0 ? null : t; + var r = n.memoizedState; + return r !== null && t !== null && Oo(t, r[1]) ? r[0] : ((n.memoizedState = [e, t]), e); + } + function ns(e, t) { + var n = Mo(); + t = t === void 0 ? null : t; + var r = n.memoizedState; + return r !== null && t !== null && Oo(t, r[1]) ? r[0] : ((e = e()), (n.memoizedState = [e, t]), e); + } + function rs(e, t, n) { + return yo & 21 + ? (Or(n, t) || ((n = Bt()), (bo.lanes |= n), (Jc |= n), (e.baseState = !0)), t) + : (e.baseState && ((e.baseState = !1), (Ms = !0)), (e.memoizedState = n)); + } + function is(e, t) { + var n = R; + ((R = n !== 0 && 4 > n ? n : 4), e(!0)); + var r = vo.transition; + vo.transition = {}; + try { + (e(!1), t()); + } finally { + ((R = n), (vo.transition = r)); + } + } + function as() { + return Mo().memoizedState; + } + function os(e, t, n) { + var r = pl(e); + if (((n = { lane: r, action: n, hasEagerState: !1, eagerState: null, next: null }), cs(e))) ls(t, n); + else if (((n = Ka(e, t, n, r)), n !== null)) { + var i = fl(); + (ml(n, e, r, i), us(n, t, r)); + } + } + function ss(e, t, n) { + var r = pl(e), + i = { lane: r, action: n, hasEagerState: !1, eagerState: null, next: null }; + if (cs(e)) ls(t, i); + else { + var a = e.alternate; + if (e.lanes === 0 && (a === null || a.lanes === 0) && ((a = t.lastRenderedReducer), a !== null)) + try { + var o = t.lastRenderedState, + s = a(o, n); + if (((i.hasEagerState = !0), (i.eagerState = s), Or(s, o))) { + var c = t.interleaved; + (c === null ? ((i.next = i), Ga(t)) : ((i.next = c.next), (c.next = i)), (t.interleaved = i)); + return; + } + } catch {} + ((n = Ka(e, t, i, r)), n !== null && ((i = fl()), ml(n, e, r, i), us(n, t, r))); + } + } + function cs(e) { + var t = e.alternate; + return e === bo || (t !== null && t === bo); + } + function ls(e, t) { + wo = Co = !0; + var n = e.pending; + (n === null ? (t.next = t) : ((t.next = n.next), (n.next = t)), (e.pending = t)); + } + function us(e, t, n) { + if (n & 4194240) { + var r = t.lanes; + ((r &= e.pendingLanes), (n |= r), (t.lanes = n), Ut(e, n)); + } + } + var ds = { + readContext: Ua, + useCallback: Do, + useContext: Do, + useEffect: Do, + useImperativeHandle: Do, + useInsertionEffect: Do, + useLayoutEffect: Do, + useMemo: Do, + useReducer: Do, + useRef: Do, + useState: Do, + useDebugValue: Do, + useDeferredValue: Do, + useTransition: Do, + useMutableSource: Do, + useSyncExternalStore: Do, + useId: Do, + unstable_isNewReconciler: !1, + }, + fs = { + readContext: Ua, + useCallback: function (e, t) { + return ((jo().memoizedState = [e, t === void 0 ? null : t]), e); + }, + useContext: Ua, + useEffect: Jo, + useImperativeHandle: function (e, t, n) { + return ((n = n == null ? null : n.concat([e])), Ko(4194308, 4, Qo.bind(null, t, e), n)); + }, + useLayoutEffect: function (e, t) { + return Ko(4194308, 4, e, t); + }, + useInsertionEffect: function (e, t) { + return Ko(4, 2, e, t); + }, + useMemo: function (e, t) { + var n = jo(); + return ((t = t === void 0 ? null : t), (e = e()), (n.memoizedState = [e, t]), e); + }, + useReducer: function (e, t, n) { + var r = jo(); + return ( + (t = n === void 0 ? t : n(t)), + (r.memoizedState = r.baseState = t), + (e = { + pending: null, + interleaved: null, + lanes: 0, + dispatch: null, + lastRenderedReducer: e, + lastRenderedState: t, + }), + (r.queue = e), + (e = e.dispatch = os.bind(null, bo, e)), + [r.memoizedState, e] + ); + }, + useRef: function (e) { + var t = jo(); + return ((e = { current: e }), (t.memoizedState = e)); + }, + useState: Uo, + useDebugValue: es, + useDeferredValue: function (e) { + return (jo().memoizedState = e); + }, + useTransition: function () { + var e = Uo(!1), + t = e[0]; + return ((e = is.bind(null, e[1])), (jo().memoizedState = e), [t, e]); + }, + useMutableSource: function () {}, + useSyncExternalStore: function (e, t, n) { + var i = bo, + a = jo(); + if (Z) { + if (n === void 0) throw Error(r(407)); + n = n(); + } else { + if (((n = t()), Vc === null)) throw Error(r(349)); + yo & 30 || Ro(i, t, n); + } + a.memoizedState = n; + var o = { value: n, getSnapshot: t }; + return ( + (a.queue = o), + Jo(Bo.bind(null, i, o, e), [e]), + (i.flags |= 2048), + Wo(9, zo.bind(null, i, o, n, t), void 0, null), + n + ); + }, + useId: function () { + var e = jo(), + t = Vc.identifierPrefix; + if (Z) { + var n = fa, + r = da; + ((n = (r & ~(1 << (32 - kt(r) - 1))).toString(32) + n), + (t = `:` + t + `R` + n), + (n = To++), + 0 < n && (t += `H` + n.toString(32)), + (t += `:`)); + } else ((n = Eo++), (t = `:` + t + `r` + n.toString(32) + `:`)); + return (e.memoizedState = t); + }, + unstable_isNewReconciler: !1, + }, + ps = { + readContext: Ua, + useCallback: ts, + useContext: Ua, + useEffect: Yo, + useImperativeHandle: $o, + useInsertionEffect: Xo, + useLayoutEffect: Zo, + useMemo: ns, + useReducer: Po, + useRef: Go, + useState: function () { + return Po(No); + }, + useDebugValue: es, + useDeferredValue: function (e) { + return rs(Mo(), xo.memoizedState, e); + }, + useTransition: function () { + return [Po(No)[0], Mo().memoizedState]; + }, + useMutableSource: Io, + useSyncExternalStore: Lo, + useId: as, + unstable_isNewReconciler: !1, + }, + ms = { + readContext: Ua, + useCallback: ts, + useContext: Ua, + useEffect: Yo, + useImperativeHandle: $o, + useInsertionEffect: Xo, + useLayoutEffect: Zo, + useMemo: ns, + useReducer: Fo, + useRef: Go, + useState: function () { + return Fo(No); + }, + useDebugValue: es, + useDeferredValue: function (e) { + var t = Mo(); + return xo === null ? (t.memoizedState = e) : rs(t, xo.memoizedState, e); + }, + useTransition: function () { + return [Fo(No)[0], Mo().memoizedState]; + }, + useMutableSource: Io, + useSyncExternalStore: Lo, + useId: as, + unstable_isNewReconciler: !1, + }; + function hs(e, t) { + if (e && e.defaultProps) { + for (var n in ((t = M({}, t)), (e = e.defaultProps), e)) t[n] === void 0 && (t[n] = e[n]); + return t; + } + return t; + } + function gs(e, t, n, r) { + ((t = e.memoizedState), + (n = n(r, t)), + (n = n == null ? t : M({}, t, n)), + (e.memoizedState = n), + e.lanes === 0 && (e.updateQueue.baseState = n)); + } + var _s = { + isMounted: function (e) { + return (e = e._reactInternals) ? lt(e) === e : !1; + }, + enqueueSetState: function (e, t, n) { + e = e._reactInternals; + var r = fl(), + i = pl(e), + a = Za(r, i); + ((a.payload = t), + n != null && (a.callback = n), + (t = Qa(e, a, i)), + t !== null && (ml(t, e, i, r), $a(t, e, i))); + }, + enqueueReplaceState: function (e, t, n) { + e = e._reactInternals; + var r = fl(), + i = pl(e), + a = Za(r, i); + ((a.tag = 1), + (a.payload = t), + n != null && (a.callback = n), + (t = Qa(e, a, i)), + t !== null && (ml(t, e, i, r), $a(t, e, i))); + }, + enqueueForceUpdate: function (e, t) { + e = e._reactInternals; + var n = fl(), + r = pl(e), + i = Za(n, r); + ((i.tag = 2), t != null && (i.callback = t), (t = Qa(e, i, r)), t !== null && (ml(t, e, r, n), $a(t, e, r))); + }, + }; + function vs(e, t, n, r, i, a, o) { + return ( + (e = e.stateNode), + typeof e.shouldComponentUpdate == `function` + ? e.shouldComponentUpdate(r, a, o) + : t.prototype && t.prototype.isPureReactComponent + ? !kr(n, r) || !kr(i, a) + : !0 + ); + } + function ys(e, t, n) { + var r = !1, + i = Vi, + a = t.contextType; + return ( + typeof a == `object` && a + ? (a = Ua(a)) + : ((i = Ki(t) ? Wi : Hi.current), (r = t.contextTypes), (a = (r = r != null) ? Gi(e, i) : Vi)), + (t = new t(n, a)), + (e.memoizedState = t.state !== null && t.state !== void 0 ? t.state : null), + (t.updater = _s), + (e.stateNode = t), + (t._reactInternals = e), + r && + ((e = e.stateNode), + (e.__reactInternalMemoizedUnmaskedChildContext = i), + (e.__reactInternalMemoizedMaskedChildContext = a)), + t + ); + } + function bs(e, t, n, r) { + ((e = t.state), + typeof t.componentWillReceiveProps == `function` && t.componentWillReceiveProps(n, r), + typeof t.UNSAFE_componentWillReceiveProps == `function` && t.UNSAFE_componentWillReceiveProps(n, r), + t.state !== e && _s.enqueueReplaceState(t, t.state, null)); + } + function xs(e, t, n, r) { + var i = e.stateNode; + ((i.props = n), (i.state = e.memoizedState), (i.refs = {}), Ya(e)); + var a = t.contextType; + (typeof a == `object` && a ? (i.context = Ua(a)) : ((a = Ki(t) ? Wi : Hi.current), (i.context = Gi(e, a))), + (i.state = e.memoizedState), + (a = t.getDerivedStateFromProps), + typeof a == `function` && (gs(e, t, a, n), (i.state = e.memoizedState)), + typeof t.getDerivedStateFromProps == `function` || + typeof i.getSnapshotBeforeUpdate == `function` || + (typeof i.UNSAFE_componentWillMount != `function` && typeof i.componentWillMount != `function`) || + ((t = i.state), + typeof i.componentWillMount == `function` && i.componentWillMount(), + typeof i.UNSAFE_componentWillMount == `function` && i.UNSAFE_componentWillMount(), + t !== i.state && _s.enqueueReplaceState(i, i.state, null), + to(e, n, i, r), + (i.state = e.memoizedState)), + typeof i.componentDidMount == `function` && (e.flags |= 4194308)); + } + function Ss(e, t) { + try { + var n = ``, + r = t; + do ((n += de(r)), (r = r.return)); + while (r); + var i = n; + } catch (e) { + i = + ` +Error generating stack: ` + + e.message + + ` +` + + e.stack; + } + return { value: e, source: t, stack: i, digest: null }; + } + function Cs(e, t, n) { + return { value: e, source: null, stack: n ?? null, digest: t ?? null }; + } + function ws(e, t) { + try { + console.error(t.value); + } catch (e) { + setTimeout(function () { + throw e; + }); + } + } + var Ts = typeof WeakMap == `function` ? WeakMap : Map; + function Es(e, t, n) { + ((n = Za(-1, n)), (n.tag = 3), (n.payload = { element: null })); + var r = t.value; + return ( + (n.callback = function () { + (nl || ((nl = !0), (rl = r)), ws(e, t)); + }), + n + ); + } + function Ds(e, t, n) { + ((n = Za(-1, n)), (n.tag = 3)); + var r = e.type.getDerivedStateFromError; + if (typeof r == `function`) { + var i = t.value; + ((n.payload = function () { + return r(i); + }), + (n.callback = function () { + ws(e, t); + })); + } + var a = e.stateNode; + return ( + a !== null && + typeof a.componentDidCatch == `function` && + (n.callback = function () { + (ws(e, t), typeof r != `function` && (il === null ? (il = new Set([this])) : il.add(this))); + var n = t.stack; + this.componentDidCatch(t.value, { componentStack: n === null ? `` : n }); + }), + n + ); + } + function Os(e, t, n) { + var r = e.pingCache; + if (r === null) { + r = e.pingCache = new Ts(); + var i = new Set(); + r.set(t, i); + } else ((i = r.get(t)), i === void 0 && ((i = new Set()), r.set(t, i))); + i.has(n) || (i.add(n), (e = zl.bind(null, e, t, n)), t.then(e, e)); + } + function ks(e) { + do { + var t; + if (((t = e.tag === 13) && ((t = e.memoizedState), (t = t === null ? !0 : t.dehydrated !== null)), t)) return e; + e = e.return; + } while (e !== null); + return null; + } + function As(e, t, n, r, i) { + return e.mode & 1 + ? ((e.flags |= 65536), (e.lanes = i), e) + : (e === t + ? (e.flags |= 65536) + : ((e.flags |= 128), + (n.flags |= 131072), + (n.flags &= -52805), + n.tag === 1 && (n.alternate === null ? (n.tag = 17) : ((t = Za(-1, 1)), (t.tag = 2), Qa(n, t, 1))), + (n.lanes |= 1)), + e); + } + var js = C.ReactCurrentOwner, + Ms = !1; + function Ns(e, t, n, r) { + t.child = e === null ? Pa(t, null, n, r) : Na(t, e.child, n, r); + } + function Ps(e, t, n, r, i) { + n = n.render; + var a = t.ref; + return ( + Ha(t, i), + (r = ko(e, t, n, r, a, i)), + (n = Ao()), + e !== null && !Ms + ? ((t.updateQueue = e.updateQueue), (t.flags &= -2053), (e.lanes &= ~i), ec(e, t, i)) + : (Z && n && ma(t), (t.flags |= 1), Ns(e, t, r, i), t.child) + ); + } + function Fs(e, t, n, r, i) { + if (e === null) { + var a = n.type; + return typeof a == `function` && + !ql(a) && + a.defaultProps === void 0 && + n.compare === null && + n.defaultProps === void 0 + ? ((t.tag = 15), (t.type = a), Is(e, t, a, r, i)) + : ((e = Xl(n.type, null, r, t, t.mode, i)), (e.ref = t.ref), (e.return = t), (t.child = e)); + } + if (((a = e.child), (e.lanes & i) === 0)) { + var o = a.memoizedProps; + if (((n = n.compare), (n = n === null ? kr : n), n(o, r) && e.ref === t.ref)) return ec(e, t, i); + } + return ((t.flags |= 1), (e = Yl(a, r)), (e.ref = t.ref), (e.return = t), (t.child = e)); + } + function Is(e, t, n, r, i) { + if (e !== null) { + var a = e.memoizedProps; + if (kr(a, r) && e.ref === t.ref) + if (((Ms = !1), (t.pendingProps = r = a), (e.lanes & i) !== 0)) e.flags & 131072 && (Ms = !0); + else return ((t.lanes = e.lanes), ec(e, t, i)); + } + return zs(e, t, n, r, i); + } + function Ls(e, t, n) { + var r = t.pendingProps, + i = r.children, + a = e === null ? null : e.memoizedState; + if (r.mode === `hidden`) + if (!(t.mode & 1)) + ((t.memoizedState = { baseLanes: 0, cachePool: null, transitions: null }), Y(Gc, Wc), (Wc |= n)); + else { + if (!(n & 1073741824)) + return ( + (e = a === null ? n : a.baseLanes | n), + (t.lanes = t.childLanes = 1073741824), + (t.memoizedState = { baseLanes: e, cachePool: null, transitions: null }), + (t.updateQueue = null), + Y(Gc, Wc), + (Wc |= e), + null + ); + ((t.memoizedState = { baseLanes: 0, cachePool: null, transitions: null }), + (r = a === null ? n : a.baseLanes), + Y(Gc, Wc), + (Wc |= r)); + } + else (a === null ? (r = n) : ((r = a.baseLanes | n), (t.memoizedState = null)), Y(Gc, Wc), (Wc |= r)); + return (Ns(e, t, i, n), t.child); + } + function Rs(e, t) { + var n = t.ref; + ((e === null && n !== null) || (e !== null && e.ref !== n)) && ((t.flags |= 512), (t.flags |= 2097152)); + } + function zs(e, t, n, r, i) { + var a = Ki(n) ? Wi : Hi.current; + return ( + (a = Gi(t, a)), + Ha(t, i), + (n = ko(e, t, n, r, a, i)), + (r = Ao()), + e !== null && !Ms + ? ((t.updateQueue = e.updateQueue), (t.flags &= -2053), (e.lanes &= ~i), ec(e, t, i)) + : (Z && r && ma(t), (t.flags |= 1), Ns(e, t, n, i), t.child) + ); + } + function Bs(e, t, n, r, i) { + if (Ki(n)) { + var a = !0; + Xi(t); + } else a = !1; + if ((Ha(t, i), t.stateNode === null)) ($s(e, t), ys(t, n, r), xs(t, n, r, i), (r = !0)); + else if (e === null) { + var o = t.stateNode, + s = t.memoizedProps; + o.props = s; + var c = o.context, + l = n.contextType; + typeof l == `object` && l ? (l = Ua(l)) : ((l = Ki(n) ? Wi : Hi.current), (l = Gi(t, l))); + var u = n.getDerivedStateFromProps, + d = typeof u == `function` || typeof o.getSnapshotBeforeUpdate == `function`; + (d || + (typeof o.UNSAFE_componentWillReceiveProps != `function` && + typeof o.componentWillReceiveProps != `function`) || + ((s !== r || c !== l) && bs(t, o, r, l)), + (Ja = !1)); + var f = t.memoizedState; + ((o.state = f), + to(t, r, o, i), + (c = t.memoizedState), + s !== r || f !== c || Ui.current || Ja + ? (typeof u == `function` && (gs(t, n, u, r), (c = t.memoizedState)), + (s = Ja || vs(t, n, s, r, f, c, l)) + ? (d || + (typeof o.UNSAFE_componentWillMount != `function` && typeof o.componentWillMount != `function`) || + (typeof o.componentWillMount == `function` && o.componentWillMount(), + typeof o.UNSAFE_componentWillMount == `function` && o.UNSAFE_componentWillMount()), + typeof o.componentDidMount == `function` && (t.flags |= 4194308)) + : (typeof o.componentDidMount == `function` && (t.flags |= 4194308), + (t.memoizedProps = r), + (t.memoizedState = c)), + (o.props = r), + (o.state = c), + (o.context = l), + (r = s)) + : (typeof o.componentDidMount == `function` && (t.flags |= 4194308), (r = !1))); + } else { + ((o = t.stateNode), + Xa(e, t), + (s = t.memoizedProps), + (l = t.type === t.elementType ? s : hs(t.type, s)), + (o.props = l), + (d = t.pendingProps), + (f = o.context), + (c = n.contextType), + typeof c == `object` && c ? (c = Ua(c)) : ((c = Ki(n) ? Wi : Hi.current), (c = Gi(t, c)))); + var p = n.getDerivedStateFromProps; + ((u = typeof p == `function` || typeof o.getSnapshotBeforeUpdate == `function`) || + (typeof o.UNSAFE_componentWillReceiveProps != `function` && + typeof o.componentWillReceiveProps != `function`) || + ((s !== d || f !== c) && bs(t, o, r, c)), + (Ja = !1), + (f = t.memoizedState), + (o.state = f), + to(t, r, o, i)); + var m = t.memoizedState; + s !== d || f !== m || Ui.current || Ja + ? (typeof p == `function` && (gs(t, n, p, r), (m = t.memoizedState)), + (l = Ja || vs(t, n, l, r, f, m, c) || !1) + ? (u || + (typeof o.UNSAFE_componentWillUpdate != `function` && typeof o.componentWillUpdate != `function`) || + (typeof o.componentWillUpdate == `function` && o.componentWillUpdate(r, m, c), + typeof o.UNSAFE_componentWillUpdate == `function` && o.UNSAFE_componentWillUpdate(r, m, c)), + typeof o.componentDidUpdate == `function` && (t.flags |= 4), + typeof o.getSnapshotBeforeUpdate == `function` && (t.flags |= 1024)) + : (typeof o.componentDidUpdate != `function` || + (s === e.memoizedProps && f === e.memoizedState) || + (t.flags |= 4), + typeof o.getSnapshotBeforeUpdate != `function` || + (s === e.memoizedProps && f === e.memoizedState) || + (t.flags |= 1024), + (t.memoizedProps = r), + (t.memoizedState = m)), + (o.props = r), + (o.state = m), + (o.context = c), + (r = l)) + : (typeof o.componentDidUpdate != `function` || + (s === e.memoizedProps && f === e.memoizedState) || + (t.flags |= 4), + typeof o.getSnapshotBeforeUpdate != `function` || + (s === e.memoizedProps && f === e.memoizedState) || + (t.flags |= 1024), + (r = !1)); + } + return Vs(e, t, n, r, a, i); + } + function Vs(e, t, n, r, i, a) { + Rs(e, t); + var o = (t.flags & 128) != 0; + if (!r && !o) return (i && Zi(t, n, !1), ec(e, t, a)); + ((r = t.stateNode), (js.current = t)); + var s = o && typeof n.getDerivedStateFromError != `function` ? null : r.render(); + return ( + (t.flags |= 1), + e !== null && o ? ((t.child = Na(t, e.child, null, a)), (t.child = Na(t, null, s, a))) : Ns(e, t, s, a), + (t.memoizedState = r.state), + i && Zi(t, n, !0), + t.child + ); + } + function Hs(e) { + var t = e.stateNode; + (t.pendingContext ? Ji(e, t.pendingContext, t.pendingContext !== t.context) : t.context && Ji(e, t.context, !1), + co(e, t.containerInfo)); + } + function Us(e, t, n, r, i) { + return (Ea(), Da(i), (t.flags |= 256), Ns(e, t, n, r), t.child); + } + var Ws = { dehydrated: null, treeContext: null, retryLane: 0 }; + function Gs(e) { + return { baseLanes: e, cachePool: null, transitions: null }; + } + function Ks(e, t, n) { + var r = t.pendingProps, + i = po.current, + a = !1, + o = (t.flags & 128) != 0, + s; + if ( + ((s = o) || (s = e !== null && e.memoizedState === null ? !1 : (i & 2) != 0), + s ? ((a = !0), (t.flags &= -129)) : (e === null || e.memoizedState !== null) && (i |= 1), + Y(po, i & 1), + e === null) + ) + return ( + Sa(t), + (e = t.memoizedState), + e !== null && ((e = e.dehydrated), e !== null) + ? (t.mode & 1 ? (e.data === `$!` ? (t.lanes = 8) : (t.lanes = 1073741824)) : (t.lanes = 1), null) + : ((o = r.children), + (e = r.fallback), + a + ? ((r = t.mode), + (a = t.child), + (o = { mode: `hidden`, children: o }), + !(r & 1) && a !== null ? ((a.childLanes = 0), (a.pendingProps = o)) : (a = Ql(o, r, 0, null)), + (e = Zl(e, r, n, null)), + (a.return = t), + (e.return = t), + (a.sibling = e), + (t.child = a), + (t.child.memoizedState = Gs(n)), + (t.memoizedState = Ws), + e) + : qs(t, o)) + ); + if (((i = e.memoizedState), i !== null && ((s = i.dehydrated), s !== null))) return Ys(e, t, o, r, s, i, n); + if (a) { + ((a = r.fallback), (o = t.mode), (i = e.child), (s = i.sibling)); + var c = { mode: `hidden`, children: r.children }; + return ( + !(o & 1) && t.child !== i + ? ((r = t.child), (r.childLanes = 0), (r.pendingProps = c), (t.deletions = null)) + : ((r = Yl(i, c)), (r.subtreeFlags = i.subtreeFlags & 14680064)), + s === null ? ((a = Zl(a, o, n, null)), (a.flags |= 2)) : (a = Yl(s, a)), + (a.return = t), + (r.return = t), + (r.sibling = a), + (t.child = r), + (r = a), + (a = t.child), + (o = e.child.memoizedState), + (o = o === null ? Gs(n) : { baseLanes: o.baseLanes | n, cachePool: null, transitions: o.transitions }), + (a.memoizedState = o), + (a.childLanes = e.childLanes & ~n), + (t.memoizedState = Ws), + r + ); + } + return ( + (a = e.child), + (e = a.sibling), + (r = Yl(a, { mode: `visible`, children: r.children })), + !(t.mode & 1) && (r.lanes = n), + (r.return = t), + (r.sibling = null), + e !== null && ((n = t.deletions), n === null ? ((t.deletions = [e]), (t.flags |= 16)) : n.push(e)), + (t.child = r), + (t.memoizedState = null), + r + ); + } + function qs(e, t) { + return ((t = Ql({ mode: `visible`, children: t }, e.mode, 0, null)), (t.return = e), (e.child = t)); + } + function Js(e, t, n, r) { + return ( + r !== null && Da(r), + Na(t, e.child, null, n), + (e = qs(t, t.pendingProps.children)), + (e.flags |= 2), + (t.memoizedState = null), + e + ); + } + function Ys(e, t, n, i, a, o, s) { + if (n) + return t.flags & 256 + ? ((t.flags &= -257), (i = Cs(Error(r(422)))), Js(e, t, s, i)) + : t.memoizedState === null + ? ((o = i.fallback), + (a = t.mode), + (i = Ql({ mode: `visible`, children: i.children }, a, 0, null)), + (o = Zl(o, a, s, null)), + (o.flags |= 2), + (i.return = t), + (o.return = t), + (i.sibling = o), + (t.child = i), + t.mode & 1 && Na(t, e.child, null, s), + (t.child.memoizedState = Gs(s)), + (t.memoizedState = Ws), + o) + : ((t.child = e.child), (t.flags |= 128), null); + if (!(t.mode & 1)) return Js(e, t, s, null); + if (a.data === `$!`) { + if (((i = a.nextSibling && a.nextSibling.dataset), i)) var c = i.dgst; + return ((i = c), (o = Error(r(419))), (i = Cs(o, i, void 0)), Js(e, t, s, i)); + } + if (((c = (s & e.childLanes) !== 0), Ms || c)) { + if (((i = Vc), i !== null)) { + switch (s & -s) { + case 4: + a = 2; + break; + case 16: + a = 8; + break; + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + case 262144: + case 524288: + case 1048576: + case 2097152: + case 4194304: + case 8388608: + case 16777216: + case 33554432: + case 67108864: + a = 32; + break; + case 536870912: + a = 268435456; + break; + default: + a = 0; + } + ((a = (a & (i.suspendedLanes | s)) === 0 ? a : 0), + a !== 0 && a !== o.retryLane && ((o.retryLane = a), qa(e, a), ml(i, e, a, -1))); + } + return (Ol(), (i = Cs(Error(r(421)))), Js(e, t, s, i)); + } + return a.data === `$?` + ? ((t.flags |= 128), (t.child = e.child), (t = Vl.bind(null, e)), (a._reactRetry = t), null) + : ((e = o.treeContext), + (_a = Ti(a.nextSibling)), + (ga = t), + (Z = !0), + (va = null), + e !== null && ((ca[la++] = da), (ca[la++] = fa), (ca[la++] = ua), (da = e.id), (fa = e.overflow), (ua = t)), + (t = qs(t, i.children)), + (t.flags |= 4096), + t); + } + function Xs(e, t, n) { + e.lanes |= t; + var r = e.alternate; + (r !== null && (r.lanes |= t), Va(e.return, t, n)); + } + function Zs(e, t, n, r, i) { + var a = e.memoizedState; + a === null + ? (e.memoizedState = { isBackwards: t, rendering: null, renderingStartTime: 0, last: r, tail: n, tailMode: i }) + : ((a.isBackwards = t), + (a.rendering = null), + (a.renderingStartTime = 0), + (a.last = r), + (a.tail = n), + (a.tailMode = i)); + } + function Qs(e, t, n) { + var r = t.pendingProps, + i = r.revealOrder, + a = r.tail; + if ((Ns(e, t, r.children, n), (r = po.current), r & 2)) ((r = (r & 1) | 2), (t.flags |= 128)); + else { + if (e !== null && e.flags & 128) + a: for (e = t.child; e !== null; ) { + if (e.tag === 13) e.memoizedState !== null && Xs(e, n, t); + else if (e.tag === 19) Xs(e, n, t); + else if (e.child !== null) { + ((e.child.return = e), (e = e.child)); + continue; + } + if (e === t) break a; + for (; e.sibling === null; ) { + if (e.return === null || e.return === t) break a; + e = e.return; + } + ((e.sibling.return = e.return), (e = e.sibling)); + } + r &= 1; + } + if ((Y(po, r), !(t.mode & 1))) t.memoizedState = null; + else + switch (i) { + case `forwards`: + for (n = t.child, i = null; n !== null; ) + ((e = n.alternate), e !== null && mo(e) === null && (i = n), (n = n.sibling)); + ((n = i), + n === null ? ((i = t.child), (t.child = null)) : ((i = n.sibling), (n.sibling = null)), + Zs(t, !1, i, n, a)); + break; + case `backwards`: + for (n = null, i = t.child, t.child = null; i !== null; ) { + if (((e = i.alternate), e !== null && mo(e) === null)) { + t.child = i; + break; + } + ((e = i.sibling), (i.sibling = n), (n = i), (i = e)); + } + Zs(t, !0, n, null, a); + break; + case `together`: + Zs(t, !1, null, null, void 0); + break; + default: + t.memoizedState = null; + } + return t.child; + } + function $s(e, t) { + !(t.mode & 1) && e !== null && ((e.alternate = null), (t.alternate = null), (t.flags |= 2)); + } + function ec(e, t, n) { + if ((e !== null && (t.dependencies = e.dependencies), (Jc |= t.lanes), (n & t.childLanes) === 0)) return null; + if (e !== null && t.child !== e.child) throw Error(r(153)); + if (t.child !== null) { + for (e = t.child, n = Yl(e, e.pendingProps), t.child = n, n.return = t; e.sibling !== null; ) + ((e = e.sibling), (n = n.sibling = Yl(e, e.pendingProps)), (n.return = t)); + n.sibling = null; + } + return t.child; + } + function tc(e, t, n) { + switch (t.tag) { + case 3: + (Hs(t), Ea()); + break; + case 5: + uo(t); + break; + case 1: + Ki(t.type) && Xi(t); + break; + case 4: + co(t, t.stateNode.containerInfo); + break; + case 10: + var r = t.type._context, + i = t.memoizedProps.value; + (Y(Fa, r._currentValue), (r._currentValue = i)); + break; + case 13: + if (((r = t.memoizedState), r !== null)) + return r.dehydrated === null + ? (n & t.child.childLanes) === 0 + ? (Y(po, po.current & 1), (e = ec(e, t, n)), e === null ? null : e.sibling) + : Ks(e, t, n) + : (Y(po, po.current & 1), (t.flags |= 128), null); + Y(po, po.current & 1); + break; + case 19: + if (((r = (n & t.childLanes) !== 0), e.flags & 128)) { + if (r) return Qs(e, t, n); + t.flags |= 128; + } + if ( + ((i = t.memoizedState), + i !== null && ((i.rendering = null), (i.tail = null), (i.lastEffect = null)), + Y(po, po.current), + r) + ) + break; + return null; + case 22: + case 23: + return ((t.lanes = 0), Ls(e, t, n)); + } + return ec(e, t, n); + } + var nc = function (e, t) { + for (var n = t.child; n !== null; ) { + if (n.tag === 5 || n.tag === 6) e.appendChild(n.stateNode); + else if (n.tag !== 4 && n.child !== null) { + ((n.child.return = n), (n = n.child)); + continue; + } + if (n === t) break; + for (; n.sibling === null; ) { + if (n.return === null || n.return === t) return; + n = n.return; + } + ((n.sibling.return = n.return), (n = n.sibling)); + } + }, + rc = function (e, t, n, r) { + var i = e.memoizedProps; + if (i !== r) { + ((e = t.stateNode), so(io.current)); + var o = null; + switch (n) { + case `input`: + ((i = ye(e, i)), (r = ye(e, r)), (o = [])); + break; + case `select`: + ((i = M({}, i, { value: void 0 })), (r = M({}, r, { value: void 0 })), (o = [])); + break; + case `textarea`: + ((i = Te(e, i)), (r = Te(e, r)), (o = [])); + break; + default: + typeof i.onClick != `function` && typeof r.onClick == `function` && (e.onclick = hi); + } + ze(n, r); + var s; + for (u in ((n = null), i)) + if (!r.hasOwnProperty(u) && i.hasOwnProperty(u) && i[u] != null) + if (u === `style`) { + var c = i[u]; + for (s in c) c.hasOwnProperty(s) && ((n ||= {}), (n[s] = ``)); + } else + u !== `dangerouslySetInnerHTML` && + u !== `children` && + u !== `suppressContentEditableWarning` && + u !== `suppressHydrationWarning` && + u !== `autoFocus` && + (a.hasOwnProperty(u) ? (o ||= []) : (o ||= []).push(u, null)); + for (u in r) { + var l = r[u]; + if (((c = i?.[u]), r.hasOwnProperty(u) && l !== c && (l != null || c != null))) + if (u === `style`) + if (c) { + for (s in c) !c.hasOwnProperty(s) || (l && l.hasOwnProperty(s)) || ((n ||= {}), (n[s] = ``)); + for (s in l) l.hasOwnProperty(s) && c[s] !== l[s] && ((n ||= {}), (n[s] = l[s])); + } else (n || ((o ||= []), o.push(u, n)), (n = l)); + else + u === `dangerouslySetInnerHTML` + ? ((l = l ? l.__html : void 0), + (c = c ? c.__html : void 0), + l != null && c !== l && (o ||= []).push(u, l)) + : u === `children` + ? (typeof l != `string` && typeof l != `number`) || (o ||= []).push(u, `` + l) + : u !== `suppressContentEditableWarning` && + u !== `suppressHydrationWarning` && + (a.hasOwnProperty(u) + ? (l != null && u === `onScroll` && G(`scroll`, e), o || c === l || (o = [])) + : (o ||= []).push(u, l)); + } + n && (o ||= []).push(`style`, n); + var u = o; + (t.updateQueue = u) && (t.flags |= 4); + } + }, + ic = function (e, t, n, r) { + n !== r && (t.flags |= 4); + }; + function ac(e, t) { + if (!Z) + switch (e.tailMode) { + case `hidden`: + t = e.tail; + for (var n = null; t !== null; ) (t.alternate !== null && (n = t), (t = t.sibling)); + n === null ? (e.tail = null) : (n.sibling = null); + break; + case `collapsed`: + n = e.tail; + for (var r = null; n !== null; ) (n.alternate !== null && (r = n), (n = n.sibling)); + r === null ? (t || e.tail === null ? (e.tail = null) : (e.tail.sibling = null)) : (r.sibling = null); + } + } + function oc(e) { + var t = e.alternate !== null && e.alternate.child === e.child, + n = 0, + r = 0; + if (t) + for (var i = e.child; i !== null; ) + ((n |= i.lanes | i.childLanes), + (r |= i.subtreeFlags & 14680064), + (r |= i.flags & 14680064), + (i.return = e), + (i = i.sibling)); + else + for (i = e.child; i !== null; ) + ((n |= i.lanes | i.childLanes), (r |= i.subtreeFlags), (r |= i.flags), (i.return = e), (i = i.sibling)); + return ((e.subtreeFlags |= r), (e.childLanes = n), t); + } + function sc(e, t, n) { + var i = t.pendingProps; + switch ((ha(t), t.tag)) { + case 2: + case 16: + case 15: + case 0: + case 11: + case 7: + case 8: + case 12: + case 9: + case 14: + return (oc(t), null); + case 1: + return (Ki(t.type) && qi(), oc(t), null); + case 3: + return ( + (i = t.stateNode), + lo(), + J(Ui), + J(Hi), + go(), + i.pendingContext && ((i.context = i.pendingContext), (i.pendingContext = null)), + (e === null || e.child === null) && + (wa(t) + ? (t.flags |= 4) + : e === null || + (e.memoizedState.isDehydrated && !(t.flags & 256)) || + ((t.flags |= 1024), va !== null && (vl(va), (va = null)))), + oc(t), + null + ); + case 5: + fo(t); + var o = so(oo.current); + if (((n = t.type), e !== null && t.stateNode != null)) + (rc(e, t, n, i, o), e.ref !== t.ref && ((t.flags |= 512), (t.flags |= 2097152))); + else { + if (!i) { + if (t.stateNode === null) throw Error(r(166)); + return (oc(t), null); + } + if (((e = so(io.current)), wa(t))) { + ((i = t.stateNode), (n = t.type)); + var s = t.memoizedProps; + switch (((i[Oi] = t), (i[ki] = s), (e = (t.mode & 1) != 0), n)) { + case `dialog`: + (G(`cancel`, i), G(`close`, i)); + break; + case `iframe`: + case `object`: + case `embed`: + G(`load`, i); + break; + case `video`: + case `audio`: + for (o = 0; o < ei.length; o++) G(ei[o], i); + break; + case `source`: + G(`error`, i); + break; + case `img`: + case `image`: + case `link`: + (G(`error`, i), G(`load`, i)); + break; + case `details`: + G(`toggle`, i); + break; + case `input`: + (P(i, s), G(`invalid`, i)); + break; + case `select`: + ((i._wrapperState = { wasMultiple: !!s.multiple }), G(`invalid`, i)); + break; + case `textarea`: + (Ee(i, s), G(`invalid`, i)); + } + for (var c in (ze(n, s), (o = null), s)) + if (s.hasOwnProperty(c)) { + var l = s[c]; + c === `children` + ? typeof l == `string` + ? i.textContent !== l && + (!0 !== s.suppressHydrationWarning && mi(i.textContent, l, e), (o = [`children`, l])) + : typeof l == `number` && + i.textContent !== `` + l && + (!0 !== s.suppressHydrationWarning && mi(i.textContent, l, e), (o = [`children`, `` + l])) + : a.hasOwnProperty(c) && l != null && c === `onScroll` && G(`scroll`, i); + } + switch (n) { + case `input`: + (ge(i), Se(i, s, !0)); + break; + case `textarea`: + (ge(i), Oe(i)); + break; + case `select`: + case `option`: + break; + default: + typeof s.onClick == `function` && (i.onclick = hi); + } + ((i = o), (t.updateQueue = i), i !== null && (t.flags |= 4)); + } else { + ((c = o.nodeType === 9 ? o : o.ownerDocument), + e === `http://www.w3.org/1999/xhtml` && (e = ke(n)), + e === `http://www.w3.org/1999/xhtml` + ? n === `script` + ? ((e = c.createElement(`div`)), + (e.innerHTML = ` - - - - -
- - + + + + + + + + + + + + + + PaperParty + + + + + +
+ + diff --git a/pro/index.html b/pro/index.html index 81c6b4e..abf3e9e 100644 --- a/pro/index.html +++ b/pro/index.html @@ -1,19 +1,19 @@ - + - + - - - + + + PaperParty diff --git a/pro/package-lock.json b/pro/package-lock.json index 1e1be5b..be15b3d 100644 --- a/pro/package-lock.json +++ b/pro/package-lock.json @@ -13,10 +13,10 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.30.3", + "react-zoom-pan-pinch": "^4.0.3", "socket.io-client": "^4.8.3", "sweetalert2": "^11.26.24", - "use-sound": "^5.0.0", - "web-vitals": "^2.1.4" + "use-sound": "^5.0.0" }, "devDependencies": { "@tailwindcss/vite": "^4.3.0", @@ -2305,6 +2305,20 @@ "react-dom": ">=16.8" } }, + "node_modules/react-zoom-pan-pinch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-4.0.3.tgz", + "integrity": "sha512-N2Hi6L78fFmhRra+ORpFSW7WST5x6kxpOPplIvtB0b7b+U2anpo1z1wLgaWRPS2kUSqcraRG+JgBCIlDJnqqAg==", + "license": "MIT", + "engines": { + "node": ">=8", + "npm": ">=5" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -2835,11 +2849,6 @@ "node": ">=18" } }, - "node_modules/web-vitals": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.4.tgz", - "integrity": "sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==" - }, "node_modules/webidl-conversions": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", diff --git a/pro/package.json b/pro/package.json index 601dd7c..6e63479 100644 --- a/pro/package.json +++ b/pro/package.json @@ -8,10 +8,10 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.30.3", + "react-zoom-pan-pinch": "^4.0.3", "socket.io-client": "^4.8.3", "sweetalert2": "^11.26.24", - "use-sound": "^5.0.0", - "web-vitals": "^2.1.4" + "use-sound": "^5.0.0" }, "scripts": { "dev": "vite", @@ -19,12 +19,6 @@ "preview": "vite preview", "test": "vitest" }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, "browserslist": { "production": [ ">0.2%", diff --git a/pro/src/bingo/Bingo.css b/pro/src/bingo/Bingo.css deleted file mode 100644 index 91460fa..0000000 --- a/pro/src/bingo/Bingo.css +++ /dev/null @@ -1,19 +0,0 @@ -/* Bingo.css */ -.bingo { - text-align: center; -} - -.bingo-grid { - display: grid; - grid-template-columns: repeat(5, 1fr); - grid-gap: 5px; -} - -.bingo-cell { - display: flex; - justify-content: center; - align-items: center; - width: 50px; - height: 50px; - border: 1px solid #ccc; -} \ No newline at end of file diff --git a/pro/src/bingo/Bingo.jsx b/pro/src/bingo/Bingo.jsx index d62d43e..ad5cc9f 100644 --- a/pro/src/bingo/Bingo.jsx +++ b/pro/src/bingo/Bingo.jsx @@ -1,26 +1,28 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useState, useEffect, useCallback, useRef } from 'react'; import { useGameContext } from '../context/GameContext'; -import RetroButton from '../components/ui/RetroButton'; +import { SketchButton, SketchCard, sketchPopupClass, GameLayout } from '../components/ui'; import useSound from 'use-sound'; import confetti from 'canvas-confetti'; import Swal from 'sweetalert2'; import { useNavigate } from 'react-router-dom'; -import { ArrowLeft, Users, Trophy, SwatchBook, Timer } from 'lucide-react'; +import { Users, Trophy, SwatchBook, Timer } from 'lucide-react'; +import logger from '../utils/logger'; + +const PLAYER_COLORS = ['#2a2a3e', '#c73e1d', '#2d4a8f', '#2f5233']; const Bingo = () => { - const { socket, playerName, roomId, setRoomId } = useGameContext(); - const [numbers, setNumbers] = useState(() => { - const nums = Array.from({ length: 25 }, (_, i) => i + 1); - return nums.sort(() => Math.random() - 0.5); - }); + const { socket, playerName, roomId, setRoomId, clearRoomId } = useGameContext(); + const [numbers, setNumbers] = useState(Array.from({ length: 25 }, (_, i) => i + 1)); const [players, setPlayers] = useState([]); const [gameState, setGameState] = useState('waiting'); const [currentTurn, setCurrentTurn] = useState(null); const [isCreator, setIsCreator] = useState(false); const [strikedOut, setStrikedOut] = useState(''); const [turnTimer, setTurnTimer] = useState(30); + const [, setMyPlayerIndex] = useState(-1); const navigate = useNavigate(); + const strikedNumbersRef = useRef([]); const [playPop] = useSound('/sounds/pop.mp3', { volume: 0.5 }); const [playWin] = useSound('/sounds/win.mp3', { volume: 0.7 }); const [playTurn] = useSound('/sounds/turn.mp3', { volume: 0.6 }); @@ -29,57 +31,143 @@ const Bingo = () => { let timerInterval; if (gameState === 'playing' && currentTurn === socket?.id && turnTimer > 0) { timerInterval = setInterval(() => { - setTurnTimer(prev => prev - 1); + setTurnTimer((prev) => prev - 1); }, 1000); } return () => clearInterval(timerInterval); }, [gameState, currentTurn, socket?.id, turnTimer]); + const generateBoard = useCallback(() => { + const nums = Array.from({ length: 25 }, (_, i) => i + 1); + for (let i = nums.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [nums[i], nums[j]] = [nums[j], nums[i]]; + } + return nums; + }, []); + + const calculateBingoProgress = useCallback((boardNumbers) => { + const size = 5; + const lines = []; + for (let i = 0; i < size; i++) { + lines.push(Array.from({ length: size }, (_, j) => i * size + j)); + } + for (let i = 0; i < size; i++) { + lines.push(Array.from({ length: size }, (_, j) => i + j * size)); + } + lines.push(Array.from({ length: size }, (_, i) => i * size + i)); + lines.push(Array.from({ length: size }, (_, i) => (i + 1) * size - (i + 1))); + + const completedLinesCount = lines.filter((line) => + line.every((idx) => typeof boardNumbers[idx] === 'string'), + ).length; + + return 'BINGO'.slice(0, Math.min(completedLinesCount, 5)); + }, []); + useEffect(() => { if (!socket) return; - socket.on('bingo_roomInfo', ({ id, creator, players, gameState, currentTurn }) => { + const saved = sessionStorage.getItem('bingo_reconnect'); + if (saved && !roomId) { + const { roomId: savedRoomId, playerId } = JSON.parse(saved); + logger.socket('➡️', 'bingo_reconnect', { roomId: savedRoomId, playerId }); + socket.emit('bingo_reconnect', { roomId: savedRoomId, playerId }); + setRoomId(savedRoomId); + } + + socket.on('bingo_roomInfo', ({ id, creator, players, gameState, currentTurn, strikedNumbers }) => { + logger.socket('⬅️', 'bingo_roomInfo', { roomId: id, gameState }); setRoomId(id); setPlayers(players); setGameState(gameState); setCurrentTurn(currentTurn); setIsCreator(creator === socket.id); + + const playerIndex = players.findIndex((p) => p.id === socket.id); + setMyPlayerIndex(playerIndex); + + if (gameState === 'playing' && players.length > 0) { + const me = players.find((p) => p.id === socket.id); + if (me) sessionStorage.setItem('bingo_reconnect', JSON.stringify({ roomId: id, playerId: me.id })); + } + + if (strikedNumbers) { + strikedNumbersRef.current = strikedNumbers; + } + }); + + socket.on('bingo_playerBoard', ({ board }) => { + logger.socket('⬅️', 'bingo_playerBoard', 'Received board from server'); + const savedBoard = localStorage.getItem(`bingo_board_${roomId}`); + const rawBoard = savedBoard ? JSON.parse(savedBoard) : board; + const sn = strikedNumbersRef.current; + const updatedBoard = sn.length > 0 ? rawBoard.map((n) => (sn.includes(n) ? 'X' : n)) : rawBoard; + setNumbers(updatedBoard); + if (!savedBoard) { + localStorage.setItem(`bingo_board_${roomId}`, JSON.stringify(board)); + } + }); + + socket.on('bingo_gamePaused', ({ reason }) => { + logger.socket('⬅️', 'bingo_gamePaused', { reason }); + Swal.fire({ + title: 'Game Paused', + text: reason, + icon: 'warning', + customClass: { popup: sketchPopupClass }, + }); }); - socket.on('bingo_gameStarted', (firstPlayerId) => { + socket.on('bingo_gameStarted', ({ firstPlayerId, playerBoards }) => { + logger.socket('⬅️', 'bingo_gameStarted', { firstPlayerId }); setGameState('playing'); setCurrentTurn(firstPlayerId); setTurnTimer(30); + setStrikedOut(''); + + const myBoard = playerBoards?.[socket.id]; + if (myBoard) { + setNumbers(myBoard); + localStorage.setItem(`bingo_board_${roomId}`, JSON.stringify(myBoard)); + } + Swal.fire({ title: 'Eyes Down!', text: 'Bingo has started!', timer: 1500, showConfirmButton: false, - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); }); socket.on('bingo_gameRestarted', () => { - setNumbers(Array.from({ length: 25 }, (_, i) => i + 1).sort(() => Math.random() - 0.5)); - setStrikedOut(''); setGameState('ready'); + setStrikedOut(''); + setNumbers((prev) => { + const fresh = prev.map((n) => (typeof n === 'number' ? n : n)); + localStorage.setItem(`bingo_board_${roomId}`, JSON.stringify(fresh)); + return fresh; + }); Swal.fire({ title: 'Game Restarted', - text: 'New card generated!', + text: 'Get ready for a new round!', timer: 1500, showConfirmButton: false, - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); }); - socket.on('bingo_numberMarked', ({ number, playerId }) => { - setNumbers(prev => prev.map(n => n === number ? 'X' : n)); + socket.on('bingo_numberMarked', ({ number: _number, nextTurn, strikedNumbers }) => { + setNumbers((prev) => prev.map((n) => (strikedNumbers.includes(n) ? 'X' : typeof n === 'string' ? n : n))); + setCurrentTurn(nextTurn); playPop(); }); - socket.on('bingo_nextTurn', (nextPlayerId) => { + socket.on('bingo_nextTurn', ({ nextPlayerId, timestamp }) => { setCurrentTurn(nextPlayerId); - setTurnTimer(30); + const elapsed = Math.floor((Date.now() - timestamp) / 1000); + setTurnTimer(Math.max(0, 30 - elapsed)); if (nextPlayerId === socket.id) { playTurn(); } @@ -90,78 +178,82 @@ const Bingo = () => { confetti({ particleCount: 150, spread: 70, - origin: { y: 0.6 } + origin: { y: 0.6 }, }); - const winnerName = players.find(p => p.id === winnerId)?.name || 'Someone'; + const winnerName = players.find((p) => p.id === winnerId)?.name || 'Someone'; Swal.fire({ title: 'BINGO!', text: `${winnerName} has achieved Bingo!`, icon: 'success', - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); setGameState('ended'); + sessionStorage.removeItem('bingo_reconnect'); }); - socket.on('bingo_playerLeft', (playerId) => { + socket.on('bingo_playerLeft', (_playerId) => { Swal.fire({ title: 'Player Left', text: 'A player has left the game.', icon: 'warning', - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); }); socket.on('bingo_alert', ({ icon, title, text }) => { - Swal.fire({ icon, title, text, customClass: { popup: 'glass rounded-3xl paper-font' } }); + // Auto-dismiss "Room Created" alerts that are informational + if (title === 'Room Created') { + Swal.fire({ + icon, + title, + text, + timer: 2000, + showConfirmButton: false, + customClass: { popup: sketchPopupClass }, + }); + } else { + Swal.fire({ + icon, + title, + text, + customClass: { popup: sketchPopupClass }, + }); + } }); return () => { socket.off('bingo_roomInfo'); + socket.off('bingo_playerBoard'); socket.off('bingo_gameStarted'); socket.off('bingo_gameRestarted'); socket.off('bingo_numberMarked'); socket.off('bingo_nextTurn'); socket.off('bingo_playerWon'); socket.off('bingo_playerLeft'); + socket.off('bingo_gamePaused'); socket.off('bingo_alert'); + sessionStorage.removeItem('bingo_reconnect'); }; - }, [socket, players, setRoomId, playPop, playWin, playTurn]); - - const checkForWin = useCallback(() => { - const size = 5; - const lines = []; + }, [socket, roomId, playPop, playWin, playTurn, generateBoard]); - // Horizontal - for (let i = 0; i < size; i++) { - lines.push(Array.from({ length: size }, (_, j) => i * size + j)); - } - // Vertical - for (let i = 0; i < size; i++) { - lines.push(Array.from({ length: size }, (_, j) => i + j * size)); - } - // Diagonals - lines.push(Array.from({ length: size }, (_, i) => i * size + i)); - lines.push(Array.from({ length: size }, (_, i) => (i + 1) * size - (i + 1))); - - const completedLinesCount = lines.filter(line => line.every(cell => numbers[cell] === 'X')).length; - const newStrikedOut = 'BINGO'.slice(0, Math.min(completedLinesCount, 5)); + useEffect(() => { + if (gameState !== 'playing' || numbers.length !== 25) return; - if (newStrikedOut.length > strikedOut.length) { - setStrikedOut(newStrikedOut); - if (newStrikedOut === 'BINGO') { + const progress = calculateBingoProgress(numbers); + if (progress.length > strikedOut.length) { + setStrikedOut(progress); + if (progress === 'BINGO') { socket.emit('bingo_achieved', roomId); } } - }, [numbers, strikedOut, roomId, socket]); - - useEffect(() => { - checkForWin(); - }, [numbers, checkForWin]); + }, [numbers, gameState, strikedOut, roomId, socket, calculateBingoProgress]); const handleCellClick = (number) => { - if (gameState === 'playing' && currentTurn === socket?.id && number !== 'X') { - socket.emit('bingo_markNumber', { roomId, number }); - } + if (gameState !== 'playing') return; + if (currentTurn !== socket?.id) return; + if (typeof number === 'string') return; + + socket.emit('bingo_markNumber', { roomId, number }); }; const handleCreateRoom = () => { @@ -174,121 +266,181 @@ const Bingo = () => { input: 'text', inputPlaceholder: 'Enter Room ID', showCancelButton: true, - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); if (joinRoomId) { - socket.emit('bingo_joinRoom', { roomId: joinRoomId.toUpperCase(), playerName }); + socket.emit('bingo_joinRoom', { + roomId: joinRoomId.toUpperCase(), + playerName, + }); } }; const handleStartGame = () => { if (players.length < 2) { - Swal.fire({ title: 'Wait!', text: 'Need at least 2 players!', icon: 'info' }); + Swal.fire({ + title: 'Wait!', + text: 'Need at least 2 players!', + icon: 'info', + }); return; } socket.emit('bingo_startGame', roomId); }; - const handleRestartGame = () => { - socket.emit('bingo_restartGame', roomId); + const handleLeaveRoom = () => { + Swal.fire({ + title: 'Leave Game?', + text: 'Are you sure you want to leave?', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Yes, leave', + customClass: { popup: sketchPopupClass }, + }).then((result) => { + if (result.isConfirmed) { + Swal.fire({ + title: 'Leaving...', + text: 'Are you absolutely sure?', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Yes, leave now', + cancelButtonText: 'Stay', + customClass: { popup: sketchPopupClass }, + }).then((confirmResult) => { + if (confirmResult.isConfirmed) { + socket.emit('bingo_leaveRoom', roomId); + sessionStorage.removeItem('bingo_reconnect'); + clearRoomId(roomId); + navigate('/'); + } + }); + } + }); }; return ( -
- navigate('/')} - variant="secondary" - className="absolute top-8 left-8 flex items-center gap-2" - > - - Back - - -

Bingo Party

- - {!roomId ? ( -
- Create Room - Join Room -
- ) : ( -
-
-
-
- - Room: {roomId} -
-
- {'BINGO'.split('').map((l, i) => ( - - {l} - - ))} -
-
+ +
+

Bingo Party

-
- {numbers.map((n, i) => ( - - ))} + {!roomId ? ( + +
+ Create Room + Join Room
-
+ + ) : ( +
+
+ +
+ + Room: {roomId} +
+
+ {'BINGO'.split('').map((l, i) => ( + + {l} + + ))} +
+
-
-
-

- - Players -

-
- {players.map(p => ( -
- {p.name} - {p.id === currentTurn && } -
+
+ {numbers.map((n, i) => ( + ))}
- {isCreator && gameState === 'ready' && ( - - 🚀 Start Party! - - )} - - {gameState === 'playing' && ( -
-
- - Time Remaining -
-
- {turnTimer}s +
+ +

+ + Players +

+
+ {players.map((p, i) => ( +
+
+
+ {p.name} + {p.id === socket?.id && (You)} +
+ {p.id === currentTurn && } +
+ ))}
- {currentTurn === socket?.id && ( -
- - Your Turn! + + + {isCreator && gameState === 'ready' && ( + + 🚀 Start Party! + + )} + + {(gameState === 'ready' || gameState === 'playing') && ( + + Leave Room + + )} + + {gameState === 'playing' && ( + +
+ + Time Remaining
- )} -
- )} +
+ {turnTimer}s +
+ {currentTurn === socket?.id && ( +
+ + Your Turn! +
+ )} + + )} +
-
- )} -
+ )} +
+ ); }; diff --git a/pro/src/bingo/Bingo.test.jsx b/pro/src/bingo/Bingo.test.jsx index b60a8f9..27fd979 100644 --- a/pro/src/bingo/Bingo.test.jsx +++ b/pro/src/bingo/Bingo.test.jsx @@ -5,7 +5,6 @@ import Bingo from './Bingo'; import { GameProvider } from '../context/GameContext'; import { BrowserRouter } from 'react-router-dom'; -// Mock Socket.io const mockSocket = { id: 'mock-id', on: vi.fn(), @@ -14,57 +13,180 @@ const mockSocket = { disconnect: vi.fn(), }; -vi.mock('socket.io-client', () => ({ - default: () => mockSocket -})); +vi.mock('socket.io-client', () => ({ default: () => mockSocket })); +vi.mock('use-sound', () => ({ default: () => [vi.fn()] })); +vi.mock('canvas-confetti', () => ({ default: vi.fn() })); +vi.mock('sweetalert2', () => ({ default: { fire: vi.fn().mockResolvedValue({ isConfirmed: true }) } })); + +const Wrapper = ({ children }) => ( + + {children} + +); + +const findEventCb = (event) => { + const call = mockSocket.on.mock.calls.find((c) => c[0] === event); + return call?.[1]; +}; describe('Bingo', () => { beforeEach(() => { vi.clearAllMocks(); + localStorage.clear(); + sessionStorage.clear(); + }); + + describe('Board Rendering', () => { + it('shows Create Room and Join Room buttons in waiting state', () => { + render(, { wrapper: Wrapper }); + expect(screen.getByText('Create Room')).toBeTruthy(); + expect(screen.getByText('Join Room')).toBeTruthy(); + }); + + it('renders 25 number cells when playing', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('bingo_roomInfo'); + await act(async () => { + cb({ + id: 'BINGO1', + creator: 'mock-id', + players: [ + { id: 'mock-id', name: 'Alice', connected: true }, + { id: 'bob-id', name: 'Bob', connected: true }, + ], + gameState: 'playing', + currentTurn: 'mock-id', + turnOrder: ['mock-id', 'bob-id'], + }); + }); + + const buttons = screen.getAllByRole('button'); + const numberCells = buttons.filter((b) => { + const n = parseInt(b.textContent); + return n >= 1 && n <= 25; + }); + expect(numberCells.length).toBe(25); + }); + + it('shows BINGO progress display', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('bingo_roomInfo'); + await act(async () => { + cb({ + id: 'BINGO1', + creator: 'mock-id', + players: [ + { id: 'mock-id', name: 'Alice', connected: true }, + { id: 'bob-id', name: 'Bob', connected: true }, + ], + gameState: 'playing', + currentTurn: 'mock-id', + turnOrder: ['mock-id', 'bob-id'], + }); + }); + + for (const letter of 'BINGO') { + expect(screen.getByText(letter)).toBeTruthy(); + } + }); }); - it('emits markNumber when a cell is clicked', async () => { - render( - - - - - - ); - - // Simulate being in a game and it being our turn - const roomInfoCall = mockSocket.on.mock.calls.find(call => call[0] === 'bingo_roomInfo'); - if (!roomInfoCall) throw new Error('bingo_roomInfo listener not registered'); - - const roomInfoCallback = roomInfoCall[1]; - - await act(async () => { - roomInfoCallback({ - id: '123456', - creator: 'mock-id', - players: [{ id: 'mock-id', name: 'Alice' }, { id: 'bob-id', name: 'Bob' }], - gameState: 'playing', - currentTurn: 'mock-id', - turnOrder: ['mock-id', 'bob-id'] + describe('Mark Numbers', () => { + it('emits bingo_markNumber when a cell is clicked on my turn', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('bingo_roomInfo'); + await act(async () => { + cb({ + id: 'BINGO1', + creator: 'mock-id', + players: [ + { id: 'mock-id', name: 'Alice', connected: true }, + { id: 'bob-id', name: 'Bob', connected: true }, + ], + gameState: 'playing', + currentTurn: 'mock-id', + turnOrder: ['mock-id', 'bob-id'], + }); + }); + + const buttons = screen.getAllByRole('button'); + const numberCell = buttons.find((b) => { + const n = parseInt(b.textContent); + return n >= 1 && n <= 25; + }); + expect(numberCell).toBeDefined(); + const number = parseInt(numberCell.textContent); + + await act(async () => { + fireEvent.click(numberCell); }); + + expect(mockSocket.emit).toHaveBeenCalledWith('bingo_markNumber', expect.objectContaining({ number })); }); - // Our Bingo cells are buttons. - // There are 25 cells + navigation buttons. - const cells = screen.getAllByRole('button'); - - // Find a cell with a number (not navigation) - const gameCell = cells.find(c => !isNaN(parseInt(c.textContent))); - if (!gameCell) throw new Error('Bingo cell not found'); + it('does not emit when it is not my turn', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('bingo_roomInfo'); + await act(async () => { + cb({ + id: 'BINGO1', + creator: 'other-id', + players: [ + { id: 'mock-id', name: 'Alice', connected: true }, + { id: 'bob-id', name: 'Bob', connected: true }, + ], + gameState: 'playing', + currentTurn: 'bob-id', + turnOrder: ['mock-id', 'bob-id'], + }); + }); - const number = parseInt(gameCell.textContent); + const buttons = screen.getAllByRole('button'); + const numberCell = buttons.find((b) => { + const n = parseInt(b.textContent); + return n >= 1 && n <= 25; + }); - await act(async () => { - fireEvent.click(gameCell); + await act(async () => { + fireEvent.click(numberCell); + }); + + expect(mockSocket.emit).not.toHaveBeenCalledWith('bingo_markNumber', expect.any(Object)); }); - expect(mockSocket.emit).toHaveBeenCalledWith('bingo_markNumber', expect.objectContaining({ - number: number - })); + it('shows striked cells as stars after bingo_numberMarked', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('bingo_roomInfo'); + await act(async () => { + cb({ + id: 'BINGO1', + creator: 'mock-id', + players: [ + { id: 'mock-id', name: 'Alice', connected: true }, + { id: 'bob-id', name: 'Bob', connected: true }, + ], + gameState: 'playing', + currentTurn: 'mock-id', + turnOrder: ['mock-id', 'bob-id'], + }); + }); + + const numberMarkedCb = findEventCb('bingo_numberMarked'); + await act(async () => { + numberMarkedCb({ + number: 5, + nextTurn: 'bob-id', + strikedNumbers: [5], + }); + }); + + const stars = screen.getAllByText('★'); + expect(stars.length).toBeGreaterThanOrEqual(1); + }); }); }); diff --git a/pro/src/components/ErrorBoundary.jsx b/pro/src/components/ErrorBoundary.jsx index 640c0a0..e3fb298 100644 --- a/pro/src/components/ErrorBoundary.jsx +++ b/pro/src/components/ErrorBoundary.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import { Box, Typography, Button } from '@mui/material'; class ErrorBoundary extends React.Component { constructor(props) { @@ -7,16 +6,12 @@ class ErrorBoundary extends React.Component { this.state = { hasError: false, error: null, errorInfo: null }; } - static getDerivedStateFromError(error) { + static getDerivedStateFromError() { return { hasError: true }; } componentDidCatch(error, errorInfo) { - this.setState({ - error: error, - errorInfo: errorInfo - }); - // You can also log the error to an error reporting service here + this.setState({ error, errorInfo }); console.error('Error caught by ErrorBoundary:', error, errorInfo); } @@ -27,49 +22,24 @@ class ErrorBoundary extends React.Component { render() { if (this.state.hasError) { return ( - - - Oops! Something went wrong - - - We're sorry for the inconvenience. Please try refreshing the page. - - - {process.env.NODE_ENV === 'development' && ( - - - Error Details: - -
+          
+          {import.meta.env.DEV && (
+            
+

Error Details:

+
                 {this.state.error && this.state.error.toString()}
                 {this.state.errorInfo && this.state.errorInfo.componentStack}
               
- +
)} - +
); } @@ -77,4 +47,4 @@ class ErrorBoundary extends React.Component { } } -export default ErrorBoundary; \ No newline at end of file +export default ErrorBoundary; diff --git a/pro/src/components/PaperPartyLanding.jsx b/pro/src/components/PaperPartyLanding.jsx index 1da9aa6..9e3c536 100644 --- a/pro/src/components/PaperPartyLanding.jsx +++ b/pro/src/components/PaperPartyLanding.jsx @@ -1,21 +1,119 @@ import React, { useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useGameContext } from '../context/GameContext'; -import RetroButton from './ui/RetroButton'; import Swal from 'sweetalert2'; -import { Dices, Hash, User, Grid3X3, Square } from 'lucide-react'; - -const GameCard = ({ title, description, onClick, icon: Icon }) => ( -
-
-
- +import { User, BookOpen, PenTool, Share2, Zap, Circle } from 'lucide-react'; + +const BingoIcon = () => ( + + + + B + + +); + +const TicTacToeIcon = () => ( + + + + + + + X + + + O + + +); + +const UTTTIcon = () => ( + + + + + + + X + + + O + + +); + +const DotsAndBoxesIcon = () => ( + + + + + + + + + + + + + + + + +); + +const ComingSoonIcon = () => ( + + + + ? + + +); + +const GameCard = ({ title, description, onClick, icon: Icon, accentColor, badge }) => ( +
+
+
+
+
+ +
+
+
+

{title}

+ {badge && ( + + {badge} + + )} +
+

{description}

+
+
+
+ + Click to play + + + +
-

{title}

-

{description}

); @@ -31,68 +129,120 @@ const PaperPartyLanding = () => { input: 'text', inputPlaceholder: 'Enter your name...', allowOutsideClick: false, - confirmButtonText: 'Let\'s Play!', + confirmButtonText: "Let's Play!", customClass: { popup: 'glass rounded-3xl paper-font', title: 'hand-drawn text-3xl', - confirmButton: 'bg-blue-500/80 hover:bg-blue-500 px-8 py-3 rounded-xl font-bold transition-all' + confirmButton: 'bg-blue-500/80 hover:bg-blue-500 px-8 py-3 rounded-xl font-bold transition-all', }, buttonsStyling: false, inputValidator: (value) => { - if (!value) return 'We need a name to start the party!'; - } + if (!value || !value.trim()) return 'We need a name to start the party!'; + }, }).then((result) => { if (result.isConfirmed) { - setPlayerName(result.value); + setPlayerName(result.value.trim()); } }); } }, [playerName, setPlayerName]); return ( -
-
-

+
+
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+

PaperParty

-

- Multiplayer games that feel like the back of your notebook. -

+
+ +

+ Multiplayer games that feel like the back of your notebook. +

+
+
+ {[...Array(5)].map((_, i) => ( +
+ ))} +
-
- + navigate('/bingo')} /> - navigate('/tictactoe')} /> - navigate('/uttt')} /> - navigate('/dab')} /> + +
+ +
{playerName && ( -
- - Playing as {playerName} +
+
+ +
+ Playing as + {playerName}
)} + +
+ + + +
); }; diff --git a/pro/src/components/PaperPartyLanding.test.jsx b/pro/src/components/PaperPartyLanding.test.jsx index 1fc454c..4f90e71 100644 --- a/pro/src/components/PaperPartyLanding.test.jsx +++ b/pro/src/components/PaperPartyLanding.test.jsx @@ -1,6 +1,6 @@ import React from 'react'; -import { render, screen, fireEvent } from '@testing-library/react'; -import { describe, it, expect, vi, beforeEach } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import { describe, it, expect, vi } from 'vitest'; import PaperPartyLanding from './PaperPartyLanding'; import { GameProvider } from '../context/GameContext'; import { BrowserRouter } from 'react-router-dom'; @@ -8,8 +8,8 @@ import { BrowserRouter } from 'react-router-dom'; // Mock SweetAlert2 vi.mock('sweetalert2', () => ({ default: { - fire: vi.fn().mockResolvedValue({ isConfirmed: true, value: 'Alice' }) - } + fire: vi.fn().mockResolvedValue({ isConfirmed: true, value: 'Alice' }), + }, })); describe('PaperPartyLanding', () => { @@ -19,7 +19,7 @@ describe('PaperPartyLanding', () => { - + , ); expect(screen.getByText('Bingo')).toBeDefined(); diff --git a/pro/src/components/ui/AvatarSelector.jsx b/pro/src/components/ui/AvatarSelector.jsx new file mode 100644 index 0000000..7f4a974 --- /dev/null +++ b/pro/src/components/ui/AvatarSelector.jsx @@ -0,0 +1,36 @@ +import React from 'react'; + +const AVATARS = ['🐼', '🦊', '🐸', '🐙', '🦁', '🐧']; +const COLORS = ['#2a2a3e', '#c73e1d', '#2d4a8f', '#2f5233', '#7b2d8f', '#b5651d']; + +const AvatarSelector = ({ avatar, color, onAvatarChange, onColorChange }) => { + return ( +
+
+ {AVATARS.map((a) => ( + + ))} +
+
+ {COLORS.map((c) => ( +
+
+ ); +}; + +export default AvatarSelector; diff --git a/pro/src/components/ui/AvatarSelector.test.jsx b/pro/src/components/ui/AvatarSelector.test.jsx new file mode 100644 index 0000000..ed79544 --- /dev/null +++ b/pro/src/components/ui/AvatarSelector.test.jsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { describe, it, expect, vi } from 'vitest'; +import AvatarSelector from './AvatarSelector'; + +describe('AvatarSelector', () => { + it('renders all 6 avatar options', () => { + render(); + ['🐼', '🦊', '🐸', '🐙', '🦁', '🐧'].forEach((a) => { + expect(screen.getByText(a)).toBeTruthy(); + }); + }); + + it('calls onAvatarChange with clicked avatar', () => { + const onAvatarChange = vi.fn(); + render(); + fireEvent.click(screen.getByText('🦊')); + expect(onAvatarChange).toHaveBeenCalledWith('🦊'); + }); + + it('calls onColorChange with clicked color', () => { + const onColorChange = vi.fn(); + render(); + const colorBtns = screen.getAllByRole('button').filter((b) => !b.textContent); + fireEvent.click(colorBtns[1]); + expect(onColorChange).toHaveBeenCalled(); + }); + + it('highlights the selected avatar', () => { + render(); + const frogBtn = screen.getByText('🐸'); + expect(frogBtn.className).toContain('border-ink'); + }); +}); diff --git a/pro/src/components/ui/CountdownOverlay.jsx b/pro/src/components/ui/CountdownOverlay.jsx new file mode 100644 index 0000000..c8aca15 --- /dev/null +++ b/pro/src/components/ui/CountdownOverlay.jsx @@ -0,0 +1,30 @@ +import React, { useState, useEffect } from 'react'; + +const CountdownOverlay = ({ onComplete }) => { + const [count, setCount] = useState(3); + + useEffect(() => { + if (count === 0) { + onComplete?.(); + return; + } + const t = setTimeout(() => setCount((c) => c - 1), 1000); + return () => clearTimeout(t); + }, [count, onComplete]); + + if (count === 0) return null; + + return ( +
+ + {count} + +
+ ); +}; + +export default CountdownOverlay; diff --git a/pro/src/components/ui/CountdownOverlay.test.jsx b/pro/src/components/ui/CountdownOverlay.test.jsx new file mode 100644 index 0000000..98feec9 --- /dev/null +++ b/pro/src/components/ui/CountdownOverlay.test.jsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { render, screen, act } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import CountdownOverlay from './CountdownOverlay'; + +describe('CountdownOverlay', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + afterEach(() => { + vi.useRealTimers(); + }); + + it('starts at 3', () => { + render(); + expect(screen.getByText('3')).toBeTruthy(); + }); + + it('counts down to 2 after 1 second', () => { + render(); + act(() => { + vi.advanceTimersByTime(1000); + }); + expect(screen.getByText('2')).toBeTruthy(); + }); + + it('counts down to 1 after 2 seconds', () => { + render(); + act(() => { + vi.advanceTimersByTime(1000); + }); + act(() => { + vi.advanceTimersByTime(1000); + }); + expect(screen.getByText('1')).toBeTruthy(); + }); + + it('calls onComplete and renders nothing after 3 ticks', () => { + const onComplete = vi.fn(); + const { container } = render(); + act(() => { + vi.advanceTimersByTime(1000); + }); + act(() => { + vi.advanceTimersByTime(1000); + }); + act(() => { + vi.advanceTimersByTime(1000); + }); + expect(onComplete).toHaveBeenCalledTimes(1); + expect(container.firstChild).toBeNull(); + }); +}); diff --git a/pro/src/components/ui/GameLayout.jsx b/pro/src/components/ui/GameLayout.jsx new file mode 100644 index 0000000..09d724a --- /dev/null +++ b/pro/src/components/ui/GameLayout.jsx @@ -0,0 +1,63 @@ +import React from 'react'; +import { ArrowLeft } from 'lucide-react'; +import Swal from 'sweetalert2'; +import { useNavigate } from 'react-router-dom'; +import { sketchPopupClass } from './SketchPopup'; + +const GameLayout = ({ socket, roomId, _gamePrefix, players = [], children }) => { + const navigate = useNavigate(); + + const handleLeave = async () => { + const result = await Swal.fire({ + title: 'Leave Game?', + text: 'Your progress will be lost.', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Leave', + cancelButtonText: 'Stay', + customClass: { popup: sketchPopupClass }, + }); + if (!result.isConfirmed) return; + socket?.disconnect(); + navigate('/'); + }; + + const handleCopyRoomId = () => { + navigator.clipboard?.writeText(roomId); + }; + + return ( +
+ {/* Info Zone */} + + + {/* Canvas Zone */} +
{children}
+
+ ); +}; + +export default GameLayout; diff --git a/pro/src/components/ui/GameLayout.test.jsx b/pro/src/components/ui/GameLayout.test.jsx new file mode 100644 index 0000000..3ddcb84 --- /dev/null +++ b/pro/src/components/ui/GameLayout.test.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { render, screen, fireEvent, act } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import GameLayout from './GameLayout'; +import { BrowserRouter } from 'react-router-dom'; + +vi.mock('sweetalert2', () => ({ + default: { + fire: vi.fn().mockResolvedValue({ isConfirmed: true }), + }, +})); + +const mockSocket = { emit: vi.fn(), disconnect: vi.fn() }; +const mockNavigate = vi.fn(); + +vi.mock('react-router-dom', async (importOriginal) => { + const actual = await importOriginal(); + return { ...actual, useNavigate: () => mockNavigate }; +}); + +const renderLayout = (props = {}) => + render( + + +
Board
+
+
, + ); + +describe('GameLayout', () => { + beforeEach(() => vi.clearAllMocks()); + + it('renders children in the canvas zone', () => { + renderLayout(); + expect(screen.getByTestId('game-content')).toBeInTheDocument(); + }); + + it('displays the roomId badge', () => { + renderLayout(); + expect(screen.getByText('ABC123')).toBeInTheDocument(); + }); + + it('renders player avatars when players prop is provided', () => { + renderLayout({ + players: [ + { id: 'p1', name: 'Alice' }, + { id: 'p2', name: 'Bob' }, + ], + }); + expect(screen.getByText('Al')).toBeInTheDocument(); + expect(screen.getByText('Bo')).toBeInTheDocument(); + }); + + it('back button triggers leave confirmation', async () => { + const Swal = (await import('sweetalert2')).default; + renderLayout(); + const backBtn = screen.getByRole('button', { name: /back|leave/i }); + await act(async () => fireEvent.click(backBtn)); + expect(Swal.fire).toHaveBeenCalled(); + }); + + it('disconnects and navigates to / on confirmed leave', async () => { + renderLayout(); + const backBtn = screen.getByRole('button', { name: /back|leave/i }); + await act(async () => fireEvent.click(backBtn)); + expect(mockSocket.disconnect).toHaveBeenCalled(); + expect(mockNavigate).toHaveBeenCalledWith('/'); + }); + + it('copies roomId to clipboard when badge is clicked', async () => { + const writeText = vi.fn().mockResolvedValue(undefined); + Object.assign(navigator, { clipboard: { writeText } }); + renderLayout(); + await act(async () => fireEvent.click(screen.getByText('ABC123'))); + expect(writeText).toHaveBeenCalledWith('ABC123'); + }); +}); diff --git a/pro/src/components/ui/LeaveButton.jsx b/pro/src/components/ui/LeaveButton.jsx new file mode 100644 index 0000000..08a1ee3 --- /dev/null +++ b/pro/src/components/ui/LeaveButton.jsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { ArrowLeft } from 'lucide-react'; +import Swal from 'sweetalert2'; +import { sketchPopupClass } from './SketchPopup'; + +const LeaveButton = ({ onLeave, className = '' }) => { + const handleClick = async () => { + const result = await Swal.fire({ + title: 'Leave Game?', + text: 'Are you sure you want to leave?', + showCancelButton: true, + confirmButtonText: 'Yes, Leave', + cancelButtonText: 'Stay', + customClass: { popup: sketchPopupClass }, + }); + if (result.isConfirmed) { + onLeave(); + } + }; + + return ( + + ); +}; + +export default LeaveButton; diff --git a/pro/src/components/ui/LeaveButton.test.jsx b/pro/src/components/ui/LeaveButton.test.jsx new file mode 100644 index 0000000..b06c1c0 --- /dev/null +++ b/pro/src/components/ui/LeaveButton.test.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import LeaveButton from './LeaveButton'; + +vi.mock('sweetalert2', () => ({ + default: { fire: vi.fn().mockResolvedValue({ isConfirmed: true }) }, +})); + +describe('LeaveButton', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('renders a button', () => { + render(); + expect(screen.getByRole('button')).toBeTruthy(); + }); + + it('calls onLeave when confirmed', async () => { + const onLeave = vi.fn(); + render(); + await fireEvent.click(screen.getByRole('button')); + await vi.waitFor(() => expect(onLeave).toHaveBeenCalledTimes(1)); + }); + + it('does not call onLeave when cancelled', async () => { + const Swal = (await import('sweetalert2')).default; + Swal.fire.mockResolvedValueOnce({ isConfirmed: false }); + const onLeave = vi.fn(); + render(); + await fireEvent.click(screen.getByRole('button')); + await vi.waitFor(() => expect(Swal.fire).toHaveBeenCalled()); + expect(onLeave).not.toHaveBeenCalled(); + }); +}); diff --git a/pro/src/components/ui/MatchReport.jsx b/pro/src/components/ui/MatchReport.jsx new file mode 100644 index 0000000..73114bf --- /dev/null +++ b/pro/src/components/ui/MatchReport.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Trophy, Frown } from 'lucide-react'; +import SketchButton from './SketchButton'; +import SketchCard from './SketchCard'; + +const MatchReport = ({ winner, isWinner, stats = {}, onRematch, onNewRoom }) => { + return ( + +
+ {isWinner ? : } +
+

{isWinner ? 'You Win!' : `${winner} Wins!`}

+ {(stats.moves || stats.time) && ( +
+ {stats.moves &&
Moves: {stats.moves}
} + {stats.time &&
Time: {stats.time}
} +
+ )} +
+ {onRematch && Rematch} + {onNewRoom && New Room} +
+
+ ); +}; + +export default MatchReport; diff --git a/pro/src/components/ui/MatchReport.test.jsx b/pro/src/components/ui/MatchReport.test.jsx new file mode 100644 index 0000000..e6da6a3 --- /dev/null +++ b/pro/src/components/ui/MatchReport.test.jsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { describe, it, expect, vi } from 'vitest'; +import MatchReport from './MatchReport'; + +describe('MatchReport', () => { + it('shows "You Win!" when isWinner is true', () => { + render(); + expect(screen.getByText('You Win!')).toBeTruthy(); + }); + + it('shows winner name when isWinner is false', () => { + render(); + expect(screen.getByText('Bob Wins!')).toBeTruthy(); + }); + + it('shows stats when provided', () => { + render(); + expect(screen.getByText('Moves: 12')).toBeTruthy(); + expect(screen.getByText('Time: 1m 23s')).toBeTruthy(); + }); + + it('calls onRematch when Rematch is clicked', () => { + const onRematch = vi.fn(); + render(); + fireEvent.click(screen.getByText('Rematch')); + expect(onRematch).toHaveBeenCalledTimes(1); + }); + + it('calls onNewRoom when New Room is clicked', () => { + const onNewRoom = vi.fn(); + render(); + fireEvent.click(screen.getByText('New Room')); + expect(onNewRoom).toHaveBeenCalledTimes(1); + }); + + it('does not render Rematch button when onRematch is not provided', () => { + render(); + expect(screen.queryByText('Rematch')).toBeNull(); + }); +}); diff --git a/pro/src/components/ui/ModeSelector.jsx b/pro/src/components/ui/ModeSelector.jsx new file mode 100644 index 0000000..9cfd41c --- /dev/null +++ b/pro/src/components/ui/ModeSelector.jsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { SwatchBook } from 'lucide-react'; + +const ModeSelector = ({ mode, onModeChange, customRows, customCols, onRowsChange, onColsChange }) => { + return ( +
+
+ + Game Mode +
+
+ + +
+ {mode === 'custom' && ( +
+
+ + onRowsChange(Number(e.target.value))} + className="w-full" + /> +
+
+ + onColsChange(Number(e.target.value))} + className="w-full" + /> +
+
+ )} +
+ ); +}; + +export default ModeSelector; diff --git a/pro/src/components/ui/ModeSelector.test.jsx b/pro/src/components/ui/ModeSelector.test.jsx new file mode 100644 index 0000000..8184274 --- /dev/null +++ b/pro/src/components/ui/ModeSelector.test.jsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { describe, it, expect, vi } from 'vitest'; +import ModeSelector from './ModeSelector'; + +const defaults = { + mode: 'classic', + onModeChange: vi.fn(), + customRows: 5, + customCols: 5, + onRowsChange: vi.fn(), + onColsChange: vi.fn(), +}; + +describe('ModeSelector', () => { + it('renders Classic and Custom buttons', () => { + render(); + expect(screen.getByText('Classic (9×9)')).toBeTruthy(); + expect(screen.getByText('Custom Size')).toBeTruthy(); + }); + + it('calls onModeChange with "custom" when Custom is clicked', () => { + const onModeChange = vi.fn(); + render(); + fireEvent.click(screen.getByText('Custom Size')); + expect(onModeChange).toHaveBeenCalledWith('custom'); + }); + + it('calls onModeChange with "classic" when Classic is clicked', () => { + const onModeChange = vi.fn(); + render(); + fireEvent.click(screen.getByText('Classic (9×9)')); + expect(onModeChange).toHaveBeenCalledWith('classic'); + }); + + it('shows row/col sliders only in custom mode', () => { + render(); + expect(screen.getByText(/Rows:/)).toBeTruthy(); + expect(screen.getByText(/Columns:/)).toBeTruthy(); + }); + + it('does not show sliders in classic mode', () => { + render(); + expect(screen.queryByText(/Rows:/)).toBeNull(); + }); + + it('calls onRowsChange when row slider changes', () => { + const onRowsChange = vi.fn(); + render(); + const sliders = screen.getAllByRole('slider'); + fireEvent.change(sliders[0], { target: { value: '7' } }); + expect(onRowsChange).toHaveBeenCalledWith(7); + }); +}); diff --git a/pro/src/components/ui/PlayerBadge.jsx b/pro/src/components/ui/PlayerBadge.jsx new file mode 100644 index 0000000..78a6635 --- /dev/null +++ b/pro/src/components/ui/PlayerBadge.jsx @@ -0,0 +1,19 @@ +import React from 'react'; + +const PLAYER_COLORS = ['#1a1a2e', '#c73e1d', '#2d4a8f', '#2f5233']; + +const PlayerBadge = ({ player, index, isConnected }) => { + return ( +
+ {player.name} {!isConnected && '(disconnected)'} +
+ ); +}; + +export default PlayerBadge; diff --git a/pro/src/components/ui/PlayerBadge.test.jsx b/pro/src/components/ui/PlayerBadge.test.jsx new file mode 100644 index 0000000..775303b --- /dev/null +++ b/pro/src/components/ui/PlayerBadge.test.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { describe, it, expect } from 'vitest'; +import PlayerBadge from './PlayerBadge'; + +describe('PlayerBadge', () => { + it('renders player name', () => { + render(); + expect(screen.getByText(/Alice/)).toBeTruthy(); + }); + + it('shows disconnected label when isConnected is false', () => { + render(); + expect(screen.getByText(/disconnected/)).toBeTruthy(); + }); + + it('does not show disconnected label when connected', () => { + render(); + expect(screen.queryByText(/disconnected/)).toBeNull(); + }); + + it('applies reduced opacity when disconnected', () => { + const { container } = render(); + expect(container.firstChild.style.opacity).toBe('0.4'); + }); + + it('applies full opacity when connected', () => { + const { container } = render(); + expect(container.firstChild.style.opacity).toBe('1'); + }); +}); diff --git a/pro/src/components/ui/RetroButton.jsx b/pro/src/components/ui/RetroButton.jsx index 3639c55..27663ff 100644 --- a/pro/src/components/ui/RetroButton.jsx +++ b/pro/src/components/ui/RetroButton.jsx @@ -1,21 +1,18 @@ import React from 'react'; const RetroButton = ({ children, onClick, disabled, className = '', variant = 'primary' }) => { - const baseStyles = "px-6 py-2 rounded-lg font-bold transition-all duration-300 transform active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none glass"; - + const baseStyles = + 'px-6 py-2 rounded-lg font-bold transition-all duration-300 transform active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none glass'; + const variants = { - primary: "bg-blue-500/40 hover:bg-blue-500/60 text-blue-900 border-blue-400/50", - secondary: "bg-purple-500/40 hover:bg-purple-500/60 text-purple-900 border-purple-400/50", - success: "bg-green-500/40 hover:bg-green-500/60 text-green-900 border-green-400/50", - danger: "bg-red-500/40 hover:bg-red-500/60 text-red-900 border-red-400/50", + primary: 'bg-blue-500/40 hover:bg-blue-500/60 text-blue-900 border-blue-400/50', + secondary: 'bg-purple-500/40 hover:bg-purple-500/60 text-purple-900 border-purple-400/50', + success: 'bg-green-500/40 hover:bg-green-500/60 text-green-900 border-green-400/50', + danger: 'bg-red-500/40 hover:bg-red-500/60 text-red-900 border-red-400/50', }; return ( - ); diff --git a/pro/src/components/ui/RetroButton.test.jsx b/pro/src/components/ui/RetroButton.test.jsx index 79e06cb..c70c6ad 100644 --- a/pro/src/components/ui/RetroButton.test.jsx +++ b/pro/src/components/ui/RetroButton.test.jsx @@ -17,7 +17,11 @@ describe('RetroButton', () => { it('can be disabled', () => { const handleClick = vi.fn(); - render(Disabled); + render( + + Disabled + , + ); const button = screen.getByText('Disabled'); expect(button).toBeDisabled(); diff --git a/pro/src/components/ui/RoomLobby.jsx b/pro/src/components/ui/RoomLobby.jsx new file mode 100644 index 0000000..48d7ffc --- /dev/null +++ b/pro/src/components/ui/RoomLobby.jsx @@ -0,0 +1,121 @@ +import React, { useState, useEffect } from 'react'; +import SketchButton from './SketchButton'; +import CountdownOverlay from './CountdownOverlay'; + +const RoomLobby = ({ + roomId, + players = [], + isHost, + minPlayers = 2, + onStart, + onLeave, + gameName = 'Game', + showCountdown = false, + onCountdownComplete, +}) => { + const [dots, setDots] = useState(''); + const [shareSupported] = useState(() => !!navigator.share); + + // Animated "Waiting..." dots + useEffect(() => { + if (players.length >= minPlayers) return; + const id = setInterval(() => { + setDots((d) => (d.length >= 3 ? '' : d + '.')); + }, 500); + return () => clearInterval(id); + }, [players.length, minPlayers]); + + const handleShare = async () => { + try { + await navigator.share({ + title: `Join my ${gameName} room!`, + text: `Use room code: ${roomId}`, + url: window.location.href, + }); + } catch { + // user cancelled or not supported + } + }; + + const canStart = players.length >= minPlayers; + + return ( +
+ {showCountdown && } + +
+ {/* Room ID */} +
+

Room Code

+

{roomId}

+
+ + {/* Animated status banner */} +
+ {canStart ? ( + ✅ Ready to start! + ) : ( + Waiting for players{dots} + )} +
+ + {/* Player ready checklist */} +
+

+ Players ({players.length}/{minPlayers} min) +

+ {players.map((p, i) => ( +
+ {p.connected !== false ? '☑️' : '☐'} + {p.name} + {i === 0 && host} +
+ ))} + {/* Empty slots */} + {Array.from({ length: Math.max(0, minPlayers - players.length) }).map((_, i) => ( +
+ ☐ + Waiting... +
+ ))} +
+ + {/* Actions */} +
+ {/* Web Share API invite */} + {shareSupported && ( + + 📤 Invite Friends + + )} + + {isHost && ( + + {canStart ? '🚀 Start Game' : `Need ${minPlayers - players.length} more player(s)`} + + )} + + {!isHost &&

Waiting for host to start…

} + + + Leave Room + +
+
+
+ ); +}; + +export default RoomLobby; diff --git a/pro/src/components/ui/RoomLobby.test.jsx b/pro/src/components/ui/RoomLobby.test.jsx new file mode 100644 index 0000000..565ae4e --- /dev/null +++ b/pro/src/components/ui/RoomLobby.test.jsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import RoomLobby from './RoomLobby'; + +const players2 = [ + { id: '1', name: 'Alice', connected: true }, + { id: '2', name: 'Bob', connected: true }, +]; + +describe('RoomLobby', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + afterEach(() => { + vi.useRealTimers(); + }); + + it('displays the room code', () => { + render(); + expect(screen.getByText('ABC123')).toBeTruthy(); + }); + + it('shows "Waiting for players" when below minPlayers', () => { + render( + , + ); + expect(screen.getByText(/Waiting for players/)).toBeTruthy(); + }); + + it('shows "Ready to start!" when minPlayers met', () => { + render(); + expect(screen.getByText('✅ Ready to start!')).toBeTruthy(); + }); + + it('renders player names in checklist', () => { + render(); + expect(screen.getByText('Alice')).toBeTruthy(); + expect(screen.getByText('Bob')).toBeTruthy(); + }); + + it('shows Start Game button for host when ready', () => { + render(); + expect(screen.getByText('🚀 Start Game')).toBeTruthy(); + }); + + it('calls onStart when Start Game is clicked', () => { + const onStart = vi.fn(); + render(); + fireEvent.click(screen.getByText('🚀 Start Game')); + expect(onStart).toHaveBeenCalledTimes(1); + }); + + it('shows "Waiting for host" message for non-host', () => { + render(); + expect(screen.getByText(/Waiting for host/)).toBeTruthy(); + }); + + it('calls onLeave when Leave Room is clicked', () => { + const onLeave = vi.fn(); + render(); + fireEvent.click(screen.getByText('Leave Room')); + expect(onLeave).toHaveBeenCalledTimes(1); + }); + + it('shows CountdownOverlay when showCountdown is true', () => { + render( + , + ); + expect(screen.getByText('3')).toBeTruthy(); + }); +}); diff --git a/pro/src/components/ui/SketchBorder.jsx b/pro/src/components/ui/SketchBorder.jsx new file mode 100644 index 0000000..0429879 --- /dev/null +++ b/pro/src/components/ui/SketchBorder.jsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const SketchBorder = ({ children, className = '' }) => { + return
{children}
; +}; + +export default SketchBorder; diff --git a/pro/src/components/ui/SketchButton.jsx b/pro/src/components/ui/SketchButton.jsx new file mode 100644 index 0000000..b4c8037 --- /dev/null +++ b/pro/src/components/ui/SketchButton.jsx @@ -0,0 +1,16 @@ +import React from 'react'; + +const SketchButton = ({ children, onClick, disabled, className = '', type = 'button' }) => { + return ( + + ); +}; + +export default SketchButton; diff --git a/pro/src/components/ui/SketchCard.jsx b/pro/src/components/ui/SketchCard.jsx new file mode 100644 index 0000000..0bc7304 --- /dev/null +++ b/pro/src/components/ui/SketchCard.jsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const SketchCard = ({ children, className = '' }) => { + return
{children}
; +}; + +export default SketchCard; diff --git a/pro/src/components/ui/SketchPopup.jsx b/pro/src/components/ui/SketchPopup.jsx new file mode 100644 index 0000000..0d4c955 --- /dev/null +++ b/pro/src/components/ui/SketchPopup.jsx @@ -0,0 +1 @@ +export const sketchPopupClass = 'sketch-popup'; diff --git a/pro/src/components/ui/TextInput.test.jsx b/pro/src/components/ui/TextInput.test.jsx index 79e24f3..4f87058 100644 --- a/pro/src/components/ui/TextInput.test.jsx +++ b/pro/src/components/ui/TextInput.test.jsx @@ -16,7 +16,7 @@ describe('TextInput', () => { it('renders label and placeholder', () => { render(); - + expect(screen.getByText('Room ID')).toBeDefined(); expect(screen.getByPlaceholderText('Enter code')).toBeDefined(); }); diff --git a/pro/src/components/ui/TurnIndicator.jsx b/pro/src/components/ui/TurnIndicator.jsx new file mode 100644 index 0000000..e154b48 --- /dev/null +++ b/pro/src/components/ui/TurnIndicator.jsx @@ -0,0 +1,22 @@ +import React from 'react'; + +const TurnIndicator = ({ playerName, isActive, isMyTurn = false, turnTimer = null }) => { + const initials = playerName.slice(0, 2); + const timerProgress = turnTimer !== null ? turnTimer / 30 : null; + + return ( +
+ {initials} +
+ ); +}; + +export default TurnIndicator; diff --git a/pro/src/components/ui/TurnIndicator.test.jsx b/pro/src/components/ui/TurnIndicator.test.jsx new file mode 100644 index 0000000..173da24 --- /dev/null +++ b/pro/src/components/ui/TurnIndicator.test.jsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import { describe, it, expect } from 'vitest'; +import TurnIndicator from './TurnIndicator'; + +describe('TurnIndicator', () => { + it('renders player avatar with initials', () => { + render(); + expect(screen.getByText('Al')).toBeInTheDocument(); + }); + + it('shows pulse animation when it is my turn', () => { + render(); + const avatar = screen.getByText('Bo'); + expect(avatar).toHaveClass('animate-pulse'); + }); + + it('does not show pulse when not my turn', () => { + render(); + const avatar = screen.getByText('Ch'); + expect(avatar).not.toHaveClass('animate-pulse'); + }); + + it('dims when not active', () => { + render(); + const avatar = screen.getByText('Da'); + expect(avatar).toHaveClass('opacity-50'); + }); + + it('shows timer progress when turnTimer is provided', () => { + render(); + const avatar = screen.getByText('Ev'); + expect(avatar).toHaveAttribute('data-timer', '0.5'); + }); +}); diff --git a/pro/src/components/ui/index.js b/pro/src/components/ui/index.js new file mode 100644 index 0000000..df71883 --- /dev/null +++ b/pro/src/components/ui/index.js @@ -0,0 +1,13 @@ +export { default as SketchButton } from './SketchButton'; +export { default as SketchCard } from './SketchCard'; +export { default as SketchBorder } from './SketchBorder'; +export { default as PlayerBadge } from './PlayerBadge'; +export { default as ModeSelector } from './ModeSelector'; +export { default as LeaveButton } from './LeaveButton'; +export { default as RoomLobby } from './RoomLobby'; +export { sketchPopupClass } from './SketchPopup'; +export { default as GameLayout } from './GameLayout'; +export { default as TurnIndicator } from './TurnIndicator'; +export { default as MatchReport } from './MatchReport'; +export { default as AvatarSelector } from './AvatarSelector'; +export { default as CountdownOverlay } from './CountdownOverlay'; diff --git a/pro/src/context/GameContext.jsx b/pro/src/context/GameContext.jsx index 6d4cf2a..18cee2e 100644 --- a/pro/src/context/GameContext.jsx +++ b/pro/src/context/GameContext.jsx @@ -19,7 +19,11 @@ export const GameProvider = ({ children }) => { const socketRef = useRef(null); useEffect(() => { - const newSocket = io('http://localhost:4000'); + // Use window.location.hostname for host so it works when served from any IP + const host = window.location.hostname || 'localhost'; + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + const port = import.meta.env.VITE_PORT || 4000; + const newSocket = io(`${protocol}//${host}:${port}`); socketRef.current = newSocket; setSocket(newSocket); @@ -49,17 +53,25 @@ export const GameProvider = ({ children }) => { } }, [playerName]); + const roomIdRef = useRef(roomId); + useEffect(() => { + roomIdRef.current = roomId; + }, [roomId]); + + const clearRoomId = (id) => { + if (roomIdRef.current === id) { + setRoomId(null); + } + }; + const value = { playerName, setPlayerName, roomId, setRoomId, - socket + clearRoomId, + socket, }; - return ( - - {children} - - ); + return {children}; }; diff --git a/pro/src/context/GameContext.test.jsx b/pro/src/context/GameContext.test.jsx index bcad5e8..e33f564 100644 --- a/pro/src/context/GameContext.test.jsx +++ b/pro/src/context/GameContext.test.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; -import { describe, it, expect, vi } from 'vitest'; +import { describe, it, expect } from 'vitest'; import { GameProvider, useGameContext } from './GameContext'; const TestComponent = () => { @@ -18,7 +18,7 @@ describe('GameContext', () => { render( - + , ); const nameDisplay = screen.getByTestId('player-name'); diff --git a/pro/src/dab/DabGame.jsx b/pro/src/dab/DabGame.jsx index add60ae..8845e04 100644 --- a/pro/src/dab/DabGame.jsx +++ b/pro/src/dab/DabGame.jsx @@ -1,19 +1,40 @@ import React, { useState, useEffect, useCallback, useRef } from 'react'; import { useGameContext } from '../context/GameContext'; import { TransformWrapper, TransformComponent } from 'react-zoom-pan-pinch'; -import RetroButton from '../components/ui/RetroButton'; +import { SketchButton, SketchCard, sketchPopupClass, GameLayout, AvatarSelector, MatchReport } from '../components/ui'; import useSound from 'use-sound'; import confetti from 'canvas-confetti'; import Swal from 'sweetalert2'; import { useNavigate } from 'react-router-dom'; -import { ArrowLeft, Users, Trophy, SwatchBook, Plus, Minus, RotateCcw } from 'lucide-react'; +import { ArrowLeft, Users, Trophy, SwatchBook, Plus, Minus, RotateCcw, Undo2 } from 'lucide-react'; import logger from '../utils/logger'; -const PLAYER_COLORS = ['#3B82F6', '#EF4444', '#22C55E', '#F97316']; -const PLAYER_TAILWIND = ['blue-500', 'red-500', 'green-500', 'orange-500']; +const PLAYER_COLORS = ['#1a1a2e', '#c73e1d', '#2d4a8f', '#2f5233']; + +const addWobble = (x1, y1, x2, y2, seed = 0) => { + const segments = 8; + const wobbleAmount = 1.5; + const points = []; + + for (let i = 0; i <= segments; i++) { + const t = i / segments; + const x = x1 + (x2 - x1) * t; + const y = y1 + (y2 - y1) * t; + + const offsetX = Math.sin(seed + i * 2.3) * wobbleAmount; + const offsetY = Math.cos(seed + i * 1.7) * wobbleAmount; + + points.push(`${x + offsetX},${y + offsetY}`); + } + + return `M ${points[0]} ${points + .slice(1) + .map((p) => `L ${p}`) + .join(' ')}`; +}; const DabGame = () => { - const { socket, playerName, roomId, setRoomId } = useGameContext(); + const { socket, playerName, roomId, setRoomId, clearRoomId } = useGameContext(); const navigate = useNavigate(); const [players, setPlayers] = useState([]); @@ -29,15 +50,44 @@ const DabGame = () => { const [mode, setMode] = useState('classic'); const [customRows, setCustomRows] = useState(5); const [customCols, setCustomCols] = useState(5); - const [customPlayers, setCustomPlayers] = useState(2); + const [customPlayers] = useState(2); const [myPlayerIndex, setMyPlayerIndex] = useState(-1); const [isPaused, setIsPaused] = useState(false); + const [redoRequest, setRedoRequest] = useState(null); + const [avatar, setAvatar] = useState('🐼'); + const [avatarColor, setAvatarColor] = useState('#1a1a2e'); const [playLine] = useSound('/sounds/move.mp3', { volume: 0.5 }); const [playBox] = useSound('/sounds/win.mp3', { volume: 0.7 }); const reconnectAttempted = useRef(false); + const handleCreateRoom = useCallback(() => { + socket.emit('dab_createRoom', { + mode, + customRows, + customCols, + customPlayers, + playerName, + }); + }, [mode, customRows, customCols, customPlayers, playerName, socket]); + + const handleJoinRoom = useCallback(async () => { + const { value: joinRoomId } = await Swal.fire({ + title: 'Join DAB Room', + input: 'text', + inputPlaceholder: 'Enter Room ID', + showCancelButton: true, + customClass: { popup: sketchPopupClass }, + }); + if (joinRoomId) { + socket.emit('dab_joinRoom', { + roomId: joinRoomId.toUpperCase(), + playerName, + }); + } + }, [socket, playerName]); + useEffect(() => { if (!socket) return; @@ -45,14 +95,12 @@ const DabGame = () => { if (saved && !reconnectAttempted.current) { reconnectAttempted.current = true; const { roomId: savedRoomId, playerId } = JSON.parse(saved); - logger.socket('➡️', 'dab_reconnect', { roomId: savedRoomId, playerId }); socket.emit('dab_reconnect', { roomId: savedRoomId, playerId }); setRoomId(savedRoomId); return; } socket.on('dab_roomInfo', (room) => { - logger.socket('⬅️', 'dab_roomInfo', { roomId: room.id, gameState: room.gameState }); setRoomId(room.id); setPlayers(room.players); setGameState(room.gameState); @@ -66,15 +114,14 @@ const DabGame = () => { setLastMove(room.lastMove); setIsPaused(room.gameState === 'paused'); - const idx = room.players.findIndex(p => p.id === socket.id); + const idx = room.players.findIndex((p) => p.id === socket.id); if (idx !== -1) { setMyPlayerIndex(idx); sessionStorage.setItem('dab_reconnect', JSON.stringify({ roomId: room.id, playerId: room.players[idx].id })); } }); - socket.on('dab_gameStarted', ({ firstTurn }) => { - logger.socket('⬅️', 'dab_gameStarted', { firstTurn }); + socket.on('dab_gameStarted', () => { setGameState('playing'); setIsPaused(false); Swal.fire({ @@ -82,17 +129,28 @@ const DabGame = () => { text: 'Draw lines to claim boxes!', timer: 1500, showConfirmButton: false, - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); }); socket.on('dab_gameRestarted', () => { - logger.socket('⬅️', 'dab_gameRestarted', 'Game restarted'); setGameState('waiting'); setCurrentTurn(0); - setHorizontalLines(rowsArray => Array(rows).fill(null).map(() => Array(cols).fill(null))); - setVerticalLines(rowsArray => Array(rows).fill(null).map(() => Array(cols + 1).fill(null))); - setBoxes(rowsArray => Array(rows).fill(null).map(() => Array(cols).fill(null))); + setHorizontalLines( + Array(rows) + .fill(null) + .map(() => Array(cols).fill(null)), + ); + setVerticalLines( + Array(rows) + .fill(null) + .map(() => Array(cols + 1).fill(null)), + ); + setBoxes( + Array(rows) + .fill(null) + .map(() => Array(cols).fill(null)), + ); setScores(Array(players.length).fill(0)); setLastMove(null); setIsPaused(false); @@ -101,85 +159,88 @@ const DabGame = () => { text: 'New game starting!', timer: 1500, showConfirmButton: false, - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); }); - socket.on('dab_moveResult', ({ lineType, r, c, claimedBoxes, scores: newScores, currentTurn: newTurn, playerIndex: movePlayerIndex }) => { - logger.socket('⬅️', 'dab_moveResult', { claimedBoxes, scores: newScores }); - playLine(); - - setHorizontalLines(prev => { - const copy = prev.map(row => [...row]); - if (lineType === 'h') copy[r][c] = movePlayerIndex; - return copy; - }); - setVerticalLines(prev => { - const copy = prev.map(row => [...row]); - if (lineType === 'v') copy[r][c] = movePlayerIndex; - return copy; - }); - - if (claimedBoxes.length > 0) { - playBox(); - setBoxes(prev => { - const copy = prev.map(row => [...row]); - for (const box of claimedBoxes) { - copy[box.r][box.c] = movePlayerIndex; - } - return copy; - }); - } - - setScores(newScores); - setCurrentTurn(newTurn); - }); + socket.on( + 'dab_moveResult', + ({ lineType, r, c, claimedBoxes, scores: newScores, currentTurn: newTurn, playerIndex: movePlayerIndex }) => { + playLine(); + + setHorizontalLines((prev) => { + const copy = prev.map((row) => [...row]); + if (lineType === 'h') copy[r][c] = movePlayerIndex; + return copy; + }); + setVerticalLines((prev) => { + const copy = prev.map((row) => [...row]); + if (lineType === 'v') copy[r][c] = movePlayerIndex; + return copy; + }); + + if (claimedBoxes.length > 0) { + playBox(); + setBoxes((prev) => { + const copy = prev.map((row) => [...row]); + for (const box of claimedBoxes) { + copy[box.r][box.c] = movePlayerIndex; + } + return copy; + }); + } + + setScores(newScores); + setCurrentTurn(newTurn); + }, + ); socket.on('dab_gameOver', ({ winner, scores: finalScores, winners }) => { - logger.socket('⬅️', 'dab_gameOver', { winner, winners }); setGameState('ended'); setScores(finalScores); sessionStorage.removeItem('dab_reconnect'); confetti({ particleCount: 150, spread: 70, origin: { y: 0.6 } }); - if (winner) { - const winnerName = players.find(p => p.id === winner)?.name || 'Player'; - Swal.fire({ - title: 'Victory!', - text: `${winnerName} wins!`, - icon: 'success', - customClass: { popup: 'glass rounded-3xl paper-font' } - }); - } else { + if (!winner) { Swal.fire({ title: "It's a Tie!", text: 'Multiple players share the top score!', icon: 'info', - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); } }); socket.on('dab_playerLeft', ({ playerId }) => { - logger.socket('⬅️', 'dab_playerLeft', { playerId }); - setPlayers(prev => prev.map(p => p.id === playerId ? { ...p, connected: false } : p)); + setPlayers((prev) => prev.map((p) => (p.id === playerId ? { ...p, connected: false } : p))); + }); + + socket.on('dab_playerReconnected', ({ playerId }) => { + setPlayers((prev) => prev.map((p) => (p.id === playerId ? { ...p, connected: true } : p))); + setIsPaused(false); }); - socket.on('dab_gamePaused', ({ reason }) => { - logger.socket('⬅️', 'dab_gamePaused', { reason }); + socket.on('dab_gamePaused', () => { setIsPaused(true); - Swal.fire({ - title: 'Game Paused', - text: reason, - icon: 'warning', - customClass: { popup: 'glass rounded-3xl paper-font' } - }); }); - socket.on('dab_alert', ({ icon, title, text }) => { - logger.socket('⬅️', 'dab_alert', { icon, title, text }); - Swal.fire({ icon, title, text, customClass: { popup: 'glass rounded-3xl paper-font' } }); + socket.on('dab_redoRequested', ({ requesterId }) => { + setRedoRequest(requesterId); + }); + + socket.on('dab_redoCancelled', () => { + setRedoRequest(null); + }); + + socket.on('dab_moveUndone', ({ horizontalLines: h, verticalLines: v, boxes: b, scores: s, currentTurn: t }) => { + setHorizontalLines(h); + setVerticalLines(v); + setBoxes(b); + setScores(s); + setCurrentTurn(t); + setLastMove(null); + setRedoRequest(null); }); return () => { @@ -189,330 +250,552 @@ const DabGame = () => { socket.off('dab_moveResult'); socket.off('dab_gameOver'); socket.off('dab_playerLeft'); + socket.off('dab_playerReconnected'); socket.off('dab_gamePaused'); - socket.off('dab_alert'); + socket.off('dab_redoRequested'); + socket.off('dab_redoCancelled'); + socket.off('dab_moveUndone'); }; - }, [socket, players, setRoomId, playLine, playBox]); - - const handleCreateRoom = () => { - let r = rows, c = cols, maxP = customPlayers; - if (mode === 'custom') { - r = customRows; - c = customCols; - maxP = customPlayers; - } - logger.socket('➡️', 'dab_createRoom', { mode, customRows: r, customCols: c, customPlayers: maxP, playerName }); - socket.emit('dab_createRoom', { mode, customRows: r, customCols: c, customPlayers: maxP, playerName }); + }, [socket]); + + const handleLineClick = (lineType, r, c) => { + if (gameState !== 'playing') return; + if (isPaused) return; + if (myPlayerIndex !== currentTurn) return; + + const arr = lineType === 'h' ? horizontalLines : verticalLines; + if (arr[r]?.[c] !== null) return; + + socket.emit('dab_makeMove', { roomId, lineType, r, c }); + setLastMove({ lineType, r, c }); }; - const handleJoinRoom = async () => { - const { value: joinRoomId } = await Swal.fire({ - title: 'Join Room', - input: 'text', - inputPlaceholder: 'Enter Room ID', + const handleLeaveRoom = () => { + Swal.fire({ + title: 'Leave Game?', + text: 'Are you sure you want to leave?', showCancelButton: true, - customClass: { popup: 'glass rounded-3xl paper-font' } + confirmButtonText: 'Yes, Leave', + cancelButtonText: 'Stay', + customClass: { popup: sketchPopupClass }, + }).then((result) => { + if (result.isConfirmed) { + socket.emit('dab_leaveRoom', roomId); + clearRoomId(); + sessionStorage.removeItem('dab_reconnect'); + navigate('/dab'); + } }); - if (joinRoomId) { - logger.socket('➡️', 'dab_joinRoom', { roomId: joinRoomId.toUpperCase(), playerName }); - socket.emit('dab_joinRoom', { roomId: joinRoomId.toUpperCase(), playerName }); - } }; - const handleLineClick = useCallback((lineType, r, c, e) => { - e.stopPropagation(); - logger.socket('➡️', 'dab_makeMove', { roomId, lineType, r, c, gameState, currentTurn, myPlayerIndex }); - if (gameState !== 'playing' || isPaused) return; - if (currentTurn !== myPlayerIndex) return; - - socket.emit('dab_makeMove', { roomId, lineType, r, c }); - }, [gameState, isPaused, currentTurn, myPlayerIndex, roomId, socket]); + const handleStartGame = () => { + const sizeMap = { classic: 9, extended: 14, marathon: 19 }; + const gameRows = mode === 'custom' ? customRows : sizeMap[mode] || 9; + const gameCols = mode === 'custom' ? customCols : sizeMap[mode] || 9; + socket.emit('dab_startGame', { roomId, rows: gameRows, cols: gameCols }); + }; const handleRestartGame = () => { - logger.socket('➡️', 'dab_restartGame', { roomId, playerId: socket.id }); socket.emit('dab_restartGame', roomId); }; - const handleLeaveRoom = () => { - sessionStorage.removeItem('dab_reconnect'); - setRoomId(null); - setPlayers([]); - setGameState('waiting'); - setBoxes([]); - setHorizontalLines([]); - setVerticalLines([]); - setScores([]); - setMyPlayerIndex(-1); - setIsPaused(false); - }; - - const spacing = 40; + const spacing = 60; const dotRadius = 4; const lineWidth = 3; - const hitLineWidth = 16; + const hitLineWidth = 20; + const svgWidth = cols * spacing; const svgHeight = rows * spacing; - return ( -
- navigate('/')} - variant="secondary" - className="absolute top-2 sm:top-8 left-2 sm:left-8 flex items-center gap-1 sm:gap-2 text-xs sm:text-base px-2 sm:px-4" - > - - Back - - -

Dots & Boxes

- - {!roomId ? ( -
-
-
- - + if (!roomId) { + return ( +
+

Dots & Boxes

+ + + + +

Game Mode

+
+ setMode('classic')} + className={mode === 'classic' ? 'flex-1 bg-ink text-white' : 'flex-1'} + > + Classic (9×9) + + setMode('extended')} + className={mode === 'extended' ? 'flex-1 bg-ink text-white' : 'flex-1'} + > + Extended (14×14) + + setMode('marathon')} + className={mode === 'marathon' ? 'flex-1 bg-ink text-white' : 'flex-1'} + > + Marathon (19×19) + +
+ setMode('custom')} + className={`w-full mb-4 ${mode === 'custom' ? 'bg-ink text-white' : ''}`} + > + Custom Size + + {mode === 'custom' && ( +
+
+ + setCustomRows(Number(e.target.value))} + className="w-full" + /> +
+
+ + setCustomCols(Number(e.target.value))} + className="w-full" + /> +
+ )} +
+ + Create Room + + + Join Room + +
+
+
+ ); + } - {mode === 'custom' && ( -
-
-
- - setCustomRows(Math.max(1, Math.min(30, parseInt(e.target.value) || 1)))} - className="w-full bg-white/50 border border-gray-300 rounded-lg px-3 py-2 paper-font" - /> -
-
- - setCustomCols(Math.max(1, Math.min(30, parseInt(e.target.value) || 1)))} - className="w-full bg-white/50 border border-gray-300 rounded-lg px-3 py-2 paper-font" - /> -
+ return ( + +
+ {gameState === 'waiting' && ( +
+
+
+

+ Dots + & + Boxes +

+ +
+ +
+
+ + Room Code:
-
- - setCustomPlayers(Math.max(2, Math.min(4, parseInt(e.target.value) || 2)))} - className="w-full bg-white/50 border border-gray-300 rounded-lg px-3 py-2 paper-font" - /> +
{roomId}
+
+ +
+

+ + Players ({players.length}) +

+
+ {players.map((p, idx) => ( +
+ {p.name} {!p.connected && '(disconnected)'} +
+ ))}
- )} -
- Create Room - Join Room +
-
- ) : ( -
-
-
-
- - Room: - {roomId} -
- - Leave - + )} + + {(gameState === 'playing' || gameState === 'ended') && ( +
+
+
-
- {players.map((p, i) => ( -
-
- {p.name.length > 10 ? p.name.slice(0, 10) + '...' : p.name} - {scores[i] || 0} - {!p.connected && (DC)} - {i === currentTurn && gameState === 'playing' && !isPaused && p.connected && ( -
- )} +
+
+
+

+ + Scoreboard +

+
+ {players.map((p, idx) => ( +
+
+
+ + {p.name} + {idx === myPlayerIndex && ' (You)'} + +
+ {scores[idx] || 0} +
+ ))} +
- ))} -
- {gameState === 'playing' && !isPaused && ( -
- {currentTurn === myPlayerIndex ? ( - Your turn! - ) : ( - Waiting for {players[currentTurn]?.name}... + {redoRequest && ( +
+

+ {players.find((p) => p.id === redoRequest)?.name} wants to undo + the last move +

+ {myPlayerIndex === currentTurn && ( +
+ + +
+ )} +
)} -
- )} - {isPaused && ( -
- Game Paused — Waiting for players to reconnect -
- )} - {gameState === 'ended' && ( -
- Game Over! -
- )} - {gameState === 'ended' && ( - - Play Again - - )} -
-
- - {({ zoomIn, zoomOut, resetTransform }) => ( - <> -
- - - -
- -
- - {boxes.map((row, r) => - row.map((boxOwner, c) => - boxOwner !== null ? ( - - ) : null - ) + {gameState === 'playing' && ( +
+ {myPlayerIndex === currentTurn ? ( +
+
+

Your Turn!

+

Draw a line

+
+ ) : ( +
+
+

+ Waiting for {players[currentTurn]?.name} + ... +

+ {lastMove && myPlayerIndex === (currentTurn + 1) % players.length && ( + + )} +
)} +
+ )} - {Array.from({ length: rows + 1 }, (_, r) => - Array.from({ length: cols }, (_, c) => { - const owner = horizontalLines[r]?.[c]; - return ( - - {owner !== null && ( - - )} - handleLineClick('h', r, c, e)} - /> - - ); - }) - )} + {isPaused && ( +
+

Game Paused

+

+ Waiting for players to reconnect +

+
+ )} - {Array.from({ length: rows }, (_, r) => - Array.from({ length: cols + 1 }, (_, c) => { - const owner = verticalLines[r]?.[c]; - return ( - - {owner !== null && ( - - )} - handleLineClick('v', r, c, e)} - /> - - ); - }) - )} + {gameState === 'ended' && ( +
+
+ +
+

Game Over!

+ +
+ )} +
- {Array.from({ length: rows + 1 }, (_, r) => - Array.from({ length: cols + 1 }, (_, c) => ( - - )) - )} - +
+
+ {svgWidth > 0 && svgHeight > 0 ? ( + + {({ zoomIn, zoomOut, resetTransform }) => ( + <> +
+ + + +
+ +
+ + + + + + + + + + + {boxes.map((row, r) => + row.map((boxOwner, c) => + boxOwner !== null ? ( + + + + + ) : null, + ), + )} + + {Array.from({ length: rows + 1 }, (_, r) => + Array.from({ length: cols }, (_, c) => { + const owner = horizontalLines[r]?.[c]; + const seed = r * 100 + c; + return ( + + {owner !== null && ( + + )} + { + e.stopPropagation(); + handleLineClick('h', r, c); + }} + /> + + ); + }), + )} + + {Array.from({ length: rows }, (_, r) => + Array.from({ length: cols + 1 }, (_, c) => { + const owner = verticalLines[r]?.[c]; + const seed = r * 100 + c + 1000; + return ( + + {owner !== null && ( + + )} + { + e.stopPropagation(); + handleLineClick('v', r, c); + }} + /> + + ); + }), + )} + + {Array.from({ length: rows + 1 }, (_, r) => + Array.from({ length: cols + 1 }, (_, c) => { + const seed = r * 1000 + c; + const offsetX = Math.sin(seed * 0.1) * 0.5; + const offsetY = Math.cos(seed * 0.1) * 0.5; + return ( + + ); + }), + )} + +
+
+ + )} +
+ ) : ( +
+

Loading...

+
+ )}
- - - )} - +
+
-
- )} -
+ )} +
+ ); }; diff --git a/pro/src/dab/DabGame.test.jsx b/pro/src/dab/DabGame.test.jsx new file mode 100644 index 0000000..20baa4f --- /dev/null +++ b/pro/src/dab/DabGame.test.jsx @@ -0,0 +1,228 @@ +import React from 'react'; +import { render, screen, fireEvent, act } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import DabGame from './DabGame'; +import { GameProvider } from '../context/GameContext'; +import { BrowserRouter } from 'react-router-dom'; + +const mockSocket = { + id: 'p1', + on: vi.fn(), + off: vi.fn(), + emit: vi.fn(), + disconnect: vi.fn(), +}; + +vi.mock('socket.io-client', () => ({ default: () => mockSocket })); +vi.mock('use-sound', () => ({ default: () => [vi.fn()] })); +vi.mock('canvas-confetti', () => ({ default: vi.fn() })); +vi.mock('sweetalert2', () => ({ default: { fire: vi.fn().mockResolvedValue({ isConfirmed: true }) } })); +vi.mock('react-zoom-pan-pinch', () => ({ + TransformWrapper: ({ children }) => children({ zoomIn: vi.fn(), zoomOut: vi.fn(), resetTransform: vi.fn() }), + TransformComponent: ({ children }) => <>{children}, +})); + +const Wrapper = ({ children }) => ( + + {children} + +); + +const findEventCb = (event) => { + const call = mockSocket.on.mock.calls.find((c) => c[0] === event); + return call?.[1]; +}; + +const makePlayingRoomInfo = (overrides = {}) => ({ + id: 'DAB01', + creator: 'p1', + players: [ + { id: 'p1', name: 'Alice', connected: true }, + { id: 'p2', name: 'Bob', connected: true }, + ], + gameState: 'playing', + currentTurn: 0, + rows: 9, + cols: 9, + horizontalLines: Array(10) + .fill(null) + .map(() => Array(9).fill(null)), + verticalLines: Array(9) + .fill(null) + .map(() => Array(10).fill(null)), + boxes: Array(9) + .fill(null) + .map(() => Array(9).fill(null)), + scores: [0, 0], + lastMove: null, + mode: 'classic', + ...overrides, +}); + +describe('DabGame', () => { + beforeEach(() => { + vi.clearAllMocks(); + sessionStorage.clear(); + }); + + describe('Lobby - No Room', () => { + it('shows Create Room and Join Room buttons', () => { + render(, { wrapper: Wrapper }); + expect(screen.getByText('Create Room')).toBeTruthy(); + expect(screen.getByText('Join Room')).toBeTruthy(); + }); + + it('emits dab_createRoom when Create Room is clicked', async () => { + render(, { wrapper: Wrapper }); + await act(async () => { + fireEvent.click(screen.getByText('Create Room')); + }); + expect(mockSocket.emit).toHaveBeenCalledWith('dab_createRoom', expect.objectContaining({ mode: 'classic' })); + }); + }); + + describe('Mode Selection', () => { + it('shows Classic, Extended, and Marathon mode buttons', () => { + render(, { wrapper: Wrapper }); + expect(screen.getByText('Classic (9×9)')).toBeTruthy(); + expect(screen.getByText('Extended (14×14)')).toBeTruthy(); + expect(screen.getByText('Marathon (19×19)')).toBeTruthy(); + }); + + it('switches mode when Extended is clicked', async () => { + render(, { wrapper: Wrapper }); + await act(async () => { + fireEvent.click(screen.getByText('Extended (14×14)')); + }); + await act(async () => { + fireEvent.click(screen.getByText('Create Room')); + }); + expect(mockSocket.emit).toHaveBeenCalledWith('dab_createRoom', expect.objectContaining({ mode: 'extended' })); + }); + }); + + describe('Playing State', () => { + it('shows player scores when playing', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('dab_roomInfo'); + await act(async () => { + cb(makePlayingRoomInfo()); + }); + + expect(screen.getByText(/Alice/)).toBeTruthy(); + expect(screen.getByText(/Bob/)).toBeTruthy(); + }); + + it('shows "Your Turn!" when it is my turn', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('dab_roomInfo'); + await act(async () => { + cb(makePlayingRoomInfo({ currentTurn: 0 })); + }); + + expect(screen.getByText('Your Turn!')).toBeTruthy(); + }); + }); + + describe('Avatar Selector', () => { + it('shows avatar picker in the lobby', () => { + render(, { wrapper: Wrapper }); + expect(screen.getByText('🐼')).toBeTruthy(); + expect(screen.getByText('🦊')).toBeTruthy(); + }); + }); + + describe('Game Over', () => { + it('shows Game Over text and Play Again button', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('dab_roomInfo'); + await act(async () => { + cb(makePlayingRoomInfo()); + }); + + const gameOverCb = findEventCb('dab_gameOver'); + await act(async () => { + gameOverCb({ winner: 'p1', scores: [5, 3], winners: ['p1'] }); + }); + + expect(screen.getByText(/Play Again/)).toBeTruthy(); + }); + + it('emits dab_restartGame when Play Again is clicked', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('dab_roomInfo'); + await act(async () => { + cb(makePlayingRoomInfo()); + }); + + const gameOverCb = findEventCb('dab_gameOver'); + await act(async () => { + gameOverCb({ winner: 'p1', scores: [5, 3], winners: ['p1'] }); + }); + + const playAgainBtn = screen.getByText('Play Again'); + await act(async () => { + fireEvent.click(playAgainBtn); + }); + + expect(mockSocket.emit).toHaveBeenCalledWith('dab_restartGame', expect.any(String)); + }); + }); + + describe('Redo Flow', () => { + it('shows redo request when dab_redoRequested is received', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('dab_roomInfo'); + await act(async () => { + cb(makePlayingRoomInfo({ currentTurn: 0 })); + }); + + const redoCb = findEventCb('dab_redoRequested'); + await act(async () => { + redoCb({ requesterId: 'p2' }); + }); + + expect(screen.getByText(/wants to undo/)).toBeTruthy(); + }); + + it('shows Allow and Deny buttons when I am the current turn', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('dab_roomInfo'); + await act(async () => { + cb(makePlayingRoomInfo({ currentTurn: 0 })); + }); + + const redoCb = findEventCb('dab_redoRequested'); + await act(async () => { + redoCb({ requesterId: 'p2' }); + }); + + expect(screen.getByText('Allow')).toBeTruthy(); + expect(screen.getByText('Deny')).toBeTruthy(); + }); + }); + + describe('Pause', () => { + it('shows Game Paused message when dab_gamePaused is received', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('dab_roomInfo'); + await act(async () => { + cb(makePlayingRoomInfo()); + }); + + const pauseCb = findEventCb('dab_gamePaused'); + await act(async () => { + pauseCb(); + }); + + expect(screen.getByText(/Game Paused/)).toBeTruthy(); + }); + }); +}); diff --git a/pro/src/hooks/useGameHandlers.js b/pro/src/hooks/useGameHandlers.js new file mode 100644 index 0000000..dea1ce2 --- /dev/null +++ b/pro/src/hooks/useGameHandlers.js @@ -0,0 +1,57 @@ +import { useCallback } from 'react'; +import { useNavigate } from 'react-router-dom'; +import Swal from 'sweetalert2'; +import { sketchPopupClass } from '../components/ui'; + +const useGameHandlers = (socket, roomId, gamePrefix, options = {}) => { + const navigate = useNavigate(); + const { onLeave, softLeave = false } = options; + + const handleCreateRoom = useCallback( + (options) => { + if (!socket) return; + socket.emit(`${gamePrefix}_createRoom`, options); + }, + [socket, gamePrefix], + ); + + const handleJoinRoom = useCallback( + (options) => { + if (!socket) return; + socket.emit(`${gamePrefix}_joinRoom`, options); + }, + [socket, gamePrefix], + ); + + const handleStartGame = useCallback(() => { + if (!socket) return; + socket.emit(`${gamePrefix}_startGame`, roomId); + }, [socket, gamePrefix, roomId]); + + const handleLeaveRoom = useCallback(async () => { + const result = await Swal.fire({ + title: 'Leave Game?', + text: 'Your progress will be lost.', + icon: 'warning', + showCancelButton: true, + confirmButtonText: 'Leave', + cancelButtonText: 'Stay', + customClass: { popup: sketchPopupClass }, + }); + if (!result.isConfirmed) return; + + if (softLeave && roomId) { + socket?.emit(`${gamePrefix}_leaveRoom`, roomId); + } + + onLeave?.(); + if (!softLeave) { + socket?.disconnect(); + } + navigate('/'); + }, [socket, navigate, roomId, gamePrefix, onLeave, softLeave]); + + return { handleCreateRoom, handleJoinRoom, handleStartGame, handleLeaveRoom }; +}; + +export default useGameHandlers; diff --git a/pro/src/hooks/useGameHandlers.test.js b/pro/src/hooks/useGameHandlers.test.js new file mode 100644 index 0000000..1c3be0b --- /dev/null +++ b/pro/src/hooks/useGameHandlers.test.js @@ -0,0 +1,73 @@ +import { renderHook, act } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import useGameHandlers from './useGameHandlers'; + +const mockSocket = { + emit: vi.fn(), + disconnect: vi.fn(), +}; + +const mockNavigate = vi.fn(); + +vi.mock('react-router-dom', () => ({ + useNavigate: () => mockNavigate, +})); + +vi.mock('sweetalert2', () => ({ + default: { + fire: vi.fn().mockResolvedValue({ isConfirmed: true }), + }, +})); + +describe('useGameHandlers', () => { + beforeEach(() => { + vi.clearAllMocks(); + sessionStorage.clear(); + }); + + it('handleCreateRoom emits _createRoom with options', () => { + const { result } = renderHook(() => useGameHandlers(mockSocket, 'room1', 'ttt')); + act(() => result.current.handleCreateRoom({ playerName: 'Alice' })); + expect(mockSocket.emit).toHaveBeenCalledWith('ttt_createRoom', { playerName: 'Alice' }); + }); + + it('handleJoinRoom emits _joinRoom with options', () => { + const { result } = renderHook(() => useGameHandlers(mockSocket, 'room1', 'ttt')); + act(() => result.current.handleJoinRoom({ roomId: 'ABC', playerName: 'Bob' })); + expect(mockSocket.emit).toHaveBeenCalledWith('ttt_joinRoom', { roomId: 'ABC', playerName: 'Bob' }); + }); + + it('handleStartGame emits _startGame with roomId', () => { + const { result } = renderHook(() => useGameHandlers(mockSocket, 'room1', 'ttt')); + act(() => result.current.handleStartGame()); + expect(mockSocket.emit).toHaveBeenCalledWith('ttt_startGame', 'room1'); + }); + + it('handleLeaveRoom shows confirmation and disconnects on confirm', async () => { + const { result } = renderHook(() => useGameHandlers(mockSocket, 'room1', 'ttt')); + await act(async () => { + await result.current.handleLeaveRoom(); + }); + expect(mockSocket.disconnect).toHaveBeenCalled(); + expect(mockNavigate).toHaveBeenCalledWith('/'); + }); + + it('handleLeaveRoom does nothing when user cancels', async () => { + const Swal = (await import('sweetalert2')).default; + Swal.fire.mockResolvedValueOnce({ isConfirmed: false }); + + const { result } = renderHook(() => useGameHandlers(mockSocket, 'room1', 'ttt')); + await act(async () => { + await result.current.handleLeaveRoom(); + }); + expect(mockSocket.disconnect).not.toHaveBeenCalled(); + expect(mockNavigate).not.toHaveBeenCalled(); + }); + + it('does not emit when socket is null', () => { + const { result } = renderHook(() => useGameHandlers(null, 'room1', 'ttt')); + act(() => result.current.handleCreateRoom({ playerName: 'Alice' })); + act(() => result.current.handleStartGame()); + expect(mockSocket.emit).not.toHaveBeenCalled(); + }); +}); diff --git a/pro/src/hooks/usePlayerAvatars.js b/pro/src/hooks/usePlayerAvatars.js new file mode 100644 index 0000000..70eb79a --- /dev/null +++ b/pro/src/hooks/usePlayerAvatars.js @@ -0,0 +1,24 @@ +import { useState, useEffect } from 'react'; + +const STORAGE_KEY = 'player_avatar'; + +const usePlayerAvatars = () => { + const saved = (() => { + try { + return JSON.parse(sessionStorage.getItem(STORAGE_KEY)) || {}; + } catch { + return {}; + } + })(); + + const [avatar, setAvatar] = useState(saved.avatar || '🐼'); + const [color, setColor] = useState(saved.color || '#2a2a3e'); + + useEffect(() => { + sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ avatar, color })); + }, [avatar, color]); + + return { avatar, color, setAvatar, setColor }; +}; + +export default usePlayerAvatars; diff --git a/pro/src/hooks/usePlayerAvatars.test.js b/pro/src/hooks/usePlayerAvatars.test.js new file mode 100644 index 0000000..a0e5774 --- /dev/null +++ b/pro/src/hooks/usePlayerAvatars.test.js @@ -0,0 +1,48 @@ +import { renderHook, act } from '@testing-library/react'; +import { describe, it, expect, beforeEach } from 'vitest'; +import usePlayerAvatars from './usePlayerAvatars'; + +describe('usePlayerAvatars', () => { + beforeEach(() => { + sessionStorage.clear(); + }); + + it('returns default avatar and color on first use', () => { + const { result } = renderHook(() => usePlayerAvatars()); + expect(result.current.avatar).toBe('🐼'); + expect(result.current.color).toBe('#2a2a3e'); + }); + + it('persists avatar to sessionStorage when setAvatar is called', () => { + const { result } = renderHook(() => usePlayerAvatars()); + act(() => { + result.current.setAvatar('🦊'); + }); + expect(result.current.avatar).toBe('🦊'); + const stored = JSON.parse(sessionStorage.getItem('player_avatar')); + expect(stored.avatar).toBe('🦊'); + }); + + it('persists color to sessionStorage when setColor is called', () => { + const { result } = renderHook(() => usePlayerAvatars()); + act(() => { + result.current.setColor('#ff0000'); + }); + expect(result.current.color).toBe('#ff0000'); + const stored = JSON.parse(sessionStorage.getItem('player_avatar')); + expect(stored.color).toBe('#ff0000'); + }); + + it('restores avatar and color from sessionStorage on mount', () => { + sessionStorage.setItem('player_avatar', JSON.stringify({ avatar: '🐯', color: '#123456' })); + const { result } = renderHook(() => usePlayerAvatars()); + expect(result.current.avatar).toBe('🐯'); + expect(result.current.color).toBe('#123456'); + }); + + it('exposes setAvatar and setColor functions', () => { + const { result } = renderHook(() => usePlayerAvatars()); + expect(typeof result.current.setAvatar).toBe('function'); + expect(typeof result.current.setColor).toBe('function'); + }); +}); diff --git a/pro/src/hooks/useTurnTimer.js b/pro/src/hooks/useTurnTimer.js new file mode 100644 index 0000000..9781ec4 --- /dev/null +++ b/pro/src/hooks/useTurnTimer.js @@ -0,0 +1,29 @@ +import { useState, useEffect, useRef } from 'react'; + +const useTurnTimer = (isMyTurn, duration = 30, onExpire) => { + const [timeLeft, setTimeLeft] = useState(duration); + const expireRef = useRef(onExpire); + expireRef.current = onExpire; + + useEffect(() => { + setTimeLeft(duration); + if (!isMyTurn) return; + + const interval = setInterval(() => { + setTimeLeft((prev) => { + if (prev <= 1) { + clearInterval(interval); + expireRef.current?.(); + return 0; + } + return prev - 1; + }); + }, 1000); + + return () => clearInterval(interval); + }, [isMyTurn, duration]); + + return timeLeft; +}; + +export default useTurnTimer; diff --git a/pro/src/hooks/useTurnTimer.test.js b/pro/src/hooks/useTurnTimer.test.js new file mode 100644 index 0000000..e3eb909 --- /dev/null +++ b/pro/src/hooks/useTurnTimer.test.js @@ -0,0 +1,61 @@ +import { renderHook, act } from '@testing-library/react'; +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import useTurnTimer from './useTurnTimer'; + +describe('useTurnTimer', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + afterEach(() => { + vi.useRealTimers(); + }); + + it('returns full duration initially when isMyTurn is true', () => { + const { result } = renderHook(() => useTurnTimer(true, 30, vi.fn())); + expect(result.current).toBe(30); + }); + + it('returns full duration when isMyTurn is false', () => { + const { result } = renderHook(() => useTurnTimer(false, 30, vi.fn())); + expect(result.current).toBe(30); + }); + + it('counts down each second when isMyTurn is true', () => { + const { result } = renderHook(() => useTurnTimer(true, 30, vi.fn())); + act(() => { + vi.advanceTimersByTime(3000); + }); + expect(result.current).toBe(27); + }); + + it('does not count down when isMyTurn is false', () => { + const { result } = renderHook(() => useTurnTimer(false, 30, vi.fn())); + act(() => { + vi.advanceTimersByTime(5000); + }); + expect(result.current).toBe(30); + }); + + it('calls onExpire when timer reaches 0', () => { + const onExpire = vi.fn(); + renderHook(() => useTurnTimer(true, 3, onExpire)); + act(() => { + vi.advanceTimersByTime(3000); + }); + expect(onExpire).toHaveBeenCalledTimes(1); + }); + + it('resets timer when isMyTurn changes to true', () => { + const { result, rerender } = renderHook(({ isMyTurn }) => useTurnTimer(isMyTurn, 10, vi.fn()), { + initialProps: { isMyTurn: true }, + }); + act(() => { + vi.advanceTimersByTime(4000); + }); + expect(result.current).toBe(6); + + rerender({ isMyTurn: false }); + rerender({ isMyTurn: true }); + expect(result.current).toBe(10); + }); +}); diff --git a/pro/src/index.css b/pro/src/index.css index eb99b9a..83d0607 100644 --- a/pro/src/index.css +++ b/pro/src/index.css @@ -1,4 +1,4 @@ -@import "tailwindcss"; +@import 'tailwindcss'; @theme { --font-hand-drawn: 'Permanent Marker', cursive; @@ -13,6 +13,180 @@ font-family: var(--font-paper); } +.font-sketch { + font-family: 'Caveat', cursive; + letter-spacing: 0.5px; +} + +.font-handwriting { + font-family: 'Patrick Hand', cursive; +} + +.text-ink { + color: #2a2a3e; +} + +.bg-paper { + background-color: #f5f1e8; + background-image: repeating-linear-gradient( + 0deg, + transparent, + transparent 30px, + rgba(139, 99, 76, 0.05) 30px, + rgba(139, 99, 76, 0.05) 31px + ); + position: relative; +} + +.bg-paper::before { + content: ''; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.03'/%3E%3C/svg%3E"); + pointer-events: none; + z-index: 0; +} + +.sketch-card { + background: #fffef9; + border: 2px solid #2a2a3e; + border-radius: 3px; + box-shadow: + 3px 3px 0px rgba(0, 0, 0, 0.1), + inset 0 0 0 1px rgba(255, 255, 255, 0.5); + position: relative; + transform: rotate(-0.5deg); +} + +.sketch-card::before { + content: ''; + position: absolute; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + border: 2px solid #2a2a3e; + border-radius: 3px; + opacity: 0.3; + transform: translate(1px, 1px); + pointer-events: none; +} + +.sketch-border { + border: 2px dashed #8b7355; + border-radius: 2px; + background: rgba(255, 254, 249, 0.6); + padding: 1rem; +} + +.sketch-button { + font-family: 'Patrick Hand', cursive; + background: #fffef9; + border: 2px solid #2a2a3e; + padding: 0.5rem 1rem; + border-radius: 2px; + cursor: pointer; + position: relative; + transform: rotate(-0.3deg); + transition: all 0.2s; + box-shadow: 2px 2px 0px rgba(0, 0, 0, 0.2); +} + +.sketch-button:hover { + transform: rotate(0deg) translateY(-2px); + box-shadow: 3px 3px 0px rgba(0, 0, 0, 0.2); +} + +.sketch-button:active { + transform: rotate(0deg) translateY(0); + box-shadow: 1px 1px 0px rgba(0, 0, 0, 0.2); +} + +.player-badge { + display: inline-block; + padding: 0.25rem 0.75rem; + border: 2px solid currentColor; + border-radius: 20px; + font-family: 'Patrick Hand', cursive; + transform: rotate(-1deg); + position: relative; +} + +.player-badge::after { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border: 2px solid currentColor; + border-radius: 20px; + opacity: 0.3; + transform: translate(1px, 1px); +} + +.sketch-popup { + font-family: 'Patrick Hand', cursive !important; + background: #fffef9 !important; + border: 3px solid #2a2a3e !important; + border-radius: 5px !important; +} + +.sketch-dot { + animation: sketch-wiggle 3s ease-in-out infinite; +} + +@keyframes sketch-wiggle { + 0%, + 100% { + transform: rotate(0deg) translateY(0); + } + 25% { + transform: rotate(0.5deg) translateY(-1px); + } + 75% { + transform: rotate(-0.5deg) translateY(1px); + } +} + +@keyframes wiggle { + 0%, + 100% { + transform: rotate(-1deg); + } + 50% { + transform: rotate(1deg); + } +} + +@keyframes pencil-scribble { + 0% { + filter: brightness(1); + } + 50% { + filter: brightness(1.2) contrast(1.1); + } + 100% { + filter: brightness(1); + } +} + +@keyframes screen-shake { + 0%, + 100% { + transform: translate(0); + } + 25% { + transform: translate(-2px, 2px); + } + 75% { + transform: translate(2px, -2px); + } +} + .glass { background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(10px); @@ -21,22 +195,10 @@ } body { - background: - linear-gradient(rgba(255,255,255,0.9), rgba(255,255,255,0.9)), - repeating-linear-gradient( - 0deg, - transparent, - transparent 19px, - #e5e7eb 19px, - #e5e7eb 20px - ), - repeating-linear-gradient( - 90deg, - transparent, - transparent 19px, - #e5e7eb 19px, - #e5e7eb 20px - ); + background: + linear-gradient(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.9)), + repeating-linear-gradient(0deg, transparent, transparent 19px, #e5e7eb 19px, #e5e7eb 20px), + repeating-linear-gradient(90deg, transparent, transparent 19px, #e5e7eb 19px, #e5e7eb 20px); background-size: 20px 20px; min-height: 100vh; -} \ No newline at end of file +} diff --git a/pro/src/index.jsx b/pro/src/index.jsx index dd56628..ede130f 100644 --- a/pro/src/index.jsx +++ b/pro/src/index.jsx @@ -10,5 +10,5 @@ root.render( - + , ); diff --git a/pro/src/test-setup.js b/pro/src/test-setup.js index 7b0828b..66c85ee 100644 --- a/pro/src/test-setup.js +++ b/pro/src/test-setup.js @@ -1 +1,37 @@ import '@testing-library/jest-dom'; + +Object.defineProperty(window, 'localStorage', { + value: (() => { + let store = {}; + return { + getItem: (key) => store[key] ?? null, + setItem: (key, value) => { + store[key] = String(value); + }, + removeItem: (key) => { + delete store[key]; + }, + clear: () => { + store = {}; + }, + }; + })(), +}); + +Object.defineProperty(window, 'sessionStorage', { + value: (() => { + let store = {}; + return { + getItem: (key) => store[key] ?? null, + setItem: (key, value) => { + store[key] = String(value); + }, + removeItem: (key) => { + delete store[key]; + }, + clear: () => { + store = {}; + }, + }; + })(), +}); diff --git a/pro/src/tictactoe/TicTacToe.jsx b/pro/src/tictactoe/TicTacToe.jsx index d5c8539..8b17ec4 100644 --- a/pro/src/tictactoe/TicTacToe.jsx +++ b/pro/src/tictactoe/TicTacToe.jsx @@ -1,21 +1,34 @@ import React, { useState, useEffect } from 'react'; import { useGameContext } from '../context/GameContext'; -import RetroButton from '../components/ui/RetroButton'; +import { + SketchButton, + SketchCard, + sketchPopupClass, + GameLayout, + RoomLobby, + MatchReport, + AvatarSelector, + LeaveButton, +} from '../components/ui'; import useSound from 'use-sound'; import confetti from 'canvas-confetti'; import Swal from 'sweetalert2'; import { useNavigate } from 'react-router-dom'; -import { ArrowLeft, Users, Trophy, SwatchBook } from 'lucide-react'; +import { Trophy } from 'lucide-react'; import logger from '../utils/logger'; +const PLAYER_COLORS = ['#2a2a3e', '#c73e1d', '#2d4a8f', '#2f5233']; + const TicTacToe = () => { - const { socket, playerName, roomId, setRoomId } = useGameContext(); + const { socket, playerName, roomId, setRoomId, clearRoomId } = useGameContext(); const [board, setBoard] = useState(Array(9).fill(null)); const [players, setPlayers] = useState([]); const [currentTurn, setCurrentTurn] = useState(null); const [gameState, setGameState] = useState('waiting'); const [winningCells, setWinningCells] = useState([]); - const [mySymbol, setMySymbol] = useState(null); + const [myPlayerIndex, setMyPlayerIndex] = useState(-1); + const [avatar, setAvatar] = useState('🐼'); + const [avatarColor, setAvatarColor] = useState('#2a2a3e'); const navigate = useNavigate(); const [playMove] = useSound('/sounds/move.mp3', { volume: 0.5 }); @@ -24,105 +37,81 @@ const TicTacToe = () => { useEffect(() => { if (!socket) return; - logger.info('TTT', `Socket connected: ${socket.id}`); + const saved = sessionStorage.getItem('ttt_reconnect'); + if (saved && !roomId) { + const { roomId: savedRoomId, playerId } = JSON.parse(saved); + socket.emit('ttt_reconnect', { roomId: savedRoomId, playerId }); + } socket.on('ttt_roomInfo', ({ id, players, gameState, currentTurn, board }) => { - logger.socket('⬅️', 'ttt_roomInfo', { roomId: id, gameState }); setRoomId(id); setPlayers(players); setGameState(gameState); setCurrentTurn(currentTurn); if (board) setBoard(board); - - const playerIndex = players.findIndex(p => p.id === socket.id); + + const playerIndex = players.findIndex((p) => p.id === socket.id); if (playerIndex !== -1) { - setMySymbol(playerIndex === 0 ? 'X' : 'O'); + setMyPlayerIndex(playerIndex); + sessionStorage.setItem('ttt_reconnect', JSON.stringify({ roomId: id, playerId: players[playerIndex].id })); } }); + socket.on('ttt_gamePaused', ({ reason }) => { + Swal.fire({ + title: 'Game Paused', + text: reason, + icon: 'warning', + customClass: { popup: sketchPopupClass }, + }); + }); + socket.on('ttt_gameStarted', () => { - logger.socket('⬅️', 'ttt_gameStarted', 'Game started'); setGameState('playing'); setWinningCells([]); - Swal.fire({ - title: 'Game Started!', - text: 'The battle begins!', - timer: 1500, - showConfirmButton: false, - customClass: { popup: 'glass rounded-3xl paper-font' } - }); }); socket.on('ttt_gameRestarted', () => { - logger.socket('⬅️', 'ttt_gameRestarted', 'Game restarted'); setGameState('playing'); setWinningCells([]); setBoard(Array(9).fill(null)); - Swal.fire({ - title: 'Game Restarted', - text: 'Round 2!', - timer: 1500, - showConfirmButton: false, - customClass: { popup: 'glass rounded-3xl paper-font' } - }); }); - socket.on('ttt_moveMade', ({ position, symbol, board }) => { - logger.socket('⬅️', 'ttt_moveMade', { position, symbol }); + socket.on('ttt_moveMade', ({ board }) => { playMove(); setBoard(board); }); socket.on('ttt_nextTurn', (playerId) => { - logger.socket('⬅️', 'ttt_nextTurn', { playerId }); setCurrentTurn(playerId); }); socket.on('ttt_gameWon', ({ winner, winningLine }) => { - logger.socket('⬅️', 'ttt_gameWon', { winner, winningLine }); playWin(); setWinningCells(winningLine); - confetti({ - particleCount: 150, - spread: 70, - origin: { y: 0.6 } - }); - const winnerName = players.find(p => p.id === winner)?.name || 'Someone'; - Swal.fire({ - title: '🎉 Victory!', - text: `${winnerName} has won!`, - icon: 'success', - customClass: { popup: 'glass rounded-3xl paper-font' } - }); + confetti({ particleCount: 150, spread: 70, origin: { y: 0.6 } }); setGameState('ended'); + sessionStorage.removeItem('ttt_reconnect'); }); socket.on('ttt_gameDraw', () => { - logger.socket('⬅️', 'ttt_gameDraw', 'Draw!'); - Swal.fire({ - title: '🤝 Draw!', - text: 'It\'s a tie!', - icon: 'info', - customClass: { popup: 'glass rounded-3xl paper-font' } - }); setGameState('ended'); + sessionStorage.removeItem('ttt_reconnect'); }); - socket.on('ttt_playerLeft', (playerId) => { - logger.socket('⬅️', 'ttt_playerLeft', { playerId }); + socket.on('ttt_playerLeft', () => { Swal.fire({ title: 'Player Left', text: 'The opponent has left the party.', icon: 'warning', - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); setGameState('waiting'); setBoard(Array(9).fill(null)); }); socket.on('ttt_alert', ({ icon, title, text }) => { - logger.socket('⬅️', 'ttt_alert', { icon, title, text }); - Swal.fire({ icon, title, text, customClass: { popup: 'glass rounded-3xl paper-font' } }); + Swal.fire({ icon, title, text, customClass: { popup: sketchPopupClass } }); }); return () => { @@ -134,19 +123,18 @@ const TicTacToe = () => { socket.off('ttt_gameWon'); socket.off('ttt_gameDraw'); socket.off('ttt_playerLeft'); + socket.off('ttt_gamePaused'); socket.off('ttt_alert'); }; - }, [socket, players, setRoomId, playMove, playWin]); + }, [socket, setRoomId, playMove, playWin]); const handleCellClick = (position) => { if (gameState === 'playing' && currentTurn === socket?.id && !board[position]) { - logger.socket('➡️', 'ttt_makeMove', { roomId, position }); socket.emit('ttt_makeMove', { roomId, position }); } }; const handleCreateRoom = () => { - logger.socket('➡️', 'ttt_createRoom', { playerName }); socket.emit('ttt_createRoom', playerName); }; @@ -156,21 +144,58 @@ const TicTacToe = () => { input: 'text', inputPlaceholder: 'Enter Room ID', showCancelButton: true, - customClass: { popup: 'glass rounded-3xl paper-font' } + customClass: { popup: sketchPopupClass }, }); if (joinRoomId) { - logger.socket('➡️', 'ttt_joinRoom', { roomId: joinRoomId.toUpperCase(), playerName }); - socket.emit('ttt_joinRoom', { roomId: joinRoomId.toUpperCase(), playerName }); + socket.emit('ttt_joinRoom', { + roomId: joinRoomId.toUpperCase(), + playerName, + }); } }; const handleRestartGame = () => { - logger.socket('➡️', 'ttt_restartGame', { roomId }); socket.emit('ttt_restartGame', roomId); }; + const handleLeaveRoom = () => { + socket.emit('ttt_leaveRoom', roomId); + sessionStorage.removeItem('ttt_reconnect'); + clearRoomId(roomId); + navigate('/'); + }; + + const isGameOver = gameState === 'ended'; + const isDraw = isGameOver && winningCells.length === 0; + const isWinner = isGameOver && winningCells.length > 0; + const winnerName = + isWinner && players.length > 0 ? players.find((p) => p.id === currentTurn)?.name || 'Someone' : null; + const iWon = isWinner && currentTurn !== socket?.id; + + if (!roomId) { + return ( +
+

Tic Tac Toe

+ + + + +
+ Create + Join +
+
+
+ ); + } + const renderBoard = () => ( -
+
{board.map((cell, i) => ( ))}
-
+ ); -return ( -
- navigate('/')} - variant="secondary" - className="absolute top-2 sm:top-8 left-2 sm:left-8 flex items-center gap-1 sm:gap-2 text-xs sm:text-base px-2 sm:px-4" - > - - Back - - -

Tic Tac Toe

+ return ( + +
+

Tic Tac Toe

- {!roomId ? ( -
- Create - Join -
- ) : ( -
-
-
- - Room: - {roomId} -
-
- {players.map((p, i) => ( -
- {p.id === currentTurn ? ( - - ) : ( -
- )} - - {p.name.length > 8 ? p.name.slice(0,8)+'...' : p.name} + {gameState === 'ended' ? ( + + ) : ( +
+ {gameState === 'playing' && ( +
+
+ + + {currentTurn === socket?.id ? 'Your turn!' : "Opponent's turn"}
- ))} -
-
- - {renderBoard()} +
+ )} - {gameState === 'ended' && ( - - Play Again - - )} + {renderBoard()} -
- {gameState === 'playing' ? ( - currentTurn === socket?.id ? ( -
- - Your turn! -
- ) : ( -
-
- Waiting for {players.find(p => p.id === currentTurn)?.name}... - Waiting... -
- ) - ) : ( - gameState === 'waiting' ? "Waiting for opponent..." : "Game Over!" + {gameState === 'waiting' && ( +
Waiting for opponent...
)} + +
+ + Leave Room + +
-
- )} -
+ )} +
+ ); }; diff --git a/pro/src/tictactoe/TicTacToe.test.jsx b/pro/src/tictactoe/TicTacToe.test.jsx index 9aa3e36..0b3b00d 100644 --- a/pro/src/tictactoe/TicTacToe.test.jsx +++ b/pro/src/tictactoe/TicTacToe.test.jsx @@ -5,60 +5,155 @@ import TicTacToe from './TicTacToe'; import { GameProvider } from '../context/GameContext'; import { BrowserRouter } from 'react-router-dom'; -// Mock Socket.io const mockSocket = { - id: 'mock-id', + id: 'p1', on: vi.fn(), off: vi.fn(), emit: vi.fn(), disconnect: vi.fn(), }; -vi.mock('socket.io-client', () => ({ - default: () => mockSocket -})); +vi.mock('socket.io-client', () => ({ default: () => mockSocket })); +vi.mock('use-sound', () => ({ default: () => [vi.fn()] })); +vi.mock('canvas-confetti', () => ({ default: vi.fn() })); +vi.mock('sweetalert2', () => ({ default: { fire: vi.fn().mockResolvedValue({ isConfirmed: true }) } })); + +const Wrapper = ({ children }) => ( + + {children} + +); + +const findEventCb = (event) => { + const call = mockSocket.on.mock.calls.find((c) => c[0] === event); + return call?.[1]; +}; + +const playingRoomInfo = { + id: 'TTT01', + players: [ + { id: 'p1', name: 'Alice', connected: true }, + { id: 'p2', name: 'Bob', connected: true }, + ], + gameState: 'playing', + currentTurn: 'p1', + board: Array(9).fill(null), +}; describe('TicTacToe', () => { beforeEach(() => { vi.clearAllMocks(); + sessionStorage.clear(); + }); + + describe('Lobby - No Room', () => { + it('shows Create and Join buttons when no room', () => { + render(, { wrapper: Wrapper }); + expect(screen.getByText('Create')).toBeTruthy(); + expect(screen.getByText('Join')).toBeTruthy(); + }); + + it('emits ttt_createRoom when Create is clicked', async () => { + render(, { wrapper: Wrapper }); + await act(async () => { + fireEvent.click(screen.getByText('Create')); + }); + expect(mockSocket.emit).toHaveBeenCalledWith('ttt_createRoom', expect.any(String)); + }); + }); + + describe('Board Rendering', () => { + it('renders the game board when roomInfo received with playing state', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('ttt_roomInfo'); + await act(async () => { + cb(playingRoomInfo); + }); + + expect(screen.getByText('Your turn!')).toBeTruthy(); + }); + + it('shows player initials in nav', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('ttt_roomInfo'); + await act(async () => { + cb(playingRoomInfo); + }); + + expect(screen.getByText('Al')).toBeTruthy(); + expect(screen.getByText('Bo')).toBeTruthy(); + }); + + it('shows Rematch button when game ends with win', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('ttt_roomInfo'); + await act(async () => { + cb(playingRoomInfo); + }); + + const gameWonCb = findEventCb('ttt_gameWon'); + await act(async () => { + gameWonCb({ winner: 'p1', winningLine: [0, 1, 2] }); + }); + + expect(screen.getByText('Rematch')).toBeTruthy(); + }); + + it('shows Rematch button when game ends with draw', async () => { + render(, { wrapper: Wrapper }); + + const cb = findEventCb('ttt_roomInfo'); + await act(async () => { + cb(playingRoomInfo); + }); + + const gameDrawCb = findEventCb('ttt_gameDraw'); + await act(async () => { + gameDrawCb(); + }); + + expect(screen.getByText('Rematch')).toBeTruthy(); + }); }); - it('emits ttt_makeMove when a cell is clicked', async () => { - render( - - - - - - ); - - // Simulate being in a game and it being our turn - const roomInfoCall = mockSocket.on.mock.calls.find(call => call[0] === 'ttt_roomInfo'); - if (!roomInfoCall) throw new Error('ttt_roomInfo listener not registered'); - - const roomInfoCallback = roomInfoCall[1]; - - await act(async () => { - roomInfoCallback({ - id: '123456', - players: [{ id: 'mock-id', name: 'Alice' }, { id: 'bob-id', name: 'Bob' }], - gameState: 'playing', - currentTurn: 'mock-id', - board: Array(9).fill(null) + describe('Making Moves', () => { + it('emits ttt_makeMove when a cell is clicked on my turn', async () => { + const { container } = render(, { wrapper: Wrapper }); + + const cb = findEventCb('ttt_roomInfo'); + await act(async () => { + cb(playingRoomInfo); }); + + const boardGrid = container.querySelector('.grid.grid-cols-3'); + expect(boardGrid).toBeTruthy(); + const cells = boardGrid.querySelectorAll('button'); + + await act(async () => { + fireEvent.click(cells[0]); + }); + + expect(mockSocket.emit).toHaveBeenCalledWith('ttt_makeMove', expect.objectContaining({ position: 0 })); }); + }); - const cells = screen.getAllByRole('button'); - // The first few buttons might be navigation, but the board cells have numbers or are empty - // Our TicTacToe board uses ); }; @@ -54,49 +60,103 @@ const InnerGrid = ({ const renderOverlay = () => { if (macroWinner === 'DEAD') { return ( -
-
- {Array(9).fill(null).map((_, i) => ( - × - ))} +
+
+ {Array(9) + .fill(null) + .map((_, i) => ( + + × + + ))}
); } - + if (macroWinner === 'X' || macroWinner === 'O') { return ( -
- - {macroWinner} - +
+
+ + {macroWinner} + + {/* Sketch wobble effect */} + + {macroWinner} + +
); } - + return null; }; const renderGridLines = () => ( <> -
-
-
-
+ {/* Horizontal lines with slight wobble */} +
+
+ {/* Vertical lines with slight wobble */} +
+
); return ( -
+
- {Array(9).fill(null).map((_, i) => renderCell(i))} + {Array(9) + .fill(null) + .map((_, i) => renderCell(i))} {renderGridLines()}
{renderOverlay()} + + {/* Paper texture overlay */} +
); }; -export default InnerGrid; \ No newline at end of file +export default InnerGrid; diff --git a/pro/src/uttt/components/MacroGrid.jsx b/pro/src/uttt/components/MacroGrid.jsx index e06a35d..552e956 100644 --- a/pro/src/uttt/components/MacroGrid.jsx +++ b/pro/src/uttt/components/MacroGrid.jsx @@ -2,28 +2,61 @@ import React from 'react'; import InnerGrid from './InnerGrid'; const MacroGrid = ({ board, macroBoard, activeGrid, lastMove, onCellClick }) => { + const getContainerClasses = () => { + let base = 'relative rounded-xl transition-all duration-300 shadow-lg'; + return `${base} bg-white/95 border-2 border-gray-800/10`; + }; + + const renderGridLines = () => ( + <> +
+
+
+
+ + ); + return ( -
-
- {Array(9).fill(null).map((_, gridIndex) => ( - onCellClick(gridIndex, squareIndex)} - /> - ))} +
+
+ {Array(9) + .fill(null) + .map((_, gridIndex) => ( + onCellClick(gridIndex, squareIndex)} + /> + ))} + {renderGridLines()}
-
-
-
-
+ +
); }; -export default MacroGrid; \ No newline at end of file +export default MacroGrid; diff --git a/pro/vite.config.js b/pro/vite.config.js index d0087bd..c6663bf 100644 --- a/pro/vite.config.js +++ b/pro/vite.config.js @@ -4,10 +4,11 @@ import tailwindcss from '@tailwindcss/vite'; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [ - react(), - tailwindcss(), - ], + server: { + host: true, + port: Number(process.env.VITE_PORT) || 5173, + }, + plugins: [react(), tailwindcss()], test: { globals: true, environment: 'jsdom', diff --git a/test-results/.last-run.json b/test-results/.last-run.json new file mode 100644 index 0000000..544c11f --- /dev/null +++ b/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "failed", + "failedTests": [] +}