Compare commits

...

2 Commits

Author SHA1 Message Date
0fe4683683 feat: fix sight edit 2025-06-07 15:16:29 +03:00
1104e94ba8 feat: Delete user preview + snapshot preview + coordinates update 2025-06-06 20:15:02 +03:00
27 changed files with 894 additions and 508 deletions

View File

@ -19,9 +19,7 @@ import {
VehicleListPage,
ArticleListPage,
CityPreviewPage,
UserPreviewPage,
CountryPreviewPage,
SnapshotPreviewPage,
VehiclePreviewPage,
CarrierPreviewPage,
SnapshotCreatePage,
@ -132,12 +130,10 @@ const router = createBrowserRouter([
// User
{ path: "user", element: <UserListPage /> },
{ path: "user/:id", element: <UserPreviewPage /> },
// Snapshot
{ path: "snapshot", element: <SnapshotListPage /> },
{ path: "snapshot/create", element: <SnapshotCreatePage /> },
{ path: "snapshot/:id", element: <SnapshotPreviewPage /> },
// Carrier
{ path: "carrier", element: <CarrierListPage /> },

View File

@ -3,3 +3,7 @@
button {
cursor: pointer;
}
.mde-preview {
background-color: #f5f5f5;
}

View File

@ -1,5 +1,10 @@
import { Box, Tab, Tabs } from "@mui/material";
import { articlesStore, cityStore, languageStore } from "@shared";
import {
articlesStore,
cityStore,
createSightStore,
languageStore,
} from "@shared";
import {
CreateInformationTab,
CreateLeftTab,
@ -22,13 +27,15 @@ export const CreateSightPage = observer(() => {
const [value, setValue] = useState(0);
const { getCities } = cityStore;
const { getArticles } = articlesStore;
const { needLeaveAgree } = createSightStore;
const handleChange = (_: React.SyntheticEvent, newValue: number) => {
setValue(newValue);
};
let blocker = useBlocker(
({ currentLocation, nextLocation }) =>
true && currentLocation.pathname !== nextLocation.pathname
needLeaveAgree && currentLocation.pathname !== nextLocation.pathname
);
useEffect(() => {

View File

@ -20,7 +20,7 @@ function a11yProps(index: number) {
export const EditSightPage = observer(() => {
const [value, setValue] = useState(0);
const { sight, getSightInfo } = editSightStore;
const { sight, getSightInfo, needLeaveAgree } = editSightStore;
const { getArticles } = articlesStore;
const { language } = languageStore;
const { id } = useParams();
@ -28,7 +28,7 @@ export const EditSightPage = observer(() => {
let blocker = useBlocker(
({ currentLocation, nextLocation }) =>
true && currentLocation.pathname !== nextLocation.pathname
needLeaveAgree && currentLocation.pathname !== nextLocation.pathname
);
const handleChange = (_: React.SyntheticEvent, newValue: number) => {

View File

@ -1135,7 +1135,7 @@ const MapControls: React.FC<MapControlsProps> = ({
},
{
mode: "statistics",
title: "Инфо",
title: "Информация",
longTitle: "Информация",
icon: <StatsIcon />,
action: () => mapService.activateStatisticsMode(),

View File

@ -4,7 +4,7 @@ import { useEffect, useState } from "react";
import { observer } from "mobx-react-lite";
import { Pencil, Trash2 } from "lucide-react";
import { useNavigate } from "react-router-dom";
import { DeleteModal, LanguageSwitcher } from "@widgets";
import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets";
export const SightListPage = observer(() => {
const { sights, getSights, deleteListSight } = sightsStore;
@ -69,6 +69,13 @@ export const SightListPage = observer(() => {
<LanguageSwitcher />
<div className="w-full">
<div className="flex justify-between items-center mb-10">
<h1 className="text-2xl">Достопримечательности</h1>
<CreateButton
label="Создать достопримечательность"
path="/sight/create"
/>
</div>
<DataGrid
rows={rows}
columns={columns}

View File

@ -53,9 +53,7 @@ export const SnapshotListPage = observer(() => {
>
<DatabaseBackup size={20} className="text-blue-500" />
</button>
<button onClick={() => navigate(`/snapshot/${params.row.id}`)}>
<Eye size={20} className="text-green-500" />
</button>
<button
onClick={() => {
setIsDeleteModalOpen(true);

View File

@ -1,58 +0,0 @@
import { Paper } from "@mui/material";
import { snapshotStore } from "@shared";
import { observer } from "mobx-react-lite";
import { ArrowLeft } from "lucide-react";
import { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
export const SnapshotPreviewPage = observer(() => {
const { id } = useParams();
const { getSnapshot, snapshot } = snapshotStore;
const navigate = useNavigate();
useEffect(() => {
(async () => {
await getSnapshot(id as string);
})();
}, [id]);
return (
<Paper className="w-full h-full p-3 flex flex-col gap-10">
<div className="flex justify-between items-center">
<button
className="flex items-center gap-2"
onClick={() => navigate(-1)}
>
<ArrowLeft size={20} />
Назад
</button>
{/* <div className="flex gap-2">
<Button
variant="contained"
color="primary"
onClick={() => navigate(`/snapshot/${id}/edit`)}
startIcon={<Pencil size={20} />}
>
Редактировать
</Button>
<Button
variant="contained"
color="error"
onClick={() => navigate(`/snapshot/${id}/delete`)}
startIcon={<Trash2 size={20} />}
>
Удалить
</Button>
</div> */}
</div>
{snapshot && (
<div className="flex flex-col gap-10 w-full">
<div className="flex flex-col gap-2">
<h1 className="text-lg font-bold">Название</h1>
<p>{snapshot?.Name}</p>
</div>
</div>
)}
</Paper>
);
});

View File

@ -1,3 +1,3 @@
export * from "./SnapshotListPage";
export * from "./SnapshotPreviewPage";
export * from "./SnapshotCreatePage";

View File

@ -56,9 +56,6 @@ export const UserListPage = observer(() => {
renderCell: (params: GridRenderCellParams) => {
return (
<div className="flex h-full gap-7 justify-center items-center">
<button onClick={() => navigate(`/user/${params.row.id}`)}>
<Eye size={20} className="text-green-500" />
</button>
<button
onClick={() => {
setIsDeleteModalOpen(true);

View File

@ -1,74 +0,0 @@
import { Paper } from "@mui/material";
import { userStore } from "@shared";
import { observer } from "mobx-react-lite";
import { ArrowLeft } from "lucide-react";
import { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
export const UserPreviewPage = observer(() => {
const { id } = useParams();
const { getUser, user } = userStore;
const navigate = useNavigate();
useEffect(() => {
(async () => {
await getUser(Number(id));
})();
}, [id]);
return (
<Paper className="w-full h-full p-3 flex flex-col gap-10">
<div className="flex justify-between items-center">
<button
className="flex items-center gap-2"
onClick={() => navigate(-1)}
>
<ArrowLeft size={20} />
Назад
</button>
{/* <div className="flex gap-2">
<Button
variant="contained"
color="primary"
onClick={() => navigate(`/user/${id}/edit`)}
startIcon={<Pencil size={20} />}
>
Редактировать
</Button>
<Button
variant="contained"
color="error"
onClick={() => navigate(`/user/${id}/delete`)}
startIcon={<Trash2 size={20} />}
>
Удалить
</Button>
</div> */}
</div>
{user && (
<div className="flex flex-col gap-10 w-full">
<div className="flex flex-col gap-2">
<h1 className="text-lg font-bold">Название</h1>
<p>{user?.name}</p>
</div>
<div className="flex flex-col gap-2">
<h1 className="text-lg font-bold">Email</h1>
<p>{user?.email}</p>
</div>
<div className="flex flex-col gap-2">
<h1 className="text-lg font-bold">Роль</h1>
<p
className={
user?.is_admin === true ? "text-green-500" : "text-red-500"
}
>
{user?.is_admin ? "Администратор" : "Пользователь"}
</p>
</div>
</div>
)}
</Paper>
);
});

View File

@ -1,2 +1 @@
export * from "./UserListPage";
export * from "./UserPreviewPage";

View File

@ -202,87 +202,100 @@ export const SelectArticleModal = observer(
)}
</List>
</Paper>
<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="max-h-[80%] overflow-y-scroll mx-auto rounded-[10px]">
<Paper
elevation={3}
sx={{
width: "100%",
height: 175,
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: "3px",
}}
>
{articlesStore.articleMedia ? (
<MediaViewer
media={{
id: articlesStore.articleMedia.id,
media_type: articlesStore.articleMedia.media_type,
filename: articlesStore.articleMedia.filename,
}}
/>
) : (
<ImagePlus size={48} color="white" />
)}
</Box>
minWidth: 320,
maxWidth: 310,
<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",
padding: 0,
margin: "0px auto",
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%)",
overflow: "hidden",
width: "100%",
minHeight: 100,
padding: "3px",
display: "flex",
alignItems: "center",
justifyContent: "center",
"& img": {
borderTopLeftRadius: "10px",
borderTopRightRadius: "10px",
width: "100%",
height: "auto",
objectFit: "contain",
},
}}
>
<ReactMarkdownComponent
value={articlesStore.articleData?.body || "Описание"}
/>
{articlesStore.articleMedia ? (
<MediaViewer
media={{
id: articlesStore.articleMedia.id,
media_type: articlesStore.articleMedia.media_type,
filename: articlesStore.articleMedia.filename,
}}
fullWidth={true}
/>
) : (
<ImagePlus size={48} color="white" />
)}
</Box>
)}
</Paper>
<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>
</Box>
</DialogContent>
<DialogActions sx={{ p: 2 }}>
<Button onClick={onClose}>Отмена</Button>

View File

@ -1,4 +1,4 @@
import { MEDIA_TYPE_LABELS, editSightStore } from "@shared";
import { MEDIA_TYPE_LABELS, MEDIA_TYPE_VALUES, editSightStore } from "@shared";
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";
import {
@ -31,6 +31,7 @@ interface UploadMediaDialogProps {
media_type: number;
}) => void;
afterUploadSight?: (id: string) => void;
hardcodeType?: "thumbnail" | "watermark_lu" | "watermark_rd" | null;
}
export const UploadMediaDialog = observer(
@ -39,6 +40,7 @@ export const UploadMediaDialog = observer(
onClose,
afterUpload,
afterUploadSight,
hardcodeType,
}: UploadMediaDialogProps) => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
@ -165,10 +167,12 @@ export const UploadMediaDialog = observer(
<FormControl fullWidth sx={{ width: "50%" }}>
<InputLabel>Тип медиа</InputLabel>
<Select
value={mediaType}
value={
hardcodeType ? MEDIA_TYPE_VALUES[hardcodeType] : mediaType
}
disabled={!!hardcodeType}
label="Тип медиа"
onChange={(e) => setMediaType(Number(e.target.value))}
disabled={isLoading}
>
{availableMediaTypes.map((type) => (
<MenuItem key={type} value={type}>

View File

@ -98,18 +98,22 @@ class CreateSightStore {
heading: "New Heading (EN)",
body: "New Text (EN)",
};
const articleZhData = { heading: "新标题 (ZH)", body: "新文本 (ZH)" };
const articleZhData = {
heading: "Новый заголовок (ZH)",
body: "Новый текст (ZH)",
};
try {
const articleRes = await languageInstance("ru").post(
"/article",
articleRuData
);
this.needLeaveAgree = true;
const articleRes = await authInstance.post("/article", {
translation: {
ru: articleRuData,
en: articleEnData,
zh: articleZhData,
},
});
const { id } = articleRes.data; // New article's ID
await languageInstance("en").patch(`/article/${id}`, articleEnData);
await languageInstance("zh").patch(`/article/${id}`, articleZhData);
runInAction(() => {
const newArticleEntry = { id, media: [] };
this.sight.ru.right.push({ ...newArticleEntry, ...articleRuData });
@ -376,6 +380,7 @@ class CreateSightStore {
// --- General Store Methods ---
clearCreateSight = () => {
this.needLeaveAgree = false;
this.sight = JSON.parse(JSON.stringify(initialSightState)); // Reset to initial
};
@ -383,6 +388,7 @@ class CreateSightStore {
content: Partial<SightLanguageInfo | SightCommonInfo>, // Corrected types
language?: Language
) => {
this.needLeaveAgree = true;
if (language) {
this.sight[language] = { ...this.sight[language], ...content };
} else {
@ -587,10 +593,31 @@ class CreateSightStore {
}
};
updateRightArticles = async (articles: any[], language: Language) => {
runInAction(() => {
this.sight[language].right = articles;
});
updateRightArticles = async (articles: any[]) => {
const articlesIds = articles.map((article) => article.id);
const sortArticles = (existing: any[]) => {
const articleMap = new Map(
existing.map((article) => [article.id, article])
);
return articlesIds
.map((id) => articleMap.get(id))
.filter(
(article): article is (typeof existing)[number] =>
article !== undefined
);
};
this.sight.ru.right = sortArticles(this.sight.ru.right);
this.sight.en.right = sortArticles(this.sight.en.right);
this.sight.zh.right = sortArticles(this.sight.zh.right); // теперь zh тоже сортируется одинаково
this.needLeaveAgree = true;
};
needLeaveAgree = false;
setNeedLeaveAgree = (need: boolean) => {
this.needLeaveAgree = need;
};
}

View File

@ -170,6 +170,7 @@ class EditSightStore {
};
clearSightInfo = () => {
this.needLeaveAgree = false;
this.sight = {
common: {
id: 0,
@ -215,6 +216,7 @@ class EditSightStore {
content: Partial<SightLanguageInfo | SightCommonInfo>,
common: boolean = false
) => {
this.needLeaveAgree = true;
if (common) {
this.sight.common = {
...this.sight.common,
@ -262,61 +264,72 @@ class EditSightStore {
this.sight.common.left_article != 0 &&
this.sight.common.left_article != null
) {
await languageInstance("ru").patch(
`/article/${this.sight.common.left_article}`,
{
heading: this.sight.ru.left.heading,
body: this.sight.ru.left.body,
}
);
await languageInstance("en").patch(
`/article/${this.sight.common.left_article}`,
{
heading: this.sight.en.left.heading,
body: this.sight.en.left.body,
}
);
await languageInstance("zh").patch(
`/article/${this.sight.common.left_article}`,
{
heading: this.sight.zh.left.heading,
body: this.sight.zh.left.body,
}
);
await authInstance.patch(`/article/${this.sight.common.left_article}`, {
translation: {
ru: {
heading: this.sight.ru.left.heading,
body: this.sight.ru.left.body,
},
en: {
heading: this.sight.en.left.heading,
body: this.sight.en.left.body,
},
zh: {
heading: this.sight.zh.left.heading,
body: this.sight.zh.left.body,
},
},
});
}
await languageInstance("ru").patch(`/sight/${this.sight.common.id}`, {
await authInstance.patch(`/sight/${this.sight.common.id}`, {
...this.sight.common,
name: this.sight.ru.name,
address: this.sight.ru.address,
left_article: createdLeftArticleId,
});
await languageInstance("en").patch(`/sight/${this.sight.common.id}`, {
...this.sight.common,
name: this.sight.en.name,
address: this.sight.en.address,
left_article: createdLeftArticleId,
});
await languageInstance("zh").patch(`/sight/${this.sight.common.id}`, {
...this.sight.common,
name: this.sight.zh.name,
address: this.sight.zh.address,
left_article: createdLeftArticleId,
translation: {
ru: {
name: this.sight.ru.name,
address: this.sight.ru.address,
},
en: {
name: this.sight.en.name,
address: this.sight.en.address,
},
zh: {
name: this.sight.zh.name,
address: this.sight.zh.address,
},
},
});
for (const language of ["ru", "en", "zh"] as Language[]) {
for (const article of this.sight[language].right) {
if (article.id == 0 || article.id == null) {
continue;
}
await languageInstance(language).patch(`/article/${article.id}`, {
heading: article.heading,
body: article.body,
});
for (const article of this.sight.ru.right) {
if (article.id == 0 || article.id == null) {
continue;
}
await authInstance.patch(`/article/${article.id}`, {
translation: {
ru: {
heading: article.heading,
body: article.body,
},
en: {
heading: article.heading,
body: article.body,
},
zh: {
heading: article.heading,
body: article.body,
},
},
});
}
const articleIdsInObject = this.sight.ru.right.map((article) => ({
id: article.id,
}));
await authInstance.post(`/sight/${this.sight.common.id}/article/order`, {
articles: articleIdsInObject,
});
// await languageInstance("ru").patch(
// `/sight/${this.sight.common.left_article}/article`,
// {
@ -578,19 +591,27 @@ class EditSightStore {
};
createNewRightArticle = async () => {
const articleId = await languageInstance("ru").post("/article", {
heading: "Введите русский заголовок",
body: "Введите русский текст",
const articleRuData = {
heading: "Новый заголовок (RU)",
body: "Новый текст (RU)",
};
const articleEnData = {
heading: "New Heading (EN)",
body: "New Text (EN)",
};
const articleZhData = {
heading: "Новый заголовок (ZH)",
body: "Новый текст (ZH)",
};
const articleId = await authInstance.post("/article", {
translation: {
ru: articleRuData,
en: articleEnData,
zh: articleZhData,
},
});
const { id } = articleId.data;
await languageInstance("en").patch(`/article/${id}`, {
heading: "Enter the English heading",
body: "Enter the English text",
});
await languageInstance("zh").patch(`/article/${id}`, {
heading: "Введите китайский заголовок",
body: "Введите китайский текст",
});
await authInstance.post(`/sight/${this.sight.common.id}/article`, {
article_id: id,
page_num: this.sight.ru.right.length + 1,
@ -598,20 +619,20 @@ class EditSightStore {
this.sight.ru.right.push({
id: id,
heading: "Введите русский заголовок",
body: "Введите русский текст",
heading: articleRuData.heading,
body: articleRuData.body,
media: [],
});
this.sight.en.right.push({
id: id,
heading: "Enter the English heading",
body: "Enter the English text",
heading: articleEnData.heading,
body: articleEnData.body,
media: [],
});
this.sight.zh.right.push({
id: id,
heading: "Введите китайский заголовок",
body: "Введите китайский текст",
heading: articleZhData.heading,
body: articleZhData.body,
media: [],
});
};
@ -671,14 +692,31 @@ class EditSightStore {
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,
});
updateRightArticles = async (articles: any[]) => {
const articlesIds = articles.map((article) => article.id);
const sortArticles = (existing: any[]) => {
const articleMap = new Map(
existing.map((article) => [article.id, article])
);
return articlesIds
.map((id) => articleMap.get(id))
.filter(
(article): article is (typeof existing)[number] =>
article !== undefined
);
};
this.sight.ru.right = sortArticles(this.sight.ru.right);
this.sight.en.right = sortArticles(this.sight.en.right);
this.sight.zh.right = sortArticles(this.sight.zh.right); // теперь zh тоже сортируется одинаково
this.needLeaveAgree = true;
};
needLeaveAgree = false;
setNeedLeaveAgree = (need: boolean) => {
this.needLeaveAgree = need;
};
}

View File

@ -1,8 +1,8 @@
import React, { useRef, useState, DragEvent, useEffect } from "react";
import { Paper, Box, Typography, Button, Tooltip } from "@mui/material";
import { X, Info, MousePointer } from "lucide-react"; // Assuming lucide-react for icons
import { X, Info, Plus } from "lucide-react"; // Assuming lucide-react for icons
import { editSightStore } from "@shared";
import { toast } from "react-toastify";
interface ImageUploadCardProps {
title: string;
imageKey?: "thumbnail" | "watermark_lu" | "watermark_rd";
@ -12,16 +12,18 @@ interface ImageUploadCardProps {
onSelectFileClick: () => void;
setUploadMediaOpen: (open: boolean) => void;
tooltipText?: string;
setHardcodeType?: (type: string) => void;
}
export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({
title,
imageKey,
imageUrl,
onImageClick,
onDeleteImageClick,
onSelectFileClick,
setUploadMediaOpen,
setHardcodeType,
tooltipText,
}) => {
const fileInputRef = useRef<HTMLInputElement>(null);
@ -46,6 +48,9 @@ export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({
if (file) {
setFileToUpload(file);
setUploadMediaOpen(true);
if (imageKey && setHardcodeType) {
setHardcodeType(imageKey);
}
}
// Reset the input value so selecting the same file again triggers change
event.target.value = "";
@ -73,8 +78,12 @@ export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({
const files = event.dataTransfer.files;
if (files && files.length > 0) {
const file = files[0];
setFileToUpload(file);
setUploadMediaOpen(true);
if (file.type.startsWith("image/")) {
setFileToUpload(file);
setUploadMediaOpen(true);
} else {
toast.error("Пожалуйста, выберите изображение");
}
}
};
@ -159,7 +168,7 @@ export const ImageUploadCard: React.FC<ImageUploadCardProps> = ({
<Button
variant="contained"
color="primary"
startIcon={<MousePointer color="white" size={18} />}
startIcon={<Plus color="white" size={18} />}
onClick={(e) => {
e.stopPropagation(); // Prevent `handleZoneClick` from firing
onSelectFileClick(); // This button might trigger a different modal

View File

@ -96,10 +96,10 @@ export const MediaArea = observer(
</Button>
</div>
<div className="w-full flex flex-start flex-wrap gap-2 mt-4">
<div className="w-full flex flex-start flex-wrap gap-2 mt-4 py-10">
{mediaIds.map((m) => (
<button
className="relative w-40 h-40"
className="relative w-20 h-20"
key={m.id}
onClick={() => handleMediaModal(m.id)}
>

View File

@ -12,29 +12,17 @@ export interface MediaData {
export function MediaViewer({
media,
className,
}: Readonly<{ media?: MediaData; className?: string }>) {
fullWidth,
}: Readonly<{ media?: MediaData; className?: string; fullWidth?: boolean }>) {
const token = localStorage.getItem("token");
return (
<Box
sx={{
width: "100%",
height: "100%",
display: "flex",
flexGrow: 1,
}}
className={className}
>
<Box className={className} width={fullWidth ? "100%" : "auto"}>
{media?.media_type === 1 && (
<img
src={`${import.meta.env.VITE_KRBL_MEDIA}${
media?.id
}/download?token=${token}`}
alt={media?.filename}
style={{
width: "100%",
height: "100%",
objectFit: "contain",
}}
/>
)}
@ -46,7 +34,7 @@ export function MediaViewer({
style={{
width: "100%",
height: "100%",
objectFit: "contain",
objectFit: "cover",
borderRadius: 8,
}}
controls
@ -60,12 +48,6 @@ export function MediaViewer({
media?.id
}/download?token=${token}`}
alt={media?.filename}
style={{
width: "100%",
height: "100%",
objectFit: "contain",
borderRadius: 8,
}}
/>
)}
{media?.media_type === 4 && (
@ -75,10 +57,7 @@ export function MediaViewer({
}/download?token=${token}`}
alt={media?.filename}
style={{
width: "100%",
height: "100%",
objectFit: "contain",
borderRadius: 8,
objectFit: "cover",
}}
/>
)}

View File

@ -1,5 +1,6 @@
import { useMemo } from "react";
import { styled } from "@mui/material/styles";
import SimpleMDE, { SimpleMDEReactProps } from "react-simplemde-editor";
import SimpleMDE from "react-simplemde-editor";
import "easymde/dist/easymde.min.css";
const StyledMarkdownEditor = styled("div")(({ theme }) => ({
@ -19,28 +20,32 @@ const StyledMarkdownEditor = styled("div")(({ theme }) => ({
"& .editor-statusbar": {
display: "none",
},
// Стили для самого редактора
"& .CodeMirror": {
backgroundColor: theme.palette.background.paper,
color: theme.palette.text.primary,
borderColor: theme.palette.divider,
height: "auto",
minHeight: "200px",
minHeight: "400px",
maxHeight: "500px",
overflow: "auto",
overflowY: "auto",
overflowX: "hidden",
wordWrap: "break-word", // ✅ добавлено
whiteSpace: "pre-wrap", // ✅ добавлено
},
"& .CodeMirror-scroll": {
minHeight: "200px",
minHeight: "400px",
maxHeight: "500px",
overflowY: "auto",
overflowX: "hidden",
wordBreak: "break-word", // ✅ добавлено
},
// Стили для текста в редакторе
"& .CodeMirror-selected": {
backgroundColor: `${theme.palette.action.selected} !important`,
},
"& .CodeMirror-cursor": {
borderLeftColor: theme.palette.text.primary,
},
// Стили для markdown разметки
"& .cm-header": {
color: theme.palette.primary.main,
},
@ -57,13 +62,11 @@ const StyledMarkdownEditor = styled("div")(({ theme }) => ({
"& .cm-formatting": {
color: theme.palette.text.secondary,
},
"& .CodeMirror .editor-preview-full": {
backgroundColor: theme.palette.background.paper,
color: theme.palette.text.primary,
borderColor: theme.palette.divider,
},
"& .EasyMDEContainer": {
position: "relative",
zIndex: 1000,
@ -73,45 +76,56 @@ const StyledMarkdownEditor = styled("div")(({ theme }) => ({
},
}));
export const ReactMarkdownEditor = (props: SimpleMDEReactProps) => {
if (props.options)
props.options.toolbar = [
"bold",
"italic",
"strikethrough",
{
name: "Underline",
action: (editor: any) => {
const cm = editor.codemirror;
let output = "";
const selectedText = cm.getSelection();
const text = selectedText ?? "placeholder";
output = "<u>" + text + "</u>";
cm.replaceSelection(output);
},
className: "fa fa-underline", // Look for a suitable icon
title: "Underline (Ctrl/Cmd-Alt-U)",
export const ReactMarkdownEditor = ({
options: incomingOptions,
...restProps
}: any) => {
const mergedOptions = useMemo(() => {
return {
...incomingOptions,
codeMirrorOptions: {
lineWrapping: true,
},
"heading",
"quote",
"unordered-list",
"ordered-list",
"link",
"image",
"code",
"table",
"horizontal-rule",
"preview",
"fullscreen",
"guide",
];
forceSync: true,
spellChecker: false,
toolbar: [
"bold",
"italic",
"strikethrough",
{
name: "Underline",
action: (editor: any) => {
const cm = editor.codemirror;
const selectedText = cm.getSelection();
const text = selectedText || "placeholder";
const output = `<u>${text}</u>`;
cm.replaceSelection(output);
},
className: "fa fa-underline",
title: "Underline (Ctrl/Cmd-Alt-U)",
},
"heading",
"quote",
"unordered-list",
"ordered-list",
"link",
"image",
"code",
"table",
"horizontal-rule",
"preview",
"fullscreen",
"guide",
],
};
}, []); // создаётся один раз
return (
<StyledMarkdownEditor
className="my-markdown-editor"
sx={{ marginTop: 1.5, marginBottom: 3 }}
>
<SimpleMDE {...props} />
<SimpleMDE options={mergedOptions} {...restProps} />
</StyledMarkdownEditor>
);
};

View File

@ -40,7 +40,7 @@ export const CreateInformationTab = observer(
const data = sight[language];
const [, setCity] = useState<number>(sight.city_id ?? 0);
const [coordinates, setCoordinates] = useState<string>(`0 0`);
const [coordinates, setCoordinates] = useState<string>(`0, 0`);
// Menu state for each media button
const [menuAnchorEl, setMenuAnchorEl] = useState<null | HTMLElement>(null);
@ -48,6 +48,9 @@ export const CreateInformationTab = observer(
"thumbnail" | "watermark_lu" | "watermark_rd" | null
>(null);
const [isAddMediaOpen, setIsAddMediaOpen] = useState(false);
const [hardcodeType, setHardcodeType] = useState<
"thumbnail" | "watermark_lu" | "watermark_rd" | null
>(null);
// const handleMenuOpen = (
// event: React.MouseEvent<HTMLElement>,
@ -60,7 +63,7 @@ export const CreateInformationTab = observer(
useEffect(() => {
// Показывать только при инициализации (не менять при ошибках пользователя)
if (sight.latitude !== 0 || sight.longitude !== 0) {
setCoordinates(`${sight.latitude} ${sight.longitude}`);
setCoordinates(`${sight.latitude}, ${sight.longitude}`);
}
// если координаты обнулились — оставить поле как есть
}, [sight.latitude, sight.longitude]);
@ -260,10 +263,15 @@ export const CreateInformationTab = observer(
setIsUploadMediaOpen(true);
setActiveMenuType("thumbnail");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
}}
/>
<ImageUploadCard
title="Водяной знак (л.в)"
title="Водяной знак (леввый верхний)"
imageKey="watermark_lu"
imageUrl={sight.watermark_lu}
onImageClick={() => {
@ -284,10 +292,15 @@ export const CreateInformationTab = observer(
setIsUploadMediaOpen(true);
setActiveMenuType("watermark_lu");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
}}
/>
<ImageUploadCard
title="Водяной знак (п.в)"
title="Водяной знак (правый нижний)"
imageKey="watermark_rd"
imageUrl={sight.watermark_rd}
onImageClick={() => {
@ -308,6 +321,11 @@ export const CreateInformationTab = observer(
setIsUploadMediaOpen(true);
setActiveMenuType("watermark_rd");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
}}
/>
</Box>
</Box>
@ -397,6 +415,7 @@ export const CreateInformationTab = observer(
setActiveMenuType(null);
setIsUploadMediaOpen(false);
}}
hardcodeType={hardcodeType}
/>
</>
);

View File

@ -9,6 +9,7 @@ import {
createSightStore,
SelectArticleModal,
UploadMediaDialog,
Language,
} from "@shared";
import {
LanguageSwitcher,
@ -308,8 +309,8 @@ export const CreateLeftTab = observer(
flex: 1,
display: "flex",
flexDirection: "column",
gap: 1.5,
maxWidth: "320px",
gap: 0.5,
}}
>
<Paper
@ -317,49 +318,32 @@ export const CreateLeftTab = observer(
sx={{
width: "100%",
minWidth: 320,
maxWidth: 400,
height: "auto",
minHeight: 500,
backgroundColor: "#877361",
background:
"#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)",
overflowY: "auto",
padding: 0,
display: "flex",
flexDirection: "column",
}}
>
{/* {data.left.media?.filename ? (
<Box
sx={{
width: "100%",
height: 200,
backgroundColor: "grey.300",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<img
src={data.left.media?.filename ?? ""}
alt="Превью медиа"
style={{
objectFit: "cover",
width: "100%",
height: "100%",
}}
/>
</Box>
) : (
)} */}
flexDirection: "column",
borderRadius: "10px",
}}
>
<Box
sx={{
overflow: "hidden",
width: "100%",
height: 200,
backgroundColor: "grey.300",
minHeight: 100,
padding: "3px",
display: "flex",
alignItems: "center",
justifyContent: "center",
"& img": {
borderTopLeftRadius: "10px",
borderTopRightRadius: "10px",
width: "100%",
height: "auto",
objectFit: "contain",
},
}}
>
{sight[language].left.media.length > 0 ? (
@ -370,40 +354,67 @@ export const CreateLeftTab = observer(
sight[language].left.media[0].media_type,
filename: sight[language].left.media[0].filename,
}}
fullWidth
/>
) : (
<ImagePlus size={48} color="grey" />
<ImagePlus size={48} color="white" />
)}
</Box>
{/* Заголовок в превью */}
<Box
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",
padding: 1.5,
margin: "5px 0px 5px 0px",
display: "flex",
flexDirection: "column",
gap: 1,
padding: 1,
}}
>
<Typography
variant="h5"
component="h2"
sx={{ wordBreak: "break-word" }}
sx={{
wordBreak: "break-word",
fontSize: "24px",
fontWeight: 700,
lineHeight: "120%",
}}
>
{sight[language].left.heading || "Название информации"}
</Typography>
<Typography
variant="h6"
component="h2"
sx={{
wordBreak: "break-word",
fontSize: "18px",
lineHeight: "120%",
}}
>
{sight[language as Language].address}
</Typography>
</Box>
{/* Текст статьи в превью */}
<Box
sx={{
padding: 2,
flexGrow: 1,
}}
>
<ReactMarkdownComponent
value={sight[language].left.body}
/>
</Box>
{sight[language].left.body && (
<Box
sx={{
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,
}}
>
<ReactMarkdownComponent
value={sight[language].left.body}
/>
</Box>
)}
</Paper>
</Box>
</Box>

View File

@ -239,7 +239,7 @@ export const CreateRightTab = observer(
// 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);
updateRightArticles(newRightArticles);
};
return (
@ -418,7 +418,7 @@ export const CreateRightTab = observer(
<Box sx={{ minHeight: 200, flexGrow: 1 }}>
<ReactMarkdownEditor
value={currentRightArticle.body}
onChange={(mdValue) =>
onChange={(mdValue: any) =>
activeArticleIndex !== null &&
updateRightArticleInfo(
activeArticleIndex,
@ -511,7 +511,7 @@ export const CreateRightTab = observer(
<Paper
className="flex-1 flex flex-col max-w-[500px]"
sx={{
borderRadius: "16px",
borderRadius: "10px",
overflow: "hidden",
}}
elevation={2}
@ -531,13 +531,17 @@ export const CreateRightTab = observer(
0 ? (
<Box
sx={{
overflow: "hidden",
width: "100%",
maxHeight: "290px",
flexShrink: 0,
padding: "2px 2px 0px 2px",
display: "flex",
alignItems: "center",
justifyContent: "center",
"& img": {
borderTopLeftRadius: "10px",
borderTopRightRadius: "10px",
width: "100%",
height: "auto",
objectFit: "contain",
},
}}
>
<MediaViewer
@ -571,6 +575,7 @@ export const CreateRightTab = observer(
fontWeight: 700,
lineHeight: "120%",
backdropFilter: "blur(12px)",
borderBottom: "1px solid #A89F90",
boxShadow:
"inset 4px 4px 12px 0 rgba(255,255,255,0.12)",
background:

View File

@ -42,7 +42,7 @@ export const InformationTab = observer(
const { sight, updateSightInfo, updateSight } = editSightStore;
const [, setCity] = useState<number>(sight.common.city_id ?? 0);
const [coordinates, setCoordinates] = useState<string>(`0 0`);
const [coordinates, setCoordinates] = useState<string>(`0, 0`);
// Menu state for each media button
const [menuAnchorEl, setMenuAnchorEl] = useState<null | HTMLElement>(null);
@ -50,11 +50,13 @@ export const InformationTab = observer(
"thumbnail" | "watermark_lu" | "watermark_rd" | null
>(null);
const [isAddMediaOpen, setIsAddMediaOpen] = useState(false);
const [hardcodeType, setHardcodeType] = useState<
"thumbnail" | "watermark_lu" | "watermark_rd" | null
>(null);
useEffect(() => {
// Показывать только при инициализации (не менять при ошибках пользователя)
if (sight.common.latitude !== 0 || sight.common.longitude !== 0) {
setCoordinates(`${sight.common.latitude} ${sight.common.longitude}`);
setCoordinates(`${sight.common.latitude}, ${sight.common.longitude}`);
}
// если координаты обнулились — оставить поле как есть
}, [sight.common.latitude, sight.common.longitude]);
@ -178,10 +180,12 @@ export const InformationTab = observer(
label="Координаты"
value={coordinates}
onChange={(e) => {
const input = e.target.value;
setCoordinates(input); // показываем как есть
const newValue = e.target.value;
setCoordinates(newValue); // сохраняем ввод пользователя как есть
const [latStr, lonStr] = input.split(/\s+/); // учитываем любые пробелы
// Обрабатываем значение для сохранения
const input = newValue.replace(/,/g, " ").trim();
const [latStr, lonStr] = input.split(/\s+/);
const lat = parseFloat(latStr);
const lon = parseFloat(lonStr);
@ -212,7 +216,7 @@ export const InformationTab = observer(
}}
fullWidth
variant="outlined"
placeholder="Введите координаты в формате: широта долгота"
placeholder="Введите координаты в формате: широта долгота (можно использовать запятые или пробелы)"
/>
</Box>
@ -258,9 +262,14 @@ export const InformationTab = observer(
setIsUploadMediaOpen(true);
setActiveMenuType("thumbnail");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
}}
/>
<ImageUploadCard
title="Водяной знак (л.в)"
title="Водяной знак (левый верхний)"
imageKey="watermark_lu"
imageUrl={sight.common.watermark_lu}
onImageClick={() => {
@ -285,9 +294,14 @@ export const InformationTab = observer(
setIsUploadMediaOpen(true);
setActiveMenuType("watermark_lu");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
}}
/>
<ImageUploadCard
title="Водяной знак (п.в)"
title="Водяной знак (правый нижний)"
imageKey="watermark_rd"
imageUrl={sight.common.watermark_rd}
onImageClick={() => {
@ -312,6 +326,11 @@ export const InformationTab = observer(
setIsUploadMediaOpen(true);
setActiveMenuType("watermark_rd");
}}
setHardcodeType={(type) => {
setHardcodeType(
type as "thumbnail" | "watermark_lu" | "watermark_rd"
);
}}
/>
</Box>
</Box>
@ -397,6 +416,7 @@ export const InformationTab = observer(
setActiveMenuType(null);
setIsUploadMediaOpen(false);
}}
hardcodeType={hardcodeType}
/>
<PreviewMediaDialog
open={isPreviewMediaOpen}

View File

@ -260,22 +260,32 @@ export const LeftWidgetTab = observer(
sx={{
width: "100%",
minWidth: 320,
background:
"#806c59 linear-gradient(90deg, rgba(255, 255, 255, 0.2) 12.5%, rgba(255, 255, 255, 0.2) 100%)",
overflowY: "auto",
padding: 0,
display: "flex",
flexDirection: "column",
borderRadius: "10px",
}}
>
<Box
sx={{
overflow: "hidden",
width: "100%",
height: 175,
minHeight: 100,
padding: "3px",
display: "flex",
alignItems: "center",
padding: "3px",
justifyContent: "center",
"& img": {
borderTopLeftRadius: "10px",
borderTopRightRadius: "10px",
width: "100%",
height: "auto",
objectFit: "contain",
},
}}
>
{data.left.media.length > 0 ? (
@ -285,9 +295,10 @@ export const LeftWidgetTab = observer(
media_type: data.left.media[0].media_type,
filename: data.left.media[0].filename,
}}
fullWidth
/>
) : (
<ImagePlus size={48} color="grey" />
<ImagePlus size={48} color="white" />
)}
</Box>

View File

@ -182,7 +182,7 @@ export const RightWidgetTab = observer(
// 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);
updateRightArticles(newRightArticles);
};
return (
@ -347,7 +347,7 @@ export const RightWidgetTab = observer(
value={
sight[language].right[activeArticleIndex].body
}
onChange={(value) =>
onChange={(value: any) =>
updateRightArticleInfo(
activeArticleIndex,
language,
@ -381,11 +381,11 @@ export const RightWidgetTab = observer(
</Box>
)}
{type === "media" && (
<Box className="w-[80%] border border-gray-300 rounded-2xl relative">
<Box className="w-[80%] border border-gray-300 rounded-2xl relative flex justify-center items-center">
{sight.common.preview_media && (
<>
{type === "media" && (
<Box className="w-[80%] h-full rounded-2xl relative flex items-center justify-center">
<Box className="w-full h-full rounded-2xl relative flex items-center justify-center">
{previewMedia && (
<>
<Box className="absolute top-4 right-4 z-10">
@ -397,7 +397,7 @@ export const RightWidgetTab = observer(
</button>
</Box>
<Box className="w-1/2 h-1/2">
<Box className="w-1/2 h-1/2 flex justify-center items-center">
<MediaViewer
media={{
id: previewMedia.id || "",
@ -453,7 +453,7 @@ export const RightWidgetTab = observer(
<Paper
className="flex-1 flex flex-col max-w-[500px]"
sx={{
borderRadius: "16px",
borderRadius: "10px",
overflow: "hidden",
}}
elevation={2}
@ -473,13 +473,17 @@ export const RightWidgetTab = observer(
0 ? (
<Box
sx={{
overflow: "hidden",
width: "100%",
maxHeight: "290px",
flexShrink: 0,
padding: "2px 2px 0px 2px",
display: "flex",
alignItems: "center",
justifyContent: "center",
"& img": {
borderTopLeftRadius: "10px",
borderTopRightRadius: "10px",
width: "100%",
height: "auto",
objectFit: "contain",
},
}}
>
<MediaViewer
@ -513,6 +517,7 @@ export const RightWidgetTab = observer(
fontWeight: 700,
lineHeight: "120%",
backdropFilter: "blur(12px)",
borderBottom: "1px solid #A89F90",
boxShadow:
"inset 4px 4px 12px 0 rgba(255,255,255,0.12)",
background:

435
yarn.lock
View File

@ -24,7 +24,7 @@
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz"
integrity sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.26.10":
"@babel/core@^7.26.10":
version "7.27.3"
resolved "https://registry.npmjs.org/@babel/core/-/core-7.27.3.tgz"
integrity sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==
@ -173,6 +173,28 @@
resolved "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz"
integrity sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==
"@emnapi/core@^1.4.3":
version "1.4.3"
resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.3.tgz#9ac52d2d5aea958f67e52c40a065f51de59b77d6"
integrity sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==
dependencies:
"@emnapi/wasi-threads" "1.0.2"
tslib "^2.4.0"
"@emnapi/runtime@^1.4.3":
version "1.4.3"
resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.3.tgz#c0564665c80dc81c448adac23f9dfbed6c838f7d"
integrity sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==
dependencies:
tslib "^2.4.0"
"@emnapi/wasi-threads@1.0.2", "@emnapi/wasi-threads@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz#977f44f844eac7d6c138a415a123818c655f874c"
integrity sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==
dependencies:
tslib "^2.4.0"
"@emotion/babel-plugin@^11.13.5":
version "11.13.5"
resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz"
@ -218,7 +240,7 @@
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.14.0", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0", "@emotion/react@^11.9.0":
"@emotion/react@^11.14.0":
version "11.14.0"
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz"
integrity sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==
@ -248,7 +270,7 @@
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
"@emotion/styled@^11.14.0", "@emotion/styled@^11.3.0", "@emotion/styled@^11.8.1":
"@emotion/styled@^11.14.0":
version "11.14.0"
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz"
integrity sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==
@ -280,11 +302,131 @@
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
"@esbuild/aix-ppc64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18"
integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==
"@esbuild/android-arm64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f"
integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==
"@esbuild/android-arm@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26"
integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==
"@esbuild/android-x64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff"
integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==
"@esbuild/darwin-arm64@0.25.5":
version "0.25.5"
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz"
integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==
"@esbuild/darwin-x64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418"
integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==
"@esbuild/freebsd-arm64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c"
integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==
"@esbuild/freebsd-x64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f"
integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==
"@esbuild/linux-arm64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8"
integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==
"@esbuild/linux-arm@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911"
integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==
"@esbuild/linux-ia32@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783"
integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==
"@esbuild/linux-loong64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506"
integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==
"@esbuild/linux-mips64el@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96"
integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==
"@esbuild/linux-ppc64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9"
integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==
"@esbuild/linux-riscv64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e"
integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==
"@esbuild/linux-s390x@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d"
integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==
"@esbuild/linux-x64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4"
integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==
"@esbuild/netbsd-arm64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d"
integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==
"@esbuild/netbsd-x64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79"
integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==
"@esbuild/openbsd-arm64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd"
integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==
"@esbuild/openbsd-x64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0"
integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==
"@esbuild/sunos-x64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5"
integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==
"@esbuild/win32-arm64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e"
integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==
"@esbuild/win32-ia32@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d"
integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==
"@esbuild/win32-x64@0.25.5":
version "0.25.5"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1"
integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.7.0":
version "4.7.0"
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz"
@ -333,7 +475,7 @@
minimatch "^3.1.2"
strip-json-comments "^3.1.1"
"@eslint/js@^9.25.0", "@eslint/js@9.27.0":
"@eslint/js@9.27.0", "@eslint/js@^9.25.0":
version "9.27.0"
resolved "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz"
integrity sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==
@ -446,7 +588,7 @@
resolved "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.0.tgz"
integrity sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==
"@mui/material@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/material@^7.1.0":
"@mui/material@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/material/-/material-7.1.0.tgz"
integrity sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==
@ -485,7 +627,7 @@
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^5.15.14 || ^6.0.0 || ^7.0.0", "@mui/system@^7.1.0":
"@mui/system@^7.1.0":
version "7.1.0"
resolved "https://registry.npmjs.org/@mui/system/-/system-7.1.0.tgz"
integrity sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==
@ -539,6 +681,15 @@
"@babel/runtime" "^7.27.4"
"@mui/utils" "^7.1.1"
"@napi-rs/wasm-runtime@^0.2.10":
version "0.2.10"
resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.10.tgz#f3b7109419c6670000b2401e0c778b98afc25f84"
integrity sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==
dependencies:
"@emnapi/core" "^1.4.3"
"@emnapi/runtime" "^1.4.3"
"@tybys/wasm-util" "^0.9.0"
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
@ -547,7 +698,7 @@
"@nodelib/fs.stat" "2.0.5"
run-parallel "^1.1.9"
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
version "2.0.5"
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
@ -565,7 +716,7 @@
resolved "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz"
integrity sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==
"@photo-sphere-viewer/core@^5.13.2", "@photo-sphere-viewer/core@>=5.13.1":
"@photo-sphere-viewer/core@^5.13.2":
version "5.13.2"
resolved "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.13.2.tgz"
integrity sha512-rL4Ey39Prx4Iyxt1f2tAqlXvqu4/ovXfUvIpLt540OpZJiFjWccs6qLywof9vuhBJ7PXHudHWCjRPce0W8kx8w==
@ -604,7 +755,7 @@
utility-types "^3.11.0"
zustand "^5.0.1"
"@react-three/fiber@^9.0.0", "@react-three/fiber@^9.1.2":
"@react-three/fiber@^9.1.2":
version "9.1.2"
resolved "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.1.2.tgz"
integrity sha512-k8FR9yVHV9kIF3iuOD0ds5hVymXYXfgdKklqziBVod9ZEJ8uk05Zjw29J/omU3IKeUfLNAIHfxneN3TUYM4I2w==
@ -627,11 +778,106 @@
resolved "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.9.tgz"
integrity sha512-e9MeMtVWo186sgvFFJOPGy7/d2j2mZhLJIdVW0C/xDluuOvymEATqz6zKsP0ZmXGzQtqlyjz5sC1sYQUoJG98w==
"@rollup/rollup-android-arm-eabi@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz#f39f09f60d4a562de727c960d7b202a2cf797424"
integrity sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==
"@rollup/rollup-android-arm64@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz#d19af7e23760717f1d879d4ca3d2cd247742dff2"
integrity sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==
"@rollup/rollup-darwin-arm64@4.41.1":
version "4.41.1"
resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz"
integrity sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==
"@rollup/rollup-darwin-x64@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz#aa66d2ba1a25e609500e13bef06dc0e71cc0c0d4"
integrity sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==
"@rollup/rollup-freebsd-arm64@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz#df10a7b6316a0ef1028c6ca71a081124c537e30d"
integrity sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==
"@rollup/rollup-freebsd-x64@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz#a3fdce8a05e95b068cbcb46e4df5185e407d0c35"
integrity sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==
"@rollup/rollup-linux-arm-gnueabihf@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz#49f766c55383bd0498014a9d76924348c2f3890c"
integrity sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==
"@rollup/rollup-linux-arm-musleabihf@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz#1d4d7d32fc557e17d52e1857817381ea365e2959"
integrity sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==
"@rollup/rollup-linux-arm64-gnu@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz#f4fc317268441e9589edad3be8f62b6c03009bc1"
integrity sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==
"@rollup/rollup-linux-arm64-musl@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz#63a1f1b0671cb17822dabae827fef0e443aebeb7"
integrity sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==
"@rollup/rollup-linux-loongarch64-gnu@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz#c659b01cc6c0730b547571fc3973e1e955369f98"
integrity sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==
"@rollup/rollup-linux-powerpc64le-gnu@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz#612e746f9ad7e58480f964d65e0d6c3f4aae69a8"
integrity sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==
"@rollup/rollup-linux-riscv64-gnu@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz#4610dbd1dcfbbae32fbc10c20ae7387acb31110c"
integrity sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==
"@rollup/rollup-linux-riscv64-musl@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz#054911fab40dc83fafc21e470193c058108f19d8"
integrity sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==
"@rollup/rollup-linux-s390x-gnu@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz#98896eca8012547c7f04bd07eaa6896825f9e1a5"
integrity sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==
"@rollup/rollup-linux-x64-gnu@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz#01cf56844a1e636ee80dfb364e72c2b7142ad896"
integrity sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==
"@rollup/rollup-linux-x64-musl@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz#e67c7531df6dff0b4c241101d4096617fbca87c3"
integrity sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==
"@rollup/rollup-win32-arm64-msvc@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz#7eeada98444e580674de6989284e4baacd48ea65"
integrity sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==
"@rollup/rollup-win32-ia32-msvc@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz#516c4b54f80587b4a390aaf4940b40870271d35d"
integrity sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==
"@rollup/rollup-win32-x64-msvc@4.41.1":
version "4.41.1"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz#848f99b0d9936d92221bb6070baeff4db6947a30"
integrity sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==
"@tailwindcss/node@4.1.8":
version "4.1.8"
resolved "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.8.tgz"
@ -645,11 +891,73 @@
source-map-js "^1.2.1"
tailwindcss "4.1.8"
"@tailwindcss/oxide-android-arm64@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.8.tgz#4cb4b464636fc7e3154a1bb7df38a828291b3e9a"
integrity sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==
"@tailwindcss/oxide-darwin-arm64@4.1.8":
version "4.1.8"
resolved "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.8.tgz"
integrity sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==
"@tailwindcss/oxide-darwin-x64@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.8.tgz#d0f3fa4c3bde21a772e29e31c9739d91db79de12"
integrity sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==
"@tailwindcss/oxide-freebsd-x64@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.8.tgz#545c94c941007ed1aa2e449465501b70d59cb3da"
integrity sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==
"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.8.tgz#e1bdbf63a179081669b8cd1c9523889774760eb9"
integrity sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==
"@tailwindcss/oxide-linux-arm64-gnu@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.8.tgz#8d28093bbd43bdae771a2dcca720e926baa57093"
integrity sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==
"@tailwindcss/oxide-linux-arm64-musl@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.8.tgz#cc6cece814d813885ead9cd8b9d55aeb3db56c97"
integrity sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ==
"@tailwindcss/oxide-linux-x64-gnu@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.8.tgz#4cac14fa71382574773fb7986d9f0681ad89e3de"
integrity sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==
"@tailwindcss/oxide-linux-x64-musl@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.8.tgz#e085f1ccbc8f97625773a6a3afc2a6f88edf59da"
integrity sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==
"@tailwindcss/oxide-wasm32-wasi@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.8.tgz#c5e19fffe67f25cabf12a357bba4e87128151ea0"
integrity sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==
dependencies:
"@emnapi/core" "^1.4.3"
"@emnapi/runtime" "^1.4.3"
"@emnapi/wasi-threads" "^1.0.2"
"@napi-rs/wasm-runtime" "^0.2.10"
"@tybys/wasm-util" "^0.9.0"
tslib "^2.8.0"
"@tailwindcss/oxide-win32-arm64-msvc@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.8.tgz#77521f23f91604c587736927fd2cb526667b7344"
integrity sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==
"@tailwindcss/oxide-win32-x64-msvc@4.1.8":
version "4.1.8"
resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.8.tgz#55c876ab35f8779d1dceec61483cd9834d7365ac"
integrity sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==
"@tailwindcss/oxide@4.1.8":
version "4.1.8"
resolved "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.8.tgz"
@ -695,6 +1003,13 @@
resolved "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz"
integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==
"@tybys/wasm-util@^0.9.0":
version "0.9.0"
resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.9.0.tgz#3e75eb00604c8d6db470bf18c37b7d984a0e3355"
integrity sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==
dependencies:
tslib "^2.4.0"
"@types/babel__core@^7.20.5":
version "7.20.5"
resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz"
@ -754,7 +1069,7 @@
dependencies:
"@types/estree" "*"
"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.6", "@types/estree@1.0.7":
"@types/estree@*", "@types/estree@1.0.7", "@types/estree@^1.0.0", "@types/estree@^1.0.6":
version "1.0.7"
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz"
integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==
@ -788,7 +1103,7 @@
resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz"
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
"@types/node@^18.0.0 || ^20.0.0 || >=22.0.0", "@types/node@^22.15.24":
"@types/node@^22.15.24":
version "22.15.24"
resolved "https://registry.npmjs.org/@types/node/-/node-22.15.24.tgz"
integrity sha512-w9CZGm9RDjzTh/D+hFwlBJ3ziUaVw7oufKA3vOFSOZlzmW9AkZnfjPb+DLnrV6qtgL/LNmP0/2zBNCFHL3F0ng==
@ -830,7 +1145,7 @@
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
"@types/react@*", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^18.2.25 || ^19", "@types/react@^19.0.0", "@types/react@^19.1.2", "@types/react@>=16.8", "@types/react@>=18", "@types/react@>=18.0.0":
"@types/react@^19.1.2":
version "19.1.6"
resolved "https://registry.npmjs.org/@types/react/-/react-19.1.6.tgz"
integrity sha512-JeG0rEWak0N6Itr6QUx+X60uQmN+5t3j9r/OVDtWzFXKaj6kD1BwJzOksD0FF6iWxZlbE1kB0q9vtnU2ekqa1Q==
@ -849,7 +1164,7 @@
dependencies:
"@types/estree" "*"
"@types/three@*", "@types/three@>=0.134.0":
"@types/three@*":
version "0.177.0"
resolved "https://registry.npmjs.org/@types/three/-/three-0.177.0.tgz"
integrity sha512-/ZAkn4OLUijKQySNci47lFO+4JLE1TihEjsGWPUT+4jWqxtwOPPEwJV1C3k5MEx0mcBPCdkFjzRzDOnHEI1R+A==
@ -897,7 +1212,7 @@
natural-compare "^1.4.0"
ts-api-utils "^2.1.0"
"@typescript-eslint/parser@^8.33.0", "@typescript-eslint/parser@8.33.0":
"@typescript-eslint/parser@8.33.0":
version "8.33.0"
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.0.tgz"
integrity sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==
@ -925,7 +1240,7 @@
"@typescript-eslint/types" "8.33.0"
"@typescript-eslint/visitor-keys" "8.33.0"
"@typescript-eslint/tsconfig-utils@^8.33.0", "@typescript-eslint/tsconfig-utils@8.33.0":
"@typescript-eslint/tsconfig-utils@8.33.0", "@typescript-eslint/tsconfig-utils@^8.33.0":
version "8.33.0"
resolved "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.0.tgz"
integrity sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==
@ -940,7 +1255,7 @@
debug "^4.3.4"
ts-api-utils "^2.1.0"
"@typescript-eslint/types@^8.33.0", "@typescript-eslint/types@8.33.0":
"@typescript-eslint/types@8.33.0", "@typescript-eslint/types@^8.33.0":
version "8.33.0"
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.0.tgz"
integrity sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==
@ -1018,7 +1333,7 @@ acorn-jsx@^5.3.2:
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.0:
acorn@^8.14.0:
version "8.14.1"
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz"
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
@ -1117,7 +1432,7 @@ braces@^3.0.3:
dependencies:
fill-range "^7.1.1"
browserslist@^4.24.0, "browserslist@>= 4.21.0":
browserslist@^4.24.0:
version "4.24.5"
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz"
integrity sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==
@ -1376,7 +1691,7 @@ earcut@^3.0.0:
resolved "https://registry.npmjs.org/earcut/-/earcut-3.0.1.tgz"
integrity sha512-0l1/0gOjESMeQyYaK5IDiPNvFeu93Z/cO0TjZh9eZ1vyCtZnA7KMZ8rQggpsJHIbGSdrqYq9OhuveadOVHCshw==
easymde@^2.20.0, "easymde@>= 2.0.0 < 3.0.0":
easymde@^2.20.0:
version "2.20.0"
resolved "https://registry.npmjs.org/easymde/-/easymde-2.20.0.tgz"
integrity sha512-V1Z5f92TfR42Na852OWnIZMbM7zotWQYTddNaLYZFVKj7APBbyZ3FYJ27gBw2grMW3R6Qdv9J8n5Ij7XRSIgXQ==
@ -1508,7 +1823,7 @@ eslint-visitor-keys@^4.2.0:
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz"
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
"eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9.25.0, eslint@>=8.40:
eslint@^9.25.0:
version "9.27.0"
resolved "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz"
integrity sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==
@ -2064,7 +2379,7 @@ its-fine@^2.0.0:
dependencies:
"@types/react-reconciler" "^0.28.9"
jiti@*, jiti@^2.4.2, jiti@>=1.21.0:
jiti@^2.4.2:
version "2.4.2"
resolved "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz"
integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==
@ -2143,7 +2458,52 @@ lightningcss-darwin-arm64@1.30.1:
resolved "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz"
integrity sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==
lightningcss@^1.21.0, lightningcss@1.30.1:
lightningcss-darwin-x64@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz#e81105d3fd6330860c15fe860f64d39cff5fbd22"
integrity sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==
lightningcss-freebsd-x64@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz#a0e732031083ff9d625c5db021d09eb085af8be4"
integrity sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==
lightningcss-linux-arm-gnueabihf@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz#1f5ecca6095528ddb649f9304ba2560c72474908"
integrity sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==
lightningcss-linux-arm64-gnu@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz#eee7799726103bffff1e88993df726f6911ec009"
integrity sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==
lightningcss-linux-arm64-musl@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz#f2e4b53f42892feeef8f620cbb889f7c064a7dfe"
integrity sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==
lightningcss-linux-x64-gnu@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz#2fc7096224bc000ebb97eea94aea248c5b0eb157"
integrity sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==
lightningcss-linux-x64-musl@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz#66dca2b159fd819ea832c44895d07e5b31d75f26"
integrity sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==
lightningcss-win32-arm64-msvc@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz#7d8110a19d7c2d22bfdf2f2bb8be68e7d1b69039"
integrity sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==
lightningcss-win32-x64-msvc@1.30.1:
version "1.30.1"
resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz#fd7dd008ea98494b85d24b4bea016793f2e0e352"
integrity sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==
lightningcss@1.30.1:
version "1.30.1"
resolved "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz"
integrity sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==
@ -2606,7 +2966,7 @@ mobx-react-lite@^4.1.0:
dependencies:
use-sync-external-store "^1.4.0"
mobx@^6.13.7, mobx@^6.9.0:
mobx@^6.13.7:
version "6.13.7"
resolved "https://registry.npmjs.org/mobx/-/mobx-6.13.7.tgz"
integrity sha512-aChaVU/DO5aRPmk1GX8L+whocagUUpBQqoPtJk+cm7UOXUk87J4PeWCh6nNmTTIfEhiR9DI/+FnA8dln/hTK7g==
@ -2765,7 +3125,7 @@ picomatch@^2.3.1:
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
"picomatch@^3 || ^4", picomatch@^4.0.2:
picomatch@^4.0.2:
version "4.0.2"
resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz"
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
@ -2810,7 +3170,7 @@ promise-worker-transferable@^1.0.4:
is-promise "^2.1.0"
lie "^3.0.2"
prop-types@^15.5.4, prop-types@^15.6.2, prop-types@^15.8.1:
prop-types@^15.6.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -2876,7 +3236,7 @@ react-colorful@^5.6.1:
resolved "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz"
integrity sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==
"react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18 || ^19", "react-dom@^18.0.0 || ^19.0.0", react-dom@^19, react-dom@^19.0.0, react-dom@^19.1.0, react-dom@>=16.0.0, react-dom@>=16.13, react-dom@>=16.6.0, react-dom@>=16.8.0, react-dom@>=16.8.2, react-dom@>=18:
react-dom@^19.1.0:
version "19.1.0"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz"
integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==
@ -2990,12 +3350,12 @@ react-use-measure@^2.1.7:
resolved "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz"
integrity sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==
"react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18 || ^19", "react@^18.0 || ^19", "react@^18.0.0 || ^19.0.0", react@^19, react@^19.0.0, react@^19.1.0, "react@>= 16.8 || 18.0.0", "react@>= 16.8.0", react@>=16.0.0, react@>=16.13, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=16.8.2, react@>=17.0, react@>=18, react@>=18.0.0:
react@^19.1.0:
version "19.1.0"
resolved "https://registry.npmjs.org/react/-/react-19.1.0.tgz"
integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==
redux@^5.0.0, redux@^5.0.1:
redux@^5.0.1:
version "5.0.1"
resolved "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz"
integrity sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==
@ -3216,7 +3576,7 @@ suspend-react@^0.1.3:
resolved "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz"
integrity sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==
tailwindcss@^4.1.8, "tailwindcss@>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1", tailwindcss@4.1.8:
tailwindcss@4.1.8, tailwindcss@^4.1.8:
version "4.1.8"
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.8.tgz"
integrity sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==
@ -3265,7 +3625,7 @@ three@^0.175.0:
resolved "https://registry.npmjs.org/three/-/three-0.175.0.tgz"
integrity sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg==
three@^0.177.0, "three@>= 0.159.0", three@>=0.125.0, three@>=0.126.1, three@>=0.128.0, three@>=0.134.0, three@>=0.137, three@>=0.156, three@>=0.159:
three@^0.177.0:
version "0.177.0"
resolved "https://registry.npmjs.org/three/-/three-0.177.0.tgz"
integrity sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg==
@ -3325,9 +3685,9 @@ ts-api-utils@^2.1.0:
resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz"
integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==
tslib@^2.7.0:
tslib@^2.4.0, tslib@^2.7.0, tslib@^2.8.0:
version "2.8.1"
resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
tunnel-rat@^0.1.2:
@ -3353,7 +3713,7 @@ typescript-eslint@^8.30.1:
"@typescript-eslint/parser" "8.33.0"
"@typescript-eslint/utils" "8.33.0"
typescript@>=4.8.4, "typescript@>=4.8.4 <5.9.0", typescript@~5.8.3:
typescript@~5.8.3:
version "5.8.3"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz"
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
@ -3434,7 +3794,7 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0, use-sync-external-store@^1.5.0, use-sync-external-store@>=1.2.0:
use-sync-external-store@^1.2.2, use-sync-external-store@^1.4.0, use-sync-external-store@^1.5.0:
version "1.5.0"
resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz"
integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==
@ -3480,7 +3840,7 @@ vfile@^6.0.0:
"@types/unist" "^3.0.0"
vfile-message "^4.0.0"
"vite@^4.2.0 || ^5.0.0 || ^6.0.0", "vite@^5.2.0 || ^6", vite@^6.3.5:
vite@^6.3.5:
version "6.3.5"
resolved "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz"
integrity sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==
@ -3546,11 +3906,6 @@ yaml@^1.10.0:
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
yaml@^2.4.2:
version "2.8.0"
resolved "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz"
integrity sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"