From f10ed6bf08d976e997fc4ca1ad9a46804071a644 Mon Sep 17 00:00:00 2001 From: 2ManyProjects Date: Wed, 30 Apr 2025 19:26:40 -0500 Subject: [PATCH] Blog Support, Whitelabel support better themeing --- .gitignore | 2 +- backend/src/index.js | 23 +- backend/src/middleware/adminAuth.js | 3 +- backend/src/middleware/auth.js | 1 - backend/src/middleware/upload.js | 1 - backend/src/routes/auth.js | 35 +- backend/src/routes/blog.js | 3 - backend/src/routes/blogAdmin.js | 14 +- backend/src/routes/blogCommentsAdmin.js | 8 +- backend/src/routes/couponAdmin.js | 12 +- backend/src/routes/emailTemplatesAdmin.js | 602 +++ backend/src/routes/orderAdmin.js | 219 +- backend/src/routes/productAdmin.js | 2 +- backend/src/routes/productReviews.js | 2 +- backend/src/routes/productReviewsAdmin.js | 8 +- backend/src/routes/publicSettings.js | 52 + backend/src/routes/settingsAdmin.js | 12 +- backend/src/routes/userAdmin.js | 8 +- backend/src/services/emailService.js | 278 ++ backend/src/services/notificationService.js | 72 +- db/init/09-system-settings.sql | 2 +- db/init/18-email-templates.sql | 53 + db/init/19-branding-settings.sql | 49 + fileStructure.txt | 280 +- frontend/package-lock.json | 4365 ++++++----------- frontend/package.json | 2 +- frontend/src/App.jsx | 64 +- frontend/src/components/Footer.jsx | 45 +- frontend/src/components/ImageUploader.jsx | 16 +- frontend/src/features/ui/uiSlice.js | 7 +- frontend/src/hooks/brandingHooks.js | 38 + frontend/src/hooks/emailTemplateHooks.js | 146 + frontend/src/layouts/AdminLayout.jsx | 20 +- frontend/src/layouts/AuthLayout.jsx | 33 +- frontend/src/layouts/MainLayout.jsx | 80 +- frontend/src/pages/Admin/BrandingPage.jsx | 945 ++++ .../src/pages/Admin/EmailTemplatesPage.jsx | 660 +++ frontend/src/pages/Admin/OrdersPage.jsx | 3 + frontend/src/pages/HomePage.jsx | 12 +- frontend/src/pages/ProductsPage.jsx | 6 +- frontend/src/pages/UserOrdersPage.jsx | 10 +- frontend/src/services/emailTemplateService.js | 203 + frontend/src/theme/ThemeProvider.jsx | 188 +- 43 files changed, 5109 insertions(+), 3475 deletions(-) create mode 100644 backend/src/routes/emailTemplatesAdmin.js create mode 100644 backend/src/routes/publicSettings.js create mode 100644 backend/src/services/emailService.js create mode 100644 db/init/18-email-templates.sql create mode 100644 db/init/19-branding-settings.sql create mode 100644 frontend/src/hooks/brandingHooks.js create mode 100644 frontend/src/hooks/emailTemplateHooks.js create mode 100644 frontend/src/pages/Admin/BrandingPage.jsx create mode 100644 frontend/src/pages/Admin/EmailTemplatesPage.jsx create mode 100644 frontend/src/services/emailTemplateService.js diff --git a/.gitignore b/.gitignore index b347d25..4ec5b20 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,4 @@ node_modules npm-debug.log yarn-error.log .DS_Store -public/uploads/* \ No newline at end of file +backend/public/uploads/* \ No newline at end of file diff --git a/backend/src/index.js b/backend/src/index.js index cd63ee1..a1fb07d 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -11,9 +11,8 @@ const settingsAdminRoutes = require('./routes/settingsAdmin'); const SystemSettings = require('./models/SystemSettings'); const fs = require('fs'); // services - const notificationService = require('./services/notificationService'); - +const emailService = require('./services/emailService'); // routes const stripePaymentRoutes = require('./routes/stripePayment'); @@ -32,6 +31,8 @@ const blogAdminRoutes = require('./routes/blogAdmin'); const blogCommentsAdminRoutes = require('./routes/blogCommentsAdmin'); const productReviewsRoutes = require('./routes/productReviews'); const productReviewsAdminRoutes = require('./routes/productReviewsAdmin'); +const emailTemplatesAdminRoutes = require('./routes/emailTemplatesAdmin'); +const publicSettingsRoutes = require('./routes/publicSettings'); // Create Express app const app = express(); @@ -180,6 +181,8 @@ app.get('/health', (req, res) => { res.status(200).json({ status: 'ok', message: 'API is running' }); }); +app.use('/api/settings', publicSettingsRoutes(pool, query)); + // Upload endpoints // Public upload endpoint (basic) app.post('/api/image/upload', upload.single('image'), (req, res) => { @@ -197,6 +200,21 @@ app.post('/api/image/upload', upload.single('image'), (req, res) => { }); }); +app.get('/api/public-file/:filename', (req, res) => { + const { filename } = req.params; + + // Prevent path traversal attacks + if (filename.includes('..') || filename.includes('/')) { + return res.status(400).json({ + error: true, + message: 'Invalid filename' + }); + } + + // Serve files from public uploads folder + res.sendFile(path.join(__dirname, '../public/uploads', filename)); +}); + app.use('/api/product-reviews', productReviewsRoutes(pool, query, authMiddleware(pool, query))); app.use('/api/admin/product-reviews', productReviewsAdminRoutes(pool, query, adminAuthMiddleware(pool, query))); @@ -205,6 +223,7 @@ app.use('/api/admin/coupons', couponsAdminRoutes(pool, query, adminAuthMiddlewar app.use('/api/admin/orders', ordersAdminRoutes(pool, query, adminAuthMiddleware(pool, query))); app.use('/api/admin/blog', blogAdminRoutes(pool, query, adminAuthMiddleware(pool, query))); app.use('/api/admin/blog-comments', blogCommentsAdminRoutes(pool, query, adminAuthMiddleware(pool, query))); +app.use('/api/admin/email-templates', emailTemplatesAdminRoutes(pool, query, adminAuthMiddleware(pool, query))); // Add new route // Admin-only product image upload app.post('/api/image/product', adminAuthMiddleware(pool, query), upload.single('image'), (req, res) => { diff --git a/backend/src/middleware/adminAuth.js b/backend/src/middleware/adminAuth.js index 52db624..2527697 100644 --- a/backend/src/middleware/adminAuth.js +++ b/backend/src/middleware/adminAuth.js @@ -27,7 +27,7 @@ module.exports = (pool, query) => { }); } - // Check if user is admin + if (!result.rows[0].is_admin) { return res.status(403).json({ error: true, @@ -38,7 +38,6 @@ module.exports = (pool, query) => { // Add user to request object req.user = result.rows[0]; - // Continue to next middleware/route handler next(); } catch (error) { return res.status(500).json({ diff --git a/backend/src/middleware/auth.js b/backend/src/middleware/auth.js index a009b32..2b75427 100644 --- a/backend/src/middleware/auth.js +++ b/backend/src/middleware/auth.js @@ -30,7 +30,6 @@ module.exports = (pool, query) => { // Add user to request object req.user = result.rows[0]; - // Continue to next middleware/route handler next(); } catch (error) { return res.status(500).json({ diff --git a/backend/src/middleware/upload.js b/backend/src/middleware/upload.js index 679f1a2..96c09bf 100644 --- a/backend/src/middleware/upload.js +++ b/backend/src/middleware/upload.js @@ -47,7 +47,6 @@ const fileFilter = (req, file, cb) => { } }; -// Create the multer instance const upload = multer({ storage, fileFilter, diff --git a/backend/src/routes/auth.js b/backend/src/routes/auth.js index e6eb385..a27cdac 100644 --- a/backend/src/routes/auth.js +++ b/backend/src/routes/auth.js @@ -1,21 +1,9 @@ const express = require('express'); const { v4: uuidv4 } = require('uuid'); -const nodemailer = require('nodemailer'); const config = require('../config'); +const emailService = require('../services/emailService'); const router = express.Router(); -const createTransporter = () => { - return nodemailer.createTransport({ - host: config.email.host, - port: config.email.port, - auth: { - user: config.email.user, - pass: config.email.pass - } - }); -}; - -const transporter = createTransporter(); module.exports = (pool, query) => { // Register new user @@ -95,18 +83,15 @@ module.exports = (pool, query) => { const loginLink = `${config.site.protocol}://${config.site.domain}/verify?code=${authCode}&email=${encodeURIComponent(email)}`; - - - await transporter.sendMail({ - from: 'noreply@2many.ca', - to: email, - subject: 'Your Login Code', - html: ` -

Your login code is: ${authCode}

-

This code will expire in 15 minutes.

-

Or click here to log in directly.

- ` - }); + try { + await emailService.sendLoginCodeEmail({ + to: email, + code: authCode, + loginLink: loginLink + }); + } catch (emailError) { + console.error('Failed to send login code email:', emailError); + } let retObj = { message: 'Login code sent to address: ' + email } diff --git a/backend/src/routes/blog.js b/backend/src/routes/blog.js index 038a70a..731f316 100644 --- a/backend/src/routes/blog.js +++ b/backend/src/routes/blog.js @@ -152,7 +152,6 @@ module.exports = (pool, query, authMiddleware) => { const commentThreads = []; const commentMap = {}; - // First, create a map of all comments commentsResult.rows.forEach(comment => { commentMap[comment.id] = { ...comment, @@ -173,7 +172,6 @@ module.exports = (pool, query, authMiddleware) => { } }); - // Return the post with images and comments res.json({ ...post, images: imagesResult.rows, @@ -245,7 +243,6 @@ module.exports = (pool, query, authMiddleware) => { } } - // Determine if comment needs moderation const isApproved = req.user.is_admin ? true : false; // Insert comment diff --git a/backend/src/routes/blogAdmin.js b/backend/src/routes/blogAdmin.js index f2bee22..4653e69 100644 --- a/backend/src/routes/blogAdmin.js +++ b/backend/src/routes/blogAdmin.js @@ -10,7 +10,7 @@ module.exports = (pool, query, authMiddleware) => { // Get all blog posts (admin) router.get('/', async (req, res, next) => { try { - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -47,7 +47,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { id } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -112,7 +112,6 @@ module.exports = (pool, query, authMiddleware) => { tags, featuredImagePath, status, publishNow } = req.body; - // Check if user is admin if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -135,7 +134,6 @@ module.exports = (pool, query, authMiddleware) => { remove: /[*+~.()'"!:@]/g // regex to remove characters }); - // Check if slug already exists const slugCheck = await query( 'SELECT id FROM blog_posts WHERE slug = $1', [slug] @@ -221,7 +219,7 @@ module.exports = (pool, query, authMiddleware) => { tags, featuredImagePath, status, publishNow } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -365,7 +363,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { id } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -406,7 +404,7 @@ module.exports = (pool, query, authMiddleware) => { const { postId } = req.params; const { imagePath, caption, displayOrder } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -457,7 +455,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { postId, imageId } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, diff --git a/backend/src/routes/blogCommentsAdmin.js b/backend/src/routes/blogCommentsAdmin.js index 0563310..13c77cd 100644 --- a/backend/src/routes/blogCommentsAdmin.js +++ b/backend/src/routes/blogCommentsAdmin.js @@ -8,7 +8,7 @@ module.exports = (pool, query, authMiddleware) => { // Get all pending comments (admin) router.get('/pending', async (req, res, next) => { try { - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -41,7 +41,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { postId } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -120,7 +120,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { commentId } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -169,7 +169,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { commentId } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, diff --git a/backend/src/routes/couponAdmin.js b/backend/src/routes/couponAdmin.js index 37c437e..c87d9ad 100644 --- a/backend/src/routes/couponAdmin.js +++ b/backend/src/routes/couponAdmin.js @@ -12,7 +12,7 @@ module.exports = (pool, query, authMiddleware) => { */ router.get('/', async (req, res, next) => { try { - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -68,7 +68,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { id } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -151,7 +151,7 @@ module.exports = (pool, query, authMiddleware) => { blacklistedProducts } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -343,7 +343,7 @@ module.exports = (pool, query, authMiddleware) => { blacklistedProducts } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -605,7 +605,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { id } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -648,7 +648,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { id } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, diff --git a/backend/src/routes/emailTemplatesAdmin.js b/backend/src/routes/emailTemplatesAdmin.js new file mode 100644 index 0000000..e458279 --- /dev/null +++ b/backend/src/routes/emailTemplatesAdmin.js @@ -0,0 +1,602 @@ +const express = require('express'); +const { v4: uuidv4 } = require('uuid'); +const router = express.Router(); +const nodemailer = require('nodemailer'); +const config = require('../config'); + +// Create email transporter +const createTransporter = () => { + return nodemailer.createTransport({ + host: config.email.host, + port: config.email.port, + auth: { + user: config.email.user, + pass: config.email.pass + } + }); +}; + +module.exports = (pool, query, authMiddleware) => { + // Apply authentication middleware to all routes + router.use(authMiddleware); + + /** + * Get all email templates + * GET /api/admin/email-templates + */ + router.get('/', async (req, res, next) => { + try { + + if (!req.user.is_admin) { + return res.status(403).json({ + error: true, + message: 'Admin access required' + }); + } + + // Get all settings with 'email_templates' category + const result = await query( + 'SELECT * FROM system_settings WHERE category = $1 ORDER BY key', + ['email_templates'] + ); + + // Transform settings into template objects + const templates = result.rows.map(setting => { + try { + // Parse the template data from the JSON value + const templateData = JSON.parse(setting.value); + return { + id: setting.key, + ...templateData + }; + } catch (e) { + console.error(`Failed to parse template setting: ${setting.key}`, e); + return null; + } + }).filter(Boolean); // Remove any null entries + + res.json(templates); + } catch (error) { + next(error); + } + }); + + /** + * Get templates by type + * GET /api/admin/email-templates/type/:type + */ + router.get('/type/:type', async (req, res, next) => { + try { + const { type } = req.params; + + if (!req.user.is_admin) { + return res.status(403).json({ + error: true, + message: 'Admin access required' + }); + } + + // Get all settings with 'email_templates' category + const result = await query( + 'SELECT * FROM system_settings WHERE category = $1 ORDER BY key', + ['email_templates'] + ); + + // Transform settings into template objects and filter by type + const templates = result.rows + .map(setting => { + try { + // Parse the template data from the JSON value + const templateData = JSON.parse(setting.value); + if (templateData.type === type) { + return { + id: setting.key, + ...templateData + }; + } + return null; + } catch (e) { + console.error(`Failed to parse template setting: ${setting.key}`, e); + return null; + } + }) + .filter(Boolean); // Remove any null entries + + res.json(templates); + } catch (error) { + next(error); + } + }); + + /** + * Get default template for a type + * GET /api/admin/email-templates/default/:type + */ + router.get('/default/:type', async (req, res, next) => { + try { + const { type } = req.params; + + if (!req.user.is_admin) { + return res.status(403).json({ + error: true, + message: 'Admin access required' + }); + } + + // Get all settings with 'email_templates' category + const result = await query( + 'SELECT * FROM system_settings WHERE category = $1 ORDER BY key', + ['email_templates'] + ); + + // Find the default template for the specified type + let defaultTemplate = null; + + for (const setting of result.rows) { + try { + const templateData = JSON.parse(setting.value); + if (templateData.type === type && templateData.isDefault) { + defaultTemplate = { + id: setting.key, + ...templateData + }; + break; + } + } catch (e) { + console.error(`Failed to parse template setting: ${setting.key}`, e); + } + } + + if (defaultTemplate) { + res.json(defaultTemplate); + } else { + res.status(404).json({ + error: true, + message: `No default template found for type: ${type}` + }); + } + } catch (error) { + next(error); + } + }); + + /** + * Get a single template by ID + * GET /api/admin/email-templates/:id + */ + router.get('/:id', async (req, res, next) => { + try { + const { id } = req.params; + + + if (!req.user.is_admin) { + return res.status(403).json({ + error: true, + message: 'Admin access required' + }); + } + + // Get the setting by key + const result = await query( + 'SELECT * FROM system_settings WHERE key = $1', + [id] + ); + + if (result.rows.length === 0) { + return res.status(404).json({ + error: true, + message: 'Template not found' + }); + } + + try { + // Parse the template data from the JSON value + const templateData = JSON.parse(result.rows[0].value); + res.json({ + id: result.rows[0].key, + ...templateData + }); + } catch (e) { + console.error(`Failed to parse template setting: ${id}`, e); + return res.status(500).json({ + error: true, + message: 'Failed to parse template data' + }); + } + } catch (error) { + next(error); + } + }); + + /** + * Create a new template + * POST /api/admin/email-templates + */ + router.post('/', async (req, res, next) => { + try { + const { name, type, subject, content, isDefault } = req.body; + + + if (!req.user.is_admin) { + return res.status(403).json({ + error: true, + message: 'Admin access required' + }); + } + + // Validate required fields + if (!name || !type || !subject || !content) { + return res.status(400).json({ + error: true, + message: 'Name, type, subject, and content are required' + }); + } + + // Begin transaction for potential default template updates + const client = await pool.connect(); + + try { + await client.query('BEGIN'); + + // Generate a unique key for the setting + const templateKey = `email_template_${Date.now()}`; + + // Create the template object + const templateData = { + name, + type, + subject, + content, + isDefault: isDefault || false, + createdAt: new Date().toISOString() + }; + + // If this template should be the default, unset any existing defaults + if (templateData.isDefault) { + // Get all settings with 'email_templates' category + const existingTemplates = await client.query( + 'SELECT * FROM system_settings WHERE category = $1', + ['email_templates'] + ); + + // Find and update any existing default templates of the same type + for (const setting of existingTemplates.rows) { + try { + const existingData = JSON.parse(setting.value); + if (existingData.type === type && existingData.isDefault) { + existingData.isDefault = false; + existingData.updatedAt = new Date().toISOString(); + + await client.query( + 'UPDATE system_settings SET value = $1, updated_at = NOW() WHERE key = $2', + [JSON.stringify(existingData), setting.key] + ); + } + } catch (e) { + console.error(`Failed to parse template setting: ${setting.key}`, e); + } + } + } + + // Insert the new template + await client.query( + 'INSERT INTO system_settings (key, value, category) VALUES ($1, $2, $3)', + [templateKey, JSON.stringify(templateData), 'email_templates'] + ); + + await client.query('COMMIT'); + + res.status(201).json({ + id: templateKey, + ...templateData + }); + } catch (error) { + await client.query('ROLLBACK'); + throw error; + } finally { + client.release(); + } + } catch (error) { + next(error); + } + }); + + /** + * Update a template + * PUT /api/admin/email-templates/:id + */ + router.put('/:id', async (req, res, next) => { + try { + const { id } = req.params; + const { name, type, subject, content, isDefault } = req.body; + + + if (!req.user.is_admin) { + return res.status(403).json({ + error: true, + message: 'Admin access required' + }); + } + + // Validate required fields + if (!name || !type || !subject || !content) { + return res.status(400).json({ + error: true, + message: 'Name, type, subject, and content are required' + }); + } + + // Begin transaction for potential default template updates + const client = await pool.connect(); + + try { + await client.query('BEGIN'); + + // Check if the template exists + const templateCheck = await client.query( + 'SELECT * FROM system_settings WHERE key = $1', + [id] + ); + + if (templateCheck.rows.length === 0) { + await client.query('ROLLBACK'); + return res.status(404).json({ + error: true, + message: 'Template not found' + }); + } + + // Parse the existing template data + let existingData; + try { + existingData = JSON.parse(templateCheck.rows[0].value); + } catch (e) { + await client.query('ROLLBACK'); + return res.status(500).json({ + error: true, + message: 'Failed to parse existing template data' + }); + } + + // Create the updated template object + const templateData = { + name, + type, + subject, + content, + isDefault: isDefault !== undefined ? isDefault : existingData.isDefault, + createdAt: existingData.createdAt, + updatedAt: new Date().toISOString() + }; + + // If this template should be the default, unset any existing defaults + if (templateData.isDefault && (!existingData.isDefault || existingData.type !== type)) { + // Get all settings with 'email_templates' category + const existingTemplates = await client.query( + 'SELECT * FROM system_settings WHERE category = $1', + ['email_templates'] + ); + + // Find and update any existing default templates of the same type + for (const setting of existingTemplates.rows) { + if (setting.key === id) continue; // Skip the current template + + try { + const otherData = JSON.parse(setting.value); + if (otherData.type === type && otherData.isDefault) { + otherData.isDefault = false; + otherData.updatedAt = new Date().toISOString(); + + await client.query( + 'UPDATE system_settings SET value = $1, updated_at = NOW() WHERE key = $2', + [JSON.stringify(otherData), setting.key] + ); + } + } catch (e) { + console.error(`Failed to parse template setting: ${setting.key}`, e); + } + } + } + + // Update the template + await client.query( + 'UPDATE system_settings SET value = $1, updated_at = NOW() WHERE key = $2', + [JSON.stringify(templateData), id] + ); + + await client.query('COMMIT'); + + res.json({ + id, + ...templateData + }); + } catch (error) { + await client.query('ROLLBACK'); + throw error; + } finally { + client.release(); + } + } catch (error) { + next(error); + } + }); + + /** + * Delete a template + * DELETE /api/admin/email-templates/:id + */ + router.delete('/:id', async (req, res, next) => { + try { + const { id } = req.params; + + + if (!req.user.is_admin) { + return res.status(403).json({ + error: true, + message: 'Admin access required' + }); + } + + // Check if the template exists and is not a default template + const templateCheck = await query( + 'SELECT * FROM system_settings WHERE key = $1', + [id] + ); + + if (templateCheck.rows.length === 0) { + return res.status(404).json({ + error: true, + message: 'Template not found' + }); + } + + // Parse the template data to check if it's a default template + try { + const templateData = JSON.parse(templateCheck.rows[0].value); + if (templateData.isDefault) { + return res.status(400).json({ + error: true, + message: 'Cannot delete a default template. Please set another template as default first.' + }); + } + } catch (e) { + console.error(`Failed to parse template setting: ${id}`, e); + } + + // Delete the template + await query( + 'DELETE FROM system_settings WHERE key = $1', + [id] + ); + + res.json({ + success: true, + message: 'Template deleted successfully' + }); + } catch (error) { + next(error); + } + }); + + /** + * Send a test email using a template + * POST /api/admin/email-templates/:id/test + */ + router.post('/:id/test', async (req, res, next) => { + try { + const { id } = req.params; + const { email, variables } = req.body; + + + if (!req.user.is_admin) { + return res.status(403).json({ + error: true, + message: 'Admin access required' + }); + } + + // Validate email address + if (!email) { + return res.status(400).json({ + error: true, + message: 'Email address is required' + }); + } + + // Check if the template exists + const templateCheck = await query( + 'SELECT * FROM system_settings WHERE key = $1', + [id] + ); + + if (templateCheck.rows.length === 0) { + return res.status(404).json({ + error: true, + message: 'Template not found' + }); + } + + // Parse the template data + let templateData; + try { + templateData = JSON.parse(templateCheck.rows[0].value); + } catch (e) { + console.error(`Failed to parse template setting: ${id}`, e); + return res.status(500).json({ + error: true, + message: 'Failed to parse template data' + }); + } + + // Replace variables in template + let emailContent = templateData.content; + let emailSubject = templateData.subject; + + if (variables) { + for (const [key, value] of Object.entries(variables)) { + const placeholder = `{{${key}}}`; + emailContent = emailContent.replace(new RegExp(placeholder, 'g'), value); + emailSubject = emailSubject.replace(new RegExp(placeholder, 'g'), value); + } + } + + // Create a transporter + const transporter = createTransporter(); + + // Send the test email + await transporter.sendMail({ + from: config.email.reply, + to: email, + subject: `[TEST] ${emailSubject}`, + html: emailContent + }); + + res.json({ + success: true, + message: `Test email sent to ${email}` + }); + } catch (error) { + next(error); + } + }); + + /** + * Utility function to get a template by type + * @param {string} type - Template type + * @returns {Promise} Template object or null if not found + */ + async function getTemplateByType(type) { + try { + // Get all settings with 'email_templates' category + const result = await query( + 'SELECT * FROM system_settings WHERE category = $1', + ['email_templates'] + ); + + // Find the default template for the specified type + let defaultTemplate = null; + + for (const setting of result.rows) { + try { + const templateData = JSON.parse(setting.value); + if (templateData.type === type && templateData.isDefault) { + defaultTemplate = { + id: setting.key, + ...templateData + }; + break; + } + } catch (e) { + console.error(`Failed to parse template setting: ${setting.key}`, e); + } + } + + return defaultTemplate; + } catch (error) { + console.error('Error getting template by type:', error); + return null; + } + } + + return router; +}; \ No newline at end of file diff --git a/backend/src/routes/orderAdmin.js b/backend/src/routes/orderAdmin.js index 0d9214c..9bd5b2d 100644 --- a/backend/src/routes/orderAdmin.js +++ b/backend/src/routes/orderAdmin.js @@ -1,19 +1,6 @@ const express = require('express'); const router = express.Router(); -const nodemailer = require('nodemailer'); -const config = require('../config'); - -// Helper function to create email transporter -const createTransporter = () => { - return nodemailer.createTransport({ - host: config.email.host, - port: config.email.port, - auth: { - user: config.email.user, - pass: config.email.pass - } - }); -}; +const emailService = require('../services/emailService'); // Import email service module.exports = (pool, query, authMiddleware) => { // Apply authentication middleware to all routes @@ -22,7 +9,7 @@ module.exports = (pool, query, authMiddleware) => { // Get all orders (admin only) router.get('/', async (req, res, next) => { try { - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -52,7 +39,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { id } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -124,7 +111,7 @@ module.exports = (pool, query, authMiddleware) => { const { id } = req.params; const { status } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -171,7 +158,7 @@ module.exports = (pool, query, authMiddleware) => { const { id } = req.params; const { status, shippingData, sendNotification } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -240,12 +227,66 @@ module.exports = (pool, query, authMiddleware) => { const orderItems = itemsResult.rows; - // Send email notification - await sendShippingNotification( - order, - orderItems, - shippingData - ); + // Generate items HTML table + const itemsHtml = orderItems.map(item => ` + + ${item.product_name} + ${item.quantity} + $${parseFloat(item.price_at_purchase).toFixed(2)} + $${(parseFloat(item.price_at_purchase) * item.quantity).toFixed(2)} + + `).join(''); + + // Generate carrier tracking link + let trackingLink = '#'; + const shipper = shippingData.shipper || ''; + const trackingNumber = shippingData.trackingNumber; + + if (trackingNumber) { + // Match exactly with the values from the dropdown + switch(shipper) { + case 'USPS': + trackingLink = `https://tools.usps.com/go/TrackConfirmAction?tLabels=${trackingNumber}`; + break; + case 'UPS': + trackingLink = `https://www.ups.com/track?tracknum=${trackingNumber}`; + break; + case 'FedEx': + trackingLink = `https://www.fedex.com/apps/fedextrack/?tracknumbers=${trackingNumber}`; + break; + case 'DHL': + trackingLink = `https://www.dhl.com/global-en/home/tracking.html?tracking-id=${trackingNumber}`; + break; + case 'Canada Post': + trackingLink = `https://www.canadapost-postescanada.ca/track-reperage/en#/search?searchFor=${trackingNumber}`; + break; + case 'Purolator': + trackingLink = `https://www.purolator.com/en/shipping/track/tracking-number/${trackingNumber}`; + break; + default: + // For "other" or any carrier not in our list + // Just make the tracking number text without a link + trackingLink = '#'; + break; + } + } + + // Format shipping date + const shippedDate = new Date(shippingData.shippedDate || new Date()).toLocaleDateString(); + + // Send email notification using template system + await emailService.sendShippingNotification({ + to: order.email, + first_name: order.first_name, + order_id: order.id.substring(0, 8), + tracking_number: shippingData.trackingNumber || 'N/A', + carrier: shippingData.shipper || 'Standard Shipping', + tracking_link: trackingLink, + shipped_date: shippedDate, + estimated_delivery: shippingData.estimatedDelivery || 'N/A', + items_html: itemsHtml, + customer_message: shippingData.customerMessage || '' + }); // Log the notification in the database await client.query(` @@ -272,135 +313,5 @@ module.exports = (pool, query, authMiddleware) => { } }); - // Helper function to send shipping notification email - async function sendShippingNotification(order, orderItems, shippingData) { - try { - const transporter = createTransporter(); - - // Calculate order total - const orderTotal = orderItems.reduce((sum, item) => { - return sum + (parseFloat(item.price_at_purchase) * item.quantity); - }, 0); - - // Format shipping date - const shippedDate = new Date(shippingData.shippedDate || new Date()).toLocaleDateString(); - - // Generate items HTML table - const itemsHtml = orderItems.map(item => ` - - ${item.product_name} - ${item.quantity} - $${parseFloat(item.price_at_purchase).toFixed(2)} - $${(parseFloat(item.price_at_purchase) * item.quantity).toFixed(2)} - - `).join(''); - - // Generate carrier tracking link - let trackingLink = '#'; - const shipper = shippingData.shipper || ''; - const trackingNumber = shippingData.trackingNumber; - - if (trackingNumber) { - // Match exactly with the values from the dropdown - switch(shipper) { - case 'USPS': - trackingLink = `https://tools.usps.com/go/TrackConfirmAction?tLabels=${trackingNumber}`; - break; - case 'UPS': - trackingLink = `https://www.ups.com/track?tracknum=${trackingNumber}`; - break; - case 'FedEx': - trackingLink = `https://www.fedex.com/apps/fedextrack/?tracknumbers=${trackingNumber}`; - break; - case 'DHL': - trackingLink = `https://www.dhl.com/global-en/home/tracking.html?tracking-id=${trackingNumber}`; - break; - case 'Canada Post': - trackingLink = `https://www.canadapost-postescanada.ca/track-reperage/en#/search?searchFor=${trackingNumber}`; - break; - case 'Purolator': - trackingLink = `https://www.purolator.com/en/shipping/track/tracking-number/${trackingNumber}`; - break; - default: - // For "other" or any carrier not in our list - // Just make the tracking number text without a link - trackingLink = '#'; - break; - } - } - - // Build email HTML - const emailHtml = ` -
-
-

Your Order Has Shipped!

-

Order #${order.id.substring(0, 8)}

-
- -
-

Hello ${order.first_name},

- -

Good news! Your order has been shipped and is on its way to you.

- - ${shippingData.customerMessage ? `

Message from our team: ${shippingData.customerMessage}

` : ''} - -
-

Shipping Details

-

Carrier: ${shippingData.shipper || 'Standard Shipping'}

-

Tracking Number: ${shippingData.trackingNumber}

-

Shipped On: ${shippedDate}

- ${shippingData.estimatedDelivery ? `

Estimated Delivery: ${shippingData.estimatedDelivery}

` : ''} -
- -
-

Order Summary

- - - - - - - - - - - ${itemsHtml} - - - - - - - -
ItemQtyPriceTotal
Total:$${orderTotal.toFixed(2)}
-
- -
-

Thank you for your purchase! If you have any questions, please contact our customer service.

-
-
- -
-

© ${new Date().getFullYear()} Rocks, Bones & Sticks. All rights reserved.

-
-
- `; - - // Send the email - await transporter.sendMail({ - from: config.email.reply, - to: order.email, - subject: `Your Order #${order.id.substring(0, 8)} Has Shipped!`, - html: emailHtml - }); - - console.log(`Shipping notification email sent to ${order.email}`); - return true; - } catch (error) { - console.error('Error sending shipping notification:', error); - throw error; - } - } - return router; }; \ No newline at end of file diff --git a/backend/src/routes/productAdmin.js b/backend/src/routes/productAdmin.js index 87b6a69..fc79556 100644 --- a/backend/src/routes/productAdmin.js +++ b/backend/src/routes/productAdmin.js @@ -157,7 +157,7 @@ module.exports = (pool, query, authMiddleware) => { const { id } = req.params; const { enabled, email, threshold } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, diff --git a/backend/src/routes/productReviews.js b/backend/src/routes/productReviews.js index c58fae2..6f63b85 100644 --- a/backend/src/routes/productReviews.js +++ b/backend/src/routes/productReviews.js @@ -120,7 +120,7 @@ module.exports = (pool, query, authMiddleware) => { const isVerifiedPurchase = purchaseCheck.rows.length > 0; - // Check if user is admin + const isAdmin = req.user.is_admin || false; // Only allow reviews if user has purchased the product or is an admin diff --git a/backend/src/routes/productReviewsAdmin.js b/backend/src/routes/productReviewsAdmin.js index 59cf253..ca4d13b 100644 --- a/backend/src/routes/productReviewsAdmin.js +++ b/backend/src/routes/productReviewsAdmin.js @@ -8,7 +8,7 @@ module.exports = (pool, query, authMiddleware) => { // Get all pending reviews (admin) router.get('/pending', async (req, res, next) => { try { - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -41,7 +41,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { productId } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -120,7 +120,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { reviewId } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -169,7 +169,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { reviewId } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, diff --git a/backend/src/routes/publicSettings.js b/backend/src/routes/publicSettings.js new file mode 100644 index 0000000..3126b85 --- /dev/null +++ b/backend/src/routes/publicSettings.js @@ -0,0 +1,52 @@ +const express = require('express'); +const router = express.Router(); +const SystemSettings = require('../models/SystemSettings'); + +module.exports = (pool, query) => { + /** + * Get public branding settings + * GET /api/settings/branding + */ + router.get('/branding', async (req, res, next) => { + try { + // Get all settings with 'branding' category + const settings = await SystemSettings.getSettingsByCategory(pool, query, 'branding'); + + // Convert array of settings to an object for easier client-side use + const brandingSettings = {}; + settings.forEach(setting => { + brandingSettings[setting.key] = setting.value; + }); + + res.json(brandingSettings); + } catch (error) { + next(error); + } + }); + + /** + * Get basic public settings (for meta tags, favicon, etc.) + * GET /api/settings/meta + */ + router.get('/meta', async (req, res, next) => { + try { + // Get relevant settings + const siteNameSetting = await SystemSettings.getSetting(pool, query, 'site_name'); + const siteDescriptionSetting = await SystemSettings.getSetting(pool, query, 'site_description'); + const faviconSetting = await SystemSettings.getSetting(pool, query, 'favicon_url'); + + // Create response object + const metaSettings = { + siteName: siteNameSetting?.value || 'Rocks, Bones & Sticks', + siteDescription: siteDescriptionSetting?.value || '', + faviconUrl: faviconSetting?.value || '' + }; + + res.json(metaSettings); + } catch (error) { + next(error); + } + }); + + return router; +}; \ No newline at end of file diff --git a/backend/src/routes/settingsAdmin.js b/backend/src/routes/settingsAdmin.js index 8205ffb..32d4951 100644 --- a/backend/src/routes/settingsAdmin.js +++ b/backend/src/routes/settingsAdmin.js @@ -14,7 +14,7 @@ module.exports = (pool, query, authMiddleware) => { */ router.get('/', async (req, res, next) => { try { - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -46,7 +46,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { category } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -68,7 +68,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { key } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -99,7 +99,7 @@ module.exports = (pool, query, authMiddleware) => { const { key } = req.params; const { value, category } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -138,7 +138,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { settings } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -189,7 +189,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { key } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, diff --git a/backend/src/routes/userAdmin.js b/backend/src/routes/userAdmin.js index 3555629..3735d5b 100644 --- a/backend/src/routes/userAdmin.js +++ b/backend/src/routes/userAdmin.js @@ -19,7 +19,7 @@ module.exports = (pool, query, authMiddleware) => { // Get all users router.get('/', async (req, res, next) => { try { - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -53,7 +53,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { id } = req.params; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -95,7 +95,7 @@ module.exports = (pool, query, authMiddleware) => { const { id } = req.params; const { is_disabled, internal_notes, is_admin} = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, @@ -143,7 +143,7 @@ module.exports = (pool, query, authMiddleware) => { try { const { to, name, subject, message } = req.body; - // Check if user is admin + if (!req.user.is_admin) { return res.status(403).json({ error: true, diff --git a/backend/src/services/emailService.js b/backend/src/services/emailService.js new file mode 100644 index 0000000..559e471 --- /dev/null +++ b/backend/src/services/emailService.js @@ -0,0 +1,278 @@ +const nodemailer = require('nodemailer'); +const config = require('../config'); +const { query, pool } = require('../db'); + +/** + * Service for sending emails with templates + */ +const emailService = { + /** + * Create email transporter + * @returns {Object} Configured nodemailer transporter + */ + createTransporter() { + return nodemailer.createTransport({ + host: config.email.host, + port: config.email.port, + auth: { + user: config.email.user, + pass: config.email.pass + } + }); + }, + + /** + * Get a template by type, preferring the default one + * @param {string} type - Template type + * @returns {Promise} Template object or null if not found + */ + async getTemplateByType(type) { + try { + // Get all settings with 'email_templates' category + const result = await query( + 'SELECT * FROM system_settings WHERE category = $1', + ['email_templates'] + ); + + // Find the default template for the specified type + let defaultTemplate = null; + let fallbackTemplate = null; + + for (const setting of result.rows) { + try { + console.log(setting.value, typeof setting.value) + const templateData = JSON.parse(setting.value); + + if (templateData.type === type) { + if (templateData.isDefault) { + defaultTemplate = { + id: setting.key, + ...templateData + }; + break; // Found the default template + } else if (!fallbackTemplate) { + // Keep a fallback template in case no default is found + fallbackTemplate = { + id: setting.key, + ...templateData + }; + } + } + } catch (e) { + console.error(`Failed to parse template setting: ${setting.key}`, e); + } + } + + // Return default template if found, otherwise return fallback or null + return defaultTemplate || fallbackTemplate || null; + } catch (error) { + console.error('Error getting template by type:', error); + return null; + } + }, + + /** + * Replace template variables with actual values + * @param {string} content - Template content + * @param {Object} variables - Variable values + * @returns {string} Processed content + */ + replaceVariables(content, variables) { + let processedContent = content; + + if (variables) { + for (const [key, value] of Object.entries(variables)) { + const placeholder = `{{${key}}}`; + const regex = new RegExp(placeholder, 'g'); + processedContent = processedContent.replace(regex, value || ''); + } + } + + return processedContent; + }, + + /** + * Send an email using a template + * @param {Object} options - Email options + * @param {string} options.to - Recipient email address + * @param {string} options.templateType - Template type + * @param {Object} options.variables - Template variables + * @param {string} [options.from] - Sender email (optional, defaults to config) + * @param {string} [options.subject] - Custom subject (optional, defaults to template subject) + * @param {string} [options.cc] - CC recipients (optional) + * @param {string} [options.bcc] - BCC recipients (optional) + * @returns {Promise} Success status + */ + async sendTemplatedEmail(options) { + try { + const { to, templateType, variables, from, subject, cc, bcc } = options; + + // Get template + const template = await this.getTemplateByType(templateType); + + if (!template) { + throw new Error(`No template found for type: ${templateType}`); + } + + // Replace variables in content and subject + const emailContent = this.replaceVariables(template.content, variables); + const emailSubject = subject || this.replaceVariables(template.subject, variables); + + // Create transporter + const transporter = this.createTransporter(); + + // Send email + const result = await transporter.sendMail({ + from: from || config.email.reply, + to, + cc, + bcc, + subject: emailSubject, + html: emailContent + }); + + console.log(`Email sent: ${result.messageId}`); + return true; + } catch (error) { + console.error('Error sending templated email:', error); + throw error; + } + }, + + /** + * Send a login code email + * @param {Object} options - Options + * @param {string} options.to - Recipient email + * @param {string} options.code - Login verification code + * @param {string} options.loginLink - Direct login link + * @returns {Promise} Success status + */ + async sendLoginCodeEmail(options) { + const { to, code, loginLink } = options; + + return this.sendTemplatedEmail({ + to, + templateType: 'login_code', + variables: { + code, + loginLink, + email: to + } + }); + }, + + /** + * Send a shipping notification email + * @param {Object} options - Options + * @param {string} options.to - Recipient email + * @param {string} options.first_name - Customer's first name + * @param {string} options.order_id - Order ID + * @param {string} options.tracking_number - Tracking number + * @param {string} options.carrier - Shipping carrier + * @param {string} options.tracking_link - Tracking link + * @param {string} options.shipped_date - Ship date + * @param {string} options.estimated_delivery - Estimated delivery + * @param {string} options.items_html - Order items HTML table + * @param {string} options.customer_message - Custom message + * @returns {Promise} Success status + */ + async sendShippingNotification(options) { + return this.sendTemplatedEmail({ + to: options.to, + templateType: 'shipping_notification', + variables: options + }); + }, + + /** + * Send an order confirmation email + * @param {Object} options - Options + * @param {string} options.to - Recipient email + * @param {string} options.first_name - Customer's first name + * @param {string} options.order_id - Order ID + * @param {string} options.order_date - Order date + * @param {string} options.order_total - Order total + * @param {string} options.shipping_address - Shipping address + * @param {string} options.items_html - Order items HTML table + * @returns {Promise} Success status + */ + async sendOrderConfirmation(options) { + return this.sendTemplatedEmail({ + to: options.to, + templateType: 'order_confirmation', + variables: options + }); + }, + + /** + * Send a low stock alert email + * @param {Object} options - Options + * @param {string} options.to - Recipient email + * @param {string} options.product_name - Product name + * @param {string} options.current_stock - Current stock level + * @param {string} options.threshold - Stock threshold + * @returns {Promise} Success status + */ + async sendLowStockAlert(options) { + return this.sendTemplatedEmail({ + to: options.to, + templateType: 'low_stock_alert', + variables: options + }); + }, + + /** + * Send a welcome email + * @param {Object} options - Options + * @param {string} options.to - Recipient email + * @param {string} options.first_name - User's first name + * @returns {Promise} Success status + */ + async sendWelcomeEmail(options) { + return this.sendTemplatedEmail({ + to: options.to, + templateType: 'welcome_email', + variables: { + first_name: options.first_name, + email: options.to + } + }); + }, + + /** + * Log an email in the database + * @param {Object} emailData - Email data to log + * @param {string} emailData.recipient - Recipient email + * @param {string} emailData.subject - Email subject + * @param {string} emailData.sent_by - User ID who sent the email + * @param {string} [emailData.template_id] - Template ID used + * @param {string} [emailData.template_type] - Template type used + * @returns {Promise} Log entry + */ + async logEmail(emailData) { + try { + const result = await query( + `INSERT INTO email_logs + (recipient, subject, sent_by, template_id, template_type, status) + VALUES ($1, $2, $3, $4, $5, $6) + RETURNING *`, + [ + emailData.recipient, + emailData.subject, + emailData.sent_by, + emailData.template_id || null, + emailData.template_type || null, + 'sent' + ] + ); + + return result.rows[0]; + } catch (error) { + console.error('Error logging email:', error); + // Don't throw error, just log it + return null; + } + } +}; + +module.exports = emailService; \ No newline at end of file diff --git a/backend/src/services/notificationService.js b/backend/src/services/notificationService.js index d2685aa..38e793b 100644 --- a/backend/src/services/notificationService.js +++ b/backend/src/services/notificationService.js @@ -1,27 +1,10 @@ -// Create a new file: src/services/notificationService.js - -const nodemailer = require('nodemailer'); const config = require('../config'); +const emailService = require('./emailService'); /** * Service for handling notifications including stock alerts */ const notificationService = { - /** - * Create email transporter - * @returns {Object} Configured nodemailer transporter - */ - createTransporter() { - return nodemailer.createTransport({ - host: config.email.host, - port: config.email.port, - auth: { - user: config.email.user, - pass: config.email.pass - } - }); - }, - /** * Process pending low stock notifications * @param {Object} pool - Database connection pool @@ -77,21 +60,18 @@ const notificationService = { return 0; } - // Initialize email transporter - const transporter = this.createTransporter(); - // Send notifications for each low stock product for (const product of lowStockProducts.rows) { console.log("LOW STOCK ON: ", JSON.stringify(product, null, 4)) const notification = product.stock_notification; try { - // Send email notification - await transporter.sendMail({ - from: config.email.reply, + // Send email notification using template + await emailService.sendLowStockAlert({ to: notification.email, - subject: `Low Stock Alert: ${product.name}`, - html: this.generateLowStockEmailTemplate(product) + product_name: product.name, + current_stock: product.stock_quantity.toString(), + threshold: notification.threshold.toString() }); // Mark one notification as processed @@ -129,46 +109,6 @@ const notificationService = { } finally { client.release(); } - }, - - /** - * Generate email template for low stock notification - * @param {Object} product - Product with low stock - * @returns {string} HTML email template - */ - generateLowStockEmailTemplate(product) { - const stockNotification = product.stock_notification; - const threshold = stockNotification.threshold || 0; - - return ` -
-
-

Low Stock Alert

-
- -
-

Hello,

- -

This is an automated notification to inform you that the following product is running low on stock:

- -
-

${product.name}

-

Current Stock: ${product.stock_quantity}

-

Threshold: ${threshold}

-
- -

You might want to restock this item soon to avoid running out of inventory.

- -
-

This is an automated notification. You received this because you set up stock notifications for this product.

-
-
- -
-

© ${new Date().getFullYear()} Rocks, Bones & Sticks. All rights reserved.

-
-
- `; } }; diff --git a/db/init/09-system-settings.sql b/db/init/09-system-settings.sql index 2db5671..a2f758f 100644 --- a/db/init/09-system-settings.sql +++ b/db/init/09-system-settings.sql @@ -27,7 +27,7 @@ VALUES ('smtp_from_name', NULL, 'email'), -- Site Settings - ('site_name', NULL, 'site'), + -- ('site_name', NULL, 'site'), ('site_domain', NULL, 'site'), ('site_api_domain', NULL, 'site'), ('site_protocol', NULL, 'site'), diff --git a/db/init/18-email-templates.sql b/db/init/18-email-templates.sql new file mode 100644 index 0000000..0c88053 --- /dev/null +++ b/db/init/18-email-templates.sql @@ -0,0 +1,53 @@ +-- Add email_templates category in system_settings if needed +INSERT INTO system_settings (key, value, category) VALUES + ('email_templates_enabled', 'true', 'email') +ON CONFLICT (key) DO NOTHING; + +-- Add email_logs table for template logs if it doesn't exist +ALTER TABLE email_logs ADD COLUMN IF NOT EXISTS template_id VARCHAR(255); +ALTER TABLE email_logs ADD COLUMN IF NOT EXISTS template_type VARCHAR(50); + +-- Create default login code template +INSERT INTO system_settings (key, value, category) +VALUES ( + 'email_template_login_code_default', + '{"name":"Login Code Template","type":"login_code","subject":"Your Login Code","content":"

Your login code is: {{code}}

This code will expire in 15 minutes.

Or click here to log in directly.

","isDefault":true,"createdAt":"2025-04-29T00:00:00.000Z"}', + 'email_templates' +) +ON CONFLICT (key) DO NOTHING; + +-- Create default shipping notification template +INSERT INTO system_settings (key, value, category) +VALUES ( + 'email_template_shipping_notification_default', + '{"name":"Shipping Notification Template","type":"shipping_notification","subject":"Your Order Has Shipped!","content":"

Your Order Has Shipped!

Order #{{order_id}}

Hello {{first_name}},

Good news! Your order has been shipped and is on its way to you.

Shipping Details

Carrier: {{carrier}}

Tracking Number: {{tracking_number}}

Shipped On: {{shipped_date}}

Estimated Delivery: {{estimated_delivery}}

Order Summary

{{items_html}}
ItemQtyPriceTotal

Thank you for your purchase!

© 2025 Rocks, Bones & Sticks. All rights reserved.

","isDefault":true,"createdAt":"2025-04-29T00:00:00.000Z"}', + 'email_templates' +) +ON CONFLICT (key) DO NOTHING; + +-- Create default order confirmation template +INSERT INTO system_settings (key, value, category) +VALUES ( + 'email_template_order_confirmation_default', + '{"name":"Order Confirmation Template","type":"order_confirmation","subject":"Order Confirmation","content":"

Order Confirmation

Order #{{order_id}}

Hello {{first_name}},

Thank you for your order! We are processing it now and will send you another email when it ships.

Order Details

Order Date: {{order_date}}

Order Total: {{order_total}}

Shipping To: {{shipping_address}}

Order Summary

{{items_html}}
ItemQtyPriceTotal

© 2025 Rocks, Bones & Sticks. All rights reserved.

","isDefault":true,"createdAt":"2025-04-29T00:00:00.000Z"}', + 'email_templates' +) +ON CONFLICT (key) DO NOTHING; + +-- Create default low stock alert template +INSERT INTO system_settings (key, value, category) +VALUES ( + 'email_template_low_stock_alert_default', + '{"name":"Low Stock Alert Template","type":"low_stock_alert","subject":"Low Stock Alert: {{product_name}}","content":"

Low Stock Alert

Hello,

This is an automated notification to inform you that the following product is running low on stock:

{{product_name}}

Current Stock: {{current_stock}}

Threshold: {{threshold}}

You might want to restock this item soon to avoid running out of inventory.

© 2025 Rocks, Bones & Sticks. All rights reserved.

","isDefault":true,"createdAt":"2025-04-29T00:00:00.000Z"}', + 'email_templates' +) +ON CONFLICT (key) DO NOTHING; + +-- Create default welcome email template +INSERT INTO system_settings (key, value, category) +VALUES ( + 'email_template_welcome_email_default', + '{"name":"Welcome Email Template","type":"welcome_email","subject":"Welcome to Rocks, Bones & Sticks!","content":"

Welcome to Rocks, Bones & Sticks!

Hello {{first_name}},

Thank you for creating an account with us. We are excited to have you join our community of natural curiosity enthusiasts!

As a member, you will enjoy:

  • Access to our unique collection of natural specimens
  • Special offers and promotions
  • Early access to new items

Start exploring our collections today and discover the beauty of nature!

© 2025 Rocks, Bones & Sticks. All rights reserved.

","isDefault":true,"createdAt":"2025-04-29T00:00:00.000Z"}', + 'email_templates' +) +ON CONFLICT (key) DO NOTHING; \ No newline at end of file diff --git a/db/init/19-branding-settings.sql b/db/init/19-branding-settings.sql new file mode 100644 index 0000000..65525e7 --- /dev/null +++ b/db/init/19-branding-settings.sql @@ -0,0 +1,49 @@ +-- Add branding category to system_settings if needed +INSERT INTO system_settings (key, value, category) VALUES + ('branding_enabled', 'true', 'branding') +ON CONFLICT (key) DO NOTHING; + +-- Create default branding settings +INSERT INTO system_settings (key, value, category) +VALUES + ('site_name', 'Rocks, Bones & Sticks', 'branding'), + + + ('site_main_page_title', 'Discover Natural Wonders', 'branding'), + ('site_main_page_subtitle', 'Unique rocks, bones, and sticks from around my backyard', 'branding'), + ('site_main_newsletter_desc', 'Subscribe to our newsletter for updates on new items and promotions', 'branding'), + ('site_main_bottom_sting', 'Ready to explore more?', 'branding'), + ('site_description', 'Your premier source for natural curiosities and unique specimens', 'branding'), + ('site_quicklinks_title', 'Quick Links', 'branding'), + ('site_connect', 'Connect With Us', 'branding'), + + ('blog_title', 'Our Blog', 'branding'), + ('blog_desc', 'Discover insights about our natural collections, sourcing adventures, and unique specimens', 'branding'), + ('blog_no_content_title', 'No blog posts found', 'branding'), + ('blog_no_content_subtitle', 'Check back soon for new content', 'branding'), + ('blog_search', 'Search blog posts', 'branding'), + + ('cart_empty', 'Your Cart is Empty', 'branding'), + ('cart_empty_subtitle', 'Looks like you have not added any items to your cart yet.', 'branding'), + + ('product_title', 'Products', 'branding'), + + ('orders_title', 'My Orders', 'branding'), + ('orders_empty', 'You have not placed any orders yet.', 'branding'), + + + ('default_mode', 'light', 'branding'), + ('copyright_text', '© 2025 Rocks, Bones & Sticks. All rights reserved.', 'branding'), + ('light_primary_color', '#7e57c2', 'branding'), + ('light_secondary_color', '#ffb300', 'branding'), + ('light_background_color', '#f5f5f5', 'branding'), + ('light_surface_color', '#ffffff', 'branding'), + ('light_text_color', '#000000', 'branding'), + ('dark_primary_color', '#9575cd', 'branding'), + ('dark_secondary_color', '#ffd54f', 'branding'), + ('dark_background_color', '#212121', 'branding'), + ('dark_surface_color', '#424242', 'branding'), + ('dark_text_color', '#ffffff', 'branding'), + ('logo_url', '', 'branding'), + ('favicon_url', '', 'branding') +ON CONFLICT (key) DO NOTHING; \ No newline at end of file diff --git a/fileStructure.txt b/fileStructure.txt index 3562cf7..64f859a 100644 --- a/fileStructure.txt +++ b/fileStructure.txt @@ -1,146 +1,180 @@ -project/ +Rock/ +├── git/ ├── frontend/ +│ ├── node_modules/ │ ├── src/ -│ │ ├── utils/ -│ │ │ └── imageUtils.js (4/24/2025) -│ │ ├── theme/ -│ │ │ ├── ThemeProvider.jsx (4/24/2025) -│ │ │ └── index.js (4/24/2025) -│ │ ├── store/ -│ │ │ └── index.js (4/24/2025) -│ │ ├── services/ -│ │ │ ├── settingsAdminService.js (4/25/2025) -│ │ │ ├── productService.js (4/24/2025) -│ │ │ ├── imageService.js (4/24/2025) -│ │ │ ├── couponService.js (NEW - 4/29/2025) -│ │ │ ├── categoryAdminService.js (4/25/2025) -│ │ │ ├── cartService.js (4/25/2025) -│ │ │ ├── blogService.js (NEW - 4/29/2025) -│ │ │ ├── blogAdminService.js (NEW - 4/29/2025) -│ │ │ ├── authService.js (4/26/2025) -│ │ │ ├── api.js (4/24/2025) -│ │ │ └── adminService.js (4/26/2025) │ │ ├── pages/ │ │ │ ├── Admin/ -│ │ │ │ ├── SettingsPage.jsx (4/26/2025) -│ │ │ │ ├── ReportsPage.jsx (4/28/2025) -│ │ │ │ ├── ProductsPage.jsx (4/24/2025) -│ │ │ │ ├── ProductEditPage.jsx (4/28/2025) -│ │ │ │ ├── OrdersPage.jsx (4/26/2025) -│ │ │ │ ├── DashboardPage.jsx (4/28/2025) -│ │ │ │ ├── CustomersPage.jsx (4/26/2025) -│ │ │ │ ├── CouponsPage.jsx (NEW - 4/29/2025) -│ │ │ │ ├── CategoriesPage.jsx (4/25/2025) -│ │ │ │ ├── BlogPage.jsx (NEW - 4/29/2025) -│ │ │ │ └── BlogEditPage.jsx (NEW - 4/29/2025) -│ │ │ ├── BlogCommentsPage.jsx (NEW - 4/29/2025) -│ │ │ ├── VerifyPage.jsx (4/24/2025) -│ │ │ ├── UserOrdersPage.jsx (4/26/2025) -│ │ │ ├── RegisterPage.jsx (4/24/2025) -│ │ │ ├── ProductsPage.jsx (4/25/2025) -│ │ │ ├── ProductDetailPage.jsx (4/26/2025) -│ │ │ ├── PaymentSuccessPage.jsx (4/27/2025) -│ │ │ ├── PaymentCancelPage.jsx (4/26/2025) -│ │ │ ├── NotFoundPage.jsx (4/24/2025) -│ │ │ ├── LoginPage.jsx (4/24/2025) -│ │ │ ├── HomePage.jsx (4/25/2025) -│ │ │ ├── CouponRedemptionsPage.jsx (NEW - 4/29/2025) -│ │ │ ├── CouponEditPage.jsx (NEW - 4/29/2025) -│ │ │ ├── CheckoutPage.jsx (4/28/2025) -│ │ │ ├── CartPage.jsx (NEW - 4/29/2025) -│ │ │ ├── BlogPage.jsx (NEW - 4/29/2025) -│ │ │ └── BlogDetailPage.jsx (NEW - 4/29/2025) -│ │ ├── layouts/ -│ │ │ ├── MainLayout.jsx (4/29/2025) -│ │ │ ├── AuthLayout.jsx (4/24/2025) -│ │ │ └── AdminLayout.jsx (4/29/2025) +│ │ │ │ ├── ReportsPage.jsx +│ │ │ │ ├── ProductEditPage.jsx +│ │ │ │ ├── OrdersPage.jsx +│ │ │ │ ├── EmailTemplatesPage.jsx +│ │ │ │ ├── SettingsPage.jsx +│ │ │ │ ├── BlogEditPage.jsx +│ │ │ │ ├── CategoriesPage.jsx +│ │ │ │ ├── CustomersPage.jsx +│ │ │ │ ├── CouponsPage.jsx +│ │ │ │ ├── ProductReviewsPage.jsx +│ │ │ │ ├── BlogPage.jsx +│ │ │ │ ├── BlogCommentsPage.jsx +│ │ │ │ ├── DashboardPage.jsx +│ │ │ │ └── ProductsPage.jsx +│ │ │ ├── CheckoutPage.jsx +│ │ │ ├── CouponEditPage.jsx +│ │ │ ├── ProductsPage.jsx +│ │ │ ├── UserOrdersPage.jsx +│ │ │ ├── CartPage.jsx +│ │ │ ├── ProductDetailPage.jsx +│ │ │ ├── BlogDetailPage.jsx +│ │ │ ├── BlogPage.jsx +│ │ │ ├── CouponRedemptionsPage.jsx +│ │ │ ├── HomePage.jsx +│ │ │ ├── LoginPage.jsx +│ │ │ ├── PaymentSuccessPage.jsx +│ │ │ ├── RegisterPage.jsx +│ │ │ ├── VerifyPage.jsx +│ │ │ ├── NotFoundPage.jsx +│ │ │ └── PaymentCancelPage.jsx +│ │ ├── services/ +│ │ │ ├── emailTemplateService.js +│ │ │ ├── blogAdminService.js +│ │ │ ├── adminService.js +│ │ │ ├── couponService.js +│ │ │ ├── productService.js +│ │ │ ├── productReviewService.js +│ │ │ ├── settingsAdminService.js +│ │ │ ├── imageService.js +│ │ │ ├── cartService.js +│ │ │ ├── categoryAdminService.js +│ │ │ ├── authService.js +│ │ │ ├── blogService.js +│ │ │ └── api.js +│ │ ├── components/ +│ │ │ ├── ProductReviews.jsx +│ │ │ ├── OrderStatusDialog.jsx +│ │ │ ├── ImageUploader.jsx +│ │ │ ├── CouponInput.jsx +│ │ │ ├── EmailDialog.jsx +│ │ │ ├── StripePaymentForm.jsx +│ │ │ ├── Footer.jsx +│ │ │ ├── ProductImage.jsx +│ │ │ ├── ProtectedRoute.jsx +│ │ │ ├── Notifications.jsx +│ │ │ └── ProductRatingDisplay.jsx │ │ ├── hooks/ -│ │ │ ├── settingsAdminHooks.js (4/25/2025) -│ │ │ ├── reduxHooks.js (4/26/2025) -│ │ │ ├── couponAdminHooks.js (NEW - 4/29/2025) -│ │ │ ├── categoryAdminHooks.js (4/24/2025) -│ │ │ ├── blogHooks.js (NEW - 4/29/2025) -│ │ │ ├── apiHooks.js (4/26/2025) -│ │ │ └── adminHooks.js (4/26/2025) +│ │ │ ├── apiHooks.js +│ │ │ ├── blogHooks.js +│ │ │ ├── emailTemplateHooks.js +│ │ │ ├── adminHooks.js +│ │ │ ├── productReviewHooks.js +│ │ │ ├── reduxHooks.js +│ │ │ ├── couponAdminHooks.js +│ │ │ ├── settingsAdminHooks.js +│ │ │ └── categoryAdminHooks.js +│ │ ├── layouts/ +│ │ │ ├── AdminLayout.jsx +│ │ │ ├── MainLayout.jsx +│ │ │ └── AuthLayout.jsx │ │ ├── features/ │ │ │ ├── ui/ -│ │ │ │ └── uiSlice.js (4/24/2025) +│ │ │ │ └── uiSlice.js │ │ │ ├── cart/ -│ │ │ │ └── cartSlice.js (NEW - 4/29/2025) -│ │ │ └── auth/ -│ │ │ └── authSlice.js (4/26/2025) +│ │ │ │ └── cartSlice.js +│ │ │ ├── auth/ +│ │ │ │ └── authSlice.js +│ │ │ └── theme/ +│ │ │ ├── index.js +│ │ │ └── ThemeProvider.jsx +│ │ ├── utils/ +│ │ │ └── imageUtils.js +│ │ ├── store/ +│ │ │ └── index.js │ │ ├── context/ -│ │ │ └── StripeContext.jsx (4/28/2025) -│ │ ├── components/ -│ │ │ ├── StripePaymentForm.jsx (4/26/2025) -│ │ │ ├── ProtectedRoute.jsx (4/24/2025) -│ │ │ ├── ProductImage.jsx (4/24/2025) -│ │ │ ├── OrderStatusDialog.jsx (4/26/2025) -│ │ │ ├── Notifications.jsx (4/24/2025) -│ │ │ ├── ImageUploader.jsx (4/24/2025) -│ │ │ ├── Footer.jsx (4/25/2025) -│ │ │ ├── EmailDialog.jsx (4/25/2025) -│ │ │ └── CouponInput.jsx (NEW - 4/29/2025) +│ │ │ └── StripeContext.jsx │ │ ├── assets/ -│ │ │ ├── main.jsx (4/24/2025) -│ │ │ └── config.js (4/24/2025) -│ │ └── App.jsx (4/24/2025) -├── db/ -│ ├── test/ -│ └── init/ -│ ├── 16-blog-schema.sql (NEW) -│ ├── 15-coupon.sql (NEW) -│ ├── 14-product-notifications.sql (NEW) -│ ├── 13-cart-metadata.sql -│ ├── 12-shipping-orders.sql -│ ├── 11-notifications.sql -│ ├── 10-payment.sql -│ ├── 09-system-settings.sql -│ ├── 08-create-email.sql -│ ├── 07-user-keys.sql -│ ├── 06-product-categories.sql -│ ├── 05-admin-role.sql -│ ├── 04-product-images.sql -│ ├── 03-api-key.sql -│ ├── 02-seed.sql -│ └── 01-schema.sql +│ │ │ ├── App.jsx +│ │ │ ├── main.jsx +│ │ │ └── config.js +│ │ └── public/ +│ │ ├── favicon.svg +│ │ ├── package-lock.json +│ │ ├── vite.config.js +│ │ ├── README.md +│ │ ├── package.json +│ │ ├── Dockerfile +│ │ ├── nginx.conf +│ │ ├── setup-frontend.sh +│ │ ├── index.html +│ │ └── .env ├── backend/ +│ ├── node_modules/ │ ├── src/ -│ │ ├── services/ -│ │ │ ├── shippingService.js -│ │ │ └── notificationService.js │ │ ├── routes/ -│ │ │ ├── userOrders.js -│ │ │ ├── userAdmin.js -│ │ │ ├── stripePayment.js -│ │ │ ├── shipping.js -│ │ │ ├── settingsAdmin.js -│ │ │ ├── products.js -│ │ │ ├── productAdminImages.js +│ │ │ ├── cart.js +│ │ │ ├── couponAdmin.js +│ │ │ ├── emailTemplatesAdmin.js +│ │ │ ├── blogAdmin.js │ │ │ ├── productAdmin.js │ │ │ ├── orderAdmin.js -│ │ │ ├── images.js -│ │ │ ├── couponAdmin.js (NEW - Large file: 18.7 KB) +│ │ │ ├── settingsAdmin.js +│ │ │ ├── blog.js +│ │ │ ├── auth.js +│ │ │ ├── productReviews.js +│ │ │ ├── stripePayment.js +│ │ │ ├── products.js +│ │ │ ├── productReviewsAdmin.js +│ │ │ ├── blogCommentsAdmin.js +│ │ │ ├── userAdmin.js │ │ │ ├── categoryAdmin.js -│ │ │ ├── cart.js (Updated - now 39.6 KB) -│ │ │ ├── blogCommentsAdmin.js (NEW) -│ │ │ ├── blogAdmin.js (NEW) -│ │ │ ├── blog.js (NEW) -│ │ │ └── auth.js -│ │ ├── models/ -│ │ │ └── SystemSettings.js +│ │ │ ├── shipping.js +│ │ │ ├── images.js +│ │ │ ├── userOrders.js +│ │ │ └── productAdminImages.js │ │ ├── middleware/ │ │ │ ├── upload.js -│ │ │ ├── auth.js -│ │ │ └── adminAuth.js +│ │ │ ├── adminAuth.js +│ │ │ └── auth.js +│ │ ├── services/ +│ │ │ ├── shippingService.js +│ │ │ ├── emailService.js +│ │ │ └── notificationService.js +│ │ ├── models/ +│ │ │ └── SystemSettings.js │ │ └── db/ │ │ ├── index.js │ │ ├── index.js │ │ └── config.js │ └── public/ -│ └── uploads/ -│ ├── products/ -│ └── blog/ (NEW) -└── git/ - ├── fileStructure.txt - └── docker-compose.yml \ No newline at end of file +│ ├── uploads/ +│ │ ├── products/ +│ │ └── blog/ +│ ├── package-lock.json +│ ├── README.md +│ ├── .env +│ ├── package.json +│ ├── Dockerfile +│ └── .gitignore +└── db/ + ├── init/ + │ ├── 18-email-templates.sql + │ ├── 01-schema.sql + │ ├── 02-seed.sql + │ ├── 16-blog-schema.sql + │ ├── 15-coupon.sql + │ ├── 17-product-reviews.sql + │ ├── 04-product-images.sql + │ ├── 09-system-settings.sql + │ ├── 14-product-notifications.sql + │ ├── 10-payment.sql + │ ├── 11-notifications.sql + │ ├── 12-shipping-orders.sql + │ ├── 08-create-email.sql + │ ├── 05-admin-role.sql + │ ├── 03-api-key.sql + │ ├── 07-user-keys.sql + │ ├── 13-cart-metadata.sql + │ └── 06-product-categories.sql + └── test/ +├── fileStructure.txt +├── docker-compose.yml +└── .gitignore \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 34a5e11..241f369 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,85 +1,41 @@ { "name": "rocks-bones-sticks-frontend", "version": "0.1.0", - "lockfileVersion": 3, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "rocks-bones-sticks-frontend", - "version": "0.1.0", - "dependencies": { - "@emotion/react": "^11.11.1", - "@emotion/styled": "^11.11.0", - "@fontsource/roboto": "^5.0.8", - "@mui/icons-material": "^5.14.19", - "@mui/material": "^5.14.19", - "@reduxjs/toolkit": "^2.0.1", - "@stripe/react-stripe-js": "^2.4.0", - "@stripe/stripe-js": "^2.2.0", - "@tanstack/react-query": "^5.12.2", - "@tanstack/react-query-devtools": "^5.12.2", - "axios": "^1.6.2", - "date-fns": "^4.1.0", - "dotenv": "^16.5.0", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-redux": "^9.0.2", - "react-router-dom": "^6.20.1", - "recharts": "^2.10.3" - }, - "devDependencies": { - "@types/react": "^18.2.37", - "@types/react-dom": "^18.2.15", - "@vitejs/plugin-react": "^4.2.0", - "eslint": "^8.53.0", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-react-refresh": "^0.4.4", - "sass": "^1.69.5", - "vite": "^5.0.0" - } - }, - "node_modules/@ampproject/remapping": { + "dependencies": { + "@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, - "dependencies": { + "requires": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, - "node_modules/@babel/code-frame": { + "@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dependencies": { + "requires": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { + "@babel/compat-data": { "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, - "engines": { - "node": ">=6.9.0" - } + "dev": true }, - "node_modules/@babel/core": { + "@babel/core": { "version": "7.26.10", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", "dev": true, - "dependencies": { + "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.26.10", @@ -96,200 +52,141 @@ "json5": "^2.2.3", "semver": "^6.3.1" }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + } } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@babel/generator": { + "@babel/generator": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "dependencies": { + "requires": { "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets": { + "@babel/helper-compilation-targets": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", "dev": true, - "dependencies": { + "requires": { "@babel/compat-data": "^7.26.8", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports": { + "@babel/helper-module-imports": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dependencies": { + "requires": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-transforms": { + "@babel/helper-module-transforms": { "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, - "dependencies": { + "requires": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { + "@babel/helper-plugin-utils": { "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, - "engines": { - "node": ">=6.9.0" - } + "dev": true }, - "node_modules/@babel/helper-string-parser": { + "@babel/helper-string-parser": { "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==", - "engines": { - "node": ">=6.9.0" - } + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==" }, - "node_modules/@babel/helper-validator-identifier": { + "@babel/helper-validator-identifier": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "engines": { - "node": ">=6.9.0" - } + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==" }, - "node_modules/@babel/helper-validator-option": { + "@babel/helper-validator-option": { "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, - "engines": { - "node": ">=6.9.0" - } + "dev": true }, - "node_modules/@babel/helpers": { + "@babel/helpers": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "dev": true, - "dependencies": { + "requires": { "@babel/template": "^7.27.0", "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/parser": { + "@babel/parser": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", - "dependencies": { + "requires": { "@babel/types": "^7.27.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { + "@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, - "dependencies": { + "requires": { "@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": { + "@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, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime": { + "@babel/runtime": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "dependencies": { + "requires": { "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/template": { + "@babel/template": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", - "dependencies": { + "requires": { "@babel/code-frame": "^7.26.2", "@babel/parser": "^7.27.0", "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/traverse": { + "@babel/traverse": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dependencies": { + "requires": { "@babel/code-frame": "^7.26.2", "@babel/generator": "^7.27.0", "@babel/parser": "^7.27.0", @@ -297,28 +194,22 @@ "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/types": { + "@babel/types": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", - "dependencies": { + "requires": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@emotion/babel-plugin": { + "@emotion/babel-plugin": { "version": "11.13.5", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", - "dependencies": { + "requires": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", "@emotion/hash": "^0.9.2", @@ -332,11 +223,11 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/cache": { + "@emotion/cache": { "version": "11.14.0", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", - "dependencies": { + "requires": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", "@emotion/utils": "^1.4.2", @@ -344,29 +235,29 @@ "stylis": "4.2.0" } }, - "node_modules/@emotion/hash": { + "@emotion/hash": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==" }, - "node_modules/@emotion/is-prop-valid": { + "@emotion/is-prop-valid": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", - "dependencies": { + "requires": { "@emotion/memoize": "^0.9.0" } }, - "node_modules/@emotion/memoize": { + "@emotion/memoize": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==" }, - "node_modules/@emotion/react": { + "@emotion/react": { "version": "11.14.0", "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", - "dependencies": { + "requires": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/cache": "^11.14.0", @@ -375,21 +266,13 @@ "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" - }, - "peerDependencies": { - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } } }, - "node_modules/@emotion/serialize": { + "@emotion/serialize": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", - "dependencies": { + "requires": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", @@ -397,457 +280,226 @@ "csstype": "^3.0.2" } }, - "node_modules/@emotion/sheet": { + "@emotion/sheet": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==" }, - "node_modules/@emotion/styled": { + "@emotion/styled": { "version": "11.14.0", "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz", "integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==", - "dependencies": { + "requires": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/is-prop-valid": "^1.3.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2" - }, - "peerDependencies": { - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } } }, - "node_modules/@emotion/unitless": { + "@emotion/unitless": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==" }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "@emotion/use-insertion-effect-with-fallbacks": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", - "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", - "peerDependencies": { - "react": ">=16.8.0" - } + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==" }, - "node_modules/@emotion/utils": { + "@emotion/utils": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==" }, - "node_modules/@emotion/weak-memoize": { + "@emotion/weak-memoize": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==" }, - "node_modules/@esbuild/aix-ppc64": { + "@esbuild/aix-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/android-arm": { + "@esbuild/android-arm": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/android-arm64": { + "@esbuild/android-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/android-x64": { + "@esbuild/android-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/darwin-arm64": { + "@esbuild/darwin-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/darwin-x64": { + "@esbuild/darwin-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/freebsd-arm64": { + "@esbuild/freebsd-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/freebsd-x64": { + "@esbuild/freebsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-arm": { + "@esbuild/linux-arm": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-arm64": { + "@esbuild/linux-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-ia32": { + "@esbuild/linux-ia32": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-loong64": { + "@esbuild/linux-loong64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-mips64el": { + "@esbuild/linux-mips64el": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-ppc64": { + "@esbuild/linux-ppc64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-riscv64": { + "@esbuild/linux-riscv64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-s390x": { + "@esbuild/linux-s390x": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/linux-x64": { + "@esbuild/linux-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/netbsd-x64": { + "@esbuild/netbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/openbsd-x64": { + "@esbuild/openbsd-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/sunos-x64": { + "@esbuild/sunos-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/win32-arm64": { + "@esbuild/win32-arm64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/win32-ia32": { + "@esbuild/win32-ia32": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@esbuild/win32-x64": { + "@esbuild/win32-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } + "optional": true }, - "node_modules/@eslint-community/eslint-utils": { + "@eslint-community/eslint-utils": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", "dev": true, - "dependencies": { + "requires": { "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@eslint-community/regexpp": { + "@eslint-community/regexpp": { "version": "4.12.1", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } + "dev": true }, - "node_modules/@eslint/eslintrc": { + "@eslint/eslintrc": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, - "dependencies": { + "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.6.0", @@ -858,162 +510,109 @@ "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + } } }, - "node_modules/@eslint/js": { + "@eslint/js": { "version": "8.57.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } + "dev": true }, - "node_modules/@fontsource/roboto": { + "@fontsource/roboto": { "version": "5.2.5", "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.5.tgz", - "integrity": "sha512-70r2UZ0raqLn5W+sPeKhqlf8wGvUXFWlofaDlcbt/S3d06+17gXKr3VNqDODB0I1ASme3dGT5OJj9NABt7OTZQ==", - "funding": { - "url": "https://github.com/sponsors/ayuhito" - } + "integrity": "sha512-70r2UZ0raqLn5W+sPeKhqlf8wGvUXFWlofaDlcbt/S3d06+17gXKr3VNqDODB0I1ASme3dGT5OJj9NABt7OTZQ==" }, - "node_modules/@humanwhocodes/config-array": { + "@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", "dev": true, - "dependencies": { + "requires": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/module-importer": { + "@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } + "dev": true }, - "node_modules/@humanwhocodes/object-schema": { + "@humanwhocodes/object-schema": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", "dev": true }, - "node_modules/@jridgewell/gen-mapping": { + "@jridgewell/gen-mapping": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dependencies": { + "requires": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, - "node_modules/@jridgewell/resolve-uri": { + "@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" }, - "node_modules/@jridgewell/set-array": { + "@jridgewell/set-array": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==" }, - "node_modules/@jridgewell/sourcemap-codec": { + "@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, - "node_modules/@jridgewell/trace-mapping": { + "@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { + "requires": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@mui/core-downloads-tracker": { + "@mixmark-io/domino": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", + "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==" + }, + "@mui/core-downloads-tracker": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.17.1.tgz", - "integrity": "sha512-OcZj+cs6EfUD39IoPBOgN61zf1XFVY+imsGoBDwXeSq2UHJZE3N59zzBOVjclck91Ne3e9gudONOeILvHCIhUA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - } + "integrity": "sha512-OcZj+cs6EfUD39IoPBOgN61zf1XFVY+imsGoBDwXeSq2UHJZE3N59zzBOVjclck91Ne3e9gudONOeILvHCIhUA==" }, - "node_modules/@mui/icons-material": { + "@mui/icons-material": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.17.1.tgz", "integrity": "sha512-CN86LocjkunFGG0yPlO4bgqHkNGgaEOEc3X/jG5Bzm401qYw79/SaLrofA7yAKCCXAGdIGnLoMHohc3+ubs95A==", - "dependencies": { + "requires": { "@babel/runtime": "^7.23.9" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@mui/material": "^5.0.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } } }, - "node_modules/@mui/material": { + "@mui/material": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.17.1.tgz", "integrity": "sha512-2B33kQf+GmPnrvXXweWAx+crbiUEsxCdCN979QDYnlH9ox4pd+0/IBriWLV+l6ORoBF60w39cWjFnJYGFdzXcw==", - "dependencies": { + "requires": { "@babel/runtime": "^7.23.9", "@mui/core-downloads-tracker": "^5.17.1", "@mui/system": "^5.17.1", @@ -1027,99 +626,40 @@ "react-is": "^19.0.0", "react-transition-group": "^4.4.5" }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true + "dependencies": { + "react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==" } } }, - "node_modules/@mui/material/node_modules/react-is": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", - "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==" - }, - "node_modules/@mui/private-theming": { + "@mui/private-theming": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.17.1.tgz", "integrity": "sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ==", - "dependencies": { + "requires": { "@babel/runtime": "^7.23.9", "@mui/utils": "^5.17.1", "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } } }, - "node_modules/@mui/styled-engine": { + "@mui/styled-engine": { "version": "5.16.14", "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.16.14.tgz", "integrity": "sha512-UAiMPZABZ7p8mUW4akDV6O7N3+4DatStpXMZwPlt+H/dA0lt67qawN021MNND+4QTpjaiMYxbhKZeQcyWCbuKw==", - "dependencies": { + "requires": { "@babel/runtime": "^7.23.9", "@emotion/cache": "^11.13.5", "csstype": "^3.1.3", "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - } } }, - "node_modules/@mui/system": { + "@mui/system": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.17.1.tgz", "integrity": "sha512-aJrmGfQpyF0U4D4xYwA6ueVtQcEMebET43CUmKMP7e7iFh3sMIF3sBR0l8Urb4pqx1CBjHAaWgB0ojpND4Q3Jg==", - "dependencies": { + "requires": { "@babel/runtime": "^7.23.9", "@mui/private-theming": "^5.17.1", "@mui/styled-engine": "^5.16.14", @@ -1128,50 +668,18 @@ "clsx": "^2.1.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } } }, - "node_modules/@mui/types": { + "@mui/types": { "version": "7.2.24", "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz", - "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==", - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } + "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==" }, - "node_modules/@mui/utils": { + "@mui/utils": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.17.1.tgz", "integrity": "sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg==", - "dependencies": { + "requires": { "@babel/runtime": "^7.23.9", "@mui/types": "~7.2.15", "@types/prop-types": "^15.7.12", @@ -1179,84 +687,47 @@ "prop-types": "^15.8.1", "react-is": "^19.0.0" }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true + "dependencies": { + "react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==" } } }, - "node_modules/@mui/utils/node_modules/react-is": { - "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", - "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==" - }, - "node_modules/@nodelib/fs.scandir": { + "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "dependencies": { + "requires": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" } }, - "node_modules/@nodelib/fs.stat": { + "@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } + "dev": true }, - "node_modules/@nodelib/fs.walk": { + "@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "dependencies": { + "requires": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" } }, - "node_modules/@parcel/watcher": { + "@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", "dev": true, - "hasInstallScript": true, "optional": true, - "dependencies": { - "detect-libc": "^1.0.3", - "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { + "requires": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", @@ -1269,654 +740,508 @@ "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", - "@parcel/watcher-win32-x64": "2.5.1" + "@parcel/watcher-win32-x64": "2.5.1", + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" } }, - "node_modules/@parcel/watcher-android-arm64": { + "@parcel/watcher-android-arm64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-darwin-arm64": { + "@parcel/watcher-darwin-arm64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-darwin-x64": { + "@parcel/watcher-darwin-x64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-freebsd-x64": { + "@parcel/watcher-freebsd-x64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-linux-arm-glibc": { + "@parcel/watcher-linux-arm-glibc": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", - "cpu": [ - "arm" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-linux-arm-musl": { + "@parcel/watcher-linux-arm-musl": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", - "cpu": [ - "arm" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { + "@parcel/watcher-linux-arm64-glibc": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-linux-arm64-musl": { + "@parcel/watcher-linux-arm64-musl": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-linux-x64-glibc": { + "@parcel/watcher-linux-x64-glibc": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-linux-x64-musl": { + "@parcel/watcher-linux-x64-musl": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-win32-arm64": { + "@parcel/watcher-win32-arm64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-win32-ia32": { + "@parcel/watcher-win32-ia32": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", - "cpu": [ - "ia32" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@parcel/watcher-win32-x64": { + "@parcel/watcher-win32-x64": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } + "optional": true }, - "node_modules/@popperjs/core": { + "@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" }, - "node_modules/@reduxjs/toolkit": { + "@reduxjs/toolkit": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.7.0.tgz", "integrity": "sha512-XVwolG6eTqwV0N8z/oDlN93ITCIGIop6leXlGJI/4EKy+0POYkR+ABHRSdGXY+0MQvJBP8yAzh+EYFxTuvmBiQ==", - "dependencies": { + "requires": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^10.0.3", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" - }, - "peerDependencies": { - "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", - "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-redux": { - "optional": true - } } }, - "node_modules/@remix-run/router": { + "@remirror/core-constants": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", + "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==" + }, + "@remix-run/router": { "version": "1.23.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", - "engines": { - "node": ">=14.0.0" - } + "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==" }, - "node_modules/@rollup/rollup-android-arm-eabi": { + "@rollup/rollup-android-arm-eabi": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz", "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==", - "cpu": [ - "arm" - ], "dev": true, - "optional": true, - "os": [ - "android" - ] + "optional": true }, - "node_modules/@rollup/rollup-android-arm64": { + "@rollup/rollup-android-arm64": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz", "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "android" - ] + "optional": true }, - "node_modules/@rollup/rollup-darwin-arm64": { + "@rollup/rollup-darwin-arm64": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz", "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "darwin" - ] + "optional": true }, - "node_modules/@rollup/rollup-darwin-x64": { + "@rollup/rollup-darwin-x64": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz", "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "darwin" - ] + "optional": true }, - "node_modules/@rollup/rollup-freebsd-arm64": { + "@rollup/rollup-freebsd-arm64": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz", "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "freebsd" - ] + "optional": true }, - "node_modules/@rollup/rollup-freebsd-x64": { + "@rollup/rollup-freebsd-x64": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz", "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "freebsd" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "@rollup/rollup-linux-arm-gnueabihf": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz", "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==", - "cpu": [ - "arm" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "@rollup/rollup-linux-arm-musleabihf": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz", "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==", - "cpu": [ - "arm" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { + "@rollup/rollup-linux-arm64-gnu": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz", "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-arm64-musl": { + "@rollup/rollup-linux-arm64-musl": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz", "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "@rollup/rollup-linux-loongarch64-gnu": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz", "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==", - "cpu": [ - "loong64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "@rollup/rollup-linux-powerpc64le-gnu": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz", "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==", - "cpu": [ - "ppc64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "@rollup/rollup-linux-riscv64-gnu": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz", "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==", - "cpu": [ - "riscv64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { + "@rollup/rollup-linux-riscv64-musl": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz", "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==", - "cpu": [ - "riscv64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { + "@rollup/rollup-linux-s390x-gnu": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz", "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==", - "cpu": [ - "s390x" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-x64-gnu": { + "@rollup/rollup-linux-x64-gnu": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz", "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-linux-x64-musl": { + "@rollup/rollup-linux-x64-musl": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz", "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "linux" - ] + "optional": true }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { + "@rollup/rollup-win32-arm64-msvc": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz", "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==", - "cpu": [ - "arm64" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ] + "optional": true }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { + "@rollup/rollup-win32-ia32-msvc": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz", "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==", - "cpu": [ - "ia32" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ] + "optional": true }, - "node_modules/@rollup/rollup-win32-x64-msvc": { + "@rollup/rollup-win32-x64-msvc": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz", "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==", - "cpu": [ - "x64" - ], "dev": true, - "optional": true, - "os": [ - "win32" - ] + "optional": true }, - "node_modules/@standard-schema/spec": { + "@standard-schema/spec": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==" }, - "node_modules/@standard-schema/utils": { + "@standard-schema/utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==" }, - "node_modules/@stripe/react-stripe-js": { + "@stripe/react-stripe-js": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-2.4.0.tgz", "integrity": "sha512-1jVQEL3OuhuzNlf4OdfqovHt+MkWh8Uh8xpLxx/xUFUDdF+7/kDOrGKy+xJO3WLCfZUL7NAy+/ypwXbbYZi0tg==", - "dependencies": { + "requires": { "prop-types": "^15.7.2" - }, - "peerDependencies": { - "@stripe/stripe-js": "^1.44.1 || ^2.0.0", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@stripe/stripe-js": { + "@stripe/stripe-js": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.3.0.tgz", "integrity": "sha512-iTwzjw1ORUR+1pH21+C/M05w+Jh5hAuE4QUei7Gnku65N7QpEaHtyVszYMYDBs6iNyLrD1tfQTSrjD6NkOA/ww==" }, - "node_modules/@tanstack/query-core": { + "@tanstack/query-core": { "version": "5.74.4", "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.74.4.tgz", - "integrity": "sha512-YuG0A0+3i9b2Gfo9fkmNnkUWh5+5cFhWBN0pJAHkHilTx6A0nv8kepkk4T4GRt4e5ahbtFj2eTtkiPcVU1xO4A==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } + "integrity": "sha512-YuG0A0+3i9b2Gfo9fkmNnkUWh5+5cFhWBN0pJAHkHilTx6A0nv8kepkk4T4GRt4e5ahbtFj2eTtkiPcVU1xO4A==" }, - "node_modules/@tanstack/query-devtools": { + "@tanstack/query-devtools": { "version": "5.74.6", "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.74.6.tgz", - "integrity": "sha512-djaFT11mVCOW3e0Ezfyiq7T6OoHy2LRI1fUFQvj+G6+/4A1FkuRMNUhQkdP1GXlx8id0f1/zd5fgDpIy5SU/Iw==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - } + "integrity": "sha512-djaFT11mVCOW3e0Ezfyiq7T6OoHy2LRI1fUFQvj+G6+/4A1FkuRMNUhQkdP1GXlx8id0f1/zd5fgDpIy5SU/Iw==" }, - "node_modules/@tanstack/react-query": { + "@tanstack/react-query": { "version": "5.74.4", "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.74.4.tgz", "integrity": "sha512-mAbxw60d4ffQ4qmRYfkO1xzRBPUEf/72Dgo3qqea0J66nIKuDTLEqQt0ku++SDFlMGMnB6uKDnEG1xD/TDse4Q==", - "dependencies": { + "requires": { "@tanstack/query-core": "5.74.4" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^18 || ^19" } }, - "node_modules/@tanstack/react-query-devtools": { + "@tanstack/react-query-devtools": { "version": "5.74.6", "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.74.6.tgz", "integrity": "sha512-vlsDwz4/FsblK0h7VAlXUdJ+9OV+i1n8OLb8CLLAZqu0M9GCnbajytZwsRmns33PXBZ6wQBJ859kg6aajx+e9Q==", - "dependencies": { + "requires": { "@tanstack/query-devtools": "5.74.6" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "@tanstack/react-query": "^5.74.4", - "react": "^18 || ^19" } }, - "node_modules/@types/babel__core": { + "@tiptap/core": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.11.9.tgz", + "integrity": "sha512-UZSxQLLyJst47xep3jlyKM6y1ebZnmvbGsB7njBVjfxf5H+4yFpRJwwNqrBHM/vyU55LCtPChojqaYC1wXLf6g==" + }, + "@tiptap/extension-blockquote": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.11.9.tgz", + "integrity": "sha512-muGiVb5k86wF01ehbtT5oh1bxwcI0yQo47y9Sso7Jlvd06GW6Ur3X2aJwtKZsV0uPTFliKKLR6DhtLJE1AaR4g==" + }, + "@tiptap/extension-bold": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.11.9.tgz", + "integrity": "sha512-VUwiKOBr2gFxI098hICgfkeCQqkFZXVFLxKMvu/ohwmuTV412cxtYJZikhN0JuINUjBt+LX1zk72BJ8q2C9puA==" + }, + "@tiptap/extension-bubble-menu": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.11.9.tgz", + "integrity": "sha512-5EttgsqjzlKRd0dmbVlujw47XGHA2JSDI4eEvsJz5O7XcRtzPjBJ+DdH4Q+wlyBf9ZWzVY/1bp90xP1dxHesJg==", + "requires": { + "tippy.js": "^6.3.7" + } + }, + "@tiptap/extension-bullet-list": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.11.9.tgz", + "integrity": "sha512-H9n0ShHVFc+UNZCui/wplDdVoi4MYVFWB1GFOhHSiSe4CCGNW6qftjI7c0NPR7Bhmzga1fraJR5W5H/qCtoPLA==" + }, + "@tiptap/extension-code": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.11.9.tgz", + "integrity": "sha512-RbTdzWk6F1+EsThT2Sj4eQHgkXO3NfFdeNZ/V+t9invJm7duqhprMT0G1aEaSxGvr3rjbdeuwYpSsEeV3Wrw+A==" + }, + "@tiptap/extension-code-block": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.11.9.tgz", + "integrity": "sha512-brwvt/SdP65DpchPv5rkhjEjjIIgE1+9ySw8kCTiyXWUrmZA0kK/iwp5zPpHfsoWT8Sa9+fh2uraVZGOF9Dcqw==" + }, + "@tiptap/extension-document": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.11.9.tgz", + "integrity": "sha512-lkrCkMDDLtaPvMljw7vfvwnNZmZTy4uIfbkLdF3BkaV4XAHMVfoOzSbq0uRaTgUSLH8Fv0L1B6Nwol4OYnzI3w==" + }, + "@tiptap/extension-dropcursor": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.11.9.tgz", + "integrity": "sha512-LqWEaAWyJ3eUrafgKT4UCIvDqhth1cX976dQcAOPg5POmldZ8KgZTeEYZl7AYpzFS++HlTIwJ8PMOu29/g+l+g==" + }, + "@tiptap/extension-floating-menu": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.11.9.tgz", + "integrity": "sha512-0rWGnfjtDx4AAOUaPd/hJsy5VOPp4A4zjVX+bPiDdSGAJZELQnQRT18GwwjdzKWE+imeGZ4pe/dbPcgD9uY2FA==", + "requires": { + "tippy.js": "^6.3.7" + } + }, + "@tiptap/extension-gapcursor": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.11.9.tgz", + "integrity": "sha512-IFdprIzeDAck0r4mS55ad6tts/AHyLg83jk2jbcy+f7CMGDpoVW8R10ORl8LD8kJBxnC/TqBsbr44mQJtxzDog==" + }, + "@tiptap/extension-hard-break": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.11.9.tgz", + "integrity": "sha512-S2IfkK+dlX+59KWuUHgtTEjLVsOTEQFt6Kng/lNqKY8G46gujY6L3EDqtPibxs63B+KKOHHOlKShcYZKWzWvvw==" + }, + "@tiptap/extension-heading": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.11.9.tgz", + "integrity": "sha512-Z84Vbw26bnMyIyZ7hc8/xXDD5uAcr4GA1zs0HPs4Er9wROOqkZnlgE54LaObXn2YbMKuDZ24cmCU8LFy0etN+w==" + }, + "@tiptap/extension-history": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.11.9.tgz", + "integrity": "sha512-DqA9tGPqmt5EmREGW2Wg3vc+Qb6rBeSmuHeQ9R4M4dYJYSh2gBheunBNnerQlZDj9Dk4H8NGgAz2YLrAkSlxSA==" + }, + "@tiptap/extension-horizontal-rule": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.11.9.tgz", + "integrity": "sha512-7UhwRZPA3ykKTat4ooY/GzGO4wy9040vzsnev+189BHIMvxe4I483B1v3sUBvUJrFf8z0+iWulJx3zoTskieoA==" + }, + "@tiptap/extension-italic": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.11.9.tgz", + "integrity": "sha512-xLQW6OtOwTEOkyvEX0jQcbm4kfjl1uOLMJ5daHolCR3DiEDWoxYrZrs2lt467nf5Sz4/50MQqGuZw8pVfWWxqg==" + }, + "@tiptap/extension-list-item": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.11.9.tgz", + "integrity": "sha512-57VO0Joe8WEEz2ypxY64TYx4KenFaqYnhrTLsWUvlearpBXbTFc8IaI/rdLubgJlEE5Q3e+NirCyQSLCE8a2Zg==" + }, + "@tiptap/extension-ordered-list": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.11.9.tgz", + "integrity": "sha512-jLRn0L6nRJ/yp3JEVuk1elc11XPSF4lDTQdj45EMSgxMoHU13LF9MZm2H2jwLXPpBflB/MVJtt9Nd2XzOPTGcw==" + }, + "@tiptap/extension-paragraph": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.11.9.tgz", + "integrity": "sha512-smoxsfujsPJ9GVXG03QqM7yBwVfaLQa0l8VHPXaJUIjjvSpG1g8WlaxC46JB4Ba4W9KlrkPt1fdEpNcelRwcmw==" + }, + "@tiptap/extension-strike": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.11.9.tgz", + "integrity": "sha512-YFZ/Mjv/wA13oO8wEK4DVw6zSuYfEz4NLF6EA2mMo8N6UUSrBFEWiGE3pHBysIwcRXTaUzzGoYN+lohbmpHwBQ==" + }, + "@tiptap/extension-text": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.11.9.tgz", + "integrity": "sha512-OGjdsXN+d3UZFQZ+r+ozX20G7BcHWCGkn9XZUVItJwzpNa9x4EiPsKCJVk17jVFRAsAHdMBcsBRdErzdO6/Hrg==" + }, + "@tiptap/extension-text-style": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-2.11.9.tgz", + "integrity": "sha512-lB3uJBRiRYTCxtNeEF70IiwzGFfAU69xvsHpQowJU357lZsTj/QPRQt8Blu48qIoUAJGU00vGRTLae6X9myMMw==" + }, + "@tiptap/pm": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.11.9.tgz", + "integrity": "sha512-hhonYVcL3fRkWyiCFJQ7HHXtmFviwnof8VDRFX1vm69GskGeqUTJUFR+1as2hZYekHe5rO4FZUm1dlETDWTnzQ==", + "requires": { + "prosemirror-changeset": "^2.2.1", + "prosemirror-collab": "^1.3.1", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.2", + "prosemirror-markdown": "^1.13.1", + "prosemirror-menu": "^1.2.4", + "prosemirror-model": "^1.23.0", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.4.1", + "prosemirror-state": "^1.4.3", + "prosemirror-tables": "^1.6.4", + "prosemirror-trailing-node": "^3.0.0", + "prosemirror-transform": "^1.10.2", + "prosemirror-view": "^1.37.0" + } + }, + "@tiptap/react": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.11.9.tgz", + "integrity": "sha512-cjQICAcx5eTlAsACbVHuDI0d2UO10lijTHhtn6WyaCzpcWcVp6RgHgn6//ffWg7oQB0IfJFRZy5tpEvNMOVuvA==", + "requires": { + "@tiptap/extension-bubble-menu": "^2.11.9", + "@tiptap/extension-floating-menu": "^2.11.9", + "@types/use-sync-external-store": "^0.0.6", + "fast-deep-equal": "^3", + "use-sync-external-store": "^1" + } + }, + "@tiptap/starter-kit": { + "version": "2.11.9", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.11.9.tgz", + "integrity": "sha512-UUx5t1PrwR+KVOjTkmGC1duOq6Ubz/fsetI1OieyegMT/2J1wkFFP1w3NFZarj5jo0GLBt3GMlBwS9GY8cJUxQ==", + "requires": { + "@tiptap/core": "^2.11.9", + "@tiptap/extension-blockquote": "^2.11.9", + "@tiptap/extension-bold": "^2.11.9", + "@tiptap/extension-bullet-list": "^2.11.9", + "@tiptap/extension-code": "^2.11.9", + "@tiptap/extension-code-block": "^2.11.9", + "@tiptap/extension-document": "^2.11.9", + "@tiptap/extension-dropcursor": "^2.11.9", + "@tiptap/extension-gapcursor": "^2.11.9", + "@tiptap/extension-hard-break": "^2.11.9", + "@tiptap/extension-heading": "^2.11.9", + "@tiptap/extension-history": "^2.11.9", + "@tiptap/extension-horizontal-rule": "^2.11.9", + "@tiptap/extension-italic": "^2.11.9", + "@tiptap/extension-list-item": "^2.11.9", + "@tiptap/extension-ordered-list": "^2.11.9", + "@tiptap/extension-paragraph": "^2.11.9", + "@tiptap/extension-strike": "^2.11.9", + "@tiptap/extension-text": "^2.11.9", + "@tiptap/extension-text-style": "^2.11.9", + "@tiptap/pm": "^2.11.9" + } + }, + "@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, - "dependencies": { + "requires": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", @@ -1924,341 +1249,293 @@ "@types/babel__traverse": "*" } }, - "node_modules/@types/babel__generator": { + "@types/babel__generator": { "version": "7.27.0", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.0.0" } }, - "node_modules/@types/babel__template": { + "@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, - "dependencies": { + "requires": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, - "node_modules/@types/babel__traverse": { + "@types/babel__traverse": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.20.7" } }, - "node_modules/@types/d3-array": { + "@types/d3-array": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" }, - "node_modules/@types/d3-color": { + "@types/d3-color": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" }, - "node_modules/@types/d3-ease": { + "@types/d3-ease": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" }, - "node_modules/@types/d3-interpolate": { + "@types/d3-interpolate": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", - "dependencies": { + "requires": { "@types/d3-color": "*" } }, - "node_modules/@types/d3-path": { + "@types/d3-path": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==" }, - "node_modules/@types/d3-scale": { + "@types/d3-scale": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", - "dependencies": { + "requires": { "@types/d3-time": "*" } }, - "node_modules/@types/d3-shape": { + "@types/d3-shape": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", - "dependencies": { + "requires": { "@types/d3-path": "*" } }, - "node_modules/@types/d3-time": { + "@types/d3-time": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==" }, - "node_modules/@types/d3-timer": { + "@types/d3-timer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" }, - "node_modules/@types/estree": { + "@types/estree": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "dev": true }, - "node_modules/@types/parse-json": { + "@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==" + }, + "@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "requires": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==" + }, + "@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, - "node_modules/@types/prop-types": { + "@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==" }, - "node_modules/@types/react": { + "@types/react": { "version": "18.3.20", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", - "dependencies": { + "dev": true, + "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" } }, - "node_modules/@types/react-dom": { + "@types/react-dom": { "version": "18.3.6", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.6.tgz", "integrity": "sha512-nf22//wEbKXusP6E9pfOCDwFdHAX4u172eaJI4YkDRQEZiorm6KfYnSC2SWLDMVWUOWPERmJnN0ujeAfTBLvrw==", - "dev": true, - "peerDependencies": { - "@types/react": "^18.0.0" - } + "dev": true }, - "node_modules/@types/react-transition-group": { + "@types/react-transition-group": { "version": "4.4.12", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", - "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", - "peerDependencies": { - "@types/react": "*" - } + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==" }, - "node_modules/@types/use-sync-external-store": { + "@types/use-sync-external-store": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==" }, - "node_modules/@ungap/structured-clone": { + "@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true }, - "node_modules/@vitejs/plugin-react": { + "@vitejs/plugin-react": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz", "integrity": "sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w==", "dev": true, - "dependencies": { + "requires": { "@babel/core": "^7.26.10", "@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.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, - "node_modules/acorn": { + "acorn": { "version": "8.14.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } + "dev": true }, - "node_modules/acorn-jsx": { + "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } + "dev": true }, - "node_modules/ajv": { + "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "dependencies": { + "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { + "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/ansi-styles": { + "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "dependencies": { + "requires": { "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/argparse": { + "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, - "node_modules/array-buffer-byte-length": { + "array-buffer-byte-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-includes": { + "array-includes": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.findlast": { + "array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.flat": { + "array.prototype.flat": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.flatmap": { + "array.prototype.flatmap": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array.prototype.tosorted": { + "array.prototype.tosorted": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/arraybuffer.prototype.slice": { + "arraybuffer.prototype.slice": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, - "dependencies": { + "requires": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -2266,632 +1543,445 @@ "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/async-function": { + "async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } + "dev": true }, - "node_modules/asynckit": { + "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/available-typed-arrays": { + "available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, - "dependencies": { + "requires": { "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/axios": { + "axios": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", - "dependencies": { + "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, - "node_modules/babel-plugin-macros": { + "babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dependencies": { + "requires": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" } }, - "node_modules/balanced-match": { + "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/brace-expansion": { + "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "dependencies": { + "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "node_modules/braces": { + "braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "optional": true, - "dependencies": { + "requires": { "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" } }, - "node_modules/browserslist": { + "browserslist": { "version": "4.24.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { + "requires": { "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" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/call-bind": { + "call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, - "dependencies": { + "requires": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-bind-apply-helpers": { + "call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dependencies": { + "requires": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/call-bound": { + "call-bound": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, - "dependencies": { + "requires": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { + "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, - "node_modules/caniuse-lite": { + "caniuse-lite": { "version": "1.0.30001715", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] + "dev": true }, - "node_modules/chalk": { + "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "dependencies": { + "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chokidar": { + "chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, - "dependencies": { + "requires": { "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" } }, - "node_modules/clsx": { + "clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" }, - "node_modules/color-convert": { + "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "dependencies": { + "requires": { "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" } }, - "node_modules/color-name": { + "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/combined-stream": { + "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { + "requires": { "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" } }, - "node_modules/concat-map": { + "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/convert-source-map": { + "convert-source-map": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, - "node_modules/cosmiconfig": { + "cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dependencies": { + "requires": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" } }, - "node_modules/cross-spawn": { + "crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, + "cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, - "dependencies": { + "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" } }, - "node_modules/csstype": { + "csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, - "node_modules/d3-array": { + "d3-array": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", - "dependencies": { + "requires": { "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" } }, - "node_modules/d3-color": { + "d3-color": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "engines": { - "node": ">=12" - } + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==" }, - "node_modules/d3-ease": { + "d3-ease": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", - "engines": { - "node": ">=12" - } + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==" }, - "node_modules/d3-format": { + "d3-format": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", - "engines": { - "node": ">=12" - } + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==" }, - "node_modules/d3-interpolate": { + "d3-interpolate": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", - "dependencies": { + "requires": { "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" } }, - "node_modules/d3-path": { + "d3-path": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "engines": { - "node": ">=12" - } + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==" }, - "node_modules/d3-scale": { + "d3-scale": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", - "dependencies": { + "requires": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" } }, - "node_modules/d3-shape": { + "d3-shape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", - "dependencies": { + "requires": { "d3-path": "^3.1.0" - }, - "engines": { - "node": ">=12" } }, - "node_modules/d3-time": { + "d3-time": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", - "dependencies": { + "requires": { "d3-array": "2 - 3" - }, - "engines": { - "node": ">=12" } }, - "node_modules/d3-time-format": { + "d3-time-format": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", - "dependencies": { + "requires": { "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" } }, - "node_modules/d3-timer": { + "d3-timer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "engines": { - "node": ">=12" - } + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==" }, - "node_modules/data-view-buffer": { + "data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/data-view-byte-length": { + "data-view-byte-length": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/data-view-byte-offset": { + "data-view-byte-offset": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/date-fns": { + "date-fns": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==" }, - "node_modules/debug": { + "debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dependencies": { + "requires": { "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } } }, - "node_modules/decimal.js-light": { + "decimal.js-light": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" }, - "node_modules/deep-is": { + "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/define-data-property": { + "define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, - "dependencies": { + "requires": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties": { + "define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, - "dependencies": { + "requires": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { + "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, - "node_modules/detect-libc": { + "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "dev": true, - "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } + "optional": true }, - "node_modules/doctrine": { + "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "dependencies": { + "requires": { "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" } }, - "node_modules/dom-helpers": { + "dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dependencies": { + "requires": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" } }, - "node_modules/dotenv": { + "dotenv": { "version": "16.5.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", - "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==" }, - "node_modules/dunder-proto": { + "dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": { + "requires": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/electron-to-chromium": { + "electron-to-chromium": { "version": "1.5.142", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.142.tgz", "integrity": "sha512-Ah2HgkTu/9RhTDNThBtzu2Wirdy4DC9b0sMT1pUhbkZQ5U/iwmE+PHZX1MpjD5IkJCc2wSghgGG/B04szAx07w==", "dev": true }, - "node_modules/error-ex": { + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + }, + "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { + "requires": { "is-arrayish": "^0.2.1" } }, - "node_modules/es-abstract": { + "es-abstract": { "version": "1.23.9", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", "dev": true, - "dependencies": { + "requires": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", @@ -2943,36 +2033,24 @@ "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.18" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-define-property": { + "es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "engines": { - "node": ">= 0.4" - } + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" }, - "node_modules/es-errors": { + "es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, - "node_modules/es-iterator-helpers": { + "es-iterator-helpers": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", @@ -2989,78 +2067,53 @@ "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/es-object-atoms": { + "es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dependencies": { + "requires": { "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/es-set-tostringtag": { + "es-set-tostringtag": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dependencies": { + "requires": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/es-shim-unscopables": { + "es-shim-unscopables": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, - "dependencies": { + "requires": { "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/es-to-primitive": { + "es-to-primitive": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, - "dependencies": { + "requires": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild": { + "esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { + "requires": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", @@ -3086,33 +2139,23 @@ "@esbuild/win32-x64": "0.21.5" } }, - "node_modules/escalade": { + "escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/escape-string-regexp": { + "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, - "node_modules/eslint": { + "eslint": { "version": "8.57.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, - "dependencies": { + "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", @@ -3152,22 +2195,24 @@ "strip-ansi": "^6.0.1", "text-table": "^0.2.0" }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "dependencies": { + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + } } }, - "node_modules/eslint-plugin-react": { + "eslint-plugin-react": { "version": "7.37.5", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", "dev": true, - "dependencies": { + "requires": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", @@ -3187,390 +2232,259 @@ "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + } } }, - "node_modules/eslint-plugin-react-hooks": { + "eslint-plugin-react-hooks": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } + "dev": true }, - "node_modules/eslint-plugin-react-refresh": { + "eslint-plugin-react-refresh": { "version": "0.4.20", "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.20.tgz", "integrity": "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA==", - "dev": true, - "peerDependencies": { - "eslint": ">=8.40" - } + "dev": true }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-scope": { + "eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, - "dependencies": { + "requires": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-visitor-keys": { + "eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } + "dev": true }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { + "espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, - "dependencies": { + "requires": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" } }, - "node_modules/esquery": { + "esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "dependencies": { + "requires": { "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" } }, - "node_modules/esrecurse": { + "esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, - "dependencies": { + "requires": { "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" } }, - "node_modules/estraverse": { + "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } + "dev": true }, - "node_modules/esutils": { + "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/eventemitter3": { + "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, - "node_modules/fast-deep-equal": { + "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/fast-equals": { + "fast-equals": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", - "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", - "engines": { - "node": ">=6.0.0" - } + "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==" }, - "node_modules/fast-json-stable-stringify": { + "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/fast-levenshtein": { + "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, - "node_modules/fastq": { + "fastq": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, - "dependencies": { + "requires": { "reusify": "^1.0.4" } }, - "node_modules/file-entry-cache": { + "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, - "dependencies": { + "requires": { "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/fill-range": { + "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "optional": true, - "dependencies": { + "requires": { "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" } }, - "node_modules/find-root": { + "find-root": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" }, - "node_modules/find-up": { + "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "dependencies": { + "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache": { + "flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, - "dependencies": { + "requires": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/flatted": { + "flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true }, - "node_modules/follow-redirects": { + "follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" }, - "node_modules/for-each": { + "for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, - "dependencies": { + "requires": { "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/form-data": { + "form-data": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", - "dependencies": { + "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" } }, - "node_modules/fs.realpath": { + "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fsevents": { + "fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "optional": true }, - "node_modules/function-bind": { + "function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, - "node_modules/function.prototype.name": { + "function.prototype.name": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functions-have-names": { + "functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/gensync": { + "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } + "dev": true }, - "node_modules/get-intrinsic": { + "get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dependencies": { + "requires": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", @@ -3581,1424 +2495,1180 @@ "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-proto": { + "get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": { + "requires": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/get-symbol-description": { + "get-symbol-description": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { + "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "dependencies": { + "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { + "glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "dependencies": { + "requires": { "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" } }, - "node_modules/globals": { + "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, - "node_modules/globalthis": { + "globalthis": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, - "dependencies": { + "requires": { "define-properties": "^1.2.1", "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { + "gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" }, - "node_modules/graphemer": { + "graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has-bigints": { + "has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/has-flag": { + "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/has-property-descriptors": { + "has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, - "dependencies": { + "requires": { "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { + "has-proto": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, - "dependencies": { + "requires": { "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { + "has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" }, - "node_modules/has-tostringtag": { + "has-tostringtag": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { + "requires": { "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hasown": { + "hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { + "requires": { "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/hoist-non-react-statics": { + "hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { + "requires": { "react-is": "^16.7.0" } }, - "node_modules/ignore": { + "ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "engines": { - "node": ">= 4" - } + "dev": true }, - "node_modules/immer": { + "immer": { "version": "10.1.1", "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", - "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==" }, - "node_modules/immutable": { + "immutable": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.1.tgz", "integrity": "sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==", "dev": true }, - "node_modules/import-fresh": { + "import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dependencies": { + "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/imurmurhash": { + "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } + "dev": true }, - "node_modules/inflight": { + "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, - "dependencies": { + "requires": { "once": "^1.3.0", "wrappy": "1" } }, - "node_modules/inherits": { + "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "node_modules/internal-slot": { + "internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, - "dependencies": { + "requires": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/internmap": { + "internmap": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", - "engines": { - "node": ">=12" - } + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==" }, - "node_modules/is-array-buffer": { + "is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { + "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, - "node_modules/is-async-function": { + "is-async-function": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, - "dependencies": { + "requires": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-bigint": { + "is-bigint": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, - "dependencies": { + "requires": { "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-boolean-object": { + "is-boolean-object": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-callable": { + "is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/is-core-module": { + "is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dependencies": { + "requires": { "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-view": { + "is-data-view": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-date-object": { + "is-date-object": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-extglob": { + "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/is-finalizationregistry": { + "is-finalizationregistry": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-generator-function": { + "is-generator-function": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "get-proto": "^1.0.0", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-glob": { + "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, - "dependencies": { + "requires": { "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" } }, - "node_modules/is-map": { + "is-map": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/is-number": { + "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "optional": true, - "engines": { - "node": ">=0.12.0" - } + "optional": true }, - "node_modules/is-number-object": { + "is-number-object": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { + "is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/is-regex": { + "is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-set": { + "is-set": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/is-shared-array-buffer": { + "is-shared-array-buffer": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-string": { + "is-string": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-symbol": { + "is-symbol": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typed-array": { + "is-typed-array": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, - "dependencies": { + "requires": { "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakmap": { + "is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/is-weakref": { + "is-weakref": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakset": { + "is-weakset": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isarray": { + "isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true }, - "node_modules/isexe": { + "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, - "node_modules/iterator.prototype": { + "iterator.prototype": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, - "dependencies": { + "requires": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/js-tokens": { + "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, - "node_modules/js-yaml": { + "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "dependencies": { + "requires": { "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsesc": { + "jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==" }, - "node_modules/json-buffer": { + "json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, - "node_modules/json-parse-even-better-errors": { + "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, - "node_modules/json-schema-traverse": { + "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, - "node_modules/json-stable-stringify-without-jsonify": { + "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "node_modules/json5": { + "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/jsx-ast-utils": { + "jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", "dev": true, - "dependencies": { + "requires": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" } }, - "node_modules/keyv": { + "keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, - "dependencies": { + "requires": { "json-buffer": "3.0.1" } }, - "node_modules/levn": { + "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "dependencies": { + "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" } }, - "node_modules/lines-and-columns": { + "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, - "node_modules/locate-path": { + "linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "requires": { + "uc.micro": "^2.0.0" + } + }, + "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "dependencies": { + "requires": { "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { + "lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash.merge": { + "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/loose-envify": { + "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==", - "dependencies": { + "requires": { "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" } }, - "node_modules/lru-cache": { + "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "dependencies": { + "requires": { "yallist": "^3.0.2" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "engines": { - "node": ">= 0.4" + "markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "requires": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" } }, - "node_modules/micromatch": { + "marked": { + "version": "15.0.11", + "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.11.tgz", + "integrity": "sha512-1BEXAU2euRCG3xwgLVT1y0xbJEld1XOrmRJpUwRCcy7rxhSCwMrmEu9LXoPhHSCJG41V7YcQ2mjKRr5BA3ITIA==" + }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" + }, + "mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" + }, + "micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "optional": true, - "dependencies": { + "requires": { "braces": "^3.0.3", "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" } }, - "node_modules/mime-db": { + "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, - "node_modules/mime-types": { + "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { + "requires": { "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" } }, - "node_modules/minimatch": { + "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "dependencies": { + "requires": { "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" } }, - "node_modules/ms": { + "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/nanoid": { + "nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } + "dev": true }, - "node_modules/natural-compare": { + "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/node-addon-api": { + "node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, "optional": true }, - "node_modules/node-releases": { + "node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, - "node_modules/object-assign": { + "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, - "node_modules/object-inspect": { + "object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "dev": true }, - "node_modules/object-keys": { + "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } + "dev": true }, - "node_modules/object.assign": { + "object.assign": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.entries": { + "object.entries": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/object.fromentries": { + "object.fromentries": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.values": { + "object.values": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { + "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "dependencies": { + "requires": { "wrappy": "1" } }, - "node_modules/optionator": { + "optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, - "dependencies": { + "requires": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" } }, - "node_modules/own-keys": { + "orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==" + }, + "own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "dev": true, - "dependencies": { + "requires": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-limit": { + "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, - "dependencies": { + "requires": { "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { + "p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, - "dependencies": { + "requires": { "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parent-module": { + "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { + "requires": { "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" } }, - "node_modules/parse-json": { + "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { + "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-exists": { + "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/path-is-absolute": { + "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/path-key": { + "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/path-parse": { + "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, - "node_modules/path-type": { + "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, - "node_modules/picocolors": { + "picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, - "node_modules/picomatch": { + "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "optional": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } + "optional": true }, - "node_modules/possible-typed-array-names": { + "possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, - "engines": { - "node": ">= 0.4" - } + "dev": true }, - "node_modules/postcss": { + "postcss": { "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { + "requires": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" } }, - "node_modules/prelude-ls": { + "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } + "dev": true }, - "node_modules/prop-types": { + "prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { + "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, - "node_modules/proxy-from-env": { + "prosemirror-changeset": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.2.1.tgz", + "integrity": "sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==", + "requires": { + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-collab": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", + "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", + "requires": { + "prosemirror-state": "^1.0.0" + } + }, + "prosemirror-commands": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", + "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.10.2" + } + }, + "prosemirror-dropcursor": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", + "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", + "requires": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "prosemirror-gapcursor": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz", + "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==", + "requires": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "prosemirror-history": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", + "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", + "requires": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "prosemirror-inputrules": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.0.tgz", + "integrity": "sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA==", + "requires": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-keymap": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.2.tgz", + "integrity": "sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==", + "requires": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "prosemirror-markdown": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.2.tgz", + "integrity": "sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==", + "requires": { + "@types/markdown-it": "^14.0.0", + "markdown-it": "^14.0.0", + "prosemirror-model": "^1.25.0" + } + }, + "prosemirror-menu": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz", + "integrity": "sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==", + "requires": { + "crelt": "^1.0.0", + "prosemirror-commands": "^1.0.0", + "prosemirror-history": "^1.0.0", + "prosemirror-state": "^1.0.0" + } + }, + "prosemirror-model": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.1.tgz", + "integrity": "sha512-AUvbm7qqmpZa5d9fPKMvH1Q5bqYQvAZWOGRvxsB6iFLyycvC9MwNemNVjHVrWgjaoxAfY8XVg7DbvQ/qxvI9Eg==", + "requires": { + "orderedmap": "^2.0.0" + } + }, + "prosemirror-schema-basic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", + "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", + "requires": { + "prosemirror-model": "^1.25.0" + } + }, + "prosemirror-schema-list": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" + } + }, + "prosemirror-state": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz", + "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "prosemirror-tables": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.7.1.tgz", + "integrity": "sha512-eRQ97Bf+i9Eby99QbyAiyov43iOKgWa7QCGly+lrDt7efZ1v8NWolhXiB43hSDGIXT1UXgbs4KJN3a06FGpr1Q==", + "requires": { + "prosemirror-keymap": "^1.2.2", + "prosemirror-model": "^1.25.0", + "prosemirror-state": "^1.4.3", + "prosemirror-transform": "^1.10.3", + "prosemirror-view": "^1.39.1" + } + }, + "prosemirror-trailing-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", + "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", + "requires": { + "@remirror/core-constants": "3.0.0", + "escape-string-regexp": "^4.0.0" + } + }, + "prosemirror-transform": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.4.tgz", + "integrity": "sha512-pwDy22nAnGqNR1feOQKHxoFkkUtepoFAd3r2hbEDsnf4wp57kKA36hXsB3njA9FtONBEwSDnDeCiJe+ItD+ykw==", + "requires": { + "prosemirror-model": "^1.21.0" + } + }, + "prosemirror-view": { + "version": "1.39.2", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.39.2.tgz", + "integrity": "sha512-BmOkml0QWNob165gyUxXi5K5CVUgVPpqMEAAml/qzgKn9boLUWVPzQ6LtzXw8Cn1GtRQX4ELumPxqtLTDaAKtg==", + "requires": { + "prosemirror-model": "^1.20.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, + "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "node_modules/punycode": { + "punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } + "dev": true }, - "node_modules/queue-microtask": { + "punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==" + }, + "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "dev": true }, - "node_modules/react": { + "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==", - "dependencies": { + "requires": { "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" } }, - "node_modules/react-dom": { + "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==", - "dependencies": { + "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" } }, - "node_modules/react-is": { + "react-email-editor": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/react-email-editor/-/react-email-editor-1.7.11.tgz", + "integrity": "sha512-AyoKKtMEPhKdqUxFX1hyJMvEO+E5fzk88uNVGHhK1ymhLpcghYLkz1+pXKLcByjR6LHkfEbrCmoYFG8zyripug==", + "requires": { + "unlayer-types": "^1.251.0" + } + }, + "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==" }, - "node_modules/react-redux": { + "react-redux": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", - "dependencies": { + "requires": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" - }, - "peerDependencies": { - "@types/react": "^18.2.25 || ^19", - "react": "^18.0 || ^19", - "redux": "^5.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "redux": { - "optional": true - } } }, - "node_modules/react-refresh": { + "react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/react-router": { + "react-router": { "version": "6.30.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz", "integrity": "sha512-D3X8FyH9nBcTSHGdEKurK7r8OYE1kKFn3d/CF+CoxbSHkxU7o37+Uh7eAHRXr6k2tSExXYO++07PeXJtA/dEhQ==", - "dependencies": { + "requires": { "@remix-run/router": "1.23.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" } }, - "node_modules/react-router-dom": { + "react-router-dom": { "version": "6.30.0", "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.0.tgz", "integrity": "sha512-x30B78HV5tFk8ex0ITwzC9TTZMua4jGyA9IUlH1JLQYQTFyxr/ZxwOJq7evg1JX1qGVUcvhsmQSKdPncQrjTgA==", - "dependencies": { + "requires": { "@remix-run/router": "1.23.0", "react-router": "6.30.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" } }, - "node_modules/react-smooth": { + "react-smooth": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", - "dependencies": { + "requires": { "fast-equals": "^5.0.1", "prop-types": "^15.8.1", "react-transition-group": "^4.4.5" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/react-transition-group": { + "react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dependencies": { + "requires": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", "loose-envify": "^1.4.0", "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" } }, - "node_modules/readdirp": { + "readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } + "dev": true }, - "node_modules/recharts": { + "recharts": { "version": "2.15.3", "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.3.tgz", "integrity": "sha512-EdOPzTwcFSuqtvkDoaM5ws/Km1+WTAO2eizL7rqiG0V2UVhTnz0m7J2i0CjVPUCdEkZImaWvXLbZDS2H5t6GFQ==", - "dependencies": { + "requires": { "clsx": "^2.0.0", "eventemitter3": "^4.0.1", "lodash": "^4.17.21", @@ -5008,46 +3678,38 @@ "tiny-invariant": "^1.3.1", "victory-vendor": "^36.6.8" }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + "dependencies": { + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + } } }, - "node_modules/recharts-scale": { + "recharts-scale": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", - "dependencies": { + "requires": { "decimal.js-light": "^2.4.1" } }, - "node_modules/recharts/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, - "node_modules/redux": { + "redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, - "node_modules/redux-thunk": { + "redux-thunk": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", - "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", - "peerDependencies": { - "redux": "^5.0.0" - } + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==" }, - "node_modules/reflect.getprototypeof": { + "reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", @@ -5056,113 +3718,68 @@ "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerator-runtime": { + "regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, - "node_modules/regexp.prototype.flags": { + "regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/reselect": { + "reselect": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" }, - "node_modules/resolve": { + "resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dependencies": { + "requires": { "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-from": { + "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, - "node_modules/reusify": { + "reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/rimraf": { + "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, - "dependencies": { + "requires": { "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rollup": { + "rollup": { "version": "4.40.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.0.tgz", "integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==", "dev": true, - "dependencies": { - "@types/estree": "1.0.7" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { + "requires": { "@rollup/rollup-android-arm-eabi": "4.40.0", "@rollup/rollup-android-arm64": "4.40.0", "@rollup/rollup-darwin-arm64": "4.40.0", @@ -5183,283 +3800,201 @@ "@rollup/rollup-win32-arm64-msvc": "4.40.0", "@rollup/rollup-win32-ia32-msvc": "4.40.0", "@rollup/rollup-win32-x64-msvc": "4.40.0", + "@types/estree": "1.0.7", "fsevents": "~2.3.2" } }, - "node_modules/run-parallel": { + "rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==" + }, + "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { + "requires": { "queue-microtask": "^1.2.2" } }, - "node_modules/safe-array-concat": { + "safe-array-concat": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-push-apply": { + "safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, - "dependencies": { + "requires": { "es-errors": "^1.3.0", "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-regex-test": { + "safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sass": { + "sass": { "version": "1.87.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.87.0.tgz", "integrity": "sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==", "dev": true, - "dependencies": { + "requires": { + "@parcel/watcher": "^2.4.1", "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" } }, - "node_modules/scheduler": { + "scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { + "requires": { "loose-envify": "^1.1.0" } }, - "node_modules/semver": { + "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } + "dev": true }, - "node_modules/set-function-length": { + "set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, - "dependencies": { + "requires": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/set-function-name": { + "set-function-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, - "dependencies": { + "requires": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/set-proto": { + "set-proto": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, - "dependencies": { + "requires": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/shebang-command": { + "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "dependencies": { + "requires": { "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/shebang-regex": { + "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } + "dev": true }, - "node_modules/side-channel": { + "side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, - "dependencies": { + "requires": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel-list": { + "side-channel-list": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, - "dependencies": { + "requires": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel-map": { + "side-channel-map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel-weakmap": { + "side-channel-weakmap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/source-map": { + "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" }, - "node_modules/source-map-js": { + "source-map-js": { "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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/string.prototype.matchall": { + "string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", @@ -5473,30 +4008,24 @@ "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.repeat": { + "string.prototype.repeat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", "dev": true, - "dependencies": { + "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, - "node_modules/string.prototype.trim": { + "string.prototype.trim": { "version": "1.2.10", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", @@ -5504,188 +4033,147 @@ "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimend": { + "string.prototype.trimend": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimstart": { + "string.prototype.trimstart": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/strip-ansi": { + "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "dependencies": { + "requires": { "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" } }, - "node_modules/strip-json-comments": { + "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "dev": true }, - "node_modules/stylis": { + "stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, - "node_modules/supports-color": { + "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "dependencies": { + "requires": { "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { + "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, - "node_modules/text-table": { + "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/tiny-invariant": { + "tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" }, - "node_modules/to-regex-range": { + "tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "requires": { + "@popperjs/core": "^2.9.0" + } + }, + "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "optional": true, - "dependencies": { + "requires": { "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" } }, - "node_modules/type-check": { + "turndown": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz", + "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==", + "requires": { + "@mixmark-io/domino": "^2.2.0" + } + }, + "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, - "dependencies": { + "requires": { "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" } }, - "node_modules/type-fest": { + "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "dev": true }, - "node_modules/typed-array-buffer": { + "typed-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" } }, - "node_modules/typed-array-byte-length": { + "typed-array-byte-length": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-array-byte-offset": { + "typed-array-byte-offset": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, - "dependencies": { + "requires": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", @@ -5693,104 +4181,73 @@ "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-array-length": { + "typed-array-length": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, - "dependencies": { + "requires": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unbox-primitive": { + "uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==" + }, + "unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/update-browserslist-db": { + "unlayer-types": { + "version": "1.251.0", + "resolved": "https://registry.npmjs.org/unlayer-types/-/unlayer-types-1.251.0.tgz", + "integrity": "sha512-HPu4I6+mq8kSEHvtzOb8OUsxw4mQagKB4d+Ukg3Vp6OVWibwi6GGdDpsI1xKXAYcrIGLgKrOAzJ3MfD98HRCLA==" + }, + "update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { + "requires": { "escalade": "^3.2.0", "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" } }, - "node_modules/uri-js": { + "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "dependencies": { + "requires": { "punycode": "^2.1.0" } }, - "node_modules/use-sync-external-store": { + "use-sync-external-store": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", - "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==" }, - "node_modules/victory-vendor": { + "victory-vendor": { "version": "36.9.2", "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", - "dependencies": { + "requires": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", @@ -5807,105 +4264,51 @@ "d3-timer": "^3.0.1" } }, - "node_modules/vite": { + "vite": { "version": "5.4.18", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.18.tgz", "integrity": "sha512-1oDcnEp3lVyHCuQ2YFelM4Alm2o91xNoMncRm1U7S+JdYfYOvbiGZ3/CxGttrOu2M/KcGz7cRC2DoNUA6urmMA==", "dev": true, - "dependencies": { + "requires": { "esbuild": "^0.21.3", + "fsevents": "~2.3.3", "postcss": "^8.4.43", "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.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", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } } }, - "node_modules/which": { + "w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, + "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "dependencies": { + "requires": { "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" } }, - "node_modules/which-boxed-primitive": { + "which-boxed-primitive": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, - "dependencies": { + "requires": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-builtin-type": { + "which-builtin-type": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, - "dependencies": { + "requires": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", @@ -5919,38 +4322,26 @@ "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-collection": { + "which-collection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, - "dependencies": { + "requires": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-typed-array": { + "which-typed-array": { "version": "1.1.19", "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, - "dependencies": { + "requires": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", @@ -5958,54 +4349,36 @@ "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/word-wrap": { + "word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "dev": true }, - "node_modules/wrappy": { + "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/yallist": { + "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, - "node_modules/yaml": { + "yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" }, - "node_modules/yocto-queue": { + "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "dev": true } } } diff --git a/frontend/package.json b/frontend/package.json index 4c7061a..8ddcdaf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,12 +19,12 @@ "@stripe/react-stripe-js": "^2.4.0", "@stripe/stripe-js": "^2.2.0", "@tanstack/react-query": "^5.12.2", - "@tanstack/react-query-devtools": "^5.12.2", "axios": "^1.6.2", "date-fns": "^4.1.0", "dotenv": "^16.5.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-email-editor": "^1.7.11", "react-redux": "^9.0.2", "react-router-dom": "^6.20.1", "recharts": "^2.10.3" diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index f384d6d..b218bf0 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,11 +1,13 @@ import { Routes, Route } from 'react-router-dom'; -import { Suspense, lazy } from 'react'; +import { Suspense, lazy, useEffect } from 'react'; import { CircularProgress, Box } from '@mui/material'; -import Notifications from './components/Notifications'; -import ProtectedRoute from './components/ProtectedRoute'; +import Notifications from '@components/Notifications'; +import ProtectedRoute from '@components/ProtectedRoute'; import { StripeProvider } from './context/StripeContext'; +import useBrandingSettings from '@hooks/brandingHooks'; +import imageUtils from '@utils/imageUtils'; -// Layouts +// Import layouts import MainLayout from './layouts/MainLayout'; import AuthLayout from './layouts/AuthLayout'; import AdminLayout from './layouts/AdminLayout'; @@ -40,7 +42,8 @@ const AdminBlogPage = lazy(() => import('@pages/Admin/BlogPage')); const BlogEditPage = lazy(() => import('@pages/Admin/BlogEditPage')); const AdminBlogCommentsPage = lazy(() => import('@pages/Admin/BlogCommentsPage')); const AdminProductReviewsPage = lazy(() => import('@pages/Admin/ProductReviewsPage')); - +const EmailTemplatesPage = lazy(() => import('@pages/Admin/EmailTemplatesPage')); +const BrandingPage = lazy(() => import('@pages/Admin/BrandingPage')); // New Branding Page // Loading component for suspense fallback const LoadingComponent = () => ( @@ -50,6 +53,55 @@ const LoadingComponent = () => ( ); function App() { + // Use the centralized hook to fetch branding settings + const { data: brandingSettings, isLoading } = useBrandingSettings(); + + // Update the document head with branding settings + useEffect(() => { + if (brandingSettings) { + // Update document title + if (brandingSettings?.site_name) { + document.title = brandingSettings?.site_name; + } + // Update favicon if available + if (brandingSettings?.favicon_url) { + // Remove any existing favicon links + const existingLinks = document.querySelectorAll("link[rel*='icon']"); + existingLinks.forEach(link => link.parentNode.removeChild(link)); + + + // Create and add new favicon link + const link = document.createElement('link'); + link.type = 'image/x-icon'; + link.rel = 'shortcut icon'; + link.href = imageUtils.getImageUrl(brandingSettings?.favicon_url); //brandingSettings?.favicon_url; + document.head.appendChild(link); + + // Also add Apple touch icon for iOS devices + const touchIcon = document.createElement('link'); + touchIcon.rel = 'apple-touch-icon'; + touchIcon.href = imageUtils.getImageUrl(brandingSettings?.favicon_url); + document.head.appendChild(touchIcon); + console.log(link); + } + + // Add meta description if available + if (brandingSettings?.site_description) { + // Remove any existing description meta tags + const existingMeta = document.querySelector("meta[name='description']"); + if (existingMeta) { + existingMeta.parentNode.removeChild(existingMeta); + } + + // Create and add new meta description + const meta = document.createElement('meta'); + meta.name = 'description'; + meta.content = brandingSettings?.site_description; + document.head.appendChild(meta); + } + } + }, [brandingSettings]); + return ( }> @@ -124,6 +176,8 @@ function App() { } /> } /> } /> + } /> + } /> {/* New Branding Route */} {/* Catch-all route for 404s */} diff --git a/frontend/src/components/Footer.jsx b/frontend/src/components/Footer.jsx index 70b6621..d1a7ffa 100644 --- a/frontend/src/components/Footer.jsx +++ b/frontend/src/components/Footer.jsx @@ -4,8 +4,15 @@ import FacebookIcon from '@mui/icons-material/Facebook'; import TwitterIcon from '@mui/icons-material/Twitter'; import InstagramIcon from '@mui/icons-material/Instagram'; import { Link as RouterLink } from 'react-router-dom'; +import imageUtils from '@utils/imageUtils'; -const Footer = () => { +const Footer = ({brandingSettings}) => { + + const siteName = brandingSettings?.site_name || 'Rocks, Bones & Sticks'; + const copyrightText = brandingSettings?.copyright_text || + `© ${new Date().getFullYear()} ${siteName}. All rights reserved.`; + const logoUrl = imageUtils.getImageUrl(brandingSettings?.logo_url) + return ( { - - Rocks, Bones & Sticks - + {logoUrl ? ( + + ) : ( + + {siteName} + + )} + - Your premier source for natural curiosities - and unique specimens from my backyards. + { brandingSettings?.site_description || `Your premier source for natural curiosities + and unique specimens from around the world.`} - Quick Links + {brandingSettings?.site_quicklinks_title || `Quick Links`} Home @@ -41,11 +63,14 @@ const Footer = () => { Shop All + + Blog + - Connect With Us + {brandingSettings?.site_connect || `Connect With Us`} @@ -59,14 +84,14 @@ const Footer = () => { - Subscribe to our newsletter for updates on new items and promotions. + {brandingSettings?.site_main_newsletter_desc || `Subscribe to our newsletter for updates on new items and promotions.`} - © {new Date().getFullYear()} Rocks, Bones & Sticks. All rights reserved. + {copyrightText} diff --git a/frontend/src/components/ImageUploader.jsx b/frontend/src/components/ImageUploader.jsx index 47d9193..5998e96 100644 --- a/frontend/src/components/ImageUploader.jsx +++ b/frontend/src/components/ImageUploader.jsx @@ -10,8 +10,6 @@ import { Card, CardMedia, CardActions, - FormControlLabel, - Checkbox, Tooltip } from '@mui/material'; import DeleteIcon from '@mui/icons-material/Delete'; @@ -28,13 +26,15 @@ import imageUtils from '@utils/imageUtils'; * @param {Function} props.onChange - Callback when images change * @param {boolean} props.multiple - Whether to allow multiple images * @param {boolean} props.admin - Whether this is for admin use + * @param {string} props.inputId - Unique ID for the file input element * @returns {JSX.Element} - Image uploader component */ const ImageUploader = ({ images = [], onChange, multiple = true, - admin = true + admin = true, + inputId = `image-upload-input-${Math.random().toString(36).substring(2, 9)}` }) => { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); @@ -129,18 +129,18 @@ const ImageUploader = ({ return ( - {/* Hidden file input */} + {/* Hidden file input with unique ID */} - {/* Upload button */} - + + handleColorChange('light_primary_color', value)} + defaultValue={DEFAULT_COLORS.light.primary} + /> + + handleColorChange('light_secondary_color', value)} + defaultValue={DEFAULT_COLORS.light.secondary} + /> + + + }> + Advanced Colors + + + handleColorChange('light_background_color', value)} + defaultValue={DEFAULT_COLORS.light.background} + /> + + handleColorChange('light_surface_color', value)} + defaultValue={DEFAULT_COLORS.light.surface} + /> + + handleColorChange('light_text_color', value)} + defaultValue={DEFAULT_COLORS.light.text} + /> + + + + + Preview + + + + + + + + + + {/* Dark Mode Colors */} + + + + + Dark Mode Colors + + + + handleColorChange('dark_primary_color', value)} + defaultValue={DEFAULT_COLORS.dark.primary} + /> + + handleColorChange('dark_secondary_color', value)} + defaultValue={DEFAULT_COLORS.dark.secondary} + /> + + + }> + Advanced Colors + + + handleColorChange('dark_background_color', value)} + defaultValue={DEFAULT_COLORS.dark.background} + /> + + handleColorChange('dark_surface_color', value)} + defaultValue={DEFAULT_COLORS.dark.surface} + /> + + handleColorChange('dark_text_color', value)} + defaultValue={DEFAULT_COLORS.dark.text} + /> + + + + + Preview + + + + + + + + + + + + {/* Assets Tab */} + + + + {/* Favicon Upload */} + + + + + Favicon + + + Upload a favicon for your site. This will appear in browser tabs. Recommended size: 32px by 32px. + + + + + {faviconImage.length > 0 && ( + + + Current Favicon + + + + )} + + + + + + {/* Logo Upload */} + + + + + Logo + + + Upload your site logo. Recommended size: 200px by 50px. + + + + + {logoImage.length > 0 && ( + + + Current Logo + + + + )} + + + + + + + + + + + + + {/* Notification */} + + + {notification.message} + + + + ); +}; + +// TabPanel component +function TabPanel(props) { + const { children, value, index, ...other } = props; + + return ( + + ); +} + +export default BrandingPage; \ No newline at end of file diff --git a/frontend/src/pages/Admin/EmailTemplatesPage.jsx b/frontend/src/pages/Admin/EmailTemplatesPage.jsx new file mode 100644 index 0000000..69ac312 --- /dev/null +++ b/frontend/src/pages/Admin/EmailTemplatesPage.jsx @@ -0,0 +1,660 @@ +import React, { useState, useEffect, useRef } from 'react'; +import { + Box, + Typography, + Paper, + Tabs, + Tab, + TextField, + Button, + Grid, + Divider, + CircularProgress, + Alert, + IconButton, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Accordion, + AccordionSummary, + AccordionDetails, + List, + ListItem, + ListItemText, + Chip, + Tooltip, + Card, + CardContent +} from '@mui/material'; +import { + Add as AddIcon, + Delete as DeleteIcon, + Edit as EditIcon, + Save as SaveIcon, + Visibility as PreviewIcon, + ExpandMore as ExpandMoreIcon, + FormatBold as BoldIcon, + FormatItalic as FormatItalicIcon, + FormatListBulleted as BulletListIcon, + FormatListNumbered as NumberedListIcon, + Link as LinkIcon, + Title as TitleIcon, + Info as InfoIcon +} from '@mui/icons-material'; +import EmailEditor from 'react-email-editor'; +import { useAdminSettingsByCategory, useDeleteSetting, useUpdateSetting } from '../../hooks/settingsAdminHooks'; + +// Available email template types +const EMAIL_TYPES = [ + { id: 'login_code', name: 'Login Code', description: 'Sent when a user requests a login code' }, + { id: 'shipping_notification', name: 'Shipping Notification', description: 'Sent when an order is shipped' }, + { id: 'order_confirmation', name: 'Order Confirmation', description: 'Sent when an order is placed' }, + { id: 'low_stock_alert', name: 'Low Stock Alert', description: 'Sent when product stock falls below threshold' }, + { id: 'welcome_email', name: 'Welcome Email', description: 'Sent when a user registers for the first time' }, + { id: 'custom', name: 'Custom Template', description: 'A custom email template for any purpose' } +]; + +// Template variable placeholders for each email type +const TEMPLATE_VARIABLES = { + login_code: [ + { key: '{{code}}', description: 'The login verification code' }, + { key: '{{loginLink}}', description: 'Direct login link with the code' }, + { key: '{{email}}', description: 'User\'s email address' } + ], + shipping_notification: [ + { key: '{{first_name}}', description: 'Customer\'s first name' }, + { key: '{{order_id}}', description: 'Order identifier' }, + { key: '{{tracking_number}}', description: 'Shipping tracking number' }, + { key: '{{carrier}}', description: 'Shipping carrier name' }, + { key: '{{tracking_link}}', description: 'Link to track the package' }, + { key: '{{shipped_date}}', description: 'Date the order was shipped' }, + { key: '{{estimated_delivery}}', description: 'Estimated delivery date/time' }, + { key: '{{items_html}}', description: 'HTML table of ordered items' }, + { key: '{{customer_message}}', description: 'Optional message from staff' } + ], + order_confirmation: [ + { key: '{{first_name}}', description: 'Customer\'s first name' }, + { key: '{{order_id}}', description: 'Order identifier' }, + { key: '{{order_date}}', description: 'Date the order was placed' }, + { key: '{{order_total}}', description: 'Total amount of the order' }, + { key: '{{shipping_address}}', description: 'Shipping address' }, + { key: '{{items_html}}', description: 'HTML table of ordered items' } + ], + low_stock_alert: [ + { key: '{{product_name}}', description: 'Name of the product low in stock' }, + { key: '{{current_stock}}', description: 'Current stock quantity' }, + { key: '{{threshold}}', description: 'Low stock threshold' } + ], + welcome_email: [ + { key: '{{first_name}}', description: 'User\'s first name' }, + { key: '{{email}}', description: 'User\'s email address' } + ], + custom: [] // Custom templates might have any variables +}; + +// Sample placeholder data for preview +const PREVIEW_DATA = { + login_code: { + code: '123456', + loginLink: 'https://example.com/verify?code=123456&email=user@example.com', + email: 'user@example.com' + }, + shipping_notification: { + first_name: 'Jane', + order_id: 'ORD-1234567', + tracking_number: 'TRK123456789', + carrier: 'FedEx', + tracking_link: 'https://www.fedex.com/track?123456789', + shipped_date: '2025-04-29', + estimated_delivery: '2-3 business days', + items_html: ` + + Amethyst Geode + 1 + $49.99 + $49.99 + + + Driftwood Piece + 2 + $14.99 + $29.98 + + `, + customer_message: 'Thank you for your order! We packaged it with extra care.' + }, + order_confirmation: { + first_name: 'John', + order_id: 'ORD-9876543', + order_date: '2025-04-29', + order_total: '$94.97', + shipping_address: '123 Main St, Anytown, CA 12345', + items_html: ` + + Polished Labradorite + 1 + $29.99 + $29.99 + + + Fossil Fish + 1 + $64.98 + $64.98 + + ` + }, + low_stock_alert: { + product_name: 'Amethyst Geode', + current_stock: '2', + threshold: '5' + }, + welcome_email: { + first_name: 'Emily', + email: 'emily@example.com' + }, + custom: {} +}; + +// Default templates +const DEFAULT_TEMPLATES = { + login_code: { + // Simplified template structure for React Email Editor + body: { + rows: [ + { + cells: [1], + columns: [ + { + contents: [ + { + type: "text", + values: { + containerPadding: "10px", + textAlign: "left", + text: "

Your login code is: {{code}}

This code will expire in 15 minutes.

Or click here to log in directly.

" + } + } + ] + } + ] + } + ] + } + }, + shipping_notification: { + // Simplified template - the actual structure would be more complex in the real editor + body: { + rows: [ + { + cells: [1], + columns: [ + { + contents: [ + { + type: "text", + values: { + containerPadding: "10px", + textAlign: "center", + text: "

Your Order Has Shipped!

Order #{{order_id}}

" + } + } + ] + } + ] + }, + { + cells: [1], + columns: [ + { + contents: [ + { + type: "text", + values: { + containerPadding: "10px", + textAlign: "left", + text: "

Hello {{first_name}},

Good news! Your order has been shipped and is on its way to you.

" + } + } + ] + } + ] + } + ] + } + }, + welcome_email: { + // Simplified template + body: { + rows: [ + { + cells: [1], + columns: [ + { + contents: [ + { + type: "text", + values: { + containerPadding: "10px", + textAlign: "center", + text: "

Welcome to Rocks, Bones & Sticks!

" + } + } + ] + } + ] + }, + { + cells: [1], + columns: [ + { + contents: [ + { + type: "text", + values: { + containerPadding: "10px", + textAlign: "left", + text: "

Hello {{first_name}},

Thank you for creating an account with us. We're excited to have you join our community!

" + } + } + ] + } + ] + } + ] + } + } +}; + +const EmailTemplatesPage = () => { + const [activeTab, setActiveTab] = useState(0); + const [editingTemplate, setEditingTemplate] = useState(null); + const [templateList, setTemplateList] = useState([]); + const [previewDialogOpen, setPreviewDialogOpen] = useState(false); + const [previewContent, setPreviewContent] = useState(''); + + const emailEditorRef = useRef(null); + + const { data: emailSettings, isLoading, error } = useAdminSettingsByCategory('email_templates'); + const deleteSettingMutation = useDeleteSetting(); + const updateSetting = useUpdateSetting(); + + useEffect(() => { + if (emailSettings) { + const templates = emailSettings.map(setting => { + try { + const templateData = JSON.parse(setting.value); + return { id: setting.key, ...templateData }; + } catch { + return null; + } + }).filter(Boolean); + setTemplateList(templates); + } + }, [emailSettings]); + + const handleTabChange = (e, newValue) => { + // Only allow tab switching if not currently editing a template + if (!editingTemplate) { + setActiveTab(newValue); + } + }; + + const handleEditTemplate = (template) => { + setEditingTemplate({ ...template }); + + // If the email editor is loaded, set its design + if (emailEditorRef.current && template.design) { + setTimeout(() => { + emailEditorRef.current.editor.loadDesign(template.design); + }, 500); + } + }; + + const handleSaveTemplate = async () => { + if (!editingTemplate || !emailEditorRef.current) return; + + try { + // Save the design from the email editor + emailEditorRef.current.editor.exportHtml(async (data) => { + const { design, html } = data; + + // Update the template with the new design and HTML + const updatedTemplate = { + ...editingTemplate, + design: design, // Store the design JSON for future editing + content: html, // Store the generated HTML for rendering + updatedAt: new Date().toISOString() + }; + + await updateSetting.mutateAsync({ + key: updatedTemplate.id, + value: JSON.stringify(updatedTemplate), + category: 'email_templates' + }); + + setTemplateList(prev => prev.map(t => t.id === updatedTemplate.id ? updatedTemplate : t)); + setEditingTemplate(null); + }); + } catch (error) { + console.error('Failed to save template:', error); + } + }; + + const handlePreviewTemplate = (template) => { + if (template.content) { + setPreviewContent(` +
+
Subject: ${template.subject}
+ ${template.content} +
+ `); + setPreviewDialogOpen(true); + } else if (emailEditorRef.current) { + emailEditorRef.current.editor.exportHtml((data) => { + const { html } = data; + setPreviewContent(` +
+
Subject: ${template.subject}
+ ${html} +
+ `); + setPreviewDialogOpen(true); + }); + } + }; + + const handleCreateTemplate = () => { + const templateType = EMAIL_TYPES[activeTab === 0 ? 5 : activeTab - 1].id; + const templateName = EMAIL_TYPES[activeTab === 0 ? 5 : activeTab - 1].name; + + // Create default HTML content for the new template + let defaultContent = `

Your ${templateName}

Start editing this template to customize it for your needs.

`; + + // Add sample placeholders based on template type + if (templateType === 'login_code') { + defaultContent = `

Your login code is: {{code}}

+

This code will expire in 15 minutes.

+

Or click here to log in directly.

`; + } else if (templateType === 'shipping_notification') { + defaultContent = `

Your Order Has Shipped!

+

Hello {{first_name}},

+

Good news! Your order #{{order_id}} has been shipped and is on its way to you.

`; + } else if (templateType === 'welcome_email') { + defaultContent = `

Welcome to Rocks, Bones & Sticks!

+

Hello {{first_name}},

+

Thank you for creating an account with us. We're excited to have you join our community!

`; + } + + const newTemplate = { + id: `email_template_${Date.now()}`, + name: `New ${templateName}`, + type: templateType, + subject: `Your ${templateName}`, + content: defaultContent, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString() + }; + + setEditingTemplate(newTemplate); + }; + + const onEditorReady = () => { + // You can perform any setup actions here when the editor is loaded + console.log('Email editor is ready'); + + // If there's a template being edited, load its design + if (editingTemplate?.design && emailEditorRef.current) { + emailEditorRef.current.editor.loadDesign(editingTemplate.design); + } + // If there's no design but we have HTML content, create a default design with that content + else if (editingTemplate?.content && emailEditorRef.current) { + const defaultDesign = { + body: { + rows: [ + { + cells: [1], + columns: [ + { + contents: [ + { + type: "html", + values: { + html: editingTemplate.content, + containerPadding: "10px" + } + } + ] + } + ] + } + ] + } + }; + emailEditorRef.current.editor.loadDesign(defaultDesign); + } + // If it's a new template with no design or content, load the default template + else if (editingTemplate && emailEditorRef.current) { + // Try to load a default template for the template type + const defaultTemplate = DEFAULT_TEMPLATES[editingTemplate.type] || { + body: { + rows: [ + { + cells: [1], + columns: [ + { + contents: [ + { + type: "html", + values: { + html: "

Your " + editingTemplate.name + "

Start editing your email template here.

", + containerPadding: "10px" + } + } + ] + } + ] + } + ] + } + }; + emailEditorRef.current.editor.loadDesign(defaultTemplate); + } + }; + + if (isLoading) return ; + if (error) return Error loading templates.; + let first_name = "{{first_name}}" + return ( + + Email Templates + + + + + {EMAIL_TYPES.map(type => )} + + {activeTab > 0 && ( + + )} + + + + {!editingTemplate ? ( + + {templateList.length > 0 ? ( + templateList + .filter(template => activeTab === 0 || template.type === EMAIL_TYPES[activeTab - 1]?.id) + .map(template => ( + + + + + {template.name} + t.id === template.type)?.name || 'Unknown'} + size="small" + color="primary" + variant="outlined" + /> + + + Last updated: {new Date(template.updatedAt).toLocaleString()} + + + Subject: {template.subject} + + + + + + + + + )) + ) : ( + + + No email templates found. Click "Create Template" to create your first template. + + + )} + + ) : ( + // Edit view + + + + + setEditingTemplate(prev => ({ ...prev, name: e.target.value }))} + /> + + + setEditingTemplate(prev => ({ ...prev, subject: e.target.value }))} + /> + + + + + + + Email Content + + + + + Tips for creating effective email templates: +
    +
  1. For best results, design your emails visually in Figma first
  2. +
  3. Export your design as HTML or use an email-specific design tool
  4. +
  5. Copy the HTML into an HTML block in this editor
  6. +
  7. Add dynamic variables like {`{{first_name}}`} as text where needed
  8. +
  9. Reference "Available Template Variables" below this tip
  10. +
+
+
+ + + + }> + Available Template Variables + + + + You can use these variables in your message. They will be replaced when the email is sent. + + + {TEMPLATE_VARIABLES[editingTemplate.type]?.map(variable => ( + + + + ))} + + + + + + + + + + + + + +
+
+ )} + + {/* Preview Dialog */} + setPreviewDialogOpen(false)} maxWidth="md" fullWidth> + Email Preview + + + + + + + +
+ ); +}; + +export default EmailTemplatesPage; \ No newline at end of file diff --git a/frontend/src/pages/Admin/OrdersPage.jsx b/frontend/src/pages/Admin/OrdersPage.jsx index 983ce4d..a9ddce9 100644 --- a/frontend/src/pages/Admin/OrdersPage.jsx +++ b/frontend/src/pages/Admin/OrdersPage.jsx @@ -47,6 +47,8 @@ import apiClient from '@services/api'; import { format } from 'date-fns'; import ProductImage from '@components/ProductImage'; import OrderStatusDialog from '@components/OrderStatusDialog'; +import useBrandingSettings from '@hooks/brandingHooks'; +const { data: brandingSettings } = useBrandingSettings(); const AdminOrdersPage = () => { const [page, setPage] = useState(0); @@ -56,6 +58,7 @@ const AdminOrdersPage = () => { const [selectedOrder, setSelectedOrder] = useState(null); const [orderDetails, setOrderDetails] = useState(null); const [statusDialogOpen, setStatusDialogOpen] = useState(false); + const { data: brandingSettings } = useBrandingSettings(); const [newStatus, setNewStatus] = useState(''); const queryClient = useQueryClient(); diff --git a/frontend/src/pages/HomePage.jsx b/frontend/src/pages/HomePage.jsx index 4614194..d259c66 100644 --- a/frontend/src/pages/HomePage.jsx +++ b/frontend/src/pages/HomePage.jsx @@ -3,10 +3,12 @@ import { Box, Typography, Button, Grid, Card, CardMedia, CardContent, Container import { Link as RouterLink } from 'react-router-dom'; import { useProducts, useCategories } from '@hooks/apiHooks'; import imageUtils from '@utils/imageUtils'; +import useBrandingSettings from '@hooks/brandingHooks'; const HomePage = () => { const { data: products, isLoading: productsLoading } = useProducts({ limit: 6 }); const { data: categories, isLoading: categoriesLoading } = useCategories(); + const { data: brandingSettings } = useBrandingSettings(); return ( @@ -25,10 +27,10 @@ const HomePage = () => { > - Discover Natural Wonders + {brandingSettings?.site_main_page_title || `Discover Natural Wonders`} - Unique rocks, bones, and sticks from around my backyards + {brandingSettings?.site_main_page_subtitle || `Unique rocks, bones, and sticks from around my backyards`} diff --git a/frontend/src/pages/ProductsPage.jsx b/frontend/src/pages/ProductsPage.jsx index a6dac88..5003cc1 100644 --- a/frontend/src/pages/ProductsPage.jsx +++ b/frontend/src/pages/ProductsPage.jsx @@ -35,12 +35,14 @@ import { useProducts, useCategories, useTags, useAddToCart } from '@hooks/apiHoo import ProductRatingDisplay from '@components/ProductRatingDisplay'; import { useAuth } from '@hooks/reduxHooks'; import imageUtils from '@utils/imageUtils'; +import useBrandingSettings from '@hooks/brandingHooks'; const ProductsPage = () => { const theme = useTheme(); const navigate = useNavigate(); const location = useLocation(); const { isAuthenticated, user } = useAuth(); + const { data: brandingSettings } = useBrandingSettings(); // Parse query params const queryParams = new URLSearchParams(location.search); @@ -139,7 +141,7 @@ const ProductsPage = () => { return ( - Products + {brandingSettings?.product_title || `Products`} {/* Search and filter bar */} @@ -156,7 +158,7 @@ const ProductsPage = () => { { const navigate = useNavigate(); + const { data: brandingSettings } = useBrandingSettings(); const [page, setPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(10); const [viewDialogOpen, setViewDialogOpen] = useState(false); @@ -127,7 +130,7 @@ const UserOrdersPage = () => { return ( - My Orders + {brandingSettings?.orders_title || `My Orders`} {/* Orders Table */} @@ -180,14 +183,15 @@ const UserOrdersPage = () => { - You haven't placed any orders yet. + {brandingSettings?.orders_empty || `You have not placed any orders`} diff --git a/frontend/src/services/emailTemplateService.js b/frontend/src/services/emailTemplateService.js new file mode 100644 index 0000000..3cc4538 --- /dev/null +++ b/frontend/src/services/emailTemplateService.js @@ -0,0 +1,203 @@ +import apiClient from './api'; + +/** + * Service for managing email templates + */ +const emailTemplateService = { + /** + * Get all email templates + * @returns {Promise} Array of email templates + */ + getAllTemplates: async () => { + try { + const response = await apiClient.get('/admin/settings/category/email_templates'); + + // Transform settings into template objects + return response.data.map(setting => { + try { + // Parse the template data from the JSON value + const templateData = JSON.parse(setting.value); + return { + id: setting.key, + ...templateData + }; + } catch (e) { + console.error(`Failed to parse template setting: ${setting.key}`, e); + return null; + } + }).filter(Boolean); // Remove any null entries + } catch (error) { + throw error.response?.data || { message: 'Failed to fetch email templates' }; + } + }, + + /** + * Get a specific email template by ID + * @param {string} id - Template ID + * @returns {Promise} Email template object + */ + getTemplateById: async (id) => { + try { + const response = await apiClient.get(`/admin/settings/${id}`); + + // Parse the template data from the JSON value + const templateData = JSON.parse(response.data.value); + return { + id: response.data.key, + ...templateData + }; + } catch (error) { + throw error.response?.data || { message: 'Failed to fetch email template' }; + } + }, + + /** + * Get templates by type + * @param {string} type - Template type (e.g., 'login_code', 'shipping_notification') + * @returns {Promise} Array of email templates of the specified type + */ + getTemplatesByType: async (type) => { + try { + const templates = await emailTemplateService.getAllTemplates(); + return templates.filter(template => template.type === type); + } catch (error) { + throw error; + } + }, + + /** + * Get the default template for a specific type + * @param {string} type - Template type + * @returns {Promise} Default email template for the type, or null if none exists + */ + getDefaultTemplate: async (type) => { + try { + const templates = await emailTemplateService.getTemplatesByType(type); + return templates.find(template => template.isDefault) || null; + } catch (error) { + throw error; + } + }, + + /** + * Create a new email template + * @param {Object} templateData - Template data + * @param {string} templateData.name - Template name + * @param {string} templateData.type - Template type + * @param {string} templateData.subject - Email subject line + * @param {string} templateData.content - HTML content of the email template + * @returns {Promise} Created email template + */ + createTemplate: async (templateData) => { + try { + // Generate a unique key for the setting + const templateKey = `email_template_${Date.now()}`; + + // Create the template object + const template = { + name: templateData.name, + type: templateData.type, + subject: templateData.subject, + content: templateData.content, + isDefault: templateData.isDefault || false, + createdAt: new Date().toISOString() + }; + + // Save to settings + const response = await apiClient.put(`/admin/settings/${templateKey}`, { + value: JSON.stringify(template), + category: 'email_templates' + }); + + return { + id: templateKey, + ...template + }; + } catch (error) { + throw error.response?.data || { message: 'Failed to create email template' }; + } + }, + + /** + * Update an existing email template + * @param {string} id - Template ID + * @param {Object} templateData - Updated template data + * @returns {Promise} Updated email template + */ + updateTemplate: async (id, templateData) => { + try { + // Create the updated template object + const template = { + name: templateData.name, + type: templateData.type, + subject: templateData.subject, + content: templateData.content, + isDefault: templateData.isDefault || false, + createdAt: templateData.createdAt, + updatedAt: new Date().toISOString() + }; + + // Update in settings + await apiClient.put(`/admin/settings/${id}`, { + value: JSON.stringify(template), + category: 'email_templates' + }); + + return { + id, + ...template + }; + } catch (error) { + throw error.response?.data || { message: 'Failed to update email template' }; + } + }, + + /** + * Delete an email template + * @param {string} id - Template ID + * @returns {Promise} Success status + */ + deleteTemplate: async (id) => { + try { + await apiClient.delete(`/admin/settings/${id}`); + return true; + } catch (error) { + throw error.response?.data || { message: 'Failed to delete email template' }; + } + }, + + /** + * Set a template as the default for its type + * @param {string} id - Template ID + * @returns {Promise} Updated template + */ + setAsDefault: async (id) => { + try { + // Get the template to set as default + const template = await emailTemplateService.getTemplateById(id); + + // Get all templates of the same type + const typeTemplates = await emailTemplateService.getTemplatesByType(template.type); + + // For each template of the same type, unset default if it's set + for (const t of typeTemplates) { + if (t.id !== id && t.isDefault) { + await emailTemplateService.updateTemplate(t.id, { + ...t, + isDefault: false + }); + } + } + + // Set the selected template as default + return await emailTemplateService.updateTemplate(id, { + ...template, + isDefault: true + }); + } catch (error) { + throw error.response?.data || { message: 'Failed to set template as default' }; + } + } +}; + +export default emailTemplateService; \ No newline at end of file diff --git a/frontend/src/theme/ThemeProvider.jsx b/frontend/src/theme/ThemeProvider.jsx index 5ece4c7..5706524 100644 --- a/frontend/src/theme/ThemeProvider.jsx +++ b/frontend/src/theme/ThemeProvider.jsx @@ -1,15 +1,191 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { ThemeProvider as MuiThemeProvider } from '@mui/material/styles'; import CssBaseline from '@mui/material/CssBaseline'; -import { useAppTheme } from './index'; +import { createTheme } from '@mui/material/styles'; +import { red, amber, grey, deepPurple } from '@mui/material/colors'; +import { useQuery } from '@tanstack/react-query'; +import apiClient from '@services/api'; +import { useDarkMode } from '@hooks/reduxHooks'; +import useBrandingSettings from '@hooks/brandingHooks'; /** - * Custom ThemeProvider that uses the app's theme with dark mode support - * This component should be used instead of the direct MUI ThemeProvider + * Custom ThemeProvider that uses branding settings for white labeling */ const ThemeProvider = ({ children }) => { - const theme = useAppTheme(); - + const [darkMode, _, setDarkMode] = useDarkMode(); + const [theme, setTheme] = useState(null); + + // Fetch branding settings + const { data: brandingSettings } = useBrandingSettings(); + + // Default colors + const defaultColors = { + light: { + primary: deepPurple[400], + secondary: amber[500], + error: red.A400, + background: '#f5f5f5', + paper: '#fff', + text: '#000000', + }, + dark: { + primary: deepPurple[300], + secondary: amber[300], + error: red.A400, + background: grey[900], + paper: grey[800], + text: '#ffffff', + } + }; + + + useEffect(() => { + // Only pull from default if user specified style hasn't been set + if(brandingSettings){ + let isDarkMode = darkMode; + if(localStorage.getItem("darkMode") == null){ + isDarkMode = brandingSettings?.default_mode === 'dark' ? true : darkMode; + setDarkMode(isDarkMode); + } + handleDarkMode(isDarkMode) + } + }, [brandingSettings, darkMode]); + function handleDarkMode(darkMode){ + let isDarkMode = darkMode; + + // Get colors based on mode + const mode = isDarkMode ? 'dark' : 'light'; + const colors = { + primary: isDarkMode + ? (brandingSettings?.dark_primary_color || defaultColors.dark.primary) + : (brandingSettings?.light_primary_color || defaultColors.light.primary), + secondary: isDarkMode + ? (brandingSettings?.dark_secondary_color || defaultColors.dark.secondary) + : (brandingSettings?.light_secondary_color || defaultColors.light.secondary), + background: isDarkMode + ? (brandingSettings?.dark_background_color || defaultColors.dark.background) + : (brandingSettings?.light_background_color || defaultColors.light.background), + paper: isDarkMode + ? (brandingSettings?.dark_surface_color || defaultColors.dark.paper) + : (brandingSettings?.light_surface_color || defaultColors.light.paper), + text: isDarkMode + ? (brandingSettings?.dark_text_color || defaultColors.dark.text) + : (brandingSettings?.light_text_color || defaultColors.light.text) + }; + + // Create theme + const newTheme = createTheme({ + palette: { + mode, + primary: { + main: colors.primary, + }, + secondary: { + main: colors.secondary, + }, + error: { + main: defaultColors[mode].error, + }, + background: { + default: colors.background, + paper: colors.paper, + }, + text: { + primary: colors.text, + secondary: isDarkMode + ? 'rgba(255, 255, 255, 0.7)' + : 'rgba(0, 0, 0, 0.6)', + }, + }, + typography: { + fontFamily: [ + 'Roboto', + '-apple-system', + 'BlinkMacSystemFont', + '"Segoe UI"', + 'Arial', + 'sans-serif', + ].join(','), + h1: { + fontSize: '2.5rem', + fontWeight: 500, + }, + h2: { + fontSize: '2rem', + fontWeight: 500, + }, + h3: { + fontSize: '1.75rem', + fontWeight: 500, + }, + h4: { + fontSize: '1.5rem', + fontWeight: 500, + }, + h5: { + fontSize: '1.25rem', + fontWeight: 500, + }, + h6: { + fontSize: '1rem', + fontWeight: 500, + }, + }, + components: { + MuiButton: { + styleOverrides: { + root: { + borderRadius: 6, + textTransform: 'none', + }, + }, + }, + MuiCard: { + styleOverrides: { + root: { + borderRadius: 8, + boxShadow: isDarkMode + ? '0 4px 20px rgba(0, 0, 0, 0.5)' + : '0 4px 20px rgba(0, 0, 0, 0.1)', + }, + }, + }, + MuiAppBar: { + styleOverrides: { + root: { + boxShadow: isDarkMode + ? '0 4px 20px rgba(0, 0, 0, 0.5)' + : '0 2px 10px rgba(0, 0, 0, 0.05)', + }, + }, + }, + }, + }); + + setTheme(newTheme); + } + // Use a default theme while loading + if (!theme) { + const defaultTheme = createTheme({ + palette: { + mode: darkMode ? 'dark' : 'light', + primary: { + main: darkMode ? defaultColors.dark.primary : defaultColors.light.primary, + }, + secondary: { + main: darkMode ? defaultColors.dark.secondary : defaultColors.light.secondary, + }, + }, + }); + + return ( + + + {children} + + ); + } + return (