@thanh01.pmt/presentation-kit 0.2.10 → 0.2.11
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/dist/ai/index.cjs +190 -7
- package/dist/ai/index.cjs.map +1 -1
- package/dist/ai/index.d.cts +123 -3
- package/dist/ai/index.d.ts +123 -3
- package/dist/ai/index.js +177 -2
- package/dist/ai/index.js.map +1 -1
- package/dist/chunk-3VGV5KYZ.js +3446 -0
- package/dist/chunk-3VGV5KYZ.js.map +1 -0
- package/dist/chunk-53GLUCYC.cjs +3464 -0
- package/dist/chunk-53GLUCYC.cjs.map +1 -0
- package/dist/{click-css-BP9oqy_1.d.cts → click-css-Ch_jyWaw.d.cts} +1 -1
- package/dist/{click-css-BbhqdtGr.d.ts → click-css-CktIYP3H.d.ts} +1 -1
- package/dist/index.cjs +30 -10
- package/dist/index.d.cts +21 -5
- package/dist/index.d.ts +21 -5
- package/dist/index.js +2 -2
- package/dist/{presets-B_TY4i2a.d.ts → presets-BUzebXzj.d.ts} +1 -1
- package/dist/{presets-BIw_4ZXR.d.cts → presets-Bkh6NzWf.d.cts} +1 -1
- package/dist/react/index.cjs +351 -90
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +25 -5
- package/dist/react/index.d.ts +25 -5
- package/dist/react/index.js +297 -41
- package/dist/react/index.js.map +1 -1
- package/dist/{types-C1121XLt.d.cts → types-8AVYoEUn.d.cts} +67 -1
- package/dist/{types-C1121XLt.d.ts → types-8AVYoEUn.d.ts} +67 -1
- package/package.json +2 -2
- package/dist/chunk-3Q4RMZVQ.cjs +0 -867
- package/dist/chunk-3Q4RMZVQ.cjs.map +0 -1
- package/dist/chunk-V6X7D44H.js +0 -854
- package/dist/chunk-V6X7D44H.js.map +0 -1
package/dist/react/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React$1 from 'react';
|
|
2
|
-
import { B as BuiltInTheme,
|
|
3
|
-
export { M as MermaidBlock,
|
|
4
|
-
export { l as ClickCssOptions, k as ClickPostprocessResult, C as ClickPreprocessResult, d as defineTheme, i as extractMaxClicks, j as generateClickCss, h as postprocessClicks, p as preprocessClicks, r as renderSlide, a as renderSlideAsync, e as resolveTheme } from '../click-css-
|
|
2
|
+
import { B as BuiltInTheme, h as SlideTheme, j as SlideRenderResult, f as HtmlDeckData, b as SlideLayoutData, L as LayoutBoxConfig } from '../types-8AVYoEUn.cjs';
|
|
3
|
+
export { M as MermaidBlock, k as SlideRenderAsyncResult, i as SlideRenderOptions, T as ThemeTokens } from '../types-8AVYoEUn.cjs';
|
|
4
|
+
export { l as ClickCssOptions, k as ClickPostprocessResult, C as ClickPreprocessResult, d as defineTheme, i as extractMaxClicks, j as generateClickCss, h as postprocessClicks, p as preprocessClicks, r as renderSlide, a as renderSlideAsync, e as resolveTheme } from '../click-css-Ch_jyWaw.cjs';
|
|
5
5
|
|
|
6
6
|
/** View mode for slide display */
|
|
7
7
|
type SlideViewMode = 'presentation' | 'deck';
|
|
@@ -80,6 +80,10 @@ interface DeckViewProps {
|
|
|
80
80
|
slideCount: number;
|
|
81
81
|
/** Container CSS class */
|
|
82
82
|
className?: string;
|
|
83
|
+
/** Presenter notes per slide (optional) */
|
|
84
|
+
notes?: string[][];
|
|
85
|
+
/** Whether to render speaker notes below each slide in deck mode */
|
|
86
|
+
showNotes?: boolean;
|
|
83
87
|
}
|
|
84
88
|
/** Props for ThemeSwitcher */
|
|
85
89
|
interface ThemeSwitcherProps {
|
|
@@ -171,6 +175,22 @@ interface SlideActions {
|
|
|
171
175
|
*/
|
|
172
176
|
declare function SlideViewer({ markdown, initialTheme, initialMode, className, showThemeSwitcher, showNavigation, enableKeyboard, enableClicks, fullscreen, showNotes, showDesignMode, themeOptions, onThemeChange, onSlideChange, onModeChange, onRenderComplete, onSaveMarkdown, }: SlideViewerProps): React$1.JSX.Element;
|
|
173
177
|
|
|
178
|
+
interface HtmlSlideViewerProps {
|
|
179
|
+
/** Pre-compiled HTML string. If provided, used directly */
|
|
180
|
+
htmlContent?: string;
|
|
181
|
+
/** Structured deck data. If provided without htmlContent, compiled automatically */
|
|
182
|
+
deckData?: HtmlDeckData;
|
|
183
|
+
/** Deck title displayed on header / download file name */
|
|
184
|
+
title?: string;
|
|
185
|
+
/** Extra CSS classes for wrapper */
|
|
186
|
+
className?: string;
|
|
187
|
+
/** Callback fired when active slide index changes */
|
|
188
|
+
onSlideChange?: (current: number, total: number) => void;
|
|
189
|
+
/** Show top control bar */
|
|
190
|
+
showTopBar?: boolean;
|
|
191
|
+
}
|
|
192
|
+
declare const HtmlSlideViewer: React$1.FC<HtmlSlideViewerProps>;
|
|
193
|
+
|
|
174
194
|
/**
|
|
175
195
|
* PresentationView — Renders a single slide at a time.
|
|
176
196
|
*
|
|
@@ -205,7 +225,7 @@ declare function PresentationView({ html, css, themeCss, layoutCss, currentIndex
|
|
|
205
225
|
* />
|
|
206
226
|
* ```
|
|
207
227
|
*/
|
|
208
|
-
declare function DeckView({ html, css, themeCss, layoutCss, slideCount, className, }: DeckViewProps): React$1.JSX.Element;
|
|
228
|
+
declare function DeckView({ html, css, themeCss, layoutCss, slideCount, className, notes, showNotes, }: DeckViewProps): React$1.JSX.Element;
|
|
209
229
|
|
|
210
230
|
/**
|
|
211
231
|
* ThemeSwitcher — Renders a row of theme toggle buttons.
|
|
@@ -321,4 +341,4 @@ interface UseSlideStateReturn {
|
|
|
321
341
|
*/
|
|
322
342
|
declare function useSlideState(options: UseSlideStateOptions): UseSlideStateReturn;
|
|
323
343
|
|
|
324
|
-
export { BuiltInTheme, DeckView, type DeckViewProps, NavigationBar, type NavigationBarProps, PresentationView, type PresentationViewProps, PresenterNotesDrawer, type PresenterNotesDrawerProps, type SlideActions, SlideDesignOverlay, type SlideDesignOverlayProps, SlideRenderResult, type SlideState, SlideTheme, type SlideViewMode, SlideViewer, type SlideViewerProps, type ThemeOption, ThemeSwitcher, type ThemeSwitcherProps, type UseSlideStateOptions, type UseSlideStateReturn, useSlideState };
|
|
344
|
+
export { BuiltInTheme, DeckView, type DeckViewProps, HtmlSlideViewer, type HtmlSlideViewerProps, NavigationBar, type NavigationBarProps, PresentationView, type PresentationViewProps, PresenterNotesDrawer, type PresenterNotesDrawerProps, type SlideActions, SlideDesignOverlay, type SlideDesignOverlayProps, SlideRenderResult, type SlideState, SlideTheme, type SlideViewMode, SlideViewer, type SlideViewerProps, type ThemeOption, ThemeSwitcher, type ThemeSwitcherProps, type UseSlideStateOptions, type UseSlideStateReturn, useSlideState };
|
package/dist/react/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React$1 from 'react';
|
|
2
|
-
import { B as BuiltInTheme,
|
|
3
|
-
export { M as MermaidBlock,
|
|
4
|
-
export { l as ClickCssOptions, k as ClickPostprocessResult, C as ClickPreprocessResult, d as defineTheme, i as extractMaxClicks, j as generateClickCss, h as postprocessClicks, p as preprocessClicks, r as renderSlide, a as renderSlideAsync, e as resolveTheme } from '../click-css-
|
|
2
|
+
import { B as BuiltInTheme, h as SlideTheme, j as SlideRenderResult, f as HtmlDeckData, b as SlideLayoutData, L as LayoutBoxConfig } from '../types-8AVYoEUn.js';
|
|
3
|
+
export { M as MermaidBlock, k as SlideRenderAsyncResult, i as SlideRenderOptions, T as ThemeTokens } from '../types-8AVYoEUn.js';
|
|
4
|
+
export { l as ClickCssOptions, k as ClickPostprocessResult, C as ClickPreprocessResult, d as defineTheme, i as extractMaxClicks, j as generateClickCss, h as postprocessClicks, p as preprocessClicks, r as renderSlide, a as renderSlideAsync, e as resolveTheme } from '../click-css-CktIYP3H.js';
|
|
5
5
|
|
|
6
6
|
/** View mode for slide display */
|
|
7
7
|
type SlideViewMode = 'presentation' | 'deck';
|
|
@@ -80,6 +80,10 @@ interface DeckViewProps {
|
|
|
80
80
|
slideCount: number;
|
|
81
81
|
/** Container CSS class */
|
|
82
82
|
className?: string;
|
|
83
|
+
/** Presenter notes per slide (optional) */
|
|
84
|
+
notes?: string[][];
|
|
85
|
+
/** Whether to render speaker notes below each slide in deck mode */
|
|
86
|
+
showNotes?: boolean;
|
|
83
87
|
}
|
|
84
88
|
/** Props for ThemeSwitcher */
|
|
85
89
|
interface ThemeSwitcherProps {
|
|
@@ -171,6 +175,22 @@ interface SlideActions {
|
|
|
171
175
|
*/
|
|
172
176
|
declare function SlideViewer({ markdown, initialTheme, initialMode, className, showThemeSwitcher, showNavigation, enableKeyboard, enableClicks, fullscreen, showNotes, showDesignMode, themeOptions, onThemeChange, onSlideChange, onModeChange, onRenderComplete, onSaveMarkdown, }: SlideViewerProps): React$1.JSX.Element;
|
|
173
177
|
|
|
178
|
+
interface HtmlSlideViewerProps {
|
|
179
|
+
/** Pre-compiled HTML string. If provided, used directly */
|
|
180
|
+
htmlContent?: string;
|
|
181
|
+
/** Structured deck data. If provided without htmlContent, compiled automatically */
|
|
182
|
+
deckData?: HtmlDeckData;
|
|
183
|
+
/** Deck title displayed on header / download file name */
|
|
184
|
+
title?: string;
|
|
185
|
+
/** Extra CSS classes for wrapper */
|
|
186
|
+
className?: string;
|
|
187
|
+
/** Callback fired when active slide index changes */
|
|
188
|
+
onSlideChange?: (current: number, total: number) => void;
|
|
189
|
+
/** Show top control bar */
|
|
190
|
+
showTopBar?: boolean;
|
|
191
|
+
}
|
|
192
|
+
declare const HtmlSlideViewer: React$1.FC<HtmlSlideViewerProps>;
|
|
193
|
+
|
|
174
194
|
/**
|
|
175
195
|
* PresentationView — Renders a single slide at a time.
|
|
176
196
|
*
|
|
@@ -205,7 +225,7 @@ declare function PresentationView({ html, css, themeCss, layoutCss, currentIndex
|
|
|
205
225
|
* />
|
|
206
226
|
* ```
|
|
207
227
|
*/
|
|
208
|
-
declare function DeckView({ html, css, themeCss, layoutCss, slideCount, className, }: DeckViewProps): React$1.JSX.Element;
|
|
228
|
+
declare function DeckView({ html, css, themeCss, layoutCss, slideCount, className, notes, showNotes, }: DeckViewProps): React$1.JSX.Element;
|
|
209
229
|
|
|
210
230
|
/**
|
|
211
231
|
* ThemeSwitcher — Renders a row of theme toggle buttons.
|
|
@@ -321,4 +341,4 @@ interface UseSlideStateReturn {
|
|
|
321
341
|
*/
|
|
322
342
|
declare function useSlideState(options: UseSlideStateOptions): UseSlideStateReturn;
|
|
323
343
|
|
|
324
|
-
export { BuiltInTheme, DeckView, type DeckViewProps, NavigationBar, type NavigationBarProps, PresentationView, type PresentationViewProps, PresenterNotesDrawer, type PresenterNotesDrawerProps, type SlideActions, SlideDesignOverlay, type SlideDesignOverlayProps, SlideRenderResult, type SlideState, SlideTheme, type SlideViewMode, SlideViewer, type SlideViewerProps, type ThemeOption, ThemeSwitcher, type ThemeSwitcherProps, type UseSlideStateOptions, type UseSlideStateReturn, useSlideState };
|
|
344
|
+
export { BuiltInTheme, DeckView, type DeckViewProps, HtmlSlideViewer, type HtmlSlideViewerProps, NavigationBar, type NavigationBarProps, PresentationView, type PresentationViewProps, PresenterNotesDrawer, type PresenterNotesDrawerProps, type SlideActions, SlideDesignOverlay, type SlideDesignOverlayProps, SlideRenderResult, type SlideState, SlideTheme, type SlideViewMode, SlideViewer, type SlideViewerProps, type ThemeOption, ThemeSwitcher, type ThemeSwitcherProps, type UseSlideStateOptions, type UseSlideStateReturn, useSlideState };
|
package/dist/react/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { renderSlide, renderMermaidDiagrams } from '../chunk-NYLDRVHZ.js';
|
|
2
2
|
export { defineTheme, extractMaxClicks, generateClickCss, postprocessClicks, preprocessClicks, renderSlide, renderSlideAsync, resolveTheme } from '../chunk-NYLDRVHZ.js';
|
|
3
|
-
import { SLIDE_LAYOUT_PRESETS, updateSlideLayoutInMarkdown } from '../chunk-
|
|
4
|
-
import { useState, useRef, useMemo, useEffect, useCallback } from 'react';
|
|
3
|
+
import { SLIDE_LAYOUT_PRESETS, updateSlideLayoutInMarkdown, compileHtmlDeck } from '../chunk-3VGV5KYZ.js';
|
|
4
|
+
import React2, { useState, useRef, useMemo, useEffect, useCallback } from 'react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
function useSlideState(options) {
|
|
@@ -410,8 +410,45 @@ function DeckView({
|
|
|
410
410
|
themeCss,
|
|
411
411
|
layoutCss,
|
|
412
412
|
slideCount,
|
|
413
|
-
className
|
|
413
|
+
className,
|
|
414
|
+
notes,
|
|
415
|
+
showNotes = false
|
|
414
416
|
}) {
|
|
417
|
+
const hostRef = React2.useRef(null);
|
|
418
|
+
React2.useEffect(() => {
|
|
419
|
+
if (!hostRef.current) return;
|
|
420
|
+
hostRef.current.querySelectorAll(".deck-slide-note-item").forEach((el) => el.remove());
|
|
421
|
+
if (!showNotes || !notes || notes.length === 0) return;
|
|
422
|
+
const svgs = hostRef.current.querySelectorAll("svg[data-marpit-svg], svg");
|
|
423
|
+
svgs.forEach((svg, idx) => {
|
|
424
|
+
const slideNotes = notes[idx];
|
|
425
|
+
if (slideNotes && slideNotes.length > 0) {
|
|
426
|
+
const noteBox = document.createElement("div");
|
|
427
|
+
noteBox.className = "deck-slide-note-item";
|
|
428
|
+
noteBox.style.cssText = `
|
|
429
|
+
width: 100%;
|
|
430
|
+
max-width: 960px;
|
|
431
|
+
margin: -16px auto 32px auto;
|
|
432
|
+
background: rgba(24, 24, 32, 0.85);
|
|
433
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
434
|
+
border-left: 4px solid #0284c7;
|
|
435
|
+
border-radius: 8px;
|
|
436
|
+
padding: 14px 18px;
|
|
437
|
+
color: #e4e4e7;
|
|
438
|
+
font-size: 14px;
|
|
439
|
+
line-height: 1.6;
|
|
440
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
441
|
+
`;
|
|
442
|
+
noteBox.innerHTML = `
|
|
443
|
+
<div style="font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: #38bdf8; margin-bottom: 4px; display: flex; align-items: center; gap: 6px;">
|
|
444
|
+
<span>\u{1F4DD}</span><span>Presenter Notes (Slide ${idx + 1})</span>
|
|
445
|
+
</div>
|
|
446
|
+
<div style="white-space: pre-wrap; font-size: 13px; line-height: 1.6; color: inherit;">${slideNotes.join("\n")}</div>
|
|
447
|
+
`;
|
|
448
|
+
svg.after(noteBox);
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
}, [html, notes, showNotes]);
|
|
415
452
|
const deckCss = `
|
|
416
453
|
.slide-deck-host {
|
|
417
454
|
display: flex !important;
|
|
@@ -451,6 +488,46 @@ function DeckView({
|
|
|
451
488
|
transform: translateY(-2px);
|
|
452
489
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2) !important;
|
|
453
490
|
}
|
|
491
|
+
|
|
492
|
+
@media print {
|
|
493
|
+
@page {
|
|
494
|
+
size: landscape;
|
|
495
|
+
margin: 0;
|
|
496
|
+
}
|
|
497
|
+
body {
|
|
498
|
+
background: #ffffff !important;
|
|
499
|
+
color: #000000 !important;
|
|
500
|
+
}
|
|
501
|
+
.slide-deck-host {
|
|
502
|
+
padding: 0 !important;
|
|
503
|
+
}
|
|
504
|
+
.slide-deck-host #marp-container svg[data-marpit-svg],
|
|
505
|
+
.slide-deck-host #marp-container > svg,
|
|
506
|
+
.slide-deck-host > div > svg {
|
|
507
|
+
width: 100vw !important;
|
|
508
|
+
max-width: none !important;
|
|
509
|
+
height: 56.25vw !important;
|
|
510
|
+
page-break-inside: avoid !important;
|
|
511
|
+
break-inside: avoid !important;
|
|
512
|
+
page-break-after: always !important;
|
|
513
|
+
break-after: page !important;
|
|
514
|
+
margin: 0 auto !important;
|
|
515
|
+
box-shadow: none !important;
|
|
516
|
+
border-radius: 0 !important;
|
|
517
|
+
}
|
|
518
|
+
.deck-slide-note-item {
|
|
519
|
+
page-break-after: always !important;
|
|
520
|
+
break-after: page !important;
|
|
521
|
+
background: #f8fafc !important;
|
|
522
|
+
border: 1px solid #cbd5e1 !important;
|
|
523
|
+
border-left: 4px solid #2563eb !important;
|
|
524
|
+
color: #1e293b !important;
|
|
525
|
+
padding: 12px 18px !important;
|
|
526
|
+
margin: 12px auto 32px auto !important;
|
|
527
|
+
width: 90vw !important;
|
|
528
|
+
font-size: 11pt !important;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
454
531
|
`;
|
|
455
532
|
return /* @__PURE__ */ jsxs("div", { className, style: { width: "100%" }, children: [
|
|
456
533
|
/* @__PURE__ */ jsx("style", { children: css }),
|
|
@@ -460,6 +537,7 @@ function DeckView({
|
|
|
460
537
|
/* @__PURE__ */ jsx(
|
|
461
538
|
"div",
|
|
462
539
|
{
|
|
540
|
+
ref: hostRef,
|
|
463
541
|
className: "slide-deck-host",
|
|
464
542
|
dangerouslySetInnerHTML: { __html: html }
|
|
465
543
|
}
|
|
@@ -1219,6 +1297,13 @@ function SlideViewer({
|
|
|
1219
1297
|
setIsFullscreen((prev) => !prev);
|
|
1220
1298
|
}
|
|
1221
1299
|
break;
|
|
1300
|
+
case "p":
|
|
1301
|
+
case "P":
|
|
1302
|
+
if (showNotes) {
|
|
1303
|
+
e.preventDefault();
|
|
1304
|
+
setShowNotesDrawer((prev) => !prev);
|
|
1305
|
+
}
|
|
1306
|
+
break;
|
|
1222
1307
|
}
|
|
1223
1308
|
};
|
|
1224
1309
|
window.addEventListener("keydown", handleKey);
|
|
@@ -1440,45 +1525,62 @@ function SlideViewer({
|
|
|
1440
1525
|
transition: "width 0.2s ease"
|
|
1441
1526
|
} }) })
|
|
1442
1527
|
] }),
|
|
1443
|
-
/* @__PURE__ */ jsx(
|
|
1444
|
-
|
|
1445
|
-
PresentationView,
|
|
1446
|
-
{
|
|
1447
|
-
html: result.html,
|
|
1448
|
-
css: result.css,
|
|
1449
|
-
themeCss: result.themeCss,
|
|
1450
|
-
layoutCss: result.layoutCss,
|
|
1451
|
-
currentIndex,
|
|
1452
|
-
slideCount
|
|
1453
|
-
}
|
|
1454
|
-
),
|
|
1455
|
-
isDesignMode && /* @__PURE__ */ jsx(
|
|
1456
|
-
SlideDesignOverlay,
|
|
1457
|
-
{
|
|
1458
|
-
slideIndex: currentIndex,
|
|
1459
|
-
layout: liveLayout ?? result.layouts?.[currentIndex] ?? null,
|
|
1460
|
-
onLayoutChange: setLiveLayout,
|
|
1461
|
-
onSave: (layout) => {
|
|
1462
|
-
setLiveLayout(layout);
|
|
1463
|
-
if (onSaveMarkdown) {
|
|
1464
|
-
const updated = updateSlideLayoutInMarkdown(markdown, currentIndex, layout);
|
|
1465
|
-
onSaveMarkdown(updated);
|
|
1466
|
-
}
|
|
1467
|
-
},
|
|
1468
|
-
onClose: () => setIsDesignMode(false),
|
|
1469
|
-
isActive: isDesignMode
|
|
1470
|
-
}
|
|
1471
|
-
)
|
|
1472
|
-
] }) : /* @__PURE__ */ jsx(
|
|
1473
|
-
DeckView,
|
|
1528
|
+
/* @__PURE__ */ jsx(
|
|
1529
|
+
"div",
|
|
1474
1530
|
{
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1531
|
+
style: { position: "relative", width: "100%" },
|
|
1532
|
+
onClick: (e) => {
|
|
1533
|
+
if (mode !== "presentation" || isDesignMode) return;
|
|
1534
|
+
if (e.target.closest("button, a, input, select, textarea, [contenteditable], .slide-design-overlay")) return;
|
|
1535
|
+
if (enableClicks && currentClick < maxClicks) {
|
|
1536
|
+
nextClick();
|
|
1537
|
+
} else {
|
|
1538
|
+
nextSlide();
|
|
1539
|
+
}
|
|
1540
|
+
},
|
|
1541
|
+
children: mode === "presentation" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1542
|
+
/* @__PURE__ */ jsx(
|
|
1543
|
+
PresentationView,
|
|
1544
|
+
{
|
|
1545
|
+
html: result.html,
|
|
1546
|
+
css: result.css,
|
|
1547
|
+
themeCss: result.themeCss,
|
|
1548
|
+
layoutCss: result.layoutCss,
|
|
1549
|
+
currentIndex,
|
|
1550
|
+
slideCount
|
|
1551
|
+
}
|
|
1552
|
+
),
|
|
1553
|
+
isDesignMode && /* @__PURE__ */ jsx(
|
|
1554
|
+
SlideDesignOverlay,
|
|
1555
|
+
{
|
|
1556
|
+
slideIndex: currentIndex,
|
|
1557
|
+
layout: liveLayout ?? result.layouts?.[currentIndex] ?? null,
|
|
1558
|
+
onLayoutChange: setLiveLayout,
|
|
1559
|
+
onSave: (layout) => {
|
|
1560
|
+
setLiveLayout(layout);
|
|
1561
|
+
if (onSaveMarkdown) {
|
|
1562
|
+
const updated = updateSlideLayoutInMarkdown(markdown, currentIndex, layout);
|
|
1563
|
+
onSaveMarkdown(updated);
|
|
1564
|
+
}
|
|
1565
|
+
},
|
|
1566
|
+
onClose: () => setIsDesignMode(false),
|
|
1567
|
+
isActive: isDesignMode
|
|
1568
|
+
}
|
|
1569
|
+
)
|
|
1570
|
+
] }) : /* @__PURE__ */ jsx(
|
|
1571
|
+
DeckView,
|
|
1572
|
+
{
|
|
1573
|
+
html: result.html,
|
|
1574
|
+
css: result.css,
|
|
1575
|
+
themeCss: result.themeCss,
|
|
1576
|
+
layoutCss: result.layoutCss,
|
|
1577
|
+
slideCount,
|
|
1578
|
+
notes: result.notes,
|
|
1579
|
+
showNotes: showNotesDrawer
|
|
1580
|
+
}
|
|
1581
|
+
)
|
|
1480
1582
|
}
|
|
1481
|
-
)
|
|
1583
|
+
),
|
|
1482
1584
|
showNotes && /* @__PURE__ */ jsx(
|
|
1483
1585
|
PresenterNotesDrawer,
|
|
1484
1586
|
{
|
|
@@ -1494,7 +1596,161 @@ function SlideViewer({
|
|
|
1494
1596
|
}
|
|
1495
1597
|
);
|
|
1496
1598
|
}
|
|
1599
|
+
var HtmlSlideViewer = ({
|
|
1600
|
+
htmlContent: initialHtml,
|
|
1601
|
+
deckData,
|
|
1602
|
+
title: propTitle,
|
|
1603
|
+
className = "",
|
|
1604
|
+
onSlideChange,
|
|
1605
|
+
showTopBar = true
|
|
1606
|
+
}) => {
|
|
1607
|
+
const iframeRef = useRef(null);
|
|
1608
|
+
const containerRef = useRef(null);
|
|
1609
|
+
const [currentSlide, setCurrentSlide] = useState(0);
|
|
1610
|
+
const [totalSlides, setTotalSlides] = useState(deckData?.slides?.length || 1);
|
|
1611
|
+
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
1612
|
+
const fullHtml = useMemo(() => {
|
|
1613
|
+
if (initialHtml) return initialHtml;
|
|
1614
|
+
if (deckData) {
|
|
1615
|
+
return compileHtmlDeck(deckData).html;
|
|
1616
|
+
}
|
|
1617
|
+
return "";
|
|
1618
|
+
}, [initialHtml, deckData]);
|
|
1619
|
+
const deckTitle = propTitle || deckData?.title || "Presentation";
|
|
1620
|
+
useEffect(() => {
|
|
1621
|
+
const handleMessage = (e) => {
|
|
1622
|
+
if (!e.data || typeof e.data !== "object") return;
|
|
1623
|
+
if (e.data.type === "PRESENTATION_SLIDE_CHANGE") {
|
|
1624
|
+
const cur = Number(e.data.currentIndex) || 0;
|
|
1625
|
+
const tot = Number(e.data.totalSlides) || 1;
|
|
1626
|
+
setCurrentSlide(cur);
|
|
1627
|
+
setTotalSlides(tot);
|
|
1628
|
+
if (onSlideChange) {
|
|
1629
|
+
onSlideChange(cur, tot);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
window.addEventListener("message", handleMessage);
|
|
1634
|
+
return () => window.removeEventListener("message", handleMessage);
|
|
1635
|
+
}, [onSlideChange]);
|
|
1636
|
+
useEffect(() => {
|
|
1637
|
+
const onFsChange = () => {
|
|
1638
|
+
setIsFullscreen(Boolean(document.fullscreenElement));
|
|
1639
|
+
};
|
|
1640
|
+
document.addEventListener("fullscreenchange", onFsChange);
|
|
1641
|
+
return () => document.removeEventListener("fullscreenchange", onFsChange);
|
|
1642
|
+
}, []);
|
|
1643
|
+
const sendIframeMessage = useCallback((msg) => {
|
|
1644
|
+
if (iframeRef.current?.contentWindow) {
|
|
1645
|
+
iframeRef.current.contentWindow.postMessage(msg, "*");
|
|
1646
|
+
}
|
|
1647
|
+
}, []);
|
|
1648
|
+
const handleNext = () => sendIframeMessage({ type: "NEXT_SLIDE" });
|
|
1649
|
+
const handlePrev = () => sendIframeMessage({ type: "PREV_SLIDE" });
|
|
1650
|
+
const handleToggleFullscreen = () => {
|
|
1651
|
+
if (!containerRef.current) return;
|
|
1652
|
+
if (!document.fullscreenElement) {
|
|
1653
|
+
containerRef.current.requestFullscreen().catch(() => {
|
|
1654
|
+
});
|
|
1655
|
+
} else {
|
|
1656
|
+
document.exitFullscreen().catch(() => {
|
|
1657
|
+
});
|
|
1658
|
+
}
|
|
1659
|
+
};
|
|
1660
|
+
const handleDownloadHtml = () => {
|
|
1661
|
+
if (!fullHtml) return;
|
|
1662
|
+
const blob = new Blob([fullHtml], { type: "text/html;charset=utf-8" });
|
|
1663
|
+
const url = URL.createObjectURL(blob);
|
|
1664
|
+
const a = document.createElement("a");
|
|
1665
|
+
a.href = url;
|
|
1666
|
+
a.download = `${deckTitle.toLowerCase().replace(/[^a-z0-9]/g, "-") || "slide-deck"}.html`;
|
|
1667
|
+
document.body.appendChild(a);
|
|
1668
|
+
a.click();
|
|
1669
|
+
document.body.removeChild(a);
|
|
1670
|
+
URL.revokeObjectURL(url);
|
|
1671
|
+
};
|
|
1672
|
+
return /* @__PURE__ */ jsxs(
|
|
1673
|
+
"div",
|
|
1674
|
+
{
|
|
1675
|
+
ref: containerRef,
|
|
1676
|
+
className: `relative flex flex-col w-full h-full bg-neutral-950 text-neutral-100 rounded-xl overflow-hidden shadow-2xl ${className}`,
|
|
1677
|
+
style: { minHeight: "480px" },
|
|
1678
|
+
children: [
|
|
1679
|
+
showTopBar && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2 bg-neutral-900/90 backdrop-blur border-b border-neutral-800 text-xs select-none z-20", children: [
|
|
1680
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 font-medium truncate max-w-md", children: [
|
|
1681
|
+
/* @__PURE__ */ jsx("span", { className: "w-2 h-2 rounded-full bg-blue-500 inline-block" }),
|
|
1682
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-neutral-200", children: deckTitle })
|
|
1683
|
+
] }),
|
|
1684
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1685
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 bg-neutral-800/80 px-2 py-1 rounded border border-neutral-700 font-mono text-[11px]", children: [
|
|
1686
|
+
/* @__PURE__ */ jsx(
|
|
1687
|
+
"button",
|
|
1688
|
+
{
|
|
1689
|
+
onClick: handlePrev,
|
|
1690
|
+
disabled: currentSlide <= 0,
|
|
1691
|
+
className: "hover:text-white disabled:opacity-40 p-0.5",
|
|
1692
|
+
title: "Previous Slide",
|
|
1693
|
+
children: "\u25C0"
|
|
1694
|
+
}
|
|
1695
|
+
),
|
|
1696
|
+
/* @__PURE__ */ jsxs("span", { className: "px-1 font-semibold text-neutral-200", children: [
|
|
1697
|
+
String(currentSlide + 1).padStart(2, "0"),
|
|
1698
|
+
" / ",
|
|
1699
|
+
String(totalSlides).padStart(2, "0")
|
|
1700
|
+
] }),
|
|
1701
|
+
/* @__PURE__ */ jsx(
|
|
1702
|
+
"button",
|
|
1703
|
+
{
|
|
1704
|
+
onClick: handleNext,
|
|
1705
|
+
disabled: currentSlide >= totalSlides - 1,
|
|
1706
|
+
className: "hover:text-white disabled:opacity-40 p-0.5",
|
|
1707
|
+
title: "Next Slide",
|
|
1708
|
+
children: "\u25B6"
|
|
1709
|
+
}
|
|
1710
|
+
)
|
|
1711
|
+
] }),
|
|
1712
|
+
/* @__PURE__ */ jsxs(
|
|
1713
|
+
"button",
|
|
1714
|
+
{
|
|
1715
|
+
onClick: handleDownloadHtml,
|
|
1716
|
+
className: "flex items-center gap-1 px-2.5 py-1 rounded bg-neutral-800 hover:bg-neutral-700 text-neutral-300 hover:text-white border border-neutral-700 transition-colors",
|
|
1717
|
+
title: "Download standalone offline HTML file",
|
|
1718
|
+
children: [
|
|
1719
|
+
/* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1720
|
+
/* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
1721
|
+
/* @__PURE__ */ jsx("polyline", { points: "7 10 12 15 17 10" }),
|
|
1722
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
|
|
1723
|
+
] }),
|
|
1724
|
+
/* @__PURE__ */ jsx("span", { children: "Export HTML" })
|
|
1725
|
+
]
|
|
1726
|
+
}
|
|
1727
|
+
),
|
|
1728
|
+
/* @__PURE__ */ jsx(
|
|
1729
|
+
"button",
|
|
1730
|
+
{
|
|
1731
|
+
onClick: handleToggleFullscreen,
|
|
1732
|
+
className: "p-1 rounded bg-neutral-800 hover:bg-neutral-700 text-neutral-300 hover:text-white border border-neutral-700 transition-colors",
|
|
1733
|
+
title: "Toggle Fullscreen (F)",
|
|
1734
|
+
children: /* @__PURE__ */ jsx("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: isFullscreen ? /* @__PURE__ */ jsx("path", { d: "M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3" }) : /* @__PURE__ */ jsx("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" }) })
|
|
1735
|
+
}
|
|
1736
|
+
)
|
|
1737
|
+
] })
|
|
1738
|
+
] }),
|
|
1739
|
+
/* @__PURE__ */ jsx("div", { className: "relative flex-1 w-full h-full min-h-0 bg-black", children: fullHtml ? /* @__PURE__ */ jsx(
|
|
1740
|
+
"iframe",
|
|
1741
|
+
{
|
|
1742
|
+
ref: iframeRef,
|
|
1743
|
+
srcDoc: fullHtml,
|
|
1744
|
+
title: deckTitle,
|
|
1745
|
+
sandbox: "allow-scripts allow-same-origin allow-popups allow-forms",
|
|
1746
|
+
className: "w-full h-full border-0 block"
|
|
1747
|
+
}
|
|
1748
|
+
) : /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center text-neutral-500 text-sm", children: "No slide deck content loaded." }) })
|
|
1749
|
+
]
|
|
1750
|
+
}
|
|
1751
|
+
);
|
|
1752
|
+
};
|
|
1497
1753
|
|
|
1498
|
-
export { DeckView, NavigationBar, PresentationView, PresenterNotesDrawer, SlideDesignOverlay, SlideViewer, ThemeSwitcher, useSlideState };
|
|
1754
|
+
export { DeckView, HtmlSlideViewer, NavigationBar, PresentationView, PresenterNotesDrawer, SlideDesignOverlay, SlideViewer, ThemeSwitcher, useSlideState };
|
|
1499
1755
|
//# sourceMappingURL=index.js.map
|
|
1500
1756
|
//# sourceMappingURL=index.js.map
|