mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 01:38:44 +00:00
Merge pull request #412 from storytold/bflat-fy-new-profile-pagination
pagination for profile tabs
This commit is contained in:
9 files changed
+413
-71
No files matched your search
@@ -15,6 +15,8 @@
|
||||
"@fortawesome/pro-regular-svg-icons": "^6.2.1",
|
||||
"@fortawesome/pro-solid-svg-icons": "^6.2.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@types/react-paginate": "^7.1.4",
|
||||
"react-paginate": "^8.2.0",
|
||||
"@react-spring/types": "^9.7.3",
|
||||
"@react-spring/web": "^9.7.3",
|
||||
"@storyteller/components": "0.1.0",
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
@import "scss/colours.scss";
|
||||
|
||||
.pagination {
|
||||
.page-link {
|
||||
color: rgba($white, 75%) !important;
|
||||
background-color: $secondary;
|
||||
border: 1px solid $secondary;
|
||||
transition: 0.2s;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background-color: lighten($secondary, 4%);
|
||||
border-color: lighten($secondary, 4%);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.active .page-link {
|
||||
color: $white !important;
|
||||
background-color: lighten($secondary, 15%);
|
||||
border-color: lighten($secondary, 15%);
|
||||
}
|
||||
|
||||
.disabled .page-link {
|
||||
color: rgba($white, 20%) !important;
|
||||
background-color: $secondary;
|
||||
border-color: $secondary;
|
||||
}
|
||||
|
||||
.page-item {
|
||||
&:last-child .page-link {
|
||||
border-top-right-radius: 0.5rem;
|
||||
border-bottom-right-radius: 0.5rem;
|
||||
}
|
||||
&:first-child .page-link {
|
||||
border-top-left-radius: 0.5rem;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import {
|
||||
faChevronLeft,
|
||||
faChevronRight,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import React from "react";
|
||||
import ReactPaginate from "react-paginate";
|
||||
import "./Pagination.scss";
|
||||
|
||||
interface PaginationComponentProps {
|
||||
currentPage: number;
|
||||
itemsPerPage: number;
|
||||
totalItems: number;
|
||||
onPageChange: (selectedItem: { selected: number }) => void;
|
||||
}
|
||||
|
||||
export default function Pagination({
|
||||
itemsPerPage,
|
||||
totalItems,
|
||||
onPageChange,
|
||||
currentPage,
|
||||
}: PaginationComponentProps) {
|
||||
const pageCount = Math.ceil(totalItems / itemsPerPage);
|
||||
|
||||
return (
|
||||
<ReactPaginate
|
||||
previousLabel={<FontAwesomeIcon icon={faChevronLeft} />}
|
||||
nextLabel={<FontAwesomeIcon icon={faChevronRight} />}
|
||||
breakLabel={"..."}
|
||||
pageCount={pageCount}
|
||||
marginPagesDisplayed={1}
|
||||
pageRangeDisplayed={3}
|
||||
onPageChange={onPageChange}
|
||||
containerClassName={"pagination"}
|
||||
activeClassName={"active"}
|
||||
pageClassName={"page-item"}
|
||||
pageLinkClassName={"page-link"}
|
||||
previousClassName={"page-item"}
|
||||
previousLinkClassName={"page-link"}
|
||||
nextClassName={"page-item"}
|
||||
nextLinkClassName={"page-link"}
|
||||
breakClassName={"page-item"}
|
||||
breakLinkClassName={"page-link"}
|
||||
forcePage={currentPage}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from "./Pagination";
|
||||
+143
-38
@@ -3,54 +3,159 @@ import MasonryGrid from "components/common/MasonryGrid/MasonryGrid";
|
||||
import AudioCard from "components/common/Card/AudioCard";
|
||||
import ImageCard from "components/common/Card/ImageCard";
|
||||
import VideoCard from "components/common/Card/VideoCard";
|
||||
import AudioPlayerProvider from "components/common/AudioPlayer/AudioPlayerContext";
|
||||
import SkeletonCard from "components/common/Card/SkeletonCard";
|
||||
import mockWeightsData from "./mockWeightsData";
|
||||
import Select from "components/common/Select";
|
||||
import {
|
||||
faArrowDownWideShort,
|
||||
faFilter,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import Pagination from "components/common/Pagination";
|
||||
|
||||
export default function BookmarksTab() {
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [data] = useState(mockWeightsData);
|
||||
const [isLoading] = useState(false);
|
||||
const [selectedFilter, setSelectedFilter] = useState("all");
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const itemsPerPage = 10;
|
||||
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const handlePageClick = (selectedItem: { selected: number }) => {
|
||||
setCurrentPage(selectedItem.selected);
|
||||
};
|
||||
|
||||
const currentItems = data.slice(
|
||||
currentPage * itemsPerPage,
|
||||
(currentPage + 1) * itemsPerPage
|
||||
);
|
||||
|
||||
const filterOptions = [
|
||||
{ value: "all", label: "All Weights" },
|
||||
{ value: "tts", label: "Text to Speech" },
|
||||
{ value: "vc", label: "Voice to Voice" },
|
||||
{ value: "sd", label: "Image Generation" },
|
||||
];
|
||||
|
||||
const sortOptions = [
|
||||
{ value: "newest", label: "Newest" },
|
||||
{ value: "oldest", label: "Oldest" },
|
||||
{ value: "mostliked", label: "Most Bookmarked" },
|
||||
];
|
||||
|
||||
const modelTtsOptions = [
|
||||
{ value: "all", label: "All Types" },
|
||||
{ value: "tt2", label: "Tacotron 2" },
|
||||
];
|
||||
|
||||
const modelVcOptions = [
|
||||
{ value: "all", label: "All Types" },
|
||||
{ value: "rvc", label: "RVCv2" },
|
||||
{ value: "svc", label: "SoVitsSvc" },
|
||||
];
|
||||
|
||||
const modelSdOptions = [
|
||||
{ value: "all", label: "All Types" },
|
||||
{ value: "lora", label: "LoRA" },
|
||||
{ value: "SD15", label: "SD 1.5" },
|
||||
{ value: "SDXL", label: "SD XL" },
|
||||
];
|
||||
|
||||
const handleFilterChange = (option: any) => {
|
||||
const selectedOption = option as { value: string; label: string };
|
||||
setSelectedFilter(selectedOption.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<AudioPlayerProvider>
|
||||
{isLoading ? (
|
||||
<div className="row gx-3 gy-3">
|
||||
{Array.from({ length: 6 }).map((_, index) => (
|
||||
<SkeletonCard key={index} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<MasonryGrid
|
||||
gridRef={gridContainerRef}
|
||||
onLayoutComplete={() => console.log("Layout complete!")}
|
||||
>
|
||||
{data.map((data, index) => {
|
||||
let card;
|
||||
switch (data.media_type) {
|
||||
case "audio":
|
||||
card = <AudioCard key={index} data={data} type="weights" />;
|
||||
break;
|
||||
case "image":
|
||||
card = <ImageCard key={index} data={data} type="weights" />;
|
||||
break;
|
||||
case "video":
|
||||
card = <VideoCard key={index} data={data} type="weights" />;
|
||||
break;
|
||||
default:
|
||||
card = <div key={index}>Unsupported media type</div>;
|
||||
}
|
||||
return (
|
||||
<div key={index} className="col-12 col-sm-6 col-xl-4 grid-item">
|
||||
{card}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</MasonryGrid>
|
||||
)}
|
||||
</AudioPlayerProvider>
|
||||
<div className="d-flex flex-wrap gap-3 mb-3">
|
||||
<div className="d-flex gap-2 flex-grow-1">
|
||||
<Select
|
||||
icon={faArrowDownWideShort}
|
||||
options={sortOptions}
|
||||
defaultValue={sortOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
|
||||
<Select
|
||||
icon={faFilter}
|
||||
options={filterOptions}
|
||||
defaultValue={filterOptions[0]}
|
||||
isSearchable={false}
|
||||
onChange={handleFilterChange}
|
||||
/>
|
||||
|
||||
{selectedFilter === "tts" && (
|
||||
<Select
|
||||
options={modelTtsOptions}
|
||||
defaultValue={modelTtsOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
)}
|
||||
{selectedFilter === "sd" && (
|
||||
<Select
|
||||
options={modelSdOptions}
|
||||
defaultValue={modelSdOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
)}
|
||||
{selectedFilter === "vc" && (
|
||||
<Select
|
||||
options={modelVcOptions}
|
||||
defaultValue={modelVcOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<Pagination
|
||||
itemsPerPage={itemsPerPage}
|
||||
totalItems={data.length}
|
||||
onPageChange={handlePageClick}
|
||||
currentPage={currentPage}
|
||||
/>
|
||||
</div>
|
||||
{isLoading ? (
|
||||
<div className="row gx-3 gy-3">
|
||||
{Array.from({ length: 6 }).map((_, index) => (
|
||||
<SkeletonCard key={index} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<MasonryGrid
|
||||
gridRef={gridContainerRef}
|
||||
onLayoutComplete={() => console.log("Layout complete!")}
|
||||
>
|
||||
{currentItems.map((data, index) => {
|
||||
let card;
|
||||
switch (data.media_type) {
|
||||
case "audio":
|
||||
card = <AudioCard key={index} data={data} type="weights" />;
|
||||
break;
|
||||
case "image":
|
||||
card = <ImageCard key={index} data={data} type="weights" />;
|
||||
break;
|
||||
case "video":
|
||||
card = <VideoCard key={index} data={data} type="weights" />;
|
||||
break;
|
||||
default:
|
||||
card = <div key={index}>Unsupported media type</div>;
|
||||
}
|
||||
return (
|
||||
<div key={index} className="col-12 col-sm-6 col-xl-4 grid-item">
|
||||
{card}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</MasonryGrid>
|
||||
)}
|
||||
|
||||
<div className="d-flex justify-content-end mt-4">
|
||||
<Pagination
|
||||
itemsPerPage={itemsPerPage}
|
||||
totalItems={data.length}
|
||||
onPageChange={handlePageClick}
|
||||
currentPage={currentPage}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -4,19 +4,30 @@ import mockMediaData from "./mockMediaData";
|
||||
import AudioCard from "components/common/Card/AudioCard";
|
||||
import ImageCard from "components/common/Card/ImageCard";
|
||||
import VideoCard from "components/common/Card/VideoCard";
|
||||
import { Select } from "components/common/Inputs/Inputs";
|
||||
import Select from "components/common/Select";
|
||||
import {
|
||||
faArrowDownWideShort,
|
||||
faFilter,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import AudioPlayerProvider from "components/common/AudioPlayer/AudioPlayerContext";
|
||||
import SkeletonCard from "components/common/Card/SkeletonCard";
|
||||
import Pagination from "components/common/Pagination";
|
||||
|
||||
export default function MediaTab() {
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [data] = useState(mockMediaData);
|
||||
const [isLoading] = useState(false);
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const itemsPerPage = 10;
|
||||
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const handlePageClick = (selectedItem: { selected: number }) => {
|
||||
setCurrentPage(selectedItem.selected);
|
||||
};
|
||||
|
||||
const currentItems = data.slice(
|
||||
currentPage * itemsPerPage,
|
||||
(currentPage + 1) * itemsPerPage
|
||||
);
|
||||
|
||||
const filterOptions = [
|
||||
{ value: "all", label: "All Media" },
|
||||
@@ -33,18 +44,26 @@ export default function MediaTab() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="d-flex gap-2 mb-3">
|
||||
<Select
|
||||
icon={faArrowDownWideShort}
|
||||
options={sortOptions}
|
||||
defaultValue={sortOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
<Select
|
||||
icon={faFilter}
|
||||
options={filterOptions}
|
||||
defaultValue={filterOptions[0]}
|
||||
isSearchable={false}
|
||||
<div className="d-flex flex-wrap gap-3 mb-3">
|
||||
<div className="d-flex gap-2 flex-grow-1">
|
||||
<Select
|
||||
icon={faArrowDownWideShort}
|
||||
options={sortOptions}
|
||||
defaultValue={sortOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
<Select
|
||||
icon={faFilter}
|
||||
options={filterOptions}
|
||||
defaultValue={filterOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
</div>
|
||||
<Pagination
|
||||
itemsPerPage={itemsPerPage}
|
||||
totalItems={data.length}
|
||||
onPageChange={handlePageClick}
|
||||
currentPage={currentPage}
|
||||
/>
|
||||
</div>
|
||||
<AudioPlayerProvider>
|
||||
@@ -59,7 +78,7 @@ export default function MediaTab() {
|
||||
gridRef={gridContainerRef}
|
||||
onLayoutComplete={() => console.log("Layout complete!")}
|
||||
>
|
||||
{data.map((data, index) => {
|
||||
{currentItems.map((data, index) => {
|
||||
let card;
|
||||
switch (data.media_type) {
|
||||
case "audio":
|
||||
@@ -83,6 +102,15 @@ export default function MediaTab() {
|
||||
</MasonryGrid>
|
||||
)}
|
||||
</AudioPlayerProvider>
|
||||
|
||||
<div className="d-flex justify-content-end mt-4">
|
||||
<Pagination
|
||||
itemsPerPage={itemsPerPage}
|
||||
totalItems={data.length}
|
||||
onPageChange={handlePageClick}
|
||||
currentPage={currentPage}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -4,46 +4,113 @@ import mockWeightsData from "./mockWeightsData";
|
||||
import AudioCard from "components/common/Card/AudioCard";
|
||||
import ImageCard from "components/common/Card/ImageCard";
|
||||
import VideoCard from "components/common/Card/VideoCard";
|
||||
import { Select } from "components/common/Inputs/Inputs";
|
||||
import Select from "components/common/Select";
|
||||
import {
|
||||
faArrowDownWideShort,
|
||||
faFilter,
|
||||
} from "@fortawesome/pro-solid-svg-icons";
|
||||
import SkeletonCard from "components/common/Card/SkeletonCard";
|
||||
import Pagination from "components/common/Pagination";
|
||||
|
||||
export default function WeightsTab() {
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [data] = useState(mockWeightsData);
|
||||
const [isLoading] = useState(false);
|
||||
const [selectedFilter, setSelectedFilter] = useState("all");
|
||||
const [currentPage, setCurrentPage] = useState(0);
|
||||
const itemsPerPage = 10;
|
||||
|
||||
const gridContainerRef = useRef<HTMLDivElement | null>(null);
|
||||
const handlePageClick = (selectedItem: { selected: number }) => {
|
||||
setCurrentPage(selectedItem.selected);
|
||||
};
|
||||
|
||||
const currentItems = data.slice(
|
||||
currentPage * itemsPerPage,
|
||||
(currentPage + 1) * itemsPerPage
|
||||
);
|
||||
|
||||
const filterOptions = [
|
||||
{ value: "all", label: "All Weights" },
|
||||
{ value: "tts", label: "Text to Speech" },
|
||||
{ value: "vc", label: "Voice to Voice" },
|
||||
{ value: "vd", label: "Voice Designer" },
|
||||
{ value: "sd", label: "Image Generation" },
|
||||
];
|
||||
|
||||
const sortOptions = [
|
||||
{ value: "newest", label: "Newest" },
|
||||
{ value: "oldest", label: "Oldest" },
|
||||
{ value: "mostliked", label: "Most Favorited" },
|
||||
{ value: "mostliked", label: "Most Bookmarked" },
|
||||
];
|
||||
|
||||
const modelTtsOptions = [
|
||||
{ value: "all", label: "All Types" },
|
||||
{ value: "tt2", label: "Tacotron 2" },
|
||||
];
|
||||
|
||||
const modelVcOptions = [
|
||||
{ value: "all", label: "All Types" },
|
||||
{ value: "rvc", label: "RVCv2" },
|
||||
{ value: "svc", label: "SoVitsSvc" },
|
||||
];
|
||||
|
||||
const modelSdOptions = [
|
||||
{ value: "all", label: "All Types" },
|
||||
{ value: "lora", label: "LoRA" },
|
||||
{ value: "SD15", label: "SD 1.5" },
|
||||
{ value: "SDXL", label: "SD XL" },
|
||||
];
|
||||
|
||||
const handleFilterChange = (option: any) => {
|
||||
const selectedOption = option as { value: string; label: string };
|
||||
setSelectedFilter(selectedOption.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="d-flex gap-2 mb-3">
|
||||
<Select
|
||||
icon={faArrowDownWideShort}
|
||||
options={sortOptions}
|
||||
defaultValue={sortOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
<Select
|
||||
icon={faFilter}
|
||||
options={filterOptions}
|
||||
defaultValue={filterOptions[0]}
|
||||
isSearchable={false}
|
||||
<div className="d-flex flex-wrap gap-3 mb-3">
|
||||
<div className="d-flex gap-2 flex-grow-1">
|
||||
<Select
|
||||
icon={faArrowDownWideShort}
|
||||
options={sortOptions}
|
||||
defaultValue={sortOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
|
||||
<Select
|
||||
icon={faFilter}
|
||||
options={filterOptions}
|
||||
defaultValue={filterOptions[0]}
|
||||
isSearchable={false}
|
||||
onChange={handleFilterChange}
|
||||
/>
|
||||
|
||||
{selectedFilter === "tts" && (
|
||||
<Select
|
||||
options={modelTtsOptions}
|
||||
defaultValue={modelTtsOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
)}
|
||||
{selectedFilter === "sd" && (
|
||||
<Select
|
||||
options={modelSdOptions}
|
||||
defaultValue={modelSdOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
)}
|
||||
{selectedFilter === "vc" && (
|
||||
<Select
|
||||
options={modelVcOptions}
|
||||
defaultValue={modelVcOptions[0]}
|
||||
isSearchable={false}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<Pagination
|
||||
itemsPerPage={itemsPerPage}
|
||||
totalItems={data.length}
|
||||
onPageChange={handlePageClick}
|
||||
currentPage={currentPage}
|
||||
/>
|
||||
</div>
|
||||
{isLoading ? (
|
||||
@@ -57,7 +124,7 @@ export default function WeightsTab() {
|
||||
gridRef={gridContainerRef}
|
||||
onLayoutComplete={() => console.log("Layout complete!")}
|
||||
>
|
||||
{data.map((data, index) => {
|
||||
{currentItems.map((data, index) => {
|
||||
let card;
|
||||
switch (data.media_type) {
|
||||
case "audio":
|
||||
@@ -80,6 +147,15 @@ export default function WeightsTab() {
|
||||
})}
|
||||
</MasonryGrid>
|
||||
)}
|
||||
|
||||
<div className="d-flex justify-content-end mt-4">
|
||||
<Pagination
|
||||
itemsPerPage={itemsPerPage}
|
||||
totalItems={data.length}
|
||||
onPageChange={handlePageClick}
|
||||
currentPage={currentPage}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -379,6 +379,24 @@ let mockMediaData = [
|
||||
isLiked: true,
|
||||
created_at: "2023-08-10T09:00:00.000Z",
|
||||
},
|
||||
{
|
||||
token: "token21",
|
||||
weight_name: "Watery Landscape",
|
||||
media_type: "image",
|
||||
public_bucket_path: "/images/dummy-image-4.jpg",
|
||||
likes: 150,
|
||||
isLiked: true,
|
||||
created_at: "2023-08-10T09:00:00.000Z",
|
||||
},
|
||||
{
|
||||
token: "token22",
|
||||
weight_name: "Watery Landscape",
|
||||
media_type: "image",
|
||||
public_bucket_path: "/images/dummy-image-4.jpg",
|
||||
likes: 150,
|
||||
isLiked: true,
|
||||
created_at: "2023-08-10T09:00:00.000Z",
|
||||
},
|
||||
];
|
||||
|
||||
export default mockMediaData;
|
||||
@@ -4582,6 +4582,7 @@ __metadata:
|
||||
resolution: "@storyteller/root@workspace:."
|
||||
dependencies:
|
||||
"@react-spring/types": ^9.7.3
|
||||
"@types/react-paginate": ^7.1.4
|
||||
craco: ^0.0.3
|
||||
cross-env: ^7.0.3
|
||||
husky: ^8.0.3
|
||||
@@ -4589,6 +4590,7 @@ __metadata:
|
||||
moment: ^2.29.4
|
||||
prettier: ^3.1.0
|
||||
pretty-quick: ^3.1.3
|
||||
react-paginate: ^8.2.0
|
||||
universal-cookie: ^6.1.1
|
||||
yarn: ^1.22.19
|
||||
languageName: unknown
|
||||
@@ -5508,6 +5510,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-paginate@npm:^7.1.4":
|
||||
version: 7.1.4
|
||||
resolution: "@types/react-paginate@npm:7.1.4"
|
||||
dependencies:
|
||||
"@types/react": "*"
|
||||
checksum: 3dbada2ab364307382adce1283220c83b743bfb056508dac6c513cfc1ce6b703e98129717abb052739106ae02eaab847b8b7037e7ca6b666eba86c9879e70d74
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react-router-dom@npm:^5.1.7":
|
||||
version: 5.3.3
|
||||
resolution: "@types/react-router-dom@npm:5.3.3"
|
||||
@@ -17411,7 +17422,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prop-types@npm:^15.5.10, prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
|
||||
"prop-types@npm:^15, prop-types@npm:^15.5.10, prop-types@npm:^15.6.0, prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
|
||||
version: 15.8.1
|
||||
resolution: "prop-types@npm:15.8.1"
|
||||
dependencies:
|
||||
@@ -17846,6 +17857,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-paginate@npm:^8.2.0":
|
||||
version: 8.2.0
|
||||
resolution: "react-paginate@npm:8.2.0"
|
||||
dependencies:
|
||||
prop-types: ^15
|
||||
peerDependencies:
|
||||
react: ^16 || ^17 || ^18
|
||||
checksum: a0969b4ef27be466ef3e052e2c7c61fca60af24e0d10c76770ebd9953ad6131206a276dfc335e61cf35aa494ff3aacc2610682e3192d7f2ee9541928edb46721
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-parallax-tilt@npm:^1.7.110":
|
||||
version: 1.7.110
|
||||
resolution: "react-parallax-tilt@npm:1.7.110"
|
||||
|
||||
Reference in new issue
Block a user