slidecanvas 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +282 -0
- package/dist/index.d.mts +79 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +18 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +105 -0
package/README.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# SlideCanvas
|
|
2
|
+
|
|
3
|
+
**SlideCanvas** is a high-performance, browser-native toolkit for **viewing and editing PowerPoint (.pptx) files directly in the web browser**. It provides an enterprise-grade engine for parsing, rendering, and exporting presentations with pixel-perfect accuracy and seamless S3 integration.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Key Features
|
|
8
|
+
|
|
9
|
+
- **Pixel-Perfect Rendering**: High-fidelity display of slides using a sophisticated Fabric.js-based canvas.
|
|
10
|
+
- **AI-Powered Editing**: Integrated Gemini AI for smart text manipulation (Shorten, Reframe, Lengthen).
|
|
11
|
+
- **Enterprise-Grade Parsing**: Deep internal processing of XML-based PPTX structures.
|
|
12
|
+
- **Full-Featured Toolbar**: Microsoft Office-style Ribbon UI with support for text, shapes, and images.
|
|
13
|
+
- **Professional Export**: High-quality `.pptx` generation with support for transparency and layout mapping.
|
|
14
|
+
- **S3 & Remote Support**: Built-in architecture for loading presentations via secure proxy tunnels.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
Install SlideCanvas via your preferred package manager:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install slidecanvas
|
|
24
|
+
# or
|
|
25
|
+
yarn add slidecanvas
|
|
26
|
+
# or
|
|
27
|
+
pnpm add slidecanvas
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Internal Flow Architecture
|
|
33
|
+
|
|
34
|
+
SlideCanvas operates on a sophisticated **Unidirectional Data Flow** architecture designed for reliability and scalability:
|
|
35
|
+
|
|
36
|
+
1. **Ingestion Layer**: A multi-stage processing engine that decomposes binary `.pptx` uploads or remote URLs.
|
|
37
|
+
2. **Normalization Engine**: Converts complex XML structures into a standardized, lightweight JSON presentation state.
|
|
38
|
+
3. **Virtual Canvas Sync**: Bridges the presentation state to a high-performance Fabric.js canvas, handling real-time manipulation and absolute positioning.
|
|
39
|
+
4. **Serialization Pipe**: Reconstructs the internal state back into standard OpenXML structures for high-fidelity export.
|
|
40
|
+
|
|
41
|
+
> [!NOTE]
|
|
42
|
+
> All parsing and state transformations occur within a secure, sandboxed internal context to ensure document integrity.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Getting Started
|
|
47
|
+
|
|
48
|
+
### 1. Basic Setup
|
|
49
|
+
|
|
50
|
+
To build a basic editor, import the `PptEditor` component into your React/Next.js application:
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { PptEditor } from 'slidecanvas';
|
|
54
|
+
|
|
55
|
+
export default function MyEditor() {
|
|
56
|
+
return (
|
|
57
|
+
<main className="h-screen">
|
|
58
|
+
<PptEditor appName="My Studio" />
|
|
59
|
+
</main>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. Loading Remote Presentations via URL
|
|
65
|
+
|
|
66
|
+
SlideCanvas makes it easy to load existing presentations directly via a URL. The component handles the fetching and parsing internally:
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { PptEditor } from 'slidecanvas';
|
|
70
|
+
|
|
71
|
+
export default function App() {
|
|
72
|
+
const pptxUrl = "https://example.com/presentations/q1-report.pptx";
|
|
73
|
+
|
|
74
|
+
return <PptEditor url={pptxUrl} />;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### 3. Handling Remote Files (S3 Integration)
|
|
81
|
+
|
|
82
|
+
SlideCanvas supports loading files from S3 or public URLs. To bypass CORS restrictions, we recommend setting up a proxy route in your `api/proxy/route.ts`:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Next.js API Proxy Example
|
|
86
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
87
|
+
|
|
88
|
+
export async function GET(request: NextRequest) {
|
|
89
|
+
const { searchParams } = new URL(request.url);
|
|
90
|
+
const targetUrl = searchParams.get('url');
|
|
91
|
+
|
|
92
|
+
const response = await fetch(targetUrl!, { cache: 'no-store' });
|
|
93
|
+
return new NextResponse(response.body, {
|
|
94
|
+
status: 200,
|
|
95
|
+
headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.presentationml.presentation' }
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 3. Enabling AI Features
|
|
101
|
+
|
|
102
|
+
SlideCanvas comes battery-included with Gemini AI support. To enable smart text actions (Shorten, Reframe, Lengthen), simply pass your Gemini API key to the component:
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
import { PptEditor } from 'slidecanvas';
|
|
106
|
+
|
|
107
|
+
export default function MyEditor() {
|
|
108
|
+
const geminiKey = process.env.NEXT_PUBLIC_GEMINI_API_KEY;
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<PptEditor
|
|
112
|
+
geminiApiKey={geminiKey}
|
|
113
|
+
appName="AI Design Studio"
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Advanced Usage Examples
|
|
120
|
+
|
|
121
|
+
### 1. 7-Second S3 Auto-Save (Real-Time Persistence)
|
|
122
|
+
|
|
123
|
+
To save changes back to S3 after a modifications stop for 7 seconds, use the `PptxExporter` combined with a debounce pattern:
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
import { PptEditor, PptxExporter } from 'slidecanvas';
|
|
127
|
+
import { useRef } from 'react';
|
|
128
|
+
|
|
129
|
+
export function S3Editor({ s3Key }: { s3Key: string }) {
|
|
130
|
+
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
131
|
+
|
|
132
|
+
const handleAutoSave = (presentation: any) => {
|
|
133
|
+
// 1. Clear previous timer if user keeps editing
|
|
134
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
135
|
+
|
|
136
|
+
// 2. Start a new 7-second countdown
|
|
137
|
+
timerRef.current = setTimeout(async () => {
|
|
138
|
+
console.log('User stopped editing. Exporting and saving to S3...');
|
|
139
|
+
|
|
140
|
+
// 3. Generate the .pptx file binary
|
|
141
|
+
const exporter = new PptxExporter();
|
|
142
|
+
const blob = await exporter.export(presentation);
|
|
143
|
+
|
|
144
|
+
// 4. Upload to your backend API which talks to S3
|
|
145
|
+
const formData = new FormData();
|
|
146
|
+
formData.append('file', blob, 'update.pptx');
|
|
147
|
+
formData.append('key', s3Key);
|
|
148
|
+
|
|
149
|
+
await fetch('/api/save-to-s3', {
|
|
150
|
+
method: 'POST',
|
|
151
|
+
body: formData
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
console.log('Saved successfully!');
|
|
155
|
+
}, 7000); // 7 seconds
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
return <PptEditor onChange={handleAutoSave} />;
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Sample Backend (Next.js API Route)
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// api/save-to-s3/route.ts
|
|
166
|
+
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
|
|
167
|
+
|
|
168
|
+
export async function POST(req: Request) {
|
|
169
|
+
const data = await req.formData();
|
|
170
|
+
const file = data.get('file') as File;
|
|
171
|
+
const key = data.get('key') as string;
|
|
172
|
+
|
|
173
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
174
|
+
|
|
175
|
+
const s3 = new S3Client({ region: "ap-south-1" });
|
|
176
|
+
await s3.send(new PutObjectCommand({
|
|
177
|
+
Bucket: "your-bucket-name",
|
|
178
|
+
Key: key,
|
|
179
|
+
Body: buffer,
|
|
180
|
+
ContentType: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
181
|
+
}));
|
|
182
|
+
|
|
183
|
+
return Response.json({ success: true });
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 2. Programmatic Presentation Creation
|
|
188
|
+
You can skip the parser and build a presentation state manually to generate slides on the fly:
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
import { PptEditor, Presentation } from 'slidecanvas';
|
|
192
|
+
|
|
193
|
+
const myDraft: Presentation = {
|
|
194
|
+
slides: [
|
|
195
|
+
{
|
|
196
|
+
id: 'welcome-slide',
|
|
197
|
+
elements: [
|
|
198
|
+
{
|
|
199
|
+
id: 'title-1',
|
|
200
|
+
type: 'text',
|
|
201
|
+
content: 'Hello World from SlideCanvas!',
|
|
202
|
+
x: 100, y: 100, width: 600, height: 100, fontSize: 48,
|
|
203
|
+
color: '#3b82f6', zIndex: 1
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
],
|
|
208
|
+
layout: { width: 12192000, height: 6858000 } // Standard 16:9 EMU
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export default function App() {
|
|
212
|
+
return <PptEditor initialPresentation={myDraft} />;
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 3. Custom Headless Processing (Node.js/Edge)
|
|
217
|
+
Extract text content or images without rendering the UI:
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
import { PptxParser } from 'slidecanvas';
|
|
221
|
+
|
|
222
|
+
async function extractCaptions(fileBuffer: ArrayBuffer) {
|
|
223
|
+
const parser = new PptxParser();
|
|
224
|
+
const presentation = await parser.parse(fileBuffer);
|
|
225
|
+
|
|
226
|
+
const allText = presentation.slides.flatMap(slide =>
|
|
227
|
+
slide.elements
|
|
228
|
+
.filter(el => el.type === 'text')
|
|
229
|
+
.map(el => el.content)
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
return allText;
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## API Reference
|
|
239
|
+
|
|
240
|
+
### `<PptEditor />`
|
|
241
|
+
|
|
242
|
+
| Prop | Type | Default | Description |
|
|
243
|
+
| :--- | :--- | :--- | :--- |
|
|
244
|
+
| `initialPresentation` | `Presentation` | `undefined` | Load an existing presentation state object. |
|
|
245
|
+
| `url` | `string` | `undefined` | Automatically fetch and parse a presentation from a remote URL. |
|
|
246
|
+
| `appName` | `string` | `"SlideCanvas"` | Customize the branding in the toolbar. |
|
|
247
|
+
| `geminiApiKey` | `string` | `undefined` | Your Google Gemini API key to enable assistant features. |
|
|
248
|
+
| `onChange` | `(state: Presentation) => void` | `undefined` | Callback triggered on any slide or element change. |
|
|
249
|
+
|
|
250
|
+
### `PptxParser` & `PptxExporter`
|
|
251
|
+
|
|
252
|
+
For headless workflows, you can use the internal engine directly:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
import { PptxParser, PptxExporter } from 'slidecanvas';
|
|
256
|
+
|
|
257
|
+
// Load
|
|
258
|
+
const parser = new PptxParser();
|
|
259
|
+
const presentation = await parser.parse(myBlob);
|
|
260
|
+
|
|
261
|
+
// Export
|
|
262
|
+
const exporter = new PptxExporter();
|
|
263
|
+
await exporter.export(presentation);
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Building for Production
|
|
269
|
+
|
|
270
|
+
To build your application for production, run:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npm run build
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The `slidecanvas` library is optimized for tree-shaking and minimizes your final bundle size by lazily loading the Fabric.js engine.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
This project is licensed under the MIT License. You are free to use, modify, and distribute this software as permitted by the license terms.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
type ElementType = 'text' | 'image' | 'shape';
|
|
4
|
+
type ShapeType = 'rect' | 'ellipse' | 'triangle' | 'line';
|
|
5
|
+
interface BaseElement {
|
|
6
|
+
id: string;
|
|
7
|
+
type: ElementType;
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
zIndex: number;
|
|
13
|
+
opacity?: number;
|
|
14
|
+
}
|
|
15
|
+
interface TextElement extends BaseElement {
|
|
16
|
+
type: 'text';
|
|
17
|
+
content: string;
|
|
18
|
+
fontSize: number;
|
|
19
|
+
fontFamily: string;
|
|
20
|
+
color: string;
|
|
21
|
+
isBold?: boolean;
|
|
22
|
+
isItalic?: boolean;
|
|
23
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
24
|
+
isBulleted?: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface ImageElement extends BaseElement {
|
|
27
|
+
type: 'image';
|
|
28
|
+
src: string;
|
|
29
|
+
}
|
|
30
|
+
interface ShapeElement extends BaseElement {
|
|
31
|
+
type: 'shape';
|
|
32
|
+
shapeType: ShapeType;
|
|
33
|
+
fill: string;
|
|
34
|
+
stroke?: string;
|
|
35
|
+
strokeWidth?: number;
|
|
36
|
+
}
|
|
37
|
+
type SlideElement = TextElement | ImageElement | ShapeElement;
|
|
38
|
+
interface Slide {
|
|
39
|
+
id: string;
|
|
40
|
+
elements: SlideElement[];
|
|
41
|
+
}
|
|
42
|
+
interface Presentation {
|
|
43
|
+
slides: Slide[];
|
|
44
|
+
layout?: {
|
|
45
|
+
width: number;
|
|
46
|
+
height: number;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface PptEditorProps {
|
|
51
|
+
initialPresentation?: Presentation;
|
|
52
|
+
url?: string;
|
|
53
|
+
appName?: string;
|
|
54
|
+
onChange?: (presentation: Presentation) => void;
|
|
55
|
+
geminiApiKey?: string;
|
|
56
|
+
}
|
|
57
|
+
declare const PptEditor: React.FC<PptEditorProps>;
|
|
58
|
+
|
|
59
|
+
declare class PptxParser {
|
|
60
|
+
private slideWidth;
|
|
61
|
+
private slideHeight;
|
|
62
|
+
private readonly CANVAS_WIDTH;
|
|
63
|
+
private readonly CANVAS_HEIGHT;
|
|
64
|
+
parse(input: File | Blob | ArrayBuffer | string): Promise<Presentation>;
|
|
65
|
+
private getAttr;
|
|
66
|
+
private findFirstByLocalName;
|
|
67
|
+
private findAllByLocalName;
|
|
68
|
+
private scaleX;
|
|
69
|
+
private scaleY;
|
|
70
|
+
private parseColor;
|
|
71
|
+
private resolveImage;
|
|
72
|
+
private parseSlide;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
declare class PptxExporter {
|
|
76
|
+
export(presentation: Presentation): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { type BaseElement, type ElementType, type ImageElement, PptEditor, PptxExporter, PptxParser, type Presentation, type ShapeElement, type ShapeType, type Slide, type SlideElement, type TextElement };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
type ElementType = 'text' | 'image' | 'shape';
|
|
4
|
+
type ShapeType = 'rect' | 'ellipse' | 'triangle' | 'line';
|
|
5
|
+
interface BaseElement {
|
|
6
|
+
id: string;
|
|
7
|
+
type: ElementType;
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
zIndex: number;
|
|
13
|
+
opacity?: number;
|
|
14
|
+
}
|
|
15
|
+
interface TextElement extends BaseElement {
|
|
16
|
+
type: 'text';
|
|
17
|
+
content: string;
|
|
18
|
+
fontSize: number;
|
|
19
|
+
fontFamily: string;
|
|
20
|
+
color: string;
|
|
21
|
+
isBold?: boolean;
|
|
22
|
+
isItalic?: boolean;
|
|
23
|
+
textAlign?: 'left' | 'center' | 'right';
|
|
24
|
+
isBulleted?: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface ImageElement extends BaseElement {
|
|
27
|
+
type: 'image';
|
|
28
|
+
src: string;
|
|
29
|
+
}
|
|
30
|
+
interface ShapeElement extends BaseElement {
|
|
31
|
+
type: 'shape';
|
|
32
|
+
shapeType: ShapeType;
|
|
33
|
+
fill: string;
|
|
34
|
+
stroke?: string;
|
|
35
|
+
strokeWidth?: number;
|
|
36
|
+
}
|
|
37
|
+
type SlideElement = TextElement | ImageElement | ShapeElement;
|
|
38
|
+
interface Slide {
|
|
39
|
+
id: string;
|
|
40
|
+
elements: SlideElement[];
|
|
41
|
+
}
|
|
42
|
+
interface Presentation {
|
|
43
|
+
slides: Slide[];
|
|
44
|
+
layout?: {
|
|
45
|
+
width: number;
|
|
46
|
+
height: number;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface PptEditorProps {
|
|
51
|
+
initialPresentation?: Presentation;
|
|
52
|
+
url?: string;
|
|
53
|
+
appName?: string;
|
|
54
|
+
onChange?: (presentation: Presentation) => void;
|
|
55
|
+
geminiApiKey?: string;
|
|
56
|
+
}
|
|
57
|
+
declare const PptEditor: React.FC<PptEditorProps>;
|
|
58
|
+
|
|
59
|
+
declare class PptxParser {
|
|
60
|
+
private slideWidth;
|
|
61
|
+
private slideHeight;
|
|
62
|
+
private readonly CANVAS_WIDTH;
|
|
63
|
+
private readonly CANVAS_HEIGHT;
|
|
64
|
+
parse(input: File | Blob | ArrayBuffer | string): Promise<Presentation>;
|
|
65
|
+
private getAttr;
|
|
66
|
+
private findFirstByLocalName;
|
|
67
|
+
private findAllByLocalName;
|
|
68
|
+
private scaleX;
|
|
69
|
+
private scaleY;
|
|
70
|
+
private parseColor;
|
|
71
|
+
private resolveImage;
|
|
72
|
+
private parseSlide;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
declare class PptxExporter {
|
|
76
|
+
export(presentation: Presentation): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { type BaseElement, type ElementType, type ImageElement, PptEditor, PptxExporter, PptxParser, type Presentation, type ShapeElement, type ShapeType, type Slide, type SlideElement, type TextElement };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";var Oe=Object.create;var ne=Object.defineProperty,He=Object.defineProperties,je=Object.getOwnPropertyDescriptor,Xe=Object.getOwnPropertyDescriptors,We=Object.getOwnPropertyNames,ge=Object.getOwnPropertySymbols,Ge=Object.getPrototypeOf,ye=Object.prototype.hasOwnProperty,Ye=Object.prototype.propertyIsEnumerable;var be=(m,o,l)=>o in m?ne(m,o,{enumerable:!0,configurable:!0,writable:!0,value:l}):m[o]=l,w=(m,o)=>{for(var l in o||(o={}))ye.call(o,l)&&be(m,l,o[l]);if(ge)for(var l of ge(o))Ye.call(o,l)&&be(m,l,o[l]);return m},I=(m,o)=>He(m,Xe(o));var _e=(m,o)=>{for(var l in o)ne(m,l,{get:o[l],enumerable:!0})},ve=(m,o,l,c)=>{if(o&&typeof o=="object"||typeof o=="function")for(let g of We(o))!ye.call(m,g)&&g!==l&&ne(m,g,{get:()=>o[g],enumerable:!(c=je(o,g))||c.enumerable});return m};var pe=(m,o,l)=>(l=m!=null?Oe(Ge(m)):{},ve(o||!m||!m.__esModule?ne(l,"default",{value:m,enumerable:!0}):l,m)),Ke=m=>ve(ne({},"__esModule",{value:!0}),m);var tt={};_e(tt,{PptEditor:()=>et,PptxExporter:()=>oe,PptxParser:()=>le});module.exports=Ke(tt);var z=require("react");var M=pe(require("react")),x=require("lucide-react");var we=require("clsx"),Ne=require("tailwind-merge");function E(...m){return(0,Ne.twMerge)((0,we.clsx)(m))}var e=require("react/jsx-runtime"),Ve=["Inter","Lato","Open Sans","Poppins","Roboto","Roboto Slab","Georgia","Playfair Display","Merriweather","Nunito Sans","Montserrat","Oswald","Raleway","Ubuntu","Lora","PT Sans","PT Serif","Play","Arvo","Kanit","Times New Roman","Arial"],qe=[12,14,16,18,20,24,28,32,36,48,64,72,96],Je=[{name:"Basic Shapes",shapes:["rect","circle","triangle","rightTriangle","rhombus","parallelogram","trapezoid","pentagon","hexagon","heptagon","octagon","heart","smiley","sun","moon"]},{name:"Arrows",shapes:["arrowRight","arrowLeft","arrowUp","arrowDown","arrowLeftRight","arrowUpDown"]},{name:"Stars & Symbols",shapes:["star4","star5","star6","star8","cloud","lightning"]},{name:"Equation Shapes",shapes:["plus","minus","multiply","divide","equal"]}],Ze=({onAddShape:m})=>{let[o,l]=(0,M.useState)(!1);return M.default.useEffect(()=>(window._toggleShapesMenu=()=>l(!o),()=>{window._toggleShapesMenu=void 0}),[o]),o?(0,e.jsx)("div",{className:"absolute top-full left-0 mt-2 bg-white border border-slate-200 rounded-2xl shadow-2xl p-4 w-[320px] max-h-[480px] overflow-y-auto z-[100] animate-in fade-in zoom-in-95 duration-200",children:(0,e.jsx)("div",{className:"flex flex-col gap-6",children:Je.map(c=>(0,e.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,e.jsx)("span",{className:"text-[10px] font-black uppercase tracking-widest text-slate-400 px-1",children:c.name}),(0,e.jsx)("div",{className:"grid grid-cols-5 gap-1",children:c.shapes.map(g=>(0,e.jsx)("button",{onClick:()=>{m(g),l(!1)},className:"aspect-square hover:bg-slate-50 rounded-lg flex items-center justify-center border border-transparent hover:border-slate-100 transition-all group",title:g,children:(0,e.jsx)("div",{className:"w-6 h-6 bg-slate-100 rounded-sm group-hover:bg-blue-100 group-hover:scale-110 transition-all flex items-center justify-center overflow-hidden",children:(0,e.jsx)("div",{className:"text-[8px] font-bold text-slate-400 group-hover:text-blue-600 uppercase text-center scale-[0.8] leading-tight",children:g.slice(0,3)})})},g))})]},c.name))})}):null},Se=({onAddText:m,onAddImage:o,onAddShape:l,onAddSlide:c,onExport:g,onFormatText:p,onDeleteElement:N,onApplyLayout:v,onPlay:f,selectedElement:i,appName:y,onAiAction:a,onAiResponseAction:b,aiResponse:s,isAiLoading:t,onNewPresentation:n,onLoadPresentation:u})=>{let S=M.default.useRef(null),[L,U]=(0,M.useState)("Home"),[O,X]=(0,M.useState)(!1),[W,G]=(0,M.useState)(!1),[Y,P]=(0,M.useState)(!1),[ie,F]=(0,M.useState)(!1),[_,K]=(0,M.useState)("file"),[B,q]=(0,M.useState)(""),T=(i==null?void 0:i.type)==="text",re=(i==null?void 0:i.type)==="shape",ue="#B7472A";return(0,e.jsxs)("div",{className:"flex flex-col border-b border-slate-200 bg-white z-50 select-none",children:[(0,e.jsxs)("div",{className:"flex items-center bg-[#F3F2F1] border-b border-slate-200 h-10",children:[(0,e.jsx)("div",{className:"flex items-center h-full px-4 border-r border-slate-200 mr-2 bg-[#B7472A] text-white",children:(0,e.jsx)("span",{className:"font-black text-xs tracking-tighter capitalize",children:y})}),(0,e.jsxs)("div",{className:"flex h-full relative",children:[(0,e.jsx)("button",{onClick:()=>P(!Y),className:E("px-4 h-10 transition-all flex items-center text-xs font-semibold relative",Y?"text-white bg-[#B7472A]":"text-slate-600 hover:bg-slate-200/50"),children:"File"}),Y&&(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("div",{className:"fixed inset-0 z-[140]",onClick:()=>P(!1)}),(0,e.jsxs)("div",{className:"absolute top-10 left-0 w-48 bg-white border border-slate-200 shadow-xl rounded-b-xl z-[150] py-2 animate-in fade-in slide-in-from-top-1 duration-200",children:[(0,e.jsxs)("button",{onClick:()=>{n(),P(!1)},className:"w-full text-left px-4 py-2 text-xs text-slate-700 hover:bg-slate-50 flex items-center gap-3 transition-colors",children:[(0,e.jsx)(x.Plus,{size:14,className:"text-slate-400"}),(0,e.jsx)("span",{children:"Create New"})]}),(0,e.jsxs)("button",{onClick:()=>{F(!0),P(!1)},className:"w-full text-left px-4 py-2 text-xs text-slate-700 hover:bg-slate-50 flex items-center gap-3 transition-colors",children:[(0,e.jsx)(x.Download,{size:14,className:"text-slate-400"}),(0,e.jsx)("span",{children:"Upload"})]}),(0,e.jsx)("div",{className:"h-[1px] bg-slate-100 my-1 mx-2"}),(0,e.jsxs)("button",{onClick:()=>{g(),P(!1)},className:"w-full text-left px-4 py-2 text-xs text-slate-700 hover:bg-slate-50 flex items-center gap-3 transition-colors",children:[(0,e.jsx)(x.Share2,{size:14,className:"text-slate-400"}),(0,e.jsx)("span",{children:"Export PPTX"})]})]})]})]}),(0,e.jsx)("div",{className:"flex-1"}),(0,e.jsxs)("div",{className:"flex items-center gap-4 px-4 text-slate-400",children:[(0,e.jsx)("div",{className:"h-4 w-[1px] bg-slate-200"}),(0,e.jsx)(x.Play,{size:16,className:"cursor-pointer hover:text-[#B7472A] transition-colors",onClick:f})]})]}),(0,e.jsxs)("div",{className:"bg-white h-[96px] flex items-center px-6 gap-8 justify-start",children:[(0,e.jsxs)("div",{className:"flex flex-col items-center border-r border-slate-100 pr-8 py-1 min-w-[140px]",children:[(0,e.jsxs)("div",{className:"flex items-center gap-2 mb-1",children:[(0,e.jsxs)("button",{onClick:c,className:"flex flex-col items-center justify-center p-2 hover:bg-slate-50 rounded-xl group transition-all",children:[(0,e.jsx)("div",{className:"bg-orange-50 p-2 rounded-lg group-hover:scale-110 transition-transform",children:(0,e.jsx)(x.Plus,{size:22,className:"text-[#B7472A]"})}),(0,e.jsx)("span",{className:"text-[10px] font-bold text-slate-700 mt-1",children:"New Slide"})]}),(0,e.jsxs)("div",{className:"relative",children:[(0,e.jsxs)("button",{onClick:()=>X(!O),className:E("p-2 hover:bg-slate-50 rounded-xl transition-all flex flex-col items-center",O&&"bg-slate-100"),children:[(0,e.jsx)(x.Layout,{size:20,className:"text-slate-500"}),(0,e.jsx)("span",{className:"text-[10px] font-medium text-slate-500 mt-1",children:"Layout"})]}),O&&(0,e.jsxs)("div",{className:"absolute top-full left-0 mt-2 bg-white border border-slate-200 rounded-xl shadow-2xl p-2 w-56 flex flex-col gap-1 z-[100] animate-in fade-in zoom-in-95 duration-200",children:[(0,e.jsxs)("button",{onClick:()=>{v("title"),X(!1)},className:"flex items-center gap-3 px-4 py-2.5 hover:bg-slate-50 rounded-lg text-xs font-semibold text-slate-700 transition-colors border border-transparent hover:border-slate-100",children:[(0,e.jsx)(x.FileText,{size:16,className:"text-blue-500"})," Title Slide"]}),(0,e.jsxs)("button",{onClick:()=>{v("content"),X(!1)},className:"flex items-center gap-3 px-4 py-2.5 hover:bg-slate-50 rounded-lg text-xs font-semibold text-slate-700 transition-colors border border-transparent hover:border-slate-100",children:[(0,e.jsx)(x.List,{size:16,className:"text-emerald-500"})," Title & Content"]}),(0,e.jsxs)("button",{onClick:()=>{v("split"),X(!1)},className:"flex items-center gap-3 px-4 py-2.5 hover:bg-slate-50 rounded-lg text-xs font-semibold text-slate-700 transition-colors border border-transparent hover:border-slate-100",children:[(0,e.jsx)(x.Columns,{size:16,className:"text-purple-500"})," Two Columns"]})]})]})]}),(0,e.jsx)("span",{className:"text-[9px] uppercase tracking-[0.2em] font-black text-slate-300 mt-auto",children:"Slides"})]}),(0,e.jsxs)("div",{className:"flex flex-col items-center border-r border-slate-100 px-8 py-1",children:[(0,e.jsxs)("div",{className:"flex flex-col gap-2 min-w-[220px]",children:[(0,e.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,e.jsx)("select",{disabled:!T,value:(i==null?void 0:i.fontFamily)||"Arial",onChange:A=>p({fontFamily:A.target.value}),className:"h-8 px-3 text-xs text-slate-900 border border-slate-200 rounded-lg font-semibold bg-white hover:border-slate-300 outline-none w-36 disabled:opacity-50 transition-colors appearance-none cursor-pointer",children:Ve.map(A=>(0,e.jsx)("option",{value:A,children:A},A))}),(0,e.jsx)("select",{disabled:!T,value:(i==null?void 0:i.fontSize)||24,onChange:A=>p({fontSize:parseInt(A.target.value)}),className:"h-8 px-2 text-xs text-slate-900 border border-slate-200 rounded-lg font-semibold bg-white hover:border-slate-300 outline-none w-16 disabled:opacity-50 transition-colors appearance-none cursor-pointer text-center",children:qe.map(A=>(0,e.jsx)("option",{value:A,children:A},A))})]}),(0,e.jsxs)("div",{className:"flex items-center gap-1",children:[(0,e.jsx)("button",{disabled:!T,onClick:()=>p({isBold:!i.isBold}),className:E("p-2 rounded-lg transition-all disabled:opacity-30",i!=null&&i.isBold?"bg-slate-100 text-slate-900":"text-slate-500 hover:bg-slate-50"),children:(0,e.jsx)(x.Bold,{size:16,strokeWidth:3})}),(0,e.jsx)("button",{disabled:!T,onClick:()=>p({isItalic:!i.isItalic}),className:E("p-2 rounded-lg transition-all disabled:opacity-30",i!=null&&i.isItalic?"bg-slate-100 text-slate-900":"text-slate-500 hover:bg-slate-50"),children:(0,e.jsx)(x.Italic,{size:16})}),(0,e.jsx)("div",{className:"h-4 w-[1px] bg-slate-200 mx-2"}),(0,e.jsxs)("div",{className:"relative group p-1 hover:bg-slate-50 rounded-lg transition-colors cursor-pointer",children:[(0,e.jsx)("input",{type:"color",disabled:!i,value:T?i.color||"#000000":(i==null?void 0:i.fill)||"#3b82f6",onChange:A=>p(T?{color:A.target.value}:{fill:A.target.value}),className:"w-8 h-6 p-0 border-0 bg-transparent cursor-pointer disabled:opacity-30",title:"Format Color"}),(0,e.jsx)("div",{className:"absolute bottom-1.5 left-2 right-2 h-1 rounded-full",style:{backgroundColor:T?i.color||"#000000":(i==null?void 0:i.fill)||"#3b82f6"}})]})]})]}),(0,e.jsx)("span",{className:"text-[9px] uppercase tracking-[0.2em] font-black text-slate-300 mt-auto pt-1",children:"Font"})]}),(0,e.jsxs)("div",{className:"flex flex-col items-center border-r border-slate-100 px-8 py-1",children:[(0,e.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,e.jsxs)("div",{className:"flex items-center gap-1 px-1.5 py-1 bg-slate-50 rounded-xl border border-slate-100",children:[(0,e.jsx)("button",{disabled:!T,onClick:()=>p({textAlign:"left"}),className:E("p-1.5 rounded-lg transition-all disabled:opacity-30",(i==null?void 0:i.textAlign)==="left"?"bg-white shadow-sm text-[#B7472A] scale-110":"text-slate-400"),children:(0,e.jsx)(x.AlignLeft,{size:16})}),(0,e.jsx)("button",{disabled:!T,onClick:()=>p({textAlign:"center"}),className:E("p-1.5 rounded-lg transition-all disabled:opacity-30",(i==null?void 0:i.textAlign)==="center"?"bg-white shadow-sm text-[#B7472A] scale-110":"text-slate-400"),children:(0,e.jsx)(x.AlignCenter,{size:16})}),(0,e.jsx)("button",{disabled:!T,onClick:()=>p({textAlign:"right"}),className:E("p-1.5 rounded-lg transition-all disabled:opacity-30",(i==null?void 0:i.textAlign)==="right"?"bg-white shadow-sm text-[#B7472A] scale-110":"text-slate-400"),children:(0,e.jsx)(x.AlignRight,{size:16})})]}),(0,e.jsx)("button",{disabled:!T,onClick:()=>p({isBulleted:!i.isBulleted}),className:E("p-2 rounded-lg self-start transition-all disabled:opacity-30",i!=null&&i.isBulleted?"bg-slate-100 text-[#B7472A]":"text-slate-500 hover:bg-slate-50"),children:(0,e.jsx)(x.List,{size:18})})]}),(0,e.jsx)("span",{className:"text-[9px] uppercase tracking-[0.2em] font-black text-slate-300 mt-auto",children:"Paragraph"})]}),(0,e.jsxs)("div",{className:"flex flex-col items-center border-r border-slate-100 px-8 py-1",children:[(0,e.jsxs)("div",{className:"flex flex-wrap items-center gap-2 mb-1",children:[(0,e.jsxs)("div",{className:"relative group/shapes",children:[(0,e.jsxs)("button",{className:"flex flex-col items-center justify-center p-2 hover:bg-slate-50 rounded-xl group transition-all",onClick:()=>{var A;return(A=window._toggleShapesMenu)==null?void 0:A.call(window)},children:[(0,e.jsx)("div",{className:"bg-blue-50 p-2 rounded-lg group-hover:scale-110 transition-transform",children:(0,e.jsx)(x.Square,{size:22,className:"text-blue-600"})}),(0,e.jsx)("span",{className:"text-[10px] font-bold text-slate-700 mt-1",children:"Shapes"})]}),(0,e.jsx)(Ze,{onAddShape:A=>{l(A)}})]}),(0,e.jsx)("div",{className:"h-10 w-[1px] bg-slate-100 mx-2"}),(0,e.jsx)("button",{onClick:m,className:"p-2.5 hover:bg-slate-50 rounded-xl text-slate-600 transition-colors",title:"Text Box",children:(0,e.jsx)(x.Type,{size:18})}),(0,e.jsxs)("button",{onClick:()=>{var A;return(A=S.current)==null?void 0:A.click()},className:"p-2.5 hover:bg-slate-50 rounded-xl text-slate-600 transition-colors",title:"Image",children:[(0,e.jsx)(x.Image,{size:18}),(0,e.jsx)("input",{type:"file",ref:S,className:"hidden",accept:"image/*",onChange:A=>{var Q;return((Q=A.target.files)==null?void 0:Q[0])&&o(A.target.files[0])}})]})]}),(0,e.jsx)("span",{className:"text-[9px] uppercase tracking-[0.2em] font-black text-slate-300 mt-auto",children:"Drawing"})]}),(0,e.jsxs)("div",{className:"flex flex-col items-center border-r border-slate-100 px-8 py-1",children:[(0,e.jsxs)("div",{className:"flex flex-col gap-2 relative",children:[(0,e.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,e.jsxs)("button",{disabled:!T||t,onClick:()=>a(i.id,"shorten"),className:"flex items-center gap-2 px-3 py-1.5 hover:bg-slate-50 rounded-lg text-slate-600 disabled:opacity-20 transition-all group border border-transparent hover:border-slate-100",children:[(0,e.jsx)(x.Sparkles,{size:16,className:"text-purple-500"}),(0,e.jsx)("span",{className:"text-[10px] font-bold",children:"Shorten"})]}),(0,e.jsxs)("button",{disabled:!T||t,onClick:()=>a(i.id,"reframe"),className:"flex items-center gap-2 px-3 py-1.5 hover:bg-slate-50 rounded-lg text-slate-600 disabled:opacity-20 transition-all group border border-transparent hover:border-slate-100",children:[(0,e.jsx)(x.Sparkles,{size:16,className:"text-blue-500"}),(0,e.jsx)("span",{className:"text-[10px] font-bold",children:"Reframe"})]}),(0,e.jsxs)("button",{disabled:!T||t,onClick:()=>a(i.id,"lengthen"),className:"flex items-center gap-2 px-3 py-1.5 hover:bg-slate-50 rounded-lg text-slate-600 disabled:opacity-20 transition-all group border border-transparent hover:border-slate-100",children:[(0,e.jsx)(x.Sparkles,{size:16,className:"text-emerald-500"}),(0,e.jsx)("span",{className:"text-[10px] font-bold",children:"Lengthen"})]})]}),t&&(0,e.jsx)("div",{className:"absolute inset-0 bg-white/80 flex items-center justify-center rounded-lg z-10 backdrop-blur-[1px]",children:(0,e.jsx)(x.RefreshCw,{size:18,className:"text-blue-600 animate-spin"})}),s&&(0,e.jsxs)("div",{className:"fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[400px] bg-white border border-slate-200 rounded-2xl shadow-2xl p-6 z-[200] animate-in fade-in zoom-in-95 duration-200",children:[(0,e.jsxs)("div",{className:"flex items-center gap-2 mb-4",children:[(0,e.jsx)(x.Sparkles,{size:20,className:"text-purple-600"}),(0,e.jsx)("h3",{className:"text-sm font-black text-slate-800 uppercase tracking-widest",children:"AI Generated Response"})]}),(0,e.jsxs)("div",{className:"bg-slate-50 p-4 rounded-xl mb-6 max-h-[200px] overflow-y-auto border border-slate-100 italic text-slate-700 text-sm leading-relaxed",children:['"',s,'"']}),(0,e.jsxs)("div",{className:"flex flex-col gap-2",children:[(0,e.jsxs)("div",{className:"grid grid-cols-2 gap-2",children:[(0,e.jsx)("button",{onClick:()=>b("replace"),className:"px-4 py-2.5 bg-[#B7472A] text-white text-[11px] font-bold rounded-lg hover:bg-[#a33f25] transition-colors shadow-sm",children:"REPLACE CURRENT"}),(0,e.jsx)("button",{onClick:()=>b("addBelow"),className:"px-4 py-2.5 bg-slate-800 text-white text-[11px] font-bold rounded-lg hover:bg-slate-900 transition-colors shadow-sm",children:"ADD BELOW"})]}),(0,e.jsxs)("div",{className:"flex gap-2",children:[(0,e.jsxs)("button",{onClick:()=>b("regenerate"),className:"flex-1 px-4 py-2.5 border border-slate-200 text-slate-600 text-[11px] font-bold rounded-lg hover:bg-slate-50 transition-colors flex items-center justify-center gap-2",children:[(0,e.jsx)(x.RefreshCw,{size:14})," REGENERATE"]}),(0,e.jsx)("button",{className:"px-4 py-2.5 text-slate-400 text-[11px] font-bold hover:text-slate-600 transition-colors",onClick:()=>{b("replace")},children:"CLOSE"})]})]})]})]}),(0,e.jsx)("span",{className:"text-[9px] uppercase tracking-[0.2em] font-black text-slate-300 mt-auto",children:"AI Text"})]}),(0,e.jsxs)("div",{className:"flex flex-col items-center px-8 py-1",children:[(0,e.jsxs)("div",{className:"flex gap-3",children:[(0,e.jsx)("button",{onClick:g,className:"flex flex-col items-center justify-center p-2.5 hover:bg-emerald-50 rounded-xl group transition-all",title:"Download Presentation",children:(0,e.jsx)("div",{className:"bg-emerald-100/50 p-2 rounded-lg group-hover:scale-110 transition-transform",children:(0,e.jsx)(x.Download,{size:22,className:"text-emerald-700"})})}),i&&(0,e.jsx)("button",{onClick:N,className:"flex flex-col items-center justify-center p-2.5 hover:bg-red-50 rounded-xl group transition-all",title:"Delete Element",children:(0,e.jsx)("div",{className:"bg-red-100/50 p-2 rounded-lg group-hover:scale-110 transition-transform",children:(0,e.jsx)(x.Trash2,{size:22,className:"text-red-600"})})})]}),(0,e.jsx)("span",{className:"text-[9px] uppercase tracking-[0.2em] font-black text-slate-300 mt-auto",children:"Actions"})]}),(0,e.jsx)("div",{className:"flex-1"}),(0,e.jsxs)("div",{className:"pr-12 flex flex-col items-end gap-1 group",children:[(0,e.jsxs)("div",{className:"flex items-center gap-1.5 text-[10px] font-black text-slate-300 group-hover:text-[#B7472A] transition-colors",children:[(0,e.jsx)(x.History,{size:12}),(0,e.jsx)("span",{children:"SAVED AUTOMATICALLY"})]}),(0,e.jsx)("div",{className:"h-1 w-24 bg-slate-100 rounded-full overflow-hidden",children:(0,e.jsx)("div",{className:"h-full w-full bg-emerald-500/20"})})]})]}),ie&&(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("div",{className:"fixed inset-0 bg-slate-900/40 backdrop-blur-sm z-[2000]",onClick:()=>F(!1)}),(0,e.jsxs)("div",{className:"fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[480px] bg-white rounded-3xl shadow-2xl z-[2001] border border-slate-200 p-8 animate-in fade-in zoom-in-95 duration-200",children:[(0,e.jsxs)("div",{className:"flex justify-between items-center mb-6",children:[(0,e.jsxs)("h3",{className:"text-lg font-black text-slate-800 tracking-tight flex items-center gap-3",children:[(0,e.jsx)("div",{className:"p-2 bg-blue-50 text-blue-600 rounded-xl",children:(0,e.jsx)(x.Download,{size:20})}),"Upload Presentation"]}),(0,e.jsx)("button",{onClick:()=>F(!1),className:"text-slate-400 hover:text-slate-600 transition-colors",children:(0,e.jsx)(x.RefreshCw,{size:20,className:"rotate-45"})})]}),(0,e.jsxs)("div",{className:"flex gap-2 p-1 bg-slate-50 rounded-2xl mb-8",children:[(0,e.jsx)("button",{onClick:()=>K("file"),className:E("flex-1 py-3 text-xs font-black rounded-xl transition-all",_==="file"?"bg-white text-blue-600 shadow-sm":"text-slate-500 hover:text-slate-700"),children:"FILE UPLOAD"}),(0,e.jsx)("button",{onClick:()=>K("link"),className:E("flex-1 py-3 text-xs font-black rounded-xl transition-all",_==="link"?"bg-white text-blue-600 shadow-sm":"text-slate-500 hover:text-slate-700"),children:"LINK UPLOAD"})]}),_==="file"?(0,e.jsxs)("label",{className:"flex flex-col items-center justify-center gap-4 py-12 border-2 border-dashed border-slate-200 rounded-3xl hover:border-blue-400 hover:bg-blue-50/50 transition-all cursor-pointer group",children:[(0,e.jsx)("div",{className:"p-4 bg-white rounded-2xl shadow-sm border border-slate-100 group-hover:scale-110 transition-transform",children:(0,e.jsx)(x.Plus,{size:24,className:"text-blue-500"})}),(0,e.jsxs)("div",{className:"text-center",children:[(0,e.jsx)("p",{className:"text-sm font-bold text-slate-700",children:"Choose a PPTX file"}),(0,e.jsx)("p",{className:"text-xs text-slate-400 mt-1",children:"Maximum file size: 50MB"})]}),(0,e.jsx)("input",{type:"file",accept:".pptx",className:"hidden",onChange:A=>{var de;let Q=(de=A.target.files)==null?void 0:de[0];Q&&(u(Q),F(!1))}})]}):(0,e.jsxs)("div",{className:"space-y-4",children:[(0,e.jsx)("div",{className:"relative",children:(0,e.jsx)("input",{type:"text",placeholder:"Paste S3 or public URL",value:B,onChange:A=>q(A.target.value),className:"w-full bg-slate-50 border border-slate-200 rounded-2xl px-5 py-4 focus:outline-none focus:ring-4 focus:ring-blue-500/10 focus:border-blue-500 text-sm placeholder:text-slate-400 text-black"})}),(0,e.jsx)("button",{onClick:()=>{B.trim()&&(u(B.trim()),F(!1))},disabled:!B.trim(),className:"w-full bg-blue-600 hover:bg-blue-700 disabled:bg-slate-300 text-white font-black py-4 rounded-2xl transition-all shadow-lg shadow-blue-500/20",children:"LOAD PRESENTATION"}),(0,e.jsx)("p",{className:"text-[10px] text-slate-400 text-center uppercase tracking-widest font-black",children:"Supports S3, Dropbox, and public URLS"})]})]})]})]})};var ee=require("lucide-react"),$=require("@dnd-kit/core"),Z=require("@dnd-kit/sortable"),Ae=require("@dnd-kit/utilities");var C=require("react/jsx-runtime"),Qe=({slide:m,index:o,isActive:l,onSelect:c,onDelete:g,onDuplicate:p,showDelete:N})=>{let{attributes:v,listeners:f,setNodeRef:i,transform:y,transition:a,isDragging:b}=(0,Z.useSortable)({id:m.id}),s={transform:Ae.CSS.Transform.toString(y),transition:a,zIndex:b?2:1,opacity:b?.5:1};return(0,C.jsxs)("div",{ref:i,style:s,onClick:c,className:E("cursor-pointer border-[1.5px] rounded-2xl p-2 transition-all duration-300 group relative select-none",l?"border-[#B7472A] bg-white":"border-transparent hover:border-slate-200 bg-white/50 hover:bg-white"),children:[(0,C.jsxs)("div",{className:"text-[10px] font-bold text-slate-400 mb-1 flex items-center justify-between",children:[(0,C.jsxs)("div",{className:"flex items-center gap-1",children:[(0,C.jsx)("div",I(w(w({},v),f),{className:"cursor-grab active:cursor-grabbing p-0.5 hover:bg-slate-100 rounded text-slate-300 hover:text-slate-500",children:(0,C.jsx)(ee.GripVertical,{size:10})})),(0,C.jsxs)("span",{children:["SLIDE ",o+1]})]}),(0,C.jsxs)("div",{className:"flex items-center gap-1",children:[l&&(0,C.jsx)("span",{className:"h-1.5 w-1.5 rounded-full bg-[#B7472A]"}),(0,C.jsxs)("div",{className:"flex items-center opacity-0 group-hover:opacity-100 transition-opacity",children:[(0,C.jsx)("button",{onClick:t=>{t.stopPropagation(),p()},className:"p-1 hover:bg-blue-50 text-slate-400 hover:text-blue-500 rounded transition-all",title:"Duplicate Slide",children:(0,C.jsx)(ee.Copy,{size:12})}),N&&(0,C.jsx)("button",{onClick:t=>{t.stopPropagation(),g()},className:"p-1 hover:bg-red-50 text-red-400 hover:text-red-500 rounded transition-all",title:"Delete Slide",children:(0,C.jsx)(ee.Trash2,{size:12})})]})]})]}),(0,C.jsx)("div",{className:"aspect-video bg-white rounded-xl flex items-center justify-center border border-slate-200 overflow-hidden relative group-hover:shadow-sm transition-shadow",children:(0,C.jsx)("div",{className:"absolute inset-0 origin-top-left pointer-events-none select-none",style:{width:"1200px",height:"675px",transform:"scale(0.165)",backgroundColor:"#ffffff"},children:m.elements.sort((t,n)=>(t.zIndex||0)-(n.zIndex||0)).map(t=>{var u;let n={position:"absolute",left:t.x,top:t.y,width:t.width,height:t.height,opacity:(u=t.opacity)!=null?u:1};return t.type==="text"?(0,C.jsx)("div",{style:I(w({},n),{fontSize:t.fontSize,fontFamily:t.fontFamily,color:t.color,textAlign:t.textAlign||"left",fontWeight:t.isBold?"bold":"normal",fontStyle:t.isItalic?"italic":"normal",lineHeight:1.2,overflow:"hidden",wordBreak:"break-word",whiteSpace:"pre-wrap"}),children:t.content},t.id):t.type==="shape"?(0,C.jsx)("div",{style:I(w({},n),{backgroundColor:t.fill,borderRadius:t.shapeType==="ellipse"?"50%":"0"})},t.id):t.type==="image"?(0,C.jsx)("img",{src:t.src,alt:"",style:I(w({},n),{objectFit:"contain"})},t.id):null})})})]})},ke=({slides:m,currentSlideIndex:o,onSelectSlide:l,onDeleteSlide:c,onDuplicateSlide:g,onReorderSlides:p})=>{let N=(0,$.useSensors)((0,$.useSensor)($.PointerSensor,{activationConstraint:{distance:5}}),(0,$.useSensor)($.KeyboardSensor,{coordinateGetter:Z.sortableKeyboardCoordinates}));return(0,C.jsx)("div",{className:"w-64 bg-white border-r border-slate-100 overflow-y-auto p-4 flex flex-col gap-4",children:(0,C.jsx)($.DndContext,{sensors:N,collisionDetection:$.closestCenter,onDragEnd:f=>{let{active:i,over:y}=f;if(i.id!==(y==null?void 0:y.id)){let a=m.findIndex(s=>s.id===i.id),b=m.findIndex(s=>s.id===(y==null?void 0:y.id));p(a,b)}},children:(0,C.jsx)(Z.SortableContext,{items:m.map(f=>f.id),strategy:Z.verticalListSortingStrategy,children:m.map((f,i)=>(0,C.jsx)(Qe,{slide:f,index:i,isActive:i===o,onSelect:()=>l(i),onDelete:()=>c(i),onDuplicate:()=>g(i),showDelete:m.length>1},f.id))})})})};var H=require("react"),j=pe(require("fabric"));var me=require("react/jsx-runtime"),fe=({slide:m,onElementUpdate:o,onSelect:l})=>{let c=(0,H.useRef)(null),g=(0,H.useRef)(null),p=(0,H.useRef)(!1),N=(0,H.useRef)(o),v=(0,H.useRef)(l);return(0,H.useEffect)(()=>{N.current=o,v.current=l},[o,l]),(0,H.useEffect)(()=>{if(c.current&&!g.current){g.current=new j.Canvas(c.current,{width:1200,height:675,backgroundColor:"#ffffff"});let f=g.current,i=s=>{s.left<0&&s.set("left",0),s.top<0&&s.set("top",0);let t=s.getBoundingRect();t.left+t.width>(f.width||1200)&&s.set("left",(f.width||1200)-t.width),t.top+t.height>(f.height||675)&&s.set("top",(f.height||675)-t.height)};f.on("object:moving",s=>i(s.target)),f.on("object:scaling",s=>i(s.target));let y=s=>{var u;if(p.current)return;let t=s.target,n=(u=t.get("data"))==null?void 0:u.id;t&&n&&N.current(n,w({x:t.left,y:t.top,width:t.getScaledWidth(),height:t.getScaledHeight()},t.isType("textbox")?{content:t.text,textAlign:t.textAlign,fontSize:t.fontSize,fontFamily:t.fontFamily,color:t.fill}:{fill:t.fill}))};f.on("object:modified",y),f.on("text:changed",y);let a=s=>{var n,u;let t=((n=s.selected)==null?void 0:n[0])||s.target;if(t){let S=(u=t.get("data"))==null?void 0:u.id;v.current(S)}};f.on("selection:created",a),f.on("selection:updated",a),f.on("selection:cleared",()=>v.current(null));let b=s=>{let t=f.getActiveObject();if(!t||t.isType("textbox")&&t.isEditing)return;let n=s.shiftKey?10:1,u=!1;switch(s.key){case"ArrowLeft":t.set("left",t.left-n),u=!0;break;case"ArrowRight":t.set("left",t.left+n),u=!0;break;case"ArrowUp":t.set("top",t.top-n),u=!0;break;case"ArrowDown":t.set("top",t.top+n),u=!0;break}u&&(i(t),f.requestRenderAll(),y({target:t}))};window.addEventListener("keydown",b),f._keyboardListener=b}return()=>{if(g.current){let f=g.current._keyboardListener;f&&window.removeEventListener("keydown",f),g.current.dispose(),g.current=null}}},[]),(0,H.useEffect)(()=>{if(!g.current)return;let f=g.current;(async()=>{p.current=!0;let y=f.getObjects(),a=new Set(m.elements.map(s=>s.id));y.forEach(s=>{var n;let t=(n=s.get("data"))==null?void 0:n.id;t&&!a.has(t)&&f.remove(s)});let b=[...m.elements].sort((s,t)=>(s.zIndex||0)-(t.zIndex||0));for(let s of b){let t=y.find(n=>{var u;return((u=n.get("data"))==null?void 0:u.id)===s.id});if(t){if(t===f.getActiveObject()&&t.isType("textbox")&&t.isEditing)continue;let n={left:s.x,top:s.y,opacity:s.opacity!==void 0?s.opacity:1,zIndex:s.zIndex};s.type==="text"&&t.isType("textbox")?(n.text=s.content||" ",n.fontSize=s.fontSize||22,n.fill=s.color||"#000000",n.textAlign=s.textAlign||"left",n.fontWeight=s.isBold?"bold":"normal",n.fontStyle=s.isItalic?"italic":"normal",n.fontFamily=s.fontFamily||"Arial",n.width=Math.max(s.width||50,10)):s.type==="shape"?(n.fill=s.fill||"#cccccc",n.scaleX=(s.width||50)/(t.width||1),n.scaleY=(s.height||50)/(t.height||1)):s.type==="image"&&(n.scaleX=(s.width||100)/(t.width||1),n.scaleY=(s.height||100)/(t.height||1)),t.set(n)}else{let n=null,u={left:s.x,top:s.y,data:{id:s.id},originX:"left",originY:"top",opacity:s.opacity!==void 0?s.opacity:1};if(s.type==="text")n=new j.Textbox(s.content||" ",I(w({},u),{width:Math.max(s.width||200,10),fontSize:s.fontSize||22,fill:s.color||"#000000",fontFamily:s.fontFamily||"Inter, Arial, sans-serif",textAlign:s.textAlign||"left",fontWeight:s.isBold?"bold":"normal",fontStyle:s.isItalic?"italic":"normal",splitByGrapheme:!1}));else if(s.type==="shape"){let S=s.fill||"#3b82f6";s.shapeType==="ellipse"?n=new j.Circle(I(w({},u),{radius:(s.width||100)/2,scaleY:(s.height||100)/(s.width||100),fill:S})):n=new j.Rect(I(w({},u),{width:s.width||100,height:s.height||100,fill:S}))}else if(s.type==="image")try{let S=await j.FabricImage.fromURL(s.src);S.set(I(w({},u),{scaleX:(s.width||100)/(S.width||1),scaleY:(s.height||100)/(S.height||1)})),n=S}catch(S){console.error(S)}n&&f.add(n)}}f.renderAll(),p.current=!1})()},[m]),(0,me.jsx)("div",{className:"border border-slate-200 rounded-xl overflow-hidden bg-white",children:(0,me.jsx)("canvas",{ref:c})})};var Ie=pe(require("pptxgenjs"));var oe=class{async export(o){var i,y;let l=new Ie.default,c=((i=o.layout)==null?void 0:i.width)||12192e3,g=((y=o.layout)==null?void 0:y.height)||6858e3,p=1200,N=675,v=a=>a/p*(c/914400),f=a=>a/N*(g/914400);o.slides.forEach(a=>{let b=l.addSlide();[...a.elements].sort((t,n)=>t.zIndex-n.zIndex).forEach(t=>{var S,L;let n=t.opacity!==void 0?(1-t.opacity)*100:0,u={x:v(t.x),y:f(t.y),w:v(t.width),h:f(t.height)};if(t.type==="text")b.addText(t.content,I(w({},u),{fontSize:(t.fontSize||18)/2,color:((S=t.color)==null?void 0:S.replace("#",""))||"000000",fontFace:t.fontFamily||"Arial"}));else if(t.type==="image")b.addImage(I(w({},u),{path:t.src,transparency:n}));else if(t.type==="shape"){let U=t.shapeType==="ellipse"?l.ShapeType.ellipse:l.ShapeType.rect;b.addShape(U,I(w({},u),{fill:{color:((L=t.fill)==null?void 0:L.replace("#",""))||"CCCCCC",transparency:n>0?Math.min(n+10,100):0}}))}})}),await l.writeFile({fileName:"presentation.pptx"})}};var Ce=pe(require("jszip")),le=class{constructor(){this.slideWidth=12192e3;this.slideHeight=6858e3;this.CANVAS_WIDTH=1200;this.CANVAS_HEIGHT=675}async parse(o){var y,a;let l=o;if(typeof o=="string"){let b=await fetch(o);if(!b.ok){let s=b.status,t=b.statusText,n="";try{let u=await b.json();n=u.details||u.error||""}catch(u){}throw new Error(`Failed to fetch PPTX from ${o}: ${s} ${t} ${n?`(${n})`:""}`)}l=await b.arrayBuffer()}let c=await Ce.default.loadAsync(l),g=await((y=c.file("ppt/presentation.xml"))==null?void 0:y.async("string"));if(!g)throw new Error("Invalid PPTX");let N=new DOMParser().parseFromString(g,"text/xml"),v=this.findFirstByLocalName(N,"sldSz");v&&(this.slideWidth=parseInt(this.getAttr(v,"cx")||"12192000"),this.slideHeight=parseInt(this.getAttr(v,"cy")||"6858000"));let f=Array.from(N.getElementsByTagNameNS("*","sldId")),i=[];for(let b=0;b<f.length;b++){let s=b+1,t=`ppt/slides/slide${s}.xml`,n=await((a=c.file(t))==null?void 0:a.async("string"));if(n){let u=await this.parseSlide(n,s,c);i.push(u)}}return{slides:i,layout:{width:this.slideWidth,height:this.slideHeight}}}getAttr(o,l){return o.getAttribute(l)||o.getAttribute(`a:${l}`)||o.getAttribute(`p:${l}`)||o.getAttribute(`r:${l}`)}findFirstByLocalName(o,l){let c=o.getElementsByTagNameNS("*",l);return c.length>0?c[0]:null}findAllByLocalName(o,l){return Array.from(o.getElementsByTagNameNS("*",l))}scaleX(o){return o/this.slideWidth*this.CANVAS_WIDTH}scaleY(o){return o/this.slideHeight*this.CANVAS_HEIGHT}parseColor(o){let l=this.findFirstByLocalName(o,"srgbClr");if(l){let g=`#${this.getAttr(l,"val")}`,p=this.findFirstByLocalName(l,"alpha"),N=p?parseInt(this.getAttr(p,"val")||"100000")/1e5:1;return{color:g,opacity:N}}let c=this.findFirstByLocalName(o,"schemeClr");if(c){let g=this.findFirstByLocalName(c,"alpha");return{color:"#000000",opacity:g?parseInt(this.getAttr(g,"val")||"100000")/1e5:1}}return{color:"#000000",opacity:1}}async resolveImage(o,l,c){var i,y;let g=await((i=c.file(`ppt/slides/_rels/slide${l}.xml.rels`))==null?void 0:i.async("string"));if(!g)return null;let N=new DOMParser().parseFromString(g,"text/xml"),v=Array.from(N.getElementsByTagName("Relationship")).find(a=>a.getAttribute("Id")===o),f=v==null?void 0:v.getAttribute("Target");if(f){let a=(f.startsWith("../")?`ppt/${f.substring(3)}`:`ppt/slides/${f}`).replace("ppt/slides/../","ppt/");return await((y=c.file(a))==null?void 0:y.async("blob"))||null}return null}async parseSlide(o,l,c){let p=new DOMParser().parseFromString(o,"text/xml"),N=[],v=0,f=this.findFirstByLocalName(p,"bg");if(f){let a=this.findFirstByLocalName(f,"blip"),b=(a==null?void 0:a.getAttributeNS("http://schemas.openxmlformats.org/officeDocument/2006/relationships","embed"))||(a==null?void 0:a.getAttribute("r:embed"));if(b){let s=await this.resolveImage(b,l,c);s&&N.push({id:`bg-${l}`,type:"image",src:URL.createObjectURL(s),x:0,y:0,width:this.CANVAS_WIDTH,height:this.CANVAS_HEIGHT,zIndex:v++,opacity:1})}}let i=this.findFirstByLocalName(p,"spTree");if(!i)return{id:`slide-${l}`,elements:N};let y=Array.from(i.children);for(let a of y){let b=a.localName;if(b==="sp"){let s=this.findFirstByLocalName(a,"txBody"),t=this.findFirstByLocalName(a,"xfrm"),n=t?this.findFirstByLocalName(t,"off"):null,u=t?this.findFirstByLocalName(t,"ext"):null;if(s&&n&&u){let L=this.findAllByLocalName(s,"p"),U="",O=18,X="#000000",W=1,G=!1;for(let Y of L){let P=this.findFirstByLocalName(Y,"pPr"),ie=P?this.findFirstByLocalName(P,"buNone"):null;P&&!ie&&(this.findFirstByLocalName(P,"buChar")||this.findFirstByLocalName(P,"buAutoNum"))&&(G=!0,U+="\u2022 ");let F=this.findAllByLocalName(Y,"r");for(let _ of F){let K=this.findFirstByLocalName(_,"t");K&&(U+=K.textContent);let B=this.findFirstByLocalName(_,"rPr");if(B){let q=this.getAttr(B,"sz");q&&(O=parseInt(q)/100*2);let T=this.parseColor(B);X=T.color,W=T.opacity}}U+=`
|
|
3
|
+
`}if(U.trim()){N.push({id:`el-${l}-${Date.now()}-${v}`,type:"text",content:U.trim(),x:this.scaleX(parseInt(this.getAttr(n,"x")||"0")),y:this.scaleY(parseInt(this.getAttr(n,"y")||"0")),width:this.scaleX(parseInt(this.getAttr(u,"cx")||"0")),height:this.scaleY(parseInt(this.getAttr(u,"cy")||"0")),fontSize:O,color:X,fontFamily:"Arial",zIndex:v++,isBulleted:G,opacity:W});continue}}let S=this.findFirstByLocalName(a,"prstGeom");if(S&&n&&u){let L=this.getAttr(S,"prst"),U=this.findFirstByLocalName(a,"spPr"),O=U?this.parseColor(U):{color:"#cccccc",opacity:1};N.push({id:`el-${l}-${Date.now()}-${v}`,type:"shape",shapeType:L==="ellipse"||L==="circle"?"ellipse":"rect",fill:O.color,opacity:O.opacity,x:this.scaleX(parseInt(this.getAttr(n,"x")||"0")),y:this.scaleY(parseInt(this.getAttr(n,"y")||"0")),width:this.scaleX(parseInt(this.getAttr(u,"cx")||"0")),height:this.scaleY(parseInt(this.getAttr(u,"cy")||"0")),zIndex:v++})}}if(b==="pic"){let s=this.findFirstByLocalName(a,"blip"),t=(s==null?void 0:s.getAttributeNS("http://schemas.openxmlformats.org/officeDocument/2006/relationships","embed"))||(s==null?void 0:s.getAttribute("r:embed")),n=this.findFirstByLocalName(a,"xfrm"),u=n?this.findFirstByLocalName(n,"off"):null,S=n?this.findFirstByLocalName(n,"ext"):null;if(t&&u&&S){let L=await this.resolveImage(t,l,c);L&&N.push({id:`el-${l}-${Date.now()}-${v}`,type:"image",src:URL.createObjectURL(L),x:this.scaleX(parseInt(this.getAttr(u,"x")||"0")),y:this.scaleY(parseInt(this.getAttr(u,"y")||"0")),width:this.scaleX(parseInt(this.getAttr(S,"cx")||"0")),height:this.scaleY(parseInt(this.getAttr(S,"cy")||"0")),zIndex:v++,opacity:1})}}}return{id:`slide-${l}`,elements:N}}};var te=require("react"),se=require("lucide-react");var D=require("react/jsx-runtime"),Pe=({presentation:m,initialSlideIndex:o,onClose:l})=>{let[c,g]=(0,te.useState)(o),p=m.slides[c],N=()=>{c>0&&g(c-1)},v=()=>{c<m.slides.length-1&&g(c+1)};(0,te.useEffect)(()=>{let y=a=>{a.key==="ArrowRight"||a.key===" "||a.key==="PageDown"?v():a.key==="ArrowLeft"||a.key==="Backspace"||a.key==="PageUp"?N():a.key==="Escape"&&l()};return window.addEventListener("keydown",y),()=>window.removeEventListener("keydown",y)},[c]);let[f,i]=(0,te.useState)(1);return(0,te.useEffect)(()=>{let y=()=>{let b=window.innerWidth-40,s=window.innerHeight-40,t=1200,n=675,u=b/t,S=s/n,L=Math.min(u,S);i(L)};return y(),window.addEventListener("resize",y),()=>window.removeEventListener("resize",y)},[]),(0,D.jsxs)("div",{className:"fixed inset-0 z-[99999] bg-[#0A0A0A] flex flex-col items-center justify-center overflow-hidden",children:[(0,D.jsxs)("div",{className:"absolute top-0 left-0 right-0 p-6 flex justify-between items-center opacity-0 hover:opacity-100 transition-opacity bg-gradient-to-b from-black/60 to-transparent z-[100] pointer-events-none",children:[(0,D.jsxs)("div",{className:"text-white/80 font-bold ml-4 pointer-events-auto",children:["Slide ",c+1," of ",m.slides.length]}),(0,D.jsx)("button",{onClick:l,className:"p-3 bg-white/10 hover:bg-white/20 text-white rounded-full transition-all pointer-events-auto",children:(0,D.jsx)(se.X,{size:24})})]}),(0,D.jsx)("div",{className:"w-full h-full flex items-center justify-center",children:(0,D.jsx)("div",{className:"relative shadow-2xl shadow-black/80 bg-white",style:{width:"1200px",height:"675px",transform:`scale(${f})`,transformOrigin:"center center"},children:(0,D.jsx)(fe,{slide:p,onElementUpdate:()=>{},onSelect:()=>{}})})}),(0,D.jsxs)("div",{className:"absolute bottom-10 left-1/2 -translate-x-1/2 flex items-center gap-6 opacity-0 hover:opacity-100 transition-opacity bg-black/40 backdrop-blur-md px-6 py-3 rounded-full border border-white/10 pointer-events-auto",children:[(0,D.jsx)("button",{disabled:c===0,onClick:N,className:"p-2 text-white/50 hover:text-white disabled:opacity-20 transition-colors",children:(0,D.jsx)(se.ChevronLeft,{size:32})}),(0,D.jsx)("div",{className:"h-6 w-[1px] bg-white/10"}),(0,D.jsx)("button",{disabled:c===m.slides.length-1,onClick:v,className:"p-2 text-white/50 hover:text-white disabled:opacity-20 transition-colors",children:(0,D.jsx)(se.ChevronRight,{size:32})})]})]})};var ze=require("@google/generative-ai");var V=require("react/jsx-runtime"),et=({initialPresentation:m,url:o,appName:l="SlideCanvas",onChange:c,geminiApiKey:g})=>{let[p,N]=(0,z.useState)(m||{slides:[{id:"slide-1",elements:[]}],layout:{width:12192e3,height:6858e3}}),[v,f]=(0,z.useState)([]),[i,y]=(0,z.useState)([]),[a,b]=(0,z.useState)(0),[s,t]=(0,z.useState)(null),[n,u]=(0,z.useState)(!1),[S,L]=(0,z.useState)(null),[U,O]=(0,z.useState)(!1);(0,z.useEffect)(()=>{o&&xe(o)},[o]);let[X,W]=(0,z.useState)(!1),[G,Y]=(0,z.useState)(null),P=p.slides[a],ie=(0,z.useMemo)(()=>P.elements.find(r=>r.id===s)||null,[P,s]),F=(0,z.useCallback)(r=>{f(d=>[...d.slice(-19),p]),y([]),N(r),c==null||c(r)},[c,p]),_=()=>{if(v.length===0)return;let r=v[v.length-1];y(d=>[...d,p]),f(d=>d.slice(0,-1)),N(r)},K=()=>{if(i.length===0)return;let r=i[i.length-1];f(d=>[...d,p]),y(d=>d.slice(0,-1)),N(r)},B=(0,z.useCallback)(r=>{N(d=>{let h=[...d.slides];h[a]=w(w({},h[a]),r);let k=I(w({},d),{slides:h});return f(R=>[...R.slice(-19),d]),y([]),c==null||c(k),k})},[a,c]),q=(0,z.useCallback)((r,d)=>{N(h=>{let k=h.slides[a],R=k.elements.map(ae=>ae.id===r?w(w({},ae),d):ae),J=[...h.slides];J[a]=I(w({},k),{elements:R});let ce=I(w({},h),{slides:J});return c==null||c(ce),ce})},[a,c]),T=r=>{if(!s)return;if(P.elements.find(h=>h.id===s)){q(s,r);let h=p.slides[a],k=h.elements.map(J=>J.id===s?w(w({},J),r):J),R=[...p.slides];R[a]=I(w({},h),{elements:k}),F(I(w({},p),{slides:R}))}},re=(0,z.useCallback)(()=>{if(!s)return;let d=p.slides[a].elements.filter(h=>h.id!==s);B({elements:d}),t(null)},[s,a,p,B]),ue=()=>{let r={id:`text-${Date.now()}`,type:"text",content:"New Text",x:100,y:100,width:400,height:100,fontSize:48,fontFamily:"Arial",color:"#000000",zIndex:P.elements.length};B({elements:[...P.elements,r]})},A=r=>{let d=URL.createObjectURL(r),h=`img-${Date.now()}`,k={id:h,type:"image",src:d,x:100,y:100,width:400,height:250,zIndex:P.elements.length};B({elements:[...P.elements,k]}),t(h)},Q=r=>{let d={id:`shape-${Date.now()}`,type:"shape",shapeType:r,fill:"#3b82f6",x:200,y:200,width:200,height:200,zIndex:P.elements.length};B({elements:[...P.elements,d]})},de=()=>{let r={id:`slide-${Date.now()}`,elements:[]};F(I(w({},p),{slides:[...p.slides,r]})),b(p.slides.length)},Le=r=>{if(p.slides.length<=1)return;let d=p.slides.filter((h,k)=>k!==r);F(I(w({},p),{slides:d})),r<=a&&b(Math.max(0,a-1))},Te=r=>{let d=p.slides[r],h=I(w({},d),{id:`slide-${Date.now()}`,elements:d.elements.map(R=>I(w({},R),{id:`${R.type}-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}))}),k=[...p.slides];k.splice(r+1,0,h),F(I(w({},p),{slides:k})),b(r+1)},Be=(r,d)=>{if(r===d)return;let h=[...p.slides],[k]=h.splice(r,1);h.splice(d,0,k),F(I(w({},p),{slides:h})),a===r?b(d):a>r&&a<=d?b(a-1):a<r&&a>=d&&b(a+1)},De=r=>{let d=[],h=Date.now();r==="title"?d=[{id:`text-title-${h}`,type:"text",content:"Presentation Title",x:100,y:200,width:1e3,height:150,fontSize:80,fontFamily:"Inter",color:"#000000",textAlign:"center",isBold:!0,zIndex:0},{id:`text-sub-${h}`,type:"text",content:"Subtitle goes here",x:200,y:380,width:800,height:80,fontSize:36,fontFamily:"Inter",color:"#64748b",textAlign:"center",zIndex:1}]:r==="content"?d=[{id:`text-title-${h}`,type:"text",content:"Slide Title",x:60,y:40,width:800,height:80,fontSize:48,fontFamily:"Inter",color:"#000000",isBold:!0,zIndex:0},{id:`text-body-${h}`,type:"text",content:`\u2022 Add your points here
|
|
4
|
+
\u2022 Press Enter for new line
|
|
5
|
+
\u2022 Use the toolbar to format`,x:60,y:150,width:1080,height:480,fontSize:28,fontFamily:"Inter",color:"#334155",zIndex:1,isBulleted:!0}]:r==="split"&&(d=[{id:`text-title-${h}`,type:"text",content:"Comparison Layout",x:60,y:40,width:1080,height:80,fontSize:48,fontFamily:"Inter",color:"#000000",isBold:!0,textAlign:"center",zIndex:0},{id:`text-left-${h}`,type:"text",content:"Left column content goes here.",x:60,y:180,width:520,height:400,fontSize:24,fontFamily:"Inter",color:"#334155",zIndex:1},{id:`text-right-${h}`,type:"text",content:"Right column content goes here.",x:620,y:180,width:520,height:400,fontSize:24,fontFamily:"Inter",color:"#334155",zIndex:2}]),B({elements:d})},he=async(r,d)=>{let k=p.slides[a].elements.find(R=>R.id===r);if(!(!k||k.type!=="text")){W(!0),L(null),Y({id:r,action:d});try{if(!g){L("Gemini API key is missing. Please provide it via the 'geminiApiKey' prop."),W(!1);return}let J=new ze.GoogleGenerativeAI(g).getGenerativeModel({model:"gemini-flash-latest",systemInstruction:`You are a professional presentation assistant. Your task is to transform slide text according to specific user requests (shorten, reframe, or lengthen).
|
|
6
|
+
|
|
7
|
+
CRITICAL RULES:
|
|
8
|
+
1. Return ONLY the transformed text.
|
|
9
|
+
2. Do NOT include any explanations, choices, or conversational fillers.
|
|
10
|
+
3. Do NOT use markdown formatting (like bolding or headers) unless specifically needed for bullet points.
|
|
11
|
+
4. If the input text is a title/headline, the output should be a professional title/headline.
|
|
12
|
+
5. If the input text is a bulleted list, the output MUST be a bulleted list using the same bullet style (e.g., '\u2022').
|
|
13
|
+
6. Maintain the professional tone of the original presentation.`}),ce=k.fontSize>32?"Title/Headline":"Body Text/List",ae=`Action: ${d.toUpperCase()}
|
|
14
|
+
Text Role: ${ce}
|
|
15
|
+
Original Text: "${k.content}"
|
|
16
|
+
|
|
17
|
+
Transformed Text:`,Me=await(await J.generateContent(ae)).response;L(Me.text().trim())}catch(R){console.error("Gemini AI Error:",R),L("Error generating response. Please check your API key or connection.")}finally{W(!1)}}},Fe=r=>{if(!S||!G)return;if(r==="regenerate"){he(G.id,G.action);return}let d=p.slides[a],h=d.elements.find(k=>k.id===G.id);if(!(!h||h.type!=="text")){if(r==="replace")q(G.id,{content:S});else if(r==="addBelow"){let k=I(w({},h),{id:`text-ai-${Date.now()}`,content:S,y:h.y+h.height+20,zIndex:d.elements.length});B({elements:[...d.elements,k]})}L(null),Y(null)}},Re=async()=>{await new oe().export(p)},Ee=()=>{u(!0);let r=document.documentElement;r.requestFullscreen&&r.requestFullscreen()},$e=()=>{u(!1),document.fullscreenElement&&document.exitFullscreen()};(0,z.useEffect)(()=>{let r=()=>{document.fullscreenElement||u(!1)};return document.addEventListener("fullscreenchange",r),()=>document.removeEventListener("fullscreenchange",r)},[]),(0,z.useEffect)(()=>{let r=d=>{if(d.key==="Delete"||d.key==="Backspace"){let h=document.activeElement;if((h==null?void 0:h.tagName)==="INPUT"||(h==null?void 0:h.tagName)==="TEXTAREA"||h!=null&&h.isContentEditable)return;re()}(d.ctrlKey||d.metaKey)&&(d.key==="z"&&(d.preventDefault(),d.shiftKey?K():_()),d.key==="y"&&(d.preventDefault(),K()))};return window.addEventListener("keydown",r),()=>window.removeEventListener("keydown",r)},[re,_,K]);let Ue=()=>{F({slides:[{id:`slide-${Date.now()}`,elements:[]}],layout:{width:12192e3,height:6858e3}}),b(0),t(null)},xe=async r=>{W(!0);try{let d=new le,h=r;typeof r=="string"&&(h=`/api/proxy?url=${encodeURIComponent(r.trim())}`);let k=await d.parse(h);N(k),f([]),y([]),b(0),t(null)}catch(d){console.error("Failed to load PPTX",d),alert("Failed to load presentation. Please ensure it is a valid .pptx.")}finally{W(!1)}};return(0,V.jsxs)("div",{className:"flex flex-col h-screen bg-white overflow-hidden",children:[n&&(0,V.jsx)(Pe,{presentation:p,initialSlideIndex:a,onClose:$e}),(0,V.jsx)(Se,{onAddText:ue,onAddImage:A,onAddShape:Q,onAddSlide:de,onExport:Re,onFormatText:T,onDeleteElement:re,onApplyLayout:De,onPlay:Ee,onAiAction:he,onAiResponseAction:Fe,onNewPresentation:Ue,onLoadPresentation:xe,aiResponse:S,isAiLoading:X,selectedElement:ie,appName:l}),(0,V.jsxs)("div",{className:"flex flex-1 overflow-hidden",children:[(0,V.jsx)(ke,{slides:p.slides,currentSlideIndex:a,onSelectSlide:b,onDeleteSlide:Le,onDuplicateSlide:Te,onReorderSlides:Be}),(0,V.jsx)("div",{className:"flex-1 flex items-center justify-center p-12 overflow-auto bg-white",children:(0,V.jsx)(fe,{slide:P,onElementUpdate:q,onSelect:t})})]})]})};0&&(module.exports={PptEditor,PptxExporter,PptxParser});
|
|
18
|
+
//# sourceMappingURL=index.js.map
|