Compare commits
	
		
			3 Commits
		
	
	
		
			078f051e8a
			...
			f2aab1ab33
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f2aab1ab33 | |||
| 1973ff4304 | |||
| 89488d9921 | 
							
								
								
									
										1303
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1303
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -12,6 +12,7 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@emotion/react": "^11.14.0", |     "@emotion/react": "^11.14.0", | ||||||
|     "@emotion/styled": "^11.14.0", |     "@emotion/styled": "^11.14.0", | ||||||
|  |     "@hello-pangea/dnd": "^18.0.1", | ||||||
|     "@mui/material": "^7.1.0", |     "@mui/material": "^7.1.0", | ||||||
|     "@photo-sphere-viewer/core": "^5.13.2", |     "@photo-sphere-viewer/core": "^5.13.2", | ||||||
|     "@react-three/drei": "^10.1.2", |     "@react-three/drei": "^10.1.2", | ||||||
|   | |||||||
| @@ -1,7 +1,5 @@ | |||||||
| import * as React from "react"; | import * as React from "react"; | ||||||
|  |  | ||||||
| import { BrowserRouter } from "react-router-dom"; |  | ||||||
|  |  | ||||||
| import { Router } from "./router"; | import { Router } from "./router"; | ||||||
| import { CustomTheme } from "@shared"; | import { CustomTheme } from "@shared"; | ||||||
| import { ThemeProvider } from "@mui/material/styles"; | import { ThemeProvider } from "@mui/material/styles"; | ||||||
| @@ -10,8 +8,7 @@ import { ToastContainer } from "react-toastify"; | |||||||
| export const App: React.FC = () => ( | export const App: React.FC = () => ( | ||||||
|   <ThemeProvider theme={CustomTheme.Light}> |   <ThemeProvider theme={CustomTheme.Light}> | ||||||
|     <ToastContainer /> |     <ToastContainer /> | ||||||
|     <BrowserRouter> |  | ||||||
|       <Router /> |     <Router /> | ||||||
|     </BrowserRouter> |  | ||||||
|   </ThemeProvider> |   </ThemeProvider> | ||||||
| ); | ); | ||||||
|   | |||||||
| @@ -9,37 +9,45 @@ import { | |||||||
|   MediaListPage, |   MediaListPage, | ||||||
|   PreviewMediaPage, |   PreviewMediaPage, | ||||||
|   EditMediaPage, |   EditMediaPage, | ||||||
|   // CreateMediaPage, |  | ||||||
| } from "@pages"; | } from "@pages"; | ||||||
| import { authStore, createSightStore, editSightStore } from "@shared"; | import { authStore, createSightStore, editSightStore } from "@shared"; | ||||||
| import { Layout } from "@widgets"; | import { Layout } from "@widgets"; | ||||||
| import { runInAction } from "mobx"; | import { runInAction } from "mobx"; | ||||||
| import { useEffect } from "react"; | import React, { useEffect } from "react"; | ||||||
|  |  | ||||||
| import { Navigate, Outlet, Route, Routes, useLocation } from "react-router-dom"; | import { | ||||||
|  |   createBrowserRouter, | ||||||
|  |   RouterProvider, | ||||||
|  |   Navigate, | ||||||
|  |   Outlet, | ||||||
|  |   useLocation, | ||||||
|  | } from "react-router-dom"; | ||||||
|  |  | ||||||
| const PublicRoute = ({ children }: { children: React.ReactNode }) => { | const PublicRoute = ({ children }: { children: React.ReactNode }) => { | ||||||
|   const { isAuthenticated } = authStore; |   const { isAuthenticated } = authStore; | ||||||
|   if (isAuthenticated) { |   if (isAuthenticated) { | ||||||
|     return <Navigate to="/sight" />; |     return <Navigate to="/sight" replace />; | ||||||
|   } |   } | ||||||
|   return children; |   return <>{children}</>; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const ProtectedRoute = ({ children }: { children: React.ReactNode }) => { | const ProtectedRoute = ({ children }: { children: React.ReactNode }) => { | ||||||
|   const { isAuthenticated } = authStore; |   const { isAuthenticated } = authStore; | ||||||
|   const pathname = useLocation(); |   const location = useLocation(); | ||||||
|   if (!isAuthenticated) { |   if (!isAuthenticated) { | ||||||
|     return <Navigate to="/login" />; |     return <Navigate to="/login" replace />; | ||||||
|   } |   } | ||||||
|   if (pathname.pathname === "/") { |   if (location.pathname === "/") { | ||||||
|     return <Navigate to="/sight" />; |     return <Navigate to="/sight" replace />; | ||||||
|   } |   } | ||||||
|   return children; |   return <>{children}</>; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const Router = () => { | // Чтобы очистка сторов происходила при смене локации | ||||||
|   const pathname = useLocation(); | const ClearStoresWrapper: React.FC<{ children: React.ReactNode }> = ({ | ||||||
|  |   children, | ||||||
|  | }) => { | ||||||
|  |   const location = useLocation(); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     editSightStore.clearSightInfo(); |     editSightStore.clearSightInfo(); | ||||||
| @@ -47,41 +55,46 @@ export const Router = () => { | |||||||
|     runInAction(() => { |     runInAction(() => { | ||||||
|       editSightStore.hasLoadedCommon = false; |       editSightStore.hasLoadedCommon = false; | ||||||
|     }); |     }); | ||||||
|   }, [pathname]); |   }, [location]); | ||||||
|  |  | ||||||
|   return ( |   return <>{children}</>; | ||||||
|     <Routes> | }; | ||||||
|       <Route |  | ||||||
|         path="/login" | const router = createBrowserRouter([ | ||||||
|         element={ |   { | ||||||
|           <PublicRoute> |     path: "/login", | ||||||
|             <LoginPage /> |     element: ( | ||||||
|           </PublicRoute> |       <PublicRoute> | ||||||
|         } |         <LoginPage /> | ||||||
|       /> |       </PublicRoute> | ||||||
|  |     ), | ||||||
|       {/* Protected routes with layout */} |   }, | ||||||
|       <Route |   { | ||||||
|         path="/" |     path: "/", | ||||||
|         element={ |     element: ( | ||||||
|           <ProtectedRoute> |       <ProtectedRoute> | ||||||
|             <Layout> |         <Layout> | ||||||
|               <Outlet /> |           <ClearStoresWrapper> | ||||||
|             </Layout> |             <Outlet /> | ||||||
|           </ProtectedRoute> |           </ClearStoresWrapper> | ||||||
|         } |         </Layout> | ||||||
|       > |       </ProtectedRoute> | ||||||
|         <Route index element={<MainPage />} /> |     ), | ||||||
|         <Route path="sight" element={<SightPage />} /> |     children: [ | ||||||
|         <Route path="sight/:id" element={<EditSightPage />} /> |       { index: true, element: <MainPage /> }, | ||||||
|         <Route path="sight/create" element={<CreateSightPage />} /> |       { path: "sight", element: <SightPage /> }, | ||||||
|         <Route path="devices" element={<DevicesPage />} /> |       { path: "sight/create", element: <CreateSightPage /> }, | ||||||
|         <Route path="map" element={<MapPage />} /> |       { path: "sight/:id", element: <EditSightPage /> }, | ||||||
|         <Route path="media" element={<MediaListPage />} /> |       { path: "devices", element: <DevicesPage /> }, | ||||||
|         <Route path="media/:id" element={<PreviewMediaPage />} /> |       { path: "map", element: <MapPage /> }, | ||||||
|         <Route path="media/:id/edit" element={<EditMediaPage />} /> |       { path: "media", element: <MediaListPage /> }, | ||||||
|         {/* <Route path="media/create" element={<CreateMediaPage />} /> */} |       { path: "media/:id", element: <PreviewMediaPage /> }, | ||||||
|       </Route> |       { path: "media/:id/edit", element: <EditMediaPage /> }, | ||||||
|     </Routes> |       // { path: "media/create", element: <CreateMediaPage /> }, | ||||||
|   ); |     ], | ||||||
|  |   }, | ||||||
|  | ]); | ||||||
|  |  | ||||||
|  | export const Router = () => { | ||||||
|  |   return <RouterProvider router={router} />; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -1,6 +1,11 @@ | |||||||
| import { Box, Tab, Tabs } from "@mui/material"; | import { Box, Tab, Tabs } from "@mui/material"; | ||||||
| import { articlesStore, cityStore, languageStore } from "@shared"; | import { articlesStore, cityStore, languageStore } from "@shared"; | ||||||
| import { CreateInformationTab, CreateLeftTab, CreateRightTab } from "@widgets"; | import { | ||||||
|  |   CreateInformationTab, | ||||||
|  |   CreateLeftTab, | ||||||
|  |   CreateRightTab, | ||||||
|  |   LeaveAgree, | ||||||
|  | } from "@widgets"; | ||||||
| import { useEffect, useState } from "react"; | import { useEffect, useState } from "react"; | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
|  |  | ||||||
| @@ -11,6 +16,8 @@ function a11yProps(index: number) { | |||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | import { useBlocker } from "react-router"; | ||||||
|  |  | ||||||
| export const CreateSightPage = observer(() => { | export const CreateSightPage = observer(() => { | ||||||
|   const [value, setValue] = useState(0); |   const [value, setValue] = useState(0); | ||||||
|   const { getCities } = cityStore; |   const { getCities } = cityStore; | ||||||
| @@ -19,6 +26,11 @@ export const CreateSightPage = observer(() => { | |||||||
|     setValue(newValue); |     setValue(newValue); | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   let blocker = useBlocker( | ||||||
|  |     ({ currentLocation, nextLocation }) => | ||||||
|  |       true && currentLocation.pathname !== nextLocation.pathname | ||||||
|  |   ); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     const fetchData = async () => { |     const fetchData = async () => { | ||||||
|       await getCities(); |       await getCities(); | ||||||
| @@ -34,6 +46,7 @@ export const CreateSightPage = observer(() => { | |||||||
|         display: "flex", |         display: "flex", | ||||||
|         flexDirection: "column", |         flexDirection: "column", | ||||||
|         minHeight: "100vh", |         minHeight: "100vh", | ||||||
|  |         z: 10, | ||||||
|       }} |       }} | ||||||
|     > |     > | ||||||
|       <Box |       <Box | ||||||
| @@ -66,6 +79,8 @@ export const CreateSightPage = observer(() => { | |||||||
|         <CreateLeftTab value={value} index={1} /> |         <CreateLeftTab value={value} index={1} /> | ||||||
|         <CreateRightTab value={value} index={2} /> |         <CreateRightTab value={value} index={2} /> | ||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
|  |       {blocker.state === "blocked" ? <LeaveAgree blocker={blocker} /> : null} | ||||||
|     </Box> |     </Box> | ||||||
|   ); |   ); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -34,6 +34,7 @@ export const EditMediaPage = observer(() => { | |||||||
|   const [mediaName, setMediaName] = useState(media?.media_name ?? ""); |   const [mediaName, setMediaName] = useState(media?.media_name ?? ""); | ||||||
|   const [mediaFilename, setMediaFilename] = useState(media?.filename ?? ""); |   const [mediaFilename, setMediaFilename] = useState(media?.filename ?? ""); | ||||||
|   const [mediaType, setMediaType] = useState(media?.media_type ?? 1); |   const [mediaType, setMediaType] = useState(media?.media_type ?? 1); | ||||||
|  |   const [availableMediaTypes, setAvailableMediaTypes] = useState<number[]>([]); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     if (id) { |     if (id) { | ||||||
| @@ -48,6 +49,18 @@ export const EditMediaPage = observer(() => { | |||||||
|       setMediaName(media.media_name); |       setMediaName(media.media_name); | ||||||
|       setMediaFilename(media.filename); |       setMediaFilename(media.filename); | ||||||
|       setMediaType(media.media_type); |       setMediaType(media.media_type); | ||||||
|  |  | ||||||
|  |       // Set available media types based on current file extension | ||||||
|  |       const extension = media.filename.split(".").pop()?.toLowerCase(); | ||||||
|  |       if (extension) { | ||||||
|  |         if (["glb", "gltf"].includes(extension)) { | ||||||
|  |           setAvailableMediaTypes([6]); // 3D model | ||||||
|  |         } else if (["jpg", "jpeg", "png", "gif"].includes(extension)) { | ||||||
|  |           setAvailableMediaTypes([1, 3, 4, 5]); // Photo, Icon, Watermark, Panorama | ||||||
|  |         } else if (["mp4", "webm", "mov"].includes(extension)) { | ||||||
|  |           setAvailableMediaTypes([2]); // Video | ||||||
|  |         } | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|   }, [media]); |   }, [media]); | ||||||
|  |  | ||||||
| @@ -76,8 +89,25 @@ export const EditMediaPage = observer(() => { | |||||||
|   const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => { |   const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => { | ||||||
|     const files = e.target.files; |     const files = e.target.files; | ||||||
|     if (files && files.length > 0) { |     if (files && files.length > 0) { | ||||||
|       setNewFile(files[0]); |       const file = files[0]; | ||||||
|       setMediaFilename(files[0].name); |       setNewFile(file); | ||||||
|  |       setMediaFilename(file.name); | ||||||
|  |  | ||||||
|  |       // Determine media type based on file extension | ||||||
|  |       const extension = file.name.split(".").pop()?.toLowerCase(); | ||||||
|  |       if (extension) { | ||||||
|  |         if (["glb", "gltf"].includes(extension)) { | ||||||
|  |           setAvailableMediaTypes([6]); // 3D model | ||||||
|  |           setMediaType(6); | ||||||
|  |         } else if (["jpg", "jpeg", "png", "gif"].includes(extension)) { | ||||||
|  |           setAvailableMediaTypes([1, 3, 4, 5]); // Photo, Icon, Watermark, Panorama | ||||||
|  |           setMediaType(1); // Default to Photo | ||||||
|  |         } else if (["mp4", "webm", "mov"].includes(extension)) { | ||||||
|  |           setAvailableMediaTypes([2]); // Video | ||||||
|  |           setMediaType(2); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|       setUploadDialogOpen(true); // Open dialog on file selection |       setUploadDialogOpen(true); // Open dialog on file selection | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
| @@ -175,11 +205,21 @@ export const EditMediaPage = observer(() => { | |||||||
|               onChange={(e) => setMediaType(Number(e.target.value))} |               onChange={(e) => setMediaType(Number(e.target.value))} | ||||||
|               disabled={isLoading} |               disabled={isLoading} | ||||||
|             > |             > | ||||||
|               {Object.entries(MEDIA_TYPE_LABELS).map(([type, label]) => ( |               {availableMediaTypes.length > 0 | ||||||
|                 <MenuItem key={type} value={Number(type)}> |                 ? availableMediaTypes.map((type) => ( | ||||||
|                   {label} |                     <MenuItem key={type} value={type}> | ||||||
|                 </MenuItem> |                       { | ||||||
|               ))} |                         MEDIA_TYPE_LABELS[ | ||||||
|  |                           type as keyof typeof MEDIA_TYPE_LABELS | ||||||
|  |                         ] | ||||||
|  |                       } | ||||||
|  |                     </MenuItem> | ||||||
|  |                   )) | ||||||
|  |                 : Object.entries(MEDIA_TYPE_LABELS).map(([type, label]) => ( | ||||||
|  |                     <MenuItem key={type} value={Number(type)}> | ||||||
|  |                       {label} | ||||||
|  |                     </MenuItem> | ||||||
|  |                   ))} | ||||||
|             </Select> |             </Select> | ||||||
|           </FormControl> |           </FormControl> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import { Box, Tab, Tabs } from "@mui/material"; | import { Box, Tab, Tabs } from "@mui/material"; | ||||||
| import { InformationTab, RightWidgetTab } from "@widgets"; | import { InformationTab, LeaveAgree, RightWidgetTab } from "@widgets"; | ||||||
| import { LeftWidgetTab } from "@widgets"; | import { LeftWidgetTab } from "@widgets"; | ||||||
| import { useEffect, useState } from "react"; | import { useEffect, useState } from "react"; | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| @@ -9,7 +9,7 @@ import { | |||||||
|   editSightStore, |   editSightStore, | ||||||
|   languageStore, |   languageStore, | ||||||
| } from "@shared"; | } from "@shared"; | ||||||
| import { useParams } from "react-router-dom"; | import { useBlocker, useParams } from "react-router-dom"; | ||||||
|  |  | ||||||
| function a11yProps(index: number) { | function a11yProps(index: number) { | ||||||
|   return { |   return { | ||||||
| @@ -26,6 +26,11 @@ export const EditSightPage = observer(() => { | |||||||
|   const { id } = useParams(); |   const { id } = useParams(); | ||||||
|   const { getCities } = cityStore; |   const { getCities } = cityStore; | ||||||
|  |  | ||||||
|  |   let blocker = useBlocker( | ||||||
|  |     ({ currentLocation, nextLocation }) => | ||||||
|  |       true && currentLocation.pathname !== nextLocation.pathname | ||||||
|  |   ); | ||||||
|  |  | ||||||
|   const handleChange = (_: React.SyntheticEvent, newValue: number) => { |   const handleChange = (_: React.SyntheticEvent, newValue: number) => { | ||||||
|     setValue(newValue); |     setValue(newValue); | ||||||
|   }; |   }; | ||||||
| @@ -82,6 +87,8 @@ export const EditSightPage = observer(() => { | |||||||
|           <RightWidgetTab value={value} index={2} /> |           <RightWidgetTab value={value} index={2} /> | ||||||
|         </div> |         </div> | ||||||
|       )} |       )} | ||||||
|  |  | ||||||
|  |       {blocker.state === "blocked" ? <LeaveAgree blocker={blocker} /> : null} | ||||||
|     </Box> |     </Box> | ||||||
|   ); |   ); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -28,8 +28,8 @@ import { FeatureLike } from "ol/Feature"; | |||||||
|  |  | ||||||
| // --- CONFIGURATION --- | // --- CONFIGURATION --- | ||||||
| export const mapConfig = { | export const mapConfig = { | ||||||
|   center: [37.6173, 55.7558] as [number, number], |   center: [30.311, 59.94] as [number, number], | ||||||
|   zoom: 10, |   zoom: 13, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // --- SVG ICONS --- | // --- SVG ICONS --- | ||||||
| @@ -1128,7 +1128,7 @@ const MapControls: React.FC<MapControlsProps> = ({ | |||||||
|   const controls = [ |   const controls = [ | ||||||
|     { |     { | ||||||
|       mode: "edit", |       mode: "edit", | ||||||
|       title: "Редакт.", |       title: "Редактировать", | ||||||
|       longTitle: "Редактирование", |       longTitle: "Редактирование", | ||||||
|       icon: <EditIcon />, |       icon: <EditIcon />, | ||||||
|       action: () => mapService.activateEditMode(), |       action: () => mapService.activateEditMode(), | ||||||
| @@ -1156,7 +1156,7 @@ const MapControls: React.FC<MapControlsProps> = ({ | |||||||
|     }, |     }, | ||||||
|   ]; |   ]; | ||||||
|   return ( |   return ( | ||||||
|     <div className="absolute top-4 left-1/2 -translate-x-1/2 z-20 flex flex-wrap justify-center p-2 bg-white/90 backdrop-blur-sm rounded-lg shadow-xl space-x-1 sm:space-x-2"> |     <div className="absolute  top-4 left-1/2 -translate-x-1/2 z-20 flex flex-nowrap justify-center p-2 bg-white/90 backdrop-blur-sm rounded-lg shadow-xl space-x-1 sm:space-x-2"> | ||||||
|       {controls.map((c) => ( |       {controls.map((c) => ( | ||||||
|         <button |         <button | ||||||
|           key={c.mode} |           key={c.mode} | ||||||
|   | |||||||
| @@ -2,10 +2,11 @@ import { TableBody } from "@mui/material"; | |||||||
| import { TableRow, TableCell } from "@mui/material"; | import { TableRow, TableCell } from "@mui/material"; | ||||||
| import { Table, TableHead } from "@mui/material"; | import { Table, TableHead } from "@mui/material"; | ||||||
| import { mediaStore, MEDIA_TYPE_LABELS } from "@shared"; | import { mediaStore, MEDIA_TYPE_LABELS } from "@shared"; | ||||||
| import { useEffect } from "react"; | import { useEffect, useState } from "react"; | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { Eye, Pencil, Trash2 } from "lucide-react"; | import { Eye, Pencil, Trash2 } from "lucide-react"; | ||||||
| import { useNavigate } from "react-router-dom"; | import { useNavigate } from "react-router-dom"; | ||||||
|  | import { DeleteModal } from "@widgets"; | ||||||
|  |  | ||||||
| const rows = (media: any[]) => { | const rows = (media: any[]) => { | ||||||
|   return media.map((row) => ({ |   return media.map((row) => ({ | ||||||
| @@ -24,7 +25,8 @@ export const MediaListPage = observer(() => { | |||||||
|   }, []); |   }, []); | ||||||
|  |  | ||||||
|   const currentRows = rows(media); |   const currentRows = rows(media); | ||||||
|  |   const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); | ||||||
|  |   const [rowId, setRowId] = useState<number | null>(null); | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <Table sx={{ minWidth: 650 }} aria-label="simple table"> |       <Table sx={{ minWidth: 650 }} aria-label="simple table"> | ||||||
| @@ -53,7 +55,12 @@ export const MediaListPage = observer(() => { | |||||||
|                     <Pencil size={20} className="text-blue-500" /> |                     <Pencil size={20} className="text-blue-500" /> | ||||||
|                   </button> |                   </button> | ||||||
|  |  | ||||||
|                   <button onClick={() => deleteMedia(row.id)}> |                   <button | ||||||
|  |                     onClick={() => { | ||||||
|  |                       setIsDeleteModalOpen(true); | ||||||
|  |                       setRowId(row.id); | ||||||
|  |                     }} | ||||||
|  |                   > | ||||||
|                     <Trash2 size={20} className="text-red-500" /> |                     <Trash2 size={20} className="text-red-500" /> | ||||||
|                   </button> |                   </button> | ||||||
|                 </div> |                 </div> | ||||||
| @@ -62,6 +69,20 @@ export const MediaListPage = observer(() => { | |||||||
|           ))} |           ))} | ||||||
|         </TableBody> |         </TableBody> | ||||||
|       </Table> |       </Table> | ||||||
|  |       <DeleteModal | ||||||
|  |         open={isDeleteModalOpen} | ||||||
|  |         onDelete={async () => { | ||||||
|  |           if (rowId) { | ||||||
|  |             await deleteMedia(rowId.toString()); | ||||||
|  |           } | ||||||
|  |           setIsDeleteModalOpen(false); | ||||||
|  |           setRowId(null); | ||||||
|  |         }} | ||||||
|  |         onCancel={() => { | ||||||
|  |           setIsDeleteModalOpen(false); | ||||||
|  |           setRowId(null); | ||||||
|  |         }} | ||||||
|  |       /> | ||||||
|     </> |     </> | ||||||
|   ); |   ); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -7,3 +7,14 @@ export const MEDIA_TYPE_LABELS = { | |||||||
|   5: "Панорама", |   5: "Панорама", | ||||||
|   6: "3Д-модель", |   6: "3Д-модель", | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const MEDIA_TYPE_VALUES = { | ||||||
|  |   photo: 1, | ||||||
|  |   video: 2, | ||||||
|  |   icon: 3, | ||||||
|  |   thumbnail: 3, | ||||||
|  |   watermark_lu: 4, | ||||||
|  |   watermark_rd: 4, | ||||||
|  |   panorama: 5, | ||||||
|  |   model: 6, | ||||||
|  | }; | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ import { | |||||||
|   InputAdornment, |   InputAdornment, | ||||||
| } from "@mui/material"; | } from "@mui/material"; | ||||||
| import { ImagePlus, Search } from "lucide-react"; | import { ImagePlus, Search } from "lucide-react"; | ||||||
| import { ReactMarkdownComponent } from "@widgets"; | import { MediaViewer, ReactMarkdownComponent } from "@widgets"; | ||||||
|  |  | ||||||
| interface SelectArticleModalProps { | interface SelectArticleModalProps { | ||||||
|   open: boolean; |   open: boolean; | ||||||
| @@ -106,7 +106,6 @@ export const SelectArticleModal = observer( | |||||||
|     //   article.service_name.toLowerCase().includes(searchQuery.toLowerCase()) |     //   article.service_name.toLowerCase().includes(searchQuery.toLowerCase()) | ||||||
|     // ); |     // ); | ||||||
|  |  | ||||||
|     const token = localStorage.getItem("token"); |  | ||||||
|     return ( |     return ( | ||||||
|       <Dialog |       <Dialog | ||||||
|         open={open} |         open={open} | ||||||
| @@ -128,10 +127,12 @@ export const SelectArticleModal = observer( | |||||||
|             height: "600px", |             height: "600px", | ||||||
|             display: "flex", |             display: "flex", | ||||||
|             flexDirection: "row", |             flexDirection: "row", | ||||||
|  |             alignItems: "center", | ||||||
|  |  | ||||||
|             p: 2, |             p: 2, | ||||||
|           }} |           }} | ||||||
|         > |         > | ||||||
|           <Paper className="w-[66%] flex flex-col" elevation={2}> |           <Paper className="w-[66%] flex flex-col h-full" elevation={2}> | ||||||
|             <TextField |             <TextField | ||||||
|               fullWidth |               fullWidth | ||||||
|               placeholder="Поиск статей..." |               placeholder="Поиск статей..." | ||||||
| @@ -201,108 +202,86 @@ export const SelectArticleModal = observer( | |||||||
|               )} |               )} | ||||||
|             </List> |             </List> | ||||||
|           </Paper> |           </Paper> | ||||||
|           <Paper className="flex-1 flex flex-col" elevation={2}> |           <Paper | ||||||
|  |             elevation={3} | ||||||
|  |             sx={{ | ||||||
|  |               width: "100%", | ||||||
|  |               minWidth: 320, | ||||||
|  |               maxWidth: 310, | ||||||
|  |  | ||||||
|  |               background: | ||||||
|  |                 "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|  |  | ||||||
|  |               padding: 0, | ||||||
|  |               margin: "0px auto", | ||||||
|  |               display: "flex", | ||||||
|  |               flexDirection: "column", | ||||||
|  |             }} | ||||||
|  |           > | ||||||
|             <Box |             <Box | ||||||
|               className="rounded-2xl overflow-hidden" |  | ||||||
|               sx={{ |               sx={{ | ||||||
|                 width: "100%", |                 width: "100%", | ||||||
|                 height: "100%", |                 height: 175, | ||||||
|                 background: "#877361", |  | ||||||
|                 borderColor: "grey.300", |  | ||||||
|                 display: "flex", |                 display: "flex", | ||||||
|                 flexDirection: "column", |                 alignItems: "center", | ||||||
|  |                 justifyContent: "center", | ||||||
|  |                 padding: "3px", | ||||||
|               }} |               }} | ||||||
|             > |             > | ||||||
|               {isLoading ? ( |               {articlesStore.articleMedia ? ( | ||||||
|                 <Box |                 <MediaViewer | ||||||
|                   sx={{ |                   media={{ | ||||||
|                     width: "100%", |                     id: articlesStore.articleMedia.id, | ||||||
|                     height: "100%", |                     media_type: articlesStore.articleMedia.media_type, | ||||||
|                     display: "flex", |                     filename: articlesStore.articleMedia.filename, | ||||||
|                     alignItems: "center", |  | ||||||
|                     justifyContent: "center", |  | ||||||
|                   }} |                   }} | ||||||
|                 > |                 /> | ||||||
|                   <Typography color="white">Загрузка...</Typography> |  | ||||||
|                 </Box> |  | ||||||
|               ) : ( |               ) : ( | ||||||
|                 <> |                 <ImagePlus size={48} color="white" /> | ||||||
|                   {articlesStore.articleMedia && ( |  | ||||||
|                     <Box sx={{ p: 2, backgroundColor: "rgba(0,0,0,0.1)" }}> |  | ||||||
|                       <img |  | ||||||
|                         src={`${import.meta.env.VITE_KRBL_MEDIA}${ |  | ||||||
|                           articlesStore.articleMedia.id |  | ||||||
|                         }/download?token=${token}`} |  | ||||||
|                         alt={articlesStore.articleMedia.filename} |  | ||||||
|                         style={{ |  | ||||||
|                           maxWidth: "100%", |  | ||||||
|                           height: "auto", |  | ||||||
|                           maxHeight: "300px", |  | ||||||
|                           objectFit: "contain", |  | ||||||
|                           borderRadius: 8, |  | ||||||
|                         }} |  | ||||||
|                       /> |  | ||||||
|                     </Box> |  | ||||||
|                   )} |  | ||||||
|                   {!articlesStore.articleMedia && ( |  | ||||||
|                     <Box |  | ||||||
|                       sx={{ |  | ||||||
|                         width: "100%", |  | ||||||
|                         height: 200, |  | ||||||
|                         flexShrink: 0, |  | ||||||
|                         backgroundColor: "rgba(0,0,0,0.1)", |  | ||||||
|                         display: "flex", |  | ||||||
|                         alignItems: "center", |  | ||||||
|                         justifyContent: "center", |  | ||||||
|                       }} |  | ||||||
|                     > |  | ||||||
|                       <ImagePlus size={48} color="white" /> |  | ||||||
|                     </Box> |  | ||||||
|                   )} |  | ||||||
|  |  | ||||||
|                   <Box |  | ||||||
|                     sx={{ |  | ||||||
|                       width: "100%", |  | ||||||
|                       minHeight: "70px", |  | ||||||
|                       background: "#877361", |  | ||||||
|                       display: "flex", |  | ||||||
|                       flexShrink: 0, |  | ||||||
|                       alignItems: "center", |  | ||||||
|                       borderBottom: "1px solid rgba(255,255,255,0.1)", |  | ||||||
|                       px: 2, |  | ||||||
|                     }} |  | ||||||
|                   > |  | ||||||
|                     <Typography variant="h6" color="white"> |  | ||||||
|                       {articlesStore.articleData?.heading || "Выберите статью"} |  | ||||||
|                     </Typography> |  | ||||||
|                   </Box> |  | ||||||
|  |  | ||||||
|                   <Box |  | ||||||
|                     sx={{ |  | ||||||
|                       px: 2, |  | ||||||
|                       flexGrow: 1, |  | ||||||
|                       overflowY: "auto", |  | ||||||
|                       backgroundColor: "#877361", |  | ||||||
|                       color: "white", |  | ||||||
|                       py: 1, |  | ||||||
|                     }} |  | ||||||
|                   > |  | ||||||
|                     {articlesStore.articleData?.body ? ( |  | ||||||
|                       <ReactMarkdownComponent |  | ||||||
|                         value={articlesStore.articleData.body} |  | ||||||
|                       /> |  | ||||||
|                     ) : ( |  | ||||||
|                       <Typography |  | ||||||
|                         color="rgba(255,255,255,0.7)" |  | ||||||
|                         sx={{ textAlign: "center", mt: 4 }} |  | ||||||
|                       > |  | ||||||
|                         Предпросмотр статьи появится здесь |  | ||||||
|                       </Typography> |  | ||||||
|                     )} |  | ||||||
|                   </Box> |  | ||||||
|                 </> |  | ||||||
|               )} |               )} | ||||||
|             </Box> |             </Box> | ||||||
|  |  | ||||||
|  |             <Box | ||||||
|  |               sx={{ | ||||||
|  |                 background: | ||||||
|  |                   "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|  |                 color: "white", | ||||||
|  |                 margin: "5px 0px 5px 0px", | ||||||
|  |                 display: "flex", | ||||||
|  |                 flexDirection: "column", | ||||||
|  |                 gap: 1, | ||||||
|  |                 padding: 1, | ||||||
|  |               }} | ||||||
|  |             > | ||||||
|  |               <Typography | ||||||
|  |                 variant="h5" | ||||||
|  |                 component="h2" | ||||||
|  |                 sx={{ | ||||||
|  |                   wordBreak: "break-word", | ||||||
|  |                   fontSize: "24px", | ||||||
|  |                   fontWeight: 700, | ||||||
|  |                   lineHeight: "120%", | ||||||
|  |                 }} | ||||||
|  |               > | ||||||
|  |                 {articlesStore.articleData?.heading || "Название cтатьи"} | ||||||
|  |               </Typography> | ||||||
|  |             </Box> | ||||||
|  |  | ||||||
|  |             {articlesStore.articleData?.body && ( | ||||||
|  |               <Box | ||||||
|  |                 sx={{ | ||||||
|  |                   padding: 1, | ||||||
|  |                   maxHeight: "200px", | ||||||
|  |                   overflowY: "scroll", | ||||||
|  |                   background: | ||||||
|  |                     "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|  |                 }} | ||||||
|  |               > | ||||||
|  |                 <ReactMarkdownComponent | ||||||
|  |                   value={articlesStore.articleData?.body || "Описание"} | ||||||
|  |                 /> | ||||||
|  |               </Box> | ||||||
|  |             )} | ||||||
|           </Paper> |           </Paper> | ||||||
|         </DialogContent> |         </DialogContent> | ||||||
|         <DialogActions sx={{ p: 2 }}> |         <DialogActions sx={{ p: 2 }}> | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { mediaStore } from "@shared"; | import { Media, mediaStore } from "@shared"; | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { useEffect, useState } from "react"; | import { useEffect, useState } from "react"; | ||||||
| import { | import { | ||||||
| @@ -29,6 +29,7 @@ interface SelectMediaDialogProps { | |||||||
|   }) => void; // Renamed from onSelectArticle |   }) => void; // Renamed from onSelectArticle | ||||||
|   onSelectForSightMedia?: (mediaId: string) => void; |   onSelectForSightMedia?: (mediaId: string) => void; | ||||||
|   linkedMediaIds?: string[]; // Renamed from linkedArticleIds, assuming it refers to media already in use |   linkedMediaIds?: string[]; // Renamed from linkedArticleIds, assuming it refers to media already in use | ||||||
|  |   mediaType?: number; | ||||||
| } | } | ||||||
|  |  | ||||||
| export const SelectMediaDialog = observer( | export const SelectMediaDialog = observer( | ||||||
| @@ -38,12 +39,29 @@ export const SelectMediaDialog = observer( | |||||||
|     onSelectMedia, // Renamed prop |     onSelectMedia, // Renamed prop | ||||||
|     onSelectForSightMedia, |     onSelectForSightMedia, | ||||||
|     linkedMediaIds = [], // Default to empty array if not provided, renamed |     linkedMediaIds = [], // Default to empty array if not provided, renamed | ||||||
|  |     mediaType, | ||||||
|   }: SelectMediaDialogProps) => { |   }: SelectMediaDialogProps) => { | ||||||
|     const { media, getMedia } = mediaStore; |     const { media, getMedia } = mediaStore; | ||||||
|     const [searchQuery, setSearchQuery] = useState(""); |     const [searchQuery, setSearchQuery] = useState(""); | ||||||
|     const [hoveredMediaId, setHoveredMediaId] = useState<string | null>(null); |     const [hoveredMediaId, setHoveredMediaId] = useState<string | null>(null); | ||||||
|  |     const [currentHoveredMedia, setCurrentHoveredMedia] = | ||||||
|  |       useState<Media | null>(null); | ||||||
|  |  | ||||||
|  |     useEffect(() => { | ||||||
|  |       if (hoveredMediaId) { | ||||||
|  |         setCurrentHoveredMedia( | ||||||
|  |           media.find((m) => m.id === hoveredMediaId) ?? null | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  |     }, [hoveredMediaId]); | ||||||
|  |  | ||||||
|  |     const handleClose = () => { | ||||||
|  |       setHoveredMediaId(null); | ||||||
|  |       setCurrentHoveredMedia(null); | ||||||
|  |       onClose(); | ||||||
|  |       setSearchQuery(""); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     // Fetch media on component mount |  | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|       getMedia(); |       getMedia(); | ||||||
|     }, [getMedia]); |     }, [getMedia]); | ||||||
| @@ -63,7 +81,7 @@ export const SelectMediaDialog = observer( | |||||||
|                 onSelectMedia(mediaItem); |                 onSelectMedia(mediaItem); | ||||||
|               } |               } | ||||||
|             } |             } | ||||||
|             onClose(); |             handleClose(); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|       }; |       }; | ||||||
| @@ -74,19 +92,21 @@ export const SelectMediaDialog = observer( | |||||||
|       }; |       }; | ||||||
|     }, [hoveredMediaId, onSelectMedia, onClose]); // Dependencies for keyboard listener |     }, [hoveredMediaId, onSelectMedia, onClose]); // Dependencies for keyboard listener | ||||||
|  |  | ||||||
|     const filteredMedia = media |     let filteredMedia = media | ||||||
|       .filter((mediaItem) => !linkedMediaIds.includes(mediaItem.id)) // Use mediaItem to avoid name collision |       .filter((mediaItem) => !linkedMediaIds.includes(mediaItem.id)) // Use mediaItem to avoid name collision | ||||||
|       .filter((mediaItem) => |       .filter((mediaItem) => | ||||||
|         mediaItem.media_name.toLowerCase().includes(searchQuery.toLowerCase()) |         mediaItem.media_name.toLowerCase().includes(searchQuery.toLowerCase()) | ||||||
|       ); |       ); | ||||||
|  |  | ||||||
|     // Find the currently hovered media object for MediaViewer |     if (mediaType) { | ||||||
|     const currentHoveredMedia = hoveredMediaId |       filteredMedia = filteredMedia.filter( | ||||||
|       ? media.find((m) => m.id === hoveredMediaId) |         (mediaItem) => mediaItem.media_type === mediaType | ||||||
|       : null; |       ); | ||||||
|  |       console.log(filteredMedia); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <Dialog open={open} onClose={onClose} maxWidth="lg" fullWidth> |       <Dialog open={open} onClose={handleClose} maxWidth="lg" fullWidth> | ||||||
|         <DialogTitle>Выберите существующее медиа</DialogTitle> |         <DialogTitle>Выберите существующее медиа</DialogTitle> | ||||||
|         <DialogContent |         <DialogContent | ||||||
|           className="flex gap-4" |           className="flex gap-4" | ||||||
| @@ -125,14 +145,22 @@ export const SelectMediaDialog = observer( | |||||||
|                         } else if (onSelectMedia) { |                         } else if (onSelectMedia) { | ||||||
|                           onSelectMedia(mediaItem); |                           onSelectMedia(mediaItem); | ||||||
|                         } |                         } | ||||||
|                         onClose(); |                         handleClose(); | ||||||
|                       }} |                       }} | ||||||
|  |                       selected={hoveredMediaId === mediaItem.id} | ||||||
|                       sx={{ |                       sx={{ | ||||||
|                         borderRadius: 1, |                         borderRadius: 1, | ||||||
|                         mb: 0.5, |                         mb: 0.5, | ||||||
|                         "&:hover": { |                         "&:hover": { | ||||||
|                           backgroundColor: "action.hover", |                           backgroundColor: "action.hover", | ||||||
|                         }, |                         }, | ||||||
|  |                         "&.Mui-selected": { | ||||||
|  |                           backgroundColor: "primary.main", | ||||||
|  |                           color: "primary.contrastText", | ||||||
|  |                           "&:hover": { | ||||||
|  |                             backgroundColor: "primary.dark", | ||||||
|  |                           }, | ||||||
|  |                         }, | ||||||
|                       }} |                       }} | ||||||
|                     > |                     > | ||||||
|                       <ListItemText primary={mediaItem.media_name} /> |                       <ListItemText primary={mediaItem.media_name} /> | ||||||
| @@ -149,7 +177,7 @@ export const SelectMediaDialog = observer( | |||||||
|               )} |               )} | ||||||
|             </List> |             </List> | ||||||
|           </Paper> |           </Paper> | ||||||
|           {currentHoveredMedia ? ( // Only render MediaViewer if currentHoveredMedia is found |           {currentHoveredMedia !== null && hoveredMediaId !== null ? ( // Only render MediaViewer if currentHoveredMedia is found | ||||||
|             <Paper className="w-[33%] h-[100%] flex justify-center items-center"> |             <Paper className="w-[33%] h-[100%] flex justify-center items-center"> | ||||||
|               <MediaViewer |               <MediaViewer | ||||||
|                 media={{ |                 media={{ | ||||||
| @@ -167,8 +195,28 @@ export const SelectMediaDialog = observer( | |||||||
|             </Paper> |             </Paper> | ||||||
|           )} |           )} | ||||||
|         </DialogContent> |         </DialogContent> | ||||||
|         <DialogActions> |  | ||||||
|           <Button onClick={onClose}>Отмена</Button> |         <DialogActions sx={{ p: 2 }}> | ||||||
|  |           <Button onClick={handleClose}>Отмена</Button> | ||||||
|  |           <Button | ||||||
|  |             variant="contained" | ||||||
|  |             onClick={() => { | ||||||
|  |               if (hoveredMediaId) { | ||||||
|  |                 const mediaItem = media.find((m) => m.id === hoveredMediaId); | ||||||
|  |                 if (mediaItem) { | ||||||
|  |                   if (onSelectForSightMedia) { | ||||||
|  |                     onSelectForSightMedia(mediaItem.id); | ||||||
|  |                   } else if (onSelectMedia) { | ||||||
|  |                     onSelectMedia(mediaItem); | ||||||
|  |                   } | ||||||
|  |                 } | ||||||
|  |                 handleClose(); | ||||||
|  |               } | ||||||
|  |             }} | ||||||
|  |             disabled={hoveredMediaId === null} | ||||||
|  |           > | ||||||
|  |             Выбрать | ||||||
|  |           </Button> | ||||||
|         </DialogActions> |         </DialogActions> | ||||||
|       </Dialog> |       </Dialog> | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -586,6 +586,12 @@ class CreateSightStore { | |||||||
|       throw error; |       throw error; | ||||||
|     } |     } | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   updateRightArticles = async (articles: any[], language: Language) => { | ||||||
|  |     runInAction(() => { | ||||||
|  |       this.sight[language].right = articles; | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
| } | } | ||||||
|  |  | ||||||
| export const createSightStore = new CreateSightStore(); | export const createSightStore = new CreateSightStore(); | ||||||
|   | |||||||
| @@ -121,35 +121,32 @@ class EditSightStore { | |||||||
|     let responseEn = await languageInstance("en").get(`/sight/${id}/article`); |     let responseEn = await languageInstance("en").get(`/sight/${id}/article`); | ||||||
|     let responseZh = await languageInstance("zh").get(`/sight/${id}/article`); |     let responseZh = await languageInstance("zh").get(`/sight/${id}/article`); | ||||||
|  |  | ||||||
|     // Function to fetch media for a given set of articles |     // Create a map of article IDs to their media | ||||||
|     const fetchMediaForArticles = async (articles: any[]) => { |     const mediaMap = new Map(); | ||||||
|       const articlesWithMedia = []; |     for (const article of responseRu.data) { | ||||||
|       for (const article of articles) { |       const responseMedia = await authInstance.get( | ||||||
|         const responseMedia = await authInstance.get( |         `/article/${article.id}/media` | ||||||
|           `/article/${article.id}/media` |       ); | ||||||
|         ); |       mediaMap.set(article.id, responseMedia.data); | ||||||
|         articlesWithMedia.push({ |     } | ||||||
|           ...article, |  | ||||||
|           media: responseMedia.data, |  | ||||||
|         }); |  | ||||||
|       } |  | ||||||
|       return articlesWithMedia; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     // Fetch media for articles in each language |     // Function to add media to articles | ||||||
|     const ruArticlesWithMedia = await fetchMediaForArticles(responseRu.data); |     const addMediaToArticles = (articles: any[]) => { | ||||||
|     const enArticlesWithMedia = await fetchMediaForArticles(responseEn.data); |       return articles.map((article) => ({ | ||||||
|     const zhArticlesWithMedia = await fetchMediaForArticles(responseZh.data); |         ...article, | ||||||
|  |         media: mediaMap.get(article.id), | ||||||
|  |       })); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     const data = { |     const data = { | ||||||
|       ru: { |       ru: { | ||||||
|         right: ruArticlesWithMedia, |         right: addMediaToArticles(responseRu.data), | ||||||
|       }, |       }, | ||||||
|       en: { |       en: { | ||||||
|         right: enArticlesWithMedia, |         right: addMediaToArticles(responseEn.data), | ||||||
|       }, |       }, | ||||||
|       zh: { |       zh: { | ||||||
|         right: zhArticlesWithMedia, |         right: addMediaToArticles(responseZh.data), | ||||||
|       }, |       }, | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| @@ -673,6 +670,16 @@ class EditSightStore { | |||||||
|     this.sight[language].right[index].heading = heading; |     this.sight[language].right[index].heading = heading; | ||||||
|     this.sight[language].right[index].body = body; |     this.sight[language].right[index].body = body; | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|  |   updateRightArticles = async (articles: any[], language: Language) => { | ||||||
|  |     this.sight[language].right = articles; | ||||||
|  |     const articleIdsInObject = articles.map((article) => ({ | ||||||
|  |       id: article.id, | ||||||
|  |     })); | ||||||
|  |     await authInstance.post(`/sight/${this.sight.common.id}/article/order`, { | ||||||
|  |       articles: articleIdsInObject, | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
| } | } | ||||||
|  |  | ||||||
| export const editSightStore = new EditSightStore(); | export const editSightStore = new EditSightStore(); | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { makeAutoObservable, runInAction } from "mobx"; | import { makeAutoObservable, runInAction } from "mobx"; | ||||||
| import { authInstance } from "@shared"; | import { authInstance } from "@shared"; | ||||||
|  |  | ||||||
| type Media = { | export type Media = { | ||||||
|   id: string; |   id: string; | ||||||
|   filename: string; |   filename: string; | ||||||
|   media_name: string; |   media_name: string; | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								src/widgets/DeleteModal/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/widgets/DeleteModal/index.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | import { Button } from "@mui/material"; | ||||||
|  |  | ||||||
|  | export const DeleteModal = ({ | ||||||
|  |   onDelete, | ||||||
|  |   onCancel, | ||||||
|  |   open, | ||||||
|  | }: { | ||||||
|  |   onDelete: () => void; | ||||||
|  |   onCancel: () => void; | ||||||
|  |   open: boolean; | ||||||
|  | }) => { | ||||||
|  |   return ( | ||||||
|  |     <div | ||||||
|  |       className={`fixed  top-0 left-0 w-screen h-screen  flex justify-center items-center z-10000 bg-black/30 transition-all duration-300 ${ | ||||||
|  |         open ? "block" : "hidden" | ||||||
|  |       }`} | ||||||
|  |     > | ||||||
|  |       <div className="bg-white p-4 w-100 rounded-lg flex flex-col gap-4 items-center"> | ||||||
|  |         <p className="text-black w-100 text-center"> | ||||||
|  |           Вы уверены, что хотите удалить этот элемент? | ||||||
|  |         </p> | ||||||
|  |         <div className="flex gap-4 justify-center"> | ||||||
|  |           <Button variant="contained" color="error" onClick={onDelete}> | ||||||
|  |             Да | ||||||
|  |           </Button> | ||||||
|  |           <Button variant="outlined" onClick={onCancel}> | ||||||
|  |             Нет | ||||||
|  |           </Button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| import React, { useRef, useState, DragEvent, useEffect } from "react"; | import React, { useRef, useState, DragEvent, useEffect } from "react"; | ||||||
| import { Paper, Box, Typography, Button, Tooltip } from "@mui/material"; | import { Paper, Box, Typography, Button, Tooltip } from "@mui/material"; | ||||||
| import { X, Info } from "lucide-react"; // Assuming lucide-react for icons | import { X, Info, MousePointer } from "lucide-react"; // Assuming lucide-react for icons | ||||||
| import { editSightStore } from "@shared"; | import { editSightStore } from "@shared"; | ||||||
|  |  | ||||||
| interface ImageUploadCardProps { | interface ImageUploadCardProps { | ||||||
| @@ -159,6 +159,7 @@ export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({ | |||||||
|             <Button |             <Button | ||||||
|               variant="contained" |               variant="contained" | ||||||
|               color="primary" |               color="primary" | ||||||
|  |               startIcon={<MousePointer color="white" size={18} />} | ||||||
|               onClick={(e) => { |               onClick={(e) => { | ||||||
|                 e.stopPropagation(); // Prevent `handleZoneClick` from firing |                 e.stopPropagation(); // Prevent `handleZoneClick` from firing | ||||||
|                 onSelectFileClick(); // This button might trigger a different modal |                 onSelectFileClick(); // This button might trigger a different modal | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								src/widgets/LeaveAgree/index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/widgets/LeaveAgree/index.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | import { Button } from "@mui/material"; | ||||||
|  |  | ||||||
|  | export const LeaveAgree = ({ blocker }: { blocker: any }) => { | ||||||
|  |   return ( | ||||||
|  |     <div className="fixed  top-0 left-0 w-screen h-screen  flex justify-center items-center z-10000 bg-black/30"> | ||||||
|  |       <div className="bg-white p-4 w-100 rounded-lg flex flex-col gap-4 items-center"> | ||||||
|  |         <p className="text-black w-100 text-center"> | ||||||
|  |           При выходе со страницы, несохраненные данные будут потеряны. | ||||||
|  |         </p> | ||||||
|  |         <div className="flex gap-4 justify-center"> | ||||||
|  |           <Button variant="contained" onClick={() => blocker.proceed()}> | ||||||
|  |             Да | ||||||
|  |           </Button> | ||||||
|  |           <Button variant="outlined" onClick={() => blocker.reset()}> | ||||||
|  |             Нет | ||||||
|  |           </Button> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
| @@ -69,7 +69,7 @@ export const MediaAreaForSight = observer( | |||||||
|         <Box className="w-full flex flex-col items-center justify-center border rounded-md p-4"> |         <Box className="w-full flex flex-col items-center justify-center border rounded-md p-4"> | ||||||
|           <div className="w-full flex flex-col items-center justify-center"> |           <div className="w-full flex flex-col items-center justify-center"> | ||||||
|             <div |             <div | ||||||
|               className={`w-full h-40 flex flex-col justify-center items-center text-gray-400 border-dashed border-2 rounded-md border-gray-400 p-4 cursor-pointer hover:bg-gray-50 ${ |               className={`w-full h-40 flex text-center flex-col justify-center items-center text-gray-400 border-dashed border-2 rounded-md border-gray-400 p-4 cursor-pointer hover:bg-gray-50 ${ | ||||||
|                 isDragging ? "bg-blue-100 border-blue-400" : "" |                 isDragging ? "bg-blue-100 border-blue-400" : "" | ||||||
|               }`} |               }`} | ||||||
|               onDrop={handleDrop} |               onDrop={handleDrop} | ||||||
|   | |||||||
| @@ -17,13 +17,11 @@ export function MediaViewer({ | |||||||
|   return ( |   return ( | ||||||
|     <Box |     <Box | ||||||
|       sx={{ |       sx={{ | ||||||
|         width: "80%", |         width: "100%", | ||||||
|         height: "100%", |         height: "100%", | ||||||
|         maxWidth: "600px", |  | ||||||
|         display: "flex", |         display: "flex", | ||||||
|         flexGrow: 1, |         flexGrow: 1, | ||||||
|         justifyContent: "center", |         justifyContent: "center", | ||||||
|         margin: "0 auto", |  | ||||||
|       }} |       }} | ||||||
|       className={className} |       className={className} | ||||||
|     > |     > | ||||||
| @@ -34,10 +32,9 @@ export function MediaViewer({ | |||||||
|           }/download?token=${token}`} |           }/download?token=${token}`} | ||||||
|           alt={media?.filename} |           alt={media?.filename} | ||||||
|           style={{ |           style={{ | ||||||
|             maxWidth: "100%", |             width: "100%", | ||||||
|             height: "auto", |  | ||||||
|             objectFit: "contain", |             objectFit: "cover", | ||||||
|             borderRadius: 8, |  | ||||||
|           }} |           }} | ||||||
|         /> |         /> | ||||||
|       )} |       )} | ||||||
| @@ -48,11 +45,10 @@ export function MediaViewer({ | |||||||
|             media?.id |             media?.id | ||||||
|           }/download?token=${token}`} |           }/download?token=${token}`} | ||||||
|           style={{ |           style={{ | ||||||
|             margin: "auto 0", |             width: "100%", | ||||||
|             height: "fit-content", |             height: "100%", | ||||||
|             width: "fit-content", |             objectFit: "cover", | ||||||
|             objectFit: "contain", |             borderRadius: 8, | ||||||
|             borderRadius: 30, |  | ||||||
|           }} |           }} | ||||||
|           controls |           controls | ||||||
|           autoPlay |           autoPlay | ||||||
| @@ -66,9 +62,9 @@ export function MediaViewer({ | |||||||
|           }/download?token=${token}`} |           }/download?token=${token}`} | ||||||
|           alt={media?.filename} |           alt={media?.filename} | ||||||
|           style={{ |           style={{ | ||||||
|             maxWidth: "100%", |             width: "100%", | ||||||
|             height: "100%", |             height: "100%", | ||||||
|             objectFit: "contain", |             objectFit: "cover", | ||||||
|             borderRadius: 8, |             borderRadius: 8, | ||||||
|           }} |           }} | ||||||
|         /> |         /> | ||||||
| @@ -80,9 +76,9 @@ export function MediaViewer({ | |||||||
|           }/download?token=${token}`} |           }/download?token=${token}`} | ||||||
|           alt={media?.filename} |           alt={media?.filename} | ||||||
|           style={{ |           style={{ | ||||||
|             maxWidth: "100%", |             width: "100%", | ||||||
|             height: "100%", |             height: "100%", | ||||||
|             objectFit: "contain", |             objectFit: "cover", | ||||||
|             borderRadius: 8, |             borderRadius: 8, | ||||||
|           }} |           }} | ||||||
|         /> |         /> | ||||||
|   | |||||||
| @@ -18,8 +18,10 @@ import { | |||||||
|   SightCommonInfo, |   SightCommonInfo, | ||||||
|   createSightStore, |   createSightStore, | ||||||
|   UploadMediaDialog, |   UploadMediaDialog, | ||||||
|  |   MEDIA_TYPE_VALUES, | ||||||
| } from "@shared"; | } from "@shared"; | ||||||
| import { ImageUploadCard, LanguageSwitcher } from "@widgets"; | import { ImageUploadCard, LanguageSwitcher } from "@widgets"; | ||||||
|  | import { Save } from "lucide-react"; | ||||||
|  |  | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { useEffect, useState } from "react"; | import { useEffect, useState } from "react"; | ||||||
| @@ -331,6 +333,7 @@ export const CreateInformationTab = observer( | |||||||
|               <Button |               <Button | ||||||
|                 variant="contained" |                 variant="contained" | ||||||
|                 color="success" |                 color="success" | ||||||
|  |                 startIcon={<Save color="white" size={18} />} | ||||||
|                 onClick={async () => { |                 onClick={async () => { | ||||||
|                   await createSight(language); |                   await createSight(language); | ||||||
|                   toast.success("Достопримечательность создана"); |                   toast.success("Достопримечательность создана"); | ||||||
| @@ -369,6 +372,13 @@ export const CreateInformationTab = observer( | |||||||
|           onSelectMedia={(media) => { |           onSelectMedia={(media) => { | ||||||
|             handleMediaSelect(media, activeMenuType ?? "thumbnail"); |             handleMediaSelect(media, activeMenuType ?? "thumbnail"); | ||||||
|           }} |           }} | ||||||
|  |           mediaType={ | ||||||
|  |             activeMenuType | ||||||
|  |               ? MEDIA_TYPE_VALUES[ | ||||||
|  |                   activeMenuType as keyof typeof MEDIA_TYPE_VALUES | ||||||
|  |                 ] | ||||||
|  |               : undefined | ||||||
|  |           } | ||||||
|         /> |         /> | ||||||
|  |  | ||||||
|         <PreviewMediaDialog |         <PreviewMediaDialog | ||||||
|   | |||||||
| @@ -16,8 +16,16 @@ import { | |||||||
|   ReactMarkdownComponent, |   ReactMarkdownComponent, | ||||||
|   ReactMarkdownEditor, |   ReactMarkdownEditor, | ||||||
|   MediaViewer, |   MediaViewer, | ||||||
|  |   DeleteModal, | ||||||
| } from "@widgets"; | } from "@widgets"; | ||||||
| import { Trash2, ImagePlus } from "lucide-react"; | import { | ||||||
|  |   Trash2, | ||||||
|  |   ImagePlus, | ||||||
|  |   Unlink, | ||||||
|  |   MousePointer, | ||||||
|  |   Plus, | ||||||
|  |   Save, | ||||||
|  | } from "lucide-react"; | ||||||
| import { useState, useCallback } from "react"; | import { useState, useCallback } from "react"; | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { toast } from "react-toastify"; | import { toast } from "react-toastify"; | ||||||
| @@ -47,7 +55,7 @@ export const CreateLeftTab = observer( | |||||||
|       useState(false); |       useState(false); | ||||||
|     const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] = |     const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] = | ||||||
|       useState(false); |       useState(false); | ||||||
|  |     const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); | ||||||
|     // const handleMediaSelected = useCallback(() => { |     // const handleMediaSelected = useCallback(() => { | ||||||
|     //   // При выборе медиа, обновляем данные для ТЕКУЩЕГО ЯЗЫКА |     //   // При выборе медиа, обновляем данные для ТЕКУЩЕГО ЯЗЫКА | ||||||
|     //   // сохраняя текущие heading и body. |     //   // сохраняя текущие heading и body. | ||||||
| @@ -123,6 +131,7 @@ export const CreateLeftTab = observer( | |||||||
|                     color="primary" |                     color="primary" | ||||||
|                     size="small" |                     size="small" | ||||||
|                     style={{ transition: "0" }} |                     style={{ transition: "0" }} | ||||||
|  |                     startIcon={<Unlink size={18} />} | ||||||
|                     onClick={() => { |                     onClick={() => { | ||||||
|                       unlinkLeftArticle(); |                       unlinkLeftArticle(); | ||||||
|                       toast.success("Статья откреплена"); |                       toast.success("Статья откреплена"); | ||||||
| @@ -136,10 +145,7 @@ export const CreateLeftTab = observer( | |||||||
|                     style={{ transition: "0" }} |                     style={{ transition: "0" }} | ||||||
|                     startIcon={<Trash2 size={18} />} |                     startIcon={<Trash2 size={18} />} | ||||||
|                     size="small" |                     size="small" | ||||||
|                     onClick={() => { |                     onClick={() => setIsDeleteModalOpen(true)} | ||||||
|                       deleteLeftArticle(sight.left_article); |  | ||||||
|                       toast.success("Статья откреплена"); |  | ||||||
|                     }} |  | ||||||
|                   > |                   > | ||||||
|                     Удалить |                     Удалить | ||||||
|                   </Button> |                   </Button> | ||||||
| @@ -150,6 +156,7 @@ export const CreateLeftTab = observer( | |||||||
|                     variant="contained" |                     variant="contained" | ||||||
|                     color="primary" |                     color="primary" | ||||||
|                     size="small" |                     size="small" | ||||||
|  |                     startIcon={<MousePointer color="white" size={18} />} | ||||||
|                     onClick={() => setIsSelectArticleDialogOpen(true)} |                     onClick={() => setIsSelectArticleDialogOpen(true)} | ||||||
|                   > |                   > | ||||||
|                     Выбрать статью |                     Выбрать статью | ||||||
| @@ -158,6 +165,7 @@ export const CreateLeftTab = observer( | |||||||
|                     variant="contained" |                     variant="contained" | ||||||
|                     color="primary" |                     color="primary" | ||||||
|                     size="small" |                     size="small" | ||||||
|  |                     startIcon={<Plus color="white" size={18} />} | ||||||
|                     style={{ transition: "0" }} |                     style={{ transition: "0" }} | ||||||
|                     onClick={createLeftArticle} |                     onClick={createLeftArticle} | ||||||
|                   > |                   > | ||||||
| @@ -301,6 +309,7 @@ export const CreateLeftTab = observer( | |||||||
|                     display: "flex", |                     display: "flex", | ||||||
|                     flexDirection: "column", |                     flexDirection: "column", | ||||||
|                     gap: 1.5, |                     gap: 1.5, | ||||||
|  |                     maxWidth: "320px", | ||||||
|                   }} |                   }} | ||||||
|                 > |                 > | ||||||
|                   <Paper |                   <Paper | ||||||
| @@ -405,10 +414,11 @@ export const CreateLeftTab = observer( | |||||||
|                 <Button |                 <Button | ||||||
|                   variant="contained" |                   variant="contained" | ||||||
|                   color="success" |                   color="success" | ||||||
|  |                   startIcon={<Save color="white" size={18} />} | ||||||
|                   onClick={async () => { |                   onClick={async () => { | ||||||
|                     try { |                     try { | ||||||
|                       await createSight(language); |                       await createSight(language); | ||||||
|                       toast.success("Странца создана"); |                       toast.success("Страница создана"); | ||||||
|                     } catch (error) { |                     } catch (error) { | ||||||
|                       console.error(error); |                       console.error(error); | ||||||
|                     } |                     } | ||||||
| @@ -445,6 +455,14 @@ export const CreateLeftTab = observer( | |||||||
|           onClose={handleCloseArticleDialog} |           onClose={handleCloseArticleDialog} | ||||||
|           onSelectArticle={handleArticleSelect} |           onSelectArticle={handleArticleSelect} | ||||||
|         /> |         /> | ||||||
|  |         <DeleteModal | ||||||
|  |           open={isDeleteModalOpen} | ||||||
|  |           onDelete={() => { | ||||||
|  |             deleteLeftArticle(sight.left_article); | ||||||
|  |             toast.success("Статья откреплена"); | ||||||
|  |           }} | ||||||
|  |           onCancel={() => setIsDeleteModalOpen(false)} | ||||||
|  |         /> | ||||||
|       </TabPanel> |       </TabPanel> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -14,7 +14,8 @@ import { | |||||||
|   SelectArticleModal, |   SelectArticleModal, | ||||||
|   TabPanel, |   TabPanel, | ||||||
|   SelectMediaDialog, // Import |   SelectMediaDialog, // Import | ||||||
|   UploadMediaDialog, // Import |   UploadMediaDialog, | ||||||
|  |   Media, // Import | ||||||
| } from "@shared"; | } from "@shared"; | ||||||
| import { | import { | ||||||
|   LanguageSwitcher, |   LanguageSwitcher, | ||||||
| @@ -22,12 +23,15 @@ import { | |||||||
|   MediaAreaForSight, // Import |   MediaAreaForSight, // Import | ||||||
|   ReactMarkdownComponent, |   ReactMarkdownComponent, | ||||||
|   ReactMarkdownEditor, |   ReactMarkdownEditor, | ||||||
|  |   DeleteModal, | ||||||
| } from "@widgets"; | } from "@widgets"; | ||||||
| import { ImagePlus, Plus, X } from "lucide-react"; // Import X | import { ImagePlus, Plus, Save, Trash2, Unlink, X } from "lucide-react"; // Import X | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { useState, useEffect } from "react"; // Added useEffect | import { useState, useEffect } from "react"; // Added useEffect | ||||||
| import { MediaViewer } from "../../MediaViewer/index"; | import { MediaViewer } from "../../MediaViewer/index"; | ||||||
| import { toast } from "react-toastify"; | import { toast } from "react-toastify"; | ||||||
|  | import { authInstance } from "@shared"; | ||||||
|  | import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd"; | ||||||
|  |  | ||||||
| type MediaItemShared = { | type MediaItemShared = { | ||||||
|   // Define if not already available from @shared |   // Define if not already available from @shared | ||||||
| @@ -56,6 +60,7 @@ export const CreateRightTab = observer( | |||||||
|       linkExistingRightArticle, |       linkExistingRightArticle, | ||||||
|       createSight, |       createSight, | ||||||
|       clearCreateSight, // For resetting form |       clearCreateSight, // For resetting form | ||||||
|  |       updateRightArticles, | ||||||
|     } = createSightStore; |     } = createSightStore; | ||||||
|     const { language } = languageStore; |     const { language } = languageStore; | ||||||
|  |  | ||||||
| @@ -65,14 +70,27 @@ export const CreateRightTab = observer( | |||||||
|       null |       null | ||||||
|     ); |     ); | ||||||
|     const [type, setType] = useState<"article" | "media">("media"); |     const [type, setType] = useState<"article" | "media">("media"); | ||||||
|  |     const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); | ||||||
|     const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] = |     const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] = | ||||||
|       useState(false); |       useState(false); | ||||||
|     const [mediaTarget, setMediaTarget] = useState< |     const [mediaTarget, setMediaTarget] = useState< | ||||||
|       "sightPreview" | "rightArticle" | null |       "sightPreview" | "rightArticle" | null | ||||||
|     >(null); |     >(null); | ||||||
|  |  | ||||||
|  |     const [previewMedia, setPreviewMedia] = useState<Media | null>(null); | ||||||
|     // Reset activeArticleIndex if language changes and index is out of bounds |     // Reset activeArticleIndex if language changes and index is out of bounds | ||||||
|  |     useEffect(() => { | ||||||
|  |       if (sight.preview_media) { | ||||||
|  |         const fetchMedia = async () => { | ||||||
|  |           const response = await authInstance.get( | ||||||
|  |             `/media/${sight.preview_media}` | ||||||
|  |           ); | ||||||
|  |           setPreviewMedia(response.data); | ||||||
|  |         }; | ||||||
|  |         fetchMedia(); | ||||||
|  |       } | ||||||
|  |     }, [sight.preview_media]); | ||||||
|  |  | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|       if ( |       if ( | ||||||
|         activeArticleIndex !== null && |         activeArticleIndex !== null && | ||||||
| @@ -168,6 +186,7 @@ export const CreateRightTab = observer( | |||||||
|  |  | ||||||
|     const handleMediaSelectedFromDialog = async (media: MediaItemShared) => { |     const handleMediaSelectedFromDialog = async (media: MediaItemShared) => { | ||||||
|       setIsSelectMediaDialogOpen(false); |       setIsSelectMediaDialogOpen(false); | ||||||
|  |  | ||||||
|       if (mediaTarget === "sightPreview") { |       if (mediaTarget === "sightPreview") { | ||||||
|         await linkPreviewMedia(media.id); |         await linkPreviewMedia(media.id); | ||||||
|       } else if (mediaTarget === "rightArticle" && currentRightArticle) { |       } else if (mediaTarget === "rightArticle" && currentRightArticle) { | ||||||
| @@ -176,6 +195,11 @@ export const CreateRightTab = observer( | |||||||
|       setMediaTarget(null); |       setMediaTarget(null); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     const handleUnlinkPreviewMedia = async () => { | ||||||
|  |       await unlinkPreviewMedia(); | ||||||
|  |       setPreviewMedia(null); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     const handleMediaUploaded = async (media: MediaItemShared) => { |     const handleMediaUploaded = async (media: MediaItemShared) => { | ||||||
|       // After UploadMediaDialog finishes |       // After UploadMediaDialog finishes | ||||||
|       setUploadMediaOpen(false); |       setUploadMediaOpen(false); | ||||||
| @@ -188,6 +212,36 @@ export const CreateRightTab = observer( | |||||||
|       setMediaTarget(null); // Reset target |       setMediaTarget(null); // Reset target | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     const handleDragEnd = (result: any) => { | ||||||
|  |       const { source, destination } = result; | ||||||
|  |  | ||||||
|  |       // 1. Guard clause: If dropped outside any droppable area, do nothing. | ||||||
|  |       if (!destination) return; | ||||||
|  |  | ||||||
|  |       // Extract source and destination indices | ||||||
|  |       const sourceIndex = source.index; | ||||||
|  |       const destinationIndex = destination.index; | ||||||
|  |  | ||||||
|  |       // 2. Guard clause: If dropped in the same position, do nothing. | ||||||
|  |       if (sourceIndex === destinationIndex) return; | ||||||
|  |  | ||||||
|  |       // 3. Create a new array with reordered articles: | ||||||
|  |       //    - Create a shallow copy of the current articles array. | ||||||
|  |       //      This is important for immutability and triggering re-renders. | ||||||
|  |       const newRightArticles = [...sight[language].right]; | ||||||
|  |  | ||||||
|  |       //    - Remove the dragged article from its original position. | ||||||
|  |       //      `splice` returns an array of removed items, so we destructure the first (and only) one. | ||||||
|  |       const [movedArticle] = newRightArticles.splice(sourceIndex, 1); | ||||||
|  |  | ||||||
|  |       //    - Insert the moved article into its new position. | ||||||
|  |       newRightArticles.splice(destinationIndex, 0, movedArticle); | ||||||
|  |  | ||||||
|  |       // 4. Update the store with the new order: | ||||||
|  |       //    This will typically trigger a re-render of the component with the updated list. | ||||||
|  |       updateRightArticles(newRightArticles, language); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TabPanel value={value} index={index}> |       <TabPanel value={value} index={index}> | ||||||
|         <LanguageSwitcher /> |         <LanguageSwitcher /> | ||||||
| @@ -223,22 +277,56 @@ export const CreateRightTab = observer( | |||||||
|                     > |                     > | ||||||
|                       <Typography>Предпросмотр медиа</Typography> |                       <Typography>Предпросмотр медиа</Typography> | ||||||
|                     </Box> |                     </Box> | ||||||
|  |                     <Box> | ||||||
|                     {sight[language].right.map((article, artIdx) => ( |                       <DragDropContext onDragEnd={handleDragEnd}> | ||||||
|                       <Box |                         <Droppable droppableId="articles"> | ||||||
|                         key={article.id || artIdx} // article.id should be preferred |                           {(provided) => ( | ||||||
|                         className={`w-full p-4 rounded-2xl text-sm cursor-pointer hover:bg-gray-300 transition-all duration-300 ${ |                             <Box | ||||||
|                           type === "article" && activeArticleIndex === artIdx |                               ref={provided.innerRef} | ||||||
|                             ? "bg-blue-300 font-semibold" |                               {...provided.droppableProps} | ||||||
|                             : "bg-gray-200" |                               className="flex flex-col gap-2" | ||||||
|                         }`} |                             > | ||||||
|                         onClick={() => handleDisplayArticleFromList(artIdx)} |                               {sight[language].right.length > 0 | ||||||
|                       > |                                 ? sight[language].right.map( | ||||||
|                         <Typography noWrap title={article.heading}> |                                     (article, index) => ( | ||||||
|                           {article.heading || "Без названия"} |                                       <Draggable | ||||||
|                         </Typography> |                                         key={article.id.toString()} | ||||||
|                       </Box> |                                         draggableId={article.id.toString()} | ||||||
|                     ))} |                                         index={index} | ||||||
|  |                                       > | ||||||
|  |                                         {(provided, snapshot) => ( | ||||||
|  |                                           <Box | ||||||
|  |                                             ref={provided.innerRef} | ||||||
|  |                                             {...provided.draggableProps} | ||||||
|  |                                             className={`w-full bg-gray-200 p-4 rounded-2xl text-sm cursor-pointer hover:bg-gray-300  ${ | ||||||
|  |                                               snapshot.isDragging | ||||||
|  |                                                 ? "shadow-lg" | ||||||
|  |                                                 : "" | ||||||
|  |                                             }`} | ||||||
|  |                                             onClick={() => { | ||||||
|  |                                               handleDisplayArticleFromList( | ||||||
|  |                                                 index | ||||||
|  |                                               ); | ||||||
|  |                                               setType("article"); | ||||||
|  |                                             }} | ||||||
|  |                                           > | ||||||
|  |                                             <Box {...provided.dragHandleProps}> | ||||||
|  |                                               <Typography> | ||||||
|  |                                                 {article.heading} | ||||||
|  |                                               </Typography> | ||||||
|  |                                             </Box> | ||||||
|  |                                           </Box> | ||||||
|  |                                         )} | ||||||
|  |                                       </Draggable> | ||||||
|  |                                     ) | ||||||
|  |                                   ) | ||||||
|  |                                 : null} | ||||||
|  |                               {provided.placeholder} | ||||||
|  |                             </Box> | ||||||
|  |                           )} | ||||||
|  |                         </Droppable> | ||||||
|  |                       </DragDropContext> | ||||||
|  |                     </Box> | ||||||
|                   </Box> |                   </Box> | ||||||
|                   <button |                   <button | ||||||
|                     className="w-10 h-10 bg-blue-500 rounded-full absolute bottom-5 left-5 flex items-center justify-center hover:bg-blue-600" |                     className="w-10 h-10 bg-blue-500 rounded-full absolute bottom-5 left-5 flex items-center justify-center hover:bg-blue-600" | ||||||
| @@ -273,12 +361,13 @@ export const CreateRightTab = observer( | |||||||
|  |  | ||||||
|                 {/* Main content area: Article Editor or Sight Media Preview */} |                 {/* Main content area: Article Editor or Sight Media Preview */} | ||||||
|                 {type === "article" && currentRightArticle ? ( |                 {type === "article" && currentRightArticle ? ( | ||||||
|                   <Box className="w-[80%] border border-gray-300 rounded-2xl p-3 flex flex-col gap-2 overflow-hidden"> |                   <Box className="w-[80%] border border-gray-300 p-3 flex flex-col gap-2 overflow-hidden"> | ||||||
|                     <Box className="flex justify-end gap-2 mb-1 flex-shrink-0"> |                     <Box className="flex justify-end gap-2 mb-1 flex-shrink-0"> | ||||||
|                       <Button |                       <Button | ||||||
|                         variant="outlined" |                         variant="contained" | ||||||
|                         color="warning" |                         color="primary" | ||||||
|                         size="small" |                         size="small" | ||||||
|  |                         startIcon={<Unlink color="white" size={18} />} | ||||||
|                         onClick={() => { |                         onClick={() => { | ||||||
|                           if (currentRightArticle) { |                           if (currentRightArticle) { | ||||||
|                             unlinkRightAritcle(currentRightArticle.id); // Corrected function name |                             unlinkRightAritcle(currentRightArticle.id); // Corrected function name | ||||||
| @@ -293,22 +382,9 @@ export const CreateRightTab = observer( | |||||||
|                         variant="contained" |                         variant="contained" | ||||||
|                         color="error" |                         color="error" | ||||||
|                         size="small" |                         size="small" | ||||||
|  |                         startIcon={<Trash2 size={18} />} | ||||||
|                         onClick={async () => { |                         onClick={async () => { | ||||||
|                           if ( |                           setIsDeleteModalOpen(true); | ||||||
|                             currentRightArticle && |  | ||||||
|                             window.confirm( |  | ||||||
|                               `Удалить статью "${currentRightArticle.heading}" окончательно?` |  | ||||||
|                             ) |  | ||||||
|                           ) { |  | ||||||
|                             try { |  | ||||||
|                               await deleteRightArticle(currentRightArticle.id); |  | ||||||
|                               setActiveArticleIndex(null); |  | ||||||
|                               setType("media"); |  | ||||||
|                               toast.success("Статья удалена"); |  | ||||||
|                             } catch { |  | ||||||
|                               toast.error("Не удалось удалить статью"); |  | ||||||
|                             } |  | ||||||
|                           } |  | ||||||
|                         }} |                         }} | ||||||
|                       > |                       > | ||||||
|                         Удалить |                         Удалить | ||||||
| @@ -371,38 +447,52 @@ export const CreateRightTab = observer( | |||||||
|                     </Box> |                     </Box> | ||||||
|                   </Box> |                   </Box> | ||||||
|                 ) : type === "media" ? ( |                 ) : type === "media" ? ( | ||||||
|                   <Box className="w-[80%] h-[70vh] border border-gray-300 rounded-2xl p-3 relative flex justify-center items-center"> |                   <Box className="w-[80%] border border-gray-300 rounded-2xl relative flex items-center justify-center"> | ||||||
|                     {type === "media" && ( |                     {sight.preview_media && ( | ||||||
|                       <Box className="w-[80%] border border-gray-300 rounded-2xl relative"> |                       <> | ||||||
|                         {sight.preview_media && ( |                         {type === "media" && ( | ||||||
|                           <> |                           <Box className="w-[80%] h-full  rounded-2xl relative flex items-center justify-center"> | ||||||
|                             <Box className="absolute top-4 right-4"> |                             {previewMedia && ( | ||||||
|                               <button |                               <> | ||||||
|                                 className="w-10 h-10 flex items-center justify-center" |                                 <Box className="absolute top-4 right-4  z-10"> | ||||||
|                                 onClick={unlinkPreviewMedia} |                                   <button | ||||||
|                               > |                                     className="w-10 h-10 flex items-center justify-center z-10" | ||||||
|                                 <X size={20} color="red" /> |                                     onClick={handleUnlinkPreviewMedia} | ||||||
|                               </button> |                                   > | ||||||
|                             </Box> |                                     <X size={20} color="red" /> | ||||||
|  |                                   </button> | ||||||
|  |                                 </Box> | ||||||
|  |  | ||||||
|                             <MediaViewer |                                 <Box className="w-1/2 h-1/2"> | ||||||
|                               media={{ |                                   <MediaViewer | ||||||
|                                 id: sight.preview_media || "", |                                     media={{ | ||||||
|                                 media_type: 1, |                                       id: previewMedia.id || "", | ||||||
|                                 filename: sight.preview_media || "", |                                       media_type: previewMedia.media_type, | ||||||
|                               }} |                                       filename: previewMedia.filename || "", | ||||||
|                             /> |                                     }} | ||||||
|                           </> |                                   /> | ||||||
|  |                                 </Box> | ||||||
|  |                               </> | ||||||
|  |                             )} | ||||||
|  |                             {!previewMedia && ( | ||||||
|  |                               <MediaAreaForSight | ||||||
|  |                                 onFinishUpload={(mediaId) => { | ||||||
|  |                                   linkPreviewMedia(mediaId); | ||||||
|  |                                 }} | ||||||
|  |                                 onFilesDrop={() => {}} | ||||||
|  |                               /> | ||||||
|  |                             )} | ||||||
|  |                           </Box> | ||||||
|                         )} |                         )} | ||||||
|                         {!sight.preview_media && ( |                       </> | ||||||
|                           <MediaAreaForSight |                     )} | ||||||
|                             onFinishUpload={(mediaId) => { |                     {!previewMedia && ( | ||||||
|                               linkPreviewMedia(mediaId); |                       <MediaAreaForSight | ||||||
|                             }} |                         onFinishUpload={(mediaId) => { | ||||||
|                             onFilesDrop={() => {}} |                           linkPreviewMedia(mediaId); | ||||||
|                           /> |                         }} | ||||||
|                         )} |                         onFilesDrop={() => {}} | ||||||
|                       </Box> |                       /> | ||||||
|                     )} |                     )} | ||||||
|                   </Box> |                   </Box> | ||||||
|                 ) : ( |                 ) : ( | ||||||
| @@ -417,31 +507,52 @@ export const CreateRightTab = observer( | |||||||
|  |  | ||||||
|             {/* Right Column: Live Preview */} |             {/* Right Column: Live Preview */} | ||||||
|             <Box className="w-[25%] mr-10"> |             <Box className="w-[25%] mr-10"> | ||||||
|               {type === "article" && currentRightArticle && ( |               {type === "article" && activeArticleIndex !== null && ( | ||||||
|                 <Paper |                 <Paper | ||||||
|                   className="flex-1 flex flex-col rounded-2xl" |                   className="flex-1 flex flex-col  max-w-[500px]" | ||||||
|  |                   sx={{ | ||||||
|  |                     borderRadius: "16px", | ||||||
|  |                     overflow: "hidden", | ||||||
|  |                   }} | ||||||
|                   elevation={2} |                   elevation={2} | ||||||
|                   sx={{ height: "75vh", overflow: "hidden" }} |  | ||||||
|                 > |                 > | ||||||
|                   <Box |                   <Box | ||||||
|                     className="rounded-2xl overflow-hidden" |                     className=" overflow-hidden" | ||||||
|                     sx={{ |                     sx={{ | ||||||
|                       width: "100%", |                       width: "100%", | ||||||
|                       height: "100%", |  | ||||||
|                       background: "#877361", // Theme background |                       background: "#877361", | ||||||
|  |                       borderColor: "grey.300", | ||||||
|                       display: "flex", |                       display: "flex", | ||||||
|                       flexDirection: "column", |                       flexDirection: "column", | ||||||
|                     }} |                     }} | ||||||
|                   > |                   > | ||||||
|                     {currentRightArticle.media && |                     {sight[language].right[activeArticleIndex].media.length > | ||||||
|                     currentRightArticle.media.length > 0 ? ( |                     0 ? ( | ||||||
|                       <MediaViewer media={currentRightArticle.media[0]} /> |                       <Box | ||||||
|  |                         sx={{ | ||||||
|  |                           width: "100%", | ||||||
|  |                           maxHeight: "290px", | ||||||
|  |                           flexShrink: 0, | ||||||
|  |  | ||||||
|  |                           display: "flex", | ||||||
|  |                           alignItems: "center", | ||||||
|  |                           justifyContent: "center", | ||||||
|  |                         }} | ||||||
|  |                       > | ||||||
|  |                         <MediaViewer | ||||||
|  |                           media={ | ||||||
|  |                             sight[language].right[activeArticleIndex].media[0] | ||||||
|  |                           } | ||||||
|  |                         /> | ||||||
|  |                       </Box> | ||||||
|                     ) : ( |                     ) : ( | ||||||
|                       <Box |                       <Box | ||||||
|                         sx={{ |                         sx={{ | ||||||
|                           width: "100%", |                           width: "100%", | ||||||
|                           height: 200, |                           height: 200, | ||||||
|                           flexShrink: 0, |                           flexShrink: 0, | ||||||
|  |  | ||||||
|                           backgroundColor: "rgba(0,0,0,0.1)", |                           backgroundColor: "rgba(0,0,0,0.1)", | ||||||
|                           display: "flex", |                           display: "flex", | ||||||
|                           alignItems: "center", |                           alignItems: "center", | ||||||
| @@ -451,84 +562,85 @@ export const CreateRightTab = observer( | |||||||
|                         <ImagePlus size={48} color="white" /> |                         <ImagePlus size={48} color="white" /> | ||||||
|                       </Box> |                       </Box> | ||||||
|                     )} |                     )} | ||||||
|  |  | ||||||
|                     <Box |                     <Box | ||||||
|                       sx={{ |                       sx={{ | ||||||
|                         width: "100%", |                         p: 1, | ||||||
|                         minHeight: "70px", // Fixed height for heading container |                         wordBreak: "break-word", | ||||||
|                         background: "#877361", // Consistent with theme |                         fontSize: "24px", | ||||||
|                         display: "flex", |                         fontWeight: 700, | ||||||
|                         flexShrink: 0, |                         lineHeight: "120%", | ||||||
|                         flex: 1, |                         backdropFilter: "blur(12px)", | ||||||
|                         alignItems: "center", |                         boxShadow: | ||||||
|                         borderBottom: "1px solid rgba(255,255,255,0.1)", |                           "inset 4px 4px 12px 0 rgba(255,255,255,0.12)", | ||||||
|                         px: 2, |                         background: | ||||||
|                         py: 1, |                           "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|                       }} |                       }} | ||||||
|                     > |                     > | ||||||
|                       <Typography |                       <Typography variant="h6" color="white"> | ||||||
|                         variant="h6" |                         {sight[language].right[activeArticleIndex].heading || | ||||||
|                         color="white" |                           "Выберите статью"} | ||||||
|                         noWrap |  | ||||||
|                         title={currentRightArticle.heading} |  | ||||||
|                       > |  | ||||||
|                         {currentRightArticle.heading || "Заголовок"} |  | ||||||
|                       </Typography> |                       </Typography> | ||||||
|                     </Box> |                     </Box> | ||||||
|  |  | ||||||
|                     <Box |                     <Box | ||||||
|                       sx={{ |                       sx={{ | ||||||
|                         px: 2, |                         padding: 1, | ||||||
|                         py: 1, |                         minHeight: "200px", | ||||||
|  |                         maxHeight: "300px", | ||||||
|  |                         overflowY: "scroll", | ||||||
|  |                         background: | ||||||
|  |                           "rgba(179, 165, 152, 0.4), linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|  |  | ||||||
|                         flexGrow: 1, |                         flexGrow: 1, | ||||||
|                         overflowY: "auto", |  | ||||||
|                         backgroundColor: "#877361", |  | ||||||
|                         color: "white", |  | ||||||
|                         "&::-webkit-scrollbar": { width: "8px" }, |  | ||||||
|                         "&::-webkit-scrollbar-thumb": { |  | ||||||
|                           backgroundColor: "rgba(255,255,255,0.3)", |  | ||||||
|                           borderRadius: "4px", |  | ||||||
|                         }, |  | ||||||
|                       }} |                       }} | ||||||
|                     > |                     > | ||||||
|                       {currentRightArticle.body ? ( |                       {sight[language].right[activeArticleIndex].body ? ( | ||||||
|                         <ReactMarkdownComponent |                         <ReactMarkdownComponent | ||||||
|                           value={currentRightArticle.body} |                           value={sight[language].right[activeArticleIndex].body} | ||||||
|                         /> |                         /> | ||||||
|                       ) : ( |                       ) : ( | ||||||
|                         <Typography |                         <Typography | ||||||
|                           color="rgba(255,255,255,0.7)" |                           color="rgba(255,255,255,0.7)" | ||||||
|                           sx={{ textAlign: "center", mt: 4 }} |                           sx={{ textAlign: "center", mt: 4 }} | ||||||
|                         > |                         > | ||||||
|                           Содержимое статьи... |                           Предпросмотр статьи появится здесь | ||||||
|                         </Typography> |                         </Typography> | ||||||
|                       )} |                       )} | ||||||
|                     </Box> |                     </Box> | ||||||
|                   </Box> |                     <Box | ||||||
|                 </Paper> |                       sx={{ | ||||||
|               )} |                         p: 2, | ||||||
|               {/* Optional: Preview for sight.preview_media when type === "media" */} |                         display: "flex", | ||||||
|               {type === "media" && sight.preview_media && ( |                         justifyContent: "space-between", | ||||||
|                 <Paper |                         fontSize: "24px", | ||||||
|                   className="flex-1 flex flex-col rounded-2xl" |                         fontWeight: 700, | ||||||
|                   elevation={2} |                         lineHeight: "120%", | ||||||
|                   sx={{ height: "75vh", overflow: "hidden" }} |                         flexWrap: "wrap", | ||||||
|                 > |  | ||||||
|                   <Box |                         gap: 1, | ||||||
|                     sx={{ |                         backdropFilter: "blur(12px)", | ||||||
|                       width: "100%", |                         boxShadow: | ||||||
|                       height: "100%", |                           "inset 4px 4px 12px 0 rgba(255,255,255,0.12)", | ||||||
|                       background: "#877361", |                         background: | ||||||
|                       display: "flex", |                           "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|                       alignItems: "center", |  | ||||||
|                       justifyContent: "center", |  | ||||||
|                     }} |  | ||||||
|                   > |  | ||||||
|                     <MediaViewer |  | ||||||
|                       media={{ |  | ||||||
|                         id: sight.preview_media, |  | ||||||
|                         filename: sight.preview_media, |  | ||||||
|                         media_type: 1, |  | ||||||
|                       }} |                       }} | ||||||
|                     /> |                     > | ||||||
|  |                       {sight[language].right.length > 0 && | ||||||
|  |                         sight[language].right.map((article, index) => ( | ||||||
|  |                           <button | ||||||
|  |                             className={`inline-block text-left text-xs text-white ${ | ||||||
|  |                               activeArticleIndex === index ? "underline" : "" | ||||||
|  |                             }`} | ||||||
|  |                             onClick={() => { | ||||||
|  |                               setActiveArticleIndex(index); | ||||||
|  |                               setType("article"); | ||||||
|  |                             }} | ||||||
|  |                           > | ||||||
|  |                             {article.heading} | ||||||
|  |                           </button> | ||||||
|  |                         ))} | ||||||
|  |                     </Box> | ||||||
|                   </Box> |                   </Box> | ||||||
|                 </Paper> |                 </Paper> | ||||||
|               )} |               )} | ||||||
| @@ -539,17 +651,15 @@ export const CreateRightTab = observer( | |||||||
|           <Box |           <Box | ||||||
|             sx={{ |             sx={{ | ||||||
|               position: "absolute", |               position: "absolute", | ||||||
|               bottom: 0, |               bottom: "-20px", | ||||||
|               left: 0, // ensure it spans from left |               left: 0, // ensure it spans from left | ||||||
|               right: 0, |               right: 0, | ||||||
|               padding: 2, |               padding: 2, | ||||||
|               backgroundColor: "background.paper", |               backgroundColor: "background.paper", | ||||||
|               borderTop: "1px solid", // Add a subtle top border |  | ||||||
|               borderColor: "divider", // Use theme's divider color |  | ||||||
|               width: "100%", |               width: "100%", | ||||||
|               display: "flex", |               display: "flex", | ||||||
|               justifyContent: "flex-end", |               justifyContent: "flex-end", | ||||||
|               boxShadow: "0 -2px 5px rgba(0,0,0,0.1)", // Optional shadow |  | ||||||
|             }} |             }} | ||||||
|           > |           > | ||||||
|             <Button |             <Button | ||||||
| @@ -557,8 +667,9 @@ export const CreateRightTab = observer( | |||||||
|               color="success" |               color="success" | ||||||
|               onClick={handleSave} |               onClick={handleSave} | ||||||
|               size="large" |               size="large" | ||||||
|  |               startIcon={<Save color="white" size={18} />} | ||||||
|             > |             > | ||||||
|               Сохранить достопримечательность |               Сохранить | ||||||
|             </Button> |             </Button> | ||||||
|           </Box> |           </Box> | ||||||
|         </Box> |         </Box> | ||||||
| @@ -588,6 +699,20 @@ export const CreateRightTab = observer( | |||||||
|           }} |           }} | ||||||
|           onSelectMedia={handleMediaSelectedFromDialog} |           onSelectMedia={handleMediaSelectedFromDialog} | ||||||
|         /> |         /> | ||||||
|  |         <DeleteModal | ||||||
|  |           open={isDeleteModalOpen} | ||||||
|  |           onDelete={async () => { | ||||||
|  |             try { | ||||||
|  |               await deleteRightArticle(currentRightArticle?.id || 0); | ||||||
|  |               setActiveArticleIndex(null); | ||||||
|  |               setType("media"); | ||||||
|  |               toast.success("Статья удалена"); | ||||||
|  |             } catch { | ||||||
|  |               toast.error("Не удалось удалить статью"); | ||||||
|  |             } | ||||||
|  |           }} | ||||||
|  |           onCancel={() => setIsDeleteModalOpen(false)} | ||||||
|  |         /> | ||||||
|       </TabPanel> |       </TabPanel> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -18,8 +18,10 @@ import { | |||||||
|   SightLanguageInfo, |   SightLanguageInfo, | ||||||
|   SightCommonInfo, |   SightCommonInfo, | ||||||
|   UploadMediaDialog, |   UploadMediaDialog, | ||||||
|  |   MEDIA_TYPE_VALUES, | ||||||
| } from "@shared"; | } from "@shared"; | ||||||
| import { ImageUploadCard, LanguageSwitcher } from "@widgets"; | import { ImageUploadCard, LanguageSwitcher } from "@widgets"; | ||||||
|  | import { Save } from "lucide-react"; | ||||||
|  |  | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { useEffect, useState } from "react"; | import { useEffect, useState } from "react"; | ||||||
| @@ -335,6 +337,7 @@ export const InformationTab = observer( | |||||||
|               <Button |               <Button | ||||||
|                 variant="contained" |                 variant="contained" | ||||||
|                 color="success" |                 color="success" | ||||||
|  |                 startIcon={<Save color="white" size={18} />} | ||||||
|                 onClick={async () => { |                 onClick={async () => { | ||||||
|                   await updateSight(); |                   await updateSight(); | ||||||
|                   toast.success("Достопримечательность сохранена"); |                   toast.success("Достопримечательность сохранена"); | ||||||
| @@ -371,6 +374,13 @@ export const InformationTab = observer( | |||||||
|             setActiveMenuType(null); |             setActiveMenuType(null); | ||||||
|           }} |           }} | ||||||
|           onSelectMedia={handleMediaSelect} |           onSelectMedia={handleMediaSelect} | ||||||
|  |           mediaType={ | ||||||
|  |             activeMenuType | ||||||
|  |               ? MEDIA_TYPE_VALUES[ | ||||||
|  |                   activeMenuType as keyof typeof MEDIA_TYPE_VALUES | ||||||
|  |                 ] | ||||||
|  |               : undefined | ||||||
|  |           } | ||||||
|         /> |         /> | ||||||
|  |  | ||||||
|         <UploadMediaDialog |         <UploadMediaDialog | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import { | |||||||
|   editSightStore, |   editSightStore, | ||||||
|   SelectArticleModal, |   SelectArticleModal, | ||||||
|   UploadMediaDialog, |   UploadMediaDialog, | ||||||
|  |   Language, | ||||||
| } from "@shared"; | } from "@shared"; | ||||||
| import { | import { | ||||||
|   LanguageSwitcher, |   LanguageSwitcher, | ||||||
| @@ -15,8 +16,16 @@ import { | |||||||
|   ReactMarkdownEditor, |   ReactMarkdownEditor, | ||||||
|   MediaArea, |   MediaArea, | ||||||
|   MediaViewer, |   MediaViewer, | ||||||
|  |   DeleteModal, | ||||||
| } from "@widgets"; | } from "@widgets"; | ||||||
| import { Trash2, ImagePlus } from "lucide-react"; | import { | ||||||
|  |   Trash2, | ||||||
|  |   ImagePlus, | ||||||
|  |   Unlink, | ||||||
|  |   Plus, | ||||||
|  |   MousePointer, | ||||||
|  |   Save, | ||||||
|  | } from "lucide-react"; | ||||||
| import { useState, useCallback } from "react"; | import { useState, useCallback } from "react"; | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { toast } from "react-toastify"; | import { toast } from "react-toastify"; | ||||||
| @@ -40,12 +49,18 @@ export const LeftWidgetTab = observer( | |||||||
|  |  | ||||||
|     const { language } = languageStore; |     const { language } = languageStore; | ||||||
|     const data = sight[language]; |     const data = sight[language]; | ||||||
|  |     const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); | ||||||
|  |  | ||||||
|     const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] = |     const [isSelectMediaDialogOpen, setIsSelectMediaDialogOpen] = | ||||||
|       useState(false); |       useState(false); | ||||||
|     const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] = |     const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] = | ||||||
|       useState(false); |       useState(false); | ||||||
|  |  | ||||||
|  |     const handleDeleteLeftArticle = useCallback(() => { | ||||||
|  |       deleteLeftArticle(sight.common.left_article); | ||||||
|  |       setIsDeleteModalOpen(false); | ||||||
|  |     }, [deleteLeftArticle, sight.common.left_article]); | ||||||
|  |  | ||||||
|     const handleMediaSelected = useCallback( |     const handleMediaSelected = useCallback( | ||||||
|       async (media: { |       async (media: { | ||||||
|         id: string; |         id: string; | ||||||
| @@ -130,6 +145,7 @@ export const LeftWidgetTab = observer( | |||||||
|                       color="primary" |                       color="primary" | ||||||
|                       size="small" |                       size="small" | ||||||
|                       style={{ transition: "0" }} |                       style={{ transition: "0" }} | ||||||
|  |                       startIcon={<Unlink size={18} />} | ||||||
|                       onClick={() => { |                       onClick={() => { | ||||||
|                         unlinkLeftArticle(); |                         unlinkLeftArticle(); | ||||||
|                         toast.success("Статья откреплена"); |                         toast.success("Статья откреплена"); | ||||||
| @@ -144,8 +160,7 @@ export const LeftWidgetTab = observer( | |||||||
|                       startIcon={<Trash2 size={18} />} |                       startIcon={<Trash2 size={18} />} | ||||||
|                       size="small" |                       size="small" | ||||||
|                       onClick={() => { |                       onClick={() => { | ||||||
|                         deleteLeftArticle(sight.common.left_article); |                         setIsDeleteModalOpen(true); | ||||||
|                         toast.success("Статья откреплена"); |  | ||||||
|                       }} |                       }} | ||||||
|                     > |                     > | ||||||
|                       Удалить |                       Удалить | ||||||
| @@ -157,6 +172,7 @@ export const LeftWidgetTab = observer( | |||||||
|                       variant="contained" |                       variant="contained" | ||||||
|                       color="primary" |                       color="primary" | ||||||
|                       size="small" |                       size="small" | ||||||
|  |                       startIcon={<MousePointer color="white" size={18} />} | ||||||
|                       onClick={() => setIsSelectArticleDialogOpen(true)} |                       onClick={() => setIsSelectArticleDialogOpen(true)} | ||||||
|                     > |                     > | ||||||
|                       Выбрать статью |                       Выбрать статью | ||||||
| @@ -166,6 +182,7 @@ export const LeftWidgetTab = observer( | |||||||
|                       color="primary" |                       color="primary" | ||||||
|                       size="small" |                       size="small" | ||||||
|                       style={{ transition: "0" }} |                       style={{ transition: "0" }} | ||||||
|  |                       startIcon={<Plus color="white" size={18} />} | ||||||
|                       onClick={() => { |                       onClick={() => { | ||||||
|                         createLeftArticle(); |                         createLeftArticle(); | ||||||
|                         toast.success("Статья создана"); |                         toast.success("Статья создана"); | ||||||
| @@ -234,7 +251,8 @@ export const LeftWidgetTab = observer( | |||||||
|                     flex: 1, |                     flex: 1, | ||||||
|                     display: "flex", |                     display: "flex", | ||||||
|                     flexDirection: "column", |                     flexDirection: "column", | ||||||
|                     gap: 1.5, |                     maxWidth: "320px", | ||||||
|  |                     gap: 0.5, | ||||||
|                   }} |                   }} | ||||||
|                 > |                 > | ||||||
|                   <Paper |                   <Paper | ||||||
| @@ -242,10 +260,9 @@ export const LeftWidgetTab = observer( | |||||||
|                     sx={{ |                     sx={{ | ||||||
|                       width: "100%", |                       width: "100%", | ||||||
|                       minWidth: 320, |                       minWidth: 320, | ||||||
|                       maxWidth: 400, |  | ||||||
|                       height: "auto", |                       background: | ||||||
|                       minHeight: 500, |                         "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|                       backgroundColor: "#877361", |  | ||||||
|                       overflowY: "auto", |                       overflowY: "auto", | ||||||
|                       padding: 0, |                       padding: 0, | ||||||
|                       display: "flex", |                       display: "flex", | ||||||
| @@ -255,11 +272,10 @@ export const LeftWidgetTab = observer( | |||||||
|                     <Box |                     <Box | ||||||
|                       sx={{ |                       sx={{ | ||||||
|                         width: "100%", |                         width: "100%", | ||||||
|                         height: 200, |                         height: 175, | ||||||
|                         backgroundColor: "grey.300", |  | ||||||
|                         display: "flex", |                         display: "flex", | ||||||
|                         alignItems: "center", |                         alignItems: "center", | ||||||
|                         justifyContent: "center", |                         padding: "3px", | ||||||
|                       }} |                       }} | ||||||
|                     > |                     > | ||||||
|                       {data.left.media.length > 0 ? ( |                       {data.left.media.length > 0 ? ( | ||||||
| @@ -277,24 +293,50 @@ export const LeftWidgetTab = observer( | |||||||
|  |  | ||||||
|                     <Box |                     <Box | ||||||
|                       sx={{ |                       sx={{ | ||||||
|                         backgroundColor: "#877361", |                         background: | ||||||
|  |                           "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|                         color: "white", |                         color: "white", | ||||||
|                         padding: 1.5, |                         margin: "5px 0px 5px 0px", | ||||||
|  |                         display: "flex", | ||||||
|  |                         flexDirection: "column", | ||||||
|  |                         gap: 1, | ||||||
|  |                         padding: 1, | ||||||
|                       }} |                       }} | ||||||
|                     > |                     > | ||||||
|                       <Typography |                       <Typography | ||||||
|                         variant="h5" |                         variant="h5" | ||||||
|                         component="h2" |                         component="h2" | ||||||
|                         sx={{ wordBreak: "break-word" }} |                         sx={{ | ||||||
|  |                           wordBreak: "break-word", | ||||||
|  |                           fontSize: "24px", | ||||||
|  |                           fontWeight: 700, | ||||||
|  |                           lineHeight: "120%", | ||||||
|  |                         }} | ||||||
|                       > |                       > | ||||||
|                         {data?.left?.heading || "Название информации"} |                         {data?.left?.heading || "Название информации"} | ||||||
|                       </Typography> |                       </Typography> | ||||||
|  |                       <Typography | ||||||
|  |                         variant="h6" | ||||||
|  |                         component="h2" | ||||||
|  |                         sx={{ | ||||||
|  |                           wordBreak: "break-word", | ||||||
|  |                           fontSize: "18px", | ||||||
|  |  | ||||||
|  |                           lineHeight: "120%", | ||||||
|  |                         }} | ||||||
|  |                       > | ||||||
|  |                         {sight[language as Language].address} | ||||||
|  |                       </Typography> | ||||||
|                     </Box> |                     </Box> | ||||||
|  |  | ||||||
|                     {data?.left?.body && ( |                     {data?.left?.body && ( | ||||||
|                       <Box |                       <Box | ||||||
|                         sx={{ |                         sx={{ | ||||||
|                           padding: 2, |                           padding: 1, | ||||||
|  |                           maxHeight: "300px", | ||||||
|  |                           overflowY: "scroll", | ||||||
|  |                           background: | ||||||
|  |                             "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|                           flexGrow: 1, |                           flexGrow: 1, | ||||||
|                         }} |                         }} | ||||||
|                       > |                       > | ||||||
| @@ -310,6 +352,7 @@ export const LeftWidgetTab = observer( | |||||||
|               <Button |               <Button | ||||||
|                 variant="contained" |                 variant="contained" | ||||||
|                 color="success" |                 color="success" | ||||||
|  |                 startIcon={<Save color="white" size={18} />} | ||||||
|                 onClick={async () => { |                 onClick={async () => { | ||||||
|                   await updateSight(); |                   await updateSight(); | ||||||
|                   toast.success("Достопримечательность сохранена"); |                   toast.success("Достопримечательность сохранена"); | ||||||
| @@ -339,6 +382,11 @@ export const LeftWidgetTab = observer( | |||||||
|           onClose={handleCloseArticleDialog} |           onClose={handleCloseArticleDialog} | ||||||
|           onSelectArticle={handleSelectArticle} |           onSelectArticle={handleSelectArticle} | ||||||
|         /> |         /> | ||||||
|  |         <DeleteModal | ||||||
|  |           open={isDeleteModalOpen} | ||||||
|  |           onDelete={handleDeleteLeftArticle} | ||||||
|  |           onCancel={() => setIsDeleteModalOpen(false)} | ||||||
|  |         /> | ||||||
|       </> |       </> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import { | |||||||
|   TextField, |   TextField, | ||||||
| } from "@mui/material"; | } from "@mui/material"; | ||||||
| import { | import { | ||||||
|  |   authInstance, | ||||||
|   BackButton, |   BackButton, | ||||||
|   editSightStore, |   editSightStore, | ||||||
|   languageStore, |   languageStore, | ||||||
| @@ -17,17 +18,24 @@ import { | |||||||
|   UploadMediaDialog, |   UploadMediaDialog, | ||||||
| } from "@shared"; | } from "@shared"; | ||||||
| import { | import { | ||||||
|  |   DeleteModal, | ||||||
|   LanguageSwitcher, |   LanguageSwitcher, | ||||||
|   MediaArea, |   MediaArea, | ||||||
|   MediaAreaForSight, |   MediaAreaForSight, | ||||||
|   ReactMarkdownComponent, |   ReactMarkdownComponent, | ||||||
|   ReactMarkdownEditor, |   ReactMarkdownEditor, | ||||||
| } from "@widgets"; | } from "@widgets"; | ||||||
| import { ImagePlus, Plus, X } from "lucide-react"; | import { ImagePlus, Plus, Save, Trash2, Unlink, X } from "lucide-react"; | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { useEffect, useState } from "react"; | import { useEffect, useState } from "react"; | ||||||
| import { toast } from "react-toastify"; | import { toast } from "react-toastify"; | ||||||
| import { MediaViewer } from "../../MediaViewer/index"; | import { MediaViewer } from "../../MediaViewer/index"; | ||||||
|  | import { | ||||||
|  |   DragDropContext, | ||||||
|  |   Droppable, | ||||||
|  |   Draggable, | ||||||
|  |   DropResult, | ||||||
|  | } from "@hello-pangea/dnd"; | ||||||
|  |  | ||||||
| export const RightWidgetTab = observer( | export const RightWidgetTab = observer( | ||||||
|   ({ value, index }: { value: number; index: number }) => { |   ({ value, index }: { value: number; index: number }) => { | ||||||
| @@ -47,8 +55,28 @@ export const RightWidgetTab = observer( | |||||||
|       createLinkWithRightArticle, |       createLinkWithRightArticle, | ||||||
|       setFileToUpload, |       setFileToUpload, | ||||||
|       createNewRightArticle, |       createNewRightArticle, | ||||||
|  |       updateRightArticles, | ||||||
|     } = editSightStore; |     } = editSightStore; | ||||||
|  |  | ||||||
|  |     const [previewMedia, setPreviewMedia] = useState<any | null>(null); | ||||||
|  |  | ||||||
|  |     useEffect(() => { | ||||||
|  |       const fetchPreviewMedia = async () => { | ||||||
|  |         if (sight.common.preview_media) { | ||||||
|  |           const response = await authInstance.get( | ||||||
|  |             `/media/${sight.common.preview_media}` | ||||||
|  |           ); | ||||||
|  |           setPreviewMedia(response.data); | ||||||
|  |         } | ||||||
|  |       }; | ||||||
|  |       fetchPreviewMedia(); | ||||||
|  |     }, [sight.common.preview_media]); | ||||||
|  |  | ||||||
|  |     const handleUnlinkPreviewMedia = () => { | ||||||
|  |       unlinkPreviewMedia(); | ||||||
|  |       setPreviewMedia(null); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     const [uploadMediaOpen, setUploadMediaOpen] = useState(false); |     const [uploadMediaOpen, setUploadMediaOpen] = useState(false); | ||||||
|     const { language } = languageStore; |     const { language } = languageStore; | ||||||
|     const [type, setType] = useState<"article" | "media">("media"); |     const [type, setType] = useState<"article" | "media">("media"); | ||||||
| @@ -67,8 +95,15 @@ export const RightWidgetTab = observer( | |||||||
|     ); |     ); | ||||||
|     const [isSelectModalOpen, setIsSelectModalOpen] = useState(false); |     const [isSelectModalOpen, setIsSelectModalOpen] = useState(false); | ||||||
|     const [isSelectMediaModalOpen, setIsSelectMediaModalOpen] = useState(false); |     const [isSelectMediaModalOpen, setIsSelectMediaModalOpen] = useState(false); | ||||||
|  |     const [isDeleteArticleModalOpen, setIsDeleteArticleModalOpen] = | ||||||
|  |       useState(false); | ||||||
|     const open = Boolean(anchorEl); |     const open = Boolean(anchorEl); | ||||||
|  |  | ||||||
|  |     const handleDeleteArticle = () => { | ||||||
|  |       deleteRightArticle(sight[language].right[activeArticleIndex || 0].id); | ||||||
|  |       setActiveArticleIndex(null); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { |     const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { | ||||||
|       setAnchorEl(event.currentTarget); |       setAnchorEl(event.currentTarget); | ||||||
|     }; |     }; | ||||||
| @@ -120,6 +155,36 @@ export const RightWidgetTab = observer( | |||||||
|       console.log(sight[language].right); |       console.log(sight[language].right); | ||||||
|     }, [sight[language].right]); |     }, [sight[language].right]); | ||||||
|  |  | ||||||
|  |     const handleDragEnd = (result: DropResult) => { | ||||||
|  |       const { source, destination } = result; | ||||||
|  |  | ||||||
|  |       // 1. Guard clause: If dropped outside any droppable area, do nothing. | ||||||
|  |       if (!destination) return; | ||||||
|  |  | ||||||
|  |       // Extract source and destination indices | ||||||
|  |       const sourceIndex = source.index; | ||||||
|  |       const destinationIndex = destination.index; | ||||||
|  |  | ||||||
|  |       // 2. Guard clause: If dropped in the same position, do nothing. | ||||||
|  |       if (sourceIndex === destinationIndex) return; | ||||||
|  |  | ||||||
|  |       // 3. Create a new array with reordered articles: | ||||||
|  |       //    - Create a shallow copy of the current articles array. | ||||||
|  |       //      This is important for immutability and triggering re-renders. | ||||||
|  |       const newRightArticles = [...sight[language].right]; | ||||||
|  |  | ||||||
|  |       //    - Remove the dragged article from its original position. | ||||||
|  |       //      `splice` returns an array of removed items, so we destructure the first (and only) one. | ||||||
|  |       const [movedArticle] = newRightArticles.splice(sourceIndex, 1); | ||||||
|  |  | ||||||
|  |       //    - Insert the moved article into its new position. | ||||||
|  |       newRightArticles.splice(destinationIndex, 0, movedArticle); | ||||||
|  |  | ||||||
|  |       // 4. Update the store with the new order: | ||||||
|  |       //    This will typically trigger a re-render of the component with the updated list. | ||||||
|  |       updateRightArticles(newRightArticles, language); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|       <TabPanel value={value} index={index}> |       <TabPanel value={value} index={index}> | ||||||
|         <LanguageSwitcher /> |         <LanguageSwitcher /> | ||||||
| @@ -140,26 +205,61 @@ export const RightWidgetTab = observer( | |||||||
|             <Box className="flex flex-col w-[75%] gap-2"> |             <Box className="flex flex-col w-[75%] gap-2"> | ||||||
|               <Box className="w-full flex gap-2"> |               <Box className="w-full flex gap-2"> | ||||||
|                 <Box className="relative w-[20%] h-[70vh] flex flex-col rounded-2xl overflow-y-auto gap-3 border border-gray-300 p-3"> |                 <Box className="relative w-[20%] h-[70vh] flex flex-col rounded-2xl overflow-y-auto gap-3 border border-gray-300 p-3"> | ||||||
|                   <Box className="flex flex-col gap-3 max-h-[60vh] overflow-y-auto "> |                   <Box className="flex flex-col gap-3 max-h-[60vh] overflow-y-auto"> | ||||||
|                     <Box |                     <Box | ||||||
|                       onClick={() => setType("media")} |                       onClick={() => setType("media")} | ||||||
|                       className="w-full  bg-green-200 p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300" |                       className="w-full bg-green-200 p-4 rounded-2xl cursor-pointer text-sm hover:bg-gray-300 transition-all duration-300" | ||||||
|                     > |                     > | ||||||
|                       <Typography>Предпросмотр медиа</Typography> |                       <Typography>Предпросмотр медиа</Typography> | ||||||
|                     </Box> |                     </Box> | ||||||
|                     {sight[language].right.length > 0 && |                     <Box> | ||||||
|                       sight[language].right.map((article, index) => ( |                       <DragDropContext onDragEnd={handleDragEnd}> | ||||||
|                         <Box |                         <Droppable droppableId="articles"> | ||||||
|                           key={index} |                           {(provided) => ( | ||||||
|                           className="w-full bg-gray-200 p-4 rounded-2xl text-sm cursor-pointer hover:bg-gray-300 transition-all duration-300" |                             <Box | ||||||
|                           onClick={() => { |                               ref={provided.innerRef} | ||||||
|                             handleSelectArticle(index); |                               {...provided.droppableProps} | ||||||
|                             setType("article"); |                               className="flex flex-col gap-2" | ||||||
|                           }} |                             > | ||||||
|                         > |                               {sight[language].right.length > 0 | ||||||
|                           <Typography>{article.heading}</Typography> |                                 ? sight[language].right.map( | ||||||
|                         </Box> |                                     (article, index) => ( | ||||||
|                       ))} |                                       <Draggable | ||||||
|  |                                         key={article.id.toString()} | ||||||
|  |                                         draggableId={article.id.toString()} | ||||||
|  |                                         index={index} | ||||||
|  |                                       > | ||||||
|  |                                         {(provided, snapshot) => ( | ||||||
|  |                                           <Box | ||||||
|  |                                             ref={provided.innerRef} | ||||||
|  |                                             {...provided.draggableProps} | ||||||
|  |                                             className={`w-full bg-gray-200 p-4 rounded-2xl text-sm cursor-pointer hover:bg-gray-300  ${ | ||||||
|  |                                               snapshot.isDragging | ||||||
|  |                                                 ? "shadow-lg" | ||||||
|  |                                                 : "" | ||||||
|  |                                             }`} | ||||||
|  |                                             onClick={() => { | ||||||
|  |                                               handleSelectArticle(index); | ||||||
|  |                                               setType("article"); | ||||||
|  |                                             }} | ||||||
|  |                                           > | ||||||
|  |                                             <Box {...provided.dragHandleProps}> | ||||||
|  |                                               <Typography> | ||||||
|  |                                                 {article.heading} | ||||||
|  |                                               </Typography> | ||||||
|  |                                             </Box> | ||||||
|  |                                           </Box> | ||||||
|  |                                         )} | ||||||
|  |                                       </Draggable> | ||||||
|  |                                     ) | ||||||
|  |                                   ) | ||||||
|  |                                 : null} | ||||||
|  |                               {provided.placeholder} | ||||||
|  |                             </Box> | ||||||
|  |                           )} | ||||||
|  |                         </Droppable> | ||||||
|  |                       </DragDropContext> | ||||||
|  |                     </Box> | ||||||
|                   </Box> |                   </Box> | ||||||
|                   <button |                   <button | ||||||
|                     className="w-10 h-10 bg-blue-500 rounded-full absolute bottom-5 left-5 flex items-center justify-center" |                     className="w-10 h-10 bg-blue-500 rounded-full absolute bottom-5 left-5 flex items-center justify-center" | ||||||
| @@ -187,13 +287,14 @@ export const RightWidgetTab = observer( | |||||||
|                 </Box> |                 </Box> | ||||||
|  |  | ||||||
|                 {type === "article" && ( |                 {type === "article" && ( | ||||||
|                   <Box className="w-[80%] border border-gray-300 rounded-2xl p-3"> |                   <Box className="w-[80%] border border-gray-300  p-3"> | ||||||
|                     {activeArticleIndex !== null && ( |                     {activeArticleIndex !== null && ( | ||||||
|                       <> |                       <> | ||||||
|                         <Box className="flex justify-end gap-2 mb-3"> |                         <Box className="flex justify-end gap-2 mb-3"> | ||||||
|                           <Button |                           <Button | ||||||
|                             variant="contained" |                             variant="contained" | ||||||
|                             color="primary" |                             color="primary" | ||||||
|  |                             startIcon={<Unlink color="white" size={18} />} | ||||||
|                             onClick={() => { |                             onClick={() => { | ||||||
|                               unlinkRightArticle( |                               unlinkRightArticle( | ||||||
|                                 sight[language].right[activeArticleIndex].id |                                 sight[language].right[activeArticleIndex].id | ||||||
| @@ -205,12 +306,10 @@ export const RightWidgetTab = observer( | |||||||
|                           </Button> |                           </Button> | ||||||
|                           <Button |                           <Button | ||||||
|                             variant="contained" |                             variant="contained" | ||||||
|                             color="success" |                             color="error" | ||||||
|  |                             startIcon={<Trash2 size={18} />} | ||||||
|                             onClick={() => { |                             onClick={() => { | ||||||
|                               deleteRightArticle( |                               setIsDeleteArticleModalOpen(true); | ||||||
|                                 sight[language].right[activeArticleIndex].id |  | ||||||
|                               ); |  | ||||||
|                               setActiveArticleIndex(null); |  | ||||||
|                             }} |                             }} | ||||||
|                           > |                           > | ||||||
|                             Удалить |                             Удалить | ||||||
| @@ -285,31 +384,63 @@ export const RightWidgetTab = observer( | |||||||
|                   <Box className="w-[80%] border border-gray-300 rounded-2xl relative"> |                   <Box className="w-[80%] border border-gray-300 rounded-2xl relative"> | ||||||
|                     {sight.common.preview_media && ( |                     {sight.common.preview_media && ( | ||||||
|                       <> |                       <> | ||||||
|                         <Box className="absolute top-4 right-4"> |                         {type === "media" && ( | ||||||
|                           <button |                           <Box className="w-[80%] h-full  rounded-2xl relative flex items-center justify-center"> | ||||||
|                             className="w-10 h-10 flex items-center justify-center" |                             {previewMedia && ( | ||||||
|                             onClick={unlinkPreviewMedia} |                               <> | ||||||
|                           > |                                 <Box className="absolute top-4 right-4  z-10"> | ||||||
|                             <X size={20} color="red" /> |                                   <button | ||||||
|                           </button> |                                     className="w-10 h-10 flex items-center justify-center z-10" | ||||||
|                         </Box> |                                     onClick={handleUnlinkPreviewMedia} | ||||||
|  |                                   > | ||||||
|  |                                     <X size={20} color="red" /> | ||||||
|  |                                   </button> | ||||||
|  |                                 </Box> | ||||||
|  |  | ||||||
|                         <MediaViewer |                                 <Box className="w-1/2 h-1/2"> | ||||||
|                           media={{ |                                   <MediaViewer | ||||||
|                             id: sight.common.preview_media || "", |                                     media={{ | ||||||
|                             media_type: 1, |                                       id: previewMedia.id || "", | ||||||
|                             filename: sight.common.preview_media || "", |                                       media_type: previewMedia.media_type, | ||||||
|                           }} |                                       filename: previewMedia.filename || "", | ||||||
|                         /> |                                     }} | ||||||
|  |                                   /> | ||||||
|  |                                 </Box> | ||||||
|  |                               </> | ||||||
|  |                             )} | ||||||
|  |                             {!previewMedia && ( | ||||||
|  |                               <MediaAreaForSight | ||||||
|  |                                 onFinishUpload={(mediaId) => { | ||||||
|  |                                   linkPreviewMedia(mediaId); | ||||||
|  |                                 }} | ||||||
|  |                                 onFilesDrop={() => {}} | ||||||
|  |                               /> | ||||||
|  |                             )} | ||||||
|  |                           </Box> | ||||||
|  |                         )} | ||||||
|                       </> |                       </> | ||||||
|                     )} |                     )} | ||||||
|  |  | ||||||
|                     {!sight.common.preview_media && ( |                     {!sight.common.preview_media && ( | ||||||
|                       <MediaAreaForSight |                       <Box className="w-full h-full flex justify-center items-center"> | ||||||
|                         onFinishUpload={(mediaId) => { |                         <Box | ||||||
|                           linkPreviewMedia(mediaId); |                           sx={{ | ||||||
|                         }} |                             maxWidth: "500px", | ||||||
|                         onFilesDrop={() => {}} |                             maxHeight: "100%", | ||||||
|                       /> |                             display: "flex", | ||||||
|  |                             flexGrow: 1, | ||||||
|  |                             margin: "0 auto", | ||||||
|  |                             justifyContent: "center", | ||||||
|  |                           }} | ||||||
|  |                         > | ||||||
|  |                           <MediaAreaForSight | ||||||
|  |                             onFinishUpload={(mediaId) => { | ||||||
|  |                               linkPreviewMedia(mediaId); | ||||||
|  |                             }} | ||||||
|  |                             onFilesDrop={() => {}} | ||||||
|  |                           /> | ||||||
|  |                         </Box> | ||||||
|  |                       </Box> | ||||||
|                     )} |                     )} | ||||||
|                   </Box> |                   </Box> | ||||||
|                 )} |                 )} | ||||||
| @@ -320,14 +451,18 @@ export const RightWidgetTab = observer( | |||||||
|               <Box className="w-[25%] mr-10"> |               <Box className="w-[25%] mr-10"> | ||||||
|                 {activeArticleIndex !== null && ( |                 {activeArticleIndex !== null && ( | ||||||
|                   <Paper |                   <Paper | ||||||
|                     className="flex-1 flex flex-col rounded-2xl" |                     className="flex-1 flex flex-col  max-w-[500px]" | ||||||
|  |                     sx={{ | ||||||
|  |                       borderRadius: "16px", | ||||||
|  |                       overflow: "hidden", | ||||||
|  |                     }} | ||||||
|                     elevation={2} |                     elevation={2} | ||||||
|                   > |                   > | ||||||
|                     <Box |                     <Box | ||||||
|                       className="rounded-2xl overflow-hidden" |                       className=" overflow-hidden" | ||||||
|                       sx={{ |                       sx={{ | ||||||
|                         width: "100%", |                         width: "100%", | ||||||
|                         height: "75vh", |  | ||||||
|                         background: "#877361", |                         background: "#877361", | ||||||
|                         borderColor: "grey.300", |                         borderColor: "grey.300", | ||||||
|                         display: "flex", |                         display: "flex", | ||||||
| @@ -336,11 +471,23 @@ export const RightWidgetTab = observer( | |||||||
|                     > |                     > | ||||||
|                       {sight[language].right[activeArticleIndex].media.length > |                       {sight[language].right[activeArticleIndex].media.length > | ||||||
|                       0 ? ( |                       0 ? ( | ||||||
|                         <MediaViewer |                         <Box | ||||||
|                           media={ |                           sx={{ | ||||||
|                             sight[language].right[activeArticleIndex].media[0] |                             width: "100%", | ||||||
|                           } |                             maxHeight: "290px", | ||||||
|                         /> |                             flexShrink: 0, | ||||||
|  |  | ||||||
|  |                             display: "flex", | ||||||
|  |                             alignItems: "center", | ||||||
|  |                             justifyContent: "center", | ||||||
|  |                           }} | ||||||
|  |                         > | ||||||
|  |                           <MediaViewer | ||||||
|  |                             media={ | ||||||
|  |                               sight[language].right[activeArticleIndex].media[0] | ||||||
|  |                             } | ||||||
|  |                           /> | ||||||
|  |                         </Box> | ||||||
|                       ) : ( |                       ) : ( | ||||||
|                         <Box |                         <Box | ||||||
|                           sx={{ |                           sx={{ | ||||||
| @@ -360,15 +507,16 @@ export const RightWidgetTab = observer( | |||||||
|  |  | ||||||
|                       <Box |                       <Box | ||||||
|                         sx={{ |                         sx={{ | ||||||
|                           width: "100%", |                           p: 1, | ||||||
|                           height: "70px", |                           wordBreak: "break-word", | ||||||
|                           background: "#877361", |                           fontSize: "24px", | ||||||
|                           display: "flex", |                           fontWeight: 700, | ||||||
|                           flexShrink: 0, |                           lineHeight: "120%", | ||||||
|  |                           backdropFilter: "blur(12px)", | ||||||
|                           alignItems: "center", |                           boxShadow: | ||||||
|                           borderBottom: "1px solid rgba(255,255,255,0.1)", |                             "inset 4px 4px 12px 0 rgba(255,255,255,0.12)", | ||||||
|                           px: 2, |                           background: | ||||||
|  |                             "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|                         }} |                         }} | ||||||
|                       > |                       > | ||||||
|                         <Typography variant="h6" color="white"> |                         <Typography variant="h6" color="white"> | ||||||
| @@ -379,14 +527,14 @@ export const RightWidgetTab = observer( | |||||||
|  |  | ||||||
|                       <Box |                       <Box | ||||||
|                         sx={{ |                         sx={{ | ||||||
|                           px: 2, |                           padding: 1, | ||||||
|  |                           minHeight: "200px", | ||||||
|  |                           maxHeight: "300px", | ||||||
|  |                           overflowY: "scroll", | ||||||
|  |                           background: | ||||||
|  |                             "rgba(179, 165, 152, 0.4), linear-gradient(180deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|  |  | ||||||
|                           flexGrow: 1, |                           flexGrow: 1, | ||||||
|                           flex: 1, |  | ||||||
|                           minHeight: "300px", |  | ||||||
|                           overflowY: "auto", |  | ||||||
|                           backgroundColor: "#877361", |  | ||||||
|                           color: "white", |  | ||||||
|                           py: 1, |  | ||||||
|                         }} |                         }} | ||||||
|                       > |                       > | ||||||
|                         {sight[language].right[activeArticleIndex].body ? ( |                         {sight[language].right[activeArticleIndex].body ? ( | ||||||
| @@ -404,6 +552,39 @@ export const RightWidgetTab = observer( | |||||||
|                           </Typography> |                           </Typography> | ||||||
|                         )} |                         )} | ||||||
|                       </Box> |                       </Box> | ||||||
|  |                       <Box | ||||||
|  |                         sx={{ | ||||||
|  |                           p: 2, | ||||||
|  |                           display: "flex", | ||||||
|  |                           justifyContent: "space-between", | ||||||
|  |                           fontSize: "24px", | ||||||
|  |                           fontWeight: 700, | ||||||
|  |                           lineHeight: "120%", | ||||||
|  |                           flexWrap: "wrap", | ||||||
|  |  | ||||||
|  |                           gap: 1, | ||||||
|  |                           backdropFilter: "blur(12px)", | ||||||
|  |                           boxShadow: | ||||||
|  |                             "inset 4px 4px 12px 0 rgba(255,255,255,0.12)", | ||||||
|  |                           background: | ||||||
|  |                             "#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)", | ||||||
|  |                         }} | ||||||
|  |                       > | ||||||
|  |                         {sight[language].right.length > 0 && | ||||||
|  |                           sight[language].right.map((article, index) => ( | ||||||
|  |                             <button | ||||||
|  |                               className={`inline-block text-left text-xs text-white ${ | ||||||
|  |                                 activeArticleIndex === index ? "underline" : "" | ||||||
|  |                               }`} | ||||||
|  |                               onClick={() => { | ||||||
|  |                                 handleSelectArticle(index); | ||||||
|  |                                 setType("article"); | ||||||
|  |                               }} | ||||||
|  |                             > | ||||||
|  |                               {article.heading} | ||||||
|  |                             </button> | ||||||
|  |                           ))} | ||||||
|  |                       </Box> | ||||||
|                     </Box> |                     </Box> | ||||||
|                   </Paper> |                   </Paper> | ||||||
|                 )} |                 )} | ||||||
| @@ -423,8 +604,13 @@ export const RightWidgetTab = observer( | |||||||
|               justifyContent: "flex-end", |               justifyContent: "flex-end", | ||||||
|             }} |             }} | ||||||
|           > |           > | ||||||
|             <Button variant="contained" color="success" onClick={handleSave}> |             <Button | ||||||
|               Сохранить изменения |               variant="contained" | ||||||
|  |               startIcon={<Save color="white" size={18} />} | ||||||
|  |               color="success" | ||||||
|  |               onClick={handleSave} | ||||||
|  |             > | ||||||
|  |               Сохранить | ||||||
|             </Button> |             </Button> | ||||||
|           </Box> |           </Box> | ||||||
|         </Box> |         </Box> | ||||||
| @@ -442,10 +628,20 @@ export const RightWidgetTab = observer( | |||||||
|           }} |           }} | ||||||
|         /> |         /> | ||||||
|  |  | ||||||
|  |         <DeleteModal | ||||||
|  |           open={isDeleteArticleModalOpen} | ||||||
|  |           onCancel={() => setIsDeleteArticleModalOpen(false)} | ||||||
|  |           onDelete={() => { | ||||||
|  |             handleDeleteArticle(); | ||||||
|  |             setIsDeleteArticleModalOpen(false); | ||||||
|  |           }} | ||||||
|  |         /> | ||||||
|  |  | ||||||
|         <SelectArticleModal |         <SelectArticleModal | ||||||
|           open={isSelectModalOpen} |           open={isSelectModalOpen} | ||||||
|           onClose={handleCloseSelectModal} |           onClose={handleCloseSelectModal} | ||||||
|           onSelectArticle={handleArticleSelect} |           onSelectArticle={handleArticleSelect} | ||||||
|  |           linkedArticleIds={sight[language].right.map((article) => article.id)} | ||||||
|         /> |         /> | ||||||
|         <SelectMediaDialog |         <SelectMediaDialog | ||||||
|           open={isSelectMediaModalOpen} |           open={isSelectMediaModalOpen} | ||||||
|   | |||||||
| @@ -6,10 +6,10 @@ import TableHead from "@mui/material/TableHead"; | |||||||
| import TableRow from "@mui/material/TableRow"; | import TableRow from "@mui/material/TableRow"; | ||||||
| import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||||
| import { authInstance, cityStore, languageStore, sightsStore } from "@shared"; | import { authInstance, cityStore, languageStore, sightsStore } from "@shared"; | ||||||
| import { useEffect } from "react"; | import { useEffect, useState } from "react"; | ||||||
| import { observer } from "mobx-react-lite"; | import { observer } from "mobx-react-lite"; | ||||||
| import { Button } from "@mui/material"; | import { Button } from "@mui/material"; | ||||||
| import { LanguageSwitcher } from "@widgets"; | import { DeleteModal, LanguageSwitcher } from "@widgets"; | ||||||
| import { Pencil, Trash2 } from "lucide-react"; | import { Pencil, Trash2 } from "lucide-react"; | ||||||
| import { useNavigate } from "react-router-dom"; | import { useNavigate } from "react-router-dom"; | ||||||
|  |  | ||||||
| @@ -29,6 +29,8 @@ export const SightsTable = observer(() => { | |||||||
|   const { language } = languageStore; |   const { language } = languageStore; | ||||||
|   const { sights, getSights } = sightsStore; |   const { sights, getSights } = sightsStore; | ||||||
|   const { cities, getCities } = cityStore; |   const { cities, getCities } = cityStore; | ||||||
|  |   const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); | ||||||
|  |   const [rowId, setRowId] = useState<number | null>(null); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     const fetchData = async () => { |     const fetchData = async () => { | ||||||
| @@ -92,7 +94,10 @@ export const SightsTable = observer(() => { | |||||||
|                     </button> |                     </button> | ||||||
|                     <button |                     <button | ||||||
|                       className="rounded-md px-3 py-1.5 transition-transform transform hover:scale-105" |                       className="rounded-md px-3 py-1.5 transition-transform transform hover:scale-105" | ||||||
|                       onClick={() => handleDelete(row?.id)} |                       onClick={() => { | ||||||
|  |                         setIsDeleteModalOpen(true); | ||||||
|  |                         setRowId(row?.id); | ||||||
|  |                       }} | ||||||
|                     > |                     > | ||||||
|                       <Trash2 size={18} className="text-red-500" /> |                       <Trash2 size={18} className="text-red-500" /> | ||||||
|                     </button> |                     </button> | ||||||
| @@ -103,6 +108,17 @@ export const SightsTable = observer(() => { | |||||||
|           </TableBody> |           </TableBody> | ||||||
|         </Table> |         </Table> | ||||||
|       </TableContainer> |       </TableContainer> | ||||||
|  |       <DeleteModal | ||||||
|  |         open={isDeleteModalOpen} | ||||||
|  |         onDelete={async () => { | ||||||
|  |           if (rowId) { | ||||||
|  |             await handleDelete(rowId); | ||||||
|  |           } | ||||||
|  |           setIsDeleteModalOpen(false); | ||||||
|  |           setRowId(null); | ||||||
|  |         }} | ||||||
|  |         onCancel={() => setIsDeleteModalOpen(false)} | ||||||
|  |       /> | ||||||
|     </> |     </> | ||||||
|   ); |   ); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -12,3 +12,5 @@ export * from "./MediaArea"; | |||||||
| export * from "./ModelViewer3D"; | export * from "./ModelViewer3D"; | ||||||
| export * from "./MediaAreaForSight"; | export * from "./MediaAreaForSight"; | ||||||
| export * from "./ImageUploadCard"; | export * from "./ImageUploadCard"; | ||||||
|  | export * from "./LeaveAgree"; | ||||||
|  | export * from "./DeleteModal"; | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| {"root":["./src/main.tsx","./src/vite-env.d.ts","./src/app/index.tsx","./src/app/router/index.tsx","./src/entities/index.ts","./src/entities/navigation/index.ts","./src/entities/navigation/model/index.ts","./src/entities/navigation/ui/index.tsx","./src/features/index.ts","./src/features/navigation/index.ts","./src/features/navigation/ui/index.tsx","./src/pages/index.ts","./src/pages/createmediapage/index.tsx","./src/pages/createsightpage/index.tsx","./src/pages/devicespage/index.tsx","./src/pages/editmediapage/index.tsx","./src/pages/editsightpage/index.tsx","./src/pages/loginpage/index.tsx","./src/pages/mainpage/index.tsx","./src/pages/mappage/index.tsx","./src/pages/medialistpage/index.tsx","./src/pages/previewmediapage/index.tsx","./src/pages/sightpage/index.tsx","./src/shared/index.tsx","./src/shared/api/index.tsx","./src/shared/config/constants.tsx","./src/shared/config/index.ts","./src/shared/const/index.ts","./src/shared/lib/index.ts","./src/shared/lib/decodejwt/index.ts","./src/shared/lib/mui/theme.ts","./src/shared/modals/index.ts","./src/shared/modals/previewmediadialog/index.tsx","./src/shared/modals/selectarticledialog/index.tsx","./src/shared/modals/selectmediadialog/index.tsx","./src/shared/modals/uploadmediadialog/index.tsx","./src/shared/store/index.ts","./src/shared/store/articlesstore/index.tsx","./src/shared/store/authstore/index.tsx","./src/shared/store/citystore/index.tsx","./src/shared/store/createsightstore/index.tsx","./src/shared/store/devicesstore/index.tsx","./src/shared/store/editsightstore/index.tsx","./src/shared/store/languagestore/index.tsx","./src/shared/store/mediastore/index.tsx","./src/shared/store/sightsstore/index.tsx","./src/shared/store/snapshotstore/index.ts","./src/shared/store/vehiclestore/index.ts","./src/shared/ui/index.ts","./src/shared/ui/backbutton/index.tsx","./src/shared/ui/coordinatesinput/index.tsx","./src/shared/ui/input/index.tsx","./src/shared/ui/modal/index.tsx","./src/shared/ui/tabpanel/index.tsx","./src/widgets/index.ts","./src/widgets/devicestable/index.tsx","./src/widgets/imageuploadcard/index.tsx","./src/widgets/languageswitcher/index.tsx","./src/widgets/layout/index.tsx","./src/widgets/layout/ui/appbar.tsx","./src/widgets/layout/ui/drawer.tsx","./src/widgets/layout/ui/drawerheader.tsx","./src/widgets/mediaarea/index.tsx","./src/widgets/mediaareaforsight/index.tsx","./src/widgets/mediaviewer/threeview.tsx","./src/widgets/mediaviewer/index.tsx","./src/widgets/modelviewer3d/index.tsx","./src/widgets/reactmarkdown/index.tsx","./src/widgets/reactmarkdowneditor/index.tsx","./src/widgets/sightedit/index.tsx","./src/widgets/sightheader/index.ts","./src/widgets/sightheader/ui/index.tsx","./src/widgets/sighttabs/index.ts","./src/widgets/sighttabs/createinformationtab/mediauploadbox.tsx","./src/widgets/sighttabs/createinformationtab/index.tsx","./src/widgets/sighttabs/createlefttab/index.tsx","./src/widgets/sighttabs/createrighttab/index.tsx","./src/widgets/sighttabs/informationtab/index.tsx","./src/widgets/sighttabs/leftwidgettab/index.tsx","./src/widgets/sighttabs/rightwidgettab/index.tsx","./src/widgets/sightstable/index.tsx","./src/widgets/modals/index.ts","./src/widgets/modals/selectarticledialog/index.tsx"],"version":"5.8.3"} | {"root":["./src/main.tsx","./src/vite-env.d.ts","./src/app/index.tsx","./src/app/router/index.tsx","./src/entities/index.ts","./src/entities/navigation/index.ts","./src/entities/navigation/model/index.ts","./src/entities/navigation/ui/index.tsx","./src/features/index.ts","./src/features/navigation/index.ts","./src/features/navigation/ui/index.tsx","./src/pages/index.ts","./src/pages/createmediapage/index.tsx","./src/pages/createsightpage/index.tsx","./src/pages/devicespage/index.tsx","./src/pages/editmediapage/index.tsx","./src/pages/editsightpage/index.tsx","./src/pages/loginpage/index.tsx","./src/pages/mainpage/index.tsx","./src/pages/mappage/index.tsx","./src/pages/medialistpage/index.tsx","./src/pages/previewmediapage/index.tsx","./src/pages/sightpage/index.tsx","./src/shared/index.tsx","./src/shared/api/index.tsx","./src/shared/config/constants.tsx","./src/shared/config/index.ts","./src/shared/const/index.ts","./src/shared/lib/index.ts","./src/shared/lib/decodejwt/index.ts","./src/shared/lib/mui/theme.ts","./src/shared/modals/index.ts","./src/shared/modals/previewmediadialog/index.tsx","./src/shared/modals/selectarticledialog/index.tsx","./src/shared/modals/selectmediadialog/index.tsx","./src/shared/modals/uploadmediadialog/index.tsx","./src/shared/store/index.ts","./src/shared/store/articlesstore/index.tsx","./src/shared/store/authstore/index.tsx","./src/shared/store/citystore/index.tsx","./src/shared/store/createsightstore/index.tsx","./src/shared/store/devicesstore/index.tsx","./src/shared/store/editsightstore/index.tsx","./src/shared/store/languagestore/index.tsx","./src/shared/store/mediastore/index.tsx","./src/shared/store/sightsstore/index.tsx","./src/shared/store/snapshotstore/index.ts","./src/shared/store/vehiclestore/index.ts","./src/shared/ui/index.ts","./src/shared/ui/backbutton/index.tsx","./src/shared/ui/coordinatesinput/index.tsx","./src/shared/ui/input/index.tsx","./src/shared/ui/modal/index.tsx","./src/shared/ui/tabpanel/index.tsx","./src/widgets/index.ts","./src/widgets/deletemodal/index.tsx","./src/widgets/devicestable/index.tsx","./src/widgets/imageuploadcard/index.tsx","./src/widgets/languageswitcher/index.tsx","./src/widgets/layout/index.tsx","./src/widgets/layout/ui/appbar.tsx","./src/widgets/layout/ui/drawer.tsx","./src/widgets/layout/ui/drawerheader.tsx","./src/widgets/leaveagree/index.tsx","./src/widgets/mediaarea/index.tsx","./src/widgets/mediaareaforsight/index.tsx","./src/widgets/mediaviewer/threeview.tsx","./src/widgets/mediaviewer/index.tsx","./src/widgets/modelviewer3d/index.tsx","./src/widgets/reactmarkdown/index.tsx","./src/widgets/reactmarkdowneditor/index.tsx","./src/widgets/sightedit/index.tsx","./src/widgets/sightheader/index.ts","./src/widgets/sightheader/ui/index.tsx","./src/widgets/sighttabs/index.ts","./src/widgets/sighttabs/createinformationtab/mediauploadbox.tsx","./src/widgets/sighttabs/createinformationtab/index.tsx","./src/widgets/sighttabs/createlefttab/index.tsx","./src/widgets/sighttabs/createrighttab/index.tsx","./src/widgets/sighttabs/informationtab/index.tsx","./src/widgets/sighttabs/leftwidgettab/index.tsx","./src/widgets/sighttabs/rightwidgettab/index.tsx","./src/widgets/sightstable/index.tsx","./src/widgets/modals/index.ts","./src/widgets/modals/selectarticledialog/index.tsx"],"version":"5.8.3"} | ||||||
							
								
								
									
										286
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										286
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -133,12 +133,12 @@ | |||||||
|   dependencies: |   dependencies: | ||||||
|     "@babel/helper-plugin-utils" "^7.27.1" |     "@babel/helper-plugin-utils" "^7.27.1" | ||||||
|  |  | ||||||
| "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.27.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": | "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.26.0", "@babel/runtime@^7.27.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": | ||||||
|   version "7.27.3" |   version "7.27.3" | ||||||
|   resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.3.tgz" |   resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.3.tgz" | ||||||
|   integrity sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw== |   integrity sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw== | ||||||
|  |  | ||||||
| "@babel/runtime@^7.17.8", "@babel/runtime@^7.26.0": | "@babel/runtime@^7.26.7": | ||||||
|   version "7.27.4" |   version "7.27.4" | ||||||
|   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.4.tgz#a91ec580e6c00c67118127777c316dfd5a5a6abf" |   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.4.tgz#a91ec580e6c00c67118127777c316dfd5a5a6abf" | ||||||
|   integrity sha512-t3yaEOuGu9NlIZ+hIeGbBjFtZT7j2cb2tg0fuaJKeGotchRjjLfrBA9Kwf8quhpP1EUuxModQg04q/mBwyg8uA== |   integrity sha512-t3yaEOuGu9NlIZ+hIeGbBjFtZT7j2cb2tg0fuaJKeGotchRjjLfrBA9Kwf8quhpP1EUuxModQg04q/mBwyg8uA== | ||||||
| @@ -173,9 +173,9 @@ | |||||||
|     "@babel/helper-string-parser" "^7.27.1" |     "@babel/helper-string-parser" "^7.27.1" | ||||||
|     "@babel/helper-validator-identifier" "^7.27.1" |     "@babel/helper-validator-identifier" "^7.27.1" | ||||||
|  |  | ||||||
| "@dimforge/rapier3d-compat@^0.12.0": | "@dimforge/rapier3d-compat@~0.12.0": | ||||||
|   version "0.12.0" |   version "0.12.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz#7b3365e1dfdc5cd957b45afe920b4ac06c7cd389" |   resolved "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz" | ||||||
|   integrity sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow== |   integrity sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow== | ||||||
|  |  | ||||||
| "@emnapi/core@^1.4.3": | "@emnapi/core@^1.4.3": | ||||||
| @@ -498,6 +498,17 @@ | |||||||
|     "@eslint/core" "^0.14.0" |     "@eslint/core" "^0.14.0" | ||||||
|     levn "^0.4.1" |     levn "^0.4.1" | ||||||
|  |  | ||||||
|  | "@hello-pangea/dnd@^18.0.1": | ||||||
|  |   version "18.0.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/@hello-pangea/dnd/-/dnd-18.0.1.tgz#7d5ef7fe8bddf195307b16e03635b1be582b7b8d" | ||||||
|  |   integrity sha512-xojVWG8s/TGrKT1fC8K2tIWeejJYTAeJuj36zM//yEm/ZrnZUSFGS15BpO+jGZT1ybWvyXmeDJwPYb4dhWlbZQ== | ||||||
|  |   dependencies: | ||||||
|  |     "@babel/runtime" "^7.26.7" | ||||||
|  |     css-box-model "^1.2.1" | ||||||
|  |     raf-schd "^4.0.3" | ||||||
|  |     react-redux "^9.2.0" | ||||||
|  |     redux "^5.0.1" | ||||||
|  |  | ||||||
| "@humanfs/core@^0.19.1": | "@humanfs/core@^0.19.1": | ||||||
|   version "0.19.1" |   version "0.19.1" | ||||||
|   resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz" |   resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz" | ||||||
| @@ -567,12 +578,12 @@ | |||||||
|  |  | ||||||
| "@mediapipe/tasks-vision@0.10.17": | "@mediapipe/tasks-vision@0.10.17": | ||||||
|   version "0.10.17" |   version "0.10.17" | ||||||
|   resolved "https://registry.yarnpkg.com/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz#2c1c73ed81902b21d37336a587b96183bb6882d5" |   resolved "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz" | ||||||
|   integrity sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg== |   integrity sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg== | ||||||
|  |  | ||||||
| "@monogrid/gainmap-js@^3.0.6": | "@monogrid/gainmap-js@^3.0.6": | ||||||
|   version "3.1.0" |   version "3.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@monogrid/gainmap-js/-/gainmap-js-3.1.0.tgz#4ac1f88abd6affdf0b51d79318109183b499c502" |   resolved "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.1.0.tgz" | ||||||
|   integrity sha512-Obb0/gEd/HReTlg8ttaYk+0m62gQJmCblMOjHSMHRrBP2zdfKMHLCRbh/6ex9fSUJMKdjjIEiohwkbGD3wj2Nw== |   integrity sha512-Obb0/gEd/HReTlg8ttaYk+0m62gQJmCblMOjHSMHRrBP2zdfKMHLCRbh/6ex9fSUJMKdjjIEiohwkbGD3wj2Nw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     promise-worker-transferable "^1.0.4" |     promise-worker-transferable "^1.0.4" | ||||||
| @@ -686,12 +697,12 @@ | |||||||
|  |  | ||||||
| "@petamoriken/float16@^3.4.7": | "@petamoriken/float16@^3.4.7": | ||||||
|   version "3.9.2" |   version "3.9.2" | ||||||
|   resolved "https://registry.yarnpkg.com/@petamoriken/float16/-/float16-3.9.2.tgz#217a5d349f3655b8e286be447e0ed1eae063a78f" |   resolved "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz" | ||||||
|   integrity sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog== |   integrity sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog== | ||||||
|  |  | ||||||
| "@photo-sphere-viewer/core@^5.13.2": | "@photo-sphere-viewer/core@^5.13.2": | ||||||
|   version "5.13.2" |   version "5.13.2" | ||||||
|   resolved "https://registry.yarnpkg.com/@photo-sphere-viewer/core/-/core-5.13.2.tgz#518f27a2b7ca5a80068d8922183a9999a1b33ad1" |   resolved "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.13.2.tgz" | ||||||
|   integrity sha512-rL4Ey39Prx4Iyxt1f2tAqlXvqu4/ovXfUvIpLt540OpZJiFjWccs6qLywof9vuhBJ7PXHudHWCjRPce0W8kx8w== |   integrity sha512-rL4Ey39Prx4Iyxt1f2tAqlXvqu4/ovXfUvIpLt540OpZJiFjWccs6qLywof9vuhBJ7PXHudHWCjRPce0W8kx8w== | ||||||
|   dependencies: |   dependencies: | ||||||
|     three "^0.175.0" |     three "^0.175.0" | ||||||
| @@ -703,7 +714,7 @@ | |||||||
|  |  | ||||||
| "@react-three/drei@^10.1.2": | "@react-three/drei@^10.1.2": | ||||||
|   version "10.1.2" |   version "10.1.2" | ||||||
|   resolved "https://registry.yarnpkg.com/@react-three/drei/-/drei-10.1.2.tgz#3c41a0b19460aee7604067309cebe737147cf85a" |   resolved "https://registry.npmjs.org/@react-three/drei/-/drei-10.1.2.tgz" | ||||||
|   integrity sha512-CCcLAqZEvYiUErOcJgGzovY3RH6KgdrqD4ubeAx1nyGbSPLnKR9a8ynYbPdtZhIyiWqGc07z+RYQzpaOfN4ZIA== |   integrity sha512-CCcLAqZEvYiUErOcJgGzovY3RH6KgdrqD4ubeAx1nyGbSPLnKR9a8ynYbPdtZhIyiWqGc07z+RYQzpaOfN4ZIA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@babel/runtime" "^7.26.0" |     "@babel/runtime" "^7.26.0" | ||||||
| @@ -730,7 +741,7 @@ | |||||||
|  |  | ||||||
| "@react-three/fiber@^9.1.2": | "@react-three/fiber@^9.1.2": | ||||||
|   version "9.1.2" |   version "9.1.2" | ||||||
|   resolved "https://registry.yarnpkg.com/@react-three/fiber/-/fiber-9.1.2.tgz#c988f3aa916f64771483784ca3bb6ba4b116395e" |   resolved "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.1.2.tgz" | ||||||
|   integrity sha512-k8FR9yVHV9kIF3iuOD0ds5hVymXYXfgdKklqziBVod9ZEJ8uk05Zjw29J/omU3IKeUfLNAIHfxneN3TUYM4I2w== |   integrity sha512-k8FR9yVHV9kIF3iuOD0ds5hVymXYXfgdKklqziBVod9ZEJ8uk05Zjw29J/omU3IKeUfLNAIHfxneN3TUYM4I2w== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@babel/runtime" "^7.17.8" |     "@babel/runtime" "^7.17.8" | ||||||
| @@ -973,7 +984,7 @@ | |||||||
|  |  | ||||||
| "@tweenjs/tween.js@~23.1.3": | "@tweenjs/tween.js@~23.1.3": | ||||||
|   version "23.1.3" |   version "23.1.3" | ||||||
|   resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-23.1.3.tgz#eff0245735c04a928bb19c026b58c2a56460539d" |   resolved "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz" | ||||||
|   integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA== |   integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA== | ||||||
|  |  | ||||||
| "@tybys/wasm-util@^0.9.0": | "@tybys/wasm-util@^0.9.0": | ||||||
| @@ -1032,7 +1043,7 @@ | |||||||
|  |  | ||||||
| "@types/draco3d@^1.4.0": | "@types/draco3d@^1.4.0": | ||||||
|   version "1.4.10" |   version "1.4.10" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/draco3d/-/draco3d-1.4.10.tgz#63ec0ba78b30bd58203ec031f4e4f0198c596dca" |   resolved "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz" | ||||||
|   integrity sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw== |   integrity sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw== | ||||||
|  |  | ||||||
| "@types/estree-jsx@^1.0.0": | "@types/estree-jsx@^1.0.0": | ||||||
| @@ -1085,7 +1096,7 @@ | |||||||
|  |  | ||||||
| "@types/offscreencanvas@^2019.6.4": | "@types/offscreencanvas@^2019.6.4": | ||||||
|   version "2019.7.3" |   version "2019.7.3" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz#90267db13f64d6e9ccb5ae3eac92786a7c77a516" |   resolved "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz" | ||||||
|   integrity sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A== |   integrity sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A== | ||||||
|  |  | ||||||
| "@types/parse-json@^4.0.0": | "@types/parse-json@^4.0.0": | ||||||
| @@ -1100,7 +1111,7 @@ | |||||||
|  |  | ||||||
| "@types/rbush@4.0.0": | "@types/rbush@4.0.0": | ||||||
|   version "4.0.0" |   version "4.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/rbush/-/rbush-4.0.0.tgz#b327bf54952e9c924ea6702c36904c2ce1d47f35" |   resolved "https://registry.npmjs.org/@types/rbush/-/rbush-4.0.0.tgz" | ||||||
|   integrity sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ== |   integrity sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ== | ||||||
|  |  | ||||||
| "@types/react-dom@^19.1.2": | "@types/react-dom@^19.1.2": | ||||||
| @@ -1110,7 +1121,7 @@ | |||||||
|  |  | ||||||
| "@types/react-reconciler@^0.28.9": | "@types/react-reconciler@^0.28.9": | ||||||
|   version "0.28.9" |   version "0.28.9" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.28.9.tgz#d24b4864c384e770c83275b3fe73fba00269c83b" |   resolved "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.9.tgz" | ||||||
|   integrity sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg== |   integrity sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg== | ||||||
|  |  | ||||||
| "@types/react-transition-group@^4.4.12": | "@types/react-transition-group@^4.4.12": | ||||||
| @@ -1127,7 +1138,7 @@ | |||||||
|  |  | ||||||
| "@types/stats.js@*": | "@types/stats.js@*": | ||||||
|   version "0.17.4" |   version "0.17.4" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/stats.js/-/stats.js-0.17.4.tgz#1933e5ff153a23c7664487833198d685c22e791e" |   resolved "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz" | ||||||
|   integrity sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA== |   integrity sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA== | ||||||
|  |  | ||||||
| "@types/tern@*": | "@types/tern@*": | ||||||
| @@ -1138,11 +1149,11 @@ | |||||||
|     "@types/estree" "*" |     "@types/estree" "*" | ||||||
|  |  | ||||||
| "@types/three@*": | "@types/three@*": | ||||||
|   version "0.176.0" |   version "0.177.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/three/-/three-0.176.0.tgz#b6eced2b05e839395a6171e066c4631bc5b0a1e0" |   resolved "https://registry.npmjs.org/@types/three/-/three-0.177.0.tgz" | ||||||
|   integrity sha512-FwfPXxCqOtP7EdYMagCFePNKoG1AGBDUEVKtluv2BTVRpSt7b+X27xNsirPCTCqY1pGYsPUzaM3jgWP7dXSxlw== |   integrity sha512-/ZAkn4OLUijKQySNci47lFO+4JLE1TihEjsGWPUT+4jWqxtwOPPEwJV1C3k5MEx0mcBPCdkFjzRzDOnHEI1R+A== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@dimforge/rapier3d-compat" "^0.12.0" |     "@dimforge/rapier3d-compat" "~0.12.0" | ||||||
|     "@tweenjs/tween.js" "~23.1.3" |     "@tweenjs/tween.js" "~23.1.3" | ||||||
|     "@types/stats.js" "*" |     "@types/stats.js" "*" | ||||||
|     "@types/webxr" "*" |     "@types/webxr" "*" | ||||||
| @@ -1160,9 +1171,14 @@ | |||||||
|   resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz" |   resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz" | ||||||
|   integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== |   integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== | ||||||
|  |  | ||||||
|  | "@types/use-sync-external-store@^0.0.6": | ||||||
|  |   version "0.0.6" | ||||||
|  |   resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz#60be8d21baab8c305132eb9cb912ed497852aadc" | ||||||
|  |   integrity sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg== | ||||||
|  |  | ||||||
| "@types/webxr@*", "@types/webxr@^0.5.2": | "@types/webxr@*", "@types/webxr@^0.5.2": | ||||||
|   version "0.5.22" |   version "0.5.22" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.22.tgz#d8a14c12bbfaaa4a13de21ec2d4a8197b3e1b532" |   resolved "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.22.tgz" | ||||||
|   integrity sha512-Vr6Stjv5jPRqH690f5I5GLjVk8GSsoQSYJ2FVd/3jJF7KaqfwPi3ehfBS96mlQ2kPCwZaX6U0rG2+NGHBKkA/A== |   integrity sha512-Vr6Stjv5jPRqH690f5I5GLjVk8GSsoQSYJ2FVd/3jJF7KaqfwPi3ehfBS96mlQ2kPCwZaX6U0rG2+NGHBKkA/A== | ||||||
|  |  | ||||||
| "@typescript-eslint/eslint-plugin@8.33.0": | "@typescript-eslint/eslint-plugin@8.33.0": | ||||||
| @@ -1269,12 +1285,12 @@ | |||||||
|  |  | ||||||
| "@use-gesture/core@10.3.1": | "@use-gesture/core@10.3.1": | ||||||
|   version "10.3.1" |   version "10.3.1" | ||||||
|   resolved "https://registry.yarnpkg.com/@use-gesture/core/-/core-10.3.1.tgz#976c9421e905f0079d49822cfd5c2e56b808fc56" |   resolved "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz" | ||||||
|   integrity sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw== |   integrity sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw== | ||||||
|  |  | ||||||
| "@use-gesture/react@^10.3.1": | "@use-gesture/react@^10.3.1": | ||||||
|   version "10.3.1" |   version "10.3.1" | ||||||
|   resolved "https://registry.yarnpkg.com/@use-gesture/react/-/react-10.3.1.tgz#17a743a894d9bd9a0d1980c618f37f0164469867" |   resolved "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz" | ||||||
|   integrity sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g== |   integrity sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@use-gesture/core" "10.3.1" |     "@use-gesture/core" "10.3.1" | ||||||
| @@ -1293,7 +1309,7 @@ | |||||||
|  |  | ||||||
| "@webgpu/types@*": | "@webgpu/types@*": | ||||||
|   version "0.1.61" |   version "0.1.61" | ||||||
|   resolved "https://registry.yarnpkg.com/@webgpu/types/-/types-0.1.61.tgz#60ac1756bbeeae778b5357a94d4e6e160592d6f1" |   resolved "https://registry.npmjs.org/@webgpu/types/-/types-0.1.61.tgz" | ||||||
|   integrity sha512-w2HbBvH+qO19SB5pJOJFKs533CdZqxl3fcGonqL321VHkW7W/iBo6H8bjDy6pr/+pbMwIu5dnuaAxH7NxBqUrQ== |   integrity sha512-w2HbBvH+qO19SB5pJOJFKs533CdZqxl3fcGonqL321VHkW7W/iBo6H8bjDy6pr/+pbMwIu5dnuaAxH7NxBqUrQ== | ||||||
|  |  | ||||||
| acorn-jsx@^5.3.2: | acorn-jsx@^5.3.2: | ||||||
| @@ -1330,17 +1346,17 @@ argparse@^2.0.1: | |||||||
|  |  | ||||||
| asynckit@^0.4.0: | asynckit@^0.4.0: | ||||||
|   version "0.4.0" |   version "0.4.0" | ||||||
|   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" |   resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" | ||||||
|   integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== |   integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== | ||||||
|  |  | ||||||
| attr-accept@^2.2.4: | attr-accept@^2.2.4: | ||||||
|   version "2.2.5" |   version "2.2.5" | ||||||
|   resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.5.tgz#d7061d958e6d4f97bf8665c68b75851a0713ab5e" |   resolved "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz" | ||||||
|   integrity sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ== |   integrity sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ== | ||||||
|  |  | ||||||
| axios@^1.9.0: | axios@^1.9.0: | ||||||
|   version "1.9.0" |   version "1.9.0" | ||||||
|   resolved "https://registry.yarnpkg.com/axios/-/axios-1.9.0.tgz#25534e3b72b54540077d33046f77e3b8d7081901" |   resolved "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz" | ||||||
|   integrity sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg== |   integrity sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg== | ||||||
|   dependencies: |   dependencies: | ||||||
|     follow-redirects "^1.15.6" |     follow-redirects "^1.15.6" | ||||||
| @@ -1368,12 +1384,12 @@ balanced-match@^1.0.0: | |||||||
|  |  | ||||||
| base64-js@^1.3.1, base64-js@^1.5.1: | base64-js@^1.3.1, base64-js@^1.5.1: | ||||||
|   version "1.5.1" |   version "1.5.1" | ||||||
|   resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" |   resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" | ||||||
|   integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== |   integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== | ||||||
|  |  | ||||||
| bidi-js@^1.0.2: | bidi-js@^1.0.2: | ||||||
|   version "1.0.3" |   version "1.0.3" | ||||||
|   resolved "https://registry.yarnpkg.com/bidi-js/-/bidi-js-1.0.3.tgz#6f8bcf3c877c4d9220ddf49b9bb6930c88f877d2" |   resolved "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz" | ||||||
|   integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw== |   integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     require-from-string "^2.0.2" |     require-from-string "^2.0.2" | ||||||
| @@ -1412,7 +1428,7 @@ browserslist@^4.24.0: | |||||||
|  |  | ||||||
| buffer@^6.0.3: | buffer@^6.0.3: | ||||||
|   version "6.0.3" |   version "6.0.3" | ||||||
|   resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" |   resolved "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz" | ||||||
|   integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== |   integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     base64-js "^1.3.1" |     base64-js "^1.3.1" | ||||||
| @@ -1420,7 +1436,7 @@ buffer@^6.0.3: | |||||||
|  |  | ||||||
| call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: | call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: | ||||||
|   version "1.0.2" |   version "1.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" |   resolved "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz" | ||||||
|   integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== |   integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     es-errors "^1.3.0" |     es-errors "^1.3.0" | ||||||
| @@ -1433,7 +1449,7 @@ callsites@^3.0.0: | |||||||
|  |  | ||||||
| camera-controls@^2.9.0: | camera-controls@^2.9.0: | ||||||
|   version "2.10.1" |   version "2.10.1" | ||||||
|   resolved "https://registry.yarnpkg.com/camera-controls/-/camera-controls-2.10.1.tgz#78bc58001a2d5925c29312154ce77d16967dec56" |   resolved "https://registry.npmjs.org/camera-controls/-/camera-controls-2.10.1.tgz" | ||||||
|   integrity sha512-KnaKdcvkBJ1Irbrzl8XD6WtZltkRjp869Jx8c0ujs9K+9WD+1D7ryBsCiVqJYUqt6i/HR5FxT7RLASieUD+Q5w== |   integrity sha512-KnaKdcvkBJ1Irbrzl8XD6WtZltkRjp869Jx8c0ujs9K+9WD+1D7ryBsCiVqJYUqt6i/HR5FxT7RLASieUD+Q5w== | ||||||
|  |  | ||||||
| caniuse-lite@^1.0.30001716: | caniuse-lite@^1.0.30001716: | ||||||
| @@ -1510,7 +1526,7 @@ color-name@~1.1.4: | |||||||
|  |  | ||||||
| combined-stream@^1.0.8: | combined-stream@^1.0.8: | ||||||
|   version "1.0.8" |   version "1.0.8" | ||||||
|   resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" |   resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" | ||||||
|   integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== |   integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== | ||||||
|   dependencies: |   dependencies: | ||||||
|     delayed-stream "~1.0.0" |     delayed-stream "~1.0.0" | ||||||
| @@ -1537,7 +1553,7 @@ convert-source-map@^2.0.0: | |||||||
|  |  | ||||||
| cookie@^1.0.1: | cookie@^1.0.1: | ||||||
|   version "1.0.2" |   version "1.0.2" | ||||||
|   resolved "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz" |   resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610" | ||||||
|   integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA== |   integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA== | ||||||
|  |  | ||||||
| cosmiconfig@^7.0.0: | cosmiconfig@^7.0.0: | ||||||
| @@ -1553,7 +1569,7 @@ cosmiconfig@^7.0.0: | |||||||
|  |  | ||||||
| cross-env@^7.0.3: | cross-env@^7.0.3: | ||||||
|   version "7.0.3" |   version "7.0.3" | ||||||
|   resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" |   resolved "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz" | ||||||
|   integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== |   integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     cross-spawn "^7.0.1" |     cross-spawn "^7.0.1" | ||||||
| @@ -1567,6 +1583,13 @@ cross-spawn@^7.0.1, cross-spawn@^7.0.6: | |||||||
|     shebang-command "^2.0.0" |     shebang-command "^2.0.0" | ||||||
|     which "^2.0.1" |     which "^2.0.1" | ||||||
|  |  | ||||||
|  | css-box-model@^1.2.1: | ||||||
|  |   version "1.2.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" | ||||||
|  |   integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== | ||||||
|  |   dependencies: | ||||||
|  |     tiny-invariant "^1.0.6" | ||||||
|  |  | ||||||
| cssesc@^3.0.0: | cssesc@^3.0.0: | ||||||
|   version "3.0.0" |   version "3.0.0" | ||||||
|   resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" |   resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" | ||||||
| @@ -1598,7 +1621,7 @@ deep-is@^0.1.3: | |||||||
|  |  | ||||||
| delayed-stream@~1.0.0: | delayed-stream@~1.0.0: | ||||||
|   version "1.0.0" |   version "1.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" |   resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" | ||||||
|   integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== |   integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== | ||||||
|  |  | ||||||
| dequal@^2.0.0: | dequal@^2.0.0: | ||||||
| @@ -1608,7 +1631,7 @@ dequal@^2.0.0: | |||||||
|  |  | ||||||
| detect-gpu@^5.0.56: | detect-gpu@^5.0.56: | ||||||
|   version "5.0.70" |   version "5.0.70" | ||||||
|   resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.70.tgz#db2202d3cd440714ba6e789ff8b62d1b584eabf7" |   resolved "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.70.tgz" | ||||||
|   integrity sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w== |   integrity sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w== | ||||||
|   dependencies: |   dependencies: | ||||||
|     webgl-constants "^1.1.1" |     webgl-constants "^1.1.1" | ||||||
| @@ -1635,12 +1658,12 @@ dom-helpers@^5.0.1: | |||||||
|  |  | ||||||
| draco3d@^1.4.1: | draco3d@^1.4.1: | ||||||
|   version "1.5.7" |   version "1.5.7" | ||||||
|   resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.5.7.tgz#94f9bce293eb8920c159dc91a4ce9124a9e899e0" |   resolved "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz" | ||||||
|   integrity sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ== |   integrity sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ== | ||||||
|  |  | ||||||
| dunder-proto@^1.0.1: | dunder-proto@^1.0.1: | ||||||
|   version "1.0.1" |   version "1.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" |   resolved "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz" | ||||||
|   integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== |   integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== | ||||||
|   dependencies: |   dependencies: | ||||||
|     call-bind-apply-helpers "^1.0.1" |     call-bind-apply-helpers "^1.0.1" | ||||||
| @@ -1649,7 +1672,7 @@ dunder-proto@^1.0.1: | |||||||
|  |  | ||||||
| earcut@^3.0.0: | earcut@^3.0.0: | ||||||
|   version "3.0.1" |   version "3.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/earcut/-/earcut-3.0.1.tgz#f60b3f671c5657cca9d3e131c5527c5dde00ef38" |   resolved "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz" | ||||||
|   integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw== |   integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw== | ||||||
|  |  | ||||||
| easymde@^2.20.0: | easymde@^2.20.0: | ||||||
| @@ -1690,24 +1713,24 @@ error-ex@^1.3.1: | |||||||
|  |  | ||||||
| es-define-property@^1.0.1: | es-define-property@^1.0.1: | ||||||
|   version "1.0.1" |   version "1.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" |   resolved "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz" | ||||||
|   integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== |   integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== | ||||||
|  |  | ||||||
| es-errors@^1.3.0: | es-errors@^1.3.0: | ||||||
|   version "1.3.0" |   version "1.3.0" | ||||||
|   resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" |   resolved "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz" | ||||||
|   integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== |   integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== | ||||||
|  |  | ||||||
| es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: | es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: | ||||||
|   version "1.1.1" |   version "1.1.1" | ||||||
|   resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" |   resolved "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz" | ||||||
|   integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== |   integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     es-errors "^1.3.0" |     es-errors "^1.3.0" | ||||||
|  |  | ||||||
| es-set-tostringtag@^2.1.0: | es-set-tostringtag@^2.1.0: | ||||||
|   version "2.1.0" |   version "2.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" |   resolved "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz" | ||||||
|   integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== |   integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     es-errors "^1.3.0" |     es-errors "^1.3.0" | ||||||
| @@ -1865,7 +1888,7 @@ esutils@^2.0.2: | |||||||
|  |  | ||||||
| eventemitter3@^5.0.1: | eventemitter3@^5.0.1: | ||||||
|   version "5.0.1" |   version "5.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" |   resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz" | ||||||
|   integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== |   integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== | ||||||
|  |  | ||||||
| extend@^3.0.0: | extend@^3.0.0: | ||||||
| @@ -1913,12 +1936,12 @@ fdir@^6.4.4: | |||||||
|  |  | ||||||
| fflate@^0.6.9: | fflate@^0.6.9: | ||||||
|   version "0.6.10" |   version "0.6.10" | ||||||
|   resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43" |   resolved "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz" | ||||||
|   integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg== |   integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg== | ||||||
|  |  | ||||||
| fflate@~0.8.2: | fflate@~0.8.2: | ||||||
|   version "0.8.2" |   version "0.8.2" | ||||||
|   resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" |   resolved "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz" | ||||||
|   integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== |   integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== | ||||||
|  |  | ||||||
| file-entry-cache@^8.0.0: | file-entry-cache@^8.0.0: | ||||||
| @@ -1930,7 +1953,7 @@ file-entry-cache@^8.0.0: | |||||||
|  |  | ||||||
| file-selector@^2.1.0: | file-selector@^2.1.0: | ||||||
|   version "2.1.2" |   version "2.1.2" | ||||||
|   resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-2.1.2.tgz#fe7c7ee9e550952dfbc863d73b14dc740d7de8b4" |   resolved "https://registry.npmjs.org/file-selector/-/file-selector-2.1.2.tgz" | ||||||
|   integrity sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig== |   integrity sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig== | ||||||
|   dependencies: |   dependencies: | ||||||
|     tslib "^2.7.0" |     tslib "^2.7.0" | ||||||
| @@ -1970,12 +1993,12 @@ flatted@^3.2.9: | |||||||
|  |  | ||||||
| follow-redirects@^1.15.6: | follow-redirects@^1.15.6: | ||||||
|   version "1.15.9" |   version "1.15.9" | ||||||
|   resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" |   resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz" | ||||||
|   integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== |   integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== | ||||||
|  |  | ||||||
| form-data@^4.0.0: | form-data@^4.0.0: | ||||||
|   version "4.0.2" |   version "4.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c" |   resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz" | ||||||
|   integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== |   integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== | ||||||
|   dependencies: |   dependencies: | ||||||
|     asynckit "^0.4.0" |     asynckit "^0.4.0" | ||||||
| @@ -2000,7 +2023,7 @@ gensync@^1.0.0-beta.2: | |||||||
|  |  | ||||||
| geotiff@^2.1.3: | geotiff@^2.1.3: | ||||||
|   version "2.1.3" |   version "2.1.3" | ||||||
|   resolved "https://registry.yarnpkg.com/geotiff/-/geotiff-2.1.3.tgz#993f40f2aa6aa65fb1e0451d86dd22ca8e66910c" |   resolved "https://registry.npmjs.org/geotiff/-/geotiff-2.1.3.tgz" | ||||||
|   integrity sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA== |   integrity sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@petamoriken/float16" "^3.4.7" |     "@petamoriken/float16" "^3.4.7" | ||||||
| @@ -2014,7 +2037,7 @@ geotiff@^2.1.3: | |||||||
|  |  | ||||||
| get-intrinsic@^1.2.6: | get-intrinsic@^1.2.6: | ||||||
|   version "1.3.0" |   version "1.3.0" | ||||||
|   resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" |   resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz" | ||||||
|   integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== |   integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     call-bind-apply-helpers "^1.0.2" |     call-bind-apply-helpers "^1.0.2" | ||||||
| @@ -2030,7 +2053,7 @@ get-intrinsic@^1.2.6: | |||||||
|  |  | ||||||
| get-proto@^1.0.1: | get-proto@^1.0.1: | ||||||
|   version "1.0.1" |   version "1.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" |   resolved "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz" | ||||||
|   integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== |   integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== | ||||||
|   dependencies: |   dependencies: | ||||||
|     dunder-proto "^1.0.1" |     dunder-proto "^1.0.1" | ||||||
| @@ -2067,12 +2090,12 @@ globals@^16.0.0: | |||||||
|  |  | ||||||
| glsl-noise@^0.0.0: | glsl-noise@^0.0.0: | ||||||
|   version "0.0.0" |   version "0.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/glsl-noise/-/glsl-noise-0.0.0.tgz#367745f3a33382c0eeec4cb54b7e99cfc1d7670b" |   resolved "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz" | ||||||
|   integrity sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w== |   integrity sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w== | ||||||
|  |  | ||||||
| gopd@^1.2.0: | gopd@^1.2.0: | ||||||
|   version "1.2.0" |   version "1.2.0" | ||||||
|   resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" |   resolved "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz" | ||||||
|   integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== |   integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== | ||||||
|  |  | ||||||
| graceful-fs@^4.2.4: | graceful-fs@^4.2.4: | ||||||
| @@ -2092,12 +2115,12 @@ has-flag@^4.0.0: | |||||||
|  |  | ||||||
| has-symbols@^1.0.3, has-symbols@^1.1.0: | has-symbols@^1.0.3, has-symbols@^1.1.0: | ||||||
|   version "1.1.0" |   version "1.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" |   resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz" | ||||||
|   integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== |   integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== | ||||||
|  |  | ||||||
| has-tostringtag@^1.0.2: | has-tostringtag@^1.0.2: | ||||||
|   version "1.0.2" |   version "1.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" |   resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz" | ||||||
|   integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== |   integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     has-symbols "^1.0.3" |     has-symbols "^1.0.3" | ||||||
| @@ -2202,9 +2225,9 @@ hastscript@^9.0.0: | |||||||
|     space-separated-tokens "^2.0.0" |     space-separated-tokens "^2.0.0" | ||||||
|  |  | ||||||
| hls.js@^1.5.17: | hls.js@^1.5.17: | ||||||
|   version "1.6.4" |   version "1.6.5" | ||||||
|   resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.6.4.tgz#0c4070f5f719eda2687e2ab13b061dbb01967dd8" |   resolved "https://registry.npmjs.org/hls.js/-/hls.js-1.6.5.tgz" | ||||||
|   integrity sha512-sxFS61suCMJBvpOhmi4WLnarOZ8S8JAxK5J1icvrkopE8aRMc1pRB9WZWMX5Obh9nieVEML6uLLeyGksapyX5A== |   integrity sha512-KMn5n7JBK+olC342740hDPHnGWfE8FiHtGMOdJPfUjRdARTWj9OB+8c13fnsf9sk1VtpuU2fKSgUjHvg4rNbzQ== | ||||||
|  |  | ||||||
| hoist-non-react-statics@^3.3.1: | hoist-non-react-statics@^3.3.1: | ||||||
|   version "3.3.2" |   version "3.3.2" | ||||||
| @@ -2225,7 +2248,7 @@ html-void-elements@^3.0.0: | |||||||
|  |  | ||||||
| ieee754@^1.2.1: | ieee754@^1.2.1: | ||||||
|   version "1.2.1" |   version "1.2.1" | ||||||
|   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" |   resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" | ||||||
|   integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== |   integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== | ||||||
|  |  | ||||||
| ignore@^5.2.0: | ignore@^5.2.0: | ||||||
| @@ -2240,7 +2263,7 @@ ignore@^7.0.0: | |||||||
|  |  | ||||||
| immediate@~3.0.5: | immediate@~3.0.5: | ||||||
|   version "3.0.6" |   version "3.0.6" | ||||||
|   resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" |   resolved "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz" | ||||||
|   integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== |   integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== | ||||||
|  |  | ||||||
| import-fresh@^3.2.1: | import-fresh@^3.2.1: | ||||||
| @@ -2325,7 +2348,7 @@ is-plain-obj@^4.0.0: | |||||||
|  |  | ||||||
| is-promise@^2.1.0: | is-promise@^2.1.0: | ||||||
|   version "2.2.2" |   version "2.2.2" | ||||||
|   resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" |   resolved "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz" | ||||||
|   integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== |   integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== | ||||||
|  |  | ||||||
| isexe@^2.0.0: | isexe@^2.0.0: | ||||||
| @@ -2335,7 +2358,7 @@ isexe@^2.0.0: | |||||||
|  |  | ||||||
| its-fine@^2.0.0: | its-fine@^2.0.0: | ||||||
|   version "2.0.0" |   version "2.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-2.0.0.tgz#a90b18a3ee4c211a1fb6faac2abcc2b682ce1f21" |   resolved "https://registry.npmjs.org/its-fine/-/its-fine-2.0.0.tgz" | ||||||
|   integrity sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng== |   integrity sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@types/react-reconciler" "^0.28.9" |     "@types/react-reconciler" "^0.28.9" | ||||||
| @@ -2396,7 +2419,7 @@ keyv@^4.5.4: | |||||||
|  |  | ||||||
| lerc@^3.0.0: | lerc@^3.0.0: | ||||||
|   version "3.0.0" |   version "3.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/lerc/-/lerc-3.0.0.tgz#36f36fbd4ba46f0abf4833799fff2e7d6865f5cb" |   resolved "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz" | ||||||
|   integrity sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww== |   integrity sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww== | ||||||
|  |  | ||||||
| levn@^0.4.1: | levn@^0.4.1: | ||||||
| @@ -2409,7 +2432,7 @@ levn@^0.4.1: | |||||||
|  |  | ||||||
| lie@^3.0.2: | lie@^3.0.2: | ||||||
|   version "3.3.0" |   version "3.3.0" | ||||||
|   resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" |   resolved "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz" | ||||||
|   integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== |   integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     immediate "~3.0.5" |     immediate "~3.0.5" | ||||||
| @@ -2535,7 +2558,7 @@ lucide-react@^0.511.0: | |||||||
|  |  | ||||||
| maath@^0.10.8: | maath@^0.10.8: | ||||||
|   version "0.10.8" |   version "0.10.8" | ||||||
|   resolved "https://registry.yarnpkg.com/maath/-/maath-0.10.8.tgz#cf647544430141bf6982da6e878abb6c4b804e24" |   resolved "https://registry.npmjs.org/maath/-/maath-0.10.8.tgz" | ||||||
|   integrity sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g== |   integrity sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g== | ||||||
|  |  | ||||||
| magic-string@^0.30.17: | magic-string@^0.30.17: | ||||||
| @@ -2552,7 +2575,7 @@ marked@^4.1.0: | |||||||
|  |  | ||||||
| math-intrinsics@^1.1.0: | math-intrinsics@^1.1.0: | ||||||
|   version "1.1.0" |   version "1.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" |   resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz" | ||||||
|   integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== |   integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== | ||||||
|  |  | ||||||
| mdast-util-from-markdown@^2.0.0: | mdast-util-from-markdown@^2.0.0: | ||||||
| @@ -2667,12 +2690,12 @@ merge2@^1.3.0: | |||||||
|  |  | ||||||
| meshline@^3.3.1: | meshline@^3.3.1: | ||||||
|   version "3.3.1" |   version "3.3.1" | ||||||
|   resolved "https://registry.yarnpkg.com/meshline/-/meshline-3.3.1.tgz#20decfd5cdd25c8469e862ddf0ab1ad167759734" |   resolved "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz" | ||||||
|   integrity sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ== |   integrity sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ== | ||||||
|  |  | ||||||
| meshoptimizer@~0.18.1: | meshoptimizer@~0.18.1: | ||||||
|   version "0.18.1" |   version "0.18.1" | ||||||
|   resolved "https://registry.yarnpkg.com/meshoptimizer/-/meshoptimizer-0.18.1.tgz#cdb90907f30a7b5b1190facd3b7ee6b7087797d8" |   resolved "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz" | ||||||
|   integrity sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw== |   integrity sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw== | ||||||
|  |  | ||||||
| micromark-core-commonmark@^2.0.0: | micromark-core-commonmark@^2.0.0: | ||||||
| @@ -2879,12 +2902,12 @@ micromatch@^4.0.8: | |||||||
|  |  | ||||||
| mime-db@1.52.0: | mime-db@1.52.0: | ||||||
|   version "1.52.0" |   version "1.52.0" | ||||||
|   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" |   resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" | ||||||
|   integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== |   integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== | ||||||
|  |  | ||||||
| mime-types@^2.1.12: | mime-types@^2.1.12: | ||||||
|   version "2.1.35" |   version "2.1.35" | ||||||
|   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" |   resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" | ||||||
|   integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== |   integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     mime-db "1.52.0" |     mime-db "1.52.0" | ||||||
| @@ -2959,7 +2982,7 @@ object-assign@^4.1.1: | |||||||
|  |  | ||||||
| ol@^10.5.0: | ol@^10.5.0: | ||||||
|   version "10.5.0" |   version "10.5.0" | ||||||
|   resolved "https://registry.yarnpkg.com/ol/-/ol-10.5.0.tgz#5831dc55fe5eb5a09cb4193c9289c1b5a0a0f0ca" |   resolved "https://registry.npmjs.org/ol/-/ol-10.5.0.tgz" | ||||||
|   integrity sha512-nHFx8gkGmvYImsa7iKkwUnZidd5gn1XbMZd9GNOorvm9orjW9gQvT3Naw/MjIasVJ3cB9EJUdCGR2EFAulMHsQ== |   integrity sha512-nHFx8gkGmvYImsa7iKkwUnZidd5gn1XbMZd9GNOorvm9orjW9gQvT3Naw/MjIasVJ3cB9EJUdCGR2EFAulMHsQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@types/rbush" "4.0.0" |     "@types/rbush" "4.0.0" | ||||||
| @@ -2996,7 +3019,7 @@ p-locate@^5.0.0: | |||||||
|  |  | ||||||
| pako@^2.0.4: | pako@^2.0.4: | ||||||
|   version "2.1.0" |   version "2.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" |   resolved "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz" | ||||||
|   integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== |   integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== | ||||||
|  |  | ||||||
| parent-module@^1.0.0: | parent-module@^1.0.0: | ||||||
| @@ -3021,7 +3044,7 @@ parse-entities@^4.0.0: | |||||||
|  |  | ||||||
| parse-headers@^2.0.2: | parse-headers@^2.0.2: | ||||||
|   version "2.0.6" |   version "2.0.6" | ||||||
|   resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.6.tgz#7940f0abe5fe65df2dd25d4ce8800cb35b49d01c" |   resolved "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz" | ||||||
|   integrity sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A== |   integrity sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A== | ||||||
|  |  | ||||||
| parse-json@^5.0.0: | parse-json@^5.0.0: | ||||||
| @@ -3071,7 +3094,7 @@ path@^0.12.7: | |||||||
|  |  | ||||||
| pbf@4.0.1: | pbf@4.0.1: | ||||||
|   version "4.0.1" |   version "4.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/pbf/-/pbf-4.0.1.tgz#ad9015e022b235dcdbe05fc468a9acadf483f0d4" |   resolved "https://registry.npmjs.org/pbf/-/pbf-4.0.1.tgz" | ||||||
|   integrity sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA== |   integrity sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     resolve-protobuf-schema "^2.1.0" |     resolve-protobuf-schema "^2.1.0" | ||||||
| @@ -3110,7 +3133,7 @@ postcss@^8.5.3: | |||||||
|  |  | ||||||
| potpack@^1.0.1: | potpack@^1.0.1: | ||||||
|   version "1.0.2" |   version "1.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14" |   resolved "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz" | ||||||
|   integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ== |   integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ== | ||||||
|  |  | ||||||
| prelude-ls@^1.2.1: | prelude-ls@^1.2.1: | ||||||
| @@ -3125,7 +3148,7 @@ process@^0.11.1: | |||||||
|  |  | ||||||
| promise-worker-transferable@^1.0.4: | promise-worker-transferable@^1.0.4: | ||||||
|   version "1.0.4" |   version "1.0.4" | ||||||
|   resolved "https://registry.yarnpkg.com/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz#2c72861ba053e5ae42b487b4a83b1ed3ae3786e8" |   resolved "https://registry.npmjs.org/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz" | ||||||
|   integrity sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw== |   integrity sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     is-promise "^2.1.0" |     is-promise "^2.1.0" | ||||||
| @@ -3152,12 +3175,12 @@ property-information@^7.0.0: | |||||||
|  |  | ||||||
| protocol-buffers-schema@^3.3.1: | protocol-buffers-schema@^3.3.1: | ||||||
|   version "3.6.0" |   version "3.6.0" | ||||||
|   resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz#77bc75a48b2ff142c1ad5b5b90c94cd0fa2efd03" |   resolved "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz" | ||||||
|   integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw== |   integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw== | ||||||
|  |  | ||||||
| proxy-from-env@^1.1.0: | proxy-from-env@^1.1.0: | ||||||
|   version "1.1.0" |   version "1.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" |   resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" | ||||||
|   integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== |   integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== | ||||||
|  |  | ||||||
| punycode@^2.1.0: | punycode@^2.1.0: | ||||||
| @@ -3172,17 +3195,22 @@ queue-microtask@^1.2.2: | |||||||
|  |  | ||||||
| quick-lru@^6.1.1: | quick-lru@^6.1.1: | ||||||
|   version "6.1.2" |   version "6.1.2" | ||||||
|   resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-6.1.2.tgz#e9a90524108629be35287d0b864e7ad6ceb3659e" |   resolved "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz" | ||||||
|   integrity sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ== |   integrity sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ== | ||||||
|  |  | ||||||
| quickselect@^3.0.0: | quickselect@^3.0.0: | ||||||
|   version "3.0.0" |   version "3.0.0" | ||||||
|   resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-3.0.0.tgz#a37fc953867d56f095a20ac71c6d27063d2de603" |   resolved "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz" | ||||||
|   integrity sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g== |   integrity sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g== | ||||||
|  |  | ||||||
|  | raf-schd@^4.0.3: | ||||||
|  |   version "4.0.3" | ||||||
|  |   resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a" | ||||||
|  |   integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ== | ||||||
|  |  | ||||||
| rbush@^4.0.0: | rbush@^4.0.0: | ||||||
|   version "4.0.1" |   version "4.0.1" | ||||||
|   resolved "https://registry.yarnpkg.com/rbush/-/rbush-4.0.1.tgz#1f55afa64a978f71bf9e9a99bc14ff84f3cb0d6d" |   resolved "https://registry.npmjs.org/rbush/-/rbush-4.0.1.tgz" | ||||||
|   integrity sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ== |   integrity sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     quickselect "^3.0.0" |     quickselect "^3.0.0" | ||||||
| @@ -3196,7 +3224,7 @@ react-dom@^19.1.0: | |||||||
|  |  | ||||||
| react-dropzone@^14.3.8: | react-dropzone@^14.3.8: | ||||||
|   version "14.3.8" |   version "14.3.8" | ||||||
|   resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-14.3.8.tgz#a7eab118f8a452fe3f8b162d64454e81ba830582" |   resolved "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.3.8.tgz" | ||||||
|   integrity sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug== |   integrity sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug== | ||||||
|   dependencies: |   dependencies: | ||||||
|     attr-accept "^2.2.4" |     attr-accept "^2.2.4" | ||||||
| @@ -3232,34 +3260,42 @@ react-markdown@^10.1.0: | |||||||
|  |  | ||||||
| react-photo-sphere-viewer@^6.2.3: | react-photo-sphere-viewer@^6.2.3: | ||||||
|   version "6.2.3" |   version "6.2.3" | ||||||
|   resolved "https://registry.yarnpkg.com/react-photo-sphere-viewer/-/react-photo-sphere-viewer-6.2.3.tgz#bdbe33a03315077b1d49f2d4690f0dc72563ac9a" |   resolved "https://registry.npmjs.org/react-photo-sphere-viewer/-/react-photo-sphere-viewer-6.2.3.tgz" | ||||||
|   integrity sha512-VzG0aY9CI8OIQjdIoJCjYF1QlnLFpN2pM+zKm1JrpAKQrBZ6B+Uxy94vpVQkGDERgn8FWE0+LIntTgAr60pLyQ== |   integrity sha512-VzG0aY9CI8OIQjdIoJCjYF1QlnLFpN2pM+zKm1JrpAKQrBZ6B+Uxy94vpVQkGDERgn8FWE0+LIntTgAr60pLyQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     eventemitter3 "^5.0.1" |     eventemitter3 "^5.0.1" | ||||||
|  |  | ||||||
| react-reconciler@^0.31.0: | react-reconciler@^0.31.0: | ||||||
|   version "0.31.0" |   version "0.31.0" | ||||||
|   resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.31.0.tgz#6b7390fe8fab59210daf523d7400943973de1458" |   resolved "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.31.0.tgz" | ||||||
|   integrity sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ== |   integrity sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     scheduler "^0.25.0" |     scheduler "^0.25.0" | ||||||
|  |  | ||||||
|  | react-redux@^9.2.0: | ||||||
|  |   version "9.2.0" | ||||||
|  |   resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-9.2.0.tgz#96c3ab23fb9a3af2cb4654be4b51c989e32366f5" | ||||||
|  |   integrity sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g== | ||||||
|  |   dependencies: | ||||||
|  |     "@types/use-sync-external-store" "^0.0.6" | ||||||
|  |     use-sync-external-store "^1.4.0" | ||||||
|  |  | ||||||
| react-refresh@^0.17.0: | react-refresh@^0.17.0: | ||||||
|   version "0.17.0" |   version "0.17.0" | ||||||
|   resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz" |   resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz" | ||||||
|   integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ== |   integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ== | ||||||
|  |  | ||||||
| react-router-dom@^7.6.1: | react-router-dom@^7.6.1: | ||||||
|   version "7.6.1" |   version "7.6.2" | ||||||
|   resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.1.tgz" |   resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-7.6.2.tgz#e97e386ab390b6503a2a7968124b7a3237fb10c7" | ||||||
|   integrity sha512-vxU7ei//UfPYQ3iZvHuO1D/5fX3/JOqhNTbRR+WjSBWxf9bIvpWK+ftjmdfJHzPOuMQKe2fiEdG+dZX6E8uUpA== |   integrity sha512-Q8zb6VlTbdYKK5JJBLQEN06oTUa/RAbG/oQS1auK1I0TbJOXktqm+QENEVJU6QvWynlXPRBXI3fiOQcSEA78rA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     react-router "7.6.1" |     react-router "7.6.2" | ||||||
|  |  | ||||||
| react-router@7.6.1: | react-router@7.6.2: | ||||||
|   version "7.6.1" |   version "7.6.2" | ||||||
|   resolved "https://registry.npmjs.org/react-router/-/react-router-7.6.1.tgz" |   resolved "https://registry.yarnpkg.com/react-router/-/react-router-7.6.2.tgz#9f48b343bead7d0a94e28342fc4f9ae29131520e" | ||||||
|   integrity sha512-hPJXXxHJZEsPFNVbtATH7+MMX43UDeOauz+EAU4cgqTn7ojdI9qQORqS8Z0qmDlL1TclO/6jLRYUEtbWidtdHQ== |   integrity sha512-U7Nv3y+bMimgWjhlT5CRdzHPu2/KVmqPwKUCChW8en5P3znxUqwlYFlbmyj8Rgp1SF6zs5X4+77kBVknkg6a0w== | ||||||
|   dependencies: |   dependencies: | ||||||
|     cookie "^1.0.1" |     cookie "^1.0.1" | ||||||
|     set-cookie-parser "^2.6.0" |     set-cookie-parser "^2.6.0" | ||||||
| @@ -3273,7 +3309,7 @@ react-simplemde-editor@^5.2.0: | |||||||
|  |  | ||||||
| react-toastify@^11.0.5: | react-toastify@^11.0.5: | ||||||
|   version "11.0.5" |   version "11.0.5" | ||||||
|   resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-11.0.5.tgz#ce4c42d10eeb433988ab2264d3e445c4e9d13313" |   resolved "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.5.tgz" | ||||||
|   integrity sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA== |   integrity sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     clsx "^2.1.1" |     clsx "^2.1.1" | ||||||
| @@ -3290,7 +3326,7 @@ react-transition-group@^4.4.5: | |||||||
|  |  | ||||||
| react-use-measure@^2.1.7: | react-use-measure@^2.1.7: | ||||||
|   version "2.1.7" |   version "2.1.7" | ||||||
|   resolved "https://registry.yarnpkg.com/react-use-measure/-/react-use-measure-2.1.7.tgz#36b8a2e7fd2fa58109ab851b3addcb0aad66ad1d" |   resolved "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz" | ||||||
|   integrity sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg== |   integrity sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg== | ||||||
|  |  | ||||||
| react@^19.1.0: | react@^19.1.0: | ||||||
| @@ -3298,6 +3334,11 @@ react@^19.1.0: | |||||||
|   resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz" |   resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz" | ||||||
|   integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== |   integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== | ||||||
|  |  | ||||||
|  | redux@^5.0.1: | ||||||
|  |   version "5.0.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/redux/-/redux-5.0.1.tgz#97fa26881ce5746500125585d5642c77b6e9447b" | ||||||
|  |   integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w== | ||||||
|  |  | ||||||
| rehype-raw@^7.0.0: | rehype-raw@^7.0.0: | ||||||
|   version "7.0.0" |   version "7.0.0" | ||||||
|   resolved "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz" |   resolved "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz" | ||||||
| @@ -3330,7 +3371,7 @@ remark-rehype@^11.0.0: | |||||||
|  |  | ||||||
| require-from-string@^2.0.2: | require-from-string@^2.0.2: | ||||||
|   version "2.0.2" |   version "2.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" |   resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" | ||||||
|   integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== |   integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== | ||||||
|  |  | ||||||
| resolve-from@^4.0.0: | resolve-from@^4.0.0: | ||||||
| @@ -3340,7 +3381,7 @@ resolve-from@^4.0.0: | |||||||
|  |  | ||||||
| resolve-protobuf-schema@^2.1.0: | resolve-protobuf-schema@^2.1.0: | ||||||
|   version "2.1.0" |   version "2.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758" |   resolved "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz" | ||||||
|   integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ== |   integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     protocol-buffers-schema "^3.3.1" |     protocol-buffers-schema "^3.3.1" | ||||||
| @@ -3397,7 +3438,7 @@ run-parallel@^1.1.9: | |||||||
|  |  | ||||||
| scheduler@^0.25.0: | scheduler@^0.25.0: | ||||||
|   version "0.25.0" |   version "0.25.0" | ||||||
|   resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" |   resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz" | ||||||
|   integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== |   integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== | ||||||
|  |  | ||||||
| scheduler@^0.26.0: | scheduler@^0.26.0: | ||||||
| @@ -3417,7 +3458,7 @@ semver@^7.6.0: | |||||||
|  |  | ||||||
| set-cookie-parser@^2.6.0: | set-cookie-parser@^2.6.0: | ||||||
|   version "2.7.1" |   version "2.7.1" | ||||||
|   resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz" |   resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" | ||||||
|   integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== |   integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== | ||||||
|  |  | ||||||
| shebang-command@^2.0.0: | shebang-command@^2.0.0: | ||||||
| @@ -3449,7 +3490,7 @@ space-separated-tokens@^2.0.0: | |||||||
|  |  | ||||||
| stats-gl@^2.2.8: | stats-gl@^2.2.8: | ||||||
|   version "2.4.2" |   version "2.4.2" | ||||||
|   resolved "https://registry.yarnpkg.com/stats-gl/-/stats-gl-2.4.2.tgz#28a6c869fc3a36a8be608ef21df63c0aad99d1ba" |   resolved "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz" | ||||||
|   integrity sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ== |   integrity sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@types/three" "*" |     "@types/three" "*" | ||||||
| @@ -3457,7 +3498,7 @@ stats-gl@^2.2.8: | |||||||
|  |  | ||||||
| stats.js@^0.17.0: | stats.js@^0.17.0: | ||||||
|   version "0.17.0" |   version "0.17.0" | ||||||
|   resolved "https://registry.yarnpkg.com/stats.js/-/stats.js-0.17.0.tgz#b1c3dc46d94498b578b7fd3985b81ace7131cc7d" |   resolved "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz" | ||||||
|   integrity sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw== |   integrity sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw== | ||||||
|  |  | ||||||
| stringify-entities@^4.0.0: | stringify-entities@^4.0.0: | ||||||
| @@ -3506,7 +3547,7 @@ supports-preserve-symlinks-flag@^1.0.0: | |||||||
|  |  | ||||||
| suspend-react@^0.1.3: | suspend-react@^0.1.3: | ||||||
|   version "0.1.3" |   version "0.1.3" | ||||||
|   resolved "https://registry.yarnpkg.com/suspend-react/-/suspend-react-0.1.3.tgz#a52f49d21cfae9a2fb70bd0c68413d3f9d90768e" |   resolved "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz" | ||||||
|   integrity sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ== |   integrity sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ== | ||||||
|  |  | ||||||
| tailwindcss@4.1.8, tailwindcss@^4.1.8: | tailwindcss@4.1.8, tailwindcss@^4.1.8: | ||||||
| @@ -3533,12 +3574,12 @@ tar@^7.4.3: | |||||||
|  |  | ||||||
| three-mesh-bvh@^0.8.3: | three-mesh-bvh@^0.8.3: | ||||||
|   version "0.8.3" |   version "0.8.3" | ||||||
|   resolved "https://registry.yarnpkg.com/three-mesh-bvh/-/three-mesh-bvh-0.8.3.tgz#c5e72472e7f062ff79084157a25c122d73184163" |   resolved "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.8.3.tgz" | ||||||
|   integrity sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg== |   integrity sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg== | ||||||
|  |  | ||||||
| three-stdlib@^2.35.6: | three-stdlib@^2.35.6: | ||||||
|   version "2.36.0" |   version "2.36.0" | ||||||
|   resolved "https://registry.yarnpkg.com/three-stdlib/-/three-stdlib-2.36.0.tgz#1d806b8db9156a6c87ed10f61f56f8a3ab634b42" |   resolved "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.36.0.tgz" | ||||||
|   integrity sha512-kv0Byb++AXztEGsULgMAs8U2jgUdz6HPpAB/wDJnLiLlaWQX2APHhiTJIN7rqW+Of0eRgcp7jn05U1BsCP3xBA== |   integrity sha512-kv0Byb++AXztEGsULgMAs8U2jgUdz6HPpAB/wDJnLiLlaWQX2APHhiTJIN7rqW+Of0eRgcp7jn05U1BsCP3xBA== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@types/draco3d" "^1.4.0" |     "@types/draco3d" "^1.4.0" | ||||||
| @@ -3550,19 +3591,24 @@ three-stdlib@^2.35.6: | |||||||
|  |  | ||||||
| three@^0.170.0: | three@^0.170.0: | ||||||
|   version "0.170.0" |   version "0.170.0" | ||||||
|   resolved "https://registry.yarnpkg.com/three/-/three-0.170.0.tgz#6087f97aab79e9e9312f9c89fcef6808642dfbb7" |   resolved "https://registry.npmjs.org/three/-/three-0.170.0.tgz" | ||||||
|   integrity sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ== |   integrity sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ== | ||||||
|  |  | ||||||
| three@^0.175.0: | three@^0.175.0: | ||||||
|   version "0.175.0" |   version "0.175.0" | ||||||
|   resolved "https://registry.yarnpkg.com/three/-/three-0.175.0.tgz#67b357b0b1ee8ef0445b9a768f59363ab1fa7921" |   resolved "https://registry.npmjs.org/three/-/three-0.175.0.tgz" | ||||||
|   integrity sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg== |   integrity sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg== | ||||||
|  |  | ||||||
| three@^0.177.0: | three@^0.177.0: | ||||||
|   version "0.177.0" |   version "0.177.0" | ||||||
|   resolved "https://registry.yarnpkg.com/three/-/three-0.177.0.tgz#e51f2eb2b921fbab535bdfa81c403f9993b9dd83" |   resolved "https://registry.npmjs.org/three/-/three-0.177.0.tgz" | ||||||
|   integrity sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg== |   integrity sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg== | ||||||
|  |  | ||||||
|  | tiny-invariant@^1.0.6: | ||||||
|  |   version "1.3.3" | ||||||
|  |   resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" | ||||||
|  |   integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== | ||||||
|  |  | ||||||
| tinyglobby@^0.2.13: | tinyglobby@^0.2.13: | ||||||
|   version "0.2.14" |   version "0.2.14" | ||||||
|   resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz" |   resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz" | ||||||
| @@ -3585,7 +3631,7 @@ trim-lines@^3.0.0: | |||||||
|  |  | ||||||
| troika-three-text@^0.52.4: | troika-three-text@^0.52.4: | ||||||
|   version "0.52.4" |   version "0.52.4" | ||||||
|   resolved "https://registry.yarnpkg.com/troika-three-text/-/troika-three-text-0.52.4.tgz#f7b2389a2067d9506a5757457771cf4f6356e738" |   resolved "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.52.4.tgz" | ||||||
|   integrity sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg== |   integrity sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg== | ||||||
|   dependencies: |   dependencies: | ||||||
|     bidi-js "^1.0.2" |     bidi-js "^1.0.2" | ||||||
| @@ -3595,12 +3641,12 @@ troika-three-text@^0.52.4: | |||||||
|  |  | ||||||
| troika-three-utils@^0.52.4: | troika-three-utils@^0.52.4: | ||||||
|   version "0.52.4" |   version "0.52.4" | ||||||
|   resolved "https://registry.yarnpkg.com/troika-three-utils/-/troika-three-utils-0.52.4.tgz#9292019e93cab97582af1cf491c4c895e5c03b66" |   resolved "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.52.4.tgz" | ||||||
|   integrity sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A== |   integrity sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A== | ||||||
|  |  | ||||||
| troika-worker-utils@^0.52.0: | troika-worker-utils@^0.52.0: | ||||||
|   version "0.52.0" |   version "0.52.0" | ||||||
|   resolved "https://registry.yarnpkg.com/troika-worker-utils/-/troika-worker-utils-0.52.0.tgz#ba5525fc444345006ebab0bc9cabdd66f1561e66" |   resolved "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.52.0.tgz" | ||||||
|   integrity sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw== |   integrity sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw== | ||||||
|  |  | ||||||
| trough@^2.0.0: | trough@^2.0.0: | ||||||
| @@ -3620,7 +3666,7 @@ tslib@^2.4.0, tslib@^2.7.0, tslib@^2.8.0: | |||||||
|  |  | ||||||
| tunnel-rat@^0.1.2: | tunnel-rat@^0.1.2: | ||||||
|   version "0.1.2" |   version "0.1.2" | ||||||
|   resolved "https://registry.yarnpkg.com/tunnel-rat/-/tunnel-rat-0.1.2.tgz#1717efbc474ea2d8aa05a91622457a6e201c0aeb" |   resolved "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz" | ||||||
|   integrity sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ== |   integrity sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ== | ||||||
|   dependencies: |   dependencies: | ||||||
|     zustand "^4.3.2" |     zustand "^4.3.2" | ||||||
| @@ -3741,7 +3787,7 @@ util@^0.10.3: | |||||||
|  |  | ||||||
| utility-types@^3.11.0: | utility-types@^3.11.0: | ||||||
|   version "3.11.0" |   version "3.11.0" | ||||||
|   resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.11.0.tgz#607c40edb4f258915e901ea7995607fdf319424c" |   resolved "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz" | ||||||
|   integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== |   integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== | ||||||
|  |  | ||||||
| vfile-location@^5.0.0: | vfile-location@^5.0.0: | ||||||
| @@ -3789,17 +3835,17 @@ web-namespaces@^2.0.0: | |||||||
|  |  | ||||||
| web-worker@^1.2.0: | web-worker@^1.2.0: | ||||||
|   version "1.5.0" |   version "1.5.0" | ||||||
|   resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.5.0.tgz#71b2b0fbcc4293e8f0aa4f6b8a3ffebff733dcc5" |   resolved "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz" | ||||||
|   integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw== |   integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw== | ||||||
|  |  | ||||||
| webgl-constants@^1.1.1: | webgl-constants@^1.1.1: | ||||||
|   version "1.1.1" |   version "1.1.1" | ||||||
|   resolved "https://registry.yarnpkg.com/webgl-constants/-/webgl-constants-1.1.1.tgz#f9633ee87fea56647a60b9ce735cbdfb891c6855" |   resolved "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz" | ||||||
|   integrity sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg== |   integrity sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg== | ||||||
|  |  | ||||||
| webgl-sdf-generator@1.1.1: | webgl-sdf-generator@1.1.1: | ||||||
|   version "1.1.1" |   version "1.1.1" | ||||||
|   resolved "https://registry.yarnpkg.com/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz#3e1b422b3d87cd3cc77f2602c9db63bc0f6accbd" |   resolved "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz" | ||||||
|   integrity sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA== |   integrity sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA== | ||||||
|  |  | ||||||
| which@^2.0.1: | which@^2.0.1: | ||||||
| @@ -3816,7 +3862,7 @@ word-wrap@^1.2.5: | |||||||
|  |  | ||||||
| xml-utils@^1.0.2: | xml-utils@^1.0.2: | ||||||
|   version "1.10.2" |   version "1.10.2" | ||||||
|   resolved "https://registry.yarnpkg.com/xml-utils/-/xml-utils-1.10.2.tgz#436b39ccc25a663ce367ea21abb717afdea5d6b1" |   resolved "https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.2.tgz" | ||||||
|   integrity sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA== |   integrity sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA== | ||||||
|  |  | ||||||
| yallist@^3.0.2: | yallist@^3.0.2: | ||||||
| @@ -3841,19 +3887,19 @@ yocto-queue@^0.1.0: | |||||||
|  |  | ||||||
| zstddec@^0.1.0: | zstddec@^0.1.0: | ||||||
|   version "0.1.0" |   version "0.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/zstddec/-/zstddec-0.1.0.tgz#7050f3f0e0c3978562d0c566b3e5a427d2bad7ec" |   resolved "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz" | ||||||
|   integrity sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg== |   integrity sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg== | ||||||
|  |  | ||||||
| zustand@^4.3.2: | zustand@^4.3.2: | ||||||
|   version "4.5.7" |   version "4.5.7" | ||||||
|   resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.7.tgz#7d6bb2026a142415dd8be8891d7870e6dbe65f55" |   resolved "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz" | ||||||
|   integrity sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw== |   integrity sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     use-sync-external-store "^1.2.2" |     use-sync-external-store "^1.2.2" | ||||||
|  |  | ||||||
| zustand@^5.0.1, zustand@^5.0.3: | zustand@^5.0.1, zustand@^5.0.3: | ||||||
|   version "5.0.5" |   version "5.0.5" | ||||||
|   resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.5.tgz#3e236f6a953142d975336d179bc735d97db17e84" |   resolved "https://registry.npmjs.org/zustand/-/zustand-5.0.5.tgz" | ||||||
|   integrity sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg== |   integrity sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg== | ||||||
|  |  | ||||||
| zwitch@^2.0.0: | zwitch@^2.0.0: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user