mirror of
https://github.com/johndoe6345789/AutoMetabuilder.git
synced 2026-04-24 13:54:59 +00:00
Introduce AutoMetabuilder core components and workflow packages:
- Implement core components: CLI argument parsing, environment loading, GitHub service creation, and logging configuration. - Add support for OpenAI client setup and model resolution. - Develop SDLC context loader from GitHub and repository files. - Implement workflow context and engine builders. - Introduce major workflow packages: `game_tick_loop` and `contextual_iterative_loop`. - Update localization files with new package descriptions and labels. - Streamline web navigation by loading items from a dedicated JSON file.
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Alert, Snackbar } from "@mui/material";
|
||||
import DashboardSection from "../components/sections/DashboardSection";
|
||||
import PromptSection from "../components/sections/PromptSection";
|
||||
import SettingsSection from "../components/sections/SettingsSection";
|
||||
import TranslationsSection from "../components/sections/TranslationsSection";
|
||||
import WorkflowSection from "../components/sections/WorkflowSection";
|
||||
import PageLayout from "../components/layout/PageLayout";
|
||||
import useWebhook, { emitWebhook } from "../hooks/useWebhook";
|
||||
import {
|
||||
fetchContext,
|
||||
fetchWorkflowPackage,
|
||||
@@ -22,6 +24,8 @@ export default function HomePage() {
|
||||
const [selectedSection, setSelectedSection] = useState("dashboard");
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState("");
|
||||
const [snack, setSnack] = useState("");
|
||||
const [snackOpen, setSnackOpen] = useState(false);
|
||||
|
||||
const loadContext = async () => {
|
||||
setLoading(true);
|
||||
@@ -41,6 +45,16 @@ export default function HomePage() {
|
||||
void loadContext();
|
||||
}, []);
|
||||
|
||||
useWebhook(
|
||||
"botRunComplete",
|
||||
(detail) => {
|
||||
const mode = (detail as { mode?: string })?.mode ?? "once";
|
||||
setSnack(`Run finished: ${mode}`);
|
||||
setSnackOpen(true);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const t = useMemo(
|
||||
() => (key: string, fallback?: string) => context?.messages[key] ?? fallback ?? key,
|
||||
[context]
|
||||
@@ -49,6 +63,7 @@ export default function HomePage() {
|
||||
const handleRun = async (payload: Parameters<typeof runBot>[0]) => {
|
||||
await runBot(payload);
|
||||
await loadContext();
|
||||
emitWebhook("runRequested", payload);
|
||||
};
|
||||
|
||||
const handleWorkflowSave = async (content: string) => {
|
||||
@@ -92,8 +107,9 @@ export default function HomePage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<PageLayout
|
||||
navItems={context.navigation}
|
||||
<>
|
||||
<PageLayout
|
||||
navItems={context.navigation}
|
||||
section={selectedSection}
|
||||
onSectionChange={setSelectedSection}
|
||||
t={t}
|
||||
@@ -117,6 +133,12 @@ export default function HomePage() {
|
||||
{selectedSection === "translations" && (
|
||||
<TranslationsSection languages={context.translations} onRefresh={loadContext} t={t} />
|
||||
)}
|
||||
</PageLayout>
|
||||
</PageLayout>
|
||||
<Snackbar open={snackOpen} autoHideDuration={4000} onClose={() => setSnackOpen(false)}>
|
||||
<Alert onClose={() => setSnackOpen(false)} severity="info" sx={{ width: "100%" }}>
|
||||
{snack}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ReactNode } from "react";
|
||||
import { Box, Toolbar, Typography } from "@mui/material";
|
||||
import { NavigationItem } from "../../lib/types";
|
||||
import Sidebar from "./Sidebar";
|
||||
|
||||
@@ -12,15 +13,21 @@ type PageLayoutProps = {
|
||||
|
||||
export default function PageLayout({ navItems, section, onSectionChange, t, children }: PageLayoutProps) {
|
||||
return (
|
||||
<div className="app-shell">
|
||||
<Box sx={{ display: "flex" }}>
|
||||
<Sidebar items={navItems} selected={section} onSelect={onSectionChange} t={t} />
|
||||
<div className="content-shell">
|
||||
<header className="content-shell__header">
|
||||
<h1>{t("ui.app.title", "AutoMetabuilder Dashboard")}</h1>
|
||||
<p>{t("ui.dashboard.subtitle", "Control the bot and monitor system activity")}</p>
|
||||
</header>
|
||||
<div className="content-shell__body">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
<Box component="main" sx={{ flexGrow: 1, p: 3, bgcolor: "#04070f", minHeight: "100vh" }}>
|
||||
<Toolbar disableGutters>
|
||||
<div>
|
||||
<Typography variant="h4" color="text.primary" gutterBottom>
|
||||
{t("ui.app.title", "AutoMetabuilder Dashboard")}
|
||||
</Typography>
|
||||
<Typography variant="subtitle1" color="text.secondary">
|
||||
{t("ui.dashboard.subtitle", "Control the bot and monitor system activity")}
|
||||
</Typography>
|
||||
</div>
|
||||
</Toolbar>
|
||||
<Box>{children}</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Box, Divider, Drawer, List, ListItemButton, ListItemText, Typography } from "@mui/material";
|
||||
import { NavigationItem } from "../../lib/types";
|
||||
|
||||
type SidebarProps = {
|
||||
@@ -9,23 +10,30 @@ type SidebarProps = {
|
||||
|
||||
export default function Sidebar({ items, selected, onSelect, t }: SidebarProps) {
|
||||
return (
|
||||
<aside className="sidebar">
|
||||
<div className="sidebar__brand">
|
||||
<span>{t("ui.app.name", "AutoMetabuilder")}</span>
|
||||
</div>
|
||||
<nav>
|
||||
{items.map((item) => (
|
||||
<button
|
||||
key={item.section}
|
||||
type="button"
|
||||
className={`sidebar__item ${selected === item.section ? "active" : ""}`}
|
||||
onClick={() => onSelect(item.section)}
|
||||
data-section={item.section}
|
||||
>
|
||||
<span>{t(item.label_key, item.default_label)}</span>
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
</aside>
|
||||
<Drawer variant="permanent" anchor="left" sx={{ width: 220, flexShrink: 0 }}>
|
||||
<Box sx={{ height: "100%", backgroundColor: "#0f172a" }}>
|
||||
<Box sx={{ px: 3, py: 2 }}>
|
||||
<Typography variant="overline" color="text.secondary">
|
||||
{t("ui.app.name", "AutoMetabuilder")}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ borderColor: "rgba(255,255,255,0.08)" }} />
|
||||
<List>
|
||||
{items.map((item) => (
|
||||
<ListItemButton
|
||||
key={item.section}
|
||||
selected={selected === item.section}
|
||||
onClick={() => onSelect(item.section)}
|
||||
data-section={item.section}
|
||||
sx={{
|
||||
color: selected === item.section ? "#fff" : "rgba(226,232,240,0.8)",
|
||||
}}
|
||||
>
|
||||
<ListItemText primary={t(item.label_key, item.default_label)} primaryTypographyProps={{ fontSize: 14 }} />
|
||||
</ListItemButton>
|
||||
))}
|
||||
</List>
|
||||
</Box>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Checkbox,
|
||||
FormControl,
|
||||
FormControlLabel,
|
||||
Paper,
|
||||
Radio,
|
||||
RadioGroup,
|
||||
Stack,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { UIStatus } from "../../lib/types";
|
||||
import { emitWebhook } from "../../hooks/useWebhook";
|
||||
|
||||
type DashboardSectionProps = {
|
||||
status: UIStatus;
|
||||
@@ -20,6 +34,7 @@ export default function DashboardSection({ status, logs, onRun, t }: DashboardSe
|
||||
try {
|
||||
await onRun({ mode, iterations, yolo: isYolo, stop_at_mvp: stopAtMvp });
|
||||
setFeedback(t("ui.dashboard.start_bot", "Start Bot") + " " + t("ui.dashboard.status.running", "Running"));
|
||||
emitWebhook("botRunComplete", { mode, iterations });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setFeedback(t("ui.dashboard.status.idle", "Idle"));
|
||||
@@ -27,52 +42,72 @@ export default function DashboardSection({ status, logs, onRun, t }: DashboardSe
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-card" id="dashboard">
|
||||
<div className="section-card__header">
|
||||
<h2>{t("ui.dashboard.title", "Dashboard")}</h2>
|
||||
<p>{t("ui.dashboard.subtitle", "Control the bot and monitor system activity")}</p>
|
||||
</div>
|
||||
<div className="dashboard-grid">
|
||||
<div className="dashboard-panel">
|
||||
<h3>{t("ui.dashboard.bot_control", "Bot Control")}</h3>
|
||||
<div className="dashboard-panel__strategy">
|
||||
<label>
|
||||
<input type="radio" name="mode" value="once" checked={mode === "once"} onChange={() => setMode("once")} />
|
||||
<span>{t("ui.dashboard.run.single.title", "Single Iteration")}</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="mode" value="iterations" checked={mode === "iterations"} onChange={() => setMode("iterations")} />
|
||||
<span>{t("ui.dashboard.run.repeat.title", "Repeat")}</span>
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="mode" value="yolo" checked={mode === "yolo"} onChange={() => setMode("yolo")} />
|
||||
<span>{t("ui.dashboard.run.yolo.title", "YOLO")}</span>
|
||||
</label>
|
||||
</div>
|
||||
<Paper id="dashboard" sx={{ p: 3, mb: 3, backgroundColor: "#0d111b" }}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
{t("ui.dashboard.title", "Dashboard")}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" gutterBottom>
|
||||
{t("ui.dashboard.subtitle", "Control the bot and monitor system activity")}
|
||||
</Typography>
|
||||
<Stack direction={{ xs: "column", md: "row" }} spacing={3} mt={2}>
|
||||
<Paper sx={{ flex: 1, p: 2, backgroundColor: "#0b1221" }}>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
{t("ui.dashboard.bot_control", "Bot Control")}
|
||||
</Typography>
|
||||
<FormControl component="fieldset">
|
||||
<RadioGroup row value={mode} onChange={(event) => setMode(event.target.value)} name="run-mode">
|
||||
{["once", "iterations", "yolo"].map((value) => (
|
||||
<FormControlLabel
|
||||
key={value}
|
||||
value={value}
|
||||
control={<Radio size="small" />}
|
||||
label={t(`ui.dashboard.run.${value}.title`, value === "iterations" ? "Repeat" : value.charAt(0).toUpperCase() + value.slice(1))}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
{mode === "iterations" && (
|
||||
<label className="field-group">
|
||||
<span>{t("ui.dashboard.run.repeat.label", "Iterations")}</span>
|
||||
<input type="number" min={1} value={iterations} onChange={(event) => setIterations(Number(event.target.value) || 1)} />
|
||||
</label>
|
||||
<TextField
|
||||
type="number"
|
||||
size="small"
|
||||
label={t("ui.dashboard.run.repeat.label", "Iterations")}
|
||||
value={iterations}
|
||||
onChange={(event) => setIterations(Number(event.target.value) || 1)}
|
||||
sx={{ mt: 1, width: 140 }}
|
||||
/>
|
||||
)}
|
||||
<label className="field-group">
|
||||
<input type="checkbox" checked={stopAtMvp} onChange={(event) => setStopAtMvp(event.target.checked)} />
|
||||
<span>{t("ui.dashboard.stop_mvp.title", "Stop at MVP")}</span>
|
||||
</label>
|
||||
<button className="primary" type="button" onClick={handleRun} disabled={status.is_running}>
|
||||
<FormControlLabel
|
||||
control={<Checkbox checked={stopAtMvp} onChange={(event) => setStopAtMvp(event.target.checked)} />}
|
||||
label={t("ui.dashboard.stop_mvp.title", "Stop at MVP")}
|
||||
sx={{ mt: 1 }}
|
||||
/>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleRun}
|
||||
disabled={status.is_running}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
{t("ui.dashboard.start_bot", "Start Bot")}
|
||||
</button>
|
||||
<p className="status-text">
|
||||
{status.is_running ? t("ui.dashboard.status.running", "Running") : t("ui.dashboard.status.idle", "Idle")} •{" "}
|
||||
</Button>
|
||||
<Typography variant="caption" color="text.secondary" display="block" mt={1}>
|
||||
{status.is_running ? t("ui.dashboard.status.running", "Running") : t("ui.dashboard.status.idle", "Idle")} •
|
||||
{" "}
|
||||
{status.mvp_reached ? t("ui.dashboard.status.mvp_reached", "Reached") : t("ui.dashboard.status.mvp_progress", "In Progress")}
|
||||
</p>
|
||||
<p className="status-feedback">{feedback}</p>
|
||||
</div>
|
||||
<div className="dashboard-panel">
|
||||
<h3>{t("ui.dashboard.logs.title", "Recent Logs")}</h3>
|
||||
<pre className="log-output">{logs.slice(-1200) || t("ui.dashboard.status.idle", "Idle")}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Typography>
|
||||
<Typography variant="caption" color="primary">
|
||||
{feedback}
|
||||
</Typography>
|
||||
</Paper>
|
||||
<Paper sx={{ flex: 1, p: 2, backgroundColor: "#0b1221" }}>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
{t("ui.dashboard.logs.title", "Recent Logs")}
|
||||
</Typography>
|
||||
<Box component="pre" sx={{ maxHeight: 240, overflow: "auto", fontSize: 12, color: "white" }}>
|
||||
{logs.slice(-1200) || t("ui.dashboard.status.idle", "Idle")}
|
||||
</Box>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Box, Button, Paper, Stack, TextField, Typography } from "@mui/material";
|
||||
|
||||
type PromptSectionProps = {
|
||||
content: string;
|
||||
@@ -21,18 +22,36 @@ export default function PromptSection({ content, onSave, t }: PromptSectionProps
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-card" id="prompt">
|
||||
<div className="section-card__header">
|
||||
<h2>{t("ui.prompt.title", "Prompt Builder")}</h2>
|
||||
<p>{t("ui.prompt.subtitle", "Shape how the assistant thinks, speaks, and decides")}</p>
|
||||
</div>
|
||||
<textarea className="prompt-editor" value={draft} onChange={(event) => setDraft(event.target.value)} rows={12} />
|
||||
<div className="workflow-actions">
|
||||
<button className="primary" type="button" onClick={handleSave}>
|
||||
<Paper id="prompt" sx={{ p: 3, mb: 3, backgroundColor: "#0d111b" }}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
{t("ui.prompt.title", "Prompt Builder")}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" gutterBottom>
|
||||
{t("ui.prompt.subtitle", "Shape how the assistant thinks, speaks, and decides")}
|
||||
</Typography>
|
||||
<TextField
|
||||
multiline
|
||||
minRows={10}
|
||||
value={draft}
|
||||
onChange={(event) => setDraft(event.target.value)}
|
||||
fullWidth
|
||||
InputProps={{
|
||||
sx: {
|
||||
backgroundColor: "#030712",
|
||||
borderRadius: 2,
|
||||
color: "white",
|
||||
fontFamily: "JetBrains Mono, monospace",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Stack direction="row" spacing={2} alignItems="center" mt={2}>
|
||||
<Button variant="contained" onClick={handleSave}>
|
||||
{t("ui.prompt.save", "Save Prompt")}
|
||||
</button>
|
||||
<span className="workflow-message">{message}</span>
|
||||
</div>
|
||||
</section>
|
||||
</Button>
|
||||
<Typography variant="body2" color="success.main">
|
||||
{message}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Box, Button, Paper, Stack, TextField, Typography } from "@mui/material";
|
||||
|
||||
type SettingsSectionProps = {
|
||||
envVars: Record<string, string>;
|
||||
@@ -34,32 +35,55 @@ export default function SettingsSection({ envVars, onSave, t }: SettingsSectionP
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-card" id="settings">
|
||||
<div className="section-card__header">
|
||||
<h2>{t("ui.settings.title", "Settings")}</h2>
|
||||
<p>{t("ui.settings.subtitle", "Configure services, security, and environment preferences")}</p>
|
||||
</div>
|
||||
<div className="settings-grid">
|
||||
<Paper id="settings" sx={{ p: 3, mb: 3, backgroundColor: "#0d111b" }}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
{t("ui.settings.title", "Settings")}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" gutterBottom>
|
||||
{t("ui.settings.subtitle", "Configure services, security, and environment preferences")}
|
||||
</Typography>
|
||||
<Stack spacing={2} mt={2}>
|
||||
{Object.entries(values).map(([key, value]) => (
|
||||
<label key={key} className="field-group">
|
||||
<span>{key}</span>
|
||||
<input value={value} onChange={(event) => updateField(key, event.target.value)} />
|
||||
</label>
|
||||
<TextField
|
||||
key={key}
|
||||
label={key}
|
||||
value={value}
|
||||
onChange={(event) => updateField(key, event.target.value)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
backgroundColor: "#030712",
|
||||
borderRadius: 1,
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="settings-grid settings-grid--new">
|
||||
<input placeholder={t("ui.settings.add.placeholder_key", "KEY")} value={newKey} onChange={(event) => setNewKey(event.target.value)} />
|
||||
<input placeholder={t("ui.settings.add.placeholder_value", "Value")} value={newValue} onChange={(event) => setNewValue(event.target.value)} />
|
||||
<button type="button" onClick={handleAdd}>
|
||||
</Stack>
|
||||
<Stack direction={{ xs: "column", sm: "row" }} spacing={2} sx={{ mt: 2 }}>
|
||||
<TextField
|
||||
label={t("ui.settings.add.placeholder_key", "KEY")}
|
||||
value={newKey}
|
||||
onChange={(event) => setNewKey(event.target.value)}
|
||||
fullWidth
|
||||
/>
|
||||
<TextField
|
||||
label={t("ui.settings.add.placeholder_value", "Value")}
|
||||
value={newValue}
|
||||
onChange={(event) => setNewValue(event.target.value)}
|
||||
fullWidth
|
||||
/>
|
||||
<Button variant="outlined" onClick={handleAdd}>
|
||||
{t("ui.actions.add", "Add")}
|
||||
</button>
|
||||
</div>
|
||||
<div className="workflow-actions">
|
||||
<button className="primary" type="button" onClick={handleSave}>
|
||||
</Button>
|
||||
</Stack>
|
||||
<Stack direction="row" spacing={2} alignItems="center" mt={3}>
|
||||
<Button variant="contained" onClick={handleSave}>
|
||||
{t("ui.settings.save_all", "Save All Settings")}
|
||||
</button>
|
||||
<span className="workflow-message">{message}</span>
|
||||
</div>
|
||||
</section>
|
||||
</Button>
|
||||
<Typography variant="body2" color="success.main">
|
||||
{message}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import { FormEvent, useEffect, useState } from "react";
|
||||
import {
|
||||
Button,
|
||||
Chip,
|
||||
Paper,
|
||||
Stack,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import {
|
||||
createTranslation,
|
||||
deleteTranslation,
|
||||
@@ -25,7 +33,6 @@ export default function TranslationsSection({ languages, onRefresh, t }: Transla
|
||||
setEditorValue(JSON.stringify(data.content, null, 2));
|
||||
};
|
||||
|
||||
/* eslint-disable react-hooks/set-state-in-effect */
|
||||
useEffect(() => {
|
||||
if (!selected && Object.keys(languages).length) {
|
||||
setSelected(Object.keys(languages)[0]);
|
||||
@@ -37,7 +44,6 @@ export default function TranslationsSection({ languages, onRefresh, t }: Transla
|
||||
loadContent(selected);
|
||||
}
|
||||
}, [selected]);
|
||||
/* eslint-enable react-hooks/set-state-in-effect */
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!selected) return;
|
||||
@@ -67,41 +73,64 @@ export default function TranslationsSection({ languages, onRefresh, t }: Transla
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-card" id="translations">
|
||||
<div className="section-card__header">
|
||||
<h2>{t("ui.translations.title", "Translations")}</h2>
|
||||
<p>{t("ui.translations.subtitle", "Create, edit, and maintain language files for bot messages")}</p>
|
||||
</div>
|
||||
<div className="translations-layout">
|
||||
<div className="language-list">
|
||||
<Paper id="translations" sx={{ p: 3, mb: 3, backgroundColor: "#0d111b" }}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
{t("ui.translations.title", "Translations")}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" gutterBottom>
|
||||
{t("ui.translations.subtitle", "Create, edit, and maintain language files for bot messages")}
|
||||
</Typography>
|
||||
<Stack spacing={2} sx={{ mt: 2 }}>
|
||||
<Stack direction="row" spacing={1} flexWrap="wrap">
|
||||
{Object.entries(languages).map(([lang, label]) => (
|
||||
<button
|
||||
<Chip
|
||||
label={`${lang} (${label})`}
|
||||
key={lang}
|
||||
type="button"
|
||||
className={`language-chip ${selected === lang ? "active" : ""}`}
|
||||
variant={selected === lang ? "filled" : "outlined"}
|
||||
onClick={() => setSelected(lang)}
|
||||
>
|
||||
{lang}
|
||||
<span>{`(${label})`}</span>
|
||||
</button>
|
||||
clickable
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<textarea value={editorValue} onChange={(event) => setEditorValue(event.target.value)} rows={12} />
|
||||
</div>
|
||||
<div className="translations-actions">
|
||||
<button className="primary" type="button" onClick={handleSave} disabled={!selected}>
|
||||
</Stack>
|
||||
<TextField
|
||||
multiline
|
||||
minRows={12}
|
||||
value={editorValue}
|
||||
onChange={(event) => setEditorValue(event.target.value)}
|
||||
InputProps={{
|
||||
sx: {
|
||||
backgroundColor: "#030712",
|
||||
borderRadius: 2,
|
||||
color: "white",
|
||||
fontFamily: "JetBrains Mono, monospace",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack direction="row" spacing={2} mt={2}>
|
||||
<Button variant="contained" onClick={handleSave} disabled={!selected}>
|
||||
{t("ui.actions.save", "Save")}
|
||||
</button>
|
||||
<button type="button" onClick={handleDelete} disabled={!selected}>
|
||||
</Button>
|
||||
<Button variant="outlined" onClick={handleDelete} disabled={!selected}>
|
||||
{t("ui.actions.delete", "Delete")}
|
||||
</button>
|
||||
<form onSubmit={handleCreate} className="language-form">
|
||||
<input placeholder={t("ui.translations.add_language_placeholder", "Add language...")} value={newLang} onChange={(event) => setNewLang(event.target.value)} />
|
||||
<button type="submit">{t("ui.actions.add", "Add")}</button>
|
||||
</form>
|
||||
</div>
|
||||
{message && <p className="workflow-message">{message}</p>}
|
||||
{error && <p className="workflow-error">{error}</p>}
|
||||
</section>
|
||||
</Button>
|
||||
<Stack component="form" onSubmit={handleCreate} direction="row" spacing={1} flex={1}>
|
||||
<TextField
|
||||
placeholder={t("ui.translations.add_language_placeholder", "Add language...")}
|
||||
value={newLang}
|
||||
onChange={(event) => setNewLang(event.target.value)}
|
||||
fullWidth
|
||||
/>
|
||||
<Button type="submit" variant="contained">
|
||||
{t("ui.actions.add", "Add")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
{(message || error) && (
|
||||
<Typography variant="body2" color={error ? "error.main" : "success.main"} mt={2}>
|
||||
{message || error}
|
||||
</Typography>
|
||||
)}
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Box, Button, Paper, Stack, Typography } from "@mui/material";
|
||||
import { WorkflowPackageSummary } from "../../lib/types";
|
||||
|
||||
type WorkflowSectionProps = {
|
||||
@@ -24,38 +25,60 @@ export default function WorkflowSection({ content, packages, onSave, onTemplateS
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-card" id="workflow">
|
||||
<div className="section-card__header">
|
||||
<h2>{t("ui.workflow.title", "Workflow Builder")}</h2>
|
||||
<p>{t("ui.workflow.subtitle", "Design the bot's task execution pipeline")}</p>
|
||||
</div>
|
||||
<div className="workflow-grid">
|
||||
<div className="workflow-editor">
|
||||
<textarea value={draft} onChange={(event) => setDraft(event.target.value)} />
|
||||
<div className="workflow-actions">
|
||||
<button type="button" className="primary" onClick={handleSave}>
|
||||
<Paper id="workflow" sx={{ p: 3, mb: 3, backgroundColor: "#0d111b" }}>
|
||||
<Typography variant="h5" gutterBottom>
|
||||
{t("ui.workflow.title", "Workflow Builder")}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary" gutterBottom>
|
||||
{t("ui.workflow.subtitle", "Design the bot's task execution pipeline")}
|
||||
</Typography>
|
||||
<Stack direction={{ xs: "column", md: "row" }} spacing={3}>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
<Box
|
||||
component="textarea"
|
||||
value={draft}
|
||||
onChange={(event) => setDraft(event.target.value)}
|
||||
rows={18}
|
||||
sx={{
|
||||
width: "100%",
|
||||
fontFamily: "JetBrains Mono, monospace",
|
||||
backgroundColor: "#030712",
|
||||
border: "1px solid rgba(148, 163, 184, 0.4)",
|
||||
borderRadius: 2,
|
||||
color: "white",
|
||||
p: 2,
|
||||
}}
|
||||
/>
|
||||
<Stack direction="row" spacing={1} alignItems="center" mt={2}>
|
||||
<Button variant="contained" onClick={handleSave}>
|
||||
{t("ui.workflow.save", "Save Workflow")}
|
||||
</button>
|
||||
<span className="workflow-message">{message}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="workflow-templates">
|
||||
<h3>{t("ui.workflow.templates.title", "Workflow Templates")}</h3>
|
||||
<div className="template-palette">
|
||||
</Button>
|
||||
<Typography variant="body2" color="success.main">
|
||||
{message}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Paper sx={{ flex: 1, p: 2, backgroundColor: "#0b1221" }}>
|
||||
<Typography variant="subtitle1" gutterBottom>
|
||||
{t("ui.workflow.templates.title", "Workflow Templates")}
|
||||
</Typography>
|
||||
<Stack spacing={1}>
|
||||
{packages.map((pkg) => (
|
||||
<article key={pkg.id} className="template-card">
|
||||
<div>
|
||||
<strong>{pkg.label}</strong>
|
||||
<p>{pkg.description}</p>
|
||||
</div>
|
||||
<button type="button" onClick={() => onTemplateSelect(pkg.id)}>
|
||||
{t("ui.workflow.templates.apply", "Apply Template")}
|
||||
</button>
|
||||
</article>
|
||||
<Paper key={pkg.id} variant="outlined" sx={{ p: 1 }}>
|
||||
<Stack spacing={1}>
|
||||
<Typography variant="subtitle2">{pkg.label}</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{pkg.description}
|
||||
</Typography>
|
||||
<Button size="small" variant="text" onClick={() => onTemplateSelect(pkg.id)}>
|
||||
{t("ui.workflow.templates.apply", "Apply Template")}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Paper>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
22
frontend/autometabuilder/hooks/useWebhook.ts
Normal file
22
frontend/autometabuilder/hooks/useWebhook.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
const emitter = new EventTarget();
|
||||
|
||||
export function emitWebhook(event: string, detail?: unknown) {
|
||||
emitter.dispatchEvent(new CustomEvent(event, { detail }));
|
||||
}
|
||||
|
||||
export default function useWebhook(
|
||||
name: string,
|
||||
handler: (detail: unknown) => void,
|
||||
deps: unknown[] = []
|
||||
) {
|
||||
useEffect(() => {
|
||||
const listener = (evt: Event) => {
|
||||
handler((evt as CustomEvent).detail);
|
||||
};
|
||||
emitter.addEventListener(name, listener);
|
||||
return () => emitter.removeEventListener(name, listener);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [name, handler, ...deps]);
|
||||
}
|
||||
637
frontend/package-lock.json
generated
637
frontend/package-lock.json
generated
@@ -13,6 +13,10 @@
|
||||
"react-dom": "19.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@emotion/react": "^11.12.0",
|
||||
"@emotion/styled": "^11.12.0",
|
||||
"@mui/icons-material": "^5.14.4",
|
||||
"@mui/material": "^5.15.0",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
@@ -213,6 +217,16 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.28.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
||||
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
|
||||
@@ -294,6 +308,172 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/babel-plugin": {
|
||||
"version": "11.13.5",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
|
||||
"integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.16.7",
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/hash": "^0.9.2",
|
||||
"@emotion/memoize": "^0.9.0",
|
||||
"@emotion/serialize": "^1.3.3",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"convert-source-map": "^1.5.0",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"find-root": "^1.1.0",
|
||||
"source-map": "^0.5.7",
|
||||
"stylis": "4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
|
||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@emotion/cache": {
|
||||
"version": "11.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
|
||||
"integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@emotion/memoize": "^0.9.0",
|
||||
"@emotion/sheet": "^1.4.0",
|
||||
"@emotion/utils": "^1.4.2",
|
||||
"@emotion/weak-memoize": "^0.4.0",
|
||||
"stylis": "4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/hash": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
|
||||
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@emotion/is-prop-valid": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz",
|
||||
"integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@emotion/memoize": "^0.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/memoize": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
|
||||
"integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@emotion/react": {
|
||||
"version": "11.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
|
||||
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
"@emotion/cache": "^11.14.0",
|
||||
"@emotion/serialize": "^1.3.3",
|
||||
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
|
||||
"@emotion/utils": "^1.4.2",
|
||||
"@emotion/weak-memoize": "^0.4.0",
|
||||
"hoist-non-react-statics": "^3.3.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/serialize": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
|
||||
"integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@emotion/hash": "^0.9.2",
|
||||
"@emotion/memoize": "^0.9.0",
|
||||
"@emotion/unitless": "^0.10.0",
|
||||
"@emotion/utils": "^1.4.2",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/sheet": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
|
||||
"integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@emotion/styled": {
|
||||
"version": "11.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
|
||||
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
"@emotion/is-prop-valid": "^1.3.0",
|
||||
"@emotion/serialize": "^1.3.3",
|
||||
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
|
||||
"@emotion/utils": "^1.4.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.0.0-rc.0",
|
||||
"react": ">=16.8.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/unitless": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
|
||||
"integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz",
|
||||
"integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emotion/utils": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz",
|
||||
"integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@emotion/weak-memoize": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
|
||||
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
|
||||
@@ -1006,6 +1186,253 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/core-downloads-tracker": {
|
||||
"version": "5.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.18.0.tgz",
|
||||
"integrity": "sha512-jbhwoQ1AY200PSSOrNXmrFCaSDSJWP7qk6urkTmIirvRXDROkqe+QwcLlUiw/PrREwsIF/vm3/dAXvjlMHF0RA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/icons-material": {
|
||||
"version": "5.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.18.0.tgz",
|
||||
"integrity": "sha512-1s0vEZj5XFXDMmz3Arl/R7IncFqJ+WQ95LDp1roHWGDE2oCO3IS4/hmiOv1/8SD9r6B7tv9GLiqVZYHo+6PkTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mui/material": "^5.0.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/material": {
|
||||
"version": "5.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-5.18.0.tgz",
|
||||
"integrity": "sha512-bbH/HaJZpFtXGvWg3TsBWG4eyt3gah3E7nCNU8GLyRjVoWcA91Vm/T+sjHfUcwgJSw9iLtucfHBoq+qW/T30aA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/core-downloads-tracker": "^5.18.0",
|
||||
"@mui/system": "^5.18.0",
|
||||
"@mui/types": "~7.2.15",
|
||||
"@mui/utils": "^5.17.1",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@types/react-transition-group": "^4.4.10",
|
||||
"clsx": "^2.1.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-is": "^19.0.0",
|
||||
"react-transition-group": "^4.4.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.5.0",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/material/node_modules/react-is": {
|
||||
"version": "19.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.3.tgz",
|
||||
"integrity": "sha512-qJNJfu81ByyabuG7hPFEbXqNcWSU3+eVus+KJs+0ncpGfMyYdvSmxiJxbWR65lYi1I+/0HBcliO029gc4F+PnA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@mui/private-theming": {
|
||||
"version": "5.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.17.1.tgz",
|
||||
"integrity": "sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/utils": "^5.17.1",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/styled-engine": {
|
||||
"version": "5.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.18.0.tgz",
|
||||
"integrity": "sha512-BN/vKV/O6uaQh2z5rXV+MBlVrEkwoS/TK75rFQ2mjxA7+NBo8qtTAOA4UaM0XeJfn7kh2wZ+xQw2HAx0u+TiBg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@emotion/cache": "^11.13.5",
|
||||
"@emotion/serialize": "^1.3.3",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/system": {
|
||||
"version": "5.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-5.18.0.tgz",
|
||||
"integrity": "sha512-ojZGVcRWqWhu557cdO3pWHloIGJdzVtxs3rk0F9L+x55LsUjcMUVkEhiF7E4TMxZoF9MmIHGGs0ZX3FDLAf0Xw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/private-theming": "^5.17.1",
|
||||
"@mui/styled-engine": "^5.18.0",
|
||||
"@mui/types": "~7.2.15",
|
||||
"@mui/utils": "^5.17.1",
|
||||
"clsx": "^2.1.0",
|
||||
"csstype": "^3.1.3",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/react": "^11.5.0",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@emotion/styled": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/types": {
|
||||
"version": "7.2.24",
|
||||
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz",
|
||||
"integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/utils": {
|
||||
"version": "5.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.17.1.tgz",
|
||||
"integrity": "sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.9",
|
||||
"@mui/types": "~7.2.15",
|
||||
"@types/prop-types": "^15.7.12",
|
||||
"clsx": "^2.1.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-is": "^19.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui-org"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@mui/utils/node_modules/react-is": {
|
||||
"version": "19.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.3.tgz",
|
||||
"integrity": "sha512-qJNJfu81ByyabuG7hPFEbXqNcWSU3+eVus+KJs+0ncpGfMyYdvSmxiJxbWR65lYi1I+/0HBcliO029gc4F+PnA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@napi-rs/wasm-runtime": {
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
|
||||
@@ -1521,6 +1948,17 @@
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@popperjs/core": {
|
||||
"version": "2.11.8",
|
||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/popperjs"
|
||||
}
|
||||
},
|
||||
"node_modules/@rtsao/scc": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
|
||||
@@ -1579,6 +2017,20 @@
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
|
||||
"integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
|
||||
"integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "19.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
|
||||
@@ -1599,6 +2051,16 @@
|
||||
"@types/react": "^19.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-transition-group": {
|
||||
"version": "4.4.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
|
||||
"integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.52.0.tgz",
|
||||
@@ -2423,6 +2885,22 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-macros": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
|
||||
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"cosmiconfig": "^7.0.0",
|
||||
"resolve": "^1.19.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"npm": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-react-compiler": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-1.0.0.tgz",
|
||||
@@ -2627,6 +3105,16 @@
|
||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@@ -2661,6 +3149,23 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cosmiconfig": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
|
||||
"integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/parse-json": "^4.0.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
"parse-json": "^5.0.0",
|
||||
"path-type": "^4.0.0",
|
||||
"yaml": "^1.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@@ -2832,6 +3337,17 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
@@ -2861,6 +3377,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
|
||||
"integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
"version": "1.24.1",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
|
||||
@@ -3572,6 +4098,13 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/find-root": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
|
||||
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||
@@ -3924,6 +4457,16 @@
|
||||
"hermes-estree": "0.25.1"
|
||||
}
|
||||
},
|
||||
"node_modules/hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
@@ -4001,6 +4544,13 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-async-function": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
|
||||
@@ -4470,6 +5020,13 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-parse-even-better-errors": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
@@ -4557,6 +5114,13 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
@@ -4980,6 +5544,25 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-json": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
||||
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.0.0",
|
||||
"error-ex": "^1.3.1",
|
||||
"json-parse-even-better-errors": "^2.3.0",
|
||||
"lines-and-columns": "^1.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
@@ -5007,6 +5590,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
@@ -5145,6 +5738,23 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-transition-group": {
|
||||
"version": "4.4.5",
|
||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
|
||||
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"dom-helpers": "^5.0.1",
|
||||
"loose-envify": "^1.4.0",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.6.0",
|
||||
"react-dom": ">=16.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readdirp": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||
@@ -5587,6 +6197,16 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
@@ -5776,6 +6396,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/stylis": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
|
||||
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
@@ -6262,6 +6889,16 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
|
||||
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/yocto-queue": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@emotion/react": "^11.12.0",
|
||||
"@emotion/styled": "^11.12.0",
|
||||
"@mui/icons-material": "^5.14.4",
|
||||
"@mui/material": "^5.15.0",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.1.1",
|
||||
"sass": "^1.95.0"
|
||||
|
||||
Reference in New Issue
Block a user