diff --git a/Makefile b/Makefile
index 5dca719..4662fb5 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@ SF_MEMORY = $(PHP) -d memory_limit=256M bin/console
# Misc
.DEFAULT_GOAL = help
-.PHONY : help build start install down stop logs sh composer vendor sf cc test phpmd phpcs quality fix-permissions controller entity migration migration-diff migration-migrate form crud fixtures command auth subscriber state-processor state-provider npm-install npm-run npm-watch
+.PHONY : help build start install down stop logs sh composer vendor sf cc test phpmd phpcs quality fix-permissions controller entity migration migration-diff migration-migrate form crud fixtures command auth subscriber state-processor state-provider npm-install npm-run npm-watch openapi
## —— 🎵 🐳 The Symfony Docker Makefile 🐳 🎵 ——————————————————————————————————
help: ## Outputs this help screen
@@ -147,6 +147,9 @@ consume-schedule: ## Consume schedule messages
message: ## Create a new message and handler
@$(SYMFONY) make:message
+openapi: ## Exporter la documentation OpenAPI en JSON
+ @$(SYMFONY) api:openapi:export --output=public/api-docs.json
+
## —— Webpack Encore —————————————————————————————————————————————————————————————
npm-install: ## Install npm dependencies
@$(DOCKER_COMP) exec node npm install --force
diff --git a/assets/app.js b/assets/app.js
index e66af97..e671a9f 100644
--- a/assets/app.js
+++ b/assets/app.js
@@ -1,3 +1,4 @@
+import { registerReactControllerComponents } from '@symfony/ux-react';
import './bootstrap.js';
import '@fortawesome/fontawesome-free/js/all.js';
@@ -13,3 +14,5 @@ import './styles/app.scss';
// start the Stimulus application
import './bootstrap';
+
+//registerReactControllerComponents(require.context('./react/controllers', true, /\.(j|t)sx?$/));
diff --git a/assets/controllers.json b/assets/controllers.json
index 71abe9d..3dfe062 100644
--- a/assets/controllers.json
+++ b/assets/controllers.json
@@ -9,6 +9,12 @@
}
}
},
+ "@symfony/ux-react": {
+ "react": {
+ "enabled": true,
+ "fetch": "eager"
+ }
+ },
"@symfony/ux-turbo": {
"turbo-core": {
"enabled": true,
diff --git a/assets/react/app/App.jsx b/assets/react/app/App.jsx
new file mode 100644
index 0000000..aeda3ce
--- /dev/null
+++ b/assets/react/app/App.jsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
+import { HomePage } from './presentation/pages/HomePage.jsx';
+import { MangaDetailPage } from './presentation/pages/MangaDetailPage.jsx';
+import { AddMangaPage } from './presentation/pages/AddMangaPage.jsx';
+
+function App() {
+ return (
+
+
+ } />
+ } />
+ } />
+ } />
+
+
+ );
+}
+
+export default App;
\ No newline at end of file
diff --git a/assets/react/app/application/useCases/getMangaCollection.js b/assets/react/app/application/useCases/getMangaCollection.js
new file mode 100644
index 0000000..4418605
--- /dev/null
+++ b/assets/react/app/application/useCases/getMangaCollection.js
@@ -0,0 +1,9 @@
+export class GetMangaCollection {
+ constructor(mangaRepository) {
+ this.mangaRepository = mangaRepository;
+ }
+
+ async execute(page = 1) {
+ return await this.mangaRepository.getMangaCollection(page);
+ }
+}
\ No newline at end of file
diff --git a/assets/react/app/application/useCases/getMangaDetail.js b/assets/react/app/application/useCases/getMangaDetail.js
new file mode 100644
index 0000000..d9aed45
--- /dev/null
+++ b/assets/react/app/application/useCases/getMangaDetail.js
@@ -0,0 +1,9 @@
+export class GetMangaDetail {
+ constructor(mangaRepository) {
+ this.mangaRepository = mangaRepository;
+ }
+
+ async execute(slug) {
+ return await this.mangaRepository.getMangaBySlug(slug);
+ }
+}
\ No newline at end of file
diff --git a/assets/react/app/application/useCases/searchMangas.js b/assets/react/app/application/useCases/searchMangas.js
new file mode 100644
index 0000000..dc63692
--- /dev/null
+++ b/assets/react/app/application/useCases/searchMangas.js
@@ -0,0 +1,9 @@
+export class SearchMangas {
+ constructor(mangaRepository) {
+ this.mangaRepository = mangaRepository;
+ }
+
+ async execute(query) {
+ return await this.mangaRepository.searchMangas(query);
+ }
+}
\ No newline at end of file
diff --git a/assets/react/app/assets/react.svg b/assets/react/app/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/assets/react/app/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/react/app/domain/chapter.js b/assets/react/app/domain/chapter.js
new file mode 100644
index 0000000..fcd4aa2
--- /dev/null
+++ b/assets/react/app/domain/chapter.js
@@ -0,0 +1,10 @@
+export class Chapter {
+ constructor(id, number, title, volume, isVisible, createdAt) {
+ this.id = id;
+ this.number = number;
+ this.title = title;
+ this.volume = volume;
+ this.isVisible = isVisible;
+ this.createdAt = createdAt;
+ }
+}
\ No newline at end of file
diff --git a/assets/react/app/domain/manga.js b/assets/react/app/domain/manga.js
new file mode 100644
index 0000000..7b82ed5
--- /dev/null
+++ b/assets/react/app/domain/manga.js
@@ -0,0 +1,75 @@
+import { Chapter } from './chapter.js';
+
+export class Manga {
+ constructor(
+ id,
+ title,
+ slug,
+ imageUrl,
+ author,
+ publicationYear,
+ genres,
+ status,
+ rating,
+ description = ''
+ ) {
+ this.id = id;
+ this.title = title;
+ this.slug = slug;
+ this.imageUrl = imageUrl;
+ this.author = author;
+ this.publicationYear = publicationYear;
+ this.genres = genres;
+ this.status = status;
+ this.rating = rating;
+ this.description = description;
+ }
+}
+
+export class MangaCollection {
+ constructor(items, total, page, limit, hasNextPage, hasPreviousPage) {
+ this.items = items;
+ this.total = total;
+ this.page = page;
+ this.limit = limit;
+ this.hasNextPage = hasNextPage;
+ this.hasPreviousPage = hasPreviousPage;
+ }
+}
+
+export class MangaDetail extends Manga {
+ constructor(manga, chapters = []) {
+ super(
+ manga.id,
+ manga.title,
+ manga.slug,
+ manga.imageUrl,
+ manga.author,
+ manga.publicationYear,
+ manga.genres,
+ manga.status,
+ manga.rating,
+ manga.description
+ );
+ this.chapters = this.organizeChaptersByVolume(chapters);
+ }
+
+ organizeChaptersByVolume(chapters) {
+ const volumeMap = new Map();
+
+ chapters.forEach(chapter => {
+ const volume = chapter.volume || 0;
+ if (!volumeMap.has(volume)) {
+ volumeMap.set(volume, []);
+ }
+ volumeMap.get(volume).push(chapter);
+ });
+
+ // Sort chapters within each volume
+ volumeMap.forEach(chapters => {
+ chapters.sort((a, b) => b.number - a.number);
+ });
+
+ return new Map([...volumeMap.entries()].sort((a, b) => b[0] - a[0]));
+ }
+}
\ No newline at end of file
diff --git a/assets/react/app/domain/ports/mangaRepository.js b/assets/react/app/domain/ports/mangaRepository.js
new file mode 100644
index 0000000..29ffa21
--- /dev/null
+++ b/assets/react/app/domain/ports/mangaRepository.js
@@ -0,0 +1,6 @@
+// Port (interface) for manga data access
+export class MangaRepository {
+ async getMangaCollection(page = 1) {
+ throw new Error('Not implemented');
+ }
+}
\ No newline at end of file
diff --git a/assets/react/app/index.jsx b/assets/react/app/index.jsx
new file mode 100644
index 0000000..cec8494
--- /dev/null
+++ b/assets/react/app/index.jsx
@@ -0,0 +1,11 @@
+import React from 'react'
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import App from './App.jsx'
+import '../../styles/app.scss'
+
+createRoot(document.getElementById('react-app')).render(
+
+
+ ,
+)
diff --git a/assets/react/app/infrastructure/api/apiMangaRepository.js b/assets/react/app/infrastructure/api/apiMangaRepository.js
new file mode 100644
index 0000000..3e6ca64
--- /dev/null
+++ b/assets/react/app/infrastructure/api/apiMangaRepository.js
@@ -0,0 +1,41 @@
+import axios from 'axios';
+import { Manga, MangaCollection } from '../../domain/manga';
+
+export class ApiMangaRepository {
+ constructor() {
+ this.api = axios.create({
+ baseURL: '/api'
+ });
+ }
+
+ async getMangaCollection(page = 1) {
+ try {
+ const response = await this.api.get(`/mangas?page=${page}`);
+ const data = response.data;
+
+ const mangas = data.items.map(item => new Manga(
+ item.id,
+ item.title,
+ item.slug,
+ item.imageUrl,
+ item.author,
+ item.publicationYear,
+ item.genres,
+ item.status,
+ item.rating
+ ));
+
+ return new MangaCollection(
+ mangas,
+ data.total,
+ data.page,
+ data.limit,
+ data.hasNextPage,
+ data.hasPreviousPage
+ );
+ } catch (error) {
+ console.error('Error fetching manga collection:', error);
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/react/app/infrastructure/api/mockMangaRepository.js b/assets/react/app/infrastructure/api/mockMangaRepository.js
new file mode 100644
index 0000000..6794d33
--- /dev/null
+++ b/assets/react/app/infrastructure/api/mockMangaRepository.js
@@ -0,0 +1,109 @@
+import { Manga, MangaCollection, MangaDetail } from '../../domain/manga.js';
+import { Chapter } from '../../domain/chapter.js';
+
+export class MockMangaRepository {
+ constructor() {
+ this.mangas = {
+ 'one-piece': {
+ id: '1',
+ title: 'One Piece',
+ slug: 'one-piece',
+ imageUrl: 'https://images.unsplash.com/photo-1607604276583-eef5d076aa5f?auto=format&fit=crop&w=800&q=80',
+ author: 'Eiichiro Oda',
+ publicationYear: 1997,
+ genres: ['Action', 'Adventure', 'Comedy'],
+ status: 'ongoing',
+ rating: 4.9,
+ description: 'Monkey D. Luffy refuses to let anyone or anything stand in the way of his quest to become king of all pirates.'
+ },
+ 'naruto': {
+ id: '2',
+ title: 'Naruto',
+ slug: 'naruto',
+ imageUrl: 'https://images.unsplash.com/photo-1618519764620-7403abdbdfe9?auto=format&fit=crop&w=800&q=80',
+ author: 'Masashi Kishimoto',
+ publicationYear: 1999,
+ genres: ['Action', 'Adventure', 'Fantasy'],
+ status: 'completed',
+ rating: 4.8,
+ description: 'Twelve years ago the Village Hidden in the Leaves was attacked by a fearsome threat.'
+ },
+ 'berserk': {
+ id: '3',
+ title: 'Berserk',
+ slug: 'berserk',
+ imageUrl: 'https://images.unsplash.com/photo-1607604276583-eef5d076aa5f?auto=format&fit=crop&w=800&q=80',
+ author: 'Kentaro Miura',
+ publicationYear: 1989,
+ genres: ['Action', 'Dark Fantasy', 'Horror', 'Psychological'],
+ status: 'ongoing',
+ rating: 4.9,
+ description: 'Guts, known as the Black Swordsman, seeks sanctuary from the demonic forces.'
+ }
+ };
+ }
+
+ async searchMangas(query) {
+ if (!query) return [];
+
+ const normalizedQuery = query.toLowerCase();
+ return Object.values(this.mangas)
+ .filter(manga =>
+ manga.title.toLowerCase().includes(normalizedQuery) ||
+ manga.author.toLowerCase().includes(normalizedQuery)
+ )
+ .map(manga => new Manga(
+ manga.id,
+ manga.title,
+ manga.slug,
+ manga.imageUrl,
+ manga.author,
+ manga.publicationYear,
+ manga.genres,
+ manga.status,
+ manga.rating
+ ));
+ }
+
+ async getMangaCollection(page = 1) {
+ const mangas = Object.values(this.mangas).map(manga => new Manga(
+ manga.id,
+ manga.title,
+ manga.slug,
+ manga.imageUrl,
+ manga.author,
+ manga.publicationYear,
+ manga.genres,
+ manga.status,
+ manga.rating
+ ));
+
+ return new MangaCollection(
+ mangas,
+ mangas.length,
+ page,
+ 10,
+ false,
+ false
+ );
+ }
+
+ async getMangaBySlug(slug) {
+ const manga = this.mangas[slug];
+
+ if (!manga) {
+ throw new Error(`Manga with slug "${slug}" not found`);
+ }
+
+ const chapters = [
+ new Chapter('1', 378, 'Un assassin invité', 42, true, '2024-02-15'),
+ new Chapter('2', 377, 'Snake In One\'s Bosom', 42, true, '2024-02-01'),
+ new Chapter('3', 376, 'La mer tremble, la guerre se profile', 42, true, '2024-01-15'),
+ new Chapter('4', 375, 'L\'aube suivant la nuit brumeuse', 41, true, '2024-01-01'),
+ new Chapter('5', 374, 'Le monstre noir va-t-il se laisser faire ?', 41, true, '2023-12-15'),
+ new Chapter('6', 373, 'Confrontation', 41, true, '2023-12-01'),
+ ];
+
+ return new MangaDetail(manga, chapters);
+ }
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/components/Header.jsx b/assets/react/app/presentation/components/Header.jsx
new file mode 100644
index 0000000..a2e280e
--- /dev/null
+++ b/assets/react/app/presentation/components/Header.jsx
@@ -0,0 +1,26 @@
+import React from 'react';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faBars } from '@fortawesome/free-solid-svg-icons';
+import { SearchBar } from './SearchBar/SearchBar.jsx';
+
+export function Header({ onMenuClick, onMangaClick, onAddMangaClick }) {
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/components/Layout/Layout.jsx b/assets/react/app/presentation/components/Layout/Layout.jsx
new file mode 100644
index 0000000..c599ea5
--- /dev/null
+++ b/assets/react/app/presentation/components/Layout/Layout.jsx
@@ -0,0 +1,26 @@
+import React, { useState } from 'react';
+import { Header } from '../Header';
+import { Sidebar } from '../Sidebar';
+
+export function Layout({ children, onMangaClick, onAddMangaClick }) {
+ const [isSidebarOpen, setIsSidebarOpen] = useState(false);
+
+ return (
+
+ setIsSidebarOpen(!isSidebarOpen)}
+ onMangaClick={onMangaClick}
+ onAddMangaClick={onAddMangaClick}
+ />
+ setIsSidebarOpen(false)}
+ onAddMangaClick={onAddMangaClick}
+ />
+
+
+ {children}
+
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/components/MangaCard.jsx b/assets/react/app/presentation/components/MangaCard.jsx
new file mode 100644
index 0000000..05384c4
--- /dev/null
+++ b/assets/react/app/presentation/components/MangaCard.jsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faStar } from '@fortawesome/free-solid-svg-icons';
+
+export function MangaCard({ manga, onClick }) {
+ return (
+ onClick?.(manga.slug)}
+ >
+
+

+
+
+
{manga.title}
+
By {manga.author}
+
+ {manga.publicationYear}
+ {manga.rating && (
+
+
+ {manga.rating}
+
+ )}
+
+
+ {manga.genres.map((genre, index) => (
+
+ {genre}
+
+ ))}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/components/MangaGrid.jsx b/assets/react/app/presentation/components/MangaGrid.jsx
new file mode 100644
index 0000000..fa8eb86
--- /dev/null
+++ b/assets/react/app/presentation/components/MangaGrid.jsx
@@ -0,0 +1,16 @@
+import React from 'react';
+import { MangaCard } from './MangaCard.jsx';
+
+export function MangaGrid({ mangas, onMangaClick }) {
+ return (
+
+ {mangas.map((manga) => (
+
+ ))}
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/components/SearchBar/SearchBar.jsx b/assets/react/app/presentation/components/SearchBar/SearchBar.jsx
new file mode 100644
index 0000000..44e60bb
--- /dev/null
+++ b/assets/react/app/presentation/components/SearchBar/SearchBar.jsx
@@ -0,0 +1,125 @@
+import React, { useState, useRef, useEffect } from 'react';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faSearch, faPlus } from '@fortawesome/free-solid-svg-icons';
+import { MockMangaRepository } from '../../../infrastructure/api/mockMangaRepository.js';
+import { SearchMangas } from '../../../application/useCases/searchMangas.js';
+
+const mangaRepository = new MockMangaRepository();
+const searchMangas = new SearchMangas(mangaRepository);
+
+export function SearchBar({ onMangaClick, onAddMangaClick }) {
+ const [query, setQuery] = useState('');
+ const [results, setResults] = useState([]);
+ const [isOpen, setIsOpen] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [hasSearched, setHasSearched] = useState(false);
+ const searchRef = useRef(null);
+
+ useEffect(() => {
+ const handleClickOutside = (event) => {
+ if (searchRef.current && !searchRef.current.contains(event.target)) {
+ setIsOpen(false);
+ }
+ };
+
+ document.addEventListener('mousedown', handleClickOutside);
+ return () => document.removeEventListener('mousedown', handleClickOutside);
+ }, []);
+
+ useEffect(() => {
+ const searchManga = async () => {
+ if (!query.trim()) {
+ setResults([]);
+ setHasSearched(false);
+ return;
+ }
+
+ setLoading(true);
+ try {
+ const searchResults = await searchMangas.execute(query);
+ setResults(searchResults);
+ setHasSearched(true);
+ } catch (error) {
+ console.error('Search error:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const timeoutId = setTimeout(searchManga, 300);
+ return () => clearTimeout(timeoutId);
+ }, [query]);
+
+ return (
+
+
+
+ {
+ setQuery(e.target.value);
+ setIsOpen(true);
+ }}
+ onFocus={() => setIsOpen(true)}
+ placeholder="Rechercher"
+ className="appearance-none outline-none ml-2 pl-0 bg-transparent border-b border-white w-full placeholder:text-white text-white py-1 px-2 leading-tight transition-all duration-500 ease-in-out focus:placeholder:text-opacity-0 focus:border-opacity-0"
+ />
+
+
+ {isOpen && query.trim() && (
+
+ {loading ? (
+
Chargement...
+ ) : results.length > 0 ? (
+
+
+ Mangas existants
+
+ {results.map((manga) => (
+
+ ))}
+
+ ) : hasSearched && (
+
+
+
+ )}
+
+ )}
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/components/Sidebar.jsx b/assets/react/app/presentation/components/Sidebar.jsx
new file mode 100644
index 0000000..bd96296
--- /dev/null
+++ b/assets/react/app/presentation/components/Sidebar.jsx
@@ -0,0 +1,164 @@
+import React, { useState } from 'react';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {
+ faBook,
+ faPlus,
+ faFileImport,
+ faCompass,
+ faExchangeAlt,
+ faCalendar,
+ faClockRotateLeft,
+ faCog,
+ faDesktop,
+ faChevronDown,
+ faChevronUp
+} from '@fortawesome/free-solid-svg-icons';
+
+export function Sidebar({ isOpen, onClose, onAddMangaClick }) {
+ const [expandedMenus, setExpandedMenus] = useState({
+ mangas: true, // Par défaut, le menu Mangas est ouvert
+ settings: false,
+ system: false
+ });
+
+ const menuItems = [
+ {
+ icon: faBook,
+ text: 'Mangas',
+ id: 'mangas',
+ subItems: [
+ { icon: faPlus, text: 'Ajouter un nouveau', onClick: () => onAddMangaClick() },
+ { icon: faFileImport, text: 'Import bibliothèque', href: '#' },
+ { icon: faCompass, text: 'Découvrir', href: '#' },
+ ]
+ },
+ {
+ icon: faExchangeAlt,
+ text: 'Convertir CBR en CBZ',
+ href: '#'
+ },
+ {
+ icon: faCalendar,
+ text: 'Calendrier',
+ href: '#'
+ },
+ {
+ icon: faClockRotateLeft,
+ text: 'Activité',
+ href: '#',
+ badge: '3'
+ },
+ {
+ icon: faCog,
+ text: 'Paramètres',
+ id: 'settings',
+ subItems: [
+ { text: 'Général', href: '#' },
+ { text: 'Dossiers', href: '#' },
+ { text: 'Scrappers', href: '#' },
+ { text: 'UI', href: '#' }
+ ]
+ },
+ {
+ icon: faDesktop,
+ text: 'Système',
+ id: 'system',
+ subItems: [
+ { text: 'Status', href: '#' },
+ { text: 'Backup', href: '#' },
+ { text: 'Logs', href: '#' },
+ { text: 'Updates', href: '#' }
+ ]
+ },
+ ];
+
+ const toggleMenu = (menuId) => {
+ setExpandedMenus(prev => ({
+ ...prev,
+ [menuId]: !prev[menuId]
+ }));
+ };
+
+ const MenuItem = ({ item }) => {
+ const hasSubItems = item.subItems && item.subItems.length > 0;
+ const isExpanded = item.id && expandedMenus[item.id];
+ const isActive = false; // À implémenter avec un vrai système de routing
+
+ return (
+
+
+
+ {hasSubItems && isExpanded && (
+
+ )}
+
+ );
+ };
+
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/components/Toolbar/Toolbar.jsx b/assets/react/app/presentation/components/Toolbar/Toolbar.jsx
new file mode 100644
index 0000000..7bc33ce
--- /dev/null
+++ b/assets/react/app/presentation/components/Toolbar/Toolbar.jsx
@@ -0,0 +1,29 @@
+import React from 'react';
+import { ToolbarButton } from './ToolbarButton';
+
+export function Toolbar({
+ leftSection = [],
+ centerSection = [],
+ rightSection = [],
+ className = ''
+}) {
+ const renderSection = (items) => (
+
+ {items.map((item, index) => (
+
+ ))}
+
+ );
+
+ return (
+
+
+
+ {renderSection(leftSection)}
+ {renderSection(centerSection)}
+ {renderSection(rightSection)}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/components/Toolbar/ToolbarButton.jsx b/assets/react/app/presentation/components/Toolbar/ToolbarButton.jsx
new file mode 100644
index 0000000..6d6832c
--- /dev/null
+++ b/assets/react/app/presentation/components/Toolbar/ToolbarButton.jsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+export function ToolbarButton({ icon, label, onClick, active = false }) {
+ return (
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/pages/AddMangaPage.jsx b/assets/react/app/presentation/pages/AddMangaPage.jsx
new file mode 100644
index 0000000..efe65c0
--- /dev/null
+++ b/assets/react/app/presentation/pages/AddMangaPage.jsx
@@ -0,0 +1,185 @@
+import React, { useState, useEffect } from 'react';
+import { useNavigate, useSearchParams } from 'react-router-dom';
+import { Layout } from '../components/Layout/Layout';
+import { Toolbar } from '../components/Toolbar/Toolbar';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faArrowLeft, faSearch, faStar } from '@fortawesome/free-solid-svg-icons';
+import { MockMangaRepository } from '../../infrastructure/api/mockMangaRepository';
+import { SearchMangas } from '../../application/useCases/searchMangas';
+
+const mangaRepository = new MockMangaRepository();
+const searchMangas = new SearchMangas(mangaRepository);
+
+export function AddMangaPage() {
+ const navigate = useNavigate();
+ const [searchParams] = useSearchParams();
+ const initialQuery = searchParams.get('q') || '';
+
+ const [query, setQuery] = useState(initialQuery);
+ const [results, setResults] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [selectedManga, setSelectedManga] = useState(null);
+
+ useEffect(() => {
+ if (initialQuery) {
+ handleSearch(initialQuery);
+ }
+ }, [initialQuery]);
+
+ const handleSearch = async (searchQuery) => {
+ if (!searchQuery.trim()) {
+ setResults([]);
+ return;
+ }
+
+ setLoading(true);
+ try {
+ const searchResults = await searchMangas.execute(searchQuery);
+ setResults(searchResults);
+ } catch (error) {
+ console.error('Search error:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const handleMangaClick = (slug) => {
+ navigate(`/manga/${slug}`);
+ };
+
+ const handleAddMangaClick = (query = '') => {
+ navigate(`/add${query ? `?q=${encodeURIComponent(query)}` : ''}`);
+ };
+
+ const toolbarConfig = {
+ leftSection: [
+ { icon: faArrowLeft, onClick: () => navigate(-1) }
+ ]
+ };
+
+ return (
+
+
+
+
+
Ajouter un manga
+
+
+
+
+ {
+ setQuery(e.target.value);
+ handleSearch(e.target.value);
+ }}
+ placeholder="Rechercher un manga..."
+ className="w-full px-4 py-2 pl-10 border-b border-gray-300 focus:border-green-600 outline-none transition-colors"
+ />
+
+
+
+ {loading ? (
+
+ ) : results.length > 0 ? (
+
+ {results.map((manga) => (
+
setSelectedManga(manga)}
+ className="flex gap-4 p-4 bg-gray-50 rounded-lg hover:bg-gray-100 transition-colors cursor-pointer"
+ >
+

+
+
+
+
{manga.title}
+
{manga.author}
+
+
+
+ {manga.rating}
+
+
+
+
+ {manga.publicationYear} • {manga.status}
+
+
+
+ {manga.genres.map((genre, index) => (
+
+ {genre}
+
+ ))}
+
+
+
+ ))}
+
+ ) : query && !loading && (
+
+ Aucun résultat trouvé pour "{query}"
+
+ )}
+
+
+
+
+ {/* Modal de confirmation */}
+ {selectedManga && (
+
+
+
+
Ajouter à la bibliothèque
+
+

+
+
{selectedManga.title}
+
{selectedManga.author}
+
+ {selectedManga.genres.join(', ')}
+
+
+
+
+
+
+
+
+
+
+ )}
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/pages/HomePage.jsx b/assets/react/app/presentation/pages/HomePage.jsx
new file mode 100644
index 0000000..e88444f
--- /dev/null
+++ b/assets/react/app/presentation/pages/HomePage.jsx
@@ -0,0 +1,80 @@
+import React, { useEffect, useState } from 'react';
+import { useNavigate } from 'react-router-dom';
+import { MangaGrid } from '../components/MangaGrid.jsx';
+import { Layout } from '../components/Layout/Layout.jsx';
+import { Toolbar } from '../components/Toolbar/Toolbar.jsx';
+import { MockMangaRepository } from '../../infrastructure/api/mockMangaRepository.js';
+import { GetMangaCollection } from '../../application/useCases/getMangaCollection.js';
+import {
+ faRefresh,
+ faSearch,
+ faGear,
+ faEye,
+ faSort,
+ faFilter
+} from '@fortawesome/free-solid-svg-icons';
+
+const mangaRepository = new MockMangaRepository();
+const getMangaCollection = new GetMangaCollection(mangaRepository);
+
+export function HomePage() {
+ const navigate = useNavigate();
+ const [mangaCollection, setMangaCollection] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ const handleRefresh = async () => {
+ setLoading(true);
+ try {
+ const collection = await getMangaCollection.execute(1);
+ setMangaCollection(collection);
+ } catch (err) {
+ setError('Failed to load mangas');
+ console.error(err);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ handleRefresh();
+ }, []);
+
+ const handleMangaClick = (slug) => {
+ navigate(`/manga/${slug}`);
+ };
+
+ const handleAddMangaClick = (query = '') => {
+ navigate(`/add${query ? `?q=${encodeURIComponent(query)}` : ''}`);
+ };
+
+ const toolbarConfig = {
+ leftSection: [
+ { icon: faRefresh, label: 'Refresh', onClick: handleRefresh },
+ { icon: faSearch, label: 'Search', onClick: () => {} }
+ ],
+ rightSection: [
+ { icon: faGear, onClick: () => {} },
+ { icon: faEye, onClick: () => {} },
+ { icon: faSort, onClick: () => {} },
+ { icon: faFilter, onClick: () => {} }
+ ]
+ };
+
+ if (loading) {
+ return Loading...
;
+ }
+
+ if (error) {
+ return {error}
;
+ }
+
+ return (
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/assets/react/app/presentation/pages/MangaDetailPage.jsx b/assets/react/app/presentation/pages/MangaDetailPage.jsx
new file mode 100644
index 0000000..5b39ff4
--- /dev/null
+++ b/assets/react/app/presentation/pages/MangaDetailPage.jsx
@@ -0,0 +1,183 @@
+import React, { useEffect, useState } from 'react';
+import { useParams, useNavigate } from 'react-router-dom';
+import { MockMangaRepository } from '../../infrastructure/api/mockMangaRepository.js';
+import { GetMangaDetail } from '../../application/useCases/getMangaDetail.js';
+import { Layout } from '../components/Layout/Layout.jsx';
+import { Toolbar } from '../components/Toolbar/Toolbar.jsx';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {
+ faStar,
+ faDownload,
+ faEye,
+ faArrowLeft,
+ faRefresh,
+ faBookmark,
+ faShare
+} from '@fortawesome/free-solid-svg-icons';
+
+const mangaRepository = new MockMangaRepository();
+const getMangaDetail = new GetMangaDetail(mangaRepository);
+
+export function MangaDetailPage() {
+ const { slug } = useParams();
+ const navigate = useNavigate();
+ const [manga, setManga] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ const handleRefresh = async () => {
+ setLoading(true);
+ try {
+ const mangaDetail = await getMangaDetail.execute(slug);
+ setManga(mangaDetail);
+ } catch (err) {
+ setError('Failed to load manga details');
+ console.error(err);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ handleRefresh();
+ }, [slug]);
+
+ const handleMangaClick = (mangaSlug) => {
+ navigate(`/manga/${mangaSlug}`);
+ };
+
+ const handleAddMangaClick = (query = '') => {
+ navigate(`/add${query ? `?q=${encodeURIComponent(query)}` : ''}`);
+ };
+
+ const toolbarConfig = {
+ leftSection: [
+ { icon: faArrowLeft, onClick: () => navigate(-1) },
+ { icon: faRefresh, onClick: handleRefresh }
+ ],
+ rightSection: [
+ { icon: faBookmark, onClick: () => {} },
+ { icon: faShare, onClick: () => {} },
+ { icon: faDownload, onClick: () => {} }
+ ]
+ };
+
+ if (loading) {
+ return Loading...
;
+ }
+
+ if (error) {
+ return {error}
;
+ }
+
+ return (
+
+
+
+ {/* Hero section with manga info */}
+
+
+

+
+
+
+
+
+
+
{manga.title}
+
+ {manga.status}
+
+
+
+
+
+
+ {manga.rating}
+
+
{manga.publicationYear}
+
{manga.author}
+
+
+
+ {manga.genres.map((genre, index) => (
+
+ {genre}
+
+ ))}
+
+
+
+ {manga.description}
+
+
+
+
+
+ {/* Chapters section */}
+
+ {Array.from(manga.chapters.entries()).map(([volume, chapters]) => (
+
+
+ Volume {volume || 'Unknown'}
+
+ ({chapters.length} chapters)
+
+
+
+
+
+
+
+ |
+ #
+ |
+
+ Title
+ |
+
+ Added
+ |
+
+ Actions
+ |
+
+
+
+ {chapters.map((chapter) => (
+
+ |
+ {chapter.number}
+ |
+
+ {chapter.title}
+ |
+
+ {new Date(chapter.createdAt).toLocaleDateString()}
+ |
+
+
+
+ |
+
+ ))}
+
+
+
+
+ ))}
+
+
+ );
+}
\ No newline at end of file
diff --git a/composer.json b/composer.json
index 3b04b95..074f48d 100644
--- a/composer.json
+++ b/composer.json
@@ -47,6 +47,7 @@
"symfony/stimulus-bundle": "^2.17",
"symfony/twig-bundle": "7.0.*",
"symfony/ux-live-component": "^2.17",
+ "symfony/ux-react": "^2.23",
"symfony/ux-turbo": "^2.18",
"symfony/validator": "7.0.*",
"symfony/webpack-encore-bundle": "^2.1",
diff --git a/composer.lock b/composer.lock
index d131de6..b26ae21 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "e84863f24aa342f98beebd3cd364f698",
+ "content-hash": "e2253575e3f4a0344fe2ff59ac54aad0",
"packages": [
{
"name": "api-platform/core",
@@ -8233,6 +8233,82 @@
],
"time": "2024-04-22T18:53:03+00:00"
},
+ {
+ "name": "symfony/ux-react",
+ "version": "v2.23.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/ux-react.git",
+ "reference": "9ca27a52c536994f48005ee70e2208d0769b2ae8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/ux-react/zipball/9ca27a52c536994f48005ee70e2208d0769b2ae8",
+ "reference": "9ca27a52c536994f48005ee70e2208d0769b2ae8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/stimulus-bundle": "^2.9.1"
+ },
+ "require-dev": {
+ "symfony/asset-mapper": "^6.3|^7.0",
+ "symfony/finder": "^5.4|^6.0|^7.0",
+ "symfony/framework-bundle": "^5.4|^6.0|^7.0",
+ "symfony/phpunit-bridge": "^5.4|^6.0|^7.0",
+ "symfony/twig-bundle": "^5.4|^6.0|^7.0",
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/ux",
+ "name": "symfony/ux"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\UX\\React\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Titouan Galopin",
+ "email": "galopintitouan@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Integration of React in Symfony",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "symfony-ux"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/ux-react/tree/v2.23.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-12-05T14:25:02+00:00"
+ },
{
"name": "symfony/ux-turbo",
"version": "v2.18.0",
diff --git a/config/bundles.php b/config/bundles.php
index 24a8025..2aee5e1 100644
--- a/config/bundles.php
+++ b/config/bundles.php
@@ -21,4 +21,5 @@ return [
Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true],
+ Symfony\UX\React\ReactBundle::class => ['all' => true],
];
diff --git a/config/routes.yaml b/config/routes.yaml
index 41ef814..8790af5 100644
--- a/config/routes.yaml
+++ b/config/routes.yaml
@@ -3,3 +3,9 @@ controllers:
path: ../src/Controller/
namespace: App\Controller
type: attribute
+
+react_app:
+ path: /react
+ controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController
+ defaults:
+ template: 'react/index.html.twig'
diff --git a/package-lock.json b/package-lock.json
index e3d396a..0a352c0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7,25 +7,33 @@
"license": "UNLICENSED",
"dependencies": {
"@fortawesome/fontawesome-free": "^6.5.2",
+ "@fortawesome/fontawesome-svg-core": "^6.7.2",
+ "@fortawesome/free-solid-svg-icons": "^6.7.2",
+ "@fortawesome/react-fontawesome": "^0.2.2",
"alpinejs": "^3.13.3",
"autoprefixer": "^10.4.14",
"bootstrap": "^5.3.3",
"postcss-loader": "^7.1.0",
"puppeteer": "^22.10.0",
+ "react-router-dom": "^7.1.5",
"sortablejs": "^1.15.2",
"tailwindcss": "^3.2.7"
},
"devDependencies": {
"@babel/core": "^7.17.0",
"@babel/preset-env": "^7.16.0",
+ "@babel/preset-react": "^7.26.3",
"@hotwired/stimulus": "^3.0.0",
"@hotwired/turbo": "^7.1.1 || ^8.0",
"@symfony/stimulus-bridge": "^3.2.0",
"@symfony/ux-live-component": "file:vendor/symfony/ux-live-component/assets",
+ "@symfony/ux-react": "file:vendor/symfony/ux-react/assets",
"@symfony/ux-turbo": "file:vendor/symfony/ux-turbo/assets",
"@symfony/webpack-encore": "^4.0.0",
"core-js": "^3.23.0",
"daisyui": "^4.4.2",
+ "react": "^18.0",
+ "react-dom": "^18.0",
"regenerator-runtime": "^0.13.9",
"sass": "^1.59.3",
"sass-loader": "^13.2.0",
@@ -60,11 +68,13 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz",
- "integrity": "sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==",
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/highlight": "^7.24.6",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
@@ -72,30 +82,33 @@
}
},
"node_modules/@babel/compat-data": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.6.tgz",
- "integrity": "sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==",
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz",
+ "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.6.tgz",
- "integrity": "sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==",
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.8.tgz",
+ "integrity": "sha512-l+lkXCHS6tQEc5oUpK28xBOZ6+HwaH7YwoYQbLFiYb4nS2/l1tKnZEtEWkD0GuiYdvArf9qBS0XlQGXzPMsNqQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.24.6",
- "@babel/generator": "^7.24.6",
- "@babel/helper-compilation-targets": "^7.24.6",
- "@babel/helper-module-transforms": "^7.24.6",
- "@babel/helpers": "^7.24.6",
- "@babel/parser": "^7.24.6",
- "@babel/template": "^7.24.6",
- "@babel/traverse": "^7.24.6",
- "@babel/types": "^7.24.6",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.8",
+ "@babel/helper-compilation-targets": "^7.26.5",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.7",
+ "@babel/parser": "^7.26.8",
+ "@babel/template": "^7.26.8",
+ "@babel/traverse": "^7.26.8",
+ "@babel/types": "^7.26.8",
+ "@types/gensync": "^1.0.0",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@@ -111,27 +124,30 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.6.tgz",
- "integrity": "sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==",
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.8.tgz",
+ "integrity": "sha512-ef383X5++iZHWAXX0SXQR6ZyQhw/0KtTkrTz61WXRhFM6dhpHulO/RJz79L8S6ugZHJkOOkUrUdxgdF2YiPFnA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.6",
+ "@babel/parser": "^7.26.8",
+ "@babel/types": "^7.26.8",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^2.5.1"
+ "jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz",
- "integrity": "sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.6"
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -150,14 +166,15 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz",
- "integrity": "sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==",
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz",
+ "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.24.6",
- "@babel/helper-validator-option": "^7.24.6",
- "browserslist": "^4.22.2",
+ "@babel/compat-data": "^7.26.5",
+ "@babel/helper-validator-option": "^7.25.9",
+ "browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
},
@@ -268,28 +285,29 @@
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz",
- "integrity": "sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.6"
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz",
- "integrity": "sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+ "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-environment-visitor": "^7.24.6",
- "@babel/helper-module-imports": "^7.24.6",
- "@babel/helper-simple-access": "^7.24.6",
- "@babel/helper-split-export-declaration": "^7.24.6",
- "@babel/helper-validator-identifier": "^7.24.6"
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -311,10 +329,11 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz",
- "integrity": "sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==",
+ "version": "7.26.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz",
+ "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@@ -390,27 +409,30 @@
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz",
- "integrity": "sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz",
- "integrity": "sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz",
- "integrity": "sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==",
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@@ -430,37 +452,28 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.6.tgz",
- "integrity": "sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==",
+ "version": "7.26.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz",
+ "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/template": "^7.24.6",
- "@babel/types": "^7.24.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.6.tgz",
- "integrity": "sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.24.6",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.26.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.6.tgz",
- "integrity": "sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==",
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.8.tgz",
+ "integrity": "sha512-TZIQ25pkSoaKEYYaHbbxkfL36GNsQ6iFiBbeuzAkLnXayKR1yP1zFe+NxuZWWsUyvt8icPU9CCq0sgWGXR1GEw==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.26.8"
+ },
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -661,6 +674,22 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
+ "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-logical-assignment-operators": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
@@ -1380,6 +1409,107 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-react-display-name": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz",
+ "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz",
+ "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-development": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz",
+ "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/plugin-transform-react-jsx": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz",
+ "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz",
+ "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz",
+ "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-transform-regenerator": {
"version": "7.24.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz",
@@ -1659,6 +1789,27 @@
"@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
}
},
+ "node_modules/@babel/preset-react": {
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.26.3.tgz",
+ "integrity": "sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-transform-react-display-name": "^7.25.9",
+ "@babel/plugin-transform-react-jsx": "^7.25.9",
+ "@babel/plugin-transform-react-jsx-development": "^7.25.9",
+ "@babel/plugin-transform-react-pure-annotations": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/regjsgen": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
@@ -1703,33 +1854,32 @@
"dev": true
},
"node_modules/@babel/template": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.6.tgz",
- "integrity": "sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==",
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.8.tgz",
+ "integrity": "sha512-iNKaX3ZebKIsCvJ+0jd6embf+Aulaa3vNBqZ41kM7iTWjx5qzWKXGHiJUW3+nTpQ18SG11hdF8OAzKrpXkb96Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.6",
- "@babel/parser": "^7.24.6",
- "@babel/types": "^7.24.6"
+ "@babel/code-frame": "^7.26.2",
+ "@babel/parser": "^7.26.8",
+ "@babel/types": "^7.26.8"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.6.tgz",
- "integrity": "sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==",
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.8.tgz",
+ "integrity": "sha512-nic9tRkjYH0oB2dzr/JoGIm+4Q6SuYeLEiIiZDwBscRMYFJ+tMAz98fuel9ZnbXViA2I0HVSSRRK8DW5fjXStA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.6",
- "@babel/generator": "^7.24.6",
- "@babel/helper-environment-visitor": "^7.24.6",
- "@babel/helper-function-name": "^7.24.6",
- "@babel/helper-hoist-variables": "^7.24.6",
- "@babel/helper-split-export-declaration": "^7.24.6",
- "@babel/parser": "^7.24.6",
- "@babel/types": "^7.24.6",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.26.8",
+ "@babel/parser": "^7.26.8",
+ "@babel/template": "^7.26.8",
+ "@babel/types": "^7.26.8",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@@ -1738,14 +1888,14 @@
}
},
"node_modules/@babel/types": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.6.tgz",
- "integrity": "sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==",
+ "version": "7.26.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.8.tgz",
+ "integrity": "sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.24.6",
- "@babel/helper-validator-identifier": "^7.24.6",
- "to-fast-properties": "^2.0.0"
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1760,6 +1910,465 @@
"node": ">=10.0.0"
}
},
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
+ "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz",
+ "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz",
+ "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz",
+ "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz",
+ "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz",
+ "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz",
+ "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz",
+ "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz",
+ "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz",
+ "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz",
+ "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz",
+ "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz",
+ "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz",
+ "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz",
+ "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz",
+ "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz",
+ "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz",
+ "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz",
+ "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz",
+ "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz",
+ "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz",
+ "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz",
+ "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz",
+ "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz",
+ "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
+ "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@fortawesome/fontawesome-free": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.2.tgz",
@@ -1769,6 +2378,43 @@
"node": ">=6"
}
},
+ "node_modules/@fortawesome/fontawesome-svg-core": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
+ "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
+ "license": "MIT",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-solid-svg-icons": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
+ "integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/react-fontawesome": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz",
+ "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "@fortawesome/fontawesome-svg-core": "~1 || ~6",
+ "react": ">=16.3"
+ }
+ },
"node_modules/@hotwired/stimulus": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@hotwired/stimulus/-/stimulus-3.2.2.tgz",
@@ -2154,6 +2800,291 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"license": "ISC"
},
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz",
+ "integrity": "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.6.tgz",
+ "integrity": "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.6.tgz",
+ "integrity": "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.6.tgz",
+ "integrity": "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.6.tgz",
+ "integrity": "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.6.tgz",
+ "integrity": "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.6.tgz",
+ "integrity": "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.6.tgz",
+ "integrity": "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.6.tgz",
+ "integrity": "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.6.tgz",
+ "integrity": "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.6.tgz",
+ "integrity": "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.6.tgz",
+ "integrity": "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.6.tgz",
+ "integrity": "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.6.tgz",
+ "integrity": "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.6.tgz",
+ "integrity": "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.6.tgz",
+ "integrity": "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.6.tgz",
+ "integrity": "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.6.tgz",
+ "integrity": "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.6.tgz",
+ "integrity": "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "peer": true
+ },
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@@ -2183,6 +3114,10 @@
"resolved": "vendor/symfony/ux-live-component/assets",
"link": true
},
+ "node_modules/@symfony/ux-react": {
+ "resolved": "vendor/symfony/ux-react/assets",
+ "link": true
+ },
"node_modules/@symfony/ux-turbo": {
"resolved": "vendor/symfony/ux-turbo/assets",
"link": true
@@ -2557,6 +3492,51 @@
"integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==",
"dev": true
},
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.8",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
+ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.6",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
+ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
"node_modules/@types/body-parser": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
@@ -2595,6 +3575,12 @@
"@types/node": "*"
}
},
+ "node_modules/@types/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
+ "license": "MIT"
+ },
"node_modules/@types/eslint": {
"version": "8.56.10",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz",
@@ -2614,9 +3600,10 @@
}
},
"node_modules/@types/estree": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
- "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "license": "MIT"
},
"node_modules/@types/express": {
"version": "4.17.21",
@@ -2642,6 +3629,13 @@
"@types/send": "*"
}
},
+ "node_modules/@types/gensync": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@types/gensync/-/gensync-1.0.4.tgz",
+ "integrity": "sha512-C3YYeRQWp2fmq9OryX+FoDy8nXS6scQ7dPptD8LnFDAUNcKWJjXQKDNJD3HVm+kOUsXhTOkpi69vI4EuAr95bA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
@@ -2735,6 +3729,13 @@
"@types/node": "*"
}
},
+ "node_modules/@types/prop-types": {
+ "version": "15.7.14",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz",
+ "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/qs": {
"version": "6.9.15",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz",
@@ -2747,6 +3748,27 @@
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
"dev": true
},
+ "node_modules/@types/react": {
+ "version": "18.3.18",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz",
+ "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.5",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz",
+ "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^18.0.0"
+ }
+ },
"node_modules/@types/retry": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
@@ -2832,6 +3854,26 @@
"@types/node": "*"
}
},
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz",
+ "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.26.0",
+ "@babel/plugin-transform-react-jsx-self": "^7.25.9",
+ "@babel/plugin-transform-react-jsx-source": "^7.25.9",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.14.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0"
+ }
+ },
"node_modules/@vue/reactivity": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
@@ -3173,6 +4215,7 @@
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
"dependencies": {
"color-convert": "^1.9.0"
},
@@ -3643,9 +4686,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.23.0",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
- "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
+ "version": "4.24.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
+ "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"funding": [
{
"type": "opencollective",
@@ -3660,11 +4703,12 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001587",
- "electron-to-chromium": "^1.4.668",
- "node-releases": "^2.0.14",
- "update-browserslist-db": "^1.0.13"
+ "caniuse-lite": "^1.0.30001688",
+ "electron-to-chromium": "^1.5.73",
+ "node-releases": "^2.0.19",
+ "update-browserslist-db": "^1.1.1"
},
"bin": {
"browserslist": "cli.js"
@@ -3780,9 +4824,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001627",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001627.tgz",
- "integrity": "sha512-4zgNiB8nTyV/tHhwZrFs88ryjls/lHiqFhrxCW4qSTeuRByBVnPYpDInchOIySWknznucaf31Z4KYqjfbrecVw==",
+ "version": "1.0.30001699",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001699.tgz",
+ "integrity": "sha512-b+uH5BakXZ9Do9iK+CkDmctUSEqZl+SP056vc5usa0PL+ev5OHw003rZXcnjNDv3L8P5j6rwT6C0BPKSikW08w==",
"funding": [
{
"type": "opencollective",
@@ -3796,12 +4840,14 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
- ]
+ ],
+ "license": "CC-BY-4.0"
},
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
@@ -3815,6 +4861,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
"engines": {
"node": ">=0.8.0"
}
@@ -3976,6 +5023,7 @@
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
"dependencies": {
"color-name": "1.1.3"
}
@@ -3983,7 +5031,8 @@
"node_modules/color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
},
"node_modules/colord": {
"version": "2.9.3",
@@ -4547,6 +5596,13 @@
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
"dev": true
},
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/culori": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz",
@@ -4814,9 +5870,10 @@
"dev": true
},
"node_modules/electron-to-chromium": {
- "version": "1.4.788",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.788.tgz",
- "integrity": "sha512-ubp5+Ev/VV8KuRoWnfP2QF2Bg+O2ZFdb49DiiNbz2VmgkIqrnyYaqIOqj8A6K/3p1xV0QcU5hBQ1+BmB6ot1OA=="
+ "version": "1.5.97",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.97.tgz",
+ "integrity": "sha512-HKLtaH02augM7ZOdYRuO19rWDeY+QSJ1VxnXFa/XDFLf07HvM90pALIJFgrO+UVaajI3+aJMMpojoUTLZyQ7JQ==",
+ "license": "ISC"
},
"node_modules/emoji-regex": {
"version": "8.0.0",
@@ -4935,10 +5992,53 @@
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz",
"integrity": "sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg=="
},
+ "node_modules/esbuild": {
+ "version": "0.24.2",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
+ "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.24.2",
+ "@esbuild/android-arm": "0.24.2",
+ "@esbuild/android-arm64": "0.24.2",
+ "@esbuild/android-x64": "0.24.2",
+ "@esbuild/darwin-arm64": "0.24.2",
+ "@esbuild/darwin-x64": "0.24.2",
+ "@esbuild/freebsd-arm64": "0.24.2",
+ "@esbuild/freebsd-x64": "0.24.2",
+ "@esbuild/linux-arm": "0.24.2",
+ "@esbuild/linux-arm64": "0.24.2",
+ "@esbuild/linux-ia32": "0.24.2",
+ "@esbuild/linux-loong64": "0.24.2",
+ "@esbuild/linux-mips64el": "0.24.2",
+ "@esbuild/linux-ppc64": "0.24.2",
+ "@esbuild/linux-riscv64": "0.24.2",
+ "@esbuild/linux-s390x": "0.24.2",
+ "@esbuild/linux-x64": "0.24.2",
+ "@esbuild/netbsd-arm64": "0.24.2",
+ "@esbuild/netbsd-x64": "0.24.2",
+ "@esbuild/openbsd-arm64": "0.24.2",
+ "@esbuild/openbsd-x64": "0.24.2",
+ "@esbuild/sunos-x64": "0.24.2",
+ "@esbuild/win32-arm64": "0.24.2",
+ "@esbuild/win32-ia32": "0.24.2",
+ "@esbuild/win32-x64": "0.24.2"
+ }
+ },
"node_modules/escalade": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
- "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -5672,6 +6772,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
"engines": {
"node": ">=4"
}
@@ -6454,7 +7555,8 @@
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.0",
@@ -6474,15 +7576,16 @@
"license": "MIT"
},
"node_modules/jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
+ "license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
- "node": ">=4"
+ "node": ">=6"
}
},
"node_modules/json-parse-even-better-errors": {
@@ -6615,6 +7718,18 @@
"integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
"dev": true
},
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -6874,15 +7989,16 @@
}
},
"node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "version": "3.3.8",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
+ "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -6969,9 +8085,10 @@
}
},
"node_modules/node-releases": {
- "version": "2.0.14",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
- "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
+ "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
+ "license": "MIT"
},
"node_modules/normalize-path": {
"version": "3.0.0",
@@ -7316,9 +8433,10 @@
"license": "MIT"
},
"node_modules/picocolors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
- "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew=="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
},
"node_modules/picomatch": {
"version": "2.3.1",
@@ -7458,9 +8576,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.38",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "version": "8.5.2",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz",
+ "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==",
"funding": [
{
"type": "opencollective",
@@ -7475,10 +8593,11 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
- "nanoid": "^3.3.7",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.2.0"
+ "nanoid": "^3.3.8",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
@@ -8220,6 +9339,23 @@
"node": ">=0.4.0"
}
},
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -8453,12 +9589,96 @@
"node": ">= 0.8"
}
},
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
"dev": true
},
+ "node_modules/react-refresh": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
+ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.5.tgz",
+ "integrity": "sha512-8BUF+hZEU4/z/JD201yK6S+UYhsf58bzYIDq2NS1iGpwxSXDu7F+DeGSkIXMFBuHZB21FSiCzEcUb18cQNdRkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/cookie": "^0.6.0",
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0",
+ "turbo-stream": "2.4.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.1.5",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.5.tgz",
+ "integrity": "sha512-/4f9+up0Qv92D3bB8iN5P1s3oHAepSGa9h5k6tpTFlixTTskJZwKGhJ6vRJ277tLD1zuaZTt95hyGWV1Z37csQ==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.1.5"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/react-router/node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -8724,6 +9944,46 @@
"rimraf": "bin.js"
}
},
+ "node_modules/rollup": {
+ "version": "4.34.6",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz",
+ "integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/estree": "1.0.6"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.34.6",
+ "@rollup/rollup-android-arm64": "4.34.6",
+ "@rollup/rollup-darwin-arm64": "4.34.6",
+ "@rollup/rollup-darwin-x64": "4.34.6",
+ "@rollup/rollup-freebsd-arm64": "4.34.6",
+ "@rollup/rollup-freebsd-x64": "4.34.6",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.34.6",
+ "@rollup/rollup-linux-arm-musleabihf": "4.34.6",
+ "@rollup/rollup-linux-arm64-gnu": "4.34.6",
+ "@rollup/rollup-linux-arm64-musl": "4.34.6",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.34.6",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6",
+ "@rollup/rollup-linux-riscv64-gnu": "4.34.6",
+ "@rollup/rollup-linux-s390x-gnu": "4.34.6",
+ "@rollup/rollup-linux-x64-gnu": "4.34.6",
+ "@rollup/rollup-linux-x64-musl": "4.34.6",
+ "@rollup/rollup-win32-arm64-msvc": "4.34.6",
+ "@rollup/rollup-win32-ia32-msvc": "4.34.6",
+ "@rollup/rollup-win32-x64-msvc": "4.34.6",
+ "fsevents": "~2.3.2"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -8825,6 +10085,15 @@
}
}
},
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
"node_modules/schema-utils": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
@@ -9016,6 +10285,12 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -9172,9 +10447,10 @@
}
},
"node_modules/source-map-js": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
- "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
@@ -9439,6 +10715,7 @@
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
"dependencies": {
"has-flag": "^3.0.0"
},
@@ -9789,15 +11066,6 @@
"node": ">=14.14"
}
},
- "node_modules/to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -9835,6 +11103,12 @@
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
"license": "0BSD"
},
+ "node_modules/turbo-stream": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
+ "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==",
+ "license": "ISC"
+ },
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -9922,9 +11196,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.0.16",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz",
- "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
+ "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==",
"funding": [
{
"type": "opencollective",
@@ -9939,9 +11213,10 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
- "escalade": "^3.1.2",
- "picocolors": "^1.0.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
@@ -10002,6 +11277,79 @@
"node": ">= 0.8"
}
},
+ "node_modules/vite": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.1.0.tgz",
+ "integrity": "sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "esbuild": "^0.24.2",
+ "postcss": "^8.5.1",
+ "rollup": "^4.30.1"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "jiti": ">=1.21.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "jiti": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
+ }
+ },
"node_modules/watchpack": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz",
@@ -10666,6 +12014,26 @@
"@hotwired/stimulus": "^3.0.0"
}
},
+ "vendor/symfony/ux-react/assets": {
+ "name": "@symfony/ux-react",
+ "version": "1.0.0",
+ "dev": true,
+ "license": "MIT",
+ "devDependencies": {
+ "@hotwired/stimulus": "^3.0.0",
+ "@types/react": "^18.0",
+ "@types/react-dom": "^18.0",
+ "@types/webpack-env": "^1.16",
+ "@vitejs/plugin-react": "^4.1.0",
+ "react": "^18.0",
+ "react-dom": "^18.0"
+ },
+ "peerDependencies": {
+ "@hotwired/stimulus": "^3.0.0",
+ "react": "^18.0",
+ "react-dom": "^18.0"
+ }
+ },
"vendor/symfony/ux-turbo/assets": {
"name": "@symfony/ux-turbo",
"version": "0.1.0",
diff --git a/package.json b/package.json
index 3a90333..c9c1c6c 100644
--- a/package.json
+++ b/package.json
@@ -2,14 +2,18 @@
"devDependencies": {
"@babel/core": "^7.17.0",
"@babel/preset-env": "^7.16.0",
+ "@babel/preset-react": "^7.26.3",
"@hotwired/stimulus": "^3.0.0",
"@hotwired/turbo": "^7.1.1 || ^8.0",
"@symfony/stimulus-bridge": "^3.2.0",
"@symfony/ux-live-component": "file:vendor/symfony/ux-live-component/assets",
+ "@symfony/ux-react": "file:vendor/symfony/ux-react/assets",
"@symfony/ux-turbo": "file:vendor/symfony/ux-turbo/assets",
"@symfony/webpack-encore": "^4.0.0",
"core-js": "^3.23.0",
"daisyui": "^4.4.2",
+ "react": "^18.0",
+ "react-dom": "^18.0",
"regenerator-runtime": "^0.13.9",
"sass": "^1.59.3",
"sass-loader": "^13.2.0",
@@ -28,11 +32,15 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.5.2",
+ "@fortawesome/fontawesome-svg-core": "^6.7.2",
+ "@fortawesome/free-solid-svg-icons": "^6.7.2",
+ "@fortawesome/react-fontawesome": "^0.2.2",
"alpinejs": "^3.13.3",
"autoprefixer": "^10.4.14",
"bootstrap": "^5.3.3",
"postcss-loader": "^7.1.0",
"puppeteer": "^22.10.0",
+ "react-router-dom": "^7.1.5",
"sortablejs": "^1.15.2",
"tailwindcss": "^3.2.7"
}
diff --git a/symfony.lock b/symfony.lock
index 2a29c42..d0ae49a 100644
--- a/symfony.lock
+++ b/symfony.lock
@@ -279,6 +279,18 @@
"config/routes/ux_live_component.yaml"
]
},
+ "symfony/ux-react": {
+ "version": "2.23",
+ "recipe": {
+ "repo": "github.com/symfony/recipes",
+ "branch": "main",
+ "version": "2.9",
+ "ref": "e970076b31d602ae6e2106cf91a82c7e1f7ddff2"
+ },
+ "files": [
+ "assets/react/controllers/Hello.jsx"
+ ]
+ },
"symfony/ux-turbo": {
"version": "v2.18.0"
},
diff --git a/tailwind.config.js b/tailwind.config.js
index ab82141..51b2456 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,7 +1,9 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
- './templates/**/*.html.twig'
+ './templates/**/*.html.twig',
+ './assets/react/**/*.{js,jsx}',
+ './assets/**/*.{js,jsx}'
],
theme: {
extend: {},
diff --git a/templates/react/index.html.twig b/templates/react/index.html.twig
new file mode 100644
index 0000000..74bedc4
--- /dev/null
+++ b/templates/react/index.html.twig
@@ -0,0 +1,13 @@
+
+
+
+
+
+ React App
+ {{ encore_entry_link_tags('react-app') }}
+
+
+
+ {{ encore_entry_script_tags('react-app') }}
+
+
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
index 5cac666..92480d3 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -21,6 +21,7 @@ Encore
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
*/
.addEntry('app', './assets/app.js')
+ .addEntry('react-app', './assets/react/app/index.jsx')
// .addEntry('alpine', 'alpinejs')
// enables the Symfony UX Stimulus bridge (used in assets/bootstrap.js)
@@ -29,6 +30,8 @@ Encore
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
.splitEntryChunks()
+ .enableReactPreset()
+
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()