mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-02 16:23:48 +03:00
feat: adding link direct from sources
This commit is contained in:
parent
3af0ae9f85
commit
d3450c5f65
@ -62,11 +62,13 @@
|
||||
"lodash-es": "^4.17.21",
|
||||
"parse-torrent": "^11.0.17",
|
||||
"piscina": "^4.7.0",
|
||||
"rc-virtual-list": "^3.16.1",
|
||||
"react-hook-form": "^7.53.0",
|
||||
"react-i18next": "^14.1.0",
|
||||
"react-loading-skeleton": "^3.4.0",
|
||||
"react-redux": "^9.1.1",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"react-virtualized": "^9.22.5",
|
||||
"sound-play": "^1.1.0",
|
||||
"sudo-prompt": "^9.2.1",
|
||||
"tar": "^7.4.3",
|
||||
|
@ -8,6 +8,8 @@ import "./catalogue/get-random-game";
|
||||
import "./catalogue/search-games";
|
||||
import "./catalogue/get-game-stats";
|
||||
import "./catalogue/get-trending-games";
|
||||
import "./catalogue/get-publishers";
|
||||
import "./catalogue/get-developers";
|
||||
import "./hardware/get-disk-free-space";
|
||||
import "./library/add-game-to-library";
|
||||
import "./library/create-game-shortcut";
|
||||
|
@ -65,6 +65,8 @@ contextBridge.exposeInMainWorld("electron", {
|
||||
listener
|
||||
);
|
||||
},
|
||||
getPublishers: () => ipcRenderer.invoke("getPublishers"),
|
||||
getDevelopers: () => ipcRenderer.invoke("getDevelopers"),
|
||||
|
||||
/* User preferences */
|
||||
getUserPreferences: () => ipcRenderer.invoke("getUserPreferences"),
|
||||
|
@ -7,9 +7,5 @@ export interface BadgeProps {
|
||||
}
|
||||
|
||||
export function Badge({ children }: BadgeProps) {
|
||||
return (
|
||||
<div className="badge">
|
||||
<span>{children}</span>
|
||||
</div>
|
||||
);
|
||||
return <div className="badge">{children}</div>;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ export const checkbox = recipe({
|
||||
border: `solid 1px ${vars.color.border}`,
|
||||
minWidth: "20px",
|
||||
minHeight: "20px",
|
||||
color: vars.color.darkBackground,
|
||||
":hover": {
|
||||
borderColor: "rgba(255, 255, 255, 0.5)",
|
||||
},
|
||||
|
2
src/renderer/src/declaration.d.ts
vendored
2
src/renderer/src/declaration.d.ts
vendored
@ -68,6 +68,8 @@ declare global {
|
||||
shop: GameShop,
|
||||
cb: (achievements: GameAchievement[]) => void
|
||||
) => () => Electron.IpcRenderer;
|
||||
getPublishers: () => Promise<string[]>;
|
||||
getDevelopers: () => Promise<string[]>;
|
||||
|
||||
/* Library */
|
||||
addGameToLibrary: (
|
||||
|
@ -34,4 +34,4 @@ export const catalogueSearchSlice = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export const { setSearch } = catalogueSearchSlice.actions;
|
||||
export const { setSearch, clearSearch } = catalogueSearchSlice.actions;
|
||||
|
@ -20,6 +20,14 @@ import { setSearch } from "@renderer/features";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { steamUserTags } from "./steam-user-tags";
|
||||
|
||||
const filterCategoryColors = {
|
||||
genres: "hsl(262deg 50% 47%)",
|
||||
tags: "hsl(95deg 50% 20%)",
|
||||
downloadSourceFingerprints: "hsl(27deg 50% 40%)",
|
||||
developers: "hsl(340deg 50% 46%)",
|
||||
publishers: "hsl(200deg 50% 30%)",
|
||||
};
|
||||
|
||||
export default function Catalogue() {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
@ -34,6 +42,8 @@ export default function Catalogue() {
|
||||
|
||||
const [downloadSources, setDownloadSources] = useState<DownloadSource[]>([]);
|
||||
const [games, setGames] = useState<any[]>([]);
|
||||
const [publishers, setPublishers] = useState<string[]>([]);
|
||||
const [developers, setDevelopers] = useState<string[]>([]);
|
||||
|
||||
const filters = useAppSelector((state) => state.catalogueSearch.value);
|
||||
|
||||
@ -59,6 +69,16 @@ export default function Catalogue() {
|
||||
});
|
||||
}, [filters]);
|
||||
|
||||
useEffect(() => {
|
||||
window.electron.getDevelopers().then((developers) => {
|
||||
setDevelopers(developers);
|
||||
});
|
||||
|
||||
window.electron.getPublishers().then((publishers) => {
|
||||
setPublishers(publishers);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const gamesWithRepacks = useMemo(() => {
|
||||
return games.map((game) => {
|
||||
const repacks = getRepacksForObjectId(game.objectId);
|
||||
@ -148,13 +168,50 @@ export default function Catalogue() {
|
||||
}}
|
||||
>
|
||||
<div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
|
||||
{filters.genres.map((genre) => (
|
||||
<Badge key={genre}>
|
||||
<div style={{ display: "flex", gap: 4, alignItems: "center" }}>
|
||||
<div
|
||||
style={{
|
||||
width: 10,
|
||||
height: 10,
|
||||
backgroundColor: filterCategoryColors.genres,
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
/>
|
||||
|
||||
{genre}
|
||||
</div>
|
||||
</Badge>
|
||||
))}
|
||||
|
||||
{filters.tags.map((tag) => (
|
||||
<Badge key={tag}>
|
||||
<div style={{ display: "flex", gap: 4, alignItems: "center" }}>
|
||||
{tag}
|
||||
</div>
|
||||
</Badge>
|
||||
))}
|
||||
|
||||
{filters.downloadSourceFingerprints.map((fingerprint) => (
|
||||
<Badge key={fingerprint}>
|
||||
<div style={{ display: "flex", gap: 4, alignItems: "center" }}>
|
||||
<div
|
||||
style={{
|
||||
width: 10,
|
||||
height: 10,
|
||||
backgroundColor:
|
||||
filterCategoryColors.downloadSourceFingerprints,
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
/>
|
||||
|
||||
{
|
||||
downloadSources.find(
|
||||
(source) => source.fingerprint === fingerprint
|
||||
)?.name
|
||||
}
|
||||
</div>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
@ -248,6 +305,7 @@ export default function Catalogue() {
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
|
||||
<FilterSection
|
||||
title="Genres"
|
||||
color={filterCategoryColors.genres}
|
||||
onSelect={(value) => {
|
||||
if (filters.genres.includes(value)) {
|
||||
dispatch(
|
||||
@ -300,6 +358,7 @@ export default function Catalogue() {
|
||||
|
||||
<FilterSection
|
||||
title="User tags"
|
||||
color={filterCategoryColors.tags}
|
||||
onSelect={(value) => {
|
||||
if (filters.tags.includes(value)) {
|
||||
dispatch(
|
||||
@ -322,6 +381,7 @@ export default function Catalogue() {
|
||||
|
||||
<FilterSection
|
||||
title="Download sources"
|
||||
color={filterCategoryColors.downloadSourceFingerprints}
|
||||
onSelect={(value) => {
|
||||
if (filters.downloadSourceFingerprints.includes(value)) {
|
||||
dispatch(
|
||||
@ -351,6 +411,56 @@ export default function Catalogue() {
|
||||
),
|
||||
}))}
|
||||
/>
|
||||
|
||||
<FilterSection
|
||||
title="Developers"
|
||||
color={filterCategoryColors.developers}
|
||||
onSelect={(value) => {
|
||||
if (filters.developers.includes(value)) {
|
||||
dispatch(
|
||||
setSearch({
|
||||
developers: filters.developers.filter(
|
||||
(developer) => developer !== value
|
||||
),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
dispatch(
|
||||
setSearch({ developers: [...filters.developers, value] })
|
||||
);
|
||||
}
|
||||
}}
|
||||
items={developers.map((developer) => ({
|
||||
label: developer,
|
||||
value: developer,
|
||||
checked: filters.developers.includes(developer),
|
||||
}))}
|
||||
/>
|
||||
|
||||
<FilterSection
|
||||
title="Publishers"
|
||||
color={filterCategoryColors.publishers}
|
||||
onSelect={(value) => {
|
||||
if (filters.publishers.includes(value)) {
|
||||
dispatch(
|
||||
setSearch({
|
||||
publishers: filters.publishers.filter(
|
||||
(publisher) => publisher !== value
|
||||
),
|
||||
})
|
||||
);
|
||||
} else {
|
||||
dispatch(
|
||||
setSearch({ publishers: [...filters.publishers, value] })
|
||||
);
|
||||
}
|
||||
}}
|
||||
items={publishers.map((publisher) => ({
|
||||
label: publisher,
|
||||
value: publisher,
|
||||
checked: filters.publishers.includes(publisher),
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,6 +2,8 @@ import { CheckboxField, TextField } from "@renderer/components";
|
||||
import { useFormat } from "@renderer/hooks";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
|
||||
import List from "rc-virtual-list";
|
||||
|
||||
export interface FilterSectionProps<T extends string | number> {
|
||||
title: string;
|
||||
items: {
|
||||
@ -10,11 +12,13 @@ export interface FilterSectionProps<T extends string | number> {
|
||||
checked: boolean;
|
||||
}[];
|
||||
onSelect: (value: T) => void;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export function FilterSection<T extends string | number>({
|
||||
title,
|
||||
items,
|
||||
color,
|
||||
onSelect,
|
||||
}: FilterSectionProps<T>) {
|
||||
const [search, setSearch] = useState("");
|
||||
@ -37,6 +41,15 @@ export function FilterSection<T extends string | number>({
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: "flex", gap: 8, alignItems: "center" }}>
|
||||
<div
|
||||
style={{
|
||||
width: 10,
|
||||
height: 10,
|
||||
backgroundColor: color,
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
/>
|
||||
<h3
|
||||
style={{
|
||||
fontSize: 16,
|
||||
@ -46,6 +59,7 @@ export function FilterSection<T extends string | number>({
|
||||
>
|
||||
{title}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<span style={{ fontSize: 12, marginBottom: 12, display: "block" }}>
|
||||
{formatNumber(items.length)} disponíveis
|
||||
@ -59,25 +73,31 @@ export function FilterSection<T extends string | number>({
|
||||
theme="dark"
|
||||
/>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: 8,
|
||||
overflowY: "auto",
|
||||
maxHeight: 28 * 10,
|
||||
<List
|
||||
data={filteredItems}
|
||||
height={28 * 10}
|
||||
itemHeight={28}
|
||||
itemKey="value"
|
||||
styles={{
|
||||
verticalScrollBar: {
|
||||
backgroundColor: "rgba(255, 255, 255, 0.03)",
|
||||
},
|
||||
verticalScrollBarThumb: {
|
||||
backgroundColor: "rgba(255, 255, 255, 0.08)",
|
||||
borderRadius: "24px",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{filteredItems.map((item) => (
|
||||
<div key={item.value}>
|
||||
{(item) => (
|
||||
<div key={item.value} style={{ height: 28, maxHeight: 28 }}>
|
||||
<CheckboxField
|
||||
label={item.label}
|
||||
checked={item.checked}
|
||||
onChange={() => onSelect(item.value)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</List>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -7,12 +7,14 @@ import * as styles from "./settings-download-sources.css";
|
||||
import type { DownloadSource } from "@types";
|
||||
import { NoEntryIcon, PlusCircleIcon, SyncIcon } from "@primer/octicons-react";
|
||||
import { AddDownloadSourceModal } from "./add-download-source-modal";
|
||||
import { useRepacks, useToast } from "@renderer/hooks";
|
||||
import { useAppDispatch, useRepacks, useToast } from "@renderer/hooks";
|
||||
import { DownloadSourceStatus } from "@shared";
|
||||
import { SPACING_UNIT } from "@renderer/theme.css";
|
||||
import { SPACING_UNIT, vars } from "@renderer/theme.css";
|
||||
import { settingsContext } from "@renderer/context";
|
||||
import { downloadSourcesTable } from "@renderer/dexie";
|
||||
import { downloadSourcesWorker } from "@renderer/workers";
|
||||
import { clearSearch, setSearch } from "@renderer/features";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
export function SettingsDownloadSources() {
|
||||
const [showAddDownloadSourceModal, setShowAddDownloadSourceModal] =
|
||||
@ -28,6 +30,10 @@ export function SettingsDownloadSources() {
|
||||
const { t } = useTranslation("settings");
|
||||
const { showSuccessToast } = useToast();
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { updateRepacks } = useRepacks();
|
||||
|
||||
const getDownloadSources = async () => {
|
||||
@ -96,6 +102,13 @@ export function SettingsDownloadSources() {
|
||||
setShowAddDownloadSourceModal(false);
|
||||
};
|
||||
|
||||
const navigateToCatalogue = (fingerprint: string) => {
|
||||
dispatch(clearSearch());
|
||||
dispatch(setSearch({ downloadSourceFingerprints: [fingerprint] }));
|
||||
|
||||
navigate("/catalogue");
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<AddDownloadSourceModal
|
||||
@ -147,12 +160,17 @@ export function SettingsDownloadSources() {
|
||||
<Badge>{statusTitle[downloadSource.status]}</Badge>
|
||||
</div>
|
||||
|
||||
<div
|
||||
<button
|
||||
type="button"
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
color: vars.color.muted,
|
||||
textDecoration: "underline",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onClick={() => navigateToCatalogue(downloadSource.fingerprint)}
|
||||
>
|
||||
<small>
|
||||
{t("download_count", {
|
||||
@ -161,7 +179,7 @@ export function SettingsDownloadSources() {
|
||||
downloadSource.downloadCount.toLocaleString(),
|
||||
})}
|
||||
</small>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<TextField
|
||||
|
79
yarn.lock
79
yarn.lock
@ -978,6 +978,13 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7":
|
||||
version "7.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1"
|
||||
integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/template@^7.22.15", "@babel/template@^7.24.0":
|
||||
version "7.24.0"
|
||||
resolved "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz"
|
||||
@ -3852,7 +3859,7 @@ ci-info@^3.2.0:
|
||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4"
|
||||
integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==
|
||||
|
||||
classnames@^2.5.1:
|
||||
classnames@^2.2.1, classnames@^2.2.6, classnames@^2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
|
||||
integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
|
||||
@ -3924,6 +3931,11 @@ clone@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||
integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
|
||||
|
||||
clsx@^1.0.4:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
|
||||
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
@ -4384,6 +4396,14 @@ doctrine@^3.0.0:
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
dom-helpers@^5.1.3:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
|
||||
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.8.7"
|
||||
csstype "^3.0.2"
|
||||
|
||||
dot-case@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
|
||||
@ -7248,7 +7268,7 @@ promise-retry@^2.0.1:
|
||||
err-code "^2.0.2"
|
||||
retry "^0.12.0"
|
||||
|
||||
prop-types@^15.8.1:
|
||||
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"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
@ -7300,6 +7320,34 @@ quick-lru@^5.1.1:
|
||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
|
||||
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
||||
|
||||
rc-resize-observer@^1.0.0:
|
||||
version "1.4.3"
|
||||
resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz#4fd41fa561ba51362b5155a07c35d7c89a1ea569"
|
||||
integrity sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.20.7"
|
||||
classnames "^2.2.1"
|
||||
rc-util "^5.44.1"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
|
||||
rc-util@^5.36.0, rc-util@^5.44.1:
|
||||
version "5.44.2"
|
||||
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.44.2.tgz#6bc5db0e96ebdb515eb5977a7371887e5413a6f8"
|
||||
integrity sha512-uGSk3hpPBLa3/0QAcKhCjgl4SFnhQCJDLvvpoLdbR6KgDuXrujG+dQaUeUvBJr2ZWak1O/9n+cYbJiWmmk95EQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.18.3"
|
||||
react-is "^18.2.0"
|
||||
|
||||
rc-virtual-list@^3.16.1:
|
||||
version "3.16.1"
|
||||
resolved "https://registry.yarnpkg.com/rc-virtual-list/-/rc-virtual-list-3.16.1.tgz#073d75cc0295497cdd9a35d6f5d1b71b4f35233e"
|
||||
integrity sha512-algM5UsB7vrlPNr9lsZEH8s9KHkP8XbT/Y0qylyPkiM8mIOlSJLjBNADcmbYPEQCm4zW82mZRJuVHNzqqN0EAQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.20.0"
|
||||
classnames "^2.2.6"
|
||||
rc-resize-observer "^1.0.0"
|
||||
rc-util "^5.36.0"
|
||||
|
||||
rc@^1.2.7:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||
@ -7336,6 +7384,16 @@ react-is@^16.13.1:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-is@^18.2.0:
|
||||
version "18.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
|
||||
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
|
||||
|
||||
react-lifecycles-compat@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-loading-skeleton@^3.4.0:
|
||||
version "3.5.0"
|
||||
resolved "https://registry.yarnpkg.com/react-loading-skeleton/-/react-loading-skeleton-3.5.0.tgz#da2090355b4dedcad5c53cb3f0ed364e3a76d6ca"
|
||||
@ -7369,6 +7427,18 @@ react-router@6.26.2:
|
||||
dependencies:
|
||||
"@remix-run/router" "1.19.2"
|
||||
|
||||
react-virtualized@^9.22.5:
|
||||
version "9.22.5"
|
||||
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.22.5.tgz#bfb96fed519de378b50d8c0064b92994b3b91620"
|
||||
integrity sha512-YqQMRzlVANBv1L/7r63OHa2b0ZsAaDp1UhVNEdUaXI8A5u6hTpA5NYtUueLH2rFuY/27mTGIBl7ZhqFKzw18YQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.2"
|
||||
clsx "^1.0.4"
|
||||
dom-helpers "^5.1.3"
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.7.2"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
react@^18.2.0:
|
||||
version "18.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
|
||||
@ -7485,6 +7555,11 @@ reselect@^5.1.0:
|
||||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e"
|
||||
integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==
|
||||
|
||||
resize-observer-polyfill@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||
|
||||
resolve-alpn@^1.0.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9"
|
||||
|
Loading…
Reference in New Issue
Block a user