图片预览组件添加切换按钮,修改其他有关样式
This commit is contained in:
parent
e7886b717a
commit
bfcdbb60f4
|
@ -37,6 +37,9 @@ footer{
|
|||
/* .adm-image-viewer-slides-inner > *{
|
||||
margin: 0;
|
||||
} */
|
||||
.adm-swiper-horizontal .adm-swiper-track {
|
||||
transform: none;
|
||||
}
|
||||
.custom-tabs .adm-tabs {
|
||||
border: none;
|
||||
--active-line-color: #ff8383;
|
||||
|
@ -302,3 +305,4 @@ footer{
|
|||
border-color: #FF669E;
|
||||
background-color: #FF669E;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,4 +35,29 @@
|
|||
}
|
||||
|
||||
|
||||
|
||||
.imagesBtnsControllers{
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding: 0 12px;
|
||||
justify-content: space-between;
|
||||
z-index: 10001;
|
||||
pointer-events: none;
|
||||
}
|
||||
.imagesBtnsControllerLeft,.imagesBtnsControllerRight{
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 53px;
|
||||
background-color: #0000001A;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
pointer-events: all;
|
||||
}
|
||||
.imagesBtnsControllerLeft{
|
||||
background-image: url("/icons/left.png");
|
||||
opacity: 0.5;
|
||||
}
|
||||
.imagesBtnsControllerRight{
|
||||
background-image: url("/icons/right.png");
|
||||
}
|
|
@ -193,6 +193,7 @@ export default function RootLayout({ children }) {
|
|||
<main className={`w-full bg-deepBg h-full`}>
|
||||
{withAuth(<Provider store={store}>{children}</Provider>)}
|
||||
{/* <Provider store={store}>{children}</Provider> */}
|
||||
<div id="maskDomBox"></div>
|
||||
</main>
|
||||
<footer className="fixed left-0 w-screen bg-black">
|
||||
<div>
|
||||
|
|
|
@ -60,10 +60,7 @@ function Login({ handleLogin }) {
|
|||
if(res && account){
|
||||
router.replace("/")
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
let interval;
|
||||
|
@ -158,11 +155,11 @@ function Login({ handleLogin }) {
|
|||
}
|
||||
);
|
||||
if (data.ret === -1) {
|
||||
Toast.show({
|
||||
icon: "fail",
|
||||
content: data.msg,
|
||||
position: "top",
|
||||
});
|
||||
// Toast.show({
|
||||
// icon: "fail",
|
||||
// content: data.msg,
|
||||
// position: "top",
|
||||
// });
|
||||
return;
|
||||
}
|
||||
//登录
|
||||
|
|
|
@ -116,7 +116,7 @@ export default function UnlockedWechat() {
|
|||
streamerData={{
|
||||
streamer_ext: {
|
||||
wechat_lock_type:
|
||||
currentStreamer.current?.streamer?.wechat_lock_type,
|
||||
currentStreamer.current?.lock_type,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -76,6 +76,7 @@ export default function Home() {
|
|||
</div>
|
||||
<Swiper
|
||||
direction="horizontal"
|
||||
allowTouchMove={false}
|
||||
loop={false}
|
||||
indicator={() => null}
|
||||
ref={swiperRef}
|
||||
|
@ -83,6 +84,7 @@ export default function Home() {
|
|||
onIndexChange={(index) => {
|
||||
setActiveIndex(index);
|
||||
}}
|
||||
|
||||
>
|
||||
<Swiper.Item>
|
||||
{!activeIndex && (
|
||||
|
@ -97,7 +99,7 @@ export default function Home() {
|
|||
</Swiper>
|
||||
<div
|
||||
id="rightddd"
|
||||
className={`fixed bottom-[96px] right-4 z-[999] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white
|
||||
className={`fixed bottom-[96px] right-4 z-[50] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white
|
||||
}`}
|
||||
onClick={childrenFunc}
|
||||
>
|
||||
|
|
|
@ -179,6 +179,8 @@ const ZoneItem = ({ data, showMore, link,search }) => {
|
|||
<Image
|
||||
className="flex-none w-10 h-10 rounded-full mr-2"
|
||||
src={data?.avatar?.images[0]?.urls[0]}
|
||||
width="2.5rem"
|
||||
height="2.5rem"
|
||||
alt=""
|
||||
fit="cover"
|
||||
/>
|
||||
|
|
|
@ -434,7 +434,7 @@ export default function PersonSpace() {
|
|||
</JumboTabs>
|
||||
</FloatingPanel>
|
||||
<div
|
||||
className={`fixed bottom-[96px] right-4 z-[999] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
|
||||
className={`fixed bottom-[96px] right-4 z-[50] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
|
||||
loading && !offset ? "animate-spin" : ""
|
||||
}`}
|
||||
>
|
||||
|
|
|
@ -129,10 +129,7 @@ export default function Space() {
|
|||
}
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className=""
|
||||
|
||||
>
|
||||
<div className="">
|
||||
<div className="flex justify-between items-center px-2 custom-tabs text-gray-400 sticky top-0 z-10 bg-deepBg">
|
||||
<Tabs
|
||||
activeKey={tabItems[activeIndex].key}
|
||||
|
@ -299,7 +296,7 @@ export default function Space() {
|
|||
</Swiper.Item>
|
||||
</Swiper>
|
||||
<div
|
||||
className={`fixed bottom-[96px] right-4 z-[999] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
|
||||
className={`fixed bottom-[96px] right-4 z-[50] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
|
||||
loading && !offset ? "animate-spin" : ""
|
||||
}`}
|
||||
>
|
||||
|
|
|
@ -1,21 +1,65 @@
|
|||
"use client";
|
||||
|
||||
import React,{useState,useEffect} from "react";
|
||||
import { Image ,Toast} from "antd-mobile";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Image } from "antd-mobile";
|
||||
import { get,save } from "@/utils/storeInfo";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faAngleUp, faClose } from "@fortawesome/free-solid-svg-icons";
|
||||
export default function AddToHome() {
|
||||
const [firstLogin, setFirstLogin] = useState("0");
|
||||
const [firstLogin, setFirstLogin] = useState({ first: "0", second: false });
|
||||
useEffect(() => {
|
||||
if(!(("standalone" in window.navigator) && window.navigator.standalone)
|
||||
){
|
||||
setFirstLogin(get("firstLogin"))
|
||||
if (!("standalone" in window.navigator && window.navigator.standalone)) {
|
||||
setFirstLogin((old) => ({ ...old, first: get("firstLogin") }));
|
||||
}
|
||||
|
||||
}, []);
|
||||
return (
|
||||
firstLogin=="1"?<div
|
||||
className="fixed top-0 z-[999] flex flex-col justify-end items-center h-screen w-screen bg-[#262626b0]"
|
||||
onClick={() => {save("firstLogin", 0);setFirstLogin("0")}}
|
||||
return firstLogin.first == "1" ? (
|
||||
<div
|
||||
className="fixed z-[50]"
|
||||
style={{ bottom: !firstLogin.second ? "57px" : "0" }}
|
||||
>
|
||||
{!firstLogin.second ? (
|
||||
<div className="bg-[#13121f] p-3 w-screen flex items-center justify-between relative">
|
||||
<div className="flex items-center">
|
||||
<Image
|
||||
fit="cover"
|
||||
className="rounded-md mr-3"
|
||||
// src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
|
||||
src={"/images/icon.png"}
|
||||
placeholder=""
|
||||
width={46}
|
||||
height={46}
|
||||
/>
|
||||
<div>
|
||||
<p className="font-bold text-[0.9rem]">
|
||||
建议您添加<span className="text-primary">铁粉空间</span>
|
||||
到手机桌面
|
||||
</p>
|
||||
<p className="text-[#ffffffb2] text-xs">以便随时关注圈子动态</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="bg-primary px-4 py-2 rounded-full font-bold"
|
||||
onClick={() => setFirstLogin((old) => ({ ...old, second: true }))}
|
||||
>
|
||||
去添加
|
||||
</div>
|
||||
<FontAwesomeIcon
|
||||
icon={faClose}
|
||||
size=""
|
||||
className="absolute left-1 top-1"
|
||||
onClick={() => {
|
||||
save("firstLogin", 0);
|
||||
setFirstLogin((old) => ({ first: "0", second: false }));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className="flex flex-col justify-end items-center h-screen w-screen bg-[#00000099]"
|
||||
onClick={() => {
|
||||
save("firstLogin", 0);
|
||||
setFirstLogin((old) => ({ first: "0", second: false }));
|
||||
}}
|
||||
>
|
||||
<div className="font-bold text-xl mb-2 flex items-center">
|
||||
点击
|
||||
|
@ -30,13 +74,15 @@ export default function AddToHome() {
|
|||
添加到主屏幕
|
||||
</div>
|
||||
<Image
|
||||
fit="cover"
|
||||
fit="contain"
|
||||
// src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
|
||||
src={"/images/addToHome.png"}
|
||||
placeholder=""
|
||||
width={54}
|
||||
height={54}
|
||||
height={70}
|
||||
/>
|
||||
</div>:null
|
||||
);
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
"use client";
|
||||
|
||||
import React, {
|
||||
useState,
|
||||
useEffect,
|
||||
useRef,
|
||||
forwardRef,
|
||||
useImperativeHandle,
|
||||
} from "react";
|
||||
import { Mask, Image } from "antd-mobile";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faAngleLeft, faAngleRight } from "@fortawesome/free-solid-svg-icons";
|
||||
function ImagesMask({}, ref) {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [images, setImages] = useState([]);
|
||||
const [distance, setDistance] = useState(0);
|
||||
const scrollRef = useRef(null);
|
||||
useEffect(() => {
|
||||
if (scrollRef.current) {
|
||||
setTimeout(() => {
|
||||
scrollRef.current.scrollLeft = 414 * currentIndex;
|
||||
}, 200);
|
||||
}
|
||||
}, [currentIndex]);
|
||||
useImperativeHandle(ref, () => ({
|
||||
show: (arr, index) => {
|
||||
setCurrentIndex(index);
|
||||
setImages(arr);
|
||||
setVisible(true);
|
||||
// Mask.show
|
||||
// const maskDomBox = document.getElementById("maskDomBox");
|
||||
},
|
||||
close: () => setVisible(false),
|
||||
}));
|
||||
const getDistance = (e) => {
|
||||
e.stopPropagation();
|
||||
const distance = scrollRef.current.scrollLeft;
|
||||
setDistance(distance);
|
||||
};
|
||||
const handleMoveImages = (e,index) => {
|
||||
e.stopPropagation();
|
||||
// console.log("distance",distance)
|
||||
if (
|
||||
distance > window.innerWidth * currentIndex &&
|
||||
distance < window.innerWidth + window.innerWidth * currentIndex
|
||||
) {
|
||||
setCurrentIndex(Math.ceil(distance/414))
|
||||
} else if(distance < window.innerWidth * currentIndex) {
|
||||
setCurrentIndex(Math.ceil(distance/414)-1)
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Mask
|
||||
visible={visible}
|
||||
className="z-[99] h-screen flex justify-center items-center"
|
||||
>
|
||||
<div className="relative">
|
||||
<div className="text-center mb-2">
|
||||
{currentIndex + 1}/{images.length}
|
||||
</div>
|
||||
<div
|
||||
ref={scrollRef}
|
||||
id="imagesScrollBox"
|
||||
className="flex overflow-auto"
|
||||
>
|
||||
{images.map((item, index) => {
|
||||
return (
|
||||
// <Image
|
||||
// key={index}
|
||||
// fit="cover"
|
||||
// className="mr-3"
|
||||
// // src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/nodata.png"}
|
||||
// src={item}
|
||||
// placeholder=""
|
||||
// width="100vw"
|
||||
// // height="90vh"
|
||||
// />
|
||||
<img
|
||||
key={index}
|
||||
src={item}
|
||||
// onTouchMove={(e) => handleMoveImages(e, index)}
|
||||
onTouchMove={getDistance}
|
||||
onTouchEnd={(e) => handleMoveImages(e,index)}
|
||||
onClick={() => {
|
||||
setVisible(false), setImages([]), setCurrentIndex(0);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="flex justify-between items-center w-screen absolute top-1/2 px-4 pointer-events-none">
|
||||
<div
|
||||
className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full float-left pointer-events-auto"
|
||||
onClick={() => {
|
||||
setCurrentIndex((old) => (old > 0 ? old - 1 : old));
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faAngleLeft} size="xl" />
|
||||
</div>
|
||||
<div
|
||||
className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full float-left pointer-events-auto"
|
||||
onClick={() => {
|
||||
setCurrentIndex((old) =>
|
||||
old < images.length - 1 ? old + 1 : old
|
||||
);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={faAngleRight} size="xl" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Mask>
|
||||
);
|
||||
}
|
||||
|
||||
export default forwardRef(ImagesMask);
|
|
@ -1,12 +1,14 @@
|
|||
"use client";
|
||||
|
||||
import React, { useEffect, useState,useRef } from "react";
|
||||
import React, { useEffect, useState, useRef } from "react";
|
||||
import { Image, ImageViewer, Dialog } from "antd-mobile";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faAngleUp, faClose } from "@fortawesome/free-solid-svg-icons";
|
||||
import { useRouter } from "next/navigation";
|
||||
import baseRequest from "@/utils/baseRequest";
|
||||
import Player from "next-video/player";
|
||||
// import ImagesMask from "@/components/ImagesMask";
|
||||
// import Viewer from 'react-viewer';
|
||||
export default function Photos({
|
||||
isUnlocked,
|
||||
mediaVisibleRange,
|
||||
|
@ -18,7 +20,10 @@ export default function Photos({
|
|||
const [seeAllPhotos, setSeeAllPhotos] = useState(false);
|
||||
const [currentPhotos, setCurrentPhotos] = useState([]);
|
||||
const [photos, setPhotos] = useState([]);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const currentIndex = useRef();
|
||||
const swiper = useRef(null);
|
||||
// const imagesMaskRef = useRef(null);
|
||||
const router = useRouter();
|
||||
const base = baseRequest();
|
||||
useEffect(() => {
|
||||
|
@ -57,22 +62,65 @@ export default function Photos({
|
|||
}
|
||||
}, [media]);
|
||||
const showPhotos = (photos, index) => {
|
||||
currentIndex.current=index;
|
||||
currentIndex.current = index;
|
||||
// const interval = setInterval(() => {
|
||||
// const bodyBox = document.getElementsByClassName("photos-bodyBox")[0];
|
||||
// if (bodyBox) {
|
||||
// bodyBox.firstChild.lastChild.style.transform = `translateX(-${
|
||||
// currentIndex.current * (window.innerWidth + 16)
|
||||
// }px)`;
|
||||
// // console.log(bodyBox.firstChild.lastChild.style.transform);
|
||||
// }
|
||||
// }, 400);
|
||||
|
||||
// 添加左右切换按钮
|
||||
const btns = document.createElement("div");
|
||||
btns.className = "imagesBtnsControllers";
|
||||
const btnL = document.createElement("div");
|
||||
btnL.className = "imagesBtnsControllerLeft";
|
||||
btnL.addEventListener("click", () => {
|
||||
if (currentIndex.current > 0) {
|
||||
currentIndex.current = currentIndex.current - 1;
|
||||
handleShowImages(currentIndex.current, photos, btns);
|
||||
if (!currentIndex.current) {
|
||||
btnL.style.opacity = 0.5;
|
||||
btnR.style.opacity = 1;
|
||||
} else {
|
||||
btnR.style.opacity = 1;
|
||||
btnL.style.opacity = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
const btnR = document.createElement("div");
|
||||
btnR.className = "imagesBtnsControllerRight";
|
||||
btnR.addEventListener("click", () => {
|
||||
if (currentIndex.current < currentPhotos.length - 1) {
|
||||
currentIndex.current = currentIndex.current + 1;
|
||||
handleShowImages(currentIndex.current, photos, btns);
|
||||
if (currentIndex.current == currentPhotos.length - 1) {
|
||||
btnR.style.opacity = 0.5;
|
||||
btnL.style.opacity = 1;
|
||||
} else {
|
||||
btnR.style.opacity = 1;
|
||||
btnL.style.opacity = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
btns.append(btnL, btnR);
|
||||
handleShowImages(index, photos, btns);
|
||||
|
||||
// setVisible(true)
|
||||
// imagesMaskRef.current.show(photos.map((item) => item?.url),index)
|
||||
};
|
||||
const handleShowImages = (index, photos, btns) => {
|
||||
const mediaDom = document.createElement("div");
|
||||
mediaDom.style.width = "100vw";
|
||||
document.body.appendChild(mediaDom);
|
||||
mediaDom.className = `${
|
||||
photos[index]?.type == "hid" ? "mediaDom photos-body" : "mediaDom"
|
||||
}`;
|
||||
const interval = setInterval(() => {
|
||||
const bodyBox = document.getElementsByClassName("photos-bodyBox")[0];
|
||||
if(bodyBox){
|
||||
bodyBox.firstChild.lastChild.style.transform = `translateX(-${
|
||||
(currentIndex.current) * (window.innerWidth + 16)
|
||||
}px)`;
|
||||
// console.log(bodyBox.firstChild.lastChild.style.transform);
|
||||
}
|
||||
}, 400);
|
||||
mediaDom.appendChild(btns);
|
||||
ImageViewer.clear();
|
||||
ImageViewer.Multi.show({
|
||||
images: photos.map((item) => item?.url),
|
||||
defaultIndex: index,
|
||||
|
@ -82,18 +130,31 @@ export default function Photos({
|
|||
|
||||
getContainer: mediaDom,
|
||||
onIndexChange: (index) => {
|
||||
currentIndex.current=index;
|
||||
currentIndex.current = index;
|
||||
mediaDom.className = `${
|
||||
photos[index]?.type == "hid" ? "mediaDom photos-body" : "mediaDom"
|
||||
}`;
|
||||
const leftBtn = document.getElementsByClassName("imagesBtnsControllerLeft")[0]
|
||||
const rightBtn = document.getElementsByClassName("imagesBtnsControllerRight")[0]
|
||||
if(leftBtn && rightBtn){
|
||||
if(!index){
|
||||
leftBtn.style.opacity=0.5
|
||||
rightBtn.style.opacity=1
|
||||
}else if(index==currentPhotos.length-1){
|
||||
leftBtn.style.opacity=1
|
||||
rightBtn.style.opacity=0.5
|
||||
}else{
|
||||
leftBtn.style.opacity=1
|
||||
rightBtn.style.opacity=1
|
||||
}
|
||||
}
|
||||
},
|
||||
afterClose: () => {
|
||||
mediaDom.remove();
|
||||
clearInterval(interval);
|
||||
// clearInterval(interval);
|
||||
},
|
||||
classNames: { body: "photos-bodyBox" },
|
||||
});
|
||||
|
||||
};
|
||||
const handleShowVideo = (video) => {
|
||||
Dialog.className = "videoMask";
|
||||
|
@ -293,6 +354,12 @@ export default function Photos({
|
|||
);
|
||||
})}
|
||||
</div>
|
||||
{/* <ImagesMask ref={imagesMaskRef}/> */}
|
||||
{/* <Viewer
|
||||
visible={visible}
|
||||
onClose={() => { setVisible(false); } }
|
||||
images={currentPhotos.map((it,index)=>({src:it.url,alt:index}))}
|
||||
/> */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ export default function PostItem({
|
|||
"天前"
|
||||
}有更新`}
|
||||
空间 */}
|
||||
{formatZoneUpdateTime(
|
||||
空间{formatZoneUpdateTime(
|
||||
data?.streamer_ext
|
||||
?.days_elapsed_since_the_last_zones_update
|
||||
)}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
"react-dom": "^18",
|
||||
"react-player": "^2.16.0",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-viewer": "^3.2.2",
|
||||
"redux": "^5.0.1",
|
||||
"sass": "^1.77.6"
|
||||
},
|
||||
|
@ -5876,6 +5877,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-viewer": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/react-viewer/-/react-viewer-3.2.2.tgz",
|
||||
"integrity": "sha512-DHOq1x6cXsAViY43204ILRzLVR5ovP1MgzsC+LzZCWlInRuHjzAgpQZ8GzWm1CkiNYuHGwCxH36X0JUHl2xDSg==",
|
||||
"dependencies": {
|
||||
"classnames": "^2.2.5"
|
||||
}
|
||||
},
|
||||
"node_modules/read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz",
|
||||
|
@ -11195,6 +11204,14 @@
|
|||
"use-sync-external-store": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"react-viewer": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/react-viewer/-/react-viewer-3.2.2.tgz",
|
||||
"integrity": "sha512-DHOq1x6cXsAViY43204ILRzLVR5ovP1MgzsC+LzZCWlInRuHjzAgpQZ8GzWm1CkiNYuHGwCxH36X0JUHl2xDSg==",
|
||||
"requires": {
|
||||
"classnames": "^2.2.5"
|
||||
}
|
||||
},
|
||||
"read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz",
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
"react-dom": "^18",
|
||||
"react-player": "^2.16.0",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-viewer": "^3.2.2",
|
||||
"redux": "^5.0.1",
|
||||
"sass": "^1.77.6"
|
||||
},
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
Loading…
Reference in New Issue