From df0899de1433399fcdc0e4a256269fe5f032e592 Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 18 Nov 2025 09:58:11 +0100 Subject: [PATCH 01/79] remove ionic --- packages/frontend/capacitor.config.ts | 14 - packages/frontend/ionic.config.json | 7 - packages/frontend/package.json | 16 - packages/frontend/src/App.tsx | 20 +- packages/frontend/src/MobileApp.tsx | 77 +- packages/frontend/src/customIonicStyles.scss | 37 - packages/frontend/src/main.tsx | 3 - .../src/mobile-components/Superfeed.tsx | 14 +- .../PullToRefreshContainer.tsx | 105 +- packages/ui-kit/package.json | 1 - packages/ui-kit/src/App.tsx | 5 +- packages/ui-kit/src/globalStyles/custom.scss | 8 + packages/ui-kit/src/globalStyles/index.scss | 6 - yarn.lock | 1269 +++-------------- 14 files changed, 381 insertions(+), 1201 deletions(-) delete mode 100644 packages/frontend/capacitor.config.ts delete mode 100644 packages/frontend/ionic.config.json delete mode 100644 packages/frontend/src/customIonicStyles.scss diff --git a/packages/frontend/capacitor.config.ts b/packages/frontend/capacitor.config.ts deleted file mode 100644 index 898fd9e7f..000000000 --- a/packages/frontend/capacitor.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { CapacitorConfig } from "@capacitor/cli"; - -const config: CapacitorConfig = { - appId: "com.alphaday", - appName: "alphaday", - webDir: "dist", - server: { - androidScheme: "http", - iosScheme: "http", - }, - backgroundColor: "#121212", -}; - -export default config; diff --git a/packages/frontend/ionic.config.json b/packages/frontend/ionic.config.json deleted file mode 100644 index 354ad3563..000000000 --- a/packages/frontend/ionic.config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "alphaday", - "integrations": { - "capacitor": {} - }, - "type": "react-vite" -} diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 1a6329cc8..306beb4f9 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -8,27 +8,15 @@ "dev": "pwa-assets-generator && VITE_COMMIT=$(git rev-parse --short HEAD) VITE_COMMIT_TS=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d %H:%M:%S') vite", "dev:ssl": "USE_SSL=true yarn dev --host --port 443", "build": "pwa-assets-generator && VITE_COMMIT=$(git rev-parse --short HEAD) VITE_COMMIT_TS=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d %H:%M:%S') vite build", - "build:android:dev": "ionic capacitor build android -- --mode development", - "build:android:prod": "node env-check.cjs && ionic capacitor build android --prod", - "platform:add": "ionic capacitor add", "generate-pwa-assets": "pwa-assets-generator", "preview": "vite preview", "test.e2e": "cypress run", "test.unit": "vitest", "lint": "eslint --max-warnings=0 --ignore-path .gitignore . --ext ts --ext tsx", - "resources": "cordova-res ios --skip-config --copy && cordova-res android --skip-config --copy", "typecheck": "tsc" }, "dependencies": { "@alphaday/ui-kit": "0.0.0", - "@capacitor/android": "5.4.1", - "@capacitor/app": "5.0.7", - "@capacitor/core": "5.7.4", - "@capacitor/haptics": "5.0.7", - "@capacitor/keyboard": "5.0.8", - "@capacitor/status-bar": "5.0.7", - "@ionic/react": "7.8.1", - "@ionic/react-router": "7.8.1", "@react-oauth/google": "0.12.1", "@reduxjs/toolkit": "1.8.0", "@sentry/react": "7.109.0", @@ -43,7 +31,6 @@ "html2canvas": "1.4.1", "i18next": "23.16.5", "i18next-browser-languagedetector": "8.2.0", - "ionicons": "7.3.0", "md5": "2.3.0", "moment": "2.30.1", "moment-with-locales-es6": "1.0.1", @@ -74,8 +61,6 @@ "web3-eth-accounts": "1.9.0" }, "devDependencies": { - "@capacitor/cli": "5.4.1", - "@ionic/cli": "7.2.0", "@testing-library/react": "15.0.7", "@testing-library/react-hooks": "8.0.1", "@testing-library/user-event": "14.4.3", @@ -89,7 +74,6 @@ "@vite-pwa/assets-generator": "0.2.4", "@vitejs/plugin-basic-ssl": "1.2.0", "@vitejs/plugin-legacy": "5.3.2", - "cordova-res": "0.15.4", "cypress": "12.17.4", "dotenv": "16.4.5", "happy-dom": "20.0.11", diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx index 4aa9cc907..51222d898 100644 --- a/packages/frontend/src/App.tsx +++ b/packages/frontend/src/App.tsx @@ -1,9 +1,7 @@ import { Suspense, memo, useMemo } from "react"; import { ErrorModal } from "@alphaday/ui-kit"; -import { IonApp, IonRouterOutlet } from "@ionic/react"; -import { IonReactRouter } from "@ionic/react-router"; import { Web3Modal } from "@web3modal/react"; -import { Redirect, Route } from "react-router-dom"; +import { BrowserRouter, Redirect, Route } from "react-router-dom"; import * as userStore from "src/api/store/slices/user"; import ToastContainer from "src/containers/toasts/ToastContainer"; import { @@ -117,24 +115,22 @@ const App: React.FC = () => { if (!isCookieEnabled()) { return ( - +
- +
); } return ( - - - - - - +
+ + + { duration={CONFIG.UI.TOAST_DURATION} className="fontGroup-supportBold" /> - +
); }; diff --git a/packages/frontend/src/MobileApp.tsx b/packages/frontend/src/MobileApp.tsx index 3e07780e6..1b4904fa0 100644 --- a/packages/frontend/src/MobileApp.tsx +++ b/packages/frontend/src/MobileApp.tsx @@ -1,13 +1,12 @@ import { memo } from "react"; import { - IonApp, - IonRouterOutlet, - IonTabBar, - IonTabButton, - IonTabs, -} from "@ionic/react"; -import { IonReactRouter } from "@ionic/react-router"; -import { Redirect, Route, useHistory, useLocation } from "react-router-dom"; + BrowserRouter, + Link, + Redirect, + Route, + useHistory, + useLocation, +} from "react-router-dom"; import { ReactComponent as MarketsSVG } from "src/assets/svg/markets.svg"; import { ReactComponent as PortfolioSVG } from "src/assets/svg/portfolio.svg"; import { ReactComponent as SuperfeedSVG } from "src/assets/svg/superfeed.svg"; @@ -15,7 +14,6 @@ import { useAuth, useViewRoute } from "./api/hooks"; import CONFIG from "./config"; import ToastContainer from "./containers/toasts/ToastContainer"; import "@alphaday/ui-kit/global.scss"; -import "./customIonicStyles.scss"; import { EMobileRoutePaths, EMobileTabRoutePaths, @@ -89,8 +87,8 @@ const RouterChild = () => { } return ( - - +
+
{mobileRoutes.map((route) => { return ( { )} exact /> - - + +
); }; @@ -168,17 +179,17 @@ const RouterChild = () => { */ const MobileApp: React.FC = () => { return ( - - +
+ - + - +
); }; diff --git a/packages/frontend/src/customIonicStyles.scss b/packages/frontend/src/customIonicStyles.scss deleted file mode 100644 index 9e112adcd..000000000 --- a/packages/frontend/src/customIonicStyles.scss +++ /dev/null @@ -1,37 +0,0 @@ -ion-refresher { - z-index: 100; -} - -ion-tab-bar { - position: relative; - width: 100%; - padding: 8px 0; - background-color: theme("colors.background"); - border-top: solid 1px theme("colors.borderLine"); -} - -/** - * Recall: ionic uses shadow parts, so without the part selector - * we can't change some style properties - */ -ion-tab-button::part(native) { - color: theme("colors.primaryVariant100"); -} - -ion-tab-button { - color: theme("colors.primaryVariant100"); - background: theme("colors.background"); - - svg { - color: theme("colors.primaryVariant100"); - } - - &.tab-selected { - span { - color: theme("colors.primary"); - } - svg { - color: theme("colors.secondaryOrange"); - } - } -} \ No newline at end of file diff --git a/packages/frontend/src/main.tsx b/packages/frontend/src/main.tsx index 8d8b663e4..8dda320e8 100644 --- a/packages/frontend/src/main.tsx +++ b/packages/frontend/src/main.tsx @@ -1,6 +1,5 @@ import "./polyfills"; import { Suspense } from "react"; -import { setupIonicReact } from "@ionic/react"; import * as Sentry from "@sentry/react"; import { createRoot } from "react-dom/client"; import { clarity } from "react-microsoft-clarity"; @@ -23,8 +22,6 @@ import PreloaderPage from "./pages/preloader"; const MobileApp = lazyRetry(() => import("./MobileApp")); const App = lazyRetry(() => import("./App")); -setupIonicReact(); - /** * Enable automatic page reload. * We adopted the `autoUpdate` behavior, but according to the workbox docs diff --git a/packages/frontend/src/mobile-components/Superfeed.tsx b/packages/frontend/src/mobile-components/Superfeed.tsx index 0a3bdf99d..ba8f085c0 100644 --- a/packages/frontend/src/mobile-components/Superfeed.tsx +++ b/packages/frontend/src/mobile-components/Superfeed.tsx @@ -1,6 +1,5 @@ import { useRef, FC, FormEvent, useCallback } from "react"; import { twMerge, ModuleLoader } from "@alphaday/ui-kit"; -import { IonFab, IonList } from "@ionic/react"; import { useOnScreen } from "src/api/hooks"; import { TSuperfeedItem } from "src/api/types"; import { shouldFetchMoreItems } from "src/api/utils/itemUtils"; @@ -55,7 +54,7 @@ const SuperfeedModule: FC = ({ return ( <> - @@ -90,13 +89,10 @@ const SuperfeedModule: FC = ({ onClick={() => onClickItem(item)} /> ))} - - +
@@ -108,7 +104,7 @@ const SuperfeedModule: FC = ({ > - +
); }; diff --git a/packages/frontend/src/mobile-containers/PullToRefreshContainer.tsx b/packages/frontend/src/mobile-containers/PullToRefreshContainer.tsx index 2b99a21e4..3d3c9f1c8 100644 --- a/packages/frontend/src/mobile-containers/PullToRefreshContainer.tsx +++ b/packages/frontend/src/mobile-containers/PullToRefreshContainer.tsx @@ -1,32 +1,103 @@ -import { IonContent, IonRefresher, IonRefresherContent } from "@ionic/react"; +import { useState, useRef, useEffect } from "react"; interface PullToRefreshContainerProps { children: React.ReactNode; handleRefresh: () => void; } + const PullToRefreshContainer: React.FC = ({ children, handleRefresh, }) => { + const [pullDistance, setPullDistance] = useState(0); + const [isRefreshing, setIsRefreshing] = useState(false); + const [startY, setStartY] = useState(0); + const containerRef = useRef(null); + + const pullMin = 60; + const pullMax = 200; + + const handleTouchStart = (e: React.TouchEvent) => { + if (containerRef.current && containerRef.current.scrollTop === 0) { + setStartY(e.touches[0].clientY); + } + }; + + const handleTouchMove = (e: React.TouchEvent) => { + if ( + isRefreshing || + !containerRef.current || + containerRef.current.scrollTop !== 0 + ) { + return; + } + + const currentY = e.touches[0].clientY; + const distance = currentY - startY; + + if (distance > 0) { + const adjustedDistance = Math.min(distance * 0.5, pullMax); + setPullDistance(adjustedDistance); + } + }; + + const handleTouchEnd = () => { + if (pullDistance >= pullMin) { + setIsRefreshing(true); + handleRefresh(); + setTimeout(() => { + setIsRefreshing(false); + setPullDistance(0); + }, 1000); + } else { + setPullDistance(0); + } + setStartY(0); + }; + + useEffect(() => { + if (isRefreshing) { + const timer = setTimeout(() => { + setIsRefreshing(false); + setPullDistance(0); + }, 1000); + return () => clearTimeout(timer); + } + }, [isRefreshing]); + return ( - - { - handleRefresh(); - e.detail.complete(); +
+ {(pullDistance > 0 || isRefreshing) && ( +
+
+
+ )} +
- - - {children} - + {children} +
+
); }; diff --git a/packages/ui-kit/package.json b/packages/ui-kit/package.json index 69db0fc21..2ee2d01dd 100644 --- a/packages/ui-kit/package.json +++ b/packages/ui-kit/package.json @@ -18,7 +18,6 @@ "@fullcalendar/react": "6.1.11", "@fullcalendar/timegrid": "6.1.17", "@headlessui/react": "1.7.17", - "@ionic/react": "7.6.1", "apexcharts": "3.48.0", "moment": "2.30.1", "moment-with-locales-es6": "1.0.1", diff --git a/packages/ui-kit/src/App.tsx b/packages/ui-kit/src/App.tsx index 79b0a6cb5..fb79b7e04 100644 --- a/packages/ui-kit/src/App.tsx +++ b/packages/ui-kit/src/App.tsx @@ -1,5 +1,4 @@ import { useState } from "react"; -import { setupIonicReact } from "@ionic/react"; import { Arrow } from "./components/arrow/Arrow"; import { Button } from "./components/buttons/Button"; import { IconButton } from "./components/buttons/IconButton"; @@ -11,15 +10,13 @@ import { FormTextArea, } from "./mobile-components/form-elements/FormElements"; -setupIonicReact(); - function App() { const [name, setName] = useState(""); const [checked, setChecked] = useState(false); return (

- Vite + React + Ionic + Tailwind + Vite + React + Tailwind

diff --git a/packages/ui-kit/src/globalStyles/custom.scss b/packages/ui-kit/src/globalStyles/custom.scss index 41e59fe6f..ee9227158 100644 --- a/packages/ui-kit/src/globalStyles/custom.scss +++ b/packages/ui-kit/src/globalStyles/custom.scss @@ -20,3 +20,11 @@ overflow-wrap: anywhere; } } + +/* App container styles */ +.app-container, +.mobile-app { + height: 100vh; + width: 100vw; + overflow: hidden; +} diff --git a/packages/ui-kit/src/globalStyles/index.scss b/packages/ui-kit/src/globalStyles/index.scss index 782cd529c..6c076b843 100644 --- a/packages/ui-kit/src/globalStyles/index.scss +++ b/packages/ui-kit/src/globalStyles/index.scss @@ -3,12 +3,6 @@ @tailwind components; @tailwind utilities; -/* ionic css config */ -@import "@ionic/react/css/core.css"; -@import "@ionic/react/css/normalize.css"; -@import "@ionic/react/css/structure.css"; -@import "@ionic/react/css/typography.css"; - /* ionic colors config */ @import "./colors.scss"; diff --git a/yarn.lock b/yarn.lock index fd3cfd40d..9bf5b3ab1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -921,61 +921,6 @@ resolved "https://registry.yarnpkg.com/@canvas/image-data/-/image-data-1.0.0.tgz#3bd2cd856e13fc9e2c25feff360a4056857b0367" integrity sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw== -"@capacitor/android@5.4.1": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@capacitor/android/-/android-5.4.1.tgz#5b0445202ca5e48fcb79d0c88e4403acc32504bc" - integrity sha512-25k/GyIly/8xKQo0EO6eIvJStpVWsBPyYh9Eiv+Or9DCz9iuVlGZY3vui+zjFhfHQ5f9Uwywa8B+thOGWU8f6g== - -"@capacitor/app@5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@capacitor/app/-/app-5.0.7.tgz#f71e81320bcd504c400c1f503ba43a88ccac96e8" - integrity sha512-oad0jwQu+vgQDukeS9UV56yG10dlxkAGGl26IQpZlTmg3dTI9qSJtvhmlLfkF0nEtoj5IsVQUPE+NLH1oZkgGQ== - -"@capacitor/cli@5.4.1": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@capacitor/cli/-/cli-5.4.1.tgz#b9efcb1587861009ce484234883b0eea01b4abaa" - integrity sha512-Smwn38zrTRzPDGBpcoysgL40t34pu/wPbaq6s8HYPJgjutAAO/AsO/OeNA6aY+J+lgqXreBw7NwWfC4FsbqMMA== - dependencies: - "@ionic/cli-framework-output" "^2.2.5" - "@ionic/utils-fs" "^3.1.6" - "@ionic/utils-subprocess" "^2.1.11" - "@ionic/utils-terminal" "^2.3.3" - commander "^9.3.0" - debug "^4.3.4" - env-paths "^2.2.0" - kleur "^4.1.4" - native-run "^1.7.3" - open "^8.4.0" - plist "^3.0.5" - prompts "^2.4.2" - rimraf "^4.4.1" - semver "^7.3.7" - tar "^6.1.11" - tslib "^2.4.0" - xml2js "^0.5.0" - -"@capacitor/core@5.7.4": - version "5.7.4" - resolved "https://registry.yarnpkg.com/@capacitor/core/-/core-5.7.4.tgz#df894775972413982c03fad1ab9e39da38671549" - integrity sha512-iZBgvx3o4amzKv5ttA+QHB6i7cxK+/mYpCQd1tnSdipg6ZkvfBhg1HkzhEqHk+I7MNur+QwgYDZho9+ycHRwOw== - dependencies: - tslib "^2.1.0" - -"@capacitor/haptics@5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@capacitor/haptics/-/haptics-5.0.7.tgz#7ae294b7180f08c27f9c8af12f3c5f2a8057d5ba" - integrity sha512-/j+7Qa4BxQA5aOU43cwXuiudfSXfoHFsAVfcehH5DkSjxLykZKWHEuE4uFJXqdkSIbAHjS37D0Sde6ENP6G/MA== - -"@capacitor/keyboard@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@capacitor/keyboard/-/keyboard-5.0.8.tgz#b8cc21bd6e06273ec61974be9d7f4d8c421a63a4" - integrity sha512-XYyBzGlzjgLPqyPVdu5McGLYV6+G2efVR4I3l5cF1B27M6U/oFqv9CQU74WNG08nee28bfccboNpv6eWCLYn1A== - -"@capacitor/status-bar@5.0.7": - version "5.0.7" - resolved "https://registry.yarnpkg.com/@capacitor/status-bar/-/status-bar-5.0.7.tgz#a341e8dec9f93769bed4a42e8ad397e5df1b5287" - integrity sha512-KblB3gV2LDMEjx3fQoNBAzxb+Tr+2mv68SfFLLDCMiMUD3Eile2TAWRWd1yxy496pDFTOs2BJtup8++iuuuJ/w== - "@coinbase/wallet-sdk@^3.6.6": version "3.9.3" resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-3.9.3.tgz#daf10cb0c85d0363315b7270cb3f02bedc408aab" @@ -2122,254 +2067,6 @@ resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz#56f00962ff0c4e0eb93d34a047d29fa995e3e342" integrity sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg== -"@ionic/cli-framework-output@2.2.8", "@ionic/cli-framework-output@^2.2.5": - version "2.2.8" - resolved "https://registry.yarnpkg.com/@ionic/cli-framework-output/-/cli-framework-output-2.2.8.tgz#29d541acc7773a6aaceec5f3b079937fbcef5402" - integrity sha512-TshtaFQsovB4NWRBydbNFawql6yul7d5bMiW1WYYf17hd99V6xdDdk3vtF51bw6sLkxON3bDQpWsnUc9/hVo3g== - dependencies: - "@ionic/utils-terminal" "2.3.5" - debug "^4.0.0" - tslib "^2.0.1" - -"@ionic/cli-framework-prompts@2.1.13": - version "2.1.13" - resolved "https://registry.yarnpkg.com/@ionic/cli-framework-prompts/-/cli-framework-prompts-2.1.13.tgz#ccdc6cc4fa79402a508d14c980597390d0034793" - integrity sha512-Yj1fz6p7OehreQ8C70bd9+M6tYP/rvzLw5JVj8pT/N9s0kQSjqEFRbs96LKr3lfd3TADZaS8OlZrQIqenFIUpg== - dependencies: - "@ionic/utils-terminal" "2.3.5" - debug "^4.0.0" - inquirer "^7.0.0" - tslib "^2.0.1" - -"@ionic/cli-framework@6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/@ionic/cli-framework/-/cli-framework-6.0.1.tgz#c3a2d51a5cee8b08e401873e1c502cbf9665be13" - integrity sha512-Fyix4eQt2HKTV+GoeoiziQGZyqIA8RfoMqjGyAS5XgNXLOYW0P27Ph348hQZh9Mphjf+m0lOYa6dWQTEPzUHiQ== - dependencies: - "@ionic/cli-framework-output" "2.2.8" - "@ionic/utils-array" "2.1.6" - "@ionic/utils-fs" "3.1.7" - "@ionic/utils-object" "2.1.6" - "@ionic/utils-process" "2.1.12" - "@ionic/utils-stream" "3.1.7" - "@ionic/utils-subprocess" "3.0.1" - "@ionic/utils-terminal" "2.3.5" - chalk "^4.0.0" - debug "^4.0.0" - lodash "^4.17.5" - minimist "^1.2.0" - rimraf "^3.0.0" - tslib "^2.0.1" - write-file-atomic "^3.0.0" - -"@ionic/cli@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@ionic/cli/-/cli-7.2.0.tgz#30062c2345df305a7bca380533549384825e33ed" - integrity sha512-IEms9Df8mJOoWPqgvZEXmqKztttHDFAz+9ewDPZGYv8Xx66Cj7zSen13O2Vf4FuLXhl+U95HXT9sAs4lDwFmcQ== - dependencies: - "@ionic/cli-framework" "6.0.1" - "@ionic/cli-framework-output" "2.2.8" - "@ionic/cli-framework-prompts" "2.1.13" - "@ionic/utils-array" "2.1.6" - "@ionic/utils-fs" "3.1.7" - "@ionic/utils-network" "2.1.7" - "@ionic/utils-process" "2.1.12" - "@ionic/utils-stream" "3.1.7" - "@ionic/utils-subprocess" "3.0.1" - "@ionic/utils-terminal" "2.3.5" - chalk "^4.0.0" - debug "^4.0.0" - diff "^4.0.1" - elementtree "^0.1.7" - leek "0.0.24" - lodash "^4.17.5" - open "^7.0.4" - os-name "^4.0.0" - proxy-agent "^6.3.0" - semver "^7.1.1" - split2 "^3.0.0" - ssh-config "^1.1.1" - stream-combiner2 "^1.1.1" - superagent "^8.0.9" - tar "^6.0.1" - tslib "^2.0.1" - -"@ionic/core@7.6.1": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@ionic/core/-/core-7.6.1.tgz#5f6ca84eb22e2dc9c9c008894e4eeac45bfe08ab" - integrity sha512-o4PSRxokfRB5H3E5DAM7xivG8XFXaXD3+U/tha0QKemiMSntqgPqy0FYX0pNEwIrV3llRzFbAGNqyvB1+BG97Q== - dependencies: - "@stencil/core" "^4.8.2" - ionicons "^7.2.1" - tslib "^2.1.0" - -"@ionic/core@7.8.1": - version "7.8.1" - resolved "https://registry.yarnpkg.com/@ionic/core/-/core-7.8.1.tgz#ef9710c56232011d99651100911430454dd5de7e" - integrity sha512-SsoDy0HaifCcWBlcyRIpTceboz6tSg4gjNr/LRGJyg+r2bWdoG3jeuQDg0Affox8dar7QvODk3AWO/7RFWLOfg== - dependencies: - "@stencil/core" "^4.12.2" - ionicons "^7.2.2" - tslib "^2.1.0" - -"@ionic/react-router@7.8.1": - version "7.8.1" - resolved "https://registry.yarnpkg.com/@ionic/react-router/-/react-router-7.8.1.tgz#4553a9a36ae364cf9f844aa099f1e40469550f8f" - integrity sha512-RmkucjZkMNE7OK8odL/+L9PLPINliH1uWiY9nObfwOtnyt9iXnPgs8MjxDGO3ndiTEPu+ssRLlol9GEwhxjjvw== - dependencies: - "@ionic/react" "7.8.1" - tslib "*" - -"@ionic/react@7.6.1": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@ionic/react/-/react-7.6.1.tgz#ae55fb9a39fb2a45b33ae3fdb74002c59ac14426" - integrity sha512-Gg6IezbyvMucgNgmCMFr5vrsh2kgB/5S9j/24L07wt4mCNBy5ZGrzHkq9NSmcgU7bj/qD1GzamjoqICLH2vEzw== - dependencies: - "@ionic/core" "7.6.1" - ionicons "^7.0.0" - tslib "*" - -"@ionic/react@7.8.1": - version "7.8.1" - resolved "https://registry.yarnpkg.com/@ionic/react/-/react-7.8.1.tgz#a93176f20c0340325df7ed29ab2ab73c2329a554" - integrity sha512-MJgmlsm69lvHiPBFHSUg9ZGbWyjfn5ZDUidYSE8oWA/L0Mtd7XqNl9DMlSXWy87jaOET96R72eSwgsAPZ+FEBA== - dependencies: - "@ionic/core" "7.8.1" - ionicons "^7.0.0" - tslib "*" - -"@ionic/utils-array@2.1.6", "@ionic/utils-array@^2.1.5": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@ionic/utils-array/-/utils-array-2.1.6.tgz#eee863be945ee1a28b9a10ff16fdea776fa18c22" - integrity sha512-0JZ1Zkp3wURnv8oq6Qt7fMPo5MpjbLoUoa9Bu2Q4PJuSDWM8H8gwF3dQO7VTeUj3/0o1IB1wGkFWZZYgUXZMUg== - dependencies: - debug "^4.0.0" - tslib "^2.0.1" - -"@ionic/utils-fs@3.1.7", "@ionic/utils-fs@^3.1.5", "@ionic/utils-fs@^3.1.6": - version "3.1.7" - resolved "https://registry.yarnpkg.com/@ionic/utils-fs/-/utils-fs-3.1.7.tgz#e0d41225272c346846867e88a0b84b1a4ee9d9c9" - integrity sha512-2EknRvMVfhnyhL1VhFkSLa5gOcycK91VnjfrTB0kbqkTFCOXyXgVLI5whzq7SLrgD9t1aqos3lMMQyVzaQ5gVA== - dependencies: - "@types/fs-extra" "^8.0.0" - debug "^4.0.0" - fs-extra "^9.0.0" - tslib "^2.0.1" - -"@ionic/utils-network@2.1.7": - version "2.1.7" - resolved "https://registry.yarnpkg.com/@ionic/utils-network/-/utils-network-2.1.7.tgz#52d63e95c84464f461c3ea2d309907f2230182cb" - integrity sha512-5Q3NdZtSLiLs7ufuX9X293BvAwo8CxaD93Hkp3ODPgctLYErv3nFibhq3j+eguEqUh2um9WNXEUOuQ8x+Sd1fw== - dependencies: - debug "^4.0.0" - tslib "^2.0.1" - -"@ionic/utils-object@2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@ionic/utils-object/-/utils-object-2.1.6.tgz#c0259bf925b6c12663d06f6bc1703e5dcb565e6d" - integrity sha512-vCl7sl6JjBHFw99CuAqHljYJpcE88YaH2ZW4ELiC/Zwxl5tiwn4kbdP/gxi2OT3MQb1vOtgAmSNRtusvgxI8ww== - dependencies: - debug "^4.0.0" - tslib "^2.0.1" - -"@ionic/utils-process@2.1.11": - version "2.1.11" - resolved "https://registry.yarnpkg.com/@ionic/utils-process/-/utils-process-2.1.11.tgz#ac06dfa2307027095ab0420a234924a9effeb6bd" - integrity sha512-Uavxn+x8j3rDlZEk1X7YnaN6wCgbCwYQOeIjv/m94i1dzslqWhqIHEqxEyeE8HsT5Negboagg7GtQiABy+BLbA== - dependencies: - "@ionic/utils-object" "2.1.6" - "@ionic/utils-terminal" "2.3.4" - debug "^4.0.0" - signal-exit "^3.0.3" - tree-kill "^1.2.2" - tslib "^2.0.1" - -"@ionic/utils-process@2.1.12": - version "2.1.12" - resolved "https://registry.yarnpkg.com/@ionic/utils-process/-/utils-process-2.1.12.tgz#17b05d66201859fe11f53b47be22b85aa90b9556" - integrity sha512-Jqkgyq7zBs/v/J3YvKtQQiIcxfJyplPgECMWgdO0E1fKrrH8EF0QGHNJ9mJCn6PYe2UtHNS8JJf5G21e09DfYg== - dependencies: - "@ionic/utils-object" "2.1.6" - "@ionic/utils-terminal" "2.3.5" - debug "^4.0.0" - signal-exit "^3.0.3" - tree-kill "^1.2.2" - tslib "^2.0.1" - -"@ionic/utils-stream@3.1.6": - version "3.1.6" - resolved "https://registry.yarnpkg.com/@ionic/utils-stream/-/utils-stream-3.1.6.tgz#7c2fdcf4d9e621e8b2260e2fee2471825a4e214f" - integrity sha512-4+Kitey1lTA1yGtnigeYNhV/0tggI3lWBMjC7tBs1K9GXa/q7q4CtOISppdh8QgtOhrhAXS2Igp8rbko/Cj+lA== - dependencies: - debug "^4.0.0" - tslib "^2.0.1" - -"@ionic/utils-stream@3.1.7": - version "3.1.7" - resolved "https://registry.yarnpkg.com/@ionic/utils-stream/-/utils-stream-3.1.7.tgz#224f8c99012aa54e7dbf59950de903b6a61cd811" - integrity sha512-eSELBE7NWNFIHTbTC2jiMvh1ABKGIpGdUIvARsNPMNQhxJB3wpwdiVnoBoTYp+5a6UUIww4Kpg7v6S7iTctH1w== - dependencies: - debug "^4.0.0" - tslib "^2.0.1" - -"@ionic/utils-subprocess@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@ionic/utils-subprocess/-/utils-subprocess-3.0.1.tgz#561608fecf432c28fd80f94c1563dc0d092581b7" - integrity sha512-cT4te3AQQPeIM9WCwIg8ohroJ8TjsYaMb2G4ZEgv9YzeDqHZ4JpeIKqG2SoaA3GmVQ3sOfhPM6Ox9sxphV/d1A== - dependencies: - "@ionic/utils-array" "2.1.6" - "@ionic/utils-fs" "3.1.7" - "@ionic/utils-process" "2.1.12" - "@ionic/utils-stream" "3.1.7" - "@ionic/utils-terminal" "2.3.5" - cross-spawn "^7.0.3" - debug "^4.0.0" - tslib "^2.0.1" - -"@ionic/utils-subprocess@^2.1.11": - version "2.1.14" - resolved "https://registry.yarnpkg.com/@ionic/utils-subprocess/-/utils-subprocess-2.1.14.tgz#06224bdc6d9891ed86b1e556fc172a0eeabdc846" - integrity sha512-nGYvyGVjU0kjPUcSRFr4ROTraT3w/7r502f5QJEsMRKTqa4eEzCshtwRk+/mpASm0kgBN5rrjYA5A/OZg8ahqg== - dependencies: - "@ionic/utils-array" "2.1.6" - "@ionic/utils-fs" "3.1.7" - "@ionic/utils-process" "2.1.11" - "@ionic/utils-stream" "3.1.6" - "@ionic/utils-terminal" "2.3.4" - cross-spawn "^7.0.3" - debug "^4.0.0" - tslib "^2.0.1" - -"@ionic/utils-terminal@2.3.4": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@ionic/utils-terminal/-/utils-terminal-2.3.4.tgz#e40c44b676265ed6a07a68407bda6e135870f879" - integrity sha512-cEiMFl3jklE0sW60r8JHH3ijFTwh/jkdEKWbylSyExQwZ8pPuwoXz7gpkWoJRLuoRHHSvg+wzNYyPJazIHfoJA== - dependencies: - "@types/slice-ansi" "^4.0.0" - debug "^4.0.0" - signal-exit "^3.0.3" - slice-ansi "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - tslib "^2.0.1" - untildify "^4.0.0" - wrap-ansi "^7.0.0" - -"@ionic/utils-terminal@2.3.5", "@ionic/utils-terminal@^2.3.3": - version "2.3.5" - resolved "https://registry.yarnpkg.com/@ionic/utils-terminal/-/utils-terminal-2.3.5.tgz#a48465f40496ee8f29c6d92e4506d5f19762ac3c" - integrity sha512-3cKScz9Jx2/Pr9ijj1OzGlBDfcmx7OMVBt4+P1uRR0SSW4cm1/y3Mo4OY3lfkuaYifMNBW8Wz6lQHbs1bihr7A== - dependencies: - "@types/slice-ansi" "^4.0.0" - debug "^4.0.0" - signal-exit "^3.0.3" - slice-ansi "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - tslib "^2.0.1" - untildify "^4.0.0" - wrap-ansi "^7.0.0" - "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -3123,10 +2820,104 @@ "@stablelib/random" "^1.0.2" "@stablelib/wipe" "^1.0.1" -"@stencil/core@^4.0.3", "@stencil/core@^4.12.2", "@stencil/core@^4.8.2": - version "4.27.1" - resolved "https://registry.yarnpkg.com/@stencil/core/-/core-4.27.1.tgz#d9c97b0e144747e4be4d86d733f972ff5e1f9bee" - integrity sha512-wJ+U3yJ9xSrME1PheHh8DnZrgFhjTlvF54mkA0tzTDXYdrEAYXIEAAeWbXx3munYX2Lqj3oDBEDsbsJNxDkwzA== +"@styled-system/background@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/background/-/background-5.1.2.tgz#75c63d06b497ab372b70186c0bf608d62847a2ba" + integrity sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/border@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@styled-system/border/-/border-5.1.5.tgz#0493d4332d2b59b74bb0d57d08c73eb555761ba6" + integrity sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/color@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/color/-/color-5.1.2.tgz#b8d6b4af481faabe4abca1a60f8daa4ccc2d9f43" + integrity sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/core@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/core/-/core-5.1.2.tgz#b8b7b86455d5a0514f071c4fa8e434b987f6a772" + integrity sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw== + dependencies: + object-assign "^4.1.1" + +"@styled-system/css@^5.0.0", "@styled-system/css@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@styled-system/css/-/css-5.1.5.tgz#0460d5f3ff962fa649ea128ef58d9584f403bbbc" + integrity sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A== + +"@styled-system/flexbox@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/flexbox/-/flexbox-5.1.2.tgz#077090f43f61c3852df63da24e4108087a8beecf" + integrity sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/grid@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/grid/-/grid-5.1.2.tgz#7165049877732900b99cd00759679fbe45c6c573" + integrity sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/layout@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/layout/-/layout-5.1.2.tgz#12d73e79887e10062f4dbbbc2067462eace42339" + integrity sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/position@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/position/-/position-5.1.2.tgz#56961266566836f57a24d8e8e33ce0c1adb59dd3" + integrity sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/shadow@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/shadow/-/shadow-5.1.2.tgz#beddab28d7de03cd0177a87ac4ed3b3b6d9831fd" + integrity sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/should-forward-prop@^5.0.0": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@styled-system/should-forward-prop/-/should-forward-prop-5.1.5.tgz#c392008c6ae14a6eb78bf1932733594f7f7e5c76" + integrity sha512-+rPRomgCGYnUIaFabDoOgpSDc4UUJ1KsmlnzcEp0tu5lFrBQKgZclSo18Z1URhaZm7a6agGtS5Xif7tuC2s52Q== + dependencies: + "@emotion/is-prop-valid" "^0.8.1" + "@emotion/memoize" "^0.7.1" + styled-system "^5.1.5" + +"@styled-system/space@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/space/-/space-5.1.2.tgz#38925d2fa29a41c0eb20e65b7c3efb6e8efce953" + integrity sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/typography@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@styled-system/typography/-/typography-5.1.2.tgz#65fb791c67d50cd2900d234583eaacdca8c134f7" + integrity sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg== + dependencies: + "@styled-system/core" "^5.1.2" + +"@styled-system/variant@^5.1.5": + version "5.1.5" + resolved "https://registry.yarnpkg.com/@styled-system/variant/-/variant-5.1.5.tgz#8446d8aad06af3a4c723d717841df2dbe4ddeafd" + integrity sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw== + dependencies: + "@styled-system/core" "^5.1.2" + "@styled-system/css" "^5.1.5" "@surma/rollup-plugin-off-main-thread@^2.2.3": version "2.2.3" @@ -3343,10 +3134,10 @@ resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.4.3.tgz#af975e367743fa91989cd666666aec31a8f50591" integrity sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q== -"@tootallnate/quickjs-emscripten@^0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" - integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA== +"@tokenizer/token@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" + integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A== "@trysound/sax@0.2.0": version "0.2.0" @@ -3445,13 +3236,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== -"@types/fs-extra@^8.0.0": - version "8.1.5" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.5.tgz#33aae2962d3b3ec9219b5aca2555ee00274f5927" - integrity sha512-0dzKcwO+S8s2kuF5Z9oUWatQJj5Uq/iqphEtE3GQJVRRYm/tD1LglU2UnXi2A8jLq5umkGouOXOR9y0n613ZwQ== - dependencies: - "@types/node" "*" - "@types/hast@^3.0.0": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-3.0.4.tgz#1d6b39993b82cea6ad783945b0508c25903e15aa" @@ -3671,10 +3455,10 @@ resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.9.tgz#d4597dbd4618264c414d7429363e3f50acb66ea2" integrity sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w== -"@types/slice-ansi@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/slice-ansi/-/slice-ansi-4.0.0.tgz#eb40dfbe3ac5c1de61f6bcb9ed471f54baa989d6" - integrity sha512-+OpjSaq85gvlZAYINyzKpLeiFkSC4EsC6IIiT6v6TLSU5k5U83fHGj9Lel8oKEXM0HqgrMVCjXPDPVICtxF7EQ== +"@types/stylis@4.2.5": + version "4.2.5" + resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.2.5.tgz#1daa6456f40959d06157698a653a9ab0a70281df" + integrity sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw== "@types/trusted-types@^2.0.2": version "2.0.4" @@ -4360,11 +4144,6 @@ motion "10.16.2" qrcode "1.5.3" -"@xmldom/xmldom@^0.8.8": - version "0.8.10" - resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" - integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== - "@yr/monotone-cubic-spline@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz#7272d89f8e4f6fb7a1600c28c378cc18d3b577b9" @@ -4442,10 +4221,10 @@ acorn@^8.10.0, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== -agent-base@^7.1.0, agent-base@^7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1" - integrity sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw== +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== aggregate-error@^3.0.0: version "3.1.0" @@ -4480,7 +4259,7 @@ ansi-colors@^4.1.1, ansi-colors@^4.1.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== -ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: +ansi-escapes@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -4682,11 +4461,6 @@ arraybuffer.prototype.slice@^1.0.4: get-intrinsic "^1.2.6" is-array-buffer "^3.0.4" -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - asn1.js@^4.10.1: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -4735,13 +4509,6 @@ ast-types-flow@^0.0.8: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== -ast-types@^0.13.4: - version "0.13.4" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782" - integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w== - dependencies: - tslib "^2.0.1" - astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -4942,15 +4709,15 @@ base64-arraybuffer@^1.0.2: resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz#1c37589a7c4b0746e34bd1feb951da2df01c1bdc" integrity sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ== -base64-js@^1.0.2, base64-js@^1.3.1, base64-js@^1.5.1: +base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -basic-ftp@^5.0.2: - version "5.0.5" - resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.5.tgz#14a474f5fffecca1f4f406f1c26b18f800225ac0" - integrity sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg== +base64-sol@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/base64-sol/-/base64-sol-1.0.1.tgz#91317aa341f0bc763811783c5729f1c2574600f6" + integrity sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg== bcrypt-pbkdf@^1.0.0: version "1.0.2" @@ -4964,12 +4731,12 @@ becke-ch--regex--s0-0-v1--base--pl--lib@^1.2.0: resolved "https://registry.yarnpkg.com/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz#429ceebbfa5f7e936e78d73fbdc7da7162b20e20" integrity sha512-FnWonOyaw7Vivg5nIkrUll9HSS5TjFbyuURAiDssuL6VxrBe3ERzudRxOcWRhZYlP89UArMDikz7SapRPQpmZQ== -big-integer@1.6.x: - version "1.6.52" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" - integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bignumber.js@^9.0.0: +bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.0.2: version "9.1.2" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== @@ -5059,13 +4826,6 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -bplist-parser@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.3.2.tgz#3ac79d67ec52c4c107893e0237eb787cbacbced7" - integrity sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ== - dependencies: - big-integer "1.6.x" - brace-expansion@^1.1.7: version "1.1.12" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" @@ -5525,11 +5285,6 @@ character-reference-invalid@^2.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9" integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw== -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - charenc@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" @@ -5589,11 +5344,6 @@ chownr@^1.1.1, chownr@^1.1.4: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== -chownr@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" - integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== - chroma-js@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-3.1.2.tgz#cfb807045182228574eae5380587cdb830e985d6" @@ -5664,11 +5414,6 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - client-only@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" @@ -5746,7 +5491,7 @@ color-string@^1.9.0: color-name "^1.0.0" simple-swizzle "^0.2.2" -color@^4.0.1, color@^4.2.3: +color@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== @@ -5811,21 +5556,11 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^9.3.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" - integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== - common-tags@^1.8.0: version "1.8.2" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== -component-emitter@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" - integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -5917,11 +5652,6 @@ cookie@~0.7.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== -cookiejar@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" - integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== - copy-to-clipboard@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" @@ -5929,18 +5659,6 @@ copy-to-clipboard@^3.3.3: dependencies: toggle-selection "^1.0.6" -cordova-res@0.15.4: - version "0.15.4" - resolved "https://registry.yarnpkg.com/cordova-res/-/cordova-res-0.15.4.tgz#a40af66905dd3edf6347be468c0cb0267ca0c593" - integrity sha512-TjFZhjUtK8qq4DVrgR+KI7tKcUL704cnkTPRhHbKlCPzefHoz1tBOX93wc76dOMmOWKTsbJz83DIm6mqdp5Pmg== - dependencies: - "@ionic/utils-array" "^2.1.5" - "@ionic/utils-fs" "^3.1.5" - debug "^4.2.0" - elementtree "^0.1.7" - sharp "^0.29.2" - tslib "^2.0.3" - core-js-compat@^3.38.0, core-js-compat@^3.40.0: version "3.40.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" @@ -6050,7 +5768,7 @@ cross-fetch@^3.1.4: dependencies: node-fetch "^2.7.0" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -6309,11 +6027,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -data-uri-to-buffer@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz#8a58bb67384b261a38ef18bea1810cb01badd28b" - integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw== - data-view-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" @@ -6346,20 +6059,13 @@ dayjs@^1.10.4: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -debug@2.6.9, debug@^2.1.0, debug@^2.2.0: +debug@2.6.9, debug@^2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" - debug@^3.0.1, debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -6367,6 +6073,13 @@ debug@^3.0.1, debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -6480,12 +6193,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - -define-properties@^1.1.3, define-properties@^1.2.1: +define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -6504,15 +6212,6 @@ defu@^6.1.4: resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== -degenerator@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5" - integrity sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ== - dependencies: - ast-types "^0.13.4" - escodegen "^2.1.0" - esprima "^4.0.1" - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -6561,11 +6260,6 @@ detect-browser@5.3.0, detect-browser@^5.3.0: resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== - detect-libc@^2.0.0, detect-libc@^2.0.2, detect-libc@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" @@ -6587,14 +6281,6 @@ devlop@^1.0.0, devlop@^1.1.0: dependencies: dequal "^2.0.0" -dezalgo@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" - integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== - dependencies: - asap "^2.0.0" - wrappy "1" - didyoumean@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" @@ -6610,11 +6296,6 @@ diff@^3.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - diffie-hellman@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -6784,13 +6465,6 @@ electron-to-chromium@^1.5.73: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.105.tgz#0b2396e7e1a467434cd3132950bbe53c04f74a5e" integrity sha512-ccp7LocdXx3yBhwiG0qTQ7XFrK48Ua2pxIxBdJO8cbddp/MvbBtPFzvnTchtyHQTsgqqczO8cdmAIbpMa0u2+g== -elementtree@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/elementtree/-/elementtree-0.1.7.tgz#9ac91be6e52fb6e6244c4e54a4ac3ed8ae8e29c0" - integrity sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg== - dependencies: - sax "1.1.4" - elliptic@6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -6862,11 +6536,6 @@ entities@^4.2.0, entities@^4.4.0: resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== -env-paths@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" - integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== - error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -7168,17 +6837,6 @@ escape-string-regexp@^5.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== -escodegen@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" - integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== - dependencies: - esprima "^4.0.1" - estraverse "^5.2.0" - esutils "^2.0.2" - optionalDependencies: - source-map "~0.6.1" - eslint-config-airbnb-base@^15.0.0: version "15.0.0" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236" @@ -7417,7 +7075,7 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esprima@^4.0.0, esprima@^4.0.1: +esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -7640,7 +7298,7 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@4.1.0, execa@^4.0.2: +execa@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== @@ -7716,14 +7374,10 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" +extract-files@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" + integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== extract-zip@2.0.1: version "2.0.1" @@ -7787,7 +7441,7 @@ fast-redact@^3.0.0: resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== -fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.1.1: +fast-safe-stringify@^2.0.6, fast-safe-stringify@^2.0.7: version "2.1.1" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== @@ -7825,7 +7479,7 @@ figures@2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.0.0, figures@^3.2.0: +figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -7968,15 +7622,15 @@ form-data-encoder@1.7.1: resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96" integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== -form-data@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c" - integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== +form-data@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.3.tgz#349c8f2c9d8f8f0c879ee0eb7cc0d300018d6b09" + integrity sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" es-set-tostringtag "^2.1.0" - mime-types "^2.1.12" + mime-types "^2.1.35" form-data@~2.3.2: version "2.3.3" @@ -7987,16 +7641,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -formidable@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.2.tgz#fa973a2bec150e4ce7cac15589d7a25fc30ebd89" - integrity sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g== - dependencies: - dezalgo "^1.0.4" - hexoid "^1.0.0" - once "^1.4.0" - qs "^6.11.0" - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -8043,13 +7687,6 @@ fs-minipass@^1.2.7: dependencies: minipass "^2.6.0" -fs-minipass@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" - integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== - dependencies: - minipass "^3.0.0" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -8152,15 +7789,6 @@ get-symbol-description@^1.1.0: es-errors "^1.3.0" get-intrinsic "^1.2.6" -get-uri@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.4.tgz#6daaee9e12f9759e19e55ba313956883ef50e0a7" - integrity sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ== - dependencies: - basic-ftp "^5.0.2" - data-uri-to-buffer "^6.0.2" - debug "^4.3.4" - getos@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5" @@ -8223,16 +7851,6 @@ glob@^7.0.0, glob@^7.1.0, glob@^7.1.2, glob@^7.1.3, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^9.2.0: - version "9.3.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-9.3.5.tgz#ca2ed8ca452781a3009685607fdf025a899dfe21" - integrity sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q== - dependencies: - fs.realpath "^1.0.0" - minimatch "^8.0.2" - minipass "^4.2.4" - path-scurry "^1.6.1" - global-dirs@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" @@ -8484,11 +8102,6 @@ hast-util-whitespace@^3.0.0: dependencies: "@types/hast" "^3.0.0" -hexoid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" - integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== - hey-listen@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" @@ -8589,14 +8202,6 @@ http-parser-js@>=0.5.1: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.9.tgz#b817b3ca0edea6236225000d795378707c169cec" integrity sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw== -http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" - integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== - dependencies: - agent-base "^7.1.0" - debug "^4.3.4" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -8636,14 +8241,6 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== -https-proxy-agent@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" - integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== - dependencies: - agent-base "^7.1.2" - debug "4" - human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -8673,7 +8270,7 @@ ico-endec@*: resolved "https://registry.yarnpkg.com/ico-endec/-/ico-endec-0.1.6.tgz#9b320cc3ed0a0c779f54e998a8db49002abd7c6e" integrity sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ== -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -8768,11 +8365,6 @@ ini@2.0.0: resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== -ini@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ini/-/ini-3.0.1.tgz#c76ec81007875bc44d544ff7a11a55d12294102d" - integrity sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ== - ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" @@ -8790,25 +8382,6 @@ inline-style-parser@0.2.4: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz#f4af5fe72e612839fcd453d989a586566d695f22" integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q== -inquirer@^7.0.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - insert-module-globals@^7.0.0, insert-module-globals@^7.2.1: version "7.2.1" resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.1.tgz#d5e33185181a4e1f33b15f7bf100ee91890d5cb3" @@ -8834,28 +8407,6 @@ internal-slot@^1.1.0: hasown "^2.0.2" side-channel "^1.1.0" -ionicons@7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-7.3.0.tgz#d2385e87dbe6a8c79fd44fb2e7c87b0de4a2cbcb" - integrity sha512-l9quySYi+o4T6mFzhKRyU/1nKc2Zs0zxs7jWcq9iVRhRPQondV11jYqLTed0lVVXHfGrBCfnedKl9D6BCnA1UQ== - dependencies: - "@stencil/core" "^4.0.3" - -ionicons@^7.0.0, ionicons@^7.2.1, ionicons@^7.2.2: - version "7.4.0" - resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-7.4.0.tgz#9c285aaa8089befbd6c5a89ae13292d364cd9ace" - integrity sha512-ZK94MMqgzMCPPMhmk8Ouu6goyVHFIlw/ACP6oe3FrikcI0N7CX0xcwVaEbUc0G/v3W0shI93vo+9ve/KpvcNhQ== - dependencies: - "@stencil/core" "^4.0.3" - -ip-address@^9.0.5: - version "9.0.5" - resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" - integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== - dependencies: - jsbn "1.1.0" - sprintf-js "^1.1.3" - ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -8990,11 +8541,6 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw== -is-docker@^2.0.0, is-docker@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -9196,13 +8742,6 @@ is-weakset@^2.0.3: call-bound "^1.0.3" get-intrinsic "^1.2.6" -is-wsl@^2.1.1, is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -9309,10 +8848,10 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsbn@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" - integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== +jsbi@^3.1.4: + version "3.2.5" + resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-3.2.5.tgz#b37bb90e0e5c2814c1c2a1bcd8c729888a2e37d6" + integrity sha512-aBE4n43IPvjaddScbvWRA2YlTzKEynHzu7MqOyTipdHucf/VxS63ViCjxYRg86M8Rxwbt/GfzHl1kKERkt45fQ== jsbn@~0.1.0: version "0.1.1" @@ -9483,16 +9022,6 @@ keyvaluestorage-interface@^1.0.0: resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -kleur@^4.1.4: - version "4.1.5" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" - integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== - knuth-shuffle-seeded@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz#01f1b65733aa7540ee08d8b0174164d22081e4e1" @@ -9525,15 +9054,6 @@ lazy-ass@^1.6.0: resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw== -leek@0.0.24: - version "0.0.24" - resolved "https://registry.yarnpkg.com/leek/-/leek-0.0.24.tgz#e400e57f0e60d8ef2bd4d068dc428a54345dbcda" - integrity sha512-6PVFIYXxlYF0o6hrAsHtGpTmi06otkwNrMcmQ0K96SeSRHPREPa9J3nJZ1frliVH7XT0XFswoJFQoXsDukzGNQ== - dependencies: - debug "^2.1.0" - lodash.assign "^3.2.0" - rsvp "^3.0.21" - leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -9629,52 +9149,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - integrity sha512-t3N26QR2IdSN+gqSy9Ds9pBu/J1EAFEshKlUHpJG3rvyJOYgcELIxcIeKKfZk7sjOz11cFfzJRsyFry/JyabJQ== - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ== - -lodash._bindcallback@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - integrity sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ== - -lodash._createassigner@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz#838a5bae2fdaca63ac22dee8e19fa4e6d6970b11" - integrity sha512-LziVL7IDnJjQeeV95Wvhw6G28Z8Q6da87LWKOPWmzBLv4u6FAT/x5v00pyGW0u38UoogNF2JnD3bGgZZDaNEBw== - dependencies: - lodash._bindcallback "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash.restparam "^3.0.0" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA== - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ== - -lodash.assign@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-3.2.0.tgz#3ce9f0234b4b2223e296b8fa0ac1fee8ebca64fa" - integrity sha512-/VVxzgGBmbphasTg51FrztxQJ/VgAUpol6zmJuSVSGcNg4g7FA4z7rQV8Ovr9V3vFBNWZhvKWHfpAytjTVUfFA== - dependencies: - lodash._baseassign "^3.0.0" - lodash._createassigner "^3.0.0" - lodash.keys "^3.0.0" - lodash.camelcase@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" @@ -9695,16 +9169,6 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ== - lodash.isequal@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -9715,15 +9179,6 @@ lodash.isplainobject@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ== - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - lodash.memoize@~3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" @@ -9739,17 +9194,12 @@ lodash.once@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw== - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== -lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5: +lodash@4.17.21, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -9828,21 +9278,11 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^7.14.1: - version "7.18.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" - integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== - lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== -macos-release@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.5.1.tgz#bccac4a8f7b93163a8d163b8ebf385b3c5f55bf9" - integrity sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A== - magic-string@^0.25.0, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -10055,7 +9495,18 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@^1.1.2, methods@~1.1.2: +merkletreejs@^0.3.11: + version "0.3.11" + resolved "https://registry.yarnpkg.com/merkletreejs/-/merkletreejs-0.3.11.tgz#e0de05c3ca1fd368de05a12cb8efb954ef6fc04f" + integrity sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ== + dependencies: + bignumber.js "^9.0.1" + buffer-reverse "^1.0.1" + crypto-js "^4.2.0" + treeify "^1.1.0" + web3-utils "^1.3.4" + +methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== @@ -10292,11 +9743,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -10348,13 +9794,6 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^8.0.2: - version "8.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-8.0.4.tgz#847c1b25c014d4e9a7f68aaf63dedd668a626229" - integrity sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA== - dependencies: - brace-expansion "^2.0.1" - minimatch@^9.0.4: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" @@ -10375,23 +9814,6 @@ minipass@^2.6.0, minipass@^2.9.0: safe-buffer "^5.1.2" yallist "^3.0.0" -minipass@^3.0.0: - version "3.3.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" - integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== - dependencies: - yallist "^4.0.0" - -minipass@^4.2.4: - version "4.2.8" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.2.8.tgz#f0010f64393ecfc1d1ccb5f582bcaf45f48e1a3a" - integrity sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ== - -minipass@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" - integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== - "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" @@ -10404,14 +9826,6 @@ minizlib@^1.3.3: dependencies: minipass "^2.9.0" -minizlib@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" - integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== - dependencies: - minipass "^3.0.0" - yallist "^4.0.0" - mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" @@ -10436,11 +9850,6 @@ mkdirp@^0.5.5: dependencies: minimist "^1.2.6" -mkdirp@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - mlly@^1.4.0, mlly@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.4.tgz#3d7295ea2358ec7a271eaa5d000a0f84febe100f" @@ -10554,10 +9963,23 @@ multihashes@^0.4.15, multihashes@~0.4.15: multibase "^0.7.0" varint "^5.0.0" -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +multihashes@^4.0.1, multihashes@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-4.0.3.tgz#426610539cd2551edbf533adeac4c06b3b90fb05" + integrity sha512-0AhMH7Iu95XjDLxIeuCOOE4t9+vQZsACyKZ9Fxw2pcsRmlX4iCn1mby0hS0bb+nQOVpdQYWPpnyusw4da5RPhA== + dependencies: + multibase "^4.0.1" + uint8arrays "^3.0.0" + varint "^5.0.2" + +mv@~2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" + integrity sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg== + dependencies: + mkdirp "~0.5.1" + ncp "~2.0.0" + rimraf "~2.4.0" mz@^2.4.0, mz@^2.7.0: version "2.7.0" @@ -10583,23 +10005,6 @@ napi-build-utils@^2.0.0: resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e" integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== -native-run@^1.7.3: - version "1.7.4" - resolved "https://registry.yarnpkg.com/native-run/-/native-run-1.7.4.tgz#b98b74812805cef8665cfceec651e66e662123e3" - integrity sha512-yDEwTp66vmXpqFiSQzz4sVQgyq5U58gGRovglY4GHh12ITyWa6mh6Lbpm2gViVOVD1JYFtYnwcgr7GTFBinXNA== - dependencies: - "@ionic/utils-fs" "^3.1.6" - "@ionic/utils-terminal" "^2.3.3" - bplist-parser "^0.3.2" - debug "^4.3.4" - elementtree "^0.1.7" - ini "^3.0.1" - plist "^3.0.6" - split2 "^4.1.0" - through2 "^4.0.2" - tslib "^2.4.0" - yauzl "^2.10.0" - natural-compare-lite@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" @@ -10615,11 +10020,6 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -netmask@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" - integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== - next-tick@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" @@ -10644,11 +10044,6 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-addon-api@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" - integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== - node-addon-api@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" @@ -10856,23 +10251,6 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -open@^7.0.4: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -open@^8.4.0: - version "8.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" - integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - optionator@^0.9.3: version "0.9.4" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" @@ -10890,19 +10268,6 @@ os-browserify@~0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== -os-name@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/os-name/-/os-name-4.0.1.tgz#32cee7823de85a8897647ba4d76db46bf845e555" - integrity sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw== - dependencies: - macos-release "^2.5.0" - windows-release "^4.0.0" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== - ospath@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" @@ -10981,28 +10346,6 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -pac-proxy-agent@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz#9cfaf33ff25da36f6147a20844230ec92c06e5df" - integrity sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA== - dependencies: - "@tootallnate/quickjs-emscripten" "^0.23.0" - agent-base "^7.1.2" - debug "^4.3.4" - get-uri "^6.0.1" - http-proxy-agent "^7.0.0" - https-proxy-agent "^7.0.6" - pac-resolver "^7.0.1" - socks-proxy-agent "^8.0.5" - -pac-resolver@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6" - integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg== - dependencies: - degenerator "^5.0.0" - netmask "^2.0.2" - package-json-from-dist@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" @@ -11122,7 +10465,7 @@ path-platform@~0.11.15: resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" integrity sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg== -path-scurry@^1.11.1, path-scurry@^1.6.1: +path-scurry@^1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== @@ -11257,14 +10600,10 @@ pkg-types@^1.3.0: mlly "^1.7.4" pathe "^2.0.1" -plist@^3.0.5, plist@^3.0.6: - version "3.1.0" - resolved "https://registry.yarnpkg.com/plist/-/plist-3.1.0.tgz#797a516a93e62f5bde55e0b9cc9c967f860893c9" - integrity sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ== - dependencies: - "@xmldom/xmldom" "^0.8.8" - base64-js "^1.5.1" - xmlbuilder "^15.1.1" +pngjs@^3.0.0, pngjs@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== pngjs@^5.0.0: version "5.0.0" @@ -11361,7 +10700,7 @@ preact@~10.12.1: resolved "https://registry.yarnpkg.com/preact/-/preact-10.12.1.tgz#8f9cb5442f560e532729b7d23d42fd1161354a21" integrity sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg== -prebuild-install@^7.0.0, prebuild-install@^7.1.1: +prebuild-install@^7.1.1: version "7.1.3" resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== @@ -11449,14 +10788,6 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -prompts@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -11516,20 +10847,6 @@ proxy-addr@~2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" -proxy-agent@^6.3.0: - version "6.5.0" - resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.5.0.tgz#9e49acba8e4ee234aacb539f89ed9c23d02f232d" - integrity sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A== - dependencies: - agent-base "^7.1.2" - debug "^4.3.4" - http-proxy-agent "^7.0.1" - https-proxy-agent "^7.0.6" - lru-cache "^7.14.1" - pac-proxy-agent "^7.1.0" - proxy-from-env "^1.1.0" - socks-proxy-agent "^8.0.5" - proxy-compare@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/proxy-compare/-/proxy-compare-2.5.1.tgz#17818e33d1653fbac8c2ec31406bce8a2966f600" @@ -11540,11 +10857,6 @@ proxy-from-env@1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A== -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - psl@^1.1.28, psl@^1.1.33: version "1.15.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" @@ -11613,7 +10925,7 @@ qs@6.13.0: dependencies: side-channel "^1.0.6" -qs@^6.11.0, qs@^6.12.3, qs@~6.14.0: +qs@^6.11.0, qs@^6.12.3: version "6.14.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== @@ -12019,7 +11331,7 @@ read-only-stream@^2.0.0: dependencies: readable-stream "^2.0.2" -readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: +readable-stream@3, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -12310,19 +11622,19 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" -rimraf@^4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-4.4.1.tgz#bd33364f67021c5b79e93d7f4fa0568c7c21b755" - integrity sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og== +rimraf@~2.4.0: + version "2.4.5" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" + integrity sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ== dependencies: - glob "^9.2.0" + glob "^6.0.1" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" @@ -12353,16 +11665,6 @@ rollup@^3.27.1: optionalDependencies: fsevents "~2.3.2" -rsvp@^3.0.21: - version "3.6.2" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" - integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== - -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -12370,13 +11672,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^6.6.0: - version "6.6.7" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" - integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== - dependencies: - tslib "^1.9.0" - rxjs@^7.5.1: version "7.8.2" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" @@ -12441,11 +11736,6 @@ sass@1.75.0: immutable "^4.0.0" source-map-js ">=0.6.2 <2.0.0" -sax@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.4.tgz#74b6d33c9ae1e001510f179a91168588f1aedaa9" - integrity sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg== - sax@>=0.6.0: version "1.4.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" @@ -12482,7 +11772,7 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.1.1, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.3: +semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: version "7.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== @@ -12665,20 +11955,6 @@ sharp@0.32.6, sharp@^0.32.6: tar-fs "^3.0.4" tunnel-agent "^0.6.0" -sharp@^0.29.2: - version "0.29.3" - resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.29.3.tgz#0da183d626094c974516a48fab9b3e4ba92eb5c2" - integrity sha512-fKWUuOw77E4nhpyzCCJR1ayrttHoFHBT2U/kR/qEMRhvPEcluG4BKj324+SCO1e84+knXHwhJ1HHJGnUt4ElGA== - dependencies: - color "^4.0.1" - detect-libc "^1.0.3" - node-addon-api "^4.2.0" - prebuild-install "^7.0.0" - semver "^7.3.5" - simple-get "^4.0.0" - tar-fs "^2.1.1" - tunnel-agent "^0.6.0" - shasum-object@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shasum-object/-/shasum-object-1.0.0.tgz#0b7b74ff5b66ecf9035475522fa05090ac47e29e" @@ -12756,7 +12032,7 @@ siginfo@^2.0.0: resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== -signal-exit@^3.0.2, signal-exit@^3.0.3: +signal-exit@^3.0.2: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -12796,11 +12072,6 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -12824,33 +12095,11 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - smob@^1.0.0: version "1.5.0" resolved "https://registry.yarnpkg.com/smob/-/smob-1.5.0.tgz#85d79a1403abf128d24d3ebc1cdc5e1a9548d3ab" integrity sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig== -socks-proxy-agent@^8.0.5: - version "8.0.5" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee" - integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw== - dependencies: - agent-base "^7.1.2" - debug "^4.3.4" - socks "^2.8.3" - -socks@^2.8.3: - version "2.8.4" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.4.tgz#07109755cdd4da03269bda4725baa061ab56d5cc" - integrity sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ== - dependencies: - ip-address "^9.0.5" - smart-buffer "^4.2.0" - sonic-boom@^2.2.1: version "2.8.0" resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.8.0.tgz#c1def62a77425090e6ad7516aad8eb402e047611" @@ -12881,7 +12130,7 @@ source-map@^0.5.7, source-map@~0.5.3: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@~0.6.1: +source-map@^0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -12913,33 +12162,16 @@ split-on-first@^3.0.0: resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-3.0.0.tgz#f04959c9ea8101b9b0bbf35a61b9ebea784a23e7" integrity sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA== -split2@^3.0.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" - integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== - dependencies: - readable-stream "^3.0.0" - -split2@^4.0.0, split2@^4.1.0: +split2@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== -sprintf-js@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" - integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -ssh-config@^1.1.1: - version "1.1.6" - resolved "https://registry.yarnpkg.com/ssh-config/-/ssh-config-1.1.6.tgz#c6ce2d7f85f395178c9e47c448d62b8adf9b2523" - integrity sha512-ZPO9rECxzs5JIQ6G/2EfL1I9ho/BVZkx9HRKn8+0af7QgwAmumQ7XBFP1ggMyPMo+/tUbmv0HFdv4qifdO/9JA== - sshpk@^1.14.1, sshpk@^1.7.0: version "1.18.0" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" @@ -13314,22 +12546,6 @@ sucrase@^3.32.0, sucrase@^3.35.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" -superagent@^8.0.9: - version "8.1.2" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.1.2.tgz#03cb7da3ec8b32472c9d20f6c2a57c7f3765f30b" - integrity sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA== - dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.4" - debug "^4.3.4" - fast-safe-stringify "^2.1.1" - form-data "^4.0.0" - formidable "^2.1.2" - methods "^1.1.2" - mime "2.6.0" - qs "^6.11.0" - semver "^7.3.8" - superstruct@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" @@ -13552,10 +12768,10 @@ tailwindcss@^3.3.1: resolve "^1.22.8" sucrase "^3.35.0" -tar-fs@^2.0.0, tar-fs@^2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930" - integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ== +tar-fs@^2.0.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.3.tgz#fb3b8843a26b6f13a08e606f7922875eb1fbbf92" + integrity sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg== dependencies: chownr "^1.1.1" mkdirp-classic "^0.5.2" @@ -13606,18 +12822,6 @@ tar@^4.0.2: safe-buffer "^5.2.1" yallist "^3.1.1" -tar@^6.0.1, tar@^6.1.11: - version "6.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" - integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== - dependencies: - chownr "^2.0.0" - fs-minipass "^2.0.0" - minipass "^5.0.0" - minizlib "^2.1.1" - mkdirp "^1.0.3" - yallist "^4.0.0" - temp-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" @@ -13703,7 +12907,7 @@ through2@^4.0.2: dependencies: readable-stream "3" -"through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8: +"through@>=2.2.7 <3", through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -13753,13 +12957,6 @@ title-case@^2.1.1: no-case "^2.2.0" upper-case "^1.0.3" -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - tmp@~0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.3.tgz#eb783cc22bc1e8bebd0671476d46ea4eb32a79ae" @@ -13826,10 +13023,10 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== +treeify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" + integrity sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A== trim-lines@^3.0.0: version "3.0.1" @@ -13861,16 +13058,21 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@*, tslib@>=2.0.0, tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - -tslib@1.14.1, tslib@^1.8.1, tslib@^1.9.0: +tslib@1.14.1, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== +tslib@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + +tslib@>=2.0.0, tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -14918,12 +14120,10 @@ why-is-node-running@^2.2.2: siginfo "^2.0.0" stackback "0.0.2" -windows-release@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-4.0.0.tgz#4725ec70217d1bf6e02c7772413b29cdde9ec377" - integrity sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg== - dependencies: - execa "^4.0.2" +wicg-inert@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/wicg-inert/-/wicg-inert-3.1.3.tgz#e53dbc9ac1e0d7f8c60f25e707614a835986272a" + integrity sha512-5L0PKK7iP+0Q/jv2ccgmkz/pfXbumZtlEyWS/xnX+L+Og3f7WjL4+iEs18k4IuldOX3PgGpza3qGndL9xUBjCQ== word-wrap@^1.2.5: version "1.2.5" @@ -15129,15 +14329,10 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== ws@8.12.0: version "8.12.0" @@ -15201,11 +14396,6 @@ xml2js@^0.5.0: sax ">=0.6.0" xmlbuilder "~11.0.0" -xmlbuilder@^15.1.1: - version "15.1.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" - integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== - xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" @@ -15236,12 +14426,7 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.10.0: +yaml@^1.10.0, yaml@^1.7.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== From 5af6766683fbde63b3cfd34f3d8ad697814fbc06 Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 18 Nov 2025 10:25:27 +0100 Subject: [PATCH 02/79] clean up --- packages/frontend/src/MobileApp.tsx | 17 ++++++++++------- .../PullToRefreshContainer.tsx | 2 +- .../ui-kit/src/components/dialog/Dialog.tsx | 10 +++------- .../ui-kit/src/components/modal/ErrorModal.tsx | 6 ++---- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/packages/frontend/src/MobileApp.tsx b/packages/frontend/src/MobileApp.tsx index 1b4904fa0..1006205de 100644 --- a/packages/frontend/src/MobileApp.tsx +++ b/packages/frontend/src/MobileApp.tsx @@ -153,13 +153,16 @@ const RouterChild = () => { )} { + if (!IS_DEV) { + return "flex-1 pointer-events-none opacity-50"; + } + return `flex-1 ${ + pathname === EMobileTabRoutePaths.Portfolio + ? "text-primary" + : "text-primaryVariant100" + }`; + })()} > = ({ }, 1000); return () => clearTimeout(timer); } + return undefined; }, [isRefreshing]); return ( @@ -84,7 +85,6 @@ const PullToRefreshContainer: React.FC = ({ )}
= ({ closeButtonProps, ...restProps }) => { - const modalRef = useRef(null); - - const handleCloseDialog = async () => { + const handleCloseDialog = () => { onClose?.(); - await modalRef.current?.dismiss(); }; const handleSaveDialog = async () => { await onSave?.(); - await modalRef.current?.dismiss(); }; const showSaveButton = onSave && saveButtonText; @@ -84,7 +80,7 @@ export const Dialog: FC = ({ className="border-borderLine bg-background flex h-[34px] w-[34px] items-center justify-center rounded-[50%] border-2 border-solid" {...closeButtonProps} > - + )}
diff --git a/packages/ui-kit/src/components/modal/ErrorModal.tsx b/packages/ui-kit/src/components/modal/ErrorModal.tsx index 5451dae04..8ffd5722e 100644 --- a/packages/ui-kit/src/components/modal/ErrorModal.tsx +++ b/packages/ui-kit/src/components/modal/ErrorModal.tsx @@ -1,4 +1,4 @@ -import { FC, useRef } from "react"; +import { FC } from "react"; import { twMerge } from "tailwind-merge"; import { Button } from "../buttons/Button"; import { @@ -27,10 +27,8 @@ export const ErrorModal: FC = ({ isHidden, ...restProps }) => { - const modalRef = useRef(null); - const handleCloseModal = async () => { + const handleCloseModal = () => { onClose?.(); - await modalRef.current?.dismiss(); }; return ( From 0b1d3e5b9a3bc31c6e2c7702420fa29dce7d6285 Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 18 Nov 2025 10:26:24 +0100 Subject: [PATCH 03/79] clean up --- packages/ui-kit/src/components/dialog/Dialog.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ui-kit/src/components/dialog/Dialog.tsx b/packages/ui-kit/src/components/dialog/Dialog.tsx index 7ca6c44d1..d4a7e16a1 100644 --- a/packages/ui-kit/src/components/dialog/Dialog.tsx +++ b/packages/ui-kit/src/components/dialog/Dialog.tsx @@ -72,7 +72,6 @@ export const Dialog: FC = ({ {showXButton && ( + +
+
+ + {/* Custom Boards Section */} + {activeSection === "custom" && ( +
+
+
+ + {t("navigation.boardsLibrary.customBoardsTitle")} + + + {isAuthenticated + ? t("navigation.boardsLibrary.customBoardsDescriptionWithAuth") + : t("navigation.boardsLibrary.customBoardsDescription")} + +
+ {isAuthenticated && ( + + )} +
+ +
+ {customBoards.length === 0 && isAuthenticated ? ( + + ) : ( + customBoards.map((view) => ( + + )) + )} +
+
+ )} + + {/* All Boards Section */} + {activeSection === "all" && ( +
+
+ { + onCategorySelect(name); + }} + selectedOption={ + selectedCategory + ? { + label: selectedCategory, + value: selectedCategory, + } + : DEFAULT_TAB_OPTION + } + /> +
+ + System Boards + + +
+
+ +
+ {isFetching && allBoards.length === 0 ? ( + + ) : allBoards.length === 0 ? ( + + ) : ( + allBoards.map((view) => ( + + )) + )} +
+
+ )} +
+ ); +}; + +export default MobileBoardsList; diff --git a/packages/frontend/src/mobile-containers/BoardsContainer.tsx b/packages/frontend/src/mobile-containers/BoardsContainer.tsx new file mode 100644 index 000000000..046be0a96 --- /dev/null +++ b/packages/frontend/src/mobile-containers/BoardsContainer.tsx @@ -0,0 +1,298 @@ +import { FC, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useHistory } from "react-router"; +import { + useView, + usePagination, + useViewRoute, +} from "src/api/hooks"; +import { + EItemsSortBy, + TRemoteUserViewPreview, + useGetSubscribedViewsQuery, + useGetViewCategoriesQuery, + useGetViewsQuery, + useSubscribeViewMutation, + useUnsubscribeViewMutation, +} from "src/api/services"; +import { useAppSelector } from "src/api/store/hooks"; +import { useWalletViewContext } from "src/api/store/providers/wallet-view-context"; +import * as userStore from "src/api/store/slices/user"; +import { TViewMeta } from "src/api/types"; +import { Logger } from "src/api/utils/logging"; +import { getSortOptionValue } from "src/api/utils/sortOptions"; +import { EToastRole, toast } from "src/api/utils/toastUtils"; +import { buildViewPath } from "src/api/utils/viewUtils"; +import MobileBoardsList from "src/mobile-components/MobileBoardsList"; +import CONFIG from "src/config/config"; + +const INITIAL_PAGE = 1; + +const BoardsContainer: FC = () => { + const history = useHistory(); + + const [selectedCategory, setSelectedCategory] = useState< + string | undefined + >(); + const [currentPage, setCurrentPage] = useState(INITIAL_PAGE); + const [sortBy, setSortBy] = useState(EItemsSortBy.Name); + + const { routeInfo, pathContainsHashOrSlug } = useViewRoute(); + + const { removeView, selectedView, removeViewFromCache, subscribedViews } = + useView(); + + const { setAllowFetchWalletView } = useWalletViewContext(); + + const isAuthenticated = useAppSelector(userStore.selectIsAuthenticated); + const selectedLangCode = useAppSelector( + (state) => state.ui.selectedLanguageCode + ); + + const { data: categories } = useGetViewCategoriesQuery(); + const { currentData: remoteSubscribedViews } = useGetSubscribedViewsQuery({ + lang: selectedLangCode, + }); + + const { + data: viewsDataResponse, + isSuccess, + isFetching, + } = useGetViewsQuery({ + limit: CONFIG.UI.BOARD_LIBRARY.LIMIT, + page: currentPage, + sortBy, + category: selectedCategory === "all" ? undefined : selectedCategory, + lang: selectedLangCode, + }); + + const [allViews, setAllViews] = useState([]); + + // shallow copy necessary because response is read-only + const viewsDataForCurrentPage = useMemo( + () => [...(viewsDataResponse?.results ?? [])], + [viewsDataResponse?.results] + ); + const prevViewsDataRef = useRef(); + + // if the current response changes, it means the user scrolled down + // and a request for the next page has completed + // When user subscribed/unsubscribed from a view, the response may include + // items that were already in a previous response, so we need to handle this + // as well. + if ( + viewsDataResponse?.results !== undefined && + prevViewsDataRef.current !== viewsDataForCurrentPage + ) { + setAllViews((prevState) => { + const updatedViewArray = [...prevState]; + viewsDataForCurrentPage.forEach((updatedView) => { + const existingViewIdx = prevState.findIndex( + (existingView) => existingView.id === updatedView.id + ); + if (existingViewIdx !== -1) { + updatedViewArray[existingViewIdx] = { + ...updatedViewArray[existingViewIdx], + ...updatedView, + }; + } else { + updatedViewArray.push(updatedView); + } + }); + return updatedViewArray; + }); + prevViewsDataRef.current = viewsDataForCurrentPage; + } + + const [subscribeViewMut] = useSubscribeViewMutation(); + const [unsubscribeViewMut] = useUnsubscribeViewMutation(); + + const handleRemoveView = useCallback( + (removeViewRequest: TViewMeta) => { + removeView(removeViewRequest); + if (removeViewRequest.isWalletView) { + setAllowFetchWalletView(false); + } + }, + [removeView, setAllowFetchWalletView] + ); + + const handleSelectView = useCallback( + (viewId: number) => { + const view = allViews.find((v) => v.id === viewId); + if (view === undefined) { + // this should never happen + Logger.error( + "BoardsContainer::handleSelectView failed to find view with id:", + viewId + ); + return; + } + history.push(buildViewPath(view)); + }, + [allViews, history] + ); + + const handleSubscribe = useCallback( + (viewId: number) => { + Logger.debug( + "BoardsContainer::handleSubscribe called on view:", + viewId + ); + subscribeViewMut({ id: viewId }) + .unwrap() + .then((r) => { + Logger.debug( + "BoardsContainer::handleSubscribe success", + r + ); + toast("Your board preferences have been updated."); + }) + .catch((e) => { + Logger.error( + "BoardsContainer::handleSubscribe failed", + e + ); + toast( + "You have reached the limit to pinned boards, please unpin some boards to pin others.", + { + type: EToastRole.Error, + } + ); + }); + }, + [subscribeViewMut] + ); + + const handleUnsubscribe = useCallback( + (viewId: number) => { + Logger.debug( + "BoardsContainer::handleUnsubscribe called on view:", + viewId + ); + if (subscribedViews === undefined) { + Logger.error( + "BoardsContainer::handleUnsubscribe failed to find view with id:", + viewId + ); + return; + } + const [view] = subscribedViews.filter((v) => v.data.id === viewId); + unsubscribeViewMut({ id: viewId }) + .unwrap() + .then((r) => { + removeViewFromCache(viewId); + if ( + pathContainsHashOrSlug && + [view.data.hash, view.data.slug].indexOf( + routeInfo?.value + ) !== -1 + ) { + history.push("/"); + } + Logger.debug( + "BoardsContainer::handleUnsubscribe success", + r + ); + toast("Your board preferences have been updated."); + }) + .catch((e) => { + Logger.error( + "BoardsContainer::handleUnsubscribe failed", + e + ); + toast( + "Your board preferences could not be updated. Please try again later.", + { + type: EToastRole.Error, + } + ); + }); + }, + [ + subscribedViews, + unsubscribeViewMut, + removeViewFromCache, + pathContainsHashOrSlug, + routeInfo?.value, + history, + ] + ); + + const handleSortBy = (sortValue: string): void => { + const sort = getSortOptionValue(sortValue); + if (isFetching || sort === null || sortBy === sort) return; + if (allViews.length > 0) setAllViews([]); + if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); + setSortBy(sort); + }; + + const handleCategorySelect = (newCategory: string | undefined): void => { + if (isFetching || newCategory === selectedCategory) return; + if (allViews.length > 0) setAllViews([]); + if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); + setSelectedCategory(newCategory); + }; + + const { nextPage, handleNextPage } = usePagination( + viewsDataResponse?.links, + CONFIG.UI.BOARD_LIBRARY.MAX_PAGE_NUMBER, + isSuccess + ); + + // set current page 350ms after next page is set. + // RTK should cache requests, so we don't need to be too careful about rerenders. + useEffect(() => { + if (nextPage === undefined) return () => null; + const timeout = setTimeout(() => { + setCurrentPage(nextPage); + }, 350); + return () => { + clearTimeout(timeout); + }; + }, [nextPage]); + + const handleCreateBoard = useCallback(() => { + if (isAuthenticated) { + // Navigate to create a new board - this will be handled by the desktop flow + toast("Board creation is available on desktop", { + type: EToastRole.Error, + }); + } else { + toast("Sign up to create custom boards", { + type: EToastRole.Error, + }); + } + }, [isAuthenticated]); + + const handleEditView = useCallback( + (_viewId: number, viewHash: string) => { + // Navigate to the board in edit mode + history.push(`/b/${viewHash}?edit=true`); + }, + [history] + ); + + return ( + + ); +}; + +export default BoardsContainer; diff --git a/packages/frontend/src/mobile-pages/boards.tsx b/packages/frontend/src/mobile-pages/boards.tsx new file mode 100644 index 000000000..4785f7313 --- /dev/null +++ b/packages/frontend/src/mobile-pages/boards.tsx @@ -0,0 +1,26 @@ +import md5 from "md5"; +import { useAccount } from "src/api/hooks"; +import MobileLayout from "src/layout/MobileLayout"; +import AuthPromptContainer from "src/mobile-containers/AuthPromptContainer"; +import BoardsContainer from "src/mobile-containers/BoardsContainer"; + +const BoardsPage: React.FC = () => { + const { userProfile } = useAccount(); + + return ( + + + + + ); +}; + +export default BoardsPage; diff --git a/packages/frontend/src/routes.ts b/packages/frontend/src/routes.ts index a799b08ec..f98c34280 100644 --- a/packages/frontend/src/routes.ts +++ b/packages/frontend/src/routes.ts @@ -11,6 +11,7 @@ const ErrorPage = lazyRetry(() => import("./pages/error")); * Mobile pages */ const SuperfeedPage = lazyRetry(() => import("./mobile-pages/superfeed")); +const BoardsPage = lazyRetry(() => import("./mobile-pages/boards")); const Placeholder = lazyRetry(() => import("./mobile-pages/placeholder")); const AuthPage = lazyRetry(() => import("./mobile-pages/auth")); const UserFiltersPage = lazyRetry(() => import("./mobile-pages/user-filters")); @@ -140,6 +141,7 @@ export enum EMobileTabRoutePaths { export enum EMobileRoutePaths { Base = BASE_TABS_ROUTE, Boards = EDesktopRoutePaths.Boards, + BoardsLibrary = `${BASE_TABS_ROUTE}boards`, Superfeed = `${BASE_TABS_ROUTE}superfeed`, Search = `${BASE_TABS_ROUTE}superfeed/search/:tags`, UserSettings = `${BASE_TABS_ROUTE}superfeed/user-settings`, @@ -172,6 +174,12 @@ export const mobileRoutes: TMobileRoute[] = [ exact: true, type: "regular", }, + { + path: EMobileRoutePaths.BoardsLibrary, + component: BoardsPage, + exact: true, + type: "regular", + }, { path: EMobileRoutePaths.Boards, component: SuperfeedPage, From d83d150386749925a75734ff7983b8e49d2da15d Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 26 Nov 2025 16:54:59 +0100 Subject: [PATCH 11/79] feat: Add BoardsLibrary route and update view route logic for improved navigation --- packages/frontend/src/App.tsx | 11 ++++++++-- .../frontend/src/api/hooks/useViewRoute.ts | 9 ++++++++- packages/frontend/src/mobile-pages/boards.tsx | 20 +++---------------- packages/frontend/src/routes.ts | 14 ++++++------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx index 51222d898..cf6d13cdd 100644 --- a/packages/frontend/src/App.tsx +++ b/packages/frontend/src/App.tsx @@ -37,14 +37,20 @@ const AppRoutes = () => { }); const resolvedView = useResolvedView(); - const { pathContainsHashOrSlug, isRoot, isSuperfeed } = useViewRoute(); + const { pathContainsHashOrSlug, isRoot, isSuperfeed, isBoardsLibrary } = + useViewRoute(); const errorCode = useMemo(() => { /** * At this moment, we do not support any other routes than the root and the hash/slug routes * If the path does not contain a hash or slug, we show the 404 error page */ - if (!pathContainsHashOrSlug && !isRoot && !isSuperfeed) { + if ( + !pathContainsHashOrSlug && + !isRoot && + !isSuperfeed && + !isBoardsLibrary + ) { return 404; } const errorInfo = error ?? resolvedView.error; @@ -53,6 +59,7 @@ const AppRoutes = () => { pathContainsHashOrSlug, isRoot, isSuperfeed, + isBoardsLibrary, error, resolvedView.error, ]); diff --git a/packages/frontend/src/api/hooks/useViewRoute.ts b/packages/frontend/src/api/hooks/useViewRoute.ts index 9dd9131e3..34e50d968 100644 --- a/packages/frontend/src/api/hooks/useViewRoute.ts +++ b/packages/frontend/src/api/hooks/useViewRoute.ts @@ -2,7 +2,7 @@ import { useMemo } from "react"; import { useLocation } from "react-router-dom"; import { isHash } from "src/api/utils/helpers"; import CONFIG from "src/config/config"; -import { EMobileRoutePaths } from "src/routes"; +import { EMobileRoutePaths, EDesktopRoutePaths } from "src/routes"; import { FULLSIZE_ROUTES_ARR } from "src/types"; enum ERouteType { @@ -44,6 +44,10 @@ interface IViewRouteInfo { * true if the current path is superfeed path */ isSuperfeed: boolean; + /** + * true if the current path is boards library path + */ + isBoardsLibrary: boolean; } export const useViewRoute = (): IViewRouteInfo => { @@ -123,6 +127,9 @@ export const useViewRoute = (): IViewRouteInfo => { isViewHash, isRoot: location.pathname === "/", isSuperfeed: location.pathname.includes(EMobileRoutePaths.Superfeed), + isBoardsLibrary: location.pathname.includes( + EDesktopRoutePaths.BoardsLibrary + ), }; }; diff --git a/packages/frontend/src/mobile-pages/boards.tsx b/packages/frontend/src/mobile-pages/boards.tsx index 4785f7313..e6a1f64d5 100644 --- a/packages/frontend/src/mobile-pages/boards.tsx +++ b/packages/frontend/src/mobile-pages/boards.tsx @@ -1,25 +1,11 @@ -import md5 from "md5"; -import { useAccount } from "src/api/hooks"; -import MobileLayout from "src/layout/MobileLayout"; -import AuthPromptContainer from "src/mobile-containers/AuthPromptContainer"; +import MainLayout from "src/layout/MainLayout"; import BoardsContainer from "src/mobile-containers/BoardsContainer"; const BoardsPage: React.FC = () => { - const { userProfile } = useAccount(); - return ( - - + - + ); }; diff --git a/packages/frontend/src/routes.ts b/packages/frontend/src/routes.ts index f98c34280..42e76c985 100644 --- a/packages/frontend/src/routes.ts +++ b/packages/frontend/src/routes.ts @@ -74,6 +74,7 @@ export enum EDesktopRoutePaths { CalendarEvent = "/b/:slug/calendar/event/:eventId/:eventTitle", FallBack = "*", Superfeed = "/superfeed", + BoardsLibrary = `/boards`, } /** @@ -113,6 +114,12 @@ export const desktopRoutes: TRoute[] = [ component: DashboardPage, exact: true, }, + { + type: "regular", + path: EDesktopRoutePaths.BoardsLibrary, + component: BoardsPage, + exact: true, + }, ]; /** @@ -141,7 +148,6 @@ export enum EMobileTabRoutePaths { export enum EMobileRoutePaths { Base = BASE_TABS_ROUTE, Boards = EDesktopRoutePaths.Boards, - BoardsLibrary = `${BASE_TABS_ROUTE}boards`, Superfeed = `${BASE_TABS_ROUTE}superfeed`, Search = `${BASE_TABS_ROUTE}superfeed/search/:tags`, UserSettings = `${BASE_TABS_ROUTE}superfeed/user-settings`, @@ -174,12 +180,6 @@ export const mobileRoutes: TMobileRoute[] = [ exact: true, type: "regular", }, - { - path: EMobileRoutePaths.BoardsLibrary, - component: BoardsPage, - exact: true, - type: "regular", - }, { path: EMobileRoutePaths.Boards, component: SuperfeedPage, From 54b1009e6b48994cc771319016095640fb6094b2 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 1 Dec 2025 09:48:37 +0100 Subject: [PATCH 12/79] refactor: Clean up import statements and streamline logging in BoardsContainer --- .../src/mobile-containers/BoardsContainer.tsx | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/packages/frontend/src/mobile-containers/BoardsContainer.tsx b/packages/frontend/src/mobile-containers/BoardsContainer.tsx index 046be0a96..d67851803 100644 --- a/packages/frontend/src/mobile-containers/BoardsContainer.tsx +++ b/packages/frontend/src/mobile-containers/BoardsContainer.tsx @@ -1,10 +1,6 @@ import { FC, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useHistory } from "react-router"; -import { - useView, - usePagination, - useViewRoute, -} from "src/api/hooks"; +import { useView, usePagination, useViewRoute } from "src/api/hooks"; import { EItemsSortBy, TRemoteUserViewPreview, @@ -22,8 +18,8 @@ import { Logger } from "src/api/utils/logging"; import { getSortOptionValue } from "src/api/utils/sortOptions"; import { EToastRole, toast } from "src/api/utils/toastUtils"; import { buildViewPath } from "src/api/utils/viewUtils"; -import MobileBoardsList from "src/mobile-components/MobileBoardsList"; import CONFIG from "src/config/config"; +import MobileBoardsList from "src/mobile-components/MobileBoardsList"; const INITIAL_PAGE = 1; @@ -141,17 +137,11 @@ const BoardsContainer: FC = () => { subscribeViewMut({ id: viewId }) .unwrap() .then((r) => { - Logger.debug( - "BoardsContainer::handleSubscribe success", - r - ); + Logger.debug("BoardsContainer::handleSubscribe success", r); toast("Your board preferences have been updated."); }) .catch((e) => { - Logger.error( - "BoardsContainer::handleSubscribe failed", - e - ); + Logger.error("BoardsContainer::handleSubscribe failed", e); toast( "You have reached the limit to pinned boards, please unpin some boards to pin others.", { From 5de82463ffd12448963db0a6cf1ce10ec5244a39 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 1 Dec 2025 13:35:20 +0100 Subject: [PATCH 13/79] feat: Refactor ProfileMenuWrapper to separate mobile and desktop components for improved structure and maintainability --- .../profile-menu/ProfileMenuWrapper.tsx | 390 +++++++++++------- 1 file changed, 245 insertions(+), 145 deletions(-) diff --git a/packages/frontend/src/containers/header/profile-menu/ProfileMenuWrapper.tsx b/packages/frontend/src/containers/header/profile-menu/ProfileMenuWrapper.tsx index 0bdf56b42..fe3a1761c 100644 --- a/packages/frontend/src/containers/header/profile-menu/ProfileMenuWrapper.tsx +++ b/packages/frontend/src/containers/header/profile-menu/ProfileMenuWrapper.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useState, memo } from "react"; import { Dropdown, DropdownAvatar, @@ -35,165 +35,265 @@ const Divider = () => (
); -const ProfileMenuWrapper: React.FC = ({ - onSignOut, - onSignUpSignIn, - onShowTutorial, +// Shared dropdown content component +const ProfileMenuContent: React.FC<{ + profile: TUserProfile | undefined; + walletMenuOption: { + handler: () => MaybeAsync; + menuTitle: string; + title: string; + dataTestId: string; + }; + onToggleLanguageModal: () => void; + handleToggle: () => void; + toggleTutorialState: boolean; + onShowAboutUsModal: () => void; + isMobile: boolean; + t: (key: string) => string; + onNavigateToBoards: () => void; +}> = ({ + profile, + walletMenuOption, onToggleLanguageModal, - showTutorial, + handleToggle, + toggleTutorialState, onShowAboutUsModal, - isAuthenticated, - setTutFocusElemRef, - profile, - isMobile = false, -}) => { - const history = useHistory(); - const { t } = useTranslation(); - const [toggleTutorialState, setToggleTutorialState] = useState(false); - - const handleToggle = () => { - setToggleTutorialState((prev) => !prev); - setTimeout(() => { - onShowTutorial(true); - }, 500); - }; - - const walletMenuOption = isAuthenticated - ? { - handler: onSignOut, - menuTitle: t("navigation.menu.signOut"), - title: t("navigation.menu.signOut"), - dataTestId: "profile-menu-sign-out", - } - : { - handler: onSignUpSignIn, - menuTitle: `${t("navigation.menu.signUp")} / ${t("navigation.menu.signIn")}`, - title: globalMessages.portfolio.signUp, - dataTestId: "profile-menu-sign-up", - }; - - useEffect(() => { - if (!showTutorial) setToggleTutorialState(false); - }, [showTutorial]); - - const dropdownContent = ( -
-
- - - -

- {profile?.user.username || profile?.user.email} -

-
- - { - history.push("/boards"); - }} + isMobile, + t, + onNavigateToBoards, +}) => ( +
+
+ + + +

- - {t("navigation.boards")} - - - - { - walletMenuOption.handler()?.catch((err) => { - Logger.error("profile-menu:ProfileMenuWrapper", err); - }); - }} - > - - {walletMenuOption.menuTitle} - - - - - - {t("navigation.menu.language")} - - - - - {t("navigation.menu.tutorial")}{" "} - - - - - - {t("navigation.menu.aboutUs")} - - - - {CONFIG.APP.VERSION && CONFIG.APP.COMMIT && ( - -

- {t("navigation.menu.version")}: {CONFIG.APP.VERSION} -
- {t("navigation.menu.commit")}: {CONFIG.APP.COMMIT} -
- - )} + {profile?.user.username || profile?.user.email} +

- ); + + + {t("navigation.boards")} + + + { + walletMenuOption.handler()?.catch((err) => { + Logger.error("profile-menu:ProfileMenuWrapper", err); + }); + }} + > + + {walletMenuOption.menuTitle} + + + + + {t("navigation.menu.language")} + + + + {t("navigation.menu.tutorial")}{" "} + + + + + + {t("navigation.menu.aboutUs")} + + + + {CONFIG.APP.VERSION && CONFIG.APP.COMMIT && ( + +
+ {t("navigation.menu.version")}: {CONFIG.APP.VERSION} +
+ {t("navigation.menu.commit")}: {CONFIG.APP.COMMIT} +
+
+ )} +
+); + +// Mobile version - separate component to avoid hook ordering issues +const ProfileMenuMobile: React.FC = memo( + ({ + onSignOut, + onSignUpSignIn, + onShowTutorial, + onToggleLanguageModal, + showTutorial, + onShowAboutUsModal, + isAuthenticated, + profile, + }) => { + const history = useHistory(); + const { t } = useTranslation(); + const [toggleTutorialState, setToggleTutorialState] = useState(false); + + const handleToggle = () => { + setToggleTutorialState((prev) => !prev); + setTimeout(() => { + onShowTutorial(true); + }, 500); + }; + + const walletMenuOption = isAuthenticated + ? { + handler: onSignOut, + menuTitle: t("navigation.menu.signOut"), + title: t("navigation.menu.signOut"), + dataTestId: "profile-menu-sign-out", + } + : { + handler: onSignUpSignIn, + menuTitle: `${t("navigation.menu.signUp")} / ${t("navigation.menu.signIn")}`, + title: globalMessages.portfolio.signUp, + dataTestId: "profile-menu-sign-up", + }; + + useEffect(() => { + if (!showTutorial) setToggleTutorialState(false); + }, [showTutorial]); + + const onNavigateToBoards = () => { + history.push("/boards"); + }; - if (isMobile) { return (
- {dropdownContent} +
); } +); - return ( - - - - setTutFocusElemRef && ref && setTutFocusElemRef(ref) - } - > - - +// Desktop version - separate component to avoid hook ordering issues +const ProfileMenuDesktop: React.FC = memo( + ({ + onSignOut, + onSignUpSignIn, + onShowTutorial, + onToggleLanguageModal, + showTutorial, + onShowAboutUsModal, + isAuthenticated, + setTutFocusElemRef, + profile, + }) => { + const history = useHistory(); + const { t } = useTranslation(); + const [toggleTutorialState, setToggleTutorialState] = useState(false); + + const handleToggle = () => { + setToggleTutorialState((prev) => !prev); + setTimeout(() => { + onShowTutorial(true); + }, 500); + }; + + const walletMenuOption = isAuthenticated + ? { + handler: onSignOut, + menuTitle: t("navigation.menu.signOut"), + title: t("navigation.menu.signOut"), + dataTestId: "profile-menu-sign-out", + } + : { + handler: onSignUpSignIn, + menuTitle: `${t("navigation.menu.signUp")} / ${t("navigation.menu.signIn")}`, + title: globalMessages.portfolio.signUp, + dataTestId: "profile-menu-sign-up", + }; + + useEffect(() => { + if (!showTutorial) setToggleTutorialState(false); + }, [showTutorial]); + + const onNavigateToBoards = () => { + history.push("/boards"); + }; + + return ( + + + + setTutFocusElemRef && ref && setTutFocusElemRef(ref) + } + > + + + - - - {!showTutorial && ( - - {dropdownContent} - - )} - - ); + + {!showTutorial && ( + + + + )} + + ); + } +); + +// Main wrapper component that delegates to mobile or desktop version +const ProfileMenuWrapper: React.FC = ({ + isMobile = false, + ...props +}) => { + if (isMobile) { + return ; + } + return ; }; export default ProfileMenuWrapper; From ace376f390a46517b06a8e48e06085a9bf3f7aeb Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 1 Dec 2025 14:50:36 +0100 Subject: [PATCH 14/79] feat: Integrate i18next for internationalization and update language handling in hooks --- .../src/api/hooks/usePreferredLanguage.ts | 62 +++---------------- .../frontend/src/api/hooks/useTutorial.ts | 4 +- packages/frontend/src/i18n.ts | 48 ++++++++++++++ packages/frontend/src/main.tsx | 1 + packages/frontend/src/pages/index.tsx | 3 +- 5 files changed, 59 insertions(+), 59 deletions(-) create mode 100644 packages/frontend/src/i18n.ts diff --git a/packages/frontend/src/api/hooks/usePreferredLanguage.ts b/packages/frontend/src/api/hooks/usePreferredLanguage.ts index 3554b01ef..bc7c6432b 100644 --- a/packages/frontend/src/api/hooks/usePreferredLanguage.ts +++ b/packages/frontend/src/api/hooks/usePreferredLanguage.ts @@ -1,16 +1,7 @@ import { useEffect, useRef } from "react"; import i18next from "i18next"; import moment from "moment-with-locales-es6"; -import { initReactI18next } from "react-i18next"; import { useDispatch } from "react-redux"; -import { - translationEN, - translationES, - translationFR, - translationJA, - translationTR, - translationZH, -} from "../../locales/translation"; import { alphadayApi } from "../services"; import { setSelectedLanguageCode } from "../store"; import { useAppSelector } from "../store/hooks"; @@ -18,49 +9,6 @@ import { ELanguageCode } from "../types/language"; import { Logger } from "../utils/logging"; import { useAllowedTranslations } from "./useAllowedTranslations"; -const resources: Record = { - en: { - translation: translationEN, - }, - ja: { - translation: translationJA, - }, - es: { - translation: translationES, - }, - fr: { - translation: translationFR, - }, - tr: { - translation: translationTR, - }, - zh: { - translation: translationZH, - }, -}; - -const i18nInit = (selectedLangCode: ELanguageCode) => { - i18next - .use(initReactI18next) - .init({ - debug: true, - resources, - fallbackLng: selectedLangCode, - detection: { - order: ["navigator", "htmlTag", "path", "subdomain"], - }, - interpolation: { - escapeValue: false, - }, - }) - .then(() => { - Logger.info("usePreferredLanguage: i18n initialized successfully"); - }) - .catch((e) => { - Logger.error("usePreferredLanguage: could not initialize i18n", e); - }); -}; - export const usePreferredLanguage = () => { const dispatch = useDispatch(); const { isLoading, languages } = useAllowedTranslations(); @@ -79,9 +27,13 @@ export const usePreferredLanguage = () => { if (lang && lang in languages && selectedLangCode !== lang) { dispatch(setSelectedLanguageCode({ code: lang as ELanguageCode })); prevLangCodeRef.current = lang as ELanguageCode; - i18nInit(lang as ELanguageCode); - } else { - i18nInit(selectedLangCode); + i18next.changeLanguage(lang).catch((e) => { + Logger.error("usePreferredLanguage: could not change language", e); + }); + } else if (i18next.language !== selectedLangCode) { + i18next.changeLanguage(selectedLangCode).catch((e) => { + Logger.error("usePreferredLanguage: could not change language", e); + }); } // this should only run once // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/packages/frontend/src/api/hooks/useTutorial.ts b/packages/frontend/src/api/hooks/useTutorial.ts index 47d5f61b6..011eeb1a3 100644 --- a/packages/frontend/src/api/hooks/useTutorial.ts +++ b/packages/frontend/src/api/hooks/useTutorial.ts @@ -21,7 +21,7 @@ interface ITutorial { } export const useTutorial: () => ITutorial = () => { - const { t } = useTranslation(); + const { t, ready } = useTranslation(); const dispatch = useAppDispatch(); const { tutFocusElemRef, setTutFocusElemRef } = useTutorialContext(); const { isFullSize } = useViewRoute(); @@ -33,7 +33,7 @@ export const useTutorial: () => ITutorial = () => { (key: string) => { return t(`tutorials.${key}`); }, - [t] + [t, ready] ); const translatedTutorials = useMemo( () => tutorials(translate), diff --git a/packages/frontend/src/i18n.ts b/packages/frontend/src/i18n.ts new file mode 100644 index 000000000..6e05bf76f --- /dev/null +++ b/packages/frontend/src/i18n.ts @@ -0,0 +1,48 @@ +import i18next from "i18next"; +import { initReactI18next } from "react-i18next"; +import { + translationEN, + translationES, + translationFR, + translationJA, + translationTR, + translationZH, +} from "./locales/translation"; +import { ELanguageCode } from "./api/types/language"; + +const resources: Record = { + en: { + translation: translationEN, + }, + ja: { + translation: translationJA, + }, + es: { + translation: translationES, + }, + fr: { + translation: translationFR, + }, + tr: { + translation: translationTR, + }, + zh: { + translation: translationZH, + }, +}; + +// Initialize i18n synchronously at module load time +i18next.use(initReactI18next).init({ + debug: true, + resources, + fallbackLng: ELanguageCode.EN, + lng: ELanguageCode.EN, + detection: { + order: ["navigator", "htmlTag", "path", "subdomain"], + }, + interpolation: { + escapeValue: false, + }, +}); + +export default i18next; diff --git a/packages/frontend/src/main.tsx b/packages/frontend/src/main.tsx index e75b733c4..aaf5f5f7d 100644 --- a/packages/frontend/src/main.tsx +++ b/packages/frontend/src/main.tsx @@ -1,4 +1,5 @@ import "./polyfills"; +import "./i18n"; import { Suspense } from "react"; import * as Sentry from "@sentry/react"; import { createRoot } from "react-dom/client"; diff --git a/packages/frontend/src/pages/index.tsx b/packages/frontend/src/pages/index.tsx index c415bffbc..a243445d5 100644 --- a/packages/frontend/src/pages/index.tsx +++ b/packages/frontend/src/pages/index.tsx @@ -76,7 +76,7 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { : () => dispatch(toggleRecipeLibrary()); const { toggleWidgetLib } = useWidgetLib(); - const { currentTutorial, setTutFocusElemRef } = useTutorial(); + const { currentTutorial, setTutFocusElemRef, showTutorial } = useTutorial(); const isAuthenticated = useAppSelector(userStore.selectIsAuthenticated); const windowSize = useWindowSize(); @@ -85,7 +85,6 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { aspectRatios: twoColWidgetAspectRatios, handleAspectRatioDetected, } = useImageWidget(selectedView); - const { showTutorial } = useTutorial(); const [isDraggedWidgetInView, setIsDraggedWidgetInView] = useState(false); From debcbdb46f7c6bb9546387821acbd2633b3455a4 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 1 Dec 2025 18:45:45 +0100 Subject: [PATCH 15/79] feat: Add MobileNavigation component for improved mobile layout and navigation --- packages/frontend/src/layout/MainLayout.tsx | 3 +- .../frontend/src/layout/MobileNavigation.tsx | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 packages/frontend/src/layout/MobileNavigation.tsx diff --git a/packages/frontend/src/layout/MainLayout.tsx b/packages/frontend/src/layout/MainLayout.tsx index 13deef061..bd510c451 100644 --- a/packages/frontend/src/layout/MainLayout.tsx +++ b/packages/frontend/src/layout/MainLayout.tsx @@ -3,6 +3,7 @@ import { Footer, twMerge } from "@alphaday/ui-kit"; import { TUserViewWidget } from "src/api/types"; import WidgetsLibContainer from "src/containers/widgets-library/WidgetsLibContainer"; import Header from "./LayoutHeader"; +import MobileNavigation from "./MobileNavigation"; interface IProps { hideFooter?: boolean; @@ -51,7 +52,7 @@ const MainLayout: React.FC = ({ {children}
- + {!hideFooter &&
}
); diff --git a/packages/frontend/src/layout/MobileNavigation.tsx b/packages/frontend/src/layout/MobileNavigation.tsx new file mode 100644 index 000000000..1363bc143 --- /dev/null +++ b/packages/frontend/src/layout/MobileNavigation.tsx @@ -0,0 +1,60 @@ +import React from "react"; +import { Link, useLocation } from "react-router-dom"; +import { useIsMobile } from "src/api/hooks"; +import { ReactComponent as WidgetsSVG } from "src/assets/icons/grid.svg"; +import { ReactComponent as SuperfeedSVG } from "src/assets/svg/superfeed.svg"; + +const CustomNavTab: React.FC<{ + label: string; + Icon: React.FC>; + disabled?: boolean; +}> = ({ label, Icon, disabled }) => ( +
+ + + + + {disabled ? `${label} (soon)` : label} + + {/* {disabled &&
(soon)
} */} +
+); + +const MobileNavigation = () => { + const isMobile = useIsMobile(); + const { pathname } = useLocation(); + + return ( + + ); +}; + +export default MobileNavigation; From 999b2d5175ff1a7d0ffa89b9c458d3c7310ce204 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 1 Dec 2025 19:21:48 +0100 Subject: [PATCH 16/79] feat: Enhance error handling and UI in GeneralError and ErrorContainer components; optimize MobileBoardsList rendering --- .../src/components/error/GeneralError.tsx | 2 +- .../src/containers/error/ErrorContainer.tsx | 2 +- .../mobile-components/MobileBoardsList.tsx | 67 ++++++++++++------- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/packages/frontend/src/components/error/GeneralError.tsx b/packages/frontend/src/components/error/GeneralError.tsx index 0d8cae566..8dbef8a17 100644 --- a/packages/frontend/src/components/error/GeneralError.tsx +++ b/packages/frontend/src/components/error/GeneralError.tsx @@ -21,7 +21,7 @@ const GeneralError: FC<{ children?: React.ReactNode }> = ({ children }) => { ) : ( {status} )} -

+

{t("errorPage.default.description.text")}{" "} = ({ }) => { const sortOptions = generateSortOptions(); const { t } = useTranslation(); - const [activeSection, setActiveSection] = useState<"custom" | "all">("custom"); + const [activeSection, setActiveSection] = useState<"custom" | "all">( + "custom" + ); const customBoards = subscribedViews ?.filter((board) => !board.is_system_view) @@ -215,6 +217,36 @@ const MobileBoardsList: FC = ({ }) : sortByKey; + const childPreview = useMemo(() => { + if (isFetching && allBoards?.length === 0) { + return ; + } + if (allBoards?.length === 0) { + return ; + } + return ( + + {allBoards?.map((view) => ( + + ))} + + ); + }, [ + allBoards, + isAuthenticated, + isFetching, + onBoardPin, + onSelectView, + selectedViewId, + ]); + if (customBoards === undefined || allBoards === undefined) { return ; } @@ -261,12 +293,18 @@ const MobileBoardsList: FC = ({

-
- {isFetching && allBoards.length === 0 ? ( - - ) : allBoards.length === 0 ? ( - - ) : ( - allBoards.map((view) => ( - - )) - )} -
+
{childPreview}
)} From b6b46c72babda57ab66d81b80f6866917d266f03 Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 2 Dec 2025 16:25:43 +0100 Subject: [PATCH 17/79] feat: Improve i18next initialization with error logging; clean up imports and optimize hooks --- packages/frontend/src/MobileApp.tsx | 2 +- .../src/api/hooks/usePreferredLanguage.ts | 10 ++++-- .../frontend/src/api/hooks/useTutorial.ts | 4 +-- packages/frontend/src/i18n.ts | 32 +++++++++++-------- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/packages/frontend/src/MobileApp.tsx b/packages/frontend/src/MobileApp.tsx index 451618424..01af63f41 100644 --- a/packages/frontend/src/MobileApp.tsx +++ b/packages/frontend/src/MobileApp.tsx @@ -7,10 +7,10 @@ import { useHistory, useLocation, } from "react-router-dom"; +import { ReactComponent as BoardsSVG } from "src/assets/icons/grid.svg"; import { ReactComponent as MarketsSVG } from "src/assets/svg/markets.svg"; import { ReactComponent as PortfolioSVG } from "src/assets/svg/portfolio.svg"; import { ReactComponent as SuperfeedSVG } from "src/assets/svg/superfeed.svg"; -import { ReactComponent as BoardsSVG } from "src/assets/icons/grid.svg"; import { useAuth, useViewRoute } from "./api/hooks"; import CONFIG from "./config"; import ToastContainer from "./containers/toasts/ToastContainer"; diff --git a/packages/frontend/src/api/hooks/usePreferredLanguage.ts b/packages/frontend/src/api/hooks/usePreferredLanguage.ts index bc7c6432b..3e7ecc1f1 100644 --- a/packages/frontend/src/api/hooks/usePreferredLanguage.ts +++ b/packages/frontend/src/api/hooks/usePreferredLanguage.ts @@ -28,11 +28,17 @@ export const usePreferredLanguage = () => { dispatch(setSelectedLanguageCode({ code: lang as ELanguageCode })); prevLangCodeRef.current = lang as ELanguageCode; i18next.changeLanguage(lang).catch((e) => { - Logger.error("usePreferredLanguage: could not change language", e); + Logger.error( + "usePreferredLanguage: could not change language", + e + ); }); } else if (i18next.language !== selectedLangCode) { i18next.changeLanguage(selectedLangCode).catch((e) => { - Logger.error("usePreferredLanguage: could not change language", e); + Logger.error( + "usePreferredLanguage: could not change language", + e + ); }); } // this should only run once diff --git a/packages/frontend/src/api/hooks/useTutorial.ts b/packages/frontend/src/api/hooks/useTutorial.ts index 011eeb1a3..47d5f61b6 100644 --- a/packages/frontend/src/api/hooks/useTutorial.ts +++ b/packages/frontend/src/api/hooks/useTutorial.ts @@ -21,7 +21,7 @@ interface ITutorial { } export const useTutorial: () => ITutorial = () => { - const { t, ready } = useTranslation(); + const { t } = useTranslation(); const dispatch = useAppDispatch(); const { tutFocusElemRef, setTutFocusElemRef } = useTutorialContext(); const { isFullSize } = useViewRoute(); @@ -33,7 +33,7 @@ export const useTutorial: () => ITutorial = () => { (key: string) => { return t(`tutorials.${key}`); }, - [t, ready] + [t] ); const translatedTutorials = useMemo( () => tutorials(translate), diff --git a/packages/frontend/src/i18n.ts b/packages/frontend/src/i18n.ts index 6e05bf76f..056884b63 100644 --- a/packages/frontend/src/i18n.ts +++ b/packages/frontend/src/i18n.ts @@ -1,5 +1,7 @@ import i18next from "i18next"; import { initReactI18next } from "react-i18next"; +import { ELanguageCode } from "./api/types/language"; +import { Logger } from "./api/utils/logging"; import { translationEN, translationES, @@ -8,7 +10,6 @@ import { translationTR, translationZH, } from "./locales/translation"; -import { ELanguageCode } from "./api/types/language"; const resources: Record = { en: { @@ -32,17 +33,22 @@ const resources: Record = { }; // Initialize i18n synchronously at module load time -i18next.use(initReactI18next).init({ - debug: true, - resources, - fallbackLng: ELanguageCode.EN, - lng: ELanguageCode.EN, - detection: { - order: ["navigator", "htmlTag", "path", "subdomain"], - }, - interpolation: { - escapeValue: false, - }, -}); +i18next + .use(initReactI18next) + .init({ + debug: true, + resources, + fallbackLng: ELanguageCode.EN, + lng: ELanguageCode.EN, + detection: { + order: ["navigator", "htmlTag", "path", "subdomain"], + }, + interpolation: { + escapeValue: false, + }, + }) + .catch((error: Error) => { + Logger.error("Failed to initialize i18next:", error); + }); export default i18next; From b6f20fb9c4bcef21cf122fd5879506d5f095a1cc Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 2 Dec 2025 16:57:22 +0100 Subject: [PATCH 18/79] feat: Comment out unused BoardsSVG import and Link component for cleaner code --- packages/frontend/src/MobileApp.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/MobileApp.tsx b/packages/frontend/src/MobileApp.tsx index 01af63f41..0fadf8839 100644 --- a/packages/frontend/src/MobileApp.tsx +++ b/packages/frontend/src/MobileApp.tsx @@ -7,7 +7,7 @@ import { useHistory, useLocation, } from "react-router-dom"; -import { ReactComponent as BoardsSVG } from "src/assets/icons/grid.svg"; +// import { ReactComponent as BoardsSVG } from "src/assets/icons/grid.svg"; import { ReactComponent as MarketsSVG } from "src/assets/svg/markets.svg"; import { ReactComponent as PortfolioSVG } from "src/assets/svg/portfolio.svg"; import { ReactComponent as SuperfeedSVG } from "src/assets/svg/superfeed.svg"; @@ -140,7 +140,7 @@ const RouterChild = () => { > - { }`} > - + */} {IS_DEV && ( Date: Tue, 2 Dec 2025 17:36:57 +0100 Subject: [PATCH 19/79] feat: Remove unused isFetching prop from BoardsContainer for cleaner code --- .../mobile-components/MobileBoardsList.tsx | 80 +++++++------------ .../src/mobile-containers/BoardsContainer.tsx | 2 +- 2 files changed, 30 insertions(+), 52 deletions(-) diff --git a/packages/frontend/src/mobile-components/MobileBoardsList.tsx b/packages/frontend/src/mobile-components/MobileBoardsList.tsx index b52eb0f3a..acd1b6e59 100644 --- a/packages/frontend/src/mobile-components/MobileBoardsList.tsx +++ b/packages/frontend/src/mobile-components/MobileBoardsList.tsx @@ -1,4 +1,4 @@ -import { FC, FormEvent, useCallback, useMemo, useState } from "react"; +import { FC, FormEvent, useCallback, useState } from "react"; import { BoardPreview, ModuleLoader, @@ -111,7 +111,6 @@ interface IMobileBoardsList { selectedViewId: number | undefined; isAuthenticated: boolean; sortBy: EItemsSortBy; - isFetching: boolean; onSortBy(sort: string): void; onSelectView: (viewId: number) => void; onSubscribeView: (viewId: number) => void; @@ -146,13 +145,10 @@ const MobileBoardsList: FC = ({ isAuthenticated, subscribedViews, onEditView, - isFetching, }) => { const sortOptions = generateSortOptions(); const { t } = useTranslation(); - const [activeSection, setActiveSection] = useState<"custom" | "all">( - "custom" - ); + const [activeSection, setActiveSection] = useState<"custom" | "all">("all"); const customBoards = subscribedViews ?.filter((board) => !board.is_system_view) @@ -217,36 +213,6 @@ const MobileBoardsList: FC = ({ }) : sortByKey; - const childPreview = useMemo(() => { - if (isFetching && allBoards?.length === 0) { - return ; - } - if (allBoards?.length === 0) { - return ; - } - return ( - - {allBoards?.map((view) => ( - - ))} - - ); - }, [ - allBoards, - isAuthenticated, - isFetching, - onBoardPin, - onSelectView, - selectedViewId, - ]); - if (customBoards === undefined || allBoards === undefined) { return ; } @@ -264,9 +230,9 @@ const MobileBoardsList: FC = ({ type="button" onClick={() => setActiveSection("custom")} className={twMerge( - "flex-1 py-4 text-center fontGroup-highlight border-b-2 transition-colors", + "flex-1 pb-2 text-center fontGroup-highlight border-b-2 transition-colors", activeSection === "custom" - ? "border-accentVariant100 text-primary" + ? "border-primary text-primary" : "border-transparent text-primaryVariant100" )} > @@ -276,9 +242,9 @@ const MobileBoardsList: FC = ({ type="button" onClick={() => setActiveSection("all")} className={twMerge( - "flex-1 py-4 text-center fontGroup-highlight border-b-2 transition-colors", + "flex-1 pb-2 text-center fontGroup-highlight border-b-2 transition-colors", activeSection === "all" - ? "border-accentVariant100 text-primary" + ? "border-primary text-primary" : "border-transparent text-primaryVariant100" )} > @@ -289,7 +255,7 @@ const MobileBoardsList: FC = ({ {/* Custom Boards Section */} {activeSection === "custom" && ( -
+
@@ -311,16 +277,16 @@ const MobileBoardsList: FC = ({ )}
-
+
{customBoards.length === 0 && isAuthenticated ? ( ) : ( @@ -343,8 +309,8 @@ const MobileBoardsList: FC = ({ {/* All Boards Section */} {activeSection === "all" && ( -
-
+
+
{ @@ -359,10 +325,7 @@ const MobileBoardsList: FC = ({ : DEFAULT_TAB_OPTION } /> -
- - System Boards - +
= ({
-
{childPreview}
+
+ {customBoards.length === 0 && isAuthenticated ? ( + + ) : ( + allBoards?.map((view) => ( + + )) + )} +
)}
diff --git a/packages/frontend/src/mobile-containers/BoardsContainer.tsx b/packages/frontend/src/mobile-containers/BoardsContainer.tsx index d67851803..96ceac52b 100644 --- a/packages/frontend/src/mobile-containers/BoardsContainer.tsx +++ b/packages/frontend/src/mobile-containers/BoardsContainer.tsx @@ -280,7 +280,7 @@ const BoardsContainer: FC = () => { onRemoveView={handleRemoveView} onEditView={handleEditView} isAuthenticated={isAuthenticated} - isFetching={isFetching} + // isFetching={isFetching} /> ); }; From 45175df59b6951a027a38f88862ddaea7cd60370 Mon Sep 17 00:00:00 2001 From: Xharles Date: Tue, 2 Dec 2025 17:42:27 +0100 Subject: [PATCH 20/79] feat: Update CustomNavTab styling for improved layout and accessibility --- packages/frontend/src/layout/MobileNavigation.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/layout/MobileNavigation.tsx b/packages/frontend/src/layout/MobileNavigation.tsx index 1363bc143..e575a8a70 100644 --- a/packages/frontend/src/layout/MobileNavigation.tsx +++ b/packages/frontend/src/layout/MobileNavigation.tsx @@ -11,9 +11,9 @@ const CustomNavTab: React.FC<{ }> = ({ label, Icon, disabled }) => (
- + - + {disabled ? `${label} (soon)` : label} {/* {disabled &&
(soon)
} */} @@ -26,7 +26,7 @@ const MobileNavigation = () => { return (
-
+
{customBoards.length === 0 && isAuthenticated ? ( ) : ( @@ -335,7 +335,7 @@ const MobileBoardsList: FC = ({
-
+
{customBoards.length === 0 && isAuthenticated ? ( ) : ( From 33f098d785bd71256c4a72081155dfad1cb0e40c Mon Sep 17 00:00:00 2001 From: Xharles Date: Thu, 4 Dec 2025 07:00:06 +0100 Subject: [PATCH 22/79] feat: Add Widgets feature with routing, container, and mobile components --- packages/frontend/src/App.tsx | 13 +- .../frontend/src/api/hooks/useViewRoute.ts | 5 + packages/frontend/src/layout/LayoutHeader.tsx | 2 +- .../frontend/src/layout/MobileNavigation.tsx | 6 +- .../mobile-components/MobileWidgetsList.tsx | 219 ++++++++++++++++++ .../mobile-containers/WidgetsContainer.tsx | 170 ++++++++++++++ .../frontend/src/mobile-pages/widgets.tsx | 12 + packages/frontend/src/routes.ts | 10 +- 8 files changed, 427 insertions(+), 10 deletions(-) create mode 100644 packages/frontend/src/mobile-components/MobileWidgetsList.tsx create mode 100644 packages/frontend/src/mobile-containers/WidgetsContainer.tsx create mode 100644 packages/frontend/src/mobile-pages/widgets.tsx diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx index cf6d13cdd..ea8c220c0 100644 --- a/packages/frontend/src/App.tsx +++ b/packages/frontend/src/App.tsx @@ -37,8 +37,13 @@ const AppRoutes = () => { }); const resolvedView = useResolvedView(); - const { pathContainsHashOrSlug, isRoot, isSuperfeed, isBoardsLibrary } = - useViewRoute(); + const { + pathContainsHashOrSlug, + isRoot, + isSuperfeed, + isBoardsLibrary, + isWidgets, + } = useViewRoute(); const errorCode = useMemo(() => { /** @@ -49,7 +54,8 @@ const AppRoutes = () => { !pathContainsHashOrSlug && !isRoot && !isSuperfeed && - !isBoardsLibrary + !isBoardsLibrary && + !isWidgets ) { return 404; } @@ -60,6 +66,7 @@ const AppRoutes = () => { isRoot, isSuperfeed, isBoardsLibrary, + isWidgets, error, resolvedView.error, ]); diff --git a/packages/frontend/src/api/hooks/useViewRoute.ts b/packages/frontend/src/api/hooks/useViewRoute.ts index 34e50d968..5bab6121e 100644 --- a/packages/frontend/src/api/hooks/useViewRoute.ts +++ b/packages/frontend/src/api/hooks/useViewRoute.ts @@ -48,6 +48,10 @@ interface IViewRouteInfo { * true if the current path is boards library path */ isBoardsLibrary: boolean; + /** + * true if the current path is widgets path + */ + isWidgets: boolean; } export const useViewRoute = (): IViewRouteInfo => { @@ -130,6 +134,7 @@ export const useViewRoute = (): IViewRouteInfo => { isBoardsLibrary: location.pathname.includes( EDesktopRoutePaths.BoardsLibrary ), + isWidgets: location.pathname.includes(EDesktopRoutePaths.Widgets), }; }; diff --git a/packages/frontend/src/layout/LayoutHeader.tsx b/packages/frontend/src/layout/LayoutHeader.tsx index e18520027..6cbbd3bd6 100644 --- a/packages/frontend/src/layout/LayoutHeader.tsx +++ b/packages/frontend/src/layout/LayoutHeader.tsx @@ -63,7 +63,7 @@ const LayoutHeader: FC = ({ const { width } = useWindowSize(); return ( -
+
{width >= breakpoints.TwoColMinWidth ? ( { }} > ( +
+
+ +
+

+ {msg} +

+
+); + +interface IMobileWidgetsList { + selectedCategory: string | undefined; + widgets: ReadonlyArray | undefined; + categories: ReadonlyArray | undefined; + sortBy: EItemsSortBy; + onSortBy(sort: string): void; + onSelectWidget: (widgetId: number) => void; + onCategorySelect: (category: string | undefined) => void; + handlePaginate: (type: "next" | "previous") => void; + onFilter: (filter: string) => void; + cachedWidgets: ReadonlyArray | undefined; + selectedWidget: TWidgetMini | undefined; +} + +const MobileWidgetsList: FC = ({ + sortBy, + widgets, + categories, + selectedCategory, + onSortBy, + onSelectWidget, + onCategorySelect, + handlePaginate, + onFilter, + cachedWidgets, + selectedWidget, +}) => { + const sortOptions = generateSortOptions(); + const { t } = useTranslation(); + + const tabOptions = + categories?.map((cat) => + cat.slug === "default" + ? DEFAULT_TAB_OPTION + : { + label: cat.name, + value: cat.slug, + } + ) || []; + + const handleScrollEvent = useCallback( + ({ currentTarget }: FormEvent) => { + if (shouldFetchMoreItems(currentTarget)) { + handlePaginate("next"); + } + }, + [handlePaginate] + ); + + const handleFilterChange = (e: ChangeEvent) => { + onFilter(e.target.value); + }; + + const sortByKey = + Object.keys(EItemsSortBy)[Object.values(EItemsSortBy).indexOf(sortBy)]; + + const selectedSortValue = + Object.keys(ETranslationValues).indexOf(sortByKey.toLowerCase()) !== -1 + ? translateLabels(sortByKey.toLowerCase() as TTranslationValues, { + isKey: true, + }) + : sortByKey; + + if (categories === undefined || widgets === undefined) { + return ; + } + + return ( +
+ {/* Header */} +
+
+
+ +
+
+
+ + {/* Categories and Widgets Section */} +
+
+ { + onCategorySelect(name); + }} + selectedOption={ + selectedCategory + ? { + label: selectedCategory, + value: selectedCategory, + } + : DEFAULT_TAB_OPTION + } + /> +
+
+ + {widgets.length} {t("navigation.widgets")} + +
+ +
+
+ + {widgets.length === 0 ? ( + c.slug === selectedCategory + )?.name || "this category" + }` + : "" + }`} + /> + ) : ( +
+ {widgets.map((widget) => { + const widgetCount = + cachedWidgets?.filter( + (cw) => cw.slug === widget.slug + ).length || 0; + return ( +
onSelectWidget(widget.id)} + > + + onSelectWidget(widget.id) + } + selected={ + widget.slug === selectedWidget?.slug + } + isMaxed={ + widget.max_per_view !== null && + widgetCount >= widget.max_per_view + } + /> +
+ ); + })} +
+ )} +
+
+ ); +}; + +export default MobileWidgetsList; diff --git a/packages/frontend/src/mobile-containers/WidgetsContainer.tsx b/packages/frontend/src/mobile-containers/WidgetsContainer.tsx new file mode 100644 index 000000000..201bed57b --- /dev/null +++ b/packages/frontend/src/mobile-containers/WidgetsContainer.tsx @@ -0,0 +1,170 @@ +import { FC, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { usePagination, useView } from "src/api/hooks"; +import { + EItemsSortBy, + TRemoteWidgetMini, + useGetWidgetsCategoryQuery, + useGetWidgetsQuery, +} from "src/api/services"; +import { TWidget, TWidgetMini } from "src/api/types"; +import { debounce } from "src/api/utils/helpers"; +import { Logger } from "src/api/utils/logging"; +import { getSortOptionValue } from "src/api/utils/sortOptions"; +import CONFIG from "src/config/config"; +import MobileWidgetsList from "src/mobile-components/MobileWidgetsList"; + +const INITIAL_PAGE = 1; + +const WidgetsContainer: FC = () => { + const { selectedView } = useView(); + const [selectedCategory, setSelectedCategory] = useState< + string | undefined + >(); + const [currentPage, setCurrentPage] = useState(INITIAL_PAGE); + const [sortBy, setSortBy] = useState(EItemsSortBy.Name); + const [filter, setFilter] = useState(); + const [selectedWidget, setSelectedWidget] = useState(); + + const { data: categories } = useGetWidgetsCategoryQuery(); + + const { + currentData: widgetsDataResponse, + isSuccess, + isFetching, + } = useGetWidgetsQuery({ + limit: CONFIG.UI.WIDGETS_LIBRARY.LIMIT, + page: currentPage, + sortBy, + search: filter, + }); + + const [allWidgets, setAllWidgets] = useState([]); + + // shallow copy necessary because response is read-only + const widgetsDataForCurrentPage = useMemo( + () => [...(widgetsDataResponse?.results ?? [])], + [widgetsDataResponse?.results] + ); + const prevWidgetsDataRef = useRef(); + + // if the current response changes, it means the user scrolled down + // and a request for the next page has completed + // When user subscribed/unsubscribed from a widget, the response may include + // items that were already in a previous response, so we need to handle this + // as well. + if ( + widgetsDataResponse?.results !== undefined && + prevWidgetsDataRef.current !== widgetsDataForCurrentPage + ) { + setAllWidgets((prevState) => { + const updatedWidgetArray = [...prevState]; + widgetsDataForCurrentPage.forEach((updatedWidget) => { + const existingWidgetIdx = prevState.findIndex( + (existingWidget) => existingWidget.id === updatedWidget.id + ); + if (existingWidgetIdx !== -1) { + updatedWidgetArray[existingWidgetIdx] = { + ...updatedWidgetArray[existingWidgetIdx], + ...updatedWidget, + }; + } else { + updatedWidgetArray.push(updatedWidget); + } + }); + return updatedWidgetArray; + }); + prevWidgetsDataRef.current = widgetsDataForCurrentPage; + } + + const handleSelectWidget = useCallback( + (widgetId: number) => { + setSelectedWidget( + allWidgets.find((widget) => widget.id === widgetId) + ); + Logger.debug( + "WidgetsContainer::handleSelectWidget called on widget:", + widgetId + ); + // For now, just log the selection + // In the future, this could open a widget detail modal or add to a board + }, + [allWidgets] + ); + + const handleSortBy = (sortValue: string): void => { + const sort = getSortOptionValue(sortValue); + if (isFetching || sort === null || sortBy === sort) return; + if (allWidgets.length > 0) setAllWidgets([]); + if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); + setSortBy(sort); + }; + + const handleCategorySelect = (newCategory: string | undefined): void => { + if (isFetching || newCategory === selectedCategory) return; + if (allWidgets.length > 0) setAllWidgets([]); + if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); + setSelectedCategory(newCategory); + }; + + const handleFilter = debounce((value: string) => { + const normalizedValue = value.toLowerCase(); + if (filter === normalizedValue) return; + if (allWidgets.length > 0) setAllWidgets([]); + if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); + setFilter(normalizedValue); + }, 300); + + const { nextPage, handleNextPage } = usePagination( + widgetsDataResponse?.links, + CONFIG.UI.WIDGETS_LIBRARY.LIMIT, + isSuccess + ); + + if ( + resolvedWidget !== undefined && + resolvedWidget.id !== previousResolvedWidgetId.current + ) { + addWidgetToCurrentLayout(); + previousResolvedWidgetId.current = resolvedWidget.id; + } + + // set current page 350ms after next page is set. + // RTK should cache requests, so we don't need to be too careful about rerenders. + useEffect(() => { + if (nextPage === undefined) return () => null; + const timeout = setTimeout(() => { + setCurrentPage(nextPage); + }, 350); + return () => { + clearTimeout(timeout); + }; + }, [nextPage]); + + return ( + { + // filter by category. If no category is selected, show all widgets + return ( + !selectedCategory || + w.categories.some((c) => { + return c.slug === selectedCategory; + }) + ); + })} + categories={categories?.results} + onSelectWidget={handleSelectWidget} + onCategorySelect={handleCategorySelect} + sortBy={sortBy} + onSortBy={handleSortBy} + handlePaginate={handleNextPage} + onFilter={handleFilter} + cachedWidgets={selectedView?.data.widgets?.map( + (sw) => sw.widget as TWidget + )} + selectedWidget={selectedWidget} + /> + ); +}; + +export default WidgetsContainer; diff --git a/packages/frontend/src/mobile-pages/widgets.tsx b/packages/frontend/src/mobile-pages/widgets.tsx new file mode 100644 index 000000000..d212fccd5 --- /dev/null +++ b/packages/frontend/src/mobile-pages/widgets.tsx @@ -0,0 +1,12 @@ +import MainLayout from "src/layout/MainLayout"; +import WidgetsContainer from "src/mobile-containers/WidgetsContainer"; + +const WidgetsPage: React.FC = () => { + return ( + + + + ); +}; + +export default WidgetsPage; diff --git a/packages/frontend/src/routes.ts b/packages/frontend/src/routes.ts index 42e76c985..de22f4905 100644 --- a/packages/frontend/src/routes.ts +++ b/packages/frontend/src/routes.ts @@ -30,6 +30,7 @@ const AddHoldingPage = lazyRetry(() => import("./mobile-pages/add-holding")); const PortfolioHoldingsPage = lazyRetry( () => import("./mobile-pages/portfolio-holdings") ); +const WidgetsPage = lazyRetry(() => import("./mobile-pages/widgets")); /** * A basic route. @@ -74,7 +75,8 @@ export enum EDesktopRoutePaths { CalendarEvent = "/b/:slug/calendar/event/:eventId/:eventTitle", FallBack = "*", Superfeed = "/superfeed", - BoardsLibrary = `/boards`, + BoardsLibrary = "/boards", + Widgets = "/widgets", } /** @@ -120,6 +122,12 @@ export const desktopRoutes: TRoute[] = [ component: BoardsPage, exact: true, }, + { + type: "regular", + path: EDesktopRoutePaths.Widgets, + component: WidgetsPage, + exact: true, + }, ]; /** From 6aa15709e59ed4849759d227186acd35a3e0e10a Mon Sep 17 00:00:00 2001 From: Xharles Date: Thu, 4 Dec 2025 07:24:53 +0100 Subject: [PATCH 23/79] feat: Implement responsive layout handling for mobile widgets and refactor WidgetsContainer --- .../frontend/src/api/utils/layoutUtils.ts | 47 +++++ .../widgets-library/WidgetsLibContainer.tsx | 35 +++- .../mobile-components/MobileWidgetsList.tsx | 8 +- .../mobile-containers/WidgetsContainer.tsx | 170 ------------------ .../frontend/src/mobile-pages/widgets.tsx | 14 +- packages/frontend/src/pages/index.tsx | 35 +--- 6 files changed, 100 insertions(+), 209 deletions(-) delete mode 100644 packages/frontend/src/mobile-containers/WidgetsContainer.tsx diff --git a/packages/frontend/src/api/utils/layoutUtils.ts b/packages/frontend/src/api/utils/layoutUtils.ts index 92be440cb..312b3ac00 100644 --- a/packages/frontend/src/api/utils/layoutUtils.ts +++ b/packages/frontend/src/api/utils/layoutUtils.ts @@ -308,3 +308,50 @@ export const calculateTwoColWidgetsHeight = ( return totalHeight; }; + +/** + * Computes the layout state from a selected view based on the window width. + * This function determines which column layout to use (single, two, three, or four column) + * and returns the corresponding widget arrangement. + * + * @param selectedView - The current selected view containing widgets + * @param windowWidth - The current window width in pixels + * @returns The layout state as a 2D array of widgets, or undefined if the view or layout is invalid + * + * @example + * const layoutState = getLayoutStateFromView(selectedView, 1920); + * // Returns four-column layout for wide screens + */ +export const getLayoutStateFromView = ( + selectedView: TCachedView | undefined, + windowWidth: number +): TUserViewWidget[][] | undefined => { + if (!selectedView) return undefined; + + const twoColWidgetSlugs = getTwoColWidgetTemplateSlugs(); + const layoutGrid = computeLayoutGrid( + selectedView.data.widgets.filter( + (w) => !twoColWidgetSlugs.includes(w.widget.template.slug) + ) + ); + + if (!layoutGrid) return undefined; + + const colType = getColType(windowWidth); + + if (colType === EColumnType.SingleCol && layoutGrid.singleCol) { + return layoutGrid.singleCol; + } + if (colType === EColumnType.TwoCol && layoutGrid.twoCol) { + return layoutGrid.twoCol; + } + if (colType === EColumnType.ThreeCol && layoutGrid.threeCol) { + return layoutGrid.threeCol; + } + + if (layoutGrid.fourCol) { + return layoutGrid.fourCol; + } + + return undefined; +}; diff --git a/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx b/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx index 98e212c82..553c24d57 100644 --- a/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx +++ b/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx @@ -18,6 +18,7 @@ import { getSortOptionValue } from "src/api/utils/sortOptions"; import { EToastRole, toast } from "src/api/utils/toastUtils"; import WidgetLibrary from "src/components/widget-library/WidgetLibrary"; import CONFIG from "src/config/config"; +import MobileWidgetsList from "src/mobile-components/MobileWidgetsList"; import { v4 as uuidv4 } from "uuid"; const { VIEWS } = CONFIG; @@ -25,8 +26,12 @@ const INITIAL_PAGE = 1; interface IWidgetLibContainerProps { layoutState: TUserViewWidget[][] | undefined; + isMobile?: boolean; } -const WidgetsLibContainer: FC = ({ layoutState }) => { +const WidgetsLibContainer: FC = ({ + layoutState, + isMobile, +}) => { const { selectedView, addWidgetsToCache } = useView(); const { keywordSearchList } = useGlobalSearch(); @@ -217,6 +222,34 @@ const WidgetsLibContainer: FC = ({ layoutState }) => { }; }, [nextPage]); + if (isMobile) { + { + // filter by category. If no category is selected, show all widgets + return ( + !selectedCategory || + w.categories.some((c) => { + return c.slug === selectedCategory; + }) + ); + })} + categories={[...(widgetsCategory?.results || [])].sort( + (a, d) => a.sort_order - d.sort_order + )} + onSelectWidget={handleSelectWidget} + onCategorySelect={setSelectedCategory} + sortBy={sortBy} + onSortBy={handleSortBy} + handlePaginate={handleNextPage} + onFilter={handleFilter} + cachedWidgets={selectedView?.data.widgets?.map( + (sw) => sw.widget as TWidget + )} + selectedWidget={selectedWidget} + />; + } + return ( | undefined; sortBy: EItemsSortBy; onSortBy(sort: string): void; - onSelectWidget: (widgetId: number) => void; + onSelectWidget: (w: TWidgetMini) => void; onCategorySelect: (category: string | undefined) => void; handlePaginate: (type: "next" | "previous") => void; onFilter: (filter: string) => void; @@ -188,16 +188,14 @@ const MobileWidgetsList: FC = ({ className="w-full" tabIndex={0} role="button" - onClick={() => onSelectWidget(widget.id)} + onClick={() => onSelectWidget(widget)} > - onSelectWidget(widget.id) - } + onClick={() => onSelectWidget(widget)} selected={ widget.slug === selectedWidget?.slug } diff --git a/packages/frontend/src/mobile-containers/WidgetsContainer.tsx b/packages/frontend/src/mobile-containers/WidgetsContainer.tsx deleted file mode 100644 index 201bed57b..000000000 --- a/packages/frontend/src/mobile-containers/WidgetsContainer.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import { FC, useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { usePagination, useView } from "src/api/hooks"; -import { - EItemsSortBy, - TRemoteWidgetMini, - useGetWidgetsCategoryQuery, - useGetWidgetsQuery, -} from "src/api/services"; -import { TWidget, TWidgetMini } from "src/api/types"; -import { debounce } from "src/api/utils/helpers"; -import { Logger } from "src/api/utils/logging"; -import { getSortOptionValue } from "src/api/utils/sortOptions"; -import CONFIG from "src/config/config"; -import MobileWidgetsList from "src/mobile-components/MobileWidgetsList"; - -const INITIAL_PAGE = 1; - -const WidgetsContainer: FC = () => { - const { selectedView } = useView(); - const [selectedCategory, setSelectedCategory] = useState< - string | undefined - >(); - const [currentPage, setCurrentPage] = useState(INITIAL_PAGE); - const [sortBy, setSortBy] = useState(EItemsSortBy.Name); - const [filter, setFilter] = useState(); - const [selectedWidget, setSelectedWidget] = useState(); - - const { data: categories } = useGetWidgetsCategoryQuery(); - - const { - currentData: widgetsDataResponse, - isSuccess, - isFetching, - } = useGetWidgetsQuery({ - limit: CONFIG.UI.WIDGETS_LIBRARY.LIMIT, - page: currentPage, - sortBy, - search: filter, - }); - - const [allWidgets, setAllWidgets] = useState([]); - - // shallow copy necessary because response is read-only - const widgetsDataForCurrentPage = useMemo( - () => [...(widgetsDataResponse?.results ?? [])], - [widgetsDataResponse?.results] - ); - const prevWidgetsDataRef = useRef(); - - // if the current response changes, it means the user scrolled down - // and a request for the next page has completed - // When user subscribed/unsubscribed from a widget, the response may include - // items that were already in a previous response, so we need to handle this - // as well. - if ( - widgetsDataResponse?.results !== undefined && - prevWidgetsDataRef.current !== widgetsDataForCurrentPage - ) { - setAllWidgets((prevState) => { - const updatedWidgetArray = [...prevState]; - widgetsDataForCurrentPage.forEach((updatedWidget) => { - const existingWidgetIdx = prevState.findIndex( - (existingWidget) => existingWidget.id === updatedWidget.id - ); - if (existingWidgetIdx !== -1) { - updatedWidgetArray[existingWidgetIdx] = { - ...updatedWidgetArray[existingWidgetIdx], - ...updatedWidget, - }; - } else { - updatedWidgetArray.push(updatedWidget); - } - }); - return updatedWidgetArray; - }); - prevWidgetsDataRef.current = widgetsDataForCurrentPage; - } - - const handleSelectWidget = useCallback( - (widgetId: number) => { - setSelectedWidget( - allWidgets.find((widget) => widget.id === widgetId) - ); - Logger.debug( - "WidgetsContainer::handleSelectWidget called on widget:", - widgetId - ); - // For now, just log the selection - // In the future, this could open a widget detail modal or add to a board - }, - [allWidgets] - ); - - const handleSortBy = (sortValue: string): void => { - const sort = getSortOptionValue(sortValue); - if (isFetching || sort === null || sortBy === sort) return; - if (allWidgets.length > 0) setAllWidgets([]); - if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); - setSortBy(sort); - }; - - const handleCategorySelect = (newCategory: string | undefined): void => { - if (isFetching || newCategory === selectedCategory) return; - if (allWidgets.length > 0) setAllWidgets([]); - if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); - setSelectedCategory(newCategory); - }; - - const handleFilter = debounce((value: string) => { - const normalizedValue = value.toLowerCase(); - if (filter === normalizedValue) return; - if (allWidgets.length > 0) setAllWidgets([]); - if (currentPage !== INITIAL_PAGE) setCurrentPage(INITIAL_PAGE); - setFilter(normalizedValue); - }, 300); - - const { nextPage, handleNextPage } = usePagination( - widgetsDataResponse?.links, - CONFIG.UI.WIDGETS_LIBRARY.LIMIT, - isSuccess - ); - - if ( - resolvedWidget !== undefined && - resolvedWidget.id !== previousResolvedWidgetId.current - ) { - addWidgetToCurrentLayout(); - previousResolvedWidgetId.current = resolvedWidget.id; - } - - // set current page 350ms after next page is set. - // RTK should cache requests, so we don't need to be too careful about rerenders. - useEffect(() => { - if (nextPage === undefined) return () => null; - const timeout = setTimeout(() => { - setCurrentPage(nextPage); - }, 350); - return () => { - clearTimeout(timeout); - }; - }, [nextPage]); - - return ( - { - // filter by category. If no category is selected, show all widgets - return ( - !selectedCategory || - w.categories.some((c) => { - return c.slug === selectedCategory; - }) - ); - })} - categories={categories?.results} - onSelectWidget={handleSelectWidget} - onCategorySelect={handleCategorySelect} - sortBy={sortBy} - onSortBy={handleSortBy} - handlePaginate={handleNextPage} - onFilter={handleFilter} - cachedWidgets={selectedView?.data.widgets?.map( - (sw) => sw.widget as TWidget - )} - selectedWidget={selectedWidget} - /> - ); -}; - -export default WidgetsContainer; diff --git a/packages/frontend/src/mobile-pages/widgets.tsx b/packages/frontend/src/mobile-pages/widgets.tsx index d212fccd5..852b13959 100644 --- a/packages/frontend/src/mobile-pages/widgets.tsx +++ b/packages/frontend/src/mobile-pages/widgets.tsx @@ -1,10 +1,20 @@ +import { useMemo } from "react"; +import { useView, useWindowSize } from "src/api/hooks"; +import { getLayoutStateFromView } from "src/api/utils/layoutUtils"; +import WidgetsLibContainer from "src/containers/widgets-library/WidgetsLibContainer"; import MainLayout from "src/layout/MainLayout"; -import WidgetsContainer from "src/mobile-containers/WidgetsContainer"; const WidgetsPage: React.FC = () => { + const { selectedView } = useView(); + const windowSize = useWindowSize(); + + const layoutState = useMemo(() => { + return getLayoutStateFromView(selectedView, windowSize.width); + }, [selectedView, windowSize.width]); + return ( - + ); }; diff --git a/packages/frontend/src/pages/index.tsx b/packages/frontend/src/pages/index.tsx index a243445d5..07e71ba10 100644 --- a/packages/frontend/src/pages/index.tsx +++ b/packages/frontend/src/pages/index.tsx @@ -23,13 +23,12 @@ import { useAppDispatch, useAppSelector } from "src/api/store/hooks"; import * as userStore from "src/api/store/slices/user"; import { ETutorialTipId, TUserViewWidget } from "src/api/types"; import { - computeLayoutGrid, getDraggedWidget, recomputeWidgetsPos, getColType, - EColumnType, useTwoColWidgets, calculateTwoColWidgetsHeight, + getLayoutStateFromView, } from "src/api/utils/layoutUtils"; import { Logger } from "src/api/utils/logging"; import { EToastRole, toast } from "src/api/utils/toastUtils"; @@ -139,16 +138,7 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { [isFullsize, selectedView?.data.widgets] ); - const { widgets: twoColWidgets, twoColWidgetSlugs } = - useTwoColWidgets(selectedView); - - const layoutGrid = useMemo(() => { - return computeLayoutGrid( - selectedView?.data.widgets.filter( - (w) => !twoColWidgetSlugs.includes(w.widget.template.slug) - ) - ); - }, [twoColWidgetSlugs, selectedView?.data.widgets]); + const { widgets: twoColWidgets } = useTwoColWidgets(selectedView); const twoColWidgetCollapsedStates = useAppSelector((state) => { const collapsedStates: Record = {}; @@ -164,27 +154,10 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { /** * The current layout state according to the screen size - * IMPORTANT: checking that layoutGrid. != null is necessary - * because an issue after user logout. Namely, views data may not be updated - * which causes layoutGrid to remain undefined. */ const layoutState = useMemo(() => { - const colType = getColType(windowSize.width); - if (colType === EColumnType.SingleCol && layoutGrid?.singleCol) { - return layoutGrid.singleCol; - } - if (colType === EColumnType.TwoCol && layoutGrid?.twoCol) { - return layoutGrid.twoCol; - } - if (colType === EColumnType.ThreeCol && layoutGrid?.threeCol) { - return layoutGrid.threeCol; - } - - if (layoutGrid?.fourCol) { - return layoutGrid.fourCol; - } - return undefined; - }, [windowSize.width, layoutGrid]); + return getLayoutStateFromView(selectedView, windowSize.width); + }, [windowSize.width, selectedView]); const widgetsCount = selectedView?.data.widgets.length; From d8e21f208c495556e67e0e0dbf685b2cbddefa84 Mon Sep 17 00:00:00 2001 From: Xharles Date: Thu, 4 Dec 2025 09:09:08 +0100 Subject: [PATCH 24/79] feat: Fix return statement for MobileWidgetsList rendering in WidgetsLibContainer --- .../widgets-library/WidgetsLibContainer.tsx | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx b/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx index 553c24d57..f626bf81f 100644 --- a/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx +++ b/packages/frontend/src/containers/widgets-library/WidgetsLibContainer.tsx @@ -223,31 +223,33 @@ const WidgetsLibContainer: FC = ({ }, [nextPage]); if (isMobile) { - { - // filter by category. If no category is selected, show all widgets - return ( - !selectedCategory || - w.categories.some((c) => { - return c.slug === selectedCategory; - }) - ); - })} - categories={[...(widgetsCategory?.results || [])].sort( - (a, d) => a.sort_order - d.sort_order - )} - onSelectWidget={handleSelectWidget} - onCategorySelect={setSelectedCategory} - sortBy={sortBy} - onSortBy={handleSortBy} - handlePaginate={handleNextPage} - onFilter={handleFilter} - cachedWidgets={selectedView?.data.widgets?.map( - (sw) => sw.widget as TWidget - )} - selectedWidget={selectedWidget} - />; + return ( + { + // filter by category. If no category is selected, show all widgets + return ( + !selectedCategory || + w.categories.some((c) => { + return c.slug === selectedCategory; + }) + ); + })} + categories={[...(widgetsCategory?.results || [])].sort( + (a, d) => a.sort_order - d.sort_order + )} + onSelectWidget={handleSelectWidget} + onCategorySelect={setSelectedCategory} + sortBy={sortBy} + onSortBy={handleSortBy} + handlePaginate={handleNextPage} + onFilter={handleFilter} + cachedWidgets={selectedView?.data.widgets?.map( + (sw) => sw.widget as TWidget + )} + selectedWidget={selectedWidget} + /> + ); } return ( From 96b0a647343da4362d65416bb0a47ad28df0c1a2 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 8 Dec 2025 14:34:18 +0100 Subject: [PATCH 25/79] feat: Add MobileWidgetsView component for tabbed widget display on mobile --- .../widgets/MobileWidgetsView.tsx | 83 +++++++++++++++++++ packages/frontend/src/pages/index.tsx | 22 +++++ 2 files changed, 105 insertions(+) create mode 100644 packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx diff --git a/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx b/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx new file mode 100644 index 000000000..695fce07f --- /dev/null +++ b/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx @@ -0,0 +1,83 @@ +import { FC, useState, useMemo } from "react"; +import { TabsBar } from "@alphaday/ui-kit"; +import { TUserViewWidget } from "src/api/types"; +import { Logger } from "src/api/utils/logging"; +import { TEMPLATES_DICT, IModuleContainer } from "src/types"; + +interface IMobileWidgetsViewProps { + widgets: TUserViewWidget[]; +} + +const MobileWidgetsView: FC = ({ widgets }) => { + const [selectedWidgetIndex, setSelectedWidgetIndex] = useState(0); + + // Create tab options from widgets + const tabOptions = useMemo(() => { + return widgets.map((widget, index) => ({ + label: widget.name, + value: String(index), + })); + }, [widgets]); + + // Get the currently selected widget + const selectedWidget = useMemo(() => { + if (widgets.length === 0) return null; + return widgets[selectedWidgetIndex]; + }, [widgets, selectedWidgetIndex]); + + const handleTabChange = (value: string) => { + const index = parseInt(value, 10); + if (!Number.isNaN(index) && index >= 0 && index < widgets.length) { + setSelectedWidgetIndex(index); + } + }; + + if (widgets.length === 0) { + return ( +
+

+ No widgets in this board. Add widgets from the widgets + library. +

+
+ ); + } + + if (!selectedWidget) { + return null; + } + + const Container = TEMPLATES_DICT[ + selectedWidget.widget.template.slug + ] as FC; + + if (!Container) { + Logger.warn( + `MobileWidgetsView: No container found for template ${selectedWidget.widget.template.slug}` + ); + return null; + } + + return ( +
+ {/* Tabs Bar */} +
+ +
+ + {/* Widget Content */} +
+ {}} + /> +
+
+ ); +}; + +export default MobileWidgetsView; diff --git a/packages/frontend/src/pages/index.tsx b/packages/frontend/src/pages/index.tsx index 07e71ba10..fd686f27c 100644 --- a/packages/frontend/src/pages/index.tsx +++ b/packages/frontend/src/pages/index.tsx @@ -41,7 +41,9 @@ import WalletConnectionDialogContainer from "src/containers/dialogs/WalletConnec import { LanguageModalContainer } from "src/containers/LanguageModalContainer"; import { RecipeLibraryContainer } from "src/containers/recipe-library/RecipeLibraryContainer"; import TutorialContainer from "src/containers/tutorial/TutorialContainer"; +import { deviceBreakpoints } from "src/globalStyles/breakpoints"; import MainLayout from "src/layout/MainLayout"; +import MobileWidgetsView from "src/mobile-components/widgets/MobileWidgetsView"; import { ETemplateNameRegistry } from "src/constants"; import { TTemplateSlug, TEMPLATES_DICT, IModuleContainer } from "src/types"; @@ -79,6 +81,7 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { const isAuthenticated = useAppSelector(userStore.selectIsAuthenticated); const windowSize = useWindowSize(); + const isMobile = windowSize.width < deviceBreakpoints.twoCol; const { imageWidgetSize, aspectRatios: twoColWidgetAspectRatios, @@ -313,6 +316,25 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { ); } + // Mobile view: Show widgets in a tabbed interface, one at a time + if (isMobile && selectedView?.data.widgets) { + return ( + + + + + + + + + ); + } + + // Desktop view: Show drag and drop grid layout return ( Date: Mon, 8 Dec 2025 14:39:40 +0100 Subject: [PATCH 26/79] feat: Add DesktopWidgetsView component for improved widget layout management --- .../components/widgets/DesktopWidgetsView.tsx | 136 ++++++++++++++++++ packages/frontend/src/pages/index.tsx | 116 +++------------ 2 files changed, 154 insertions(+), 98 deletions(-) create mode 100644 packages/frontend/src/components/widgets/DesktopWidgetsView.tsx diff --git a/packages/frontend/src/components/widgets/DesktopWidgetsView.tsx b/packages/frontend/src/components/widgets/DesktopWidgetsView.tsx new file mode 100644 index 000000000..99b713c42 --- /dev/null +++ b/packages/frontend/src/components/widgets/DesktopWidgetsView.tsx @@ -0,0 +1,136 @@ +import { FC } from "react"; +import { Droppable } from "react-beautiful-dnd"; +import { TUserViewWidget } from "src/api/types"; +import { calculateTwoColWidgetsHeight } from "src/api/utils/layoutUtils"; +import CONFIG from "src/config/config"; +import ModuleWrapper from "src/containers/base/ModuleWrapper"; +import { ETemplateNameRegistry } from "src/constants"; +import { TTemplateSlug, TEMPLATES_DICT, IModuleContainer } from "src/types"; + +const { UI, TWO_COL_WIDGETS } = CONFIG; + +interface IDesktopWidgetsViewProps { + layoutState: TUserViewWidget[][] | undefined; + twoColWidgets: Record; + twoColWidgetCollapsedStates: Record; + imageWidgetSize: { width: number; height: number } | undefined; + twoColWidgetAspectRatios: Record; + handleAspectRatioDetected: (hash: string, ratio: number) => void; + fullSizeWidgetConfig: + | { + slug: TTemplateSlug; + hash: string | undefined; + } + | undefined; + preferredDragTutorialWidget: [number, number] | undefined; +} + +const DesktopWidgetsView: FC = ({ + layoutState, + twoColWidgets, + twoColWidgetCollapsedStates, + imageWidgetSize, + twoColWidgetAspectRatios, + handleAspectRatioDetected, + fullSizeWidgetConfig, + preferredDragTutorialWidget, +}) => { + return ( +
+
+ {Object.entries(TWO_COL_WIDGETS).map(([key, config]) => { + const moduleData = twoColWidgets[key]; + if (!moduleData) return null; + + const Container = TEMPLATES_DICT[ + config.templateSlug + ] as FC; + if (!Container) return null; + + const isImageWidget = + config.templateSlug === + `${ETemplateNameRegistry.Two_Col_Image.toLowerCase()}_template`; + + return ( +
+ {}} + onAspectRatioDetected={ + handleAspectRatioDetected + } + /> +
+ ); + })} +
+ {layoutState?.map((widgets, colIndex) => ( + + {(provided) => ( +
{ + if (colIndex !== 0 && colIndex !== 1) { + return "0px"; + } + + // Filter out undefined values before passing to calculateTwoColWidgetsHeight + const filteredTwoColWidgets = + Object.entries(twoColWidgets).reduce< + Record + >((acc, [key, value]) => { + if (value !== undefined) { + return { ...acc, [key]: value }; + } + return acc; + }, {}); + + const totalHeight = + calculateTwoColWidgetsHeight( + filteredTwoColWidgets, + twoColWidgetCollapsedStates, + imageWidgetSize?.width, + twoColWidgetAspectRatios + ); + return totalHeight > 0 + ? `${totalHeight}px` + : "0px"; + })(), + }} + > + {widgets.map((widget, rowIndex) => ( + + ))} + {provided.placeholder} +
+ )} +
+ ))} +
+ ); +}; + +export default DesktopWidgetsView; diff --git a/packages/frontend/src/pages/index.tsx b/packages/frontend/src/pages/index.tsx index fd686f27c..55ab215dd 100644 --- a/packages/frontend/src/pages/index.tsx +++ b/packages/frontend/src/pages/index.tsx @@ -1,5 +1,5 @@ -import { useCallback, useState, useMemo, useRef, memo, FC } from "react"; -import { DragDropContext, DropResult, Droppable } from "react-beautiful-dnd"; +import { useCallback, useState, useMemo, useRef, memo } from "react"; +import { DragDropContext, DropResult } from "react-beautiful-dnd"; import { useView, useAvailableViews, @@ -27,14 +27,13 @@ import { recomputeWidgetsPos, getColType, useTwoColWidgets, - calculateTwoColWidgetsHeight, getLayoutStateFromView, } from "src/api/utils/layoutUtils"; import { Logger } from "src/api/utils/logging"; import { EToastRole, toast } from "src/api/utils/toastUtils"; +import DesktopWidgetsView from "src/components/widgets/DesktopWidgetsView"; import CONFIG from "src/config/config"; import { AboutUsModalContainer } from "src/containers/AboutUsModalContainer"; -import ModuleWrapper from "src/containers/base/ModuleWrapper"; import CookieDisclaimerContainer from "src/containers/cookie-disclaimer/CookieDisclaimerContainer"; import AuthContainer from "src/containers/dialogs/AuthContainer"; import WalletConnectionDialogContainer from "src/containers/dialogs/WalletConnectionDialogContainer"; @@ -44,10 +43,9 @@ import TutorialContainer from "src/containers/tutorial/TutorialContainer"; import { deviceBreakpoints } from "src/globalStyles/breakpoints"; import MainLayout from "src/layout/MainLayout"; import MobileWidgetsView from "src/mobile-components/widgets/MobileWidgetsView"; -import { ETemplateNameRegistry } from "src/constants"; -import { TTemplateSlug, TEMPLATES_DICT, IModuleContainer } from "src/types"; +import { TTemplateSlug } from "src/types"; -const { UI, VIEWS, TWO_COL_WIDGETS } = CONFIG; +const { UI, VIEWS } = CONFIG; function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { const dispatch = useAppDispatch(); @@ -284,7 +282,9 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { * * the function checks these widgets exist. */ - const preferredDragTutorialWidget = useMemo(() => { + const preferredDragTutorialWidget = useMemo< + [number, number] | undefined + >(() => { if (!layoutState) return undefined; if (layoutState[0][1]) return [1, 0]; // second widget first row if (layoutState[0][2]) return [2, 0]; // third widget first row @@ -363,96 +363,16 @@ function BasePage({ isFullsize }: { isFullsize: boolean | undefined }) { } }} > -
-
- {Object.entries(TWO_COL_WIDGETS).map( - ([key, config]) => { - const moduleData = twoColWidgets[key]; - if (!moduleData) return null; - - const Container = TEMPLATES_DICT[ - config.templateSlug - ] as FC; - if (!Container) return null; - - const isImageWidget = - config.templateSlug === - `${ETemplateNameRegistry.Two_Col_Image.toLowerCase()}_template`; - - return ( -
- {}} - onAspectRatioDetected={ - handleAspectRatioDetected - } - /> -
- ); - } - )} -
- {layoutState?.map((widgets, colIndex) => ( - - {(provided) => ( -
{ - if ( - colIndex !== 0 && - colIndex !== 1 - ) { - return "0px"; - } - - const totalHeight = - calculateTwoColWidgetsHeight( - twoColWidgets, - twoColWidgetCollapsedStates, - imageWidgetSize?.width, - twoColWidgetAspectRatios - ); - return totalHeight > 0 - ? `${totalHeight}px` - : "0px"; - })(), - }} - > - {widgets.map((widget, rowIndex) => ( - - ))} - {provided.placeholder} -
- )} -
- ))} -
+ From 6f331ef030275d0fa1fc9a93c6149d5446368fa0 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 8 Dec 2025 14:46:42 +0100 Subject: [PATCH 27/79] feat: Integrate useHeaderScroll hook for improved widget scrolling and tab management in MobileWidgetsView --- .../widgets/MobileWidgetsView.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx b/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx index 695fce07f..5dac0bc01 100644 --- a/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx +++ b/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx @@ -1,5 +1,6 @@ import { FC, useState, useMemo } from "react"; import { TabsBar } from "@alphaday/ui-kit"; +import useHeaderScroll from "src/api/hooks/useHeaderScroll"; import { TUserViewWidget } from "src/api/types"; import { Logger } from "src/api/utils/logging"; import { TEMPLATES_DICT, IModuleContainer } from "src/types"; @@ -9,6 +10,13 @@ interface IMobileWidgetsViewProps { } const MobileWidgetsView: FC = ({ widgets }) => { + const { + squareRef, + setHeaderRef, + handleClickScroll, + hideLeftPan, + hideRightPan, + } = useHeaderScroll(); const [selectedWidgetIndex, setSelectedWidgetIndex] = useState(0); // Create tab options from widgets @@ -59,13 +67,17 @@ const MobileWidgetsView: FC = ({ widgets }) => { } return ( -
+
{/* Tabs Bar */} -
+
From 556faabaca3b2c611d5d730d2ceae645af484392 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 8 Dec 2025 14:48:18 +0100 Subject: [PATCH 28/79] rebase --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 9bf5b3ab1..c3f6bc044 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6193,7 +6193,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" -define-properties@^1.2.1: +define-properties@^1.1.3, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== From c84ece695268924ad76ddf6a5912438a4d723338 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 8 Dec 2025 15:25:38 +0100 Subject: [PATCH 29/79] feat: Update padding in MainLayout and adjust height calculation in MobileWidgetsView for better layout consistency --- packages/frontend/src/layout/MainLayout.tsx | 2 +- .../src/mobile-components/widgets/MobileWidgetsView.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/layout/MainLayout.tsx b/packages/frontend/src/layout/MainLayout.tsx index bd510c451..5707db2cd 100644 --- a/packages/frontend/src/layout/MainLayout.tsx +++ b/packages/frontend/src/layout/MainLayout.tsx @@ -48,7 +48,7 @@ const MainLayout: React.FC = ({ )} > {/* pt-[6.5px] here is to make sure the board arae is exactly 12px away from the views tab */} -
+
{children}
diff --git a/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx b/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx index 5dac0bc01..bfb9f1335 100644 --- a/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx +++ b/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx @@ -82,7 +82,8 @@ const MobileWidgetsView: FC = ({ widgets }) => {
{/* Widget Content */} -
+ {/* -38px os the height of the tabs bar */} +
{}} From 4968686ce627ced7b67ec4c62cc332e52cf1dfda Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 8 Dec 2025 15:38:24 +0100 Subject: [PATCH 30/79] feat: Refactor mutation hooks in ItemsContainer to ensure consistent hook order and selection based on widget type --- .../src/containers/items/ItemsContainer.tsx | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/containers/items/ItemsContainer.tsx b/packages/frontend/src/containers/items/ItemsContainer.tsx index 75dc7129d..93b8b210b 100644 --- a/packages/frontend/src/containers/items/ItemsContainer.tsx +++ b/packages/frontend/src/containers/items/ItemsContainer.tsx @@ -190,9 +190,27 @@ const ItemsContainer: FC = ({ moduleData }) => { const { currentData: itemsData, isLoading, isSuccess } = response; - const [openItemMut] = ITEMS_DICT.useOpenItemMutation[widgetType]?.() || []; - const [bookmarkItemMut] = - ITEMS_DICT.useBookmarkItemMutation[widgetType]?.() || []; + // Call mutation hooks unconditionally to maintain hook order + // All hooks must be called regardless of widgetType + const [blogOpenMut] = useOpenBlogItemMutation(); + const [blogBookmarkMut] = useBookmarkBlogItemMutation(); + const [newsOpenMut] = useOpenNewsItemMutation(); + const [newsBookmarkMut] = useBookmarkNewsItemMutation(); + + // Select the appropriate mutations based on widget type + let openItemMut: typeof blogOpenMut | typeof newsOpenMut | undefined; + let bookmarkItemMut: + | typeof blogBookmarkMut + | typeof newsBookmarkMut + | undefined; + + if (widgetType === "BLOG") { + openItemMut = blogOpenMut; + bookmarkItemMut = blogBookmarkMut; + } else if (widgetType === "NEWS") { + openItemMut = newsOpenMut; + bookmarkItemMut = newsBookmarkMut; + } const onOpenItem = async (id: number) => { if (openItemMut !== undefined) { From 7d1a9c7a2174a10fc63fd76f74f0e0492f6df6e9 Mon Sep 17 00:00:00 2001 From: Xharles Date: Mon, 8 Dec 2025 16:25:19 +0100 Subject: [PATCH 31/79] feat: Refactor calendar styles for improved responsiveness and layout consistency --- packages/ui-kit/src/globalStyles/calendar.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/ui-kit/src/globalStyles/calendar.scss b/packages/ui-kit/src/globalStyles/calendar.scss index c582211f3..4135c12a0 100644 --- a/packages/ui-kit/src/globalStyles/calendar.scss +++ b/packages/ui-kit/src/globalStyles/calendar.scss @@ -16,7 +16,6 @@ & .fc-list-day { min-width: 60px; - @apply tiny:min-w-[40px] tiny:-ml-[10%]; } .event-highlight, .event-hover-highlight { @@ -25,6 +24,8 @@ text-decoration: none !important; } } + + @apply tiny:-ml-[64px]; } tr:nth-child(1) { border-top: 0 !important; @@ -74,7 +75,7 @@ z-index: 1; width: calc(100% - 2px); - @apply single-col:justify-between two-col:py-0 px-4; + @apply single-col:justify-between two-col:py-0 px-4 tiny:px-2.5; } .fc { &:first-child { @@ -231,7 +232,7 @@ justify-content: flex-start; padding-left: 6px; - @apply flex-[0_0_15%] tiny:max-w-[40px] max-w-[15%] two-col:flex-[0_0_12%] two-col:max-w-[12%] three-col:flex-[0_0_10%] three-col:max-w-[10%]; + @apply flex-[0_0_15%] max-w-[15%] two-col:flex-[0_0_12%] two-col:max-w-[12%] three-col:flex-[0_0_10%] three-col:max-w-[10%]; &:first-of-type { margin-top: 0; & + .fc-list-event { @@ -289,7 +290,6 @@ flex: 0 0 calc(90% - 60px); max-width: calc(90% - 60px); cursor: pointer; - @apply tiny:flex-[0_0_calc(100%_-_50px)] tiny:max-w-[calc(100%_-_79px)]; &:hover { background-color: theme( @@ -311,7 +311,7 @@ flex: 0 0 100%; max-width: 90%; padding-left: 60px; - @apply tiny:ml-[15%] ml-[12%] two-col:ml-[20%]; + @apply ml-[12%] two-col:ml-[20%]; } // &:first-child { // } From 44026ed886a21250e106dd73f45b120379081d45 Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 10 Dec 2025 16:51:35 +0100 Subject: [PATCH 32/79] feat: Adjust minimum width and margin for improved layout in AgendaItem, FaqModule, and RoadmapModule --- .../src/components/dynamic-modules/agenda/AgendaItem.tsx | 2 +- .../frontend/src/components/dynamic-modules/faq/FaqModule.tsx | 1 + .../src/components/dynamic-modules/roadmap/RoadmapModule.tsx | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/dynamic-modules/agenda/AgendaItem.tsx b/packages/frontend/src/components/dynamic-modules/agenda/AgendaItem.tsx index f5ca056da..866dd0f5c 100644 --- a/packages/frontend/src/components/dynamic-modules/agenda/AgendaItem.tsx +++ b/packages/frontend/src/components/dynamic-modules/agenda/AgendaItem.tsx @@ -57,7 +57,7 @@ const AgendaItem: FC = ({ item, catColor, setItemsHeight }) => { tabIndex={-1} role="button" > -
+
{dateField} {timeField && ( diff --git a/packages/frontend/src/components/dynamic-modules/faq/FaqModule.tsx b/packages/frontend/src/components/dynamic-modules/faq/FaqModule.tsx index 3e16cd4eb..1ef160cd5 100644 --- a/packages/frontend/src/components/dynamic-modules/faq/FaqModule.tsx +++ b/packages/frontend/src/components/dynamic-modules/faq/FaqModule.tsx @@ -27,6 +27,7 @@ const FaqModule: FC = ({ return (
= ({ if (items.length > 0) { return (
Date: Wed, 10 Dec 2025 17:32:09 +0100 Subject: [PATCH 33/79] feat: Add mobileViewWidgetHeight prop to PodcastModule, PodcastContainer, and MobileWidgetsView for improved layout handling --- .../src/components/podcast/PodcastModule.tsx | 6 ++++-- .../containers/podcast/PodcastContainer.tsx | 6 +++++- .../widgets/MobileWidgetsView.tsx | 21 ++++++++++++++++--- packages/frontend/src/types.ts | 1 + 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/components/podcast/PodcastModule.tsx b/packages/frontend/src/components/podcast/PodcastModule.tsx index 47720aeca..6ccb090e8 100644 --- a/packages/frontend/src/components/podcast/PodcastModule.tsx +++ b/packages/frontend/src/components/podcast/PodcastModule.tsx @@ -32,6 +32,7 @@ interface IPodcastModule { onRemoveChannel: (channel: TPodcastChannel) => void; preferredChannelIds: number[] | undefined; setPreferredChannelIds: (channels: TPodcastChannel[]) => void; + mobileViewWidgetHeight?: number; } const SWITCH_HEIGHT = 38; @@ -72,6 +73,7 @@ const PodcastModule: FC = ({ onRemoveChannel, preferredChannelIds, setPreferredChannelIds, + mobileViewWidgetHeight, }) => { const podcastNavItems = translateNavItems(); @@ -129,7 +131,7 @@ const PodcastModule: FC = ({ onSetFeedPreference(optionItem?.value); }; return ( -
+
= ({ className="transition-all duration-300 relative z-[1] bg-background" style={{ height: - widgetHeight - + (mobileViewWidgetHeight ?? widgetHeight) - SWITCH_HEIGHT - channelsHeight - audioPlayerHeight, diff --git a/packages/frontend/src/containers/podcast/PodcastContainer.tsx b/packages/frontend/src/containers/podcast/PodcastContainer.tsx index 5c4a0b44c..3303e48a6 100644 --- a/packages/frontend/src/containers/podcast/PodcastContainer.tsx +++ b/packages/frontend/src/containers/podcast/PodcastContainer.tsx @@ -37,7 +37,10 @@ import { IModuleContainer } from "src/types"; const { DEFAULT_FEED_PREFERENCE, MAX_PAGE_NUMBER } = CONFIG.WIDGETS.PODCAST; -const PodcastContainer: FC = ({ moduleData }) => { +const PodcastContainer: FC = ({ + moduleData, + mobileViewWidgetHeight, +}) => { const dispatch = useAppDispatch(); const isAuthenticated = useAppSelector(selectIsAuthenticated); @@ -297,6 +300,7 @@ const PodcastContainer: FC = ({ moduleData }) => { setSelectedPodcast={setSelectedPodcast} preferredChannelIds={preferredChannelIds} setPreferredChannelIds={setPreferredChannelIds} + mobileViewWidgetHeight={mobileViewWidgetHeight} /> ); diff --git a/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx b/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx index bfb9f1335..bea564788 100644 --- a/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx +++ b/packages/frontend/src/mobile-components/widgets/MobileWidgetsView.tsx @@ -1,4 +1,4 @@ -import { FC, useState, useMemo } from "react"; +import { FC, useState, useMemo, useRef, useCallback } from "react"; import { TabsBar } from "@alphaday/ui-kit"; import useHeaderScroll from "src/api/hooks/useHeaderScroll"; import { TUserViewWidget } from "src/api/types"; @@ -10,6 +10,7 @@ interface IMobileWidgetsViewProps { } const MobileWidgetsView: FC = ({ widgets }) => { + const widgetRef = useRef(null); const { squareRef, setHeaderRef, @@ -19,6 +20,15 @@ const MobileWidgetsView: FC = ({ widgets }) => { } = useHeaderScroll(); const [selectedWidgetIndex, setSelectedWidgetIndex] = useState(0); + // Combined callback ref to handle both widgetRef and squareRef + const combinedRef = useCallback( + (node: HTMLDivElement | null) => { + widgetRef.current = node; + squareRef(node); + }, + [squareRef] + ); + // Create tab options from widgets const tabOptions = useMemo(() => { return widgets.map((widget, index) => ({ @@ -67,7 +77,7 @@ const MobileWidgetsView: FC = ({ widgets }) => { } return ( -
+
{/* Tabs Bar */}
= ({ widgets }) => {
{/* Widget Content */} - {/* -38px os the height of the tabs bar */} + {/* -38px is the height of the tabs bar */}
{}} + mobileViewWidgetHeight={ + widgetRef?.current + ? widgetRef.current.clientHeight - 38 + : undefined + } />
diff --git a/packages/frontend/src/types.ts b/packages/frontend/src/types.ts index b448da6e3..77a7cc875 100644 --- a/packages/frontend/src/types.ts +++ b/packages/frontend/src/types.ts @@ -21,6 +21,7 @@ export interface IModuleContainer { moduleData: TUserViewWidget; toggleAdjustable(): void; onAspectRatioDetected?: (widgetHash: string, aspectRatio: number) => void; + mobileViewWidgetHeight?: number; } export type TTemplateSlug = `${Lowercase}_template`; From 58290a97ad875432b6d73fa1dd4a1c2d0078a4f0 Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 17 Dec 2025 09:38:05 +0100 Subject: [PATCH 34/79] feat: Update CustomTableContainer to accept mobileViewWidgetHeight prop and adjust widget height handling in Table components --- .../src/components/custom-modules/TableComponents.tsx | 6 +++--- .../src/containers/custom-modules/CustomTableContainer.tsx | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/components/custom-modules/TableComponents.tsx b/packages/frontend/src/components/custom-modules/TableComponents.tsx index ca6cf74a9..92d928417 100644 --- a/packages/frontend/src/components/custom-modules/TableComponents.tsx +++ b/packages/frontend/src/components/custom-modules/TableComponents.tsx @@ -91,7 +91,7 @@ export const TableHeader: React.FC<{ addExtraColumn?: boolean; }> = ({ layout, addExtraColumn }) => { return ( -
+
{layout.map((columnLayout) => ( = ({ return (
= ({ return (
= ({ moduleData }) => { +const CustomTableContainer: FC = ({ + moduleData, + mobileViewWidgetHeight, +}) => { const dispatch = useAppDispatch(); /* eslint-disable @typescript-eslint/naming-convention */ @@ -88,7 +91,7 @@ const CustomTableContainer: FC = ({ moduleData }) => { rowProps={meta.row_props} isLoadingItems={isLoading} handlePaginate={() => ({})} - widgetHeight={widgetHeight} + widgetHeight={mobileViewWidgetHeight ?? widgetHeight} setWidgetHeight={handleSetWidgetHeight} isHeaderOnlyMode={moduleData.widget.slug.includes("dune_")} /> From 28278391051338632c910dd67169a7164ecd1dcc Mon Sep 17 00:00:00 2001 From: Xharles Date: Wed, 17 Dec 2025 09:38:39 +0100 Subject: [PATCH 35/79] feat: Add margin top and responsive layout adjustments to CountdownModule --- packages/frontend/src/components/countdown/CountdownModule.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/countdown/CountdownModule.tsx b/packages/frontend/src/components/countdown/CountdownModule.tsx index 7735abff5..8c714e8c6 100644 --- a/packages/frontend/src/components/countdown/CountdownModule.tsx +++ b/packages/frontend/src/components/countdown/CountdownModule.tsx @@ -37,7 +37,7 @@ const CountdownModule: FC = ({ }, []); return ( -
+
Date: Wed, 17 Dec 2025 09:38:45 +0100 Subject: [PATCH 36/79] feat: Wrap iframe in a div for improved layout consistency in MediaModule --- .../src/components/media/MediaModule.tsx | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/frontend/src/components/media/MediaModule.tsx b/packages/frontend/src/components/media/MediaModule.tsx index c8e9fa0b0..8f5ed32e4 100644 --- a/packages/frontend/src/components/media/MediaModule.tsx +++ b/packages/frontend/src/components/media/MediaModule.tsx @@ -35,27 +35,29 @@ const MediaModule: FC = memo(function MediaModule({ if (entryUrl) { return ( -