Spaces:
Running
Running
first commit
Browse files- .claude/settings.local.json +10 -0
- README.md +0 -0
- app/api/auth/callback/route.ts +51 -0
- app/api/export-pptx/route.ts +109 -0
- app/api/generate-slides/route.ts +233 -0
- app/globals.css +15 -0
- app/layout.tsx +2 -2
- app/page.tsx +27 -96
- components/AuthProvider.tsx +117 -0
- components/ModelSelector.tsx +146 -0
- components/PresentationGenerator.tsx +223 -0
- components/SlideEditor.tsx +291 -0
- components/SlidePreview.tsx +164 -0
- package-lock.json +742 -15
- package.json +15 -7
.claude/settings.local.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"permissions": {
|
| 3 |
+
"allow": [
|
| 4 |
+
"Bash(npm install:*)",
|
| 5 |
+
"Bash(npm run build:*)"
|
| 6 |
+
],
|
| 7 |
+
"deny": [],
|
| 8 |
+
"ask": []
|
| 9 |
+
}
|
| 10 |
+
}
|
README.md
CHANGED
|
Binary files a/README.md and b/README.md differ
|
|
|
app/api/auth/callback/route.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { NextRequest, NextResponse } from 'next/server';
|
| 2 |
+
|
| 3 |
+
export async function GET(request: NextRequest) {
|
| 4 |
+
const searchParams = request.nextUrl.searchParams;
|
| 5 |
+
const code = searchParams.get('code');
|
| 6 |
+
const error = searchParams.get('error');
|
| 7 |
+
|
| 8 |
+
if (error) {
|
| 9 |
+
// Redirect to home with error
|
| 10 |
+
return NextResponse.redirect(new URL('/?error=auth_failed', request.url));
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
if (!code) {
|
| 14 |
+
return NextResponse.redirect(new URL('/?error=no_code', request.url));
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
try {
|
| 18 |
+
// Exchange code for access token
|
| 19 |
+
const tokenResponse = await fetch('https://huggingface.co/oauth/token', {
|
| 20 |
+
method: 'POST',
|
| 21 |
+
headers: {
|
| 22 |
+
'Content-Type': 'application/x-www-form-urlencoded',
|
| 23 |
+
},
|
| 24 |
+
body: new URLSearchParams({
|
| 25 |
+
client_id: process.env.HUGGINGFACE_CLIENT_ID!,
|
| 26 |
+
client_secret: process.env.HUGGINGFACE_CLIENT_SECRET!,
|
| 27 |
+
code,
|
| 28 |
+
grant_type: 'authorization_code',
|
| 29 |
+
redirect_uri: `${new URL(request.url).origin}/api/auth/callback`,
|
| 30 |
+
}),
|
| 31 |
+
});
|
| 32 |
+
|
| 33 |
+
if (!tokenResponse.ok) {
|
| 34 |
+
throw new Error('Failed to exchange code for token');
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
const tokenData = await tokenResponse.json();
|
| 38 |
+
const accessToken = tokenData.access_token;
|
| 39 |
+
|
| 40 |
+
// In a real app, you'd store this token securely (session, JWT, etc.)
|
| 41 |
+
// For this demo, we'll redirect with the token in a query parameter
|
| 42 |
+
// Note: This is not secure for production use
|
| 43 |
+
return NextResponse.redirect(
|
| 44 |
+
new URL(`/?token=${accessToken}&auth=success`, request.url)
|
| 45 |
+
);
|
| 46 |
+
|
| 47 |
+
} catch (error) {
|
| 48 |
+
console.error('OAuth callback error:', error);
|
| 49 |
+
return NextResponse.redirect(new URL('/?error=token_exchange_failed', request.url));
|
| 50 |
+
}
|
| 51 |
+
}
|
app/api/export-pptx/route.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { NextRequest, NextResponse } from 'next/server';
|
| 2 |
+
import pptxgen from 'pptxgenjs';
|
| 3 |
+
|
| 4 |
+
interface Slide {
|
| 5 |
+
id: string;
|
| 6 |
+
title: string;
|
| 7 |
+
content: string[];
|
| 8 |
+
notes?: string;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
export async function POST(request: NextRequest) {
|
| 12 |
+
try {
|
| 13 |
+
const { slides }: { slides: Slide[] } = await request.json();
|
| 14 |
+
|
| 15 |
+
if (!slides || !Array.isArray(slides) || slides.length === 0) {
|
| 16 |
+
return NextResponse.json(
|
| 17 |
+
{ error: 'Slides array is required' },
|
| 18 |
+
{ status: 400 }
|
| 19 |
+
);
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
// Create new presentation
|
| 23 |
+
const pres = new pptxgen();
|
| 24 |
+
|
| 25 |
+
// Set presentation properties
|
| 26 |
+
pres.author = 'AI PowerPoint Generator';
|
| 27 |
+
pres.company = 'AI Generated';
|
| 28 |
+
pres.subject = 'AI Generated Presentation';
|
| 29 |
+
pres.title = slides[0]?.title || 'Presentation';
|
| 30 |
+
|
| 31 |
+
// Define slide layout and styling
|
| 32 |
+
pres.defineLayout({ name: 'LAYOUT_16x9', width: 10, height: 5.625 });
|
| 33 |
+
pres.layout = 'LAYOUT_16x9';
|
| 34 |
+
|
| 35 |
+
// Process each slide
|
| 36 |
+
slides.forEach((slideData, index) => {
|
| 37 |
+
const slide = pres.addSlide();
|
| 38 |
+
|
| 39 |
+
// Add title
|
| 40 |
+
slide.addText(slideData.title, {
|
| 41 |
+
x: 0.5,
|
| 42 |
+
y: 0.5,
|
| 43 |
+
w: 9,
|
| 44 |
+
h: 1,
|
| 45 |
+
fontSize: 32,
|
| 46 |
+
bold: true,
|
| 47 |
+
color: '363636',
|
| 48 |
+
align: 'center',
|
| 49 |
+
});
|
| 50 |
+
|
| 51 |
+
// Add content points
|
| 52 |
+
if (slideData.content && slideData.content.length > 0) {
|
| 53 |
+
const contentText = slideData.content
|
| 54 |
+
.map(point => `• ${point}`)
|
| 55 |
+
.join('\n');
|
| 56 |
+
|
| 57 |
+
slide.addText(contentText, {
|
| 58 |
+
x: 1,
|
| 59 |
+
y: 2,
|
| 60 |
+
w: 8,
|
| 61 |
+
h: 3,
|
| 62 |
+
fontSize: 18,
|
| 63 |
+
color: '363636',
|
| 64 |
+
lineSpacing: 32,
|
| 65 |
+
valign: 'top',
|
| 66 |
+
});
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
// Add slide number
|
| 70 |
+
slide.addText(`${index + 1}`, {
|
| 71 |
+
x: 9.2,
|
| 72 |
+
y: 5,
|
| 73 |
+
w: 0.5,
|
| 74 |
+
h: 0.3,
|
| 75 |
+
fontSize: 12,
|
| 76 |
+
color: '999999',
|
| 77 |
+
align: 'center',
|
| 78 |
+
});
|
| 79 |
+
|
| 80 |
+
// Add speaker notes if available
|
| 81 |
+
if (slideData.notes) {
|
| 82 |
+
slide.addNotes(slideData.notes);
|
| 83 |
+
}
|
| 84 |
+
});
|
| 85 |
+
|
| 86 |
+
// Generate the presentation
|
| 87 |
+
const pptxBuffer = await pres.write({ outputType: 'nodebuffer' });
|
| 88 |
+
|
| 89 |
+
// Convert to Buffer and then to ArrayBuffer for NextResponse
|
| 90 |
+
const buffer = Buffer.from(pptxBuffer as Uint8Array);
|
| 91 |
+
const arrayBuffer = buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
|
| 92 |
+
|
| 93 |
+
// Return the file as a response
|
| 94 |
+
return new NextResponse(arrayBuffer, {
|
| 95 |
+
status: 200,
|
| 96 |
+
headers: {
|
| 97 |
+
'Content-Type': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
| 98 |
+
'Content-Disposition': 'attachment; filename="presentation.pptx"',
|
| 99 |
+
},
|
| 100 |
+
});
|
| 101 |
+
|
| 102 |
+
} catch (error) {
|
| 103 |
+
console.error('Export error:', error);
|
| 104 |
+
return NextResponse.json(
|
| 105 |
+
{ error: 'Failed to export presentation' },
|
| 106 |
+
{ status: 500 }
|
| 107 |
+
);
|
| 108 |
+
}
|
| 109 |
+
}
|
app/api/generate-slides/route.ts
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { HfInference } from '@huggingface/inference';
|
| 2 |
+
import { NextRequest, NextResponse } from 'next/server';
|
| 3 |
+
|
| 4 |
+
interface Slide {
|
| 5 |
+
id: string;
|
| 6 |
+
title: string;
|
| 7 |
+
content: string[];
|
| 8 |
+
notes?: string;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
export async function POST(request: NextRequest) {
|
| 12 |
+
try {
|
| 13 |
+
const { prompt, model, authMethod } = await request.json();
|
| 14 |
+
|
| 15 |
+
if (!prompt || !model) {
|
| 16 |
+
return NextResponse.json(
|
| 17 |
+
{ error: 'Prompt and model are required' },
|
| 18 |
+
{ status: 400 }
|
| 19 |
+
);
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
// Get API token based on auth method
|
| 23 |
+
let apiToken: string | undefined;
|
| 24 |
+
|
| 25 |
+
if (authMethod === 'api-key') {
|
| 26 |
+
const authHeader = request.headers.get('authorization');
|
| 27 |
+
if (authHeader?.startsWith('Bearer ')) {
|
| 28 |
+
apiToken = authHeader.slice(7);
|
| 29 |
+
} else {
|
| 30 |
+
return NextResponse.json(
|
| 31 |
+
{ error: 'API token required for API key authentication' },
|
| 32 |
+
{ status: 401 }
|
| 33 |
+
);
|
| 34 |
+
}
|
| 35 |
+
} else {
|
| 36 |
+
// For OAuth, we'd normally get the token from session
|
| 37 |
+
// For demo purposes, we'll require API key
|
| 38 |
+
return NextResponse.json(
|
| 39 |
+
{ error: 'Please use API key authentication for this demo' },
|
| 40 |
+
{ status: 401 }
|
| 41 |
+
);
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
// Initialize Hugging Face client
|
| 45 |
+
const hf = new HfInference(apiToken);
|
| 46 |
+
|
| 47 |
+
// Create a structured prompt for slide generation
|
| 48 |
+
const slideGenerationPrompt = `Create a professional PowerPoint presentation based on the following topic: "${prompt}"
|
| 49 |
+
|
| 50 |
+
Please format your response as a JSON array where each object represents a slide with this structure:
|
| 51 |
+
{
|
| 52 |
+
"title": "Slide title",
|
| 53 |
+
"content": ["bullet point 1", "bullet point 2", "bullet point 3"],
|
| 54 |
+
"notes": "Optional speaker notes"
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
Guidelines:
|
| 58 |
+
- Create 5-8 slides
|
| 59 |
+
- First slide should be a title slide
|
| 60 |
+
- Each content slide should have 3-5 bullet points
|
| 61 |
+
- Keep bullet points concise and informative
|
| 62 |
+
- Include a conclusion slide
|
| 63 |
+
- Add relevant speaker notes where helpful
|
| 64 |
+
|
| 65 |
+
Topic: ${prompt}
|
| 66 |
+
|
| 67 |
+
JSON Response:`;
|
| 68 |
+
|
| 69 |
+
try {
|
| 70 |
+
// Try text generation with the specified model
|
| 71 |
+
console.log(`Attempting to use model: ${model}`);
|
| 72 |
+
const response = await hf.textGeneration({
|
| 73 |
+
model,
|
| 74 |
+
inputs: slideGenerationPrompt,
|
| 75 |
+
parameters: {
|
| 76 |
+
max_new_tokens: 2000,
|
| 77 |
+
temperature: 0.7,
|
| 78 |
+
do_sample: true,
|
| 79 |
+
},
|
| 80 |
+
});
|
| 81 |
+
|
| 82 |
+
const generatedText = response.generated_text;
|
| 83 |
+
|
| 84 |
+
// Try to extract JSON from the response
|
| 85 |
+
let slides: Slide[] = [];
|
| 86 |
+
|
| 87 |
+
try {
|
| 88 |
+
// Find JSON array in the response
|
| 89 |
+
const jsonMatch = generatedText.match(/\[[\s\S]*\]/);
|
| 90 |
+
if (jsonMatch) {
|
| 91 |
+
const parsedSlides = JSON.parse(jsonMatch[0]);
|
| 92 |
+
slides = parsedSlides.map((slide: { title?: string; content?: string | string[]; notes?: string }, index: number) => ({
|
| 93 |
+
id: `slide-${index + 1}`,
|
| 94 |
+
title: slide.title || `Slide ${index + 1}`,
|
| 95 |
+
content: Array.isArray(slide.content) ? slide.content : [slide.content || 'Content'],
|
| 96 |
+
notes: slide.notes || '',
|
| 97 |
+
}));
|
| 98 |
+
} else {
|
| 99 |
+
throw new Error('No JSON found in response');
|
| 100 |
+
}
|
| 101 |
+
} catch {
|
| 102 |
+
// Fallback: Parse the text manually and create slides
|
| 103 |
+
slides = parseTextToSlides(generatedText, prompt);
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
if (slides.length === 0) {
|
| 107 |
+
slides = createFallbackSlides(prompt);
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
return NextResponse.json({ slides });
|
| 111 |
+
|
| 112 |
+
} catch (modelError) {
|
| 113 |
+
console.error('Model error:', modelError);
|
| 114 |
+
|
| 115 |
+
// Fallback to default slides if model fails
|
| 116 |
+
const slides = createFallbackSlides(prompt);
|
| 117 |
+
return NextResponse.json({
|
| 118 |
+
slides,
|
| 119 |
+
warning: 'Used fallback content generation due to model limitations'
|
| 120 |
+
});
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
} catch (error) {
|
| 124 |
+
console.error('API error:', error);
|
| 125 |
+
return NextResponse.json(
|
| 126 |
+
{ error: 'Failed to generate slides' },
|
| 127 |
+
{ status: 500 }
|
| 128 |
+
);
|
| 129 |
+
}
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
function parseTextToSlides(text: string, prompt: string): Slide[] {
|
| 133 |
+
const lines = text.split('\n').filter(line => line.trim());
|
| 134 |
+
const slides: Slide[] = [];
|
| 135 |
+
|
| 136 |
+
let currentSlide: Partial<Slide> = {};
|
| 137 |
+
let slideIndex = 1;
|
| 138 |
+
|
| 139 |
+
for (const line of lines) {
|
| 140 |
+
const trimmedLine = line.trim();
|
| 141 |
+
|
| 142 |
+
if (trimmedLine.startsWith('#') || trimmedLine.includes('Slide') || trimmedLine.includes('SLIDE')) {
|
| 143 |
+
// New slide detected
|
| 144 |
+
if (currentSlide.title) {
|
| 145 |
+
slides.push({
|
| 146 |
+
id: `slide-${slideIndex}`,
|
| 147 |
+
title: currentSlide.title,
|
| 148 |
+
content: currentSlide.content || ['Content'],
|
| 149 |
+
notes: currentSlide.notes || '',
|
| 150 |
+
});
|
| 151 |
+
slideIndex++;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
currentSlide = {
|
| 155 |
+
title: trimmedLine.replace(/^#+\s*/, '').replace(/slide\s*\d*:?\s*/i, ''),
|
| 156 |
+
content: [],
|
| 157 |
+
};
|
| 158 |
+
} else if (trimmedLine.startsWith('-') || trimmedLine.startsWith('•') || trimmedLine.startsWith('*')) {
|
| 159 |
+
// Bullet point
|
| 160 |
+
if (!currentSlide.content) currentSlide.content = [];
|
| 161 |
+
currentSlide.content.push(trimmedLine.replace(/^[-•*]\s*/, ''));
|
| 162 |
+
}
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
// Add the last slide
|
| 166 |
+
if (currentSlide.title) {
|
| 167 |
+
slides.push({
|
| 168 |
+
id: `slide-${slideIndex}`,
|
| 169 |
+
title: currentSlide.title,
|
| 170 |
+
content: currentSlide.content || ['Content'],
|
| 171 |
+
notes: currentSlide.notes || '',
|
| 172 |
+
});
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
if (slides.length === 0) {
|
| 176 |
+
return createFallbackSlides(prompt);
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
return slides;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
function createFallbackSlides(prompt: string): Slide[] {
|
| 183 |
+
return [
|
| 184 |
+
{
|
| 185 |
+
id: 'slide-1',
|
| 186 |
+
title: prompt,
|
| 187 |
+
content: ['Welcome to this presentation', 'Overview of key topics', 'Let\'s get started'],
|
| 188 |
+
notes: 'Introduction slide to set the context',
|
| 189 |
+
},
|
| 190 |
+
{
|
| 191 |
+
id: 'slide-2',
|
| 192 |
+
title: 'Main Points',
|
| 193 |
+
content: [
|
| 194 |
+
'Key concept 1 related to the topic',
|
| 195 |
+
'Important aspect 2 to consider',
|
| 196 |
+
'Critical factor 3 for understanding',
|
| 197 |
+
'Additional insight 4',
|
| 198 |
+
],
|
| 199 |
+
notes: 'Elaborate on each main point with examples',
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
id: 'slide-3',
|
| 203 |
+
title: 'Benefits & Advantages',
|
| 204 |
+
content: [
|
| 205 |
+
'Primary benefit of this approach',
|
| 206 |
+
'Secondary advantage to consider',
|
| 207 |
+
'Long-term positive impacts',
|
| 208 |
+
],
|
| 209 |
+
notes: 'Highlight the positive aspects and value proposition',
|
| 210 |
+
},
|
| 211 |
+
{
|
| 212 |
+
id: 'slide-4',
|
| 213 |
+
title: 'Implementation',
|
| 214 |
+
content: [
|
| 215 |
+
'Step 1: Initial setup and planning',
|
| 216 |
+
'Step 2: Core implementation phase',
|
| 217 |
+
'Step 3: Testing and validation',
|
| 218 |
+
'Step 4: Deployment and monitoring',
|
| 219 |
+
],
|
| 220 |
+
notes: 'Provide actionable steps for implementation',
|
| 221 |
+
},
|
| 222 |
+
{
|
| 223 |
+
id: 'slide-5',
|
| 224 |
+
title: 'Conclusion',
|
| 225 |
+
content: [
|
| 226 |
+
'Summary of key takeaways',
|
| 227 |
+
'Next steps and recommendations',
|
| 228 |
+
'Thank you for your attention',
|
| 229 |
+
],
|
| 230 |
+
notes: 'Wrap up with clear action items and call to action',
|
| 231 |
+
},
|
| 232 |
+
];
|
| 233 |
+
}
|
app/globals.css
CHANGED
|
@@ -24,3 +24,18 @@ body {
|
|
| 24 |
color: var(--foreground);
|
| 25 |
font-family: Arial, Helvetica, sans-serif;
|
| 26 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
color: var(--foreground);
|
| 25 |
font-family: Arial, Helvetica, sans-serif;
|
| 26 |
}
|
| 27 |
+
|
| 28 |
+
/* Utility classes for text truncation */
|
| 29 |
+
.line-clamp-2 {
|
| 30 |
+
display: -webkit-box;
|
| 31 |
+
-webkit-line-clamp: 2;
|
| 32 |
+
-webkit-box-orient: vertical;
|
| 33 |
+
overflow: hidden;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
.line-clamp-3 {
|
| 37 |
+
display: -webkit-box;
|
| 38 |
+
-webkit-line-clamp: 3;
|
| 39 |
+
-webkit-box-orient: vertical;
|
| 40 |
+
overflow: hidden;
|
| 41 |
+
}
|
app/layout.tsx
CHANGED
|
@@ -13,8 +13,8 @@ const geistMono = Geist_Mono({
|
|
| 13 |
});
|
| 14 |
|
| 15 |
export const metadata: Metadata = {
|
| 16 |
-
title: "
|
| 17 |
-
description: "
|
| 18 |
};
|
| 19 |
|
| 20 |
export default function RootLayout({
|
|
|
|
| 13 |
});
|
| 14 |
|
| 15 |
export const metadata: Metadata = {
|
| 16 |
+
title: "AI PowerPoint Generator",
|
| 17 |
+
description: "Generate PowerPoint presentations using AI with Hugging Face models",
|
| 18 |
};
|
| 19 |
|
| 20 |
export default function RootLayout({
|
app/page.tsx
CHANGED
|
@@ -1,103 +1,34 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
export default function Home() {
|
|
|
|
|
|
|
|
|
|
| 4 |
return (
|
| 5 |
-
<div className="
|
| 6 |
-
<
|
| 7 |
-
<
|
| 8 |
-
className="
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
/>
|
| 15 |
-
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left">
|
| 16 |
-
<li className="mb-2 tracking-[-.01em]">
|
| 17 |
-
Get started by editing{" "}
|
| 18 |
-
<code className="bg-black/[.05] dark:bg-white/[.06] font-mono font-semibold px-1 py-0.5 rounded">
|
| 19 |
-
app/page.tsx
|
| 20 |
-
</code>
|
| 21 |
-
.
|
| 22 |
-
</li>
|
| 23 |
-
<li className="tracking-[-.01em]">
|
| 24 |
-
Save and see your changes instantly.
|
| 25 |
-
</li>
|
| 26 |
-
</ol>
|
| 27 |
|
| 28 |
-
|
| 29 |
-
<
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
target="_blank"
|
| 33 |
-
rel="noopener noreferrer"
|
| 34 |
-
>
|
| 35 |
-
<Image
|
| 36 |
-
className="dark:invert"
|
| 37 |
-
src="/vercel.svg"
|
| 38 |
-
alt="Vercel logomark"
|
| 39 |
-
width={20}
|
| 40 |
-
height={20}
|
| 41 |
-
/>
|
| 42 |
-
Deploy now
|
| 43 |
-
</a>
|
| 44 |
-
<a
|
| 45 |
-
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
|
| 46 |
-
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
| 47 |
-
target="_blank"
|
| 48 |
-
rel="noopener noreferrer"
|
| 49 |
-
>
|
| 50 |
-
Read our docs
|
| 51 |
-
</a>
|
| 52 |
-
</div>
|
| 53 |
-
</main>
|
| 54 |
-
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
|
| 55 |
-
<a
|
| 56 |
-
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
| 57 |
-
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
| 58 |
-
target="_blank"
|
| 59 |
-
rel="noopener noreferrer"
|
| 60 |
-
>
|
| 61 |
-
<Image
|
| 62 |
-
aria-hidden
|
| 63 |
-
src="/file.svg"
|
| 64 |
-
alt="File icon"
|
| 65 |
-
width={16}
|
| 66 |
-
height={16}
|
| 67 |
-
/>
|
| 68 |
-
Learn
|
| 69 |
-
</a>
|
| 70 |
-
<a
|
| 71 |
-
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
| 72 |
-
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
| 73 |
-
target="_blank"
|
| 74 |
-
rel="noopener noreferrer"
|
| 75 |
-
>
|
| 76 |
-
<Image
|
| 77 |
-
aria-hidden
|
| 78 |
-
src="/window.svg"
|
| 79 |
-
alt="Window icon"
|
| 80 |
-
width={16}
|
| 81 |
-
height={16}
|
| 82 |
-
/>
|
| 83 |
-
Examples
|
| 84 |
-
</a>
|
| 85 |
-
<a
|
| 86 |
-
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
| 87 |
-
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
| 88 |
-
target="_blank"
|
| 89 |
-
rel="noopener noreferrer"
|
| 90 |
-
>
|
| 91 |
-
<Image
|
| 92 |
-
aria-hidden
|
| 93 |
-
src="/globe.svg"
|
| 94 |
-
alt="Globe icon"
|
| 95 |
-
width={16}
|
| 96 |
-
height={16}
|
| 97 |
/>
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
|
|
|
| 101 |
</div>
|
| 102 |
);
|
| 103 |
-
}
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { useState } from 'react';
|
| 4 |
+
import { PresentationGenerator } from '@/components/PresentationGenerator';
|
| 5 |
+
import { AuthProvider } from '@/components/AuthProvider';
|
| 6 |
|
| 7 |
export default function Home() {
|
| 8 |
+
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
| 9 |
+
const [authMethod, setAuthMethod] = useState<'huggingface' | 'api-key' | null>(null);
|
| 10 |
+
|
| 11 |
return (
|
| 12 |
+
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 p-4">
|
| 13 |
+
<div className="max-w-6xl mx-auto">
|
| 14 |
+
<header className="text-center py-8">
|
| 15 |
+
<h1 className="text-4xl font-bold text-gray-800 mb-2">
|
| 16 |
+
AI PowerPoint Generator
|
| 17 |
+
</h1>
|
| 18 |
+
<p className="text-lg text-gray-600">
|
| 19 |
+
Create stunning presentations with AI-powered content generation
|
| 20 |
+
</p>
|
| 21 |
+
</header>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
+
{!isAuthenticated ? (
|
| 24 |
+
<AuthProvider
|
| 25 |
+
onAuthSuccess={() => setIsAuthenticated(true)}
|
| 26 |
+
onAuthMethodSelect={setAuthMethod}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
/>
|
| 28 |
+
) : (
|
| 29 |
+
<PresentationGenerator authMethod={authMethod} />
|
| 30 |
+
)}
|
| 31 |
+
</div>
|
| 32 |
</div>
|
| 33 |
);
|
| 34 |
+
}
|
components/AuthProvider.tsx
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { useState } from 'react';
|
| 4 |
+
import { Key, ExternalLink } from 'lucide-react';
|
| 5 |
+
|
| 6 |
+
interface AuthProviderProps {
|
| 7 |
+
onAuthSuccess: () => void;
|
| 8 |
+
onAuthMethodSelect: (method: 'huggingface' | 'api-key') => void;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
export function AuthProvider({ onAuthSuccess, onAuthMethodSelect }: AuthProviderProps) {
|
| 12 |
+
// const [selectedMethod, setSelectedMethod] = useState<'huggingface' | 'api-key' | null>(null);
|
| 13 |
+
const [apiKey, setApiKey] = useState('');
|
| 14 |
+
const [isLoading, setIsLoading] = useState(false);
|
| 15 |
+
|
| 16 |
+
const handleHuggingFaceAuth = async () => {
|
| 17 |
+
setIsLoading(true);
|
| 18 |
+
try {
|
| 19 |
+
// Redirect to Hugging Face OAuth
|
| 20 |
+
const clientId = process.env.NEXT_PUBLIC_HUGGINGFACE_CLIENT_ID;
|
| 21 |
+
const redirectUri = encodeURIComponent(window.location.origin + '/auth/callback');
|
| 22 |
+
const scope = encodeURIComponent('read-repos inference');
|
| 23 |
+
|
| 24 |
+
if (!clientId) {
|
| 25 |
+
alert('Hugging Face client ID not configured. Please use API key method.');
|
| 26 |
+
setIsLoading(false);
|
| 27 |
+
return;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
const authUrl = `https://huggingface.co/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}&response_type=code`;
|
| 31 |
+
window.location.href = authUrl;
|
| 32 |
+
} catch (error) {
|
| 33 |
+
console.error('HF Auth error:', error);
|
| 34 |
+
setIsLoading(false);
|
| 35 |
+
}
|
| 36 |
+
};
|
| 37 |
+
|
| 38 |
+
const handleApiKeyAuth = () => {
|
| 39 |
+
if (!apiKey.trim()) {
|
| 40 |
+
alert('Please enter a valid API key');
|
| 41 |
+
return;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
// Store API key in localStorage for demo purposes
|
| 45 |
+
localStorage.setItem('hf_api_key', apiKey);
|
| 46 |
+
onAuthMethodSelect('api-key');
|
| 47 |
+
onAuthSuccess();
|
| 48 |
+
};
|
| 49 |
+
|
| 50 |
+
return (
|
| 51 |
+
<div className="max-w-md mx-auto bg-white rounded-lg shadow-lg p-6">
|
| 52 |
+
<h2 className="text-2xl font-bold text-center mb-6 text-gray-800">
|
| 53 |
+
Choose Authentication Method
|
| 54 |
+
</h2>
|
| 55 |
+
|
| 56 |
+
<div className="space-y-4">
|
| 57 |
+
{/* Hugging Face OAuth Option */}
|
| 58 |
+
<div className="border-2 border-orange-200 rounded-lg p-4 hover:border-orange-300 transition-colors">
|
| 59 |
+
<div className="flex items-center justify-between mb-3">
|
| 60 |
+
<h3 className="font-semibold text-lg text-gray-800">Hugging Face Login</h3>
|
| 61 |
+
<ExternalLink className="w-5 h-5 text-orange-500" />
|
| 62 |
+
</div>
|
| 63 |
+
<p className="text-gray-600 text-sm mb-4">
|
| 64 |
+
Sign in with your Hugging Face account to access all available models
|
| 65 |
+
</p>
|
| 66 |
+
<button
|
| 67 |
+
onClick={handleHuggingFaceAuth}
|
| 68 |
+
disabled={isLoading}
|
| 69 |
+
className="w-full bg-orange-500 hover:bg-orange-600 text-white font-medium py-2 px-4 rounded-md transition-colors disabled:opacity-50"
|
| 70 |
+
>
|
| 71 |
+
{isLoading ? 'Redirecting...' : 'Sign in with Hugging Face'}
|
| 72 |
+
</button>
|
| 73 |
+
</div>
|
| 74 |
+
|
| 75 |
+
{/* API Key Option */}
|
| 76 |
+
<div className="border-2 border-blue-200 rounded-lg p-4 hover:border-blue-300 transition-colors">
|
| 77 |
+
<div className="flex items-center justify-between mb-3">
|
| 78 |
+
<h3 className="font-semibold text-lg text-gray-800">API Key</h3>
|
| 79 |
+
<Key className="w-5 h-5 text-blue-500" />
|
| 80 |
+
</div>
|
| 81 |
+
<p className="text-gray-600 text-sm mb-4">
|
| 82 |
+
Use your personal Hugging Face API token for access
|
| 83 |
+
</p>
|
| 84 |
+
<div className="space-y-3">
|
| 85 |
+
<input
|
| 86 |
+
type="password"
|
| 87 |
+
placeholder="Enter your Hugging Face API token..."
|
| 88 |
+
value={apiKey}
|
| 89 |
+
onChange={(e) => setApiKey(e.target.value)}
|
| 90 |
+
className="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
| 91 |
+
/>
|
| 92 |
+
<button
|
| 93 |
+
onClick={handleApiKeyAuth}
|
| 94 |
+
className="w-full bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-md transition-colors"
|
| 95 |
+
>
|
| 96 |
+
Continue with API Key
|
| 97 |
+
</button>
|
| 98 |
+
</div>
|
| 99 |
+
</div>
|
| 100 |
+
</div>
|
| 101 |
+
|
| 102 |
+
<div className="mt-6 text-center">
|
| 103 |
+
<p className="text-xs text-gray-500">
|
| 104 |
+
Need an API key?{' '}
|
| 105 |
+
<a
|
| 106 |
+
href="https://huggingface.co/settings/tokens"
|
| 107 |
+
target="_blank"
|
| 108 |
+
rel="noopener noreferrer"
|
| 109 |
+
className="text-blue-500 hover:underline"
|
| 110 |
+
>
|
| 111 |
+
Get one here
|
| 112 |
+
</a>
|
| 113 |
+
</p>
|
| 114 |
+
</div>
|
| 115 |
+
</div>
|
| 116 |
+
);
|
| 117 |
+
}
|
components/ModelSelector.tsx
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { useState } from 'react';
|
| 4 |
+
import { ChevronDown, Plus } from 'lucide-react';
|
| 5 |
+
|
| 6 |
+
interface ModelSelectorProps {
|
| 7 |
+
selectedModel: string;
|
| 8 |
+
customModel: string;
|
| 9 |
+
onModelSelect: (model: string) => void;
|
| 10 |
+
onCustomModelChange: (model: string) => void;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
const POPULAR_MODELS = [
|
| 14 |
+
{
|
| 15 |
+
id: 'microsoft/DialoGPT-large',
|
| 16 |
+
name: 'DialoGPT Large',
|
| 17 |
+
description: 'Conversational AI model for generating natural dialogue',
|
| 18 |
+
},
|
| 19 |
+
{
|
| 20 |
+
id: 'google/flan-t5-large',
|
| 21 |
+
name: 'FLAN-T5 Large',
|
| 22 |
+
description: 'Instruction-tuned model good for structured content',
|
| 23 |
+
},
|
| 24 |
+
{
|
| 25 |
+
id: 'meta-llama/Llama-2-7b-chat-hf',
|
| 26 |
+
name: 'Llama 2 7B Chat',
|
| 27 |
+
description: 'Meta\'s conversational AI model',
|
| 28 |
+
},
|
| 29 |
+
{
|
| 30 |
+
id: 'mistralai/Mistral-7B-Instruct-v0.1',
|
| 31 |
+
name: 'Mistral 7B Instruct',
|
| 32 |
+
description: 'Efficient instruction-following model',
|
| 33 |
+
},
|
| 34 |
+
{
|
| 35 |
+
id: 'HuggingFaceH4/zephyr-7b-beta',
|
| 36 |
+
name: 'Zephyr 7B Beta',
|
| 37 |
+
description: 'Fine-tuned assistant model',
|
| 38 |
+
},
|
| 39 |
+
];
|
| 40 |
+
|
| 41 |
+
export function ModelSelector({
|
| 42 |
+
selectedModel,
|
| 43 |
+
customModel,
|
| 44 |
+
onModelSelect,
|
| 45 |
+
onCustomModelChange,
|
| 46 |
+
}: ModelSelectorProps) {
|
| 47 |
+
const [showCustomInput, setShowCustomInput] = useState(false);
|
| 48 |
+
const [isOpen, setIsOpen] = useState(false);
|
| 49 |
+
|
| 50 |
+
const handleModelSelect = (modelId: string) => {
|
| 51 |
+
onModelSelect(modelId);
|
| 52 |
+
onCustomModelChange('');
|
| 53 |
+
setShowCustomInput(false);
|
| 54 |
+
setIsOpen(false);
|
| 55 |
+
};
|
| 56 |
+
|
| 57 |
+
const handleCustomModelSubmit = () => {
|
| 58 |
+
if (customModel.trim()) {
|
| 59 |
+
setShowCustomInput(false);
|
| 60 |
+
setIsOpen(false);
|
| 61 |
+
}
|
| 62 |
+
};
|
| 63 |
+
|
| 64 |
+
const displayValue = customModel ||
|
| 65 |
+
POPULAR_MODELS.find(m => m.id === selectedModel)?.name ||
|
| 66 |
+
selectedModel;
|
| 67 |
+
|
| 68 |
+
return (
|
| 69 |
+
<div className="relative">
|
| 70 |
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
| 71 |
+
AI Model
|
| 72 |
+
</label>
|
| 73 |
+
|
| 74 |
+
<div className="relative">
|
| 75 |
+
<button
|
| 76 |
+
onClick={() => setIsOpen(!isOpen)}
|
| 77 |
+
className="w-full bg-white border border-gray-300 rounded-md px-3 py-2 text-left focus:outline-none focus:ring-2 focus:ring-blue-500 flex items-center justify-between"
|
| 78 |
+
>
|
| 79 |
+
<span className="truncate">{displayValue}</span>
|
| 80 |
+
<ChevronDown className={`w-4 h-4 transition-transform ${isOpen ? 'rotate-180' : ''}`} />
|
| 81 |
+
</button>
|
| 82 |
+
|
| 83 |
+
{isOpen && (
|
| 84 |
+
<div className="absolute z-10 w-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-64 overflow-y-auto">
|
| 85 |
+
{POPULAR_MODELS.map((model) => (
|
| 86 |
+
<button
|
| 87 |
+
key={model.id}
|
| 88 |
+
onClick={() => handleModelSelect(model.id)}
|
| 89 |
+
className={`w-full text-left px-3 py-2 hover:bg-gray-50 border-b border-gray-100 last:border-b-0 ${
|
| 90 |
+
selectedModel === model.id && !customModel ? 'bg-blue-50' : ''
|
| 91 |
+
}`}
|
| 92 |
+
>
|
| 93 |
+
<div className="font-medium text-sm">{model.name}</div>
|
| 94 |
+
<div className="text-xs text-gray-500 truncate">{model.description}</div>
|
| 95 |
+
<div className="text-xs text-gray-400 font-mono">{model.id}</div>
|
| 96 |
+
</button>
|
| 97 |
+
))}
|
| 98 |
+
|
| 99 |
+
<button
|
| 100 |
+
onClick={() => {
|
| 101 |
+
setShowCustomInput(true);
|
| 102 |
+
setIsOpen(false);
|
| 103 |
+
}}
|
| 104 |
+
className="w-full text-left px-3 py-2 hover:bg-gray-50 border-t border-gray-200 flex items-center gap-2"
|
| 105 |
+
>
|
| 106 |
+
<Plus className="w-4 h-4" />
|
| 107 |
+
<span className="font-medium text-sm">Use Custom Model</span>
|
| 108 |
+
</button>
|
| 109 |
+
</div>
|
| 110 |
+
)}
|
| 111 |
+
</div>
|
| 112 |
+
|
| 113 |
+
{showCustomInput && (
|
| 114 |
+
<div className="mt-2 p-3 border border-blue-200 rounded-md bg-blue-50">
|
| 115 |
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
| 116 |
+
Custom Model ID
|
| 117 |
+
</label>
|
| 118 |
+
<div className="flex gap-2">
|
| 119 |
+
<input
|
| 120 |
+
type="text"
|
| 121 |
+
value={customModel}
|
| 122 |
+
onChange={(e) => onCustomModelChange(e.target.value)}
|
| 123 |
+
placeholder="e.g., your-username/your-model-name"
|
| 124 |
+
className="flex-1 border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
| 125 |
+
/>
|
| 126 |
+
<button
|
| 127 |
+
onClick={handleCustomModelSubmit}
|
| 128 |
+
className="bg-blue-500 hover:bg-blue-600 text-white px-3 py-2 rounded-md text-sm"
|
| 129 |
+
>
|
| 130 |
+
Use
|
| 131 |
+
</button>
|
| 132 |
+
<button
|
| 133 |
+
onClick={() => setShowCustomInput(false)}
|
| 134 |
+
className="bg-gray-500 hover:bg-gray-600 text-white px-3 py-2 rounded-md text-sm"
|
| 135 |
+
>
|
| 136 |
+
Cancel
|
| 137 |
+
</button>
|
| 138 |
+
</div>
|
| 139 |
+
<p className="text-xs text-gray-600 mt-1">
|
| 140 |
+
Enter any Hugging Face model ID that supports text generation
|
| 141 |
+
</p>
|
| 142 |
+
</div>
|
| 143 |
+
)}
|
| 144 |
+
</div>
|
| 145 |
+
);
|
| 146 |
+
}
|
components/PresentationGenerator.tsx
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { useState } from 'react';
|
| 4 |
+
import { Wand2, Download, Edit, Eye } from 'lucide-react';
|
| 5 |
+
import { ModelSelector } from './ModelSelector';
|
| 6 |
+
import { SlideEditor } from './SlideEditor';
|
| 7 |
+
import { SlidePreview } from './SlidePreview';
|
| 8 |
+
|
| 9 |
+
interface PresentationGeneratorProps {
|
| 10 |
+
authMethod: 'huggingface' | 'api-key' | null;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
export interface Slide {
|
| 14 |
+
id: string;
|
| 15 |
+
title: string;
|
| 16 |
+
content: string[];
|
| 17 |
+
notes?: string;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
export function PresentationGenerator({ authMethod }: PresentationGeneratorProps) {
|
| 21 |
+
const [prompt, setPrompt] = useState('');
|
| 22 |
+
const [selectedModel, setSelectedModel] = useState('microsoft/DialoGPT-large');
|
| 23 |
+
const [customModel, setCustomModel] = useState('');
|
| 24 |
+
const [slides, setSlides] = useState<Slide[]>([]);
|
| 25 |
+
const [isGenerating, setIsGenerating] = useState(false);
|
| 26 |
+
const [currentView, setCurrentView] = useState<'generate' | 'edit' | 'preview'>('generate');
|
| 27 |
+
|
| 28 |
+
const generatePresentation = async () => {
|
| 29 |
+
if (!prompt.trim()) {
|
| 30 |
+
alert('Please enter a prompt for your presentation');
|
| 31 |
+
return;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
setIsGenerating(true);
|
| 35 |
+
try {
|
| 36 |
+
// Get API token from localStorage if using API key method
|
| 37 |
+
let headers: Record<string, string> = {
|
| 38 |
+
'Content-Type': 'application/json',
|
| 39 |
+
};
|
| 40 |
+
|
| 41 |
+
if (authMethod === 'api-key') {
|
| 42 |
+
const apiKey = localStorage.getItem('hf_api_key');
|
| 43 |
+
if (!apiKey) {
|
| 44 |
+
alert('API key not found. Please authenticate again.');
|
| 45 |
+
return;
|
| 46 |
+
}
|
| 47 |
+
headers = {
|
| 48 |
+
...headers,
|
| 49 |
+
'Authorization': `Bearer ${apiKey}`,
|
| 50 |
+
};
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
const response = await fetch('/api/generate-slides', {
|
| 54 |
+
method: 'POST',
|
| 55 |
+
headers,
|
| 56 |
+
body: JSON.stringify({
|
| 57 |
+
prompt,
|
| 58 |
+
model: customModel || selectedModel,
|
| 59 |
+
authMethod,
|
| 60 |
+
}),
|
| 61 |
+
});
|
| 62 |
+
|
| 63 |
+
if (!response.ok) {
|
| 64 |
+
const errorData = await response.json();
|
| 65 |
+
throw new Error(errorData.error || 'Failed to generate presentation');
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
const data = await response.json();
|
| 69 |
+
setSlides(data.slides);
|
| 70 |
+
setCurrentView('edit');
|
| 71 |
+
|
| 72 |
+
if (data.warning) {
|
| 73 |
+
alert(`Note: ${data.warning}`);
|
| 74 |
+
}
|
| 75 |
+
} catch (error) {
|
| 76 |
+
console.error('Generation error:', error);
|
| 77 |
+
alert(`Failed to generate presentation: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
| 78 |
+
} finally {
|
| 79 |
+
setIsGenerating(false);
|
| 80 |
+
}
|
| 81 |
+
};
|
| 82 |
+
|
| 83 |
+
const exportToPowerPoint = async () => {
|
| 84 |
+
try {
|
| 85 |
+
const response = await fetch('/api/export-pptx', {
|
| 86 |
+
method: 'POST',
|
| 87 |
+
headers: {
|
| 88 |
+
'Content-Type': 'application/json',
|
| 89 |
+
},
|
| 90 |
+
body: JSON.stringify({ slides }),
|
| 91 |
+
});
|
| 92 |
+
|
| 93 |
+
if (!response.ok) {
|
| 94 |
+
throw new Error('Failed to export presentation');
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
const blob = await response.blob();
|
| 98 |
+
const url = window.URL.createObjectURL(blob);
|
| 99 |
+
const a = document.createElement('a');
|
| 100 |
+
a.style.display = 'none';
|
| 101 |
+
a.href = url;
|
| 102 |
+
a.download = 'presentation.pptx';
|
| 103 |
+
document.body.appendChild(a);
|
| 104 |
+
a.click();
|
| 105 |
+
window.URL.revokeObjectURL(url);
|
| 106 |
+
} catch (error) {
|
| 107 |
+
console.error('Export error:', error);
|
| 108 |
+
alert('Failed to export presentation. Please try again.');
|
| 109 |
+
}
|
| 110 |
+
};
|
| 111 |
+
|
| 112 |
+
if (currentView === 'edit' && slides.length > 0) {
|
| 113 |
+
return (
|
| 114 |
+
<SlideEditor
|
| 115 |
+
slides={slides}
|
| 116 |
+
onSlidesUpdate={setSlides}
|
| 117 |
+
onBack={() => setCurrentView('generate')}
|
| 118 |
+
onPreview={() => setCurrentView('preview')}
|
| 119 |
+
onExport={exportToPowerPoint}
|
| 120 |
+
/>
|
| 121 |
+
);
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
if (currentView === 'preview' && slides.length > 0) {
|
| 125 |
+
return (
|
| 126 |
+
<SlidePreview
|
| 127 |
+
slides={slides}
|
| 128 |
+
onBack={() => setCurrentView('edit')}
|
| 129 |
+
onExport={exportToPowerPoint}
|
| 130 |
+
/>
|
| 131 |
+
);
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
return (
|
| 135 |
+
<div className="max-w-4xl mx-auto bg-white rounded-lg shadow-lg p-6">
|
| 136 |
+
<div className="mb-6">
|
| 137 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">Generate Your Presentation</h2>
|
| 138 |
+
|
| 139 |
+
<div className="space-y-4">
|
| 140 |
+
<div>
|
| 141 |
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
| 142 |
+
Presentation Topic
|
| 143 |
+
</label>
|
| 144 |
+
<textarea
|
| 145 |
+
value={prompt}
|
| 146 |
+
onChange={(e) => setPrompt(e.target.value)}
|
| 147 |
+
placeholder="Describe what you want your presentation to be about... (e.g., 'Create a 5-slide presentation about renewable energy sources including solar, wind, and hydroelectric power with benefits and challenges')"
|
| 148 |
+
className="w-full h-32 border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none"
|
| 149 |
+
/>
|
| 150 |
+
</div>
|
| 151 |
+
|
| 152 |
+
<ModelSelector
|
| 153 |
+
selectedModel={selectedModel}
|
| 154 |
+
customModel={customModel}
|
| 155 |
+
onModelSelect={setSelectedModel}
|
| 156 |
+
onCustomModelChange={setCustomModel}
|
| 157 |
+
/>
|
| 158 |
+
|
| 159 |
+
<button
|
| 160 |
+
onClick={generatePresentation}
|
| 161 |
+
disabled={isGenerating}
|
| 162 |
+
className="w-full bg-gradient-to-r from-blue-500 to-purple-600 hover:from-blue-600 hover:to-purple-700 text-white font-medium py-3 px-6 rounded-md transition-all duration-200 disabled:opacity-50 flex items-center justify-center gap-2"
|
| 163 |
+
>
|
| 164 |
+
<Wand2 className="w-5 h-5" />
|
| 165 |
+
{isGenerating ? 'Generating Presentation...' : 'Generate Presentation'}
|
| 166 |
+
</button>
|
| 167 |
+
</div>
|
| 168 |
+
</div>
|
| 169 |
+
|
| 170 |
+
{slides.length > 0 && (
|
| 171 |
+
<div className="border-t pt-6">
|
| 172 |
+
<div className="flex justify-between items-center mb-4">
|
| 173 |
+
<h3 className="text-lg font-semibold text-gray-800">
|
| 174 |
+
Generated Presentation ({slides.length} slides)
|
| 175 |
+
</h3>
|
| 176 |
+
<div className="flex gap-2">
|
| 177 |
+
<button
|
| 178 |
+
onClick={() => setCurrentView('edit')}
|
| 179 |
+
className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-md flex items-center gap-2"
|
| 180 |
+
>
|
| 181 |
+
<Edit className="w-4 h-4" />
|
| 182 |
+
Edit
|
| 183 |
+
</button>
|
| 184 |
+
<button
|
| 185 |
+
onClick={() => setCurrentView('preview')}
|
| 186 |
+
className="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-md flex items-center gap-2"
|
| 187 |
+
>
|
| 188 |
+
<Eye className="w-4 h-4" />
|
| 189 |
+
Preview
|
| 190 |
+
</button>
|
| 191 |
+
<button
|
| 192 |
+
onClick={exportToPowerPoint}
|
| 193 |
+
className="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded-md flex items-center gap-2"
|
| 194 |
+
>
|
| 195 |
+
<Download className="w-4 h-4" />
|
| 196 |
+
Export
|
| 197 |
+
</button>
|
| 198 |
+
</div>
|
| 199 |
+
</div>
|
| 200 |
+
|
| 201 |
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
| 202 |
+
{slides.map((slide, index) => (
|
| 203 |
+
<div
|
| 204 |
+
key={slide.id}
|
| 205 |
+
className="border border-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow"
|
| 206 |
+
>
|
| 207 |
+
<h4 className="font-semibold text-sm text-gray-600 mb-2">
|
| 208 |
+
Slide {index + 1}
|
| 209 |
+
</h4>
|
| 210 |
+
<h5 className="font-bold text-lg mb-2 line-clamp-2">{slide.title}</h5>
|
| 211 |
+
<div className="text-sm text-gray-600 line-clamp-3">
|
| 212 |
+
{slide.content.map((point, i) => (
|
| 213 |
+
<div key={i}>• {point}</div>
|
| 214 |
+
))}
|
| 215 |
+
</div>
|
| 216 |
+
</div>
|
| 217 |
+
))}
|
| 218 |
+
</div>
|
| 219 |
+
</div>
|
| 220 |
+
)}
|
| 221 |
+
</div>
|
| 222 |
+
);
|
| 223 |
+
}
|
components/SlideEditor.tsx
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { useState } from 'react';
|
| 4 |
+
import { ArrowLeft, Eye, Download, Plus, Trash2, Type, Palette } from 'lucide-react';
|
| 5 |
+
import { Slide } from './PresentationGenerator';
|
| 6 |
+
|
| 7 |
+
interface SlideEditorProps {
|
| 8 |
+
slides: Slide[];
|
| 9 |
+
onSlidesUpdate: (slides: Slide[]) => void;
|
| 10 |
+
onBack: () => void;
|
| 11 |
+
onPreview: () => void;
|
| 12 |
+
onExport: () => void;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
export function SlideEditor({ slides, onSlidesUpdate, onBack, onPreview, onExport }: SlideEditorProps) {
|
| 16 |
+
const [selectedSlideIndex, setSelectedSlideIndex] = useState(0);
|
| 17 |
+
const [fontSize, setFontSize] = useState('16');
|
| 18 |
+
const [fontFamily, setFontFamily] = useState('Arial');
|
| 19 |
+
const [textColor, setTextColor] = useState('#000000');
|
| 20 |
+
|
| 21 |
+
const currentSlide = slides[selectedSlideIndex];
|
| 22 |
+
|
| 23 |
+
const updateSlide = (updates: Partial<Slide>) => {
|
| 24 |
+
const updatedSlides = slides.map((slide, index) =>
|
| 25 |
+
index === selectedSlideIndex ? { ...slide, ...updates } : slide
|
| 26 |
+
);
|
| 27 |
+
onSlidesUpdate(updatedSlides);
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
const addSlide = () => {
|
| 31 |
+
const newSlide: Slide = {
|
| 32 |
+
id: `slide-${Date.now()}`,
|
| 33 |
+
title: 'New Slide',
|
| 34 |
+
content: ['Add your content here'],
|
| 35 |
+
notes: '',
|
| 36 |
+
};
|
| 37 |
+
const updatedSlides = [...slides, newSlide];
|
| 38 |
+
onSlidesUpdate(updatedSlides);
|
| 39 |
+
setSelectedSlideIndex(updatedSlides.length - 1);
|
| 40 |
+
};
|
| 41 |
+
|
| 42 |
+
const deleteSlide = (index: number) => {
|
| 43 |
+
if (slides.length <= 1) {
|
| 44 |
+
alert('Cannot delete the last slide');
|
| 45 |
+
return;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
const updatedSlides = slides.filter((_, i) => i !== index);
|
| 49 |
+
onSlidesUpdate(updatedSlides);
|
| 50 |
+
|
| 51 |
+
if (selectedSlideIndex >= updatedSlides.length) {
|
| 52 |
+
setSelectedSlideIndex(updatedSlides.length - 1);
|
| 53 |
+
}
|
| 54 |
+
};
|
| 55 |
+
|
| 56 |
+
const addContentPoint = () => {
|
| 57 |
+
const updatedContent = [...currentSlide.content, 'New bullet point'];
|
| 58 |
+
updateSlide({ content: updatedContent });
|
| 59 |
+
};
|
| 60 |
+
|
| 61 |
+
const updateContentPoint = (index: number, value: string) => {
|
| 62 |
+
const updatedContent = currentSlide.content.map((point, i) =>
|
| 63 |
+
i === index ? value : point
|
| 64 |
+
);
|
| 65 |
+
updateSlide({ content: updatedContent });
|
| 66 |
+
};
|
| 67 |
+
|
| 68 |
+
const deleteContentPoint = (index: number) => {
|
| 69 |
+
if (currentSlide.content.length <= 1) return;
|
| 70 |
+
|
| 71 |
+
const updatedContent = currentSlide.content.filter((_, i) => i !== index);
|
| 72 |
+
updateSlide({ content: updatedContent });
|
| 73 |
+
};
|
| 74 |
+
|
| 75 |
+
return (
|
| 76 |
+
<div className="max-w-7xl mx-auto bg-white rounded-lg shadow-lg overflow-hidden">
|
| 77 |
+
{/* Header */}
|
| 78 |
+
<div className="bg-gray-50 px-6 py-4 border-b flex items-center justify-between">
|
| 79 |
+
<div className="flex items-center gap-4">
|
| 80 |
+
<button
|
| 81 |
+
onClick={onBack}
|
| 82 |
+
className="flex items-center gap-2 text-gray-600 hover:text-gray-800"
|
| 83 |
+
>
|
| 84 |
+
<ArrowLeft className="w-4 h-4" />
|
| 85 |
+
Back to Generator
|
| 86 |
+
</button>
|
| 87 |
+
<h2 className="text-xl font-bold text-gray-800">Edit Presentation</h2>
|
| 88 |
+
</div>
|
| 89 |
+
|
| 90 |
+
<div className="flex gap-2">
|
| 91 |
+
<button
|
| 92 |
+
onClick={onPreview}
|
| 93 |
+
className="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded-md flex items-center gap-2"
|
| 94 |
+
>
|
| 95 |
+
<Eye className="w-4 h-4" />
|
| 96 |
+
Preview
|
| 97 |
+
</button>
|
| 98 |
+
<button
|
| 99 |
+
onClick={onExport}
|
| 100 |
+
className="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded-md flex items-center gap-2"
|
| 101 |
+
>
|
| 102 |
+
<Download className="w-4 h-4" />
|
| 103 |
+
Export
|
| 104 |
+
</button>
|
| 105 |
+
</div>
|
| 106 |
+
</div>
|
| 107 |
+
|
| 108 |
+
<div className="flex h-screen">
|
| 109 |
+
{/* Slide Thumbnails */}
|
| 110 |
+
<div className="w-64 bg-gray-50 border-r overflow-y-auto">
|
| 111 |
+
<div className="p-4">
|
| 112 |
+
<div className="flex items-center justify-between mb-4">
|
| 113 |
+
<h3 className="font-semibold text-gray-800">Slides</h3>
|
| 114 |
+
<button
|
| 115 |
+
onClick={addSlide}
|
| 116 |
+
className="bg-blue-500 hover:bg-blue-600 text-white p-2 rounded-md"
|
| 117 |
+
>
|
| 118 |
+
<Plus className="w-4 h-4" />
|
| 119 |
+
</button>
|
| 120 |
+
</div>
|
| 121 |
+
|
| 122 |
+
<div className="space-y-2">
|
| 123 |
+
{slides.map((slide, index) => (
|
| 124 |
+
<div
|
| 125 |
+
key={slide.id}
|
| 126 |
+
className={`border rounded-lg p-3 cursor-pointer transition-colors ${
|
| 127 |
+
selectedSlideIndex === index
|
| 128 |
+
? 'border-blue-500 bg-blue-50'
|
| 129 |
+
: 'border-gray-200 hover:border-gray-300'
|
| 130 |
+
}`}
|
| 131 |
+
onClick={() => setSelectedSlideIndex(index)}
|
| 132 |
+
>
|
| 133 |
+
<div className="flex items-center justify-between mb-2">
|
| 134 |
+
<span className="text-sm font-medium text-gray-600">
|
| 135 |
+
Slide {index + 1}
|
| 136 |
+
</span>
|
| 137 |
+
{slides.length > 1 && (
|
| 138 |
+
<button
|
| 139 |
+
onClick={(e) => {
|
| 140 |
+
e.stopPropagation();
|
| 141 |
+
deleteSlide(index);
|
| 142 |
+
}}
|
| 143 |
+
className="text-red-500 hover:text-red-700"
|
| 144 |
+
>
|
| 145 |
+
<Trash2 className="w-3 h-3" />
|
| 146 |
+
</button>
|
| 147 |
+
)}
|
| 148 |
+
</div>
|
| 149 |
+
<h4 className="text-sm font-bold line-clamp-2 mb-1">{slide.title}</h4>
|
| 150 |
+
<div className="text-xs text-gray-500 line-clamp-2">
|
| 151 |
+
{slide.content.slice(0, 2).map((point, i) => (
|
| 152 |
+
<div key={i}>• {point}</div>
|
| 153 |
+
))}
|
| 154 |
+
</div>
|
| 155 |
+
</div>
|
| 156 |
+
))}
|
| 157 |
+
</div>
|
| 158 |
+
</div>
|
| 159 |
+
</div>
|
| 160 |
+
|
| 161 |
+
{/* Main Editor */}
|
| 162 |
+
<div className="flex-1 flex">
|
| 163 |
+
{/* Content Editor */}
|
| 164 |
+
<div className="flex-1 p-6">
|
| 165 |
+
<div className="mb-6">
|
| 166 |
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
| 167 |
+
Slide Title
|
| 168 |
+
</label>
|
| 169 |
+
<input
|
| 170 |
+
type="text"
|
| 171 |
+
value={currentSlide.title}
|
| 172 |
+
onChange={(e) => updateSlide({ title: e.target.value })}
|
| 173 |
+
className="w-full border border-gray-300 rounded-md px-3 py-2 text-lg font-bold focus:outline-none focus:ring-2 focus:ring-blue-500"
|
| 174 |
+
/>
|
| 175 |
+
</div>
|
| 176 |
+
|
| 177 |
+
<div className="mb-6">
|
| 178 |
+
<div className="flex items-center justify-between mb-2">
|
| 179 |
+
<label className="block text-sm font-medium text-gray-700">
|
| 180 |
+
Content Points
|
| 181 |
+
</label>
|
| 182 |
+
<button
|
| 183 |
+
onClick={addContentPoint}
|
| 184 |
+
className="bg-blue-500 hover:bg-blue-600 text-white px-3 py-1 rounded-md text-sm flex items-center gap-1"
|
| 185 |
+
>
|
| 186 |
+
<Plus className="w-3 h-3" />
|
| 187 |
+
Add Point
|
| 188 |
+
</button>
|
| 189 |
+
</div>
|
| 190 |
+
|
| 191 |
+
<div className="space-y-3">
|
| 192 |
+
{currentSlide.content.map((point, index) => (
|
| 193 |
+
<div key={index} className="flex items-center gap-2">
|
| 194 |
+
<span className="text-gray-400">•</span>
|
| 195 |
+
<input
|
| 196 |
+
type="text"
|
| 197 |
+
value={point}
|
| 198 |
+
onChange={(e) => updateContentPoint(index, e.target.value)}
|
| 199 |
+
className="flex-1 border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
| 200 |
+
style={{
|
| 201 |
+
fontSize: `${fontSize}px`,
|
| 202 |
+
fontFamily,
|
| 203 |
+
color: textColor,
|
| 204 |
+
}}
|
| 205 |
+
/>
|
| 206 |
+
{currentSlide.content.length > 1 && (
|
| 207 |
+
<button
|
| 208 |
+
onClick={() => deleteContentPoint(index)}
|
| 209 |
+
className="text-red-500 hover:text-red-700"
|
| 210 |
+
>
|
| 211 |
+
<Trash2 className="w-4 h-4" />
|
| 212 |
+
</button>
|
| 213 |
+
)}
|
| 214 |
+
</div>
|
| 215 |
+
))}
|
| 216 |
+
</div>
|
| 217 |
+
</div>
|
| 218 |
+
|
| 219 |
+
<div>
|
| 220 |
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
| 221 |
+
Speaker Notes (Optional)
|
| 222 |
+
</label>
|
| 223 |
+
<textarea
|
| 224 |
+
value={currentSlide.notes || ''}
|
| 225 |
+
onChange={(e) => updateSlide({ notes: e.target.value })}
|
| 226 |
+
placeholder="Add speaker notes for this slide..."
|
| 227 |
+
className="w-full h-24 border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none"
|
| 228 |
+
/>
|
| 229 |
+
</div>
|
| 230 |
+
</div>
|
| 231 |
+
|
| 232 |
+
{/* Formatting Panel */}
|
| 233 |
+
<div className="w-64 bg-gray-50 border-l p-4">
|
| 234 |
+
<h3 className="font-semibold text-gray-800 mb-4 flex items-center gap-2">
|
| 235 |
+
<Type className="w-4 h-4" />
|
| 236 |
+
Formatting
|
| 237 |
+
</h3>
|
| 238 |
+
|
| 239 |
+
<div className="space-y-4">
|
| 240 |
+
<div>
|
| 241 |
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
| 242 |
+
Font Family
|
| 243 |
+
</label>
|
| 244 |
+
<select
|
| 245 |
+
value={fontFamily}
|
| 246 |
+
onChange={(e) => setFontFamily(e.target.value)}
|
| 247 |
+
className="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
| 248 |
+
>
|
| 249 |
+
<option value="Arial">Arial</option>
|
| 250 |
+
<option value="Helvetica">Helvetica</option>
|
| 251 |
+
<option value="Times New Roman">Times New Roman</option>
|
| 252 |
+
<option value="Georgia">Georgia</option>
|
| 253 |
+
<option value="Courier New">Courier New</option>
|
| 254 |
+
<option value="Verdana">Verdana</option>
|
| 255 |
+
</select>
|
| 256 |
+
</div>
|
| 257 |
+
|
| 258 |
+
<div>
|
| 259 |
+
<label className="block text-sm font-medium text-gray-700 mb-2">
|
| 260 |
+
Font Size
|
| 261 |
+
</label>
|
| 262 |
+
<input
|
| 263 |
+
type="range"
|
| 264 |
+
min="12"
|
| 265 |
+
max="24"
|
| 266 |
+
value={fontSize}
|
| 267 |
+
onChange={(e) => setFontSize(e.target.value)}
|
| 268 |
+
className="w-full"
|
| 269 |
+
/>
|
| 270 |
+
<div className="text-sm text-gray-600 text-center">{fontSize}px</div>
|
| 271 |
+
</div>
|
| 272 |
+
|
| 273 |
+
<div>
|
| 274 |
+
<label className="block text-sm font-medium text-gray-700 mb-2 flex items-center gap-2">
|
| 275 |
+
<Palette className="w-4 h-4" />
|
| 276 |
+
Text Color
|
| 277 |
+
</label>
|
| 278 |
+
<input
|
| 279 |
+
type="color"
|
| 280 |
+
value={textColor}
|
| 281 |
+
onChange={(e) => setTextColor(e.target.value)}
|
| 282 |
+
className="w-full h-10 border border-gray-300 rounded-md cursor-pointer"
|
| 283 |
+
/>
|
| 284 |
+
</div>
|
| 285 |
+
</div>
|
| 286 |
+
</div>
|
| 287 |
+
</div>
|
| 288 |
+
</div>
|
| 289 |
+
</div>
|
| 290 |
+
);
|
| 291 |
+
}
|
components/SlidePreview.tsx
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
'use client';
|
| 2 |
+
|
| 3 |
+
import { useState } from 'react';
|
| 4 |
+
import { ArrowLeft, ArrowRight, Download } from 'lucide-react';
|
| 5 |
+
import { Slide } from './PresentationGenerator';
|
| 6 |
+
|
| 7 |
+
interface SlidePreviewProps {
|
| 8 |
+
slides: Slide[];
|
| 9 |
+
onBack: () => void;
|
| 10 |
+
onExport: () => void;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
export function SlidePreview({ slides, onBack, onExport }: SlidePreviewProps) {
|
| 14 |
+
const [currentSlideIndex, setCurrentSlideIndex] = useState(0);
|
| 15 |
+
|
| 16 |
+
const currentSlide = slides[currentSlideIndex];
|
| 17 |
+
|
| 18 |
+
const nextSlide = () => {
|
| 19 |
+
if (currentSlideIndex < slides.length - 1) {
|
| 20 |
+
setCurrentSlideIndex(currentSlideIndex + 1);
|
| 21 |
+
}
|
| 22 |
+
};
|
| 23 |
+
|
| 24 |
+
const prevSlide = () => {
|
| 25 |
+
if (currentSlideIndex > 0) {
|
| 26 |
+
setCurrentSlideIndex(currentSlideIndex - 1);
|
| 27 |
+
}
|
| 28 |
+
};
|
| 29 |
+
|
| 30 |
+
const goToSlide = (index: number) => {
|
| 31 |
+
setCurrentSlideIndex(index);
|
| 32 |
+
};
|
| 33 |
+
|
| 34 |
+
return (
|
| 35 |
+
<div className="max-w-7xl mx-auto bg-white rounded-lg shadow-lg overflow-hidden">
|
| 36 |
+
{/* Header */}
|
| 37 |
+
<div className="bg-gray-50 px-6 py-4 border-b flex items-center justify-between">
|
| 38 |
+
<div className="flex items-center gap-4">
|
| 39 |
+
<button
|
| 40 |
+
onClick={onBack}
|
| 41 |
+
className="flex items-center gap-2 text-gray-600 hover:text-gray-800"
|
| 42 |
+
>
|
| 43 |
+
<ArrowLeft className="w-4 h-4" />
|
| 44 |
+
Back to Editor
|
| 45 |
+
</button>
|
| 46 |
+
<h2 className="text-xl font-bold text-gray-800">
|
| 47 |
+
Preview Mode - Slide {currentSlideIndex + 1} of {slides.length}
|
| 48 |
+
</h2>
|
| 49 |
+
</div>
|
| 50 |
+
|
| 51 |
+
<div className="flex gap-2">
|
| 52 |
+
<button
|
| 53 |
+
onClick={onExport}
|
| 54 |
+
className="bg-purple-500 hover:bg-purple-600 text-white px-4 py-2 rounded-md flex items-center gap-2"
|
| 55 |
+
>
|
| 56 |
+
<Download className="w-4 h-4" />
|
| 57 |
+
Export PowerPoint
|
| 58 |
+
</button>
|
| 59 |
+
</div>
|
| 60 |
+
</div>
|
| 61 |
+
|
| 62 |
+
<div className="flex h-screen">
|
| 63 |
+
{/* Slide Navigation */}
|
| 64 |
+
<div className="w-64 bg-gray-50 border-r overflow-y-auto">
|
| 65 |
+
<div className="p-4">
|
| 66 |
+
<h3 className="font-semibold text-gray-800 mb-4">Slides</h3>
|
| 67 |
+
<div className="space-y-2">
|
| 68 |
+
{slides.map((slide, index) => (
|
| 69 |
+
<button
|
| 70 |
+
key={slide.id}
|
| 71 |
+
onClick={() => goToSlide(index)}
|
| 72 |
+
className={`w-full text-left border rounded-lg p-3 transition-colors ${
|
| 73 |
+
currentSlideIndex === index
|
| 74 |
+
? 'border-blue-500 bg-blue-50'
|
| 75 |
+
: 'border-gray-200 hover:border-gray-300'
|
| 76 |
+
}`}
|
| 77 |
+
>
|
| 78 |
+
<div className="text-sm font-medium text-gray-600 mb-1">
|
| 79 |
+
Slide {index + 1}
|
| 80 |
+
</div>
|
| 81 |
+
<h4 className="text-sm font-bold line-clamp-2">{slide.title}</h4>
|
| 82 |
+
</button>
|
| 83 |
+
))}
|
| 84 |
+
</div>
|
| 85 |
+
</div>
|
| 86 |
+
</div>
|
| 87 |
+
|
| 88 |
+
{/* Main Slide Preview */}
|
| 89 |
+
<div className="flex-1 flex flex-col">
|
| 90 |
+
{/* Slide Content */}
|
| 91 |
+
<div className="flex-1 p-8 flex items-center justify-center bg-gray-100">
|
| 92 |
+
<div className="w-full max-w-4xl aspect-[16/9] bg-white rounded-lg shadow-lg p-12 flex flex-col">
|
| 93 |
+
{/* Slide Title */}
|
| 94 |
+
<h1 className="text-4xl font-bold text-gray-800 mb-8 text-center">
|
| 95 |
+
{currentSlide.title}
|
| 96 |
+
</h1>
|
| 97 |
+
|
| 98 |
+
{/* Slide Content */}
|
| 99 |
+
<div className="flex-1 flex flex-col justify-center">
|
| 100 |
+
<ul className="space-y-4">
|
| 101 |
+
{currentSlide.content.map((point, index) => (
|
| 102 |
+
<li
|
| 103 |
+
key={index}
|
| 104 |
+
className="text-xl text-gray-700 flex items-start gap-3"
|
| 105 |
+
>
|
| 106 |
+
<span className="text-blue-500 font-bold mt-1">•</span>
|
| 107 |
+
<span>{point}</span>
|
| 108 |
+
</li>
|
| 109 |
+
))}
|
| 110 |
+
</ul>
|
| 111 |
+
</div>
|
| 112 |
+
|
| 113 |
+
{/* Slide Number */}
|
| 114 |
+
<div className="text-right text-sm text-gray-400 mt-4">
|
| 115 |
+
{currentSlideIndex + 1} / {slides.length}
|
| 116 |
+
</div>
|
| 117 |
+
</div>
|
| 118 |
+
</div>
|
| 119 |
+
|
| 120 |
+
{/* Navigation Controls */}
|
| 121 |
+
<div className="bg-white border-t px-6 py-4 flex items-center justify-between">
|
| 122 |
+
<button
|
| 123 |
+
onClick={prevSlide}
|
| 124 |
+
disabled={currentSlideIndex === 0}
|
| 125 |
+
className="flex items-center gap-2 px-4 py-2 bg-gray-500 hover:bg-gray-600 disabled:bg-gray-300 text-white rounded-md transition-colors"
|
| 126 |
+
>
|
| 127 |
+
<ArrowLeft className="w-4 h-4" />
|
| 128 |
+
Previous
|
| 129 |
+
</button>
|
| 130 |
+
|
| 131 |
+
<div className="flex items-center gap-2">
|
| 132 |
+
{slides.map((_, index) => (
|
| 133 |
+
<button
|
| 134 |
+
key={index}
|
| 135 |
+
onClick={() => goToSlide(index)}
|
| 136 |
+
className={`w-3 h-3 rounded-full transition-colors ${
|
| 137 |
+
currentSlideIndex === index ? 'bg-blue-500' : 'bg-gray-300'
|
| 138 |
+
}`}
|
| 139 |
+
/>
|
| 140 |
+
))}
|
| 141 |
+
</div>
|
| 142 |
+
|
| 143 |
+
<button
|
| 144 |
+
onClick={nextSlide}
|
| 145 |
+
disabled={currentSlideIndex === slides.length - 1}
|
| 146 |
+
className="flex items-center gap-2 px-4 py-2 bg-gray-500 hover:bg-gray-600 disabled:bg-gray-300 text-white rounded-md transition-colors"
|
| 147 |
+
>
|
| 148 |
+
Next
|
| 149 |
+
<ArrowRight className="w-4 h-4" />
|
| 150 |
+
</button>
|
| 151 |
+
</div>
|
| 152 |
+
|
| 153 |
+
{/* Speaker Notes */}
|
| 154 |
+
{currentSlide.notes && (
|
| 155 |
+
<div className="bg-yellow-50 border-t border-yellow-200 px-6 py-4">
|
| 156 |
+
<h4 className="font-semibold text-gray-800 mb-2">Speaker Notes:</h4>
|
| 157 |
+
<p className="text-gray-700">{currentSlide.notes}</p>
|
| 158 |
+
</div>
|
| 159 |
+
)}
|
| 160 |
+
</div>
|
| 161 |
+
</div>
|
| 162 |
+
</div>
|
| 163 |
+
);
|
| 164 |
+
}
|
package-lock.json
CHANGED
|
@@ -8,7 +8,15 @@
|
|
| 8 |
"name": "powerpoint",
|
| 9 |
"version": "0.1.0",
|
| 10 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
"next": "15.5.3",
|
|
|
|
|
|
|
| 12 |
"react": "19.1.0",
|
| 13 |
"react-dom": "19.1.0"
|
| 14 |
},
|
|
@@ -37,6 +45,46 @@
|
|
| 37 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 38 |
}
|
| 39 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
"node_modules/@emnapi/core": {
|
| 41 |
"version": "1.5.0",
|
| 42 |
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
|
|
@@ -211,6 +259,34 @@
|
|
| 211 |
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
| 212 |
}
|
| 213 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
"node_modules/@humanfs/core": {
|
| 215 |
"version": "0.19.1",
|
| 216 |
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
|
@@ -949,6 +1025,15 @@
|
|
| 949 |
"node": ">=12.4.0"
|
| 950 |
}
|
| 951 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 952 |
"node_modules/@rtsao/scc": {
|
| 953 |
"version": "1.1.0",
|
| 954 |
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
|
|
@@ -1259,6 +1344,12 @@
|
|
| 1259 |
"tslib": "^2.4.0"
|
| 1260 |
}
|
| 1261 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1262 |
"node_modules/@types/estree": {
|
| 1263 |
"version": "1.0.8",
|
| 1264 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
|
@@ -1290,6 +1381,19 @@
|
|
| 1290 |
"undici-types": "~6.21.0"
|
| 1291 |
}
|
| 1292 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1293 |
"node_modules/@types/react": {
|
| 1294 |
"version": "19.1.13",
|
| 1295 |
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz",
|
|
@@ -1310,6 +1414,13 @@
|
|
| 1310 |
"@types/react": "^19.0.0"
|
| 1311 |
}
|
| 1312 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1313 |
"node_modules/@typescript-eslint/eslint-plugin": {
|
| 1314 |
"version": "8.44.0",
|
| 1315 |
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.0.tgz",
|
|
@@ -2117,6 +2228,12 @@
|
|
| 2117 |
"node": ">= 0.4"
|
| 2118 |
}
|
| 2119 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2120 |
"node_modules/available-typed-arrays": {
|
| 2121 |
"version": "1.0.7",
|
| 2122 |
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
|
@@ -2143,6 +2260,17 @@
|
|
| 2143 |
"node": ">=4"
|
| 2144 |
}
|
| 2145 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2146 |
"node_modules/axobject-query": {
|
| 2147 |
"version": "4.1.0",
|
| 2148 |
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
|
@@ -2160,6 +2288,15 @@
|
|
| 2160 |
"dev": true,
|
| 2161 |
"license": "MIT"
|
| 2162 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2163 |
"node_modules/brace-expansion": {
|
| 2164 |
"version": "1.1.12",
|
| 2165 |
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
|
@@ -2207,7 +2344,6 @@
|
|
| 2207 |
"version": "1.0.2",
|
| 2208 |
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
| 2209 |
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
| 2210 |
-
"dev": true,
|
| 2211 |
"license": "MIT",
|
| 2212 |
"dependencies": {
|
| 2213 |
"es-errors": "^1.3.0",
|
|
@@ -2264,6 +2400,26 @@
|
|
| 2264 |
],
|
| 2265 |
"license": "CC-BY-4.0"
|
| 2266 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2267 |
"node_modules/chalk": {
|
| 2268 |
"version": "4.1.2",
|
| 2269 |
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
@@ -2342,6 +2498,18 @@
|
|
| 2342 |
"simple-swizzle": "^0.2.2"
|
| 2343 |
}
|
| 2344 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2345 |
"node_modules/concat-map": {
|
| 2346 |
"version": "0.0.1",
|
| 2347 |
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
@@ -2349,6 +2517,33 @@
|
|
| 2349 |
"dev": true,
|
| 2350 |
"license": "MIT"
|
| 2351 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2352 |
"node_modules/cross-spawn": {
|
| 2353 |
"version": "7.0.6",
|
| 2354 |
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
|
@@ -2364,6 +2559,15 @@
|
|
| 2364 |
"node": ">= 8"
|
| 2365 |
}
|
| 2366 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2367 |
"node_modules/csstype": {
|
| 2368 |
"version": "3.1.3",
|
| 2369 |
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
|
@@ -2493,6 +2697,15 @@
|
|
| 2493 |
"url": "https://github.com/sponsors/ljharb"
|
| 2494 |
}
|
| 2495 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2496 |
"node_modules/detect-libc": {
|
| 2497 |
"version": "2.1.0",
|
| 2498 |
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz",
|
|
@@ -2516,11 +2729,20 @@
|
|
| 2516 |
"node": ">=0.10.0"
|
| 2517 |
}
|
| 2518 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2519 |
"node_modules/dunder-proto": {
|
| 2520 |
"version": "1.0.1",
|
| 2521 |
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
| 2522 |
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
| 2523 |
-
"dev": true,
|
| 2524 |
"license": "MIT",
|
| 2525 |
"dependencies": {
|
| 2526 |
"call-bind-apply-helpers": "^1.0.1",
|
|
@@ -2625,7 +2847,6 @@
|
|
| 2625 |
"version": "1.0.1",
|
| 2626 |
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
| 2627 |
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
| 2628 |
-
"dev": true,
|
| 2629 |
"license": "MIT",
|
| 2630 |
"engines": {
|
| 2631 |
"node": ">= 0.4"
|
|
@@ -2635,7 +2856,6 @@
|
|
| 2635 |
"version": "1.3.0",
|
| 2636 |
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
| 2637 |
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
| 2638 |
-
"dev": true,
|
| 2639 |
"license": "MIT",
|
| 2640 |
"engines": {
|
| 2641 |
"node": ">= 0.4"
|
|
@@ -2673,7 +2893,6 @@
|
|
| 2673 |
"version": "1.1.1",
|
| 2674 |
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
| 2675 |
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
| 2676 |
-
"dev": true,
|
| 2677 |
"license": "MIT",
|
| 2678 |
"dependencies": {
|
| 2679 |
"es-errors": "^1.3.0"
|
|
@@ -2686,7 +2905,6 @@
|
|
| 2686 |
"version": "2.1.0",
|
| 2687 |
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
| 2688 |
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
| 2689 |
-
"dev": true,
|
| 2690 |
"license": "MIT",
|
| 2691 |
"dependencies": {
|
| 2692 |
"es-errors": "^1.3.0",
|
|
@@ -3219,6 +3437,17 @@
|
|
| 3219 |
"dev": true,
|
| 3220 |
"license": "MIT"
|
| 3221 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3222 |
"node_modules/fastq": {
|
| 3223 |
"version": "1.19.1",
|
| 3224 |
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
|
|
@@ -3229,6 +3458,12 @@
|
|
| 3229 |
"reusify": "^1.0.4"
|
| 3230 |
}
|
| 3231 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3232 |
"node_modules/file-entry-cache": {
|
| 3233 |
"version": "8.0.0",
|
| 3234 |
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
|
@@ -3293,6 +3528,26 @@
|
|
| 3293 |
"dev": true,
|
| 3294 |
"license": "ISC"
|
| 3295 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3296 |
"node_modules/for-each": {
|
| 3297 |
"version": "0.3.5",
|
| 3298 |
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
|
|
@@ -3309,11 +3564,26 @@
|
|
| 3309 |
"url": "https://github.com/sponsors/ljharb"
|
| 3310 |
}
|
| 3311 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3312 |
"node_modules/function-bind": {
|
| 3313 |
"version": "1.1.2",
|
| 3314 |
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
| 3315 |
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
| 3316 |
-
"dev": true,
|
| 3317 |
"license": "MIT",
|
| 3318 |
"funding": {
|
| 3319 |
"url": "https://github.com/sponsors/ljharb"
|
|
@@ -3354,7 +3624,6 @@
|
|
| 3354 |
"version": "1.3.0",
|
| 3355 |
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
| 3356 |
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
| 3357 |
-
"dev": true,
|
| 3358 |
"license": "MIT",
|
| 3359 |
"dependencies": {
|
| 3360 |
"call-bind-apply-helpers": "^1.0.2",
|
|
@@ -3379,7 +3648,6 @@
|
|
| 3379 |
"version": "1.0.1",
|
| 3380 |
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
| 3381 |
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
| 3382 |
-
"dev": true,
|
| 3383 |
"license": "MIT",
|
| 3384 |
"dependencies": {
|
| 3385 |
"dunder-proto": "^1.0.1",
|
|
@@ -3467,7 +3735,6 @@
|
|
| 3467 |
"version": "1.2.0",
|
| 3468 |
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
| 3469 |
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
| 3470 |
-
"dev": true,
|
| 3471 |
"license": "MIT",
|
| 3472 |
"engines": {
|
| 3473 |
"node": ">= 0.4"
|
|
@@ -3546,7 +3813,6 @@
|
|
| 3546 |
"version": "1.1.0",
|
| 3547 |
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
| 3548 |
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
| 3549 |
-
"dev": true,
|
| 3550 |
"license": "MIT",
|
| 3551 |
"engines": {
|
| 3552 |
"node": ">= 0.4"
|
|
@@ -3559,7 +3825,6 @@
|
|
| 3559 |
"version": "1.0.2",
|
| 3560 |
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
| 3561 |
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
| 3562 |
-
"dev": true,
|
| 3563 |
"license": "MIT",
|
| 3564 |
"dependencies": {
|
| 3565 |
"has-symbols": "^1.0.3"
|
|
@@ -3575,7 +3840,6 @@
|
|
| 3575 |
"version": "2.0.2",
|
| 3576 |
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
| 3577 |
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
| 3578 |
-
"dev": true,
|
| 3579 |
"license": "MIT",
|
| 3580 |
"dependencies": {
|
| 3581 |
"function-bind": "^1.1.2"
|
|
@@ -3584,6 +3848,25 @@
|
|
| 3584 |
"node": ">= 0.4"
|
| 3585 |
}
|
| 3586 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3587 |
"node_modules/ignore": {
|
| 3588 |
"version": "5.3.2",
|
| 3589 |
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
|
@@ -3594,6 +3877,27 @@
|
|
| 3594 |
"node": ">= 4"
|
| 3595 |
}
|
| 3596 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3597 |
"node_modules/import-fresh": {
|
| 3598 |
"version": "3.3.1",
|
| 3599 |
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
|
@@ -3621,6 +3925,12 @@
|
|
| 3621 |
"node": ">=0.8.19"
|
| 3622 |
}
|
| 3623 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3624 |
"node_modules/internal-slot": {
|
| 3625 |
"version": "1.1.0",
|
| 3626 |
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
|
@@ -3636,6 +3946,12 @@
|
|
| 3636 |
"node": ">= 0.4"
|
| 3637 |
}
|
| 3638 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3639 |
"node_modules/is-array-buffer": {
|
| 3640 |
"version": "3.0.5",
|
| 3641 |
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
|
@@ -4086,6 +4402,15 @@
|
|
| 4086 |
"jiti": "lib/jiti-cli.mjs"
|
| 4087 |
}
|
| 4088 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4089 |
"node_modules/js-tokens": {
|
| 4090 |
"version": "4.0.0",
|
| 4091 |
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
|
@@ -4140,6 +4465,23 @@
|
|
| 4140 |
"json5": "lib/cli.js"
|
| 4141 |
}
|
| 4142 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4143 |
"node_modules/jsx-ast-utils": {
|
| 4144 |
"version": "3.3.5",
|
| 4145 |
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
|
@@ -4156,6 +4498,24 @@
|
|
| 4156 |
"node": ">=4.0"
|
| 4157 |
}
|
| 4158 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4159 |
"node_modules/keyv": {
|
| 4160 |
"version": "4.5.4",
|
| 4161 |
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
|
@@ -4200,6 +4560,15 @@
|
|
| 4200 |
"node": ">= 0.8.0"
|
| 4201 |
}
|
| 4202 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4203 |
"node_modules/lightningcss": {
|
| 4204 |
"version": "1.30.1",
|
| 4205 |
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
|
@@ -4475,6 +4844,33 @@
|
|
| 4475 |
"loose-envify": "cli.js"
|
| 4476 |
}
|
| 4477 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4478 |
"node_modules/magic-string": {
|
| 4479 |
"version": "0.30.19",
|
| 4480 |
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
|
@@ -4489,7 +4885,6 @@
|
|
| 4489 |
"version": "1.1.0",
|
| 4490 |
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
| 4491 |
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
| 4492 |
-
"dev": true,
|
| 4493 |
"license": "MIT",
|
| 4494 |
"engines": {
|
| 4495 |
"node": ">= 0.4"
|
|
@@ -4519,6 +4914,27 @@
|
|
| 4519 |
"node": ">=8.6"
|
| 4520 |
}
|
| 4521 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4522 |
"node_modules/minimatch": {
|
| 4523 |
"version": "3.1.2",
|
| 4524 |
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
|
@@ -4681,6 +5097,56 @@
|
|
| 4681 |
}
|
| 4682 |
}
|
| 4683 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4684 |
"node_modules/next/node_modules/postcss": {
|
| 4685 |
"version": "8.4.31",
|
| 4686 |
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
|
@@ -4709,6 +5175,21 @@
|
|
| 4709 |
"node": "^10 || ^12 || >=14"
|
| 4710 |
}
|
| 4711 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4712 |
"node_modules/object-assign": {
|
| 4713 |
"version": "4.1.1",
|
| 4714 |
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
|
@@ -4719,6 +5200,15 @@
|
|
| 4719 |
"node": ">=0.10.0"
|
| 4720 |
}
|
| 4721 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4722 |
"node_modules/object-inspect": {
|
| 4723 |
"version": "1.13.4",
|
| 4724 |
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
|
@@ -4832,6 +5322,39 @@
|
|
| 4832 |
"url": "https://github.com/sponsors/ljharb"
|
| 4833 |
}
|
| 4834 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4835 |
"node_modules/optionator": {
|
| 4836 |
"version": "0.9.4",
|
| 4837 |
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
|
@@ -4900,6 +5423,12 @@
|
|
| 4900 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 4901 |
}
|
| 4902 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4903 |
"node_modules/parent-module": {
|
| 4904 |
"version": "1.0.1",
|
| 4905 |
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
|
@@ -4940,6 +5469,13 @@
|
|
| 4940 |
"dev": true,
|
| 4941 |
"license": "MIT"
|
| 4942 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4943 |
"node_modules/picocolors": {
|
| 4944 |
"version": "1.1.1",
|
| 4945 |
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
|
@@ -4998,6 +5534,49 @@
|
|
| 4998 |
"node": "^10 || ^12 || >=14"
|
| 4999 |
}
|
| 5000 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5001 |
"node_modules/prelude-ls": {
|
| 5002 |
"version": "1.2.1",
|
| 5003 |
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
|
@@ -5008,6 +5587,18 @@
|
|
| 5008 |
"node": ">= 0.8.0"
|
| 5009 |
}
|
| 5010 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5011 |
"node_modules/prop-types": {
|
| 5012 |
"version": "15.8.1",
|
| 5013 |
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
|
@@ -5020,6 +5611,12 @@
|
|
| 5020 |
"react-is": "^16.13.1"
|
| 5021 |
}
|
| 5022 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5023 |
"node_modules/punycode": {
|
| 5024 |
"version": "2.3.1",
|
| 5025 |
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
|
@@ -5030,6 +5627,15 @@
|
|
| 5030 |
"node": ">=6"
|
| 5031 |
}
|
| 5032 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5033 |
"node_modules/queue-microtask": {
|
| 5034 |
"version": "1.2.3",
|
| 5035 |
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
|
@@ -5051,6 +5657,16 @@
|
|
| 5051 |
],
|
| 5052 |
"license": "MIT"
|
| 5053 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5054 |
"node_modules/react": {
|
| 5055 |
"version": "19.1.0",
|
| 5056 |
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
|
@@ -5079,6 +5695,27 @@
|
|
| 5079 |
"dev": true,
|
| 5080 |
"license": "MIT"
|
| 5081 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5082 |
"node_modules/reflect.getprototypeof": {
|
| 5083 |
"version": "1.0.10",
|
| 5084 |
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
|
@@ -5102,6 +5739,13 @@
|
|
| 5102 |
"url": "https://github.com/sponsors/ljharb"
|
| 5103 |
}
|
| 5104 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5105 |
"node_modules/regexp.prototype.flags": {
|
| 5106 |
"version": "1.5.4",
|
| 5107 |
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
|
|
@@ -5175,6 +5819,16 @@
|
|
| 5175 |
"node": ">=0.10.0"
|
| 5176 |
}
|
| 5177 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5178 |
"node_modules/run-parallel": {
|
| 5179 |
"version": "1.2.0",
|
| 5180 |
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
|
@@ -5219,6 +5873,12 @@
|
|
| 5219 |
"url": "https://github.com/sponsors/ljharb"
|
| 5220 |
}
|
| 5221 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5222 |
"node_modules/safe-push-apply": {
|
| 5223 |
"version": "1.0.0",
|
| 5224 |
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
|
|
@@ -5322,6 +5982,12 @@
|
|
| 5322 |
"node": ">= 0.4"
|
| 5323 |
}
|
| 5324 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5325 |
"node_modules/sharp": {
|
| 5326 |
"version": "0.34.3",
|
| 5327 |
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz",
|
|
@@ -5490,6 +6156,16 @@
|
|
| 5490 |
"dev": true,
|
| 5491 |
"license": "MIT"
|
| 5492 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5493 |
"node_modules/stop-iteration-iterator": {
|
| 5494 |
"version": "1.1.0",
|
| 5495 |
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
|
|
@@ -5504,6 +6180,15 @@
|
|
| 5504 |
"node": ">= 0.4"
|
| 5505 |
}
|
| 5506 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5507 |
"node_modules/string.prototype.includes": {
|
| 5508 |
"version": "2.0.1",
|
| 5509 |
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
|
|
@@ -5689,6 +6374,16 @@
|
|
| 5689 |
"url": "https://github.com/sponsors/ljharb"
|
| 5690 |
}
|
| 5691 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5692 |
"node_modules/tailwindcss": {
|
| 5693 |
"version": "4.1.13",
|
| 5694 |
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz",
|
|
@@ -5728,6 +6423,15 @@
|
|
| 5728 |
"node": ">=18"
|
| 5729 |
}
|
| 5730 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5731 |
"node_modules/tinyglobby": {
|
| 5732 |
"version": "0.2.15",
|
| 5733 |
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
|
@@ -5949,7 +6653,6 @@
|
|
| 5949 |
"version": "6.21.0",
|
| 5950 |
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
| 5951 |
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
| 5952 |
-
"dev": true,
|
| 5953 |
"license": "MIT"
|
| 5954 |
},
|
| 5955 |
"node_modules/unrs-resolver": {
|
|
@@ -5997,6 +6700,30 @@
|
|
| 5997 |
"punycode": "^2.1.0"
|
| 5998 |
}
|
| 5999 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6000 |
"node_modules/which": {
|
| 6001 |
"version": "2.0.2",
|
| 6002 |
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
|
|
| 8 |
"name": "powerpoint",
|
| 9 |
"version": "0.1.0",
|
| 10 |
"dependencies": {
|
| 11 |
+
"@auth/core": "^0.34.2",
|
| 12 |
+
"@huggingface/inference": "^4.8.0",
|
| 13 |
+
"axios": "^1.12.2",
|
| 14 |
+
"html2canvas": "^1.4.1",
|
| 15 |
+
"jspdf": "^3.0.2",
|
| 16 |
+
"lucide-react": "^0.544.0",
|
| 17 |
"next": "15.5.3",
|
| 18 |
+
"next-auth": "^4.24.11",
|
| 19 |
+
"pptxgenjs": "^4.0.1",
|
| 20 |
"react": "19.1.0",
|
| 21 |
"react-dom": "19.1.0"
|
| 22 |
},
|
|
|
|
| 45 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 46 |
}
|
| 47 |
},
|
| 48 |
+
"node_modules/@auth/core": {
|
| 49 |
+
"version": "0.34.2",
|
| 50 |
+
"resolved": "https://registry.npmjs.org/@auth/core/-/core-0.34.2.tgz",
|
| 51 |
+
"integrity": "sha512-KywHKRgLiF3l7PLyL73fjLSIBe1YNcA6sMeew4yMP6cfCWGXZrkkXd32AjRi1hlJ9nvovUBGZHvbn+LijO6ZeQ==",
|
| 52 |
+
"license": "ISC",
|
| 53 |
+
"dependencies": {
|
| 54 |
+
"@panva/hkdf": "^1.1.1",
|
| 55 |
+
"@types/cookie": "0.6.0",
|
| 56 |
+
"cookie": "0.6.0",
|
| 57 |
+
"jose": "^5.1.3",
|
| 58 |
+
"oauth4webapi": "^2.10.4",
|
| 59 |
+
"preact": "10.11.3",
|
| 60 |
+
"preact-render-to-string": "5.2.3"
|
| 61 |
+
},
|
| 62 |
+
"peerDependencies": {
|
| 63 |
+
"@simplewebauthn/browser": "^9.0.1",
|
| 64 |
+
"@simplewebauthn/server": "^9.0.2",
|
| 65 |
+
"nodemailer": "^6.8.0"
|
| 66 |
+
},
|
| 67 |
+
"peerDependenciesMeta": {
|
| 68 |
+
"@simplewebauthn/browser": {
|
| 69 |
+
"optional": true
|
| 70 |
+
},
|
| 71 |
+
"@simplewebauthn/server": {
|
| 72 |
+
"optional": true
|
| 73 |
+
},
|
| 74 |
+
"nodemailer": {
|
| 75 |
+
"optional": true
|
| 76 |
+
}
|
| 77 |
+
}
|
| 78 |
+
},
|
| 79 |
+
"node_modules/@babel/runtime": {
|
| 80 |
+
"version": "7.28.4",
|
| 81 |
+
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz",
|
| 82 |
+
"integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==",
|
| 83 |
+
"license": "MIT",
|
| 84 |
+
"engines": {
|
| 85 |
+
"node": ">=6.9.0"
|
| 86 |
+
}
|
| 87 |
+
},
|
| 88 |
"node_modules/@emnapi/core": {
|
| 89 |
"version": "1.5.0",
|
| 90 |
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
|
|
|
|
| 259 |
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
| 260 |
}
|
| 261 |
},
|
| 262 |
+
"node_modules/@huggingface/inference": {
|
| 263 |
+
"version": "4.8.0",
|
| 264 |
+
"resolved": "https://registry.npmjs.org/@huggingface/inference/-/inference-4.8.0.tgz",
|
| 265 |
+
"integrity": "sha512-Eq98EAXqYn4rKMfrbEXuhc3IjKfaeIO6eXNOZk9xk6v5akrIWRtd6d1h0fjAWyX4zRbdUpXRh6MvsqXnzGvXCA==",
|
| 266 |
+
"license": "MIT",
|
| 267 |
+
"dependencies": {
|
| 268 |
+
"@huggingface/jinja": "^0.5.1",
|
| 269 |
+
"@huggingface/tasks": "^0.19.45"
|
| 270 |
+
},
|
| 271 |
+
"engines": {
|
| 272 |
+
"node": ">=18"
|
| 273 |
+
}
|
| 274 |
+
},
|
| 275 |
+
"node_modules/@huggingface/jinja": {
|
| 276 |
+
"version": "0.5.1",
|
| 277 |
+
"resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.1.tgz",
|
| 278 |
+
"integrity": "sha512-yUZLld4lrM9iFxHCwFQ7D1HW2MWMwSbeB7WzWqFYDWK+rEb+WldkLdAJxUPOmgICMHZLzZGVcVjFh3w/YGubng==",
|
| 279 |
+
"license": "MIT",
|
| 280 |
+
"engines": {
|
| 281 |
+
"node": ">=18"
|
| 282 |
+
}
|
| 283 |
+
},
|
| 284 |
+
"node_modules/@huggingface/tasks": {
|
| 285 |
+
"version": "0.19.45",
|
| 286 |
+
"resolved": "https://registry.npmjs.org/@huggingface/tasks/-/tasks-0.19.45.tgz",
|
| 287 |
+
"integrity": "sha512-lM3QOgbfkGZ5gAZOYWOmzMM6BbKcXOIHjgnUAoymTdZEcEcGSr0vy/LWGEiK+vBXC4vU+sCT+WNoA/JZ8TEWdA==",
|
| 288 |
+
"license": "MIT"
|
| 289 |
+
},
|
| 290 |
"node_modules/@humanfs/core": {
|
| 291 |
"version": "0.19.1",
|
| 292 |
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
|
|
|
| 1025 |
"node": ">=12.4.0"
|
| 1026 |
}
|
| 1027 |
},
|
| 1028 |
+
"node_modules/@panva/hkdf": {
|
| 1029 |
+
"version": "1.2.1",
|
| 1030 |
+
"resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
|
| 1031 |
+
"integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==",
|
| 1032 |
+
"license": "MIT",
|
| 1033 |
+
"funding": {
|
| 1034 |
+
"url": "https://github.com/sponsors/panva"
|
| 1035 |
+
}
|
| 1036 |
+
},
|
| 1037 |
"node_modules/@rtsao/scc": {
|
| 1038 |
"version": "1.1.0",
|
| 1039 |
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
|
|
|
|
| 1344 |
"tslib": "^2.4.0"
|
| 1345 |
}
|
| 1346 |
},
|
| 1347 |
+
"node_modules/@types/cookie": {
|
| 1348 |
+
"version": "0.6.0",
|
| 1349 |
+
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
|
| 1350 |
+
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
|
| 1351 |
+
"license": "MIT"
|
| 1352 |
+
},
|
| 1353 |
"node_modules/@types/estree": {
|
| 1354 |
"version": "1.0.8",
|
| 1355 |
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
|
|
|
| 1381 |
"undici-types": "~6.21.0"
|
| 1382 |
}
|
| 1383 |
},
|
| 1384 |
+
"node_modules/@types/pako": {
|
| 1385 |
+
"version": "2.0.4",
|
| 1386 |
+
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz",
|
| 1387 |
+
"integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==",
|
| 1388 |
+
"license": "MIT"
|
| 1389 |
+
},
|
| 1390 |
+
"node_modules/@types/raf": {
|
| 1391 |
+
"version": "3.4.3",
|
| 1392 |
+
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz",
|
| 1393 |
+
"integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==",
|
| 1394 |
+
"license": "MIT",
|
| 1395 |
+
"optional": true
|
| 1396 |
+
},
|
| 1397 |
"node_modules/@types/react": {
|
| 1398 |
"version": "19.1.13",
|
| 1399 |
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.13.tgz",
|
|
|
|
| 1414 |
"@types/react": "^19.0.0"
|
| 1415 |
}
|
| 1416 |
},
|
| 1417 |
+
"node_modules/@types/trusted-types": {
|
| 1418 |
+
"version": "2.0.7",
|
| 1419 |
+
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
|
| 1420 |
+
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
|
| 1421 |
+
"license": "MIT",
|
| 1422 |
+
"optional": true
|
| 1423 |
+
},
|
| 1424 |
"node_modules/@typescript-eslint/eslint-plugin": {
|
| 1425 |
"version": "8.44.0",
|
| 1426 |
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.0.tgz",
|
|
|
|
| 2228 |
"node": ">= 0.4"
|
| 2229 |
}
|
| 2230 |
},
|
| 2231 |
+
"node_modules/asynckit": {
|
| 2232 |
+
"version": "0.4.0",
|
| 2233 |
+
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
| 2234 |
+
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
| 2235 |
+
"license": "MIT"
|
| 2236 |
+
},
|
| 2237 |
"node_modules/available-typed-arrays": {
|
| 2238 |
"version": "1.0.7",
|
| 2239 |
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
|
|
|
| 2260 |
"node": ">=4"
|
| 2261 |
}
|
| 2262 |
},
|
| 2263 |
+
"node_modules/axios": {
|
| 2264 |
+
"version": "1.12.2",
|
| 2265 |
+
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
|
| 2266 |
+
"integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
|
| 2267 |
+
"license": "MIT",
|
| 2268 |
+
"dependencies": {
|
| 2269 |
+
"follow-redirects": "^1.15.6",
|
| 2270 |
+
"form-data": "^4.0.4",
|
| 2271 |
+
"proxy-from-env": "^1.1.0"
|
| 2272 |
+
}
|
| 2273 |
+
},
|
| 2274 |
"node_modules/axobject-query": {
|
| 2275 |
"version": "4.1.0",
|
| 2276 |
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
|
|
|
| 2288 |
"dev": true,
|
| 2289 |
"license": "MIT"
|
| 2290 |
},
|
| 2291 |
+
"node_modules/base64-arraybuffer": {
|
| 2292 |
+
"version": "1.0.2",
|
| 2293 |
+
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
| 2294 |
+
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
|
| 2295 |
+
"license": "MIT",
|
| 2296 |
+
"engines": {
|
| 2297 |
+
"node": ">= 0.6.0"
|
| 2298 |
+
}
|
| 2299 |
+
},
|
| 2300 |
"node_modules/brace-expansion": {
|
| 2301 |
"version": "1.1.12",
|
| 2302 |
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
|
|
|
| 2344 |
"version": "1.0.2",
|
| 2345 |
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
| 2346 |
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
|
|
|
| 2347 |
"license": "MIT",
|
| 2348 |
"dependencies": {
|
| 2349 |
"es-errors": "^1.3.0",
|
|
|
|
| 2400 |
],
|
| 2401 |
"license": "CC-BY-4.0"
|
| 2402 |
},
|
| 2403 |
+
"node_modules/canvg": {
|
| 2404 |
+
"version": "3.0.11",
|
| 2405 |
+
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz",
|
| 2406 |
+
"integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==",
|
| 2407 |
+
"license": "MIT",
|
| 2408 |
+
"optional": true,
|
| 2409 |
+
"dependencies": {
|
| 2410 |
+
"@babel/runtime": "^7.12.5",
|
| 2411 |
+
"@types/raf": "^3.4.0",
|
| 2412 |
+
"core-js": "^3.8.3",
|
| 2413 |
+
"raf": "^3.4.1",
|
| 2414 |
+
"regenerator-runtime": "^0.13.7",
|
| 2415 |
+
"rgbcolor": "^1.0.1",
|
| 2416 |
+
"stackblur-canvas": "^2.0.0",
|
| 2417 |
+
"svg-pathdata": "^6.0.3"
|
| 2418 |
+
},
|
| 2419 |
+
"engines": {
|
| 2420 |
+
"node": ">=10.0.0"
|
| 2421 |
+
}
|
| 2422 |
+
},
|
| 2423 |
"node_modules/chalk": {
|
| 2424 |
"version": "4.1.2",
|
| 2425 |
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
|
|
|
|
| 2498 |
"simple-swizzle": "^0.2.2"
|
| 2499 |
}
|
| 2500 |
},
|
| 2501 |
+
"node_modules/combined-stream": {
|
| 2502 |
+
"version": "1.0.8",
|
| 2503 |
+
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
| 2504 |
+
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
| 2505 |
+
"license": "MIT",
|
| 2506 |
+
"dependencies": {
|
| 2507 |
+
"delayed-stream": "~1.0.0"
|
| 2508 |
+
},
|
| 2509 |
+
"engines": {
|
| 2510 |
+
"node": ">= 0.8"
|
| 2511 |
+
}
|
| 2512 |
+
},
|
| 2513 |
"node_modules/concat-map": {
|
| 2514 |
"version": "0.0.1",
|
| 2515 |
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
|
|
| 2517 |
"dev": true,
|
| 2518 |
"license": "MIT"
|
| 2519 |
},
|
| 2520 |
+
"node_modules/cookie": {
|
| 2521 |
+
"version": "0.6.0",
|
| 2522 |
+
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
| 2523 |
+
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
| 2524 |
+
"license": "MIT",
|
| 2525 |
+
"engines": {
|
| 2526 |
+
"node": ">= 0.6"
|
| 2527 |
+
}
|
| 2528 |
+
},
|
| 2529 |
+
"node_modules/core-js": {
|
| 2530 |
+
"version": "3.45.1",
|
| 2531 |
+
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.45.1.tgz",
|
| 2532 |
+
"integrity": "sha512-L4NPsJlCfZsPeXukyzHFlg/i7IIVwHSItR0wg0FLNqYClJ4MQYTYLbC7EkjKYRLZF2iof2MUgN0EGy7MdQFChg==",
|
| 2533 |
+
"hasInstallScript": true,
|
| 2534 |
+
"license": "MIT",
|
| 2535 |
+
"optional": true,
|
| 2536 |
+
"funding": {
|
| 2537 |
+
"type": "opencollective",
|
| 2538 |
+
"url": "https://opencollective.com/core-js"
|
| 2539 |
+
}
|
| 2540 |
+
},
|
| 2541 |
+
"node_modules/core-util-is": {
|
| 2542 |
+
"version": "1.0.3",
|
| 2543 |
+
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
| 2544 |
+
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
| 2545 |
+
"license": "MIT"
|
| 2546 |
+
},
|
| 2547 |
"node_modules/cross-spawn": {
|
| 2548 |
"version": "7.0.6",
|
| 2549 |
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
|
|
|
| 2559 |
"node": ">= 8"
|
| 2560 |
}
|
| 2561 |
},
|
| 2562 |
+
"node_modules/css-line-break": {
|
| 2563 |
+
"version": "2.1.0",
|
| 2564 |
+
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
|
| 2565 |
+
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
|
| 2566 |
+
"license": "MIT",
|
| 2567 |
+
"dependencies": {
|
| 2568 |
+
"utrie": "^1.0.2"
|
| 2569 |
+
}
|
| 2570 |
+
},
|
| 2571 |
"node_modules/csstype": {
|
| 2572 |
"version": "3.1.3",
|
| 2573 |
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
|
|
|
| 2697 |
"url": "https://github.com/sponsors/ljharb"
|
| 2698 |
}
|
| 2699 |
},
|
| 2700 |
+
"node_modules/delayed-stream": {
|
| 2701 |
+
"version": "1.0.0",
|
| 2702 |
+
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
| 2703 |
+
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
| 2704 |
+
"license": "MIT",
|
| 2705 |
+
"engines": {
|
| 2706 |
+
"node": ">=0.4.0"
|
| 2707 |
+
}
|
| 2708 |
+
},
|
| 2709 |
"node_modules/detect-libc": {
|
| 2710 |
"version": "2.1.0",
|
| 2711 |
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz",
|
|
|
|
| 2729 |
"node": ">=0.10.0"
|
| 2730 |
}
|
| 2731 |
},
|
| 2732 |
+
"node_modules/dompurify": {
|
| 2733 |
+
"version": "3.2.6",
|
| 2734 |
+
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz",
|
| 2735 |
+
"integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==",
|
| 2736 |
+
"license": "(MPL-2.0 OR Apache-2.0)",
|
| 2737 |
+
"optional": true,
|
| 2738 |
+
"optionalDependencies": {
|
| 2739 |
+
"@types/trusted-types": "^2.0.7"
|
| 2740 |
+
}
|
| 2741 |
+
},
|
| 2742 |
"node_modules/dunder-proto": {
|
| 2743 |
"version": "1.0.1",
|
| 2744 |
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
| 2745 |
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
|
|
|
| 2746 |
"license": "MIT",
|
| 2747 |
"dependencies": {
|
| 2748 |
"call-bind-apply-helpers": "^1.0.1",
|
|
|
|
| 2847 |
"version": "1.0.1",
|
| 2848 |
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
| 2849 |
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
|
|
|
| 2850 |
"license": "MIT",
|
| 2851 |
"engines": {
|
| 2852 |
"node": ">= 0.4"
|
|
|
|
| 2856 |
"version": "1.3.0",
|
| 2857 |
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
| 2858 |
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
|
|
|
| 2859 |
"license": "MIT",
|
| 2860 |
"engines": {
|
| 2861 |
"node": ">= 0.4"
|
|
|
|
| 2893 |
"version": "1.1.1",
|
| 2894 |
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
| 2895 |
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
|
|
|
| 2896 |
"license": "MIT",
|
| 2897 |
"dependencies": {
|
| 2898 |
"es-errors": "^1.3.0"
|
|
|
|
| 2905 |
"version": "2.1.0",
|
| 2906 |
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
| 2907 |
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
|
|
|
| 2908 |
"license": "MIT",
|
| 2909 |
"dependencies": {
|
| 2910 |
"es-errors": "^1.3.0",
|
|
|
|
| 3437 |
"dev": true,
|
| 3438 |
"license": "MIT"
|
| 3439 |
},
|
| 3440 |
+
"node_modules/fast-png": {
|
| 3441 |
+
"version": "6.4.0",
|
| 3442 |
+
"resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz",
|
| 3443 |
+
"integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
|
| 3444 |
+
"license": "MIT",
|
| 3445 |
+
"dependencies": {
|
| 3446 |
+
"@types/pako": "^2.0.3",
|
| 3447 |
+
"iobuffer": "^5.3.2",
|
| 3448 |
+
"pako": "^2.1.0"
|
| 3449 |
+
}
|
| 3450 |
+
},
|
| 3451 |
"node_modules/fastq": {
|
| 3452 |
"version": "1.19.1",
|
| 3453 |
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
|
|
|
|
| 3458 |
"reusify": "^1.0.4"
|
| 3459 |
}
|
| 3460 |
},
|
| 3461 |
+
"node_modules/fflate": {
|
| 3462 |
+
"version": "0.8.2",
|
| 3463 |
+
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
|
| 3464 |
+
"integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
|
| 3465 |
+
"license": "MIT"
|
| 3466 |
+
},
|
| 3467 |
"node_modules/file-entry-cache": {
|
| 3468 |
"version": "8.0.0",
|
| 3469 |
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
|
|
|
|
| 3528 |
"dev": true,
|
| 3529 |
"license": "ISC"
|
| 3530 |
},
|
| 3531 |
+
"node_modules/follow-redirects": {
|
| 3532 |
+
"version": "1.15.11",
|
| 3533 |
+
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
| 3534 |
+
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
| 3535 |
+
"funding": [
|
| 3536 |
+
{
|
| 3537 |
+
"type": "individual",
|
| 3538 |
+
"url": "https://github.com/sponsors/RubenVerborgh"
|
| 3539 |
+
}
|
| 3540 |
+
],
|
| 3541 |
+
"license": "MIT",
|
| 3542 |
+
"engines": {
|
| 3543 |
+
"node": ">=4.0"
|
| 3544 |
+
},
|
| 3545 |
+
"peerDependenciesMeta": {
|
| 3546 |
+
"debug": {
|
| 3547 |
+
"optional": true
|
| 3548 |
+
}
|
| 3549 |
+
}
|
| 3550 |
+
},
|
| 3551 |
"node_modules/for-each": {
|
| 3552 |
"version": "0.3.5",
|
| 3553 |
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
|
|
|
|
| 3564 |
"url": "https://github.com/sponsors/ljharb"
|
| 3565 |
}
|
| 3566 |
},
|
| 3567 |
+
"node_modules/form-data": {
|
| 3568 |
+
"version": "4.0.4",
|
| 3569 |
+
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
| 3570 |
+
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
| 3571 |
+
"license": "MIT",
|
| 3572 |
+
"dependencies": {
|
| 3573 |
+
"asynckit": "^0.4.0",
|
| 3574 |
+
"combined-stream": "^1.0.8",
|
| 3575 |
+
"es-set-tostringtag": "^2.1.0",
|
| 3576 |
+
"hasown": "^2.0.2",
|
| 3577 |
+
"mime-types": "^2.1.12"
|
| 3578 |
+
},
|
| 3579 |
+
"engines": {
|
| 3580 |
+
"node": ">= 6"
|
| 3581 |
+
}
|
| 3582 |
+
},
|
| 3583 |
"node_modules/function-bind": {
|
| 3584 |
"version": "1.1.2",
|
| 3585 |
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
| 3586 |
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
|
|
|
| 3587 |
"license": "MIT",
|
| 3588 |
"funding": {
|
| 3589 |
"url": "https://github.com/sponsors/ljharb"
|
|
|
|
| 3624 |
"version": "1.3.0",
|
| 3625 |
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
| 3626 |
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
|
|
|
| 3627 |
"license": "MIT",
|
| 3628 |
"dependencies": {
|
| 3629 |
"call-bind-apply-helpers": "^1.0.2",
|
|
|
|
| 3648 |
"version": "1.0.1",
|
| 3649 |
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
| 3650 |
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
|
|
|
| 3651 |
"license": "MIT",
|
| 3652 |
"dependencies": {
|
| 3653 |
"dunder-proto": "^1.0.1",
|
|
|
|
| 3735 |
"version": "1.2.0",
|
| 3736 |
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
| 3737 |
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
|
|
|
| 3738 |
"license": "MIT",
|
| 3739 |
"engines": {
|
| 3740 |
"node": ">= 0.4"
|
|
|
|
| 3813 |
"version": "1.1.0",
|
| 3814 |
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
| 3815 |
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
|
|
|
| 3816 |
"license": "MIT",
|
| 3817 |
"engines": {
|
| 3818 |
"node": ">= 0.4"
|
|
|
|
| 3825 |
"version": "1.0.2",
|
| 3826 |
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
| 3827 |
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
|
|
|
| 3828 |
"license": "MIT",
|
| 3829 |
"dependencies": {
|
| 3830 |
"has-symbols": "^1.0.3"
|
|
|
|
| 3840 |
"version": "2.0.2",
|
| 3841 |
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
| 3842 |
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
|
|
|
| 3843 |
"license": "MIT",
|
| 3844 |
"dependencies": {
|
| 3845 |
"function-bind": "^1.1.2"
|
|
|
|
| 3848 |
"node": ">= 0.4"
|
| 3849 |
}
|
| 3850 |
},
|
| 3851 |
+
"node_modules/html2canvas": {
|
| 3852 |
+
"version": "1.4.1",
|
| 3853 |
+
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
|
| 3854 |
+
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
|
| 3855 |
+
"license": "MIT",
|
| 3856 |
+
"dependencies": {
|
| 3857 |
+
"css-line-break": "^2.1.0",
|
| 3858 |
+
"text-segmentation": "^1.0.3"
|
| 3859 |
+
},
|
| 3860 |
+
"engines": {
|
| 3861 |
+
"node": ">=8.0.0"
|
| 3862 |
+
}
|
| 3863 |
+
},
|
| 3864 |
+
"node_modules/https": {
|
| 3865 |
+
"version": "1.0.0",
|
| 3866 |
+
"resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz",
|
| 3867 |
+
"integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==",
|
| 3868 |
+
"license": "ISC"
|
| 3869 |
+
},
|
| 3870 |
"node_modules/ignore": {
|
| 3871 |
"version": "5.3.2",
|
| 3872 |
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
|
|
|
| 3877 |
"node": ">= 4"
|
| 3878 |
}
|
| 3879 |
},
|
| 3880 |
+
"node_modules/image-size": {
|
| 3881 |
+
"version": "1.2.1",
|
| 3882 |
+
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz",
|
| 3883 |
+
"integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==",
|
| 3884 |
+
"license": "MIT",
|
| 3885 |
+
"dependencies": {
|
| 3886 |
+
"queue": "6.0.2"
|
| 3887 |
+
},
|
| 3888 |
+
"bin": {
|
| 3889 |
+
"image-size": "bin/image-size.js"
|
| 3890 |
+
},
|
| 3891 |
+
"engines": {
|
| 3892 |
+
"node": ">=16.x"
|
| 3893 |
+
}
|
| 3894 |
+
},
|
| 3895 |
+
"node_modules/immediate": {
|
| 3896 |
+
"version": "3.0.6",
|
| 3897 |
+
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
| 3898 |
+
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
| 3899 |
+
"license": "MIT"
|
| 3900 |
+
},
|
| 3901 |
"node_modules/import-fresh": {
|
| 3902 |
"version": "3.3.1",
|
| 3903 |
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
|
|
|
| 3925 |
"node": ">=0.8.19"
|
| 3926 |
}
|
| 3927 |
},
|
| 3928 |
+
"node_modules/inherits": {
|
| 3929 |
+
"version": "2.0.4",
|
| 3930 |
+
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
| 3931 |
+
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
| 3932 |
+
"license": "ISC"
|
| 3933 |
+
},
|
| 3934 |
"node_modules/internal-slot": {
|
| 3935 |
"version": "1.1.0",
|
| 3936 |
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
|
|
|
| 3946 |
"node": ">= 0.4"
|
| 3947 |
}
|
| 3948 |
},
|
| 3949 |
+
"node_modules/iobuffer": {
|
| 3950 |
+
"version": "5.4.0",
|
| 3951 |
+
"resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz",
|
| 3952 |
+
"integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==",
|
| 3953 |
+
"license": "MIT"
|
| 3954 |
+
},
|
| 3955 |
"node_modules/is-array-buffer": {
|
| 3956 |
"version": "3.0.5",
|
| 3957 |
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
|
|
|
| 4402 |
"jiti": "lib/jiti-cli.mjs"
|
| 4403 |
}
|
| 4404 |
},
|
| 4405 |
+
"node_modules/jose": {
|
| 4406 |
+
"version": "5.10.0",
|
| 4407 |
+
"resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
|
| 4408 |
+
"integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
|
| 4409 |
+
"license": "MIT",
|
| 4410 |
+
"funding": {
|
| 4411 |
+
"url": "https://github.com/sponsors/panva"
|
| 4412 |
+
}
|
| 4413 |
+
},
|
| 4414 |
"node_modules/js-tokens": {
|
| 4415 |
"version": "4.0.0",
|
| 4416 |
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
|
|
|
| 4465 |
"json5": "lib/cli.js"
|
| 4466 |
}
|
| 4467 |
},
|
| 4468 |
+
"node_modules/jspdf": {
|
| 4469 |
+
"version": "3.0.2",
|
| 4470 |
+
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.2.tgz",
|
| 4471 |
+
"integrity": "sha512-G0fQDJ5fAm6UW78HG6lNXyq09l0PrA1rpNY5i+ly17Zb1fMMFSmS+3lw4cnrAPGyouv2Y0ylujbY2Ieq3DSlKA==",
|
| 4472 |
+
"license": "MIT",
|
| 4473 |
+
"dependencies": {
|
| 4474 |
+
"@babel/runtime": "^7.26.9",
|
| 4475 |
+
"fast-png": "^6.2.0",
|
| 4476 |
+
"fflate": "^0.8.1"
|
| 4477 |
+
},
|
| 4478 |
+
"optionalDependencies": {
|
| 4479 |
+
"canvg": "^3.0.11",
|
| 4480 |
+
"core-js": "^3.6.0",
|
| 4481 |
+
"dompurify": "^3.2.4",
|
| 4482 |
+
"html2canvas": "^1.0.0-rc.5"
|
| 4483 |
+
}
|
| 4484 |
+
},
|
| 4485 |
"node_modules/jsx-ast-utils": {
|
| 4486 |
"version": "3.3.5",
|
| 4487 |
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
|
|
|
|
| 4498 |
"node": ">=4.0"
|
| 4499 |
}
|
| 4500 |
},
|
| 4501 |
+
"node_modules/jszip": {
|
| 4502 |
+
"version": "3.10.1",
|
| 4503 |
+
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
| 4504 |
+
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
| 4505 |
+
"license": "(MIT OR GPL-3.0-or-later)",
|
| 4506 |
+
"dependencies": {
|
| 4507 |
+
"lie": "~3.3.0",
|
| 4508 |
+
"pako": "~1.0.2",
|
| 4509 |
+
"readable-stream": "~2.3.6",
|
| 4510 |
+
"setimmediate": "^1.0.5"
|
| 4511 |
+
}
|
| 4512 |
+
},
|
| 4513 |
+
"node_modules/jszip/node_modules/pako": {
|
| 4514 |
+
"version": "1.0.11",
|
| 4515 |
+
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
| 4516 |
+
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
| 4517 |
+
"license": "(MIT AND Zlib)"
|
| 4518 |
+
},
|
| 4519 |
"node_modules/keyv": {
|
| 4520 |
"version": "4.5.4",
|
| 4521 |
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
|
|
|
| 4560 |
"node": ">= 0.8.0"
|
| 4561 |
}
|
| 4562 |
},
|
| 4563 |
+
"node_modules/lie": {
|
| 4564 |
+
"version": "3.3.0",
|
| 4565 |
+
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
| 4566 |
+
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
| 4567 |
+
"license": "MIT",
|
| 4568 |
+
"dependencies": {
|
| 4569 |
+
"immediate": "~3.0.5"
|
| 4570 |
+
}
|
| 4571 |
+
},
|
| 4572 |
"node_modules/lightningcss": {
|
| 4573 |
"version": "1.30.1",
|
| 4574 |
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
|
|
|
|
| 4844 |
"loose-envify": "cli.js"
|
| 4845 |
}
|
| 4846 |
},
|
| 4847 |
+
"node_modules/lru-cache": {
|
| 4848 |
+
"version": "6.0.0",
|
| 4849 |
+
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
| 4850 |
+
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
| 4851 |
+
"license": "ISC",
|
| 4852 |
+
"dependencies": {
|
| 4853 |
+
"yallist": "^4.0.0"
|
| 4854 |
+
},
|
| 4855 |
+
"engines": {
|
| 4856 |
+
"node": ">=10"
|
| 4857 |
+
}
|
| 4858 |
+
},
|
| 4859 |
+
"node_modules/lru-cache/node_modules/yallist": {
|
| 4860 |
+
"version": "4.0.0",
|
| 4861 |
+
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
| 4862 |
+
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
| 4863 |
+
"license": "ISC"
|
| 4864 |
+
},
|
| 4865 |
+
"node_modules/lucide-react": {
|
| 4866 |
+
"version": "0.544.0",
|
| 4867 |
+
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.544.0.tgz",
|
| 4868 |
+
"integrity": "sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw==",
|
| 4869 |
+
"license": "ISC",
|
| 4870 |
+
"peerDependencies": {
|
| 4871 |
+
"react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
| 4872 |
+
}
|
| 4873 |
+
},
|
| 4874 |
"node_modules/magic-string": {
|
| 4875 |
"version": "0.30.19",
|
| 4876 |
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
|
|
|
| 4885 |
"version": "1.1.0",
|
| 4886 |
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
| 4887 |
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
|
|
|
| 4888 |
"license": "MIT",
|
| 4889 |
"engines": {
|
| 4890 |
"node": ">= 0.4"
|
|
|
|
| 4914 |
"node": ">=8.6"
|
| 4915 |
}
|
| 4916 |
},
|
| 4917 |
+
"node_modules/mime-db": {
|
| 4918 |
+
"version": "1.52.0",
|
| 4919 |
+
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
| 4920 |
+
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
| 4921 |
+
"license": "MIT",
|
| 4922 |
+
"engines": {
|
| 4923 |
+
"node": ">= 0.6"
|
| 4924 |
+
}
|
| 4925 |
+
},
|
| 4926 |
+
"node_modules/mime-types": {
|
| 4927 |
+
"version": "2.1.35",
|
| 4928 |
+
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
| 4929 |
+
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
| 4930 |
+
"license": "MIT",
|
| 4931 |
+
"dependencies": {
|
| 4932 |
+
"mime-db": "1.52.0"
|
| 4933 |
+
},
|
| 4934 |
+
"engines": {
|
| 4935 |
+
"node": ">= 0.6"
|
| 4936 |
+
}
|
| 4937 |
+
},
|
| 4938 |
"node_modules/minimatch": {
|
| 4939 |
"version": "3.1.2",
|
| 4940 |
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
|
|
|
| 5097 |
}
|
| 5098 |
}
|
| 5099 |
},
|
| 5100 |
+
"node_modules/next-auth": {
|
| 5101 |
+
"version": "4.24.11",
|
| 5102 |
+
"resolved": "https://registry.npmjs.org/next-auth/-/next-auth-4.24.11.tgz",
|
| 5103 |
+
"integrity": "sha512-pCFXzIDQX7xmHFs4KVH4luCjaCbuPRtZ9oBUjUhOk84mZ9WVPf94n87TxYI4rSRf9HmfHEF8Yep3JrYDVOo3Cw==",
|
| 5104 |
+
"license": "ISC",
|
| 5105 |
+
"dependencies": {
|
| 5106 |
+
"@babel/runtime": "^7.20.13",
|
| 5107 |
+
"@panva/hkdf": "^1.0.2",
|
| 5108 |
+
"cookie": "^0.7.0",
|
| 5109 |
+
"jose": "^4.15.5",
|
| 5110 |
+
"oauth": "^0.9.15",
|
| 5111 |
+
"openid-client": "^5.4.0",
|
| 5112 |
+
"preact": "^10.6.3",
|
| 5113 |
+
"preact-render-to-string": "^5.1.19",
|
| 5114 |
+
"uuid": "^8.3.2"
|
| 5115 |
+
},
|
| 5116 |
+
"peerDependencies": {
|
| 5117 |
+
"@auth/core": "0.34.2",
|
| 5118 |
+
"next": "^12.2.5 || ^13 || ^14 || ^15",
|
| 5119 |
+
"nodemailer": "^6.6.5",
|
| 5120 |
+
"react": "^17.0.2 || ^18 || ^19",
|
| 5121 |
+
"react-dom": "^17.0.2 || ^18 || ^19"
|
| 5122 |
+
},
|
| 5123 |
+
"peerDependenciesMeta": {
|
| 5124 |
+
"@auth/core": {
|
| 5125 |
+
"optional": true
|
| 5126 |
+
},
|
| 5127 |
+
"nodemailer": {
|
| 5128 |
+
"optional": true
|
| 5129 |
+
}
|
| 5130 |
+
}
|
| 5131 |
+
},
|
| 5132 |
+
"node_modules/next-auth/node_modules/cookie": {
|
| 5133 |
+
"version": "0.7.2",
|
| 5134 |
+
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
| 5135 |
+
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
|
| 5136 |
+
"license": "MIT",
|
| 5137 |
+
"engines": {
|
| 5138 |
+
"node": ">= 0.6"
|
| 5139 |
+
}
|
| 5140 |
+
},
|
| 5141 |
+
"node_modules/next-auth/node_modules/jose": {
|
| 5142 |
+
"version": "4.15.9",
|
| 5143 |
+
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
|
| 5144 |
+
"integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
|
| 5145 |
+
"license": "MIT",
|
| 5146 |
+
"funding": {
|
| 5147 |
+
"url": "https://github.com/sponsors/panva"
|
| 5148 |
+
}
|
| 5149 |
+
},
|
| 5150 |
"node_modules/next/node_modules/postcss": {
|
| 5151 |
"version": "8.4.31",
|
| 5152 |
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
|
|
|
| 5175 |
"node": "^10 || ^12 || >=14"
|
| 5176 |
}
|
| 5177 |
},
|
| 5178 |
+
"node_modules/oauth": {
|
| 5179 |
+
"version": "0.9.15",
|
| 5180 |
+
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
|
| 5181 |
+
"integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==",
|
| 5182 |
+
"license": "MIT"
|
| 5183 |
+
},
|
| 5184 |
+
"node_modules/oauth4webapi": {
|
| 5185 |
+
"version": "2.17.0",
|
| 5186 |
+
"resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-2.17.0.tgz",
|
| 5187 |
+
"integrity": "sha512-lbC0Z7uzAFNFyzEYRIC+pkSVvDHJTbEW+dYlSBAlCYDe6RxUkJ26bClhk8ocBZip1wfI9uKTe0fm4Ib4RHn6uQ==",
|
| 5188 |
+
"license": "MIT",
|
| 5189 |
+
"funding": {
|
| 5190 |
+
"url": "https://github.com/sponsors/panva"
|
| 5191 |
+
}
|
| 5192 |
+
},
|
| 5193 |
"node_modules/object-assign": {
|
| 5194 |
"version": "4.1.1",
|
| 5195 |
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
|
|
|
| 5200 |
"node": ">=0.10.0"
|
| 5201 |
}
|
| 5202 |
},
|
| 5203 |
+
"node_modules/object-hash": {
|
| 5204 |
+
"version": "2.2.0",
|
| 5205 |
+
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
|
| 5206 |
+
"integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==",
|
| 5207 |
+
"license": "MIT",
|
| 5208 |
+
"engines": {
|
| 5209 |
+
"node": ">= 6"
|
| 5210 |
+
}
|
| 5211 |
+
},
|
| 5212 |
"node_modules/object-inspect": {
|
| 5213 |
"version": "1.13.4",
|
| 5214 |
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
|
|
|
|
| 5322 |
"url": "https://github.com/sponsors/ljharb"
|
| 5323 |
}
|
| 5324 |
},
|
| 5325 |
+
"node_modules/oidc-token-hash": {
|
| 5326 |
+
"version": "5.1.1",
|
| 5327 |
+
"resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.1.1.tgz",
|
| 5328 |
+
"integrity": "sha512-D7EmwxJV6DsEB6vOFLrBM2OzsVgQzgPWyHlV2OOAVj772n+WTXpudC9e9u5BVKQnYwaD30Ivhi9b+4UeBcGu9g==",
|
| 5329 |
+
"license": "MIT",
|
| 5330 |
+
"engines": {
|
| 5331 |
+
"node": "^10.13.0 || >=12.0.0"
|
| 5332 |
+
}
|
| 5333 |
+
},
|
| 5334 |
+
"node_modules/openid-client": {
|
| 5335 |
+
"version": "5.7.1",
|
| 5336 |
+
"resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz",
|
| 5337 |
+
"integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==",
|
| 5338 |
+
"license": "MIT",
|
| 5339 |
+
"dependencies": {
|
| 5340 |
+
"jose": "^4.15.9",
|
| 5341 |
+
"lru-cache": "^6.0.0",
|
| 5342 |
+
"object-hash": "^2.2.0",
|
| 5343 |
+
"oidc-token-hash": "^5.0.3"
|
| 5344 |
+
},
|
| 5345 |
+
"funding": {
|
| 5346 |
+
"url": "https://github.com/sponsors/panva"
|
| 5347 |
+
}
|
| 5348 |
+
},
|
| 5349 |
+
"node_modules/openid-client/node_modules/jose": {
|
| 5350 |
+
"version": "4.15.9",
|
| 5351 |
+
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.9.tgz",
|
| 5352 |
+
"integrity": "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==",
|
| 5353 |
+
"license": "MIT",
|
| 5354 |
+
"funding": {
|
| 5355 |
+
"url": "https://github.com/sponsors/panva"
|
| 5356 |
+
}
|
| 5357 |
+
},
|
| 5358 |
"node_modules/optionator": {
|
| 5359 |
"version": "0.9.4",
|
| 5360 |
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
|
|
|
| 5423 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 5424 |
}
|
| 5425 |
},
|
| 5426 |
+
"node_modules/pako": {
|
| 5427 |
+
"version": "2.1.0",
|
| 5428 |
+
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
|
| 5429 |
+
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
|
| 5430 |
+
"license": "(MIT AND Zlib)"
|
| 5431 |
+
},
|
| 5432 |
"node_modules/parent-module": {
|
| 5433 |
"version": "1.0.1",
|
| 5434 |
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
|
|
|
| 5469 |
"dev": true,
|
| 5470 |
"license": "MIT"
|
| 5471 |
},
|
| 5472 |
+
"node_modules/performance-now": {
|
| 5473 |
+
"version": "2.1.0",
|
| 5474 |
+
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
| 5475 |
+
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
|
| 5476 |
+
"license": "MIT",
|
| 5477 |
+
"optional": true
|
| 5478 |
+
},
|
| 5479 |
"node_modules/picocolors": {
|
| 5480 |
"version": "1.1.1",
|
| 5481 |
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
|
|
|
| 5534 |
"node": "^10 || ^12 || >=14"
|
| 5535 |
}
|
| 5536 |
},
|
| 5537 |
+
"node_modules/pptxgenjs": {
|
| 5538 |
+
"version": "4.0.1",
|
| 5539 |
+
"resolved": "https://registry.npmjs.org/pptxgenjs/-/pptxgenjs-4.0.1.tgz",
|
| 5540 |
+
"integrity": "sha512-TeJISr8wouAuXw4C1F/mC33xbZs/FuEG6nH9FG1Zj+nuPcGMP5YRHl6X+j3HSUnS1f3at6k75ZZXPMZlA5Lj9A==",
|
| 5541 |
+
"license": "MIT",
|
| 5542 |
+
"dependencies": {
|
| 5543 |
+
"@types/node": "^22.8.1",
|
| 5544 |
+
"https": "^1.0.0",
|
| 5545 |
+
"image-size": "^1.2.1",
|
| 5546 |
+
"jszip": "^3.10.1"
|
| 5547 |
+
}
|
| 5548 |
+
},
|
| 5549 |
+
"node_modules/pptxgenjs/node_modules/@types/node": {
|
| 5550 |
+
"version": "22.18.4",
|
| 5551 |
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.4.tgz",
|
| 5552 |
+
"integrity": "sha512-UJdblFqXymSBhmZf96BnbisoFIr8ooiiBRMolQgg77Ea+VM37jXw76C2LQr9n8wm9+i/OvlUlW6xSvqwzwqznw==",
|
| 5553 |
+
"license": "MIT",
|
| 5554 |
+
"dependencies": {
|
| 5555 |
+
"undici-types": "~6.21.0"
|
| 5556 |
+
}
|
| 5557 |
+
},
|
| 5558 |
+
"node_modules/preact": {
|
| 5559 |
+
"version": "10.11.3",
|
| 5560 |
+
"resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz",
|
| 5561 |
+
"integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==",
|
| 5562 |
+
"license": "MIT",
|
| 5563 |
+
"funding": {
|
| 5564 |
+
"type": "opencollective",
|
| 5565 |
+
"url": "https://opencollective.com/preact"
|
| 5566 |
+
}
|
| 5567 |
+
},
|
| 5568 |
+
"node_modules/preact-render-to-string": {
|
| 5569 |
+
"version": "5.2.3",
|
| 5570 |
+
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz",
|
| 5571 |
+
"integrity": "sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==",
|
| 5572 |
+
"license": "MIT",
|
| 5573 |
+
"dependencies": {
|
| 5574 |
+
"pretty-format": "^3.8.0"
|
| 5575 |
+
},
|
| 5576 |
+
"peerDependencies": {
|
| 5577 |
+
"preact": ">=10"
|
| 5578 |
+
}
|
| 5579 |
+
},
|
| 5580 |
"node_modules/prelude-ls": {
|
| 5581 |
"version": "1.2.1",
|
| 5582 |
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
|
|
|
| 5587 |
"node": ">= 0.8.0"
|
| 5588 |
}
|
| 5589 |
},
|
| 5590 |
+
"node_modules/pretty-format": {
|
| 5591 |
+
"version": "3.8.0",
|
| 5592 |
+
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz",
|
| 5593 |
+
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==",
|
| 5594 |
+
"license": "MIT"
|
| 5595 |
+
},
|
| 5596 |
+
"node_modules/process-nextick-args": {
|
| 5597 |
+
"version": "2.0.1",
|
| 5598 |
+
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
| 5599 |
+
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
| 5600 |
+
"license": "MIT"
|
| 5601 |
+
},
|
| 5602 |
"node_modules/prop-types": {
|
| 5603 |
"version": "15.8.1",
|
| 5604 |
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
|
|
|
| 5611 |
"react-is": "^16.13.1"
|
| 5612 |
}
|
| 5613 |
},
|
| 5614 |
+
"node_modules/proxy-from-env": {
|
| 5615 |
+
"version": "1.1.0",
|
| 5616 |
+
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
| 5617 |
+
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
| 5618 |
+
"license": "MIT"
|
| 5619 |
+
},
|
| 5620 |
"node_modules/punycode": {
|
| 5621 |
"version": "2.3.1",
|
| 5622 |
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
|
|
|
| 5627 |
"node": ">=6"
|
| 5628 |
}
|
| 5629 |
},
|
| 5630 |
+
"node_modules/queue": {
|
| 5631 |
+
"version": "6.0.2",
|
| 5632 |
+
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
| 5633 |
+
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
| 5634 |
+
"license": "MIT",
|
| 5635 |
+
"dependencies": {
|
| 5636 |
+
"inherits": "~2.0.3"
|
| 5637 |
+
}
|
| 5638 |
+
},
|
| 5639 |
"node_modules/queue-microtask": {
|
| 5640 |
"version": "1.2.3",
|
| 5641 |
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
|
|
|
| 5657 |
],
|
| 5658 |
"license": "MIT"
|
| 5659 |
},
|
| 5660 |
+
"node_modules/raf": {
|
| 5661 |
+
"version": "3.4.1",
|
| 5662 |
+
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
| 5663 |
+
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
| 5664 |
+
"license": "MIT",
|
| 5665 |
+
"optional": true,
|
| 5666 |
+
"dependencies": {
|
| 5667 |
+
"performance-now": "^2.1.0"
|
| 5668 |
+
}
|
| 5669 |
+
},
|
| 5670 |
"node_modules/react": {
|
| 5671 |
"version": "19.1.0",
|
| 5672 |
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
|
|
|
|
| 5695 |
"dev": true,
|
| 5696 |
"license": "MIT"
|
| 5697 |
},
|
| 5698 |
+
"node_modules/readable-stream": {
|
| 5699 |
+
"version": "2.3.8",
|
| 5700 |
+
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
| 5701 |
+
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
| 5702 |
+
"license": "MIT",
|
| 5703 |
+
"dependencies": {
|
| 5704 |
+
"core-util-is": "~1.0.0",
|
| 5705 |
+
"inherits": "~2.0.3",
|
| 5706 |
+
"isarray": "~1.0.0",
|
| 5707 |
+
"process-nextick-args": "~2.0.0",
|
| 5708 |
+
"safe-buffer": "~5.1.1",
|
| 5709 |
+
"string_decoder": "~1.1.1",
|
| 5710 |
+
"util-deprecate": "~1.0.1"
|
| 5711 |
+
}
|
| 5712 |
+
},
|
| 5713 |
+
"node_modules/readable-stream/node_modules/isarray": {
|
| 5714 |
+
"version": "1.0.0",
|
| 5715 |
+
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
| 5716 |
+
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
| 5717 |
+
"license": "MIT"
|
| 5718 |
+
},
|
| 5719 |
"node_modules/reflect.getprototypeof": {
|
| 5720 |
"version": "1.0.10",
|
| 5721 |
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
|
|
|
| 5739 |
"url": "https://github.com/sponsors/ljharb"
|
| 5740 |
}
|
| 5741 |
},
|
| 5742 |
+
"node_modules/regenerator-runtime": {
|
| 5743 |
+
"version": "0.13.11",
|
| 5744 |
+
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
| 5745 |
+
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==",
|
| 5746 |
+
"license": "MIT",
|
| 5747 |
+
"optional": true
|
| 5748 |
+
},
|
| 5749 |
"node_modules/regexp.prototype.flags": {
|
| 5750 |
"version": "1.5.4",
|
| 5751 |
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
|
|
|
|
| 5819 |
"node": ">=0.10.0"
|
| 5820 |
}
|
| 5821 |
},
|
| 5822 |
+
"node_modules/rgbcolor": {
|
| 5823 |
+
"version": "1.0.1",
|
| 5824 |
+
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
|
| 5825 |
+
"integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==",
|
| 5826 |
+
"license": "MIT OR SEE LICENSE IN FEEL-FREE.md",
|
| 5827 |
+
"optional": true,
|
| 5828 |
+
"engines": {
|
| 5829 |
+
"node": ">= 0.8.15"
|
| 5830 |
+
}
|
| 5831 |
+
},
|
| 5832 |
"node_modules/run-parallel": {
|
| 5833 |
"version": "1.2.0",
|
| 5834 |
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
|
|
|
| 5873 |
"url": "https://github.com/sponsors/ljharb"
|
| 5874 |
}
|
| 5875 |
},
|
| 5876 |
+
"node_modules/safe-buffer": {
|
| 5877 |
+
"version": "5.1.2",
|
| 5878 |
+
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
| 5879 |
+
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
| 5880 |
+
"license": "MIT"
|
| 5881 |
+
},
|
| 5882 |
"node_modules/safe-push-apply": {
|
| 5883 |
"version": "1.0.0",
|
| 5884 |
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
|
|
|
|
| 5982 |
"node": ">= 0.4"
|
| 5983 |
}
|
| 5984 |
},
|
| 5985 |
+
"node_modules/setimmediate": {
|
| 5986 |
+
"version": "1.0.5",
|
| 5987 |
+
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
| 5988 |
+
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
| 5989 |
+
"license": "MIT"
|
| 5990 |
+
},
|
| 5991 |
"node_modules/sharp": {
|
| 5992 |
"version": "0.34.3",
|
| 5993 |
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz",
|
|
|
|
| 6156 |
"dev": true,
|
| 6157 |
"license": "MIT"
|
| 6158 |
},
|
| 6159 |
+
"node_modules/stackblur-canvas": {
|
| 6160 |
+
"version": "2.7.0",
|
| 6161 |
+
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz",
|
| 6162 |
+
"integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==",
|
| 6163 |
+
"license": "MIT",
|
| 6164 |
+
"optional": true,
|
| 6165 |
+
"engines": {
|
| 6166 |
+
"node": ">=0.1.14"
|
| 6167 |
+
}
|
| 6168 |
+
},
|
| 6169 |
"node_modules/stop-iteration-iterator": {
|
| 6170 |
"version": "1.1.0",
|
| 6171 |
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
|
|
|
|
| 6180 |
"node": ">= 0.4"
|
| 6181 |
}
|
| 6182 |
},
|
| 6183 |
+
"node_modules/string_decoder": {
|
| 6184 |
+
"version": "1.1.1",
|
| 6185 |
+
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
| 6186 |
+
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
| 6187 |
+
"license": "MIT",
|
| 6188 |
+
"dependencies": {
|
| 6189 |
+
"safe-buffer": "~5.1.0"
|
| 6190 |
+
}
|
| 6191 |
+
},
|
| 6192 |
"node_modules/string.prototype.includes": {
|
| 6193 |
"version": "2.0.1",
|
| 6194 |
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
|
|
|
|
| 6374 |
"url": "https://github.com/sponsors/ljharb"
|
| 6375 |
}
|
| 6376 |
},
|
| 6377 |
+
"node_modules/svg-pathdata": {
|
| 6378 |
+
"version": "6.0.3",
|
| 6379 |
+
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz",
|
| 6380 |
+
"integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==",
|
| 6381 |
+
"license": "MIT",
|
| 6382 |
+
"optional": true,
|
| 6383 |
+
"engines": {
|
| 6384 |
+
"node": ">=12.0.0"
|
| 6385 |
+
}
|
| 6386 |
+
},
|
| 6387 |
"node_modules/tailwindcss": {
|
| 6388 |
"version": "4.1.13",
|
| 6389 |
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz",
|
|
|
|
| 6423 |
"node": ">=18"
|
| 6424 |
}
|
| 6425 |
},
|
| 6426 |
+
"node_modules/text-segmentation": {
|
| 6427 |
+
"version": "1.0.3",
|
| 6428 |
+
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
|
| 6429 |
+
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
|
| 6430 |
+
"license": "MIT",
|
| 6431 |
+
"dependencies": {
|
| 6432 |
+
"utrie": "^1.0.2"
|
| 6433 |
+
}
|
| 6434 |
+
},
|
| 6435 |
"node_modules/tinyglobby": {
|
| 6436 |
"version": "0.2.15",
|
| 6437 |
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
|
|
|
| 6653 |
"version": "6.21.0",
|
| 6654 |
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
| 6655 |
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
|
|
|
| 6656 |
"license": "MIT"
|
| 6657 |
},
|
| 6658 |
"node_modules/unrs-resolver": {
|
|
|
|
| 6700 |
"punycode": "^2.1.0"
|
| 6701 |
}
|
| 6702 |
},
|
| 6703 |
+
"node_modules/util-deprecate": {
|
| 6704 |
+
"version": "1.0.2",
|
| 6705 |
+
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
| 6706 |
+
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
| 6707 |
+
"license": "MIT"
|
| 6708 |
+
},
|
| 6709 |
+
"node_modules/utrie": {
|
| 6710 |
+
"version": "1.0.2",
|
| 6711 |
+
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
|
| 6712 |
+
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
|
| 6713 |
+
"license": "MIT",
|
| 6714 |
+
"dependencies": {
|
| 6715 |
+
"base64-arraybuffer": "^1.0.2"
|
| 6716 |
+
}
|
| 6717 |
+
},
|
| 6718 |
+
"node_modules/uuid": {
|
| 6719 |
+
"version": "8.3.2",
|
| 6720 |
+
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
| 6721 |
+
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
| 6722 |
+
"license": "MIT",
|
| 6723 |
+
"bin": {
|
| 6724 |
+
"uuid": "dist/bin/uuid"
|
| 6725 |
+
}
|
| 6726 |
+
},
|
| 6727 |
"node_modules/which": {
|
| 6728 |
"version": "2.0.2",
|
| 6729 |
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
package.json
CHANGED
|
@@ -9,19 +9,27 @@
|
|
| 9 |
"lint": "eslint"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
"react": "19.1.0",
|
| 13 |
-
"react-dom": "19.1.0"
|
| 14 |
-
"next": "15.5.3"
|
| 15 |
},
|
| 16 |
"devDependencies": {
|
| 17 |
-
"
|
|
|
|
| 18 |
"@types/node": "^20",
|
| 19 |
"@types/react": "^19",
|
| 20 |
"@types/react-dom": "^19",
|
| 21 |
-
"@tailwindcss/postcss": "^4",
|
| 22 |
-
"tailwindcss": "^4",
|
| 23 |
"eslint": "^9",
|
| 24 |
"eslint-config-next": "15.5.3",
|
| 25 |
-
"
|
|
|
|
| 26 |
}
|
| 27 |
-
}
|
|
|
|
| 9 |
"lint": "eslint"
|
| 10 |
},
|
| 11 |
"dependencies": {
|
| 12 |
+
"@auth/core": "^0.34.2",
|
| 13 |
+
"@huggingface/inference": "^4.8.0",
|
| 14 |
+
"axios": "^1.12.2",
|
| 15 |
+
"html2canvas": "^1.4.1",
|
| 16 |
+
"jspdf": "^3.0.2",
|
| 17 |
+
"lucide-react": "^0.544.0",
|
| 18 |
+
"next": "15.5.3",
|
| 19 |
+
"next-auth": "^4.24.11",
|
| 20 |
+
"pptxgenjs": "^4.0.1",
|
| 21 |
"react": "19.1.0",
|
| 22 |
+
"react-dom": "19.1.0"
|
|
|
|
| 23 |
},
|
| 24 |
"devDependencies": {
|
| 25 |
+
"@eslint/eslintrc": "^3",
|
| 26 |
+
"@tailwindcss/postcss": "^4",
|
| 27 |
"@types/node": "^20",
|
| 28 |
"@types/react": "^19",
|
| 29 |
"@types/react-dom": "^19",
|
|
|
|
|
|
|
| 30 |
"eslint": "^9",
|
| 31 |
"eslint-config-next": "15.5.3",
|
| 32 |
+
"tailwindcss": "^4",
|
| 33 |
+
"typescript": "^5"
|
| 34 |
}
|
| 35 |
+
}
|