@algorisys/yappydraw 0.8.253
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/LICENSE +661 -0
- package/README.md +45 -0
- package/chunks/AllPackages-DNX4gUvL.js +6879 -0
- package/chunks/BaseConfiguration-iE_YypNt.js +4401 -0
- package/chunks/Entities-XwxJEcR3.js +467 -0
- package/chunks/Factory--zguTNZ7.js +2768 -0
- package/chunks/InputJax-BYq2tqUz.js +42 -0
- package/chunks/MathItem-DD5NNBjZ.js +76 -0
- package/chunks/Options-BStFr0zv.js +199 -0
- package/chunks/PrioritizedList-TjDg4i-s.js +39 -0
- package/chunks/Styles-DdTYCumM.js +397 -0
- package/chunks/TeXAtom-Bp5xoo7F.js +2175 -0
- package/chunks/ai-providers-CycU8sO1.js +229 -0
- package/chunks/canva-ai-BREIRXSl.js +285 -0
- package/chunks/design-generator-C89SKTqv.js +149 -0
- package/chunks/drawing-engine-DLFI-cNg.js +903 -0
- package/chunks/drawings-store-C-PoHakg.js +109 -0
- package/chunks/ds-operations-D5B9Z5vO.js +253 -0
- package/chunks/export-game-DOlM1w0F.js +104 -0
- package/chunks/game-runtime-Hn9umSvi.js +346 -0
- package/chunks/gifenc.esm-48qFK9lH.js +278 -0
- package/chunks/html-DxnOvKy4.js +1694 -0
- package/chunks/image-utils-CJQBaGoQ.js +37 -0
- package/chunks/index-Bm3Inzn8.js +62744 -0
- package/chunks/lengths-DNFHULBn.js +70 -0
- package/chunks/liteAdaptor-BZby1Qz2.js +919 -0
- package/chunks/lucide-solid-D_6t_rbY.js +35452 -0
- package/chunks/markdown-to-slides-_1GIcD8M.js +96 -0
- package/chunks/mathjax-CnUrFnFS.js +117 -0
- package/chunks/mathjax-D6cR72fZ.js +26 -0
- package/chunks/morph-animator-7qX2s9j_.js +25 -0
- package/chunks/onboarding-tour-CthiVc3W.js +192 -0
- package/chunks/rocket-settings-CU8w9S9I.js +100 -0
- package/chunks/search-CnWoMV6A.js +384 -0
- package/chunks/slide-generator-BG0Oacui.js +553 -0
- package/chunks/svg-BvVc02XL.js +12498 -0
- package/chunks/tex-Cfi4Kfun.js +442 -0
- package/chunks/tinyfly-engine-Wfa50sVI.js +1804 -0
- package/chunks/turntable-ai-Bfq-oSsD.js +120 -0
- package/chunks/yappy-NspTXSPk.css +1 -0
- package/package.json +21 -0
- package/yappy.d.ts +34 -0
- package/yappy.js +9 -0
|
@@ -0,0 +1,553 @@
|
|
|
1
|
+
import { h as T, b as C, c as k } from "./ai-providers-CycU8sO1.js";
|
|
2
|
+
import { a1 as A, a2 as N, a3 as v, a4 as x, G as L } from "./index-Bm3Inzn8.js";
|
|
3
|
+
const R = `You are a presentation design assistant. Given a topic or description, generate a structured JSON slide deck.
|
|
4
|
+
|
|
5
|
+
## Output Format
|
|
6
|
+
Return ONLY a JSON object (no markdown fences, no explanation) with this exact schema:
|
|
7
|
+
|
|
8
|
+
{
|
|
9
|
+
"title": "Deck Title",
|
|
10
|
+
"colorPalette": "corporate" | "forest" | "royal" | "sunset" | "dark" | "minimalist",
|
|
11
|
+
"slides": [
|
|
12
|
+
{
|
|
13
|
+
"slideType": "title" | "content" | "two-column" | "bullets" | "quote" | "section-break" | "closing" | "image-text" | "metrics" | "timeline" | "card-grid" | "comparison",
|
|
14
|
+
"title": "Slide Title",
|
|
15
|
+
"subtitle": "Optional subtitle (title/closing/section-break only)",
|
|
16
|
+
"bullets": ["Bullet 1", "Bullet 2"],
|
|
17
|
+
"body": "Longer paragraph text",
|
|
18
|
+
"quote": { "text": "Quote text", "attribution": "Speaker Name" },
|
|
19
|
+
"leftColumn": ["Left item 1", "Left item 2"],
|
|
20
|
+
"rightColumn": ["Right item 1", "Right item 2"],
|
|
21
|
+
"metrics": [{ "value": "95%", "label": "Customer Satisfaction" }],
|
|
22
|
+
"timelineItems": [{ "year": "2023", "text": "Company founded" }],
|
|
23
|
+
"cards": [{ "title": "Feature", "body": "Description", "icon": "gear" }],
|
|
24
|
+
"comparisonLeft": { "title": "Before", "items": ["Item 1", "Item 2"] },
|
|
25
|
+
"comparisonRight": { "title": "After", "items": ["Item 1", "Item 2"] },
|
|
26
|
+
"backgroundColor": "#hex (optional, overrides palette)"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
## Slide Types
|
|
32
|
+
|
|
33
|
+
### Basic Types
|
|
34
|
+
- **title**: Opening slide with large centered title + optional subtitle
|
|
35
|
+
- **content/bullets**: Title + bullet list or body paragraph
|
|
36
|
+
- **two-column**: Title + two side-by-side lists (for leftColumn/rightColumn)
|
|
37
|
+
- **quote**: Centered quote with optional attribution
|
|
38
|
+
- **section-break**: Bold section divider with gradient background
|
|
39
|
+
- **closing**: Final slide with title + optional CTA/contact subtitle
|
|
40
|
+
- **image-text**: Split layout with text on left, visual placeholder on right
|
|
41
|
+
|
|
42
|
+
### Rich Types (use these for visual impact)
|
|
43
|
+
- **metrics**: 3-4 large KPI cards in a row. Provide "metrics" array: [{ "value": "2.5M", "label": "Active Users" }]. Great for stats, KPIs, revenue figures, growth numbers.
|
|
44
|
+
- **timeline**: Horizontal timeline with milestone dots. Provide "timelineItems" array: [{ "year": "Q1 2024", "text": "Beta launch" }]. Great for roadmaps, history, milestones (max 6 items).
|
|
45
|
+
- **card-grid**: 2-6 cards in a grid with optional icons. Provide "cards" array: [{ "title": "Card Title", "body": "Description", "icon": "gear" }]. Available icons: gear, target, lightbulb, trophy, rocket, flag, star, heart, shield, key, book, eye, clock, check, chart, user. Great for features, services, team, benefits.
|
|
46
|
+
- **comparison**: Two side-by-side comparison panels with headers. Provide "comparisonLeft" and "comparisonRight": { "title": "Plan A", "items": ["Feature 1", "Feature 2"] }. Great for before/after, pros/cons, plan tiers.
|
|
47
|
+
|
|
48
|
+
## Color Palettes
|
|
49
|
+
- corporate: Professional blue (#3498db primary, white background)
|
|
50
|
+
- forest: Nature green (#27ae60 primary, light gray background)
|
|
51
|
+
- royal: Rich purple (#8b5cf6 primary, light purple background)
|
|
52
|
+
- sunset: Warm orange (#f97316 primary, warm white background)
|
|
53
|
+
- dark: Dark theme (#60a5fa primary, dark background, light text)
|
|
54
|
+
- minimalist: Clean slate (#334155 primary, white background)
|
|
55
|
+
|
|
56
|
+
## Rules
|
|
57
|
+
1. Generate the number of slides requested by the user. If no count is specified, default to 6–12 slides based on content complexity. For large decks (20+ slides), organize content into clear sections with section-break slides between them.
|
|
58
|
+
2. Always start with a "title" slide and end with a "closing" slide.
|
|
59
|
+
3. Use at least 3 different slide types per deck for visual variety.
|
|
60
|
+
4. Keep bullet points concise (max 8 words each, max 6 bullets per slide).
|
|
61
|
+
5. Use "section-break" slides to separate major sections (2–3 per deck).
|
|
62
|
+
6. Use "metrics" for KPIs, statistics, revenue, or data highlights.
|
|
63
|
+
7. Use "timeline" for roadmaps, history, company milestones, or project phases.
|
|
64
|
+
8. Use "card-grid" for features, services, team members, or benefits.
|
|
65
|
+
9. Use "comparison" for before/after, pros/cons, or plan tier comparisons.
|
|
66
|
+
10. Use "two-column" for comparing two concepts or parallel lists.
|
|
67
|
+
11. Use "quote" for impactful statements or key takeaways.
|
|
68
|
+
12. Content should be specific and substantive, not generic placeholder text.
|
|
69
|
+
13. Match the color palette to the topic tone (e.g., "dark" for tech, "corporate" for business).
|
|
70
|
+
14. Each slide's title should be short (max 5 words).
|
|
71
|
+
15. For section-break slides, use the palette's secondary color as backgroundColor.
|
|
72
|
+
16. Include at least one "metrics" or "card-grid" slide per deck for visual richness.
|
|
73
|
+
17. **Product expansion**: When multiple products or services are mentioned, give each product its own section-break + dedicated slides. Each product should get at least one "card-grid" slide showing its core features (with icons) and one additional slide (metrics, content, or comparison). Don't collapse multiple products into a single bullet list.
|
|
74
|
+
18. If URLs or websites are mentioned, use your knowledge to extract real product details, features, and capabilities — not generic descriptions.
|
|
75
|
+
`;
|
|
76
|
+
function q(t, e) {
|
|
77
|
+
let i = t;
|
|
78
|
+
return e?.style && e.style !== "auto" && (i += `
|
|
79
|
+
|
|
80
|
+
Use the "${e.style}" color palette.`), e?.slideCount && (i += `
|
|
81
|
+
|
|
82
|
+
Generate exactly ${e.slideCount} slides.`), i;
|
|
83
|
+
}
|
|
84
|
+
const E = `You are a presentation content strategist. Given a topic, research it thoroughly and produce structured slide content with a compelling narrative arc.
|
|
85
|
+
|
|
86
|
+
## Your Role
|
|
87
|
+
You focus ONLY on **content quality** — what to say, not how to show it. A separate visual designer will handle layout and styling.
|
|
88
|
+
|
|
89
|
+
## Output Format
|
|
90
|
+
Return ONLY a JSON object (no markdown fences, no explanation) with this schema:
|
|
91
|
+
|
|
92
|
+
{
|
|
93
|
+
"title": "Deck Title",
|
|
94
|
+
"toneSuggestion": "professional" | "energetic" | "technical" | "creative" | "minimal",
|
|
95
|
+
"sections": [
|
|
96
|
+
{
|
|
97
|
+
"sectionTitle": "Section Name",
|
|
98
|
+
"slides": [
|
|
99
|
+
{
|
|
100
|
+
"intent": "title" | "stats" | "points" | "story" | "comparison" | "features" | "roadmap" | "quote" | "overview" | "closing",
|
|
101
|
+
"title": "Short Slide Title",
|
|
102
|
+
"content": { ... see content fields below }
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
## Intent Types and Content Fields
|
|
110
|
+
|
|
111
|
+
Each slide has an "intent" describing its communication purpose. Include the matching content fields:
|
|
112
|
+
|
|
113
|
+
### "title"
|
|
114
|
+
Opening slide. Content: { "subtitle": "Tagline or description" }
|
|
115
|
+
|
|
116
|
+
### "stats"
|
|
117
|
+
Data-driven slide with key metrics. Content: { "metrics": [{ "value": "95%", "label": "Customer Satisfaction" }] }
|
|
118
|
+
- Include 3-4 metrics with specific, real/plausible numbers
|
|
119
|
+
- Add context in labels (e.g. "+18% YoY", "vs 72% industry avg")
|
|
120
|
+
|
|
121
|
+
### "points"
|
|
122
|
+
Key talking points or arguments. Content: { "bullets": ["Point 1", "Point 2", ...] }
|
|
123
|
+
- Max 6 bullets, each max 10 words
|
|
124
|
+
- Alternatively use "body" for a paragraph: { "body": "Longer text..." }
|
|
125
|
+
|
|
126
|
+
### "story"
|
|
127
|
+
Narrative or explanatory content. Content: { "body": "Paragraph text explaining a concept or telling a story" }
|
|
128
|
+
|
|
129
|
+
### "comparison"
|
|
130
|
+
Side-by-side comparison. Content: { "leftTitle": "Before", "rightTitle": "After", "leftItems": ["Item 1"], "rightItems": ["Item 1"] }
|
|
131
|
+
- Good for before/after, pros/cons, two plans, two approaches
|
|
132
|
+
|
|
133
|
+
### "features"
|
|
134
|
+
Feature showcase with descriptions. Content: { "cards": [{ "title": "Feature Name", "body": "One-line description", "icon": "gear" }] }
|
|
135
|
+
- 2-6 cards per slide
|
|
136
|
+
- Available icons: gear, target, lightbulb, trophy, rocket, flag, star, heart, shield, key, book, eye, clock, check, chart, user
|
|
137
|
+
|
|
138
|
+
### "roadmap"
|
|
139
|
+
Timeline of milestones or phases. Content: { "timelineItems": [{ "year": "Q1 2025", "text": "Milestone description" }] }
|
|
140
|
+
- Max 6 items chronologically ordered
|
|
141
|
+
|
|
142
|
+
### "quote"
|
|
143
|
+
Impactful quote or key takeaway. Content: { "text": "The quote text", "attribution": "Speaker Name, Title" }
|
|
144
|
+
|
|
145
|
+
### "overview"
|
|
146
|
+
Two-column layout for parallel information. Content: { "leftColumn": ["Item 1", "Item 2"], "rightColumn": ["Item 1", "Item 2"] }
|
|
147
|
+
|
|
148
|
+
### "closing"
|
|
149
|
+
Final slide. Content: { "subtitle": "Call to action or closing message" }
|
|
150
|
+
|
|
151
|
+
## Rules
|
|
152
|
+
1. Generate the number of slides requested. If no count specified, default to 6-12 based on topic complexity. For 20+ slides, organize into 3-5 clear sections.
|
|
153
|
+
2. Always start with a "title" slide and end with a "closing" slide.
|
|
154
|
+
3. Group slides into logical sections (e.g. "Problem", "Solution", "Evidence", "Next Steps").
|
|
155
|
+
4. Write **specific, substantive content** — not generic placeholder text. Include real or plausible:
|
|
156
|
+
- Statistics and metrics with sources or context
|
|
157
|
+
- Named examples, companies, technologies
|
|
158
|
+
- Specific dates, quarters, years
|
|
159
|
+
- Dollar amounts, percentages, growth rates
|
|
160
|
+
5. Use at least 3 different intent types per deck for variety.
|
|
161
|
+
6. Every deck should include at least one "stats" or "features" slide for data richness.
|
|
162
|
+
7. Use "comparison" when contrasting two things (before/after, options A vs B).
|
|
163
|
+
8. Use "roadmap" for any chronological progression (history, milestones, project phases).
|
|
164
|
+
9. Keep slide titles short (max 5 words).
|
|
165
|
+
10. Build a narrative arc: hook → context → evidence → insight → action.
|
|
166
|
+
11. For business topics, include real market data, industry benchmarks, and growth figures.
|
|
167
|
+
12. For technical topics, include architecture decisions, trade-offs, and concrete specs.
|
|
168
|
+
|
|
169
|
+
## Product & Service Expansion
|
|
170
|
+
When the prompt mentions multiple products, services, or offerings:
|
|
171
|
+
13. Give **each product/service its own dedicated section** with a section-break slide followed by 2-4 slides.
|
|
172
|
+
14. For each product, create at minimum: one "features" slide (core features as cards with icons) and one additional slide (stats, story, or comparison showing the product's value proposition).
|
|
173
|
+
15. Extract specific details: product name, tagline, core features, target audience, key differentiators, tech stack, and metrics.
|
|
174
|
+
16. If URLs or websites are mentioned, use your knowledge of those products/companies to provide accurate details. Include specific feature names, real capabilities, and actual use cases — not generic descriptions.
|
|
175
|
+
17. For company profiles with multiple products, structure as: Company Overview → Product 1 (section) → Product 2 (section) → ... → Combined Value / Why Us → Closing.
|
|
176
|
+
`;
|
|
177
|
+
function U(t, e) {
|
|
178
|
+
let i = t;
|
|
179
|
+
return e?.style && e.style !== "auto" && (i += `
|
|
180
|
+
|
|
181
|
+
Tone suggestion: "${e.style}" style.`), e?.slideCount && (i += `
|
|
182
|
+
|
|
183
|
+
Generate exactly ${e.slideCount} slides (across all sections).`), i;
|
|
184
|
+
}
|
|
185
|
+
const F = `You are a presentation visual designer. You receive structured slide content from a content strategist and your job is to map it to the optimal visual layout for each slide.
|
|
186
|
+
|
|
187
|
+
## Your Role
|
|
188
|
+
You focus ONLY on **visual design decisions** — which slide type, which palette, which icons. Do NOT rewrite or reduce the content. Preserve all text, metrics, and data exactly as provided.
|
|
189
|
+
|
|
190
|
+
## Input
|
|
191
|
+
You receive a JSON object with sections and slides, each slide having an "intent" and "content" fields.
|
|
192
|
+
|
|
193
|
+
## Output Format
|
|
194
|
+
Return ONLY a JSON object (no markdown fences, no explanation) with this schema:
|
|
195
|
+
|
|
196
|
+
{
|
|
197
|
+
"title": "Deck Title (from input)",
|
|
198
|
+
"colorPalette": "corporate" | "forest" | "royal" | "sunset" | "dark" | "minimalist",
|
|
199
|
+
"slides": [
|
|
200
|
+
{
|
|
201
|
+
"slideType": "title" | "content" | "two-column" | "bullets" | "quote" | "section-break" | "closing" | "image-text" | "metrics" | "timeline" | "card-grid" | "comparison",
|
|
202
|
+
"title": "Slide Title",
|
|
203
|
+
"subtitle": "...",
|
|
204
|
+
"bullets": ["..."],
|
|
205
|
+
"body": "...",
|
|
206
|
+
"quote": { "text": "...", "attribution": "..." },
|
|
207
|
+
"leftColumn": ["..."],
|
|
208
|
+
"rightColumn": ["..."],
|
|
209
|
+
"metrics": [{ "value": "...", "label": "..." }],
|
|
210
|
+
"timelineItems": [{ "year": "...", "text": "..." }],
|
|
211
|
+
"cards": [{ "title": "...", "body": "...", "icon": "..." }],
|
|
212
|
+
"comparisonLeft": { "title": "...", "items": ["..."] },
|
|
213
|
+
"comparisonRight": { "title": "...", "items": ["..."] },
|
|
214
|
+
"backgroundColor": "#hex (optional)"
|
|
215
|
+
}
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
## Intent → SlideType Mapping Guide
|
|
220
|
+
|
|
221
|
+
| Content Intent | Best SlideType Options |
|
|
222
|
+
|---|---|
|
|
223
|
+
| title | → "title" |
|
|
224
|
+
| stats | → "metrics" (best for 3-4 KPIs), or "content" if just one stat |
|
|
225
|
+
| points | → "content" or "bullets" (for bullet lists), "image-text" (for body + visual) |
|
|
226
|
+
| story | → "content" (body paragraph), "image-text" (narrative + visual), "quote" (if impactful) |
|
|
227
|
+
| comparison | → "comparison" (side-by-side panels), "two-column" (lighter comparison) |
|
|
228
|
+
| features | → "card-grid" (best for 2-6 features with icons), "content" (for simple list) |
|
|
229
|
+
| roadmap | → "timeline" (horizontal milestone dots), "content" (if < 3 items) |
|
|
230
|
+
| quote | → "quote" (centered with attribution) |
|
|
231
|
+
| overview | → "two-column" (parallel info), "card-grid" (if items have descriptions) |
|
|
232
|
+
| closing | → "closing" |
|
|
233
|
+
|
|
234
|
+
## Color Palettes
|
|
235
|
+
Choose based on topic tone:
|
|
236
|
+
- **corporate**: Professional blue — business, finance, enterprise
|
|
237
|
+
- **forest**: Nature green — sustainability, health, growth
|
|
238
|
+
- **royal**: Rich purple — creative, luxury, innovation
|
|
239
|
+
- **sunset**: Warm orange — startup, energy, announcement
|
|
240
|
+
- **dark**: Dark theme — tech, engineering, dev tools
|
|
241
|
+
- **minimalist**: Clean slate — clean, modern, academic
|
|
242
|
+
|
|
243
|
+
## Section Breaks
|
|
244
|
+
Insert "section-break" slides between major sections from the input. Use the section title as the slide title and a brief tagline as subtitle. Set backgroundColor to the palette's darker color for contrast.
|
|
245
|
+
|
|
246
|
+
## Rules
|
|
247
|
+
1. Map EVERY slide from the input — do not drop any slides.
|
|
248
|
+
2. Preserve ALL content text exactly as provided. Do not shorten, simplify, or rewrite.
|
|
249
|
+
3. Use at least 3 different slideType values per deck for visual variety.
|
|
250
|
+
4. Add section-break slides between sections (they don't need to be in the input).
|
|
251
|
+
5. For "stats" intent, always prefer "metrics" slideType when there are 3-4 data points.
|
|
252
|
+
6. For "features" intent with icons, always use "card-grid" slideType.
|
|
253
|
+
7. For "roadmap" intent, always use "timeline" slideType.
|
|
254
|
+
8. For "comparison" intent, always use "comparison" slideType.
|
|
255
|
+
9. Ensure the first slide is "title" and the last is "closing".
|
|
256
|
+
10. Pick icons for card-grid from: gear, target, lightbulb, trophy, rocket, flag, star, heart, shield, key, book, eye, clock, check, chart, user.
|
|
257
|
+
11. If input has a toneSuggestion, use it to inform palette choice (but you may override if another palette fits better).
|
|
258
|
+
`;
|
|
259
|
+
async function J(t, e = {}, i) {
|
|
260
|
+
return e.mode === "deep" ? D(t, e, i) : M(t, e, i);
|
|
261
|
+
}
|
|
262
|
+
async function M(t, e, i) {
|
|
263
|
+
const a = performance.now();
|
|
264
|
+
if (!T())
|
|
265
|
+
return { success: !1, error: "No API key configured. Open AI Settings to add one." };
|
|
266
|
+
const { provider: o, model: n, apiKey: u } = C(), d = q(t, {
|
|
267
|
+
style: e.style,
|
|
268
|
+
slideCount: e.slideCount || void 0
|
|
269
|
+
}), p = e.slideCount || 10, r = Math.min(Math.max(p * 250, 4096), 16384);
|
|
270
|
+
i?.("Generating slides...");
|
|
271
|
+
const s = await k({
|
|
272
|
+
provider: o,
|
|
273
|
+
model: n,
|
|
274
|
+
apiKey: u,
|
|
275
|
+
systemPrompt: R,
|
|
276
|
+
userPrompt: d,
|
|
277
|
+
temperature: 0.7,
|
|
278
|
+
maxTokens: r
|
|
279
|
+
});
|
|
280
|
+
if (!s.success)
|
|
281
|
+
return { success: !1, error: s.error || "LLM request failed" };
|
|
282
|
+
const c = P(s.content);
|
|
283
|
+
return c.success ? g(c.data, a, s.usage) : { success: !1, error: c.error };
|
|
284
|
+
}
|
|
285
|
+
async function D(t, e, i) {
|
|
286
|
+
const a = performance.now();
|
|
287
|
+
if (!T())
|
|
288
|
+
return { success: !1, error: "No API key configured. Open AI Settings to add one." };
|
|
289
|
+
const { provider: o, model: n, apiKey: u } = C();
|
|
290
|
+
i?.("Researching and writing content...");
|
|
291
|
+
const d = U(t, {
|
|
292
|
+
style: e.style,
|
|
293
|
+
slideCount: e.slideCount || void 0
|
|
294
|
+
}), p = e.slideCount || 10, r = Math.min(Math.max(p * 300, 4096), 16384), s = await k({
|
|
295
|
+
provider: o,
|
|
296
|
+
model: n,
|
|
297
|
+
apiKey: u,
|
|
298
|
+
systemPrompt: E,
|
|
299
|
+
userPrompt: d,
|
|
300
|
+
temperature: 0.7,
|
|
301
|
+
maxTokens: r
|
|
302
|
+
});
|
|
303
|
+
if (!s.success)
|
|
304
|
+
return { success: !1, error: `Content agent failed: ${s.error || "Unknown error"}` };
|
|
305
|
+
const c = {
|
|
306
|
+
promptTokens: s.usage?.promptTokens || 0,
|
|
307
|
+
completionTokens: s.usage?.completionTokens || 0
|
|
308
|
+
};
|
|
309
|
+
let m;
|
|
310
|
+
try {
|
|
311
|
+
m = S(s.content);
|
|
312
|
+
} catch {
|
|
313
|
+
return { success: !1, error: "Content agent returned invalid JSON. Please try again." };
|
|
314
|
+
}
|
|
315
|
+
if (!m.sections || !Array.isArray(m.sections))
|
|
316
|
+
return { success: !1, error: "Content agent returned no sections. Please try again." };
|
|
317
|
+
i?.("Designing visual layout...");
|
|
318
|
+
const y = m.sections.reduce(
|
|
319
|
+
(h, O) => h + (O.slides?.length || 0),
|
|
320
|
+
0
|
|
321
|
+
), b = Math.min(Math.max((y + 5) * 250, 4096), 16384), f = await k({
|
|
322
|
+
provider: o,
|
|
323
|
+
model: n,
|
|
324
|
+
apiKey: u,
|
|
325
|
+
systemPrompt: F,
|
|
326
|
+
userPrompt: JSON.stringify(m),
|
|
327
|
+
temperature: 0.3,
|
|
328
|
+
maxTokens: b
|
|
329
|
+
});
|
|
330
|
+
if (!f.success) {
|
|
331
|
+
i?.("Visual agent failed, applying heuristic layout...");
|
|
332
|
+
const h = I(m, e.style);
|
|
333
|
+
return g(h, a, c);
|
|
334
|
+
}
|
|
335
|
+
c.promptTokens += f.usage?.promptTokens || 0, c.completionTokens += f.usage?.completionTokens || 0;
|
|
336
|
+
const w = P(f.content);
|
|
337
|
+
if (!w.success) {
|
|
338
|
+
i?.("Applying heuristic layout...");
|
|
339
|
+
const h = I(m, e.style);
|
|
340
|
+
return g(h, a, c);
|
|
341
|
+
}
|
|
342
|
+
return g(w.data, a, c);
|
|
343
|
+
}
|
|
344
|
+
function S(t) {
|
|
345
|
+
let e = t.trim();
|
|
346
|
+
e.startsWith("```") && (e = e.replace(/^```(?:json)?\s*/i, "").replace(/```\s*$/, "").trim());
|
|
347
|
+
try {
|
|
348
|
+
return JSON.parse(e);
|
|
349
|
+
} catch {
|
|
350
|
+
}
|
|
351
|
+
const i = e.indexOf("{"), a = e.lastIndexOf("}");
|
|
352
|
+
if (i !== -1 && a > i)
|
|
353
|
+
return JSON.parse(e.substring(i, a + 1));
|
|
354
|
+
throw new Error("No valid JSON found");
|
|
355
|
+
}
|
|
356
|
+
function P(t) {
|
|
357
|
+
let e;
|
|
358
|
+
try {
|
|
359
|
+
e = S(t);
|
|
360
|
+
} catch {
|
|
361
|
+
return { success: !1, error: "Failed to parse AI response as JSON. Please try again." };
|
|
362
|
+
}
|
|
363
|
+
return !e.slides || !Array.isArray(e.slides) || e.slides.length === 0 ? { success: !1, error: "AI returned no slides. Please try a different prompt." } : { success: !0, data: e };
|
|
364
|
+
}
|
|
365
|
+
function g(t, e, i) {
|
|
366
|
+
const a = t.colorPalette || "corporate", o = v[a] || v.corporate, n = 2e3, u = [], d = [];
|
|
367
|
+
t.slides.forEach((s, c) => {
|
|
368
|
+
const m = c * n, y = A(s, o), b = N(y, m, 0), f = Y(b, s.slideType);
|
|
369
|
+
u.push(...f), d.push({
|
|
370
|
+
id: x("slide"),
|
|
371
|
+
name: s.title || `Slide ${c + 1}`,
|
|
372
|
+
spatialPosition: { x: m, y: 0 },
|
|
373
|
+
dimensions: { width: 1920, height: 1080 },
|
|
374
|
+
order: c,
|
|
375
|
+
backgroundColor: s.backgroundColor || o.background,
|
|
376
|
+
transition: G(s.slideType, c)
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
const p = {
|
|
380
|
+
version: 4,
|
|
381
|
+
metadata: { name: t.title || "AI Presentation", docType: "slides" },
|
|
382
|
+
elements: u,
|
|
383
|
+
layers: [{ id: "default-layer", name: "Layer 1", visible: !0, locked: !1, opacity: 1, order: 0, backgroundColor: "transparent" }],
|
|
384
|
+
slides: d,
|
|
385
|
+
globalSettings: {}
|
|
386
|
+
};
|
|
387
|
+
L(p);
|
|
388
|
+
const r = performance.now() - e;
|
|
389
|
+
return {
|
|
390
|
+
success: !0,
|
|
391
|
+
slideCount: t.slides.length,
|
|
392
|
+
title: t.title,
|
|
393
|
+
duration: r,
|
|
394
|
+
usage: i
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
function G(t, e) {
|
|
398
|
+
if (e === 0)
|
|
399
|
+
return { type: "fade", duration: 600, easing: "easeInOutCubic" };
|
|
400
|
+
switch (t) {
|
|
401
|
+
case "title":
|
|
402
|
+
case "closing":
|
|
403
|
+
return { type: "fade", duration: 600, easing: "easeInOutCubic" };
|
|
404
|
+
case "section-break":
|
|
405
|
+
return { type: "zoom-in", duration: 500, easing: "easeOutCubic" };
|
|
406
|
+
case "quote":
|
|
407
|
+
return { type: "fade", duration: 700, easing: "easeInOutQuad" };
|
|
408
|
+
default:
|
|
409
|
+
return e % 3 === 0 ? { type: "fade", duration: 500, easing: "easeInOutQuad" } : { type: "slide-left", duration: 450, easing: "easeOutCubic" };
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function l(t, e = {}) {
|
|
413
|
+
return {
|
|
414
|
+
id: x("anim"),
|
|
415
|
+
type: "preset",
|
|
416
|
+
name: t,
|
|
417
|
+
trigger: e.trigger || "on-load",
|
|
418
|
+
delay: e.delay || 0,
|
|
419
|
+
duration: e.duration || 600,
|
|
420
|
+
easing: e.easing || "easeOutCubic",
|
|
421
|
+
startHidden: e.startHidden ?? !0
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
function Y(t, e) {
|
|
425
|
+
const i = t.map((o) => ({
|
|
426
|
+
el: o,
|
|
427
|
+
role: B(o)
|
|
428
|
+
}));
|
|
429
|
+
let a = 0;
|
|
430
|
+
for (const { el: o, role: n } of i)
|
|
431
|
+
switch (n) {
|
|
432
|
+
case "decorative":
|
|
433
|
+
o.animations = [l("fadeIn", { duration: 800, delay: 0, startHidden: !1 })];
|
|
434
|
+
break;
|
|
435
|
+
case "title":
|
|
436
|
+
o.animations = [l("slideInDown", { duration: 500, delay: 100 })];
|
|
437
|
+
break;
|
|
438
|
+
case "subtitle":
|
|
439
|
+
o.animations = [l("fadeIn", { duration: 500, delay: 300 })];
|
|
440
|
+
break;
|
|
441
|
+
case "content-card":
|
|
442
|
+
o.animations = [l("zoomIn", { duration: 400, delay: 200 + a * 120 })], a++;
|
|
443
|
+
break;
|
|
444
|
+
case "content-text":
|
|
445
|
+
o.animations = [l("slideInLeft", { duration: 400, delay: 200 + a * 100 })], a++;
|
|
446
|
+
break;
|
|
447
|
+
case "metric-value":
|
|
448
|
+
o.animations = [l("zoomIn", { duration: 500, delay: 200 + a * 150, easing: "easeOutBack" })], a++;
|
|
449
|
+
break;
|
|
450
|
+
case "shape-icon":
|
|
451
|
+
o.animations = [l("zoomIn", { duration: 400, delay: 200 + a * 120 })], a++;
|
|
452
|
+
break;
|
|
453
|
+
case "timeline-dot":
|
|
454
|
+
o.animations = [l("zoomIn", { duration: 300, delay: 300 + a * 150, easing: "easeOutBack" })], a++;
|
|
455
|
+
break;
|
|
456
|
+
case "accent":
|
|
457
|
+
o.animations = [l("slideInLeft", { duration: 400, delay: 150, startHidden: !1 })];
|
|
458
|
+
break;
|
|
459
|
+
default:
|
|
460
|
+
o.animations = [l("fadeIn", { duration: 500, delay: 100 + a * 80 })], a++;
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
if (e === "section-break")
|
|
464
|
+
for (const { el: o, role: n } of i)
|
|
465
|
+
n === "title" ? o.animations = [l("zoomIn", { duration: 600, delay: 100, easing: "easeOutBack" })] : n === "subtitle" ? o.animations = [l("fadeIn", { duration: 500, delay: 400 })] : o.animations = [l("fadeIn", { duration: 600, delay: 0, startHidden: !1 })];
|
|
466
|
+
if (e === "quote")
|
|
467
|
+
for (const { el: o, role: n } of i)
|
|
468
|
+
n === "title" ? o.animations = [l("fadeIn", { duration: 800, delay: 200 })] : n === "subtitle" && (o.animations = [l("fadeIn", { duration: 500, delay: 600 })]);
|
|
469
|
+
return t;
|
|
470
|
+
}
|
|
471
|
+
function B(t) {
|
|
472
|
+
const e = t.id || "", i = t.type;
|
|
473
|
+
if (e.startsWith("shape-") && (t.opacity ?? 100) <= 20 || e.startsWith("grad-") || e.startsWith("rect-") && t.width >= 1800 && t.height >= 900) return "decorative";
|
|
474
|
+
if (e.startsWith("card-")) return "content-card";
|
|
475
|
+
if (e.startsWith("shape-") && (t.opacity ?? 100) > 20)
|
|
476
|
+
return t.width <= 60 && t.height <= 60 ? "shape-icon" : i === "circle" && t.width <= 30 ? "timeline-dot" : "shape-icon";
|
|
477
|
+
if (i === "text") {
|
|
478
|
+
const a = t.fontSize || 28;
|
|
479
|
+
return a >= 36 ? "title" : a <= 20 ? "subtitle" : a >= 48 ? "metric-value" : "content-text";
|
|
480
|
+
}
|
|
481
|
+
return e.startsWith("rect-") && (t.height <= 6 || t.width <= 6) ? "accent" : e.startsWith("rect-") ? "decorative" : "unknown";
|
|
482
|
+
}
|
|
483
|
+
function I(t, e) {
|
|
484
|
+
const i = {
|
|
485
|
+
title: "title",
|
|
486
|
+
stats: "metrics",
|
|
487
|
+
points: "content",
|
|
488
|
+
story: "content",
|
|
489
|
+
comparison: "comparison",
|
|
490
|
+
features: "card-grid",
|
|
491
|
+
roadmap: "timeline",
|
|
492
|
+
quote: "quote",
|
|
493
|
+
overview: "two-column",
|
|
494
|
+
closing: "closing"
|
|
495
|
+
}, o = e && e !== "auto" ? e : {
|
|
496
|
+
professional: "corporate",
|
|
497
|
+
energetic: "sunset",
|
|
498
|
+
technical: "dark",
|
|
499
|
+
creative: "royal",
|
|
500
|
+
minimal: "minimalist"
|
|
501
|
+
}[t.toneSuggestion] || "corporate", n = [];
|
|
502
|
+
for (const u of t.sections || []) {
|
|
503
|
+
n.length > 0 && n.push({
|
|
504
|
+
slideType: "section-break",
|
|
505
|
+
title: u.sectionTitle || "Section"
|
|
506
|
+
});
|
|
507
|
+
for (const d of u.slides || []) {
|
|
508
|
+
const r = {
|
|
509
|
+
slideType: i[d.intent] || "content",
|
|
510
|
+
title: d.title
|
|
511
|
+
}, s = d.content || {};
|
|
512
|
+
switch (d.intent) {
|
|
513
|
+
case "title":
|
|
514
|
+
case "closing":
|
|
515
|
+
r.subtitle = s.subtitle;
|
|
516
|
+
break;
|
|
517
|
+
case "stats":
|
|
518
|
+
r.metrics = s.metrics;
|
|
519
|
+
break;
|
|
520
|
+
case "points":
|
|
521
|
+
r.bullets = s.bullets, r.body = s.body;
|
|
522
|
+
break;
|
|
523
|
+
case "story":
|
|
524
|
+
r.body = s.body;
|
|
525
|
+
break;
|
|
526
|
+
case "comparison":
|
|
527
|
+
r.comparisonLeft = { title: s.leftTitle || "Option A", items: s.leftItems || [] }, r.comparisonRight = { title: s.rightTitle || "Option B", items: s.rightItems || [] };
|
|
528
|
+
break;
|
|
529
|
+
case "features":
|
|
530
|
+
r.cards = s.cards;
|
|
531
|
+
break;
|
|
532
|
+
case "roadmap":
|
|
533
|
+
r.timelineItems = s.timelineItems;
|
|
534
|
+
break;
|
|
535
|
+
case "quote":
|
|
536
|
+
r.quote = { text: s.text, attribution: s.attribution };
|
|
537
|
+
break;
|
|
538
|
+
case "overview":
|
|
539
|
+
r.leftColumn = s.leftColumn, r.rightColumn = s.rightColumn;
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
542
|
+
n.push(r);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return {
|
|
546
|
+
title: t.title,
|
|
547
|
+
colorPalette: o,
|
|
548
|
+
slides: n
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
export {
|
|
552
|
+
J as generatePresentation
|
|
553
|
+
};
|