diff --git a/apps/desktop/packages/mainWindow/src/components/Sidebar/modpacks.tsx b/apps/desktop/packages/mainWindow/src/components/Sidebar/modpacks.tsx index 54c1d4ac1..5f1d45133 100644 --- a/apps/desktop/packages/mainWindow/src/components/Sidebar/modpacks.tsx +++ b/apps/desktop/packages/mainWindow/src/components/Sidebar/modpacks.tsx @@ -1,7 +1,12 @@ /* eslint-disable solid/no-innerhtml */ -import SiderbarWrapper from "./wrapper"; -import { Checkbox, Collapsable, Dropdown, Radio, Skeleton } from "@gd/ui"; -import { createMemo, For, Match, Show, Switch } from "solid-js"; +import { Cascader, Dropdown } from "@gd/ui"; +import { + createEffect, + createMemo, + createSignal, + Match, + Switch +} from "solid-js"; import { CFFECategory, FESearchAPI, @@ -12,18 +17,17 @@ import { import { ModpackPlatforms } from "@/utils/constants"; import { capitalize } from "@/utils/helpers"; import { CategoryIcon, PlatformIcon } from "@/utils/instances"; -import { Trans, useTransContext } from "@gd/i18n"; +import { useTransContext } from "@gd/i18n"; import { useInfiniteModsQuery } from "../InfiniteScrollModsQueryWrapper"; import { curseforgeCategories, - getCategoryId, ModloaderIcon, modrinthCategories, supportedModloaders } from "@/utils/sidebar"; -import { mappedMcVersions, mcVersions } from "@/utils/mcVersion"; +import { mcVersions } from "@/utils/mcVersion"; import { createStore } from "solid-js/store"; - +import _ from "lodash"; const mapTypeToColor = (type: McType) => { return ( @@ -43,6 +47,12 @@ const mapTypeToColor = (type: McType) => { ); }; +const gameVersions = [ + { type: "snapshot", label: "include snapshot versions" }, + { type: "old_alpha", label: "include old alpha versions" }, + { type: "old_beta", label: "include old beta versions" } +]; + const [gameVersionFilters, setGameVersionFilters] = createStore({ snapshot: false, oldAlpha: false, @@ -50,6 +60,33 @@ const [gameVersionFilters, setGameVersionFilters] = createStore({ }); const Sidebar = () => { + const [selectedItems, setSelectedItems] = createSignal([ + "Platform//Curseforge" + ]); + const [menuData, setMenuData] = createSignal({ + hasSearch: false, + isCheckbox: false, + isParent: true, + items: [ + { + label: "Platform", + img: "" + }, + { + label: "Game Versions", + img: "" + }, + { + label: "Modloader", + img: "" + }, + { + label: "Categories", + img: "" + } + ] + }); + const infiniteQuery = useInfiniteModsQuery(); const [t] = useTransContext(); @@ -128,205 +165,178 @@ const Sidebar = () => { } } - return ( - -
- -
- { - infiniteQuery.setQuery({ - searchApi: (val as string).toLowerCase() as FESearchAPI, - categories: [], - modloaders: null - }); - }} - value={infiniteQuery?.query?.searchApi} - options={ModpackPlatforms.map((platform) => ({ - value: platform, - label: ( -
- -

- -

-
- ) - }))} - /> -
-
- - 0}> -
-
- - updateGameVersionsFilter({ - snapshot: e - }) - } - > -
- -
-
-
-
- updateGameVersionsFilter({ oldAlpha: e })} - > -
- -
-
-
-
- updateGameVersionsFilter({ oldBeta: e })} - > -
- -
-
-
-
- } - value={infiniteQuery.query.gameVersions?.[0] || null} - onChange={(val) => { - infiniteQuery?.setQuery({ - gameVersions: val.key ? [val.key as string] : null - }); - }} - /> -
- - - -
- -
- - {(modloader) => { - return ( -
- { - const prevModloaders = - infiniteQuery?.query.modloaders || []; - - const modloaderName = - typeof modloader === "string" - ? modloader - : modloader.name; + createEffect(() => { + setMenuData((prev) => ({ + ...prev, + items: prev.items.map((item) => { + if (item.label === "Platform") { + return { + label: t("general.platform"), - const filteredModloaders = prevModloaders.filter( - (_modloader: any) => _modloader !== modloaderName - ); + img: "", + children: { + hasSearch: false, + isCheckbox: false, + isParent: false, + parentLabel: t("general.platform"), + items: ModpackPlatforms.map((platform) => { + return { + label: platform, + img: + }; + }) + } + }; + } + if (item.label === "Game Versions") { + return { + label: t("general.game_versions"), + img: "", + children: { + hasSearch: false, + isCheckbox: true, + isParent: false, + parentLabel: t("general.game_versions"), - const newModloaders = checked - ? [ - ...prevModloaders, - modloaderName as FEUnifiedModLoaderType - ] - : filteredModloaders; + items: gameVersions.map((version) => { + return { + label: version.label, + img: "" + }; + }), + hasChildren: ( + } + value={infiniteQuery.query.gameVersions?.[0] || null} + onChange={(val) => { + infiniteQuery?.setQuery({ + gameVersions: val.key ? [val.key as string] : null + }); + }} + /> + ) + } + }; + } + if (item.label === "Modloader") { + return { + label: t("general.modloaders"), + img: "", + children: { + hasSearch: true, + isCheckbox: true, + isParent: false, + parentLabel: t("general.modloaders"), + items: modloaders()!.map((modloader) => { + return { + label: capitalize( + typeof modloader === "string" ? modloader : modloader.name + ), + img: + }; + }) + } + }; + } + if (item.label === "Categories") { + return { + label: t("general.categories"), + img: "", + children: { + hasSearch: true, + isCheckbox: true, + isParent: false, + parentLabel: t("general.categories"), - infiniteQuery.setQuery({ - modloaders: - newModloaders.length === 0 ? null : newModloaders - }); - }} - > - -

- {capitalize( - typeof modloader === "string" - ? modloader - : modloader.name - )} -

-
-
- ); - }} -
-
-
- - 0}> - -
- - {(category) => { - const categoryObj = () => - isCurseforge() - ? { curseforge: (category as CFFECategory).id } - : { modrinth: (category as MRFECategory).name }; + items: categories().map((category) => { + return { + label: category.name, + img: + }; + }) + } + }; + } + return item; + }) + })); + }); - const categoryId = () => - isCurseforge() - ? (category as CFFECategory).id - : (category as MRFECategory).name; + createEffect(() => { + const versionTypes = selectedItems().filter((item) => + item.includes("Game Versions") + ); - const isCategoryIncluded = () => - infiniteQuery?.query.categories?.some( - (item) => - ("curseforge" in item[0] && - item[0].curseforge === categoryId()) || - ("modrinth" in item[0] && - item[0].modrinth === categoryId()) - ); + const versions = versionTypes.map((item) => item.split("//")[1]); + updateGameVersionsFilter({ + snapshot: versions.includes("include snapshot versions"), + oldAlpha: versions.includes("include old alpha versions"), + oldBeta: versions.includes("include old beta versions") + }); + }); - return ( -
- { - const prevCategories = - infiniteQuery?.query.categories || []; + createEffect(() => { + const selectedCategories = selectedItems() + .filter((item) => item.includes("Categories")) + .map((item) => item.split("//")[1]); + const objectCategories = selectedCategories.map((category) => { + const categ = categories().find((item) => item.name === category); + if (isCurseforge()) { + return [{ curseforge: (categ as CFFECategory).id }]; + } else { + return [{ modrinth: (categ as MRFECategory).name }]; + } + }); + infiniteQuery.setQuery({ + categories: objectCategories as any + }); + }); + const modLoaders = createMemo(() => + selectedItems().filter((item) => item.includes("Modloader")) + ); + createEffect(() => { + if (modLoaders.length === 0) { + infiniteQuery.setQuery({ + modloaders: null + }); + } else { + const modloader = modLoaders().map((item) => + item.split("//")[1].toLowerCase() + ); - const newCategories = checked - ? [...prevCategories, [categoryObj()]] - : prevCategories.filter( - (categ) => - getCategoryId(categ[0]) !== - getCategoryId(categoryObj()) - ); + infiniteQuery.setQuery({ + modloaders: modloader as FEUnifiedModLoaderType[] + }); + } + }, [selectedItems]); + createEffect(() => { + const currentPlatform = _.capitalize( + selectedItems() + .find((item) => item.includes("Platform")) + ?.split("//")[1] + ); - infiniteQuery.setQuery({ - categories: newCategories - }); - }} - > -
- -

{capitalize(category.name)}

-
-
-
- ); - }} -
-
-
-
- - - -
-
-
+ if ( + (isCurseforge() && currentPlatform !== "Curseforge") || + (!isCurseforge() && currentPlatform !== "Modrinth") + ) { + infiniteQuery.setQuery({ + searchApi: (currentPlatform as string).toLowerCase() as FESearchAPI, + categories: [], + modloaders: null + }); + } + }); + return ( + } + {...menuData()} + selectedItems={selectedItems} + setSelectedItems={setSelectedItems} + /> ); }; diff --git a/apps/desktop/packages/mainWindow/src/components/Sidebar/mods.tsx b/apps/desktop/packages/mainWindow/src/components/Sidebar/mods.tsx index 4c998c84b..e61a1bcc8 100644 --- a/apps/desktop/packages/mainWindow/src/components/Sidebar/mods.tsx +++ b/apps/desktop/packages/mainWindow/src/components/Sidebar/mods.tsx @@ -1,15 +1,14 @@ /* eslint-disable solid/no-innerhtml */ -import SiderbarWrapper from "./wrapper"; -import { Checkbox, Collapsable, Dropdown, Radio, Skeleton } from "@gd/ui"; +import { Cascader, Dropdown } from "@gd/ui"; import fetchData from "@/pages/Mods/modsBrowser.data"; import { useRouteData, useSearchParams } from "@solidjs/router"; import { + createEffect, createMemo, - For, + createSignal, getOwner, Match, runWithOwner, - Show, Switch } from "solid-js"; import { @@ -24,22 +23,23 @@ import { capitalize } from "@/utils/helpers"; import { CategoryIcon, getInstanceImageUrl, + getValideInstance, PlatformIcon } from "@/utils/instances"; -import { Trans, useTransContext } from "@gd/i18n"; +import { useTransContext } from "@gd/i18n"; import { useInfiniteModsQuery } from "../InfiniteScrollModsQueryWrapper"; import DefaultImg from "/assets/images/default-instance-img.png"; import { curseforgeCategories, - getCategoryId, ModloaderIcon, modrinthCategories, supportedModloaders } from "@/utils/sidebar"; import { createStore } from "solid-js/store"; -import { mappedMcVersions, mcVersions } from "@/utils/mcVersion"; -import { instanceId, setInstanceId } from "@/utils/browser"; +import { mcVersions } from "@/utils/mcVersion"; +import { setInstanceId } from "@/utils/browser"; import { rspc } from "@/utils/rspcClient"; +import _ from "lodash"; const mapTypeToColor = (type: McType) => { return ( @@ -59,9 +59,46 @@ const mapTypeToColor = (type: McType) => {
); }; - +const gameVersions = [ + { type: "snapshot", label: "include snapshot versions" }, + { type: "old_alpha", label: "include old alpha versions" }, + { type: "old_beta", label: "include old beta versions" } +]; const Sidebar = () => { let owner = getOwner(); + const [selectedItems, setSelectedItems] = createSignal([ + "Platform//Curseforge" + ]); + const [currentParentCategories, setCurrentParentCategories] = createSignal< + Array + >([]); + const [menuData, setMenuData] = createSignal({ + hasSearch: false, + isCheckbox: false, + isParent: true, + items: [ + { + label: "Instances", + img: "" + }, + { + label: "Platform", + img: "" + }, + { + label: "Game Versions", + img: "" + }, + { + label: "Modloader", + img: "" + }, + { + label: "Categories", + img: "" + } + ] + }); const routeData: ReturnType = useRouteData(); const rspcContext = rspc.useContext(); const [gameVersionFilters, setGameVersionFilters] = createStore({ @@ -149,276 +186,341 @@ const Sidebar = () => { }; const filteredInstances = () => - routeData.instancesUngrouped.data?.filter((instance) => { - const validInstance = - instance.status.status === "valid" ? instance.status.value : undefined; - return validInstance?.modloader; - }); + routeData.instancesUngrouped.data?.filter( + (instance) => getValideInstance(instance.status)?.modloader + ); + createEffect(() => { + console.log(routeData.instancesUngrouped.data); + }); + const NotFilteredCategories = () => + isCurseforge() + ? curseforgeCategories() + : modrinthCategories().filter( + (category) => category.project_type === "mod" + ); + createEffect(() => { + const groupedByParentCategoryId = categories().reduce( + (accumulator: any, current: any) => { + // Use the parentCategoryId as a key + const key = current.parentCategoryId; - return ( - -
- - -
- { - const details: any = await runWithOwner(owner, async () => { - return rspcContext.client.query([ - "instance.getInstanceDetails", - val as number - ]); - }); - - setSearchParams({ - instanceId: val as number - }); - setInstanceId(val as number); - - const modloaders = - details.data?.modloaders.map((v: any) => v.type_) || []; - - const gameVersion = details.data.version; - - let newModloaders = []; - if (modloaders) { - if (modloaders?.includes("forge")) { - newModloaders.push("forge"); - } else if (modloaders?.includes("quilt")) { - newModloaders.push("fabric"); - newModloaders.push("quilt"); - } else { - newModloaders = [...modloaders!] as any; - } - } - - console.log(newModloaders, [gameVersion]); - - infiniteQuery.setQuery({ - modloaders: newModloaders, - gameVersions: [gameVersion] - }); - }} - value={instanceId()} - options={(filteredInstances() || []).map((instance) => ({ - value: instance.id, - label: ( -
-
-

{instance.name}

-
- ) - }))} - /> -
- - - -
- { - infiniteQuery.setQuery({ - searchApi: (val as string).toLowerCase() as FESearchAPI, - categories: [] - }); - }} - value={infiniteQuery?.query?.searchApi} - options={ModpackPlatforms.map((platform) => ({ - value: platform, - label: ( -
- -

- -

-
- ) - }))} - /> -
-
- - 0}> -
-
- - updateGameVersionsFilter({ - snapshot: e - }) - } - > -
- -
-
-
-
- updateGameVersionsFilter({ oldAlpha: e })} - > -
- -
-
-
-
- updateGameVersionsFilter({ oldBeta: e })} - > -
- -
-
-
-
- } - value={infiniteQuery.query.gameVersions?.[0] || null} - onChange={(val) => { - infiniteQuery?.setQuery({ - gameVersions: val.key ? [val.key as string] : null - }); - }} - /> -
- - - -
- -
- - {(modloader) => { - return ( -
- { - const prevModloaders = - infiniteQuery?.query.modloaders || []; - - const modloaderName = - typeof modloader === "string" - ? modloader - : modloader.name; - - const filteredModloaders = prevModloaders.filter( - (_modloader: any) => _modloader !== modloaderName - ); - - const newModloaders = checked - ? [ - ...prevModloaders, - modloaderName as FEUnifiedModLoaderType - ] - : filteredModloaders; - - infiniteQuery.setQuery({ - modloaders: - newModloaders.length === 0 ? null : newModloaders - }); + // If the accumulator doesn't have an array for this key, create it + if (!accumulator[key]) { + accumulator[key] = []; + } + + // Push the current object into the correct array + accumulator[key].push(current); + + // Return the accumulator for the next iteration + return accumulator; + }, + {} + ); + + setMenuData((prev) => ({ + ...prev, + items: prev.items.map((item) => { + console.log(filteredInstances()); + if (item.label === "Instances") { + return { + label: t("general.instances"), + img: "", + children: { + hasSearch: true, + isCheckbox: false, + isParent: false, + parentLabel: t("general.instances"), + items: filteredInstances()?.map((instance) => { + return { + label: instance.name, + img: ( +
- -

- {capitalize( - typeof modloader === "string" - ? modloader - : modloader.name - )} -

- -
- ); - }} - -
- - - 0}> - -
- - {(category) => { - const categoryObj = () => - isCurseforge() - ? { curseforge: (category as CFFECategory).id } - : { modrinth: (category as MRFECategory).name }; - - const categoryId = () => - isCurseforge() - ? (category as CFFECategory).id - : (category as MRFECategory).name; - - const isCategoryIncluded = () => - infiniteQuery?.query.categories?.some( - (item) => - ("curseforge" in item[0] && - item[0].curseforge === categoryId()) || - ("modrinth" in item[0] && - item[0].modrinth === categoryId()) - ); + /> + ), + id: instance.id + }; + }) + } + }; + } + if (item.label === "Platform") { + return { + label: t("general.platform"), + + img: "", + children: { + hasSearch: false, + isCheckbox: false, + isParent: false, + parentLabel: t("general.platform"), + items: ModpackPlatforms.map((platform) => { + return { + label: platform, + img: + }; + }) + } + }; + } + if (item.label === "Game Versions") { + return { + label: t("general.game_versions"), + img: "", + children: { + hasSearch: false, + isCheckbox: true, + isParent: false, + parentLabel: t("general.game_versions"), - return ( -
- { - const prevCategories = - infiniteQuery?.query.categories || []; - - const newCategories = checked - ? [...prevCategories, [categoryObj()]] - : prevCategories.filter( - (categ) => - getCategoryId(categ[0]) !== - getCategoryId(categoryObj()) - ); - - infiniteQuery.setQuery({ - categories: newCategories - }); - }} - > -
- -

{capitalize(category.name)}

-
-
-
- ); + items: gameVersions.map((version) => { + return { + label: version.label, + img: "" + }; + }), + hasChildren: ( + } + value={infiniteQuery.query.gameVersions?.[0] || null} + onChange={(val) => { + infiniteQuery?.setQuery({ + gameVersions: val.key ? [val.key as string] : null + }); }} -
-
-
-
- - - -
-
- + /> + ) + } + }; + } + if (item.label === "Modloader") { + return { + label: t("general.modloaders"), + img: "", + children: { + hasSearch: true, + isCheckbox: true, + isParent: false, + parentLabel: t("general.modloaders"), + items: modloaders()!.map((modloader) => { + return { + label: capitalize( + typeof modloader === "string" ? modloader : modloader.name + ), + img: + }; + }) + } + }; + } + if (item.label === "Categories") { + let parentCategoriesIds: any; + if (isCurseforge()) { + parentCategoriesIds = Object.keys(groupedByParentCategoryId).map( + (key) => key + ); + const parentCategories = NotFilteredCategories() + .filter((category: any) => + parentCategoriesIds.includes(category.id.toString()) + ) + .map((category: any) => category.name); + setCurrentParentCategories(parentCategories); + } + + return { + label: t("general.categories"), + img: "", + children: { + hasSearch: true, + isCheckbox: true, + isParent: false, + parentLabel: t("general.categories"), + items: isCurseforge() + ? Object.entries(groupedByParentCategoryId).map( + ([key, value]) => { + const parentCategory: any = NotFilteredCategories().find( + (category: any) => category.id === parseInt(key) + ); + return { + label: parentCategory?.name, + img: , + children: { + hasSearch: true, + isCheckbox: true, + isParent: false, + parentLabel: parentCategory?.name, + items: (value as any).map((category: any) => { + return { + label: category.name, + img: + }; + }) + } + }; + } + ) + : categories().map((category) => { + return { + label: category.name, + img: + }; + }) + // items: categories().map((category) => { + // return { + // label: category.name, + // img: + // }; + // }) + } + }; + } + return item; + }) + })); + }); + + createEffect(() => { + const currentPlatform = _.capitalize( + selectedItems() + .find((item) => item.includes("Platform")) + ?.split("//")[1] + ); + + if ( + (isCurseforge() && currentPlatform !== "Curseforge") || + (!isCurseforge() && currentPlatform !== "Modrinth") + ) { + infiniteQuery.setQuery({ + searchApi: (currentPlatform as string).toLowerCase() as FESearchAPI, + categories: [], + modloaders: null + }); + } + }); + + createEffect(() => { + const versionTypes = selectedItems().filter((item) => + item.includes("Game Versions") + ); + + const versions = versionTypes.map((item) => item.split("//")[1]); + updateGameVersionsFilter({ + snapshot: versions.includes("include snapshot versions"), + oldAlpha: versions.includes("include old alpha versions"), + oldBeta: versions.includes("include old beta versions") + }); + }); + + createEffect(() => { + const clonedParentCategories = currentParentCategories(); + clonedParentCategories.push("Categories"); + const selectedCategories = selectedItems() + .filter((item) => + isCurseforge() + ? clonedParentCategories.includes(item.split("//")[0]) + : item.includes("Categories") + ) + .map((item) => item.split("//")[1]); + const objectCategories = selectedCategories.map((category) => { + const categ = NotFilteredCategories().find( + (item) => item.name === category + ); + if (isCurseforge()) { + return [{ curseforge: (categ as CFFECategory).id }]; + } else { + return [{ modrinth: (categ as MRFECategory).name }]; + } + }); + infiniteQuery.setQuery({ + categories: objectCategories as any + }); + }); + const modLoaders = createMemo(() => + selectedItems().filter((item) => item.includes("Modloader")) + ); + createEffect(() => { + if (modLoaders.length === 0) { + infiniteQuery.setQuery({ + modloaders: null + }); + } else { + const modloader = modLoaders().map((item) => + item.split("//")[1].toLowerCase() + ); + infiniteQuery.setQuery({ + modloaders: modloader as FEUnifiedModLoaderType[] + }); + } + }); + createEffect(() => { + console.log(selectedItems()); + }); + createEffect(() => { + const currentInstance = selectedItems() + .find((item) => item.includes("Instances")) + ?.split("//")[1]; + + if (currentInstance) { + const instanceId = filteredInstances()?.find( + (instance) => instance.name === currentInstance + )?.id; + const changeInstance = async () => { + const details: any = await runWithOwner(owner, async () => { + return rspcContext.client.query([ + "instance.getInstanceDetails", + instanceId as number + ]); + }); + + setSearchParams({ + instanceId: instanceId as number + }); + setInstanceId(instanceId as number); + + const modloaders = details.modloaders.map((v: any) => v.type_); + + const gameVersion = details.version; + + let newModloaders = []; + if (modloaders) { + if (modloaders?.includes("forge")) { + newModloaders.push("forge"); + } else if (modloaders?.includes("quilt")) { + newModloaders.push("fabric"); + newModloaders.push("quilt"); + } else { + newModloaders = [...modloaders!] as any; + } + } + + infiniteQuery.setQuery({ + modloaders: newModloaders, + gameVersions: [gameVersion] + }); + }; + changeInstance(); + } + }); + + return ( + } + {...menuData()} + selectedItems={selectedItems} + setSelectedItems={setSelectedItems} + /> ); }; diff --git a/apps/desktop/packages/mainWindow/src/main.tsx b/apps/desktop/packages/mainWindow/src/main.tsx index 3e8dfa841..ed34f1e78 100644 --- a/apps/desktop/packages/mainWindow/src/main.tsx +++ b/apps/desktop/packages/mainWindow/src/main.tsx @@ -16,8 +16,9 @@ import App from "@/app"; import { ModalProvider } from "@/managers/ModalsManager"; import "virtual:uno.css"; import "@gd/ui/style.css"; -import { ContextMenuProvider, NotificationsProvider } from "@gd/ui"; +import { NotificationsProvider, ContextMenuProvider } from "@gd/ui"; import { NavigationManager } from "./managers/NavigationManager"; +import { ContextCascaderProvider } from "@gd/ui"; // import { ContextMenuProvider } from "./components/ContextMenu/ContextMenuContext"; import RiveAppWapper from "./utils/RiveAppWrapper"; import GDAnimation from "./gd_logo_animation.riv"; @@ -195,11 +196,15 @@ const TransWrapper = (props: TransWrapperProps) => { - - - - - + + + + + + + + + diff --git a/apps/desktop/packages/mainWindow/src/pages/Modpacks/ModpacksBrowser.tsx b/apps/desktop/packages/mainWindow/src/pages/Modpacks/ModpacksBrowser.tsx index 14e26ab3c..07896b39c 100644 --- a/apps/desktop/packages/mainWindow/src/pages/Modpacks/ModpacksBrowser.tsx +++ b/apps/desktop/packages/mainWindow/src/pages/Modpacks/ModpacksBrowser.tsx @@ -27,6 +27,7 @@ import { NoMoreModpacks } from "./ModpacksStatus"; import { useInfiniteModsQuery } from "@/components/InfiniteScrollModsQueryWrapper"; +import Sidebar from "@/components/Sidebar/modpacks"; const ModpackBrowser = () => { const [t] = useTransContext(); @@ -97,6 +98,7 @@ const ModpackBrowser = () => {
+ - - <> - - - - - - -
+ + <> + {/* */} + + + + + ); } diff --git a/apps/desktop/packages/mainWindow/src/pages/Mods/ModsBrowser.tsx b/apps/desktop/packages/mainWindow/src/pages/Mods/ModsBrowser.tsx index 2c48b0601..dfc9283a3 100644 --- a/apps/desktop/packages/mainWindow/src/pages/Mods/ModsBrowser.tsx +++ b/apps/desktop/packages/mainWindow/src/pages/Mods/ModsBrowser.tsx @@ -32,6 +32,7 @@ import DefaultImg from "/assets/images/default-instance-img.png"; import { useGDNavigate } from "@/managers/NavigationManager"; import { getInstanceImageUrl } from "@/utils/instances"; import { setInstanceId, instanceId as _instanceId } from "@/utils/browser"; +import Sidebar from "@/components/Sidebar/mods"; const ModsBrowser = () => { const [t] = useTransContext(); @@ -186,6 +187,7 @@ const ModsBrowser = () => {
+ } diff --git a/apps/desktop/packages/mainWindow/src/pages/Mods/index.tsx b/apps/desktop/packages/mainWindow/src/pages/Mods/index.tsx index 41c27d06b..51471b523 100644 --- a/apps/desktop/packages/mainWindow/src/pages/Mods/index.tsx +++ b/apps/desktop/packages/mainWindow/src/pages/Mods/index.tsx @@ -1,20 +1,17 @@ -import Sidebar from "@/components/Sidebar/mods"; import { Outlet } from "@solidjs/router"; import ContentWrapper from "@/components/ModpackBrowserWrapper"; import InfiniteScrollModsLayout from "@/components/InfiniteScrollModsQueryWrapper"; function ModpacksLayout() { return ( -
- - <> - - - - - - -
+ + <> + {/* */} + + + + + ); } diff --git a/apps/desktop/packages/mainWindow/src/utils/instances.tsx b/apps/desktop/packages/mainWindow/src/utils/instances.tsx index d414ca585..e5d471b45 100644 --- a/apps/desktop/packages/mainWindow/src/utils/instances.tsx +++ b/apps/desktop/packages/mainWindow/src/utils/instances.tsx @@ -42,7 +42,11 @@ export const getInactiveState = (status: LaunchState | undefined) => { return status.value.failed_task; } }; - +export const getValideInstance = ( + status: ListInstanceStatus +): ValidListInstance | undefined => { + if (status.status === "valid") return status.value; +}; export const isSubTaskDownload = (input: FESubtask): input is FESubtask => { return typeof input === "object" && "download" in input; }; @@ -158,8 +162,10 @@ export const CategoryIcon = (props: { ); }; -export const PlatformIcon = (props: { modpack: "curseforge" | "modrinth" }) => { - return ; +export const PlatformIcon = (props: { + platform: "curseforge" | "modrinth"; +}) => { + return ; }; export const [importedInstances, setImportedInstances] = createSignal( diff --git a/packages/ui/package.json b/packages/ui/package.json index 71f3a3c9d..575c3c8b4 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -31,6 +31,7 @@ "@unocss/eslint-config": "^0.53.1", "@unocss/transformer-directives": "^0.55.0", "babel-loader": "^9.1.2", + "class-variance-authority": "^0.7.0", "concurrently": "^8.2.0", "eslint": "^8.43.0", "eslint-config-prettier": "^8.8.0", diff --git a/packages/ui/src/Cascader/CascaderContext.tsx b/packages/ui/src/Cascader/CascaderContext.tsx new file mode 100644 index 000000000..efe4f672b --- /dev/null +++ b/packages/ui/src/Cascader/CascaderContext.tsx @@ -0,0 +1,44 @@ +import { + Accessor, + createContext, + createSignal, + JSX, + useContext, +} from "solid-js"; + +type ContextCascaderContextValue = { + openCascader: Accessor; + setOpenCascader: (_target: HTMLElement | null) => void; + closeCascader: () => void; +}; + +const ContextCascaderContext = createContext(); + +type ContextCascaderProviderProps = { + children: JSX.Element; +}; + +const ContextCascaderProvider = (props: ContextCascaderProviderProps) => { + const [openCascader, setOpenCascader] = createSignal( + null + ); + + const closeCascader = () => { + setOpenCascader(null); + }; + const value = { openCascader, setOpenCascader, closeCascader }; + + return ( + + {props.children} + + ); +}; + +const useContextCascader = () => { + return useContext(ContextCascaderContext); +}; + +export { ContextCascaderProvider, useContextCascader }; + +export const Exported = 5; diff --git a/packages/ui/src/Cascader/CascaderItem.tsx b/packages/ui/src/Cascader/CascaderItem.tsx new file mode 100644 index 000000000..e62f465af --- /dev/null +++ b/packages/ui/src/Cascader/CascaderItem.tsx @@ -0,0 +1,171 @@ +import { Accessor, Setter, Show, createEffect, createSignal } from "solid-js"; +import { Checkbox } from "../Checkbox"; +import ChildsMenu, { ChildsMenuProps } from "./ChildsMenu"; +import { Radio } from "../Radio"; +import _ from "lodash"; + +const CascaderItem = (props: { + label: string; + children?: ChildsMenuProps; + name?: string; + value?: string; + isCheckbox?: boolean; + isOpen: boolean; + isParent: boolean; + onToggleMenu: () => void; + img?: any; + id?: string | number; + selectedItems: Accessor; + setSelectedItems: Setter; + parentLabel?: string; + items: { + label: string; + img: any; + id?: string | number; + children?: ChildsMenuProps; + }[]; +}) => { + const [numberOfCheckedItems, setNumberOfCheckedItems] = createSignal(0); + const [currentSelectedItem, setCurrentSelectedItem] = createSignal("None"); + + createEffect(() => { + if (props.children?.isCheckbox) { + setNumberOfCheckedItems( + props + .selectedItems() + .filter((item) => + item?.includes(props.children?.parentLabel as string) + ).length + ); + } + }); + const handleRadio = (val: string | number | string[] | undefined) => { + props.setSelectedItems((prev) => { + const newItems = [...prev]; + const index = newItems.findIndex((item) => + item.includes(props.parentLabel as string) + ); + let newValue = ""; + const findElement = props.items.find( + (item) => item.id === val || item.label === val + ); + if (findElement) { + newValue = `${props.parentLabel}//${findElement.label}`; + } else { + newValue = `${props.parentLabel}//${val}`; + } + + if (index === -1) { + newItems.push(newValue); + } else { + newItems[index] = newValue; + } + + return newItems; + }); + }; + createEffect(() => { + if (props.children) { + const index = props + .selectedItems() + .findIndex((item) => + item.includes(props.children?.parentLabel as string) + ); + if (index === -1) { + setCurrentSelectedItem("None"); + } else { + setCurrentSelectedItem( + props.selectedItems()[index].split("//")[1] || "None" + ); + } + } + }); + return ( +
props.children && props.onToggleMenu()} + > + +
+ {props.label} +
+
+ + { + if ( + props.selectedItems().filter((item) => item.includes(props.label)) + .length > 0 + ) { + props.setSelectedItems((prev) => + prev.filter((item) => !item.includes(props.label)) + ); + } else { + props.setSelectedItems((prev) => [ + ...prev, + props.parentLabel + "//" + props.label, + ]); + } + }} + checked={ + props + .selectedItems() + .filter((item) => item.split("//")[1] === props.label).length > 0 + } + children={ +
+ {props.img && props.img} + {props.label} +
+ } + /> +
+ + item.split("//")[1] === props.label).length > 0 + } + value={props.id || props.label} + children={ +
+ {props.img && props.img} + {props.label} +
+ } + /> +
+ + + + +
+ + {currentSelectedItem()} + + + + {numberOfCheckedItems()}/{props.children?.items.length} + + + +
+
+
+
+ ); +}; +export default CascaderItem; diff --git a/packages/ui/src/Cascader/ChildsMenu.tsx b/packages/ui/src/Cascader/ChildsMenu.tsx new file mode 100644 index 000000000..99ac3bc36 --- /dev/null +++ b/packages/ui/src/Cascader/ChildsMenu.tsx @@ -0,0 +1,123 @@ +import { For, Portal, Show } from "solid-js/web"; +import { Input } from "../Input"; +import { Accessor, Setter, createSignal } from "solid-js"; +import CascaderItem from "./CascaderItem"; + +export interface ChildsMenuProps { + items: { + label: string; + img: any; + id?: string | number; + children?: ChildsMenuProps; + }[]; + isCheckbox: boolean; + hasSearch: boolean; + isParent: boolean; + parentLabel?: string; + selectedItems: Accessor; + setSelectedItems: Setter; + hasChildren?: any; +} + +const ChildsMenu = (props: ChildsMenuProps) => { + const [search, setSearch] = createSignal(""); + const [openItem, setOpenItem] = createSignal(null); + // const [radioValue, setRadio] = createSignal( + // props + // .selectedItems() + // .find((item) => item.includes(props.parentLabel as string)) + // ?.split("//")[1] || "" + // ); + + const toggleMenu = (label: string) => { + setOpenItem((prev) => (prev === label ? null : label)); + }; + // const handleRadio = (val: string | number | string[] | undefined) => { + // props.setSelectedItems((prev) => { + // const newItems = [...prev]; + // const index = newItems.findIndex((item) => + // item.includes(props.parentLabel as string) + // ); + // let newValue = ""; + // const findElement = props.items.find((item) => item.id === val); + // if (findElement) { + // newValue = `${props.parentLabel}//${findElement.label}`; + // } else { + // newValue = `${props.parentLabel}//${val}`; + // } + + // if (index === -1) { + // newItems.push(newValue); + // } else { + // newItems[index] = newValue; + // } + // setRadio(val as string); + + // return newItems; + // }); + // }; + return ( + +
+ + setSearch(e.target.value)} + /> + + + item.label.includes(search()))} + > + {(item) => ( + toggleMenu(item.label)} + isParent={props?.isParent} + img={item.img} + selectedItems={props.selectedItems} + setSelectedItems={props.setSelectedItems} + parentLabel={props.parentLabel} + id={item.id} + items={props.items} + /> + )} + + + + {/* */} + item.label.includes(search()))} + > + {(item) => ( + toggleMenu(item.label)} + isParent={props?.isParent} + img={item.img} + selectedItems={props.selectedItems} + setSelectedItems={props.setSelectedItems} + parentLabel={props.parentLabel} + id={item.id} + items={props.items} + /> + )} + + {/* */} + + {props.hasChildren} +
+
+ ); +}; +export default ChildsMenu; diff --git a/packages/ui/src/Cascader/index.stories.tsx b/packages/ui/src/Cascader/index.stories.tsx new file mode 100644 index 000000000..774338870 --- /dev/null +++ b/packages/ui/src/Cascader/index.stories.tsx @@ -0,0 +1,194 @@ +import type { Meta, StoryObj } from "storybook-solidjs"; +import { Cascader } from "./"; + +const meta: Meta = { + /* 👇 The title prop is optional. + * See https://storybook.js.org/docs/solid/configure/overview#configure-story-loading + * to learn how to generate automatic titles + */ + title: "ChildsMenu", + component: Cascader, +}; + +export default meta; + +type Story = StoryObj; + +export const WithoutParents: Story = { + args: { + hasSearch: false, + isCheckbox: true, + isParent: false, + items: [ + { + label: "Item 1", + img: "", + }, + { + label: "Item 2", + img: "", + }, + { + label: "Item 3", + img: "", + }, + { + label: "Item 4", + img: "", + }, + { + label: "Item 5", + img: "", + }, + { + label: "Item 3", + img: "", + }, + { + label: "Item 6", + img: "", + }, + { + label: "Item 3", + img: "", + }, + { + label: "Item 3", + img: "", + }, + { + label: "Item 3", + img: "", + }, + { + label: "Item 3", + img: "", + }, + { + label: "Item 3", + img: "", + }, + ], + }, +}; + +// export const WithParents: Story = { +// args: { +// hasSearch: false, +// isCheckbox: false, +// isParent: true, +// children: , +// parentLabel: "Parent", +// items: [ +// { +// label: "Item 1", +// img: "", +// }, +// { +// label: "Item 2", +// img: "", + +// children: { +// parentLabel: "Item 2", +// isParent: false, +// items: [ +// { +// label: "Subitem 2.1", +// img: "", +// }, +// { +// label: "Subitem 2.2", +// img: "", +// children: { +// parentLabel: "Subitem 2.2", +// isParent: false, +// items: [ +// { +// label: "Subsubitem 2.2.1", +// img: "", +// }, +// ], +// isCheckbox: true, +// hasSearch: false, +// }, +// }, +// { +// label: "Subitem 2.3", +// img: "", +// }, +// ], +// isCheckbox: true, +// hasSearch: false, +// }, +// }, +// { +// label: "Item 3", +// img: "", +// children: { +// parentLabel: "Item 3", +// isParent: false, +// items: [ +// { +// label: "Subitem 3.1", +// img: "", +// }, +// ], +// isCheckbox: true, +// hasSearch: false, +// }, +// }, +// { +// label: "Item 4", +// img: "", +// children: { +// parentLabel: "Item 4", +// isParent: false, +// items: [ +// { +// label: "Subitem 4.1", +// img: "", +// }, +// ], +// isCheckbox: true, +// hasSearch: false, +// }, +// }, +// { +// label: "Item 5", +// img: "", +// }, +// { +// label: "Item 6", +// img: "", +// }, +// { +// label: "Item 7", +// img: "", +// }, +// { +// label: "Item 8", +// img: "", +// }, +// { +// label: "Item 9", +// img: "", +// }, +// { +// label: "Item 10", +// img: "", +// }, +// { +// label: "Item 11", +// img: "", +// }, +// { +// label: "Item 12", +// img: "", +// }, +// { +// label: "Item 13", +// img: "", +// }, +// ], +// }, +// }; diff --git a/packages/ui/src/Cascader/index.tsx b/packages/ui/src/Cascader/index.tsx new file mode 100644 index 000000000..d00ea6967 --- /dev/null +++ b/packages/ui/src/Cascader/index.tsx @@ -0,0 +1,123 @@ +import { Portal } from "solid-js/web"; +import ChildsMenu, { ChildsMenuProps } from "./ChildsMenu"; +import { + Show, + createSignal, + mergeProps, + onCleanup, + onMount, + splitProps, +} from "solid-js"; +import { useContextCascader } from "./CascaderContext"; + +interface ParentProps extends ChildsMenuProps { + trigger?: "context" | "click"; + children: any; +} + +const Cascader = (props: ParentProps) => { + const [local, others] = splitProps(props, ["trigger", "children"]); + const [x, setX] = createSignal(0); + const [y, setY] = createSignal(0); + const [menuRef, setMenuRef] = createSignal(); + const [containerRef, setContainerRef] = createSignal< + HTMLDivElement | undefined + >(); + + const cascaderContext = useContextCascader(); + + const mergedProps = mergeProps( + { + trigger: "context", + }, + props + ); + + const openContextMenu = (e: MouseEvent) => { + e.preventDefault(); + + if (containerRef()) { + cascaderContext?.setOpenCascader(containerRef() as HTMLDivElement); + } + + // Initially set the position to cursor location + setX(e.clientX); + setY(e.clientY); + + // Wait for the next frame when the menu has been painted + requestAnimationFrame(() => { + if (menuRef()) { + const menuElement = menuRef() as HTMLDivElement; + const boundingClientRect = menuElement.getBoundingClientRect(); + + let newX = e.clientX; // No change to X coordinate + let newY = e.clientY - boundingClientRect.height; + + // If the new y position is less than 0, set it to 0 to prevent the menu from going out of view to the top + if (newY < 0) { + newY = 0; + } + + setX(newX); + setY(newY); + } + }); + }; + const closeContextMenu = () => { + cascaderContext?.closeCascader(); + }; + + const handleClickOutside = (e: MouseEvent) => { + if ( + containerRef() && + !containerRef()?.contains(e.target as Node) && + menuRef() && + !menuRef()?.contains(e.target as Node) && + (e.target as Element).classList[0] !== "i-ri:check-line" && + containerRef() == cascaderContext?.openCascader() + ) { + closeContextMenu(); + } + }; + + const isContextTrigger = () => mergedProps.trigger === "context"; + + onMount(() => { + document.addEventListener("click", handleClickOutside); + if (isContextTrigger()) { + containerRef()?.addEventListener("contextmenu", openContextMenu); + } else { + containerRef()?.addEventListener("click", openContextMenu); + } + }); + + onCleanup(() => { + document.removeEventListener("click", handleClickOutside); + containerRef()?.removeEventListener("contextmenu", openContextMenu); + containerRef()?.removeEventListener("click", openContextMenu); + }); + return ( +
+ {local.children} + + + + + +
+ ); +}; +export { Cascader }; diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 0ef9696da..20e5bb969 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -25,4 +25,9 @@ export { Tooltip } from "./Tooltip"; export { Popover } from "./Popover"; export { ContextMenu } from "./Menu"; export { ContextMenuProvider, useContextMenu } from "./Menu/ContextMenuContext"; +export { Cascader } from "./Cascader"; +export { + ContextCascaderProvider, + useContextCascader, +} from "./Cascader/CascaderContext"; export * from "./themes"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e03cdc02c..23979e36c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,7 +62,7 @@ importers: version: 0.2.0 '@rspc/solid': specifier: ^0.2.0 - version: 0.2.0(@tanstack/solid-query@5.28.5)(solid-js@1.8.15) + version: 0.2.0(@tanstack/solid-query@5.28.8)(solid-js@1.8.15) '@sentry/electron': specifier: ^4.19.0 version: 4.19.0 @@ -80,7 +80,7 @@ importers: version: 0.9.1(solid-js@1.8.15) '@tanstack/solid-query': specifier: ^5.28.5 - version: 5.28.5(solid-js@1.8.15) + version: 5.28.8(solid-js@1.8.15) '@tanstack/solid-virtual': specifier: 3.2.0 version: 3.2.0(solid-js@1.8.15) @@ -340,6 +340,9 @@ importers: babel-loader: specifier: ^9.1.2 version: 9.1.3(@babel/core@7.23.7)(webpack@5.90.0) + class-variance-authority: + specifier: ^0.7.0 + version: 0.7.0 concurrently: specifier: ^8.2.0 version: 8.2.2 @@ -4624,14 +4627,14 @@ packages: resolution: {integrity: sha512-IIOfAk4g+bzbfr3cmvm42EocsjtzMO9CRCc95ZMx9mFh5ixHzP4Na1lun+KipGzsFV1QsmV6uYSBg/4Kpnu9iA==} dev: true - /@rspc/solid@0.2.0(@tanstack/solid-query@5.28.5)(solid-js@1.8.15): + /@rspc/solid@0.2.0(@tanstack/solid-query@5.28.8)(solid-js@1.8.15): resolution: {integrity: sha512-6w7kSn3ZeSikUNI5niE+HszTA6mDMIOglhg92BdKOKw7YeuC0b11k9gAXNq1tyOVsn8KGKlkFgPr5iOP4G0k2A==} peerDependencies: '@tanstack/solid-query': ^5.0.0 solid-js: ^1.0.0 dependencies: '@rspc/client': 0.2.0 - '@tanstack/solid-query': 5.28.5(solid-js@1.8.15) + '@tanstack/solid-query': 5.28.8(solid-js@1.8.15) solid-js: 1.8.15 dev: true @@ -6294,16 +6297,16 @@ packages: defer-to-connect: 2.0.1 dev: true - /@tanstack/query-core@5.28.4: - resolution: {integrity: sha512-uQZqOFqLWUvXNIQZ63XdKzg22NtHzgCBUfDmjDHi3BoF+nUYeBNvMi/xFPtFrMhqRzG2Ir4mYaGsWZzmiEjXpA==} + /@tanstack/query-core@5.28.8: + resolution: {integrity: sha512-cx64XHeB0kvKxFt22ibvegPeOxnaWVFUbAuhXoIrb7+XePEexHWoB9Kq5n9qroNPkRwQZwgFAP9HNbQz5ohoIg==} dev: true - /@tanstack/solid-query@5.28.5(solid-js@1.8.15): - resolution: {integrity: sha512-qQrs3lVOPi7Jj+ud7WtaGsWwv/2GGnIbqzlQZ49xTvkCfBM20OynRh90j1WB+EoNq5tr0ozCZP/lvnCy2w4lZQ==} + /@tanstack/solid-query@5.28.8(solid-js@1.8.15): + resolution: {integrity: sha512-08/1AY8wI1NxnyR5nhjN4FEGrWFMNHa8k+yDS6tkyrbqurh21yfOGzInoPTKHAJEeuuDdFHyPEfz8wo24gB8XQ==} peerDependencies: solid-js: ^1.6.0 dependencies: - '@tanstack/query-core': 5.28.4 + '@tanstack/query-core': 5.28.8 solid-js: 1.8.15 dev: true @@ -6575,7 +6578,7 @@ packages: /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 16.18.75 + '@types/node': 20.11.6 dev: true /@types/lodash@4.14.202: @@ -6617,7 +6620,7 @@ packages: /@types/node-fetch@2.6.11: resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} dependencies: - '@types/node': 18.19.9 + '@types/node': 20.11.6 form-data: 4.0.0 dev: true @@ -6680,7 +6683,7 @@ packages: /@types/responselike@1.0.3: resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} dependencies: - '@types/node': 16.18.75 + '@types/node': 20.11.6 dev: true /@types/sanitize-html@2.9.5: @@ -8116,7 +8119,6 @@ packages: /bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - requiresBuild: true dependencies: buffer: 5.7.1 inherits: 2.0.4 @@ -8247,7 +8249,6 @@ packages: /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - requiresBuild: true dependencies: base64-js: 1.5.1 ieee754: 1.2.1 @@ -8484,7 +8485,6 @@ packages: /chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - requiresBuild: true /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} @@ -8522,7 +8522,6 @@ packages: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} dependencies: clsx: 2.0.0 - dev: false /clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} @@ -8601,7 +8600,6 @@ packages: /clsx@2.0.0: resolution: {integrity: sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==} engines: {node: '>=6'} - dev: false /clsx@2.1.0: resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==} @@ -8980,7 +8978,6 @@ packages: /decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} - requiresBuild: true dependencies: mimic-response: 3.1.0 @@ -9430,7 +9427,6 @@ packages: /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - requiresBuild: true dependencies: once: 1.4.0 @@ -10381,7 +10377,6 @@ packages: /fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - requiresBuild: true /fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} @@ -12860,7 +12855,6 @@ packages: /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - requiresBuild: true /minipass@3.3.6: resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} @@ -12893,7 +12887,6 @@ packages: /mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - requiresBuild: true /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} @@ -13184,7 +13177,6 @@ packages: /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - requiresBuild: true dependencies: wrappy: 1.0.2 @@ -13858,7 +13850,6 @@ packages: /pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - requiresBuild: true dependencies: end-of-stream: 1.4.4 once: 1.4.0 @@ -15401,7 +15392,6 @@ packages: /tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} - requiresBuild: true dependencies: chownr: 1.1.4 mkdirp-classic: 0.5.3 @@ -15420,7 +15410,6 @@ packages: /tar-stream@2.2.0: resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} engines: {node: '>=6'} - requiresBuild: true dependencies: bl: 4.1.0 end-of-stream: 1.4.4 @@ -16965,7 +16954,6 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - requiresBuild: true /write-file-atomic@2.4.3: resolution: {integrity: sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==}