@thanh01.pmt/presentation-kit 0.1.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 +548 -0
- package/dist/chunk-N4Q6GUAQ.cjs +1255 -0
- package/dist/chunk-N4Q6GUAQ.cjs.map +1 -0
- package/dist/chunk-RCHOTRWI.js +1231 -0
- package/dist/chunk-RCHOTRWI.js.map +1 -0
- package/dist/click-css-CadkoJ_A.d.cts +244 -0
- package/dist/click-css-CadkoJ_A.d.ts +244 -0
- package/dist/index.cjs +126 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +86 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.cjs +788 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +269 -0
- package/dist/react/index.d.ts +269 -0
- package/dist/react/index.js +750 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
# @learnwell/presentation-kit
|
|
2
|
+
|
|
3
|
+
> Standalone **client-side** slide rendering engine. Import Marp markdown, get fully rendered 16:9 slides with syntax highlighting, Mermaid diagrams, and custom themes — **zero server roundtrip**.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
npm install @learnwell/presentation-kit
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Table of Contents
|
|
12
|
+
|
|
13
|
+
- [Installation](#installation)
|
|
14
|
+
- [Imports — Two Subpaths](#imports--two-subpaths)
|
|
15
|
+
- [Quick Start](#quick-start)
|
|
16
|
+
- [Headless (Core Only)](#headless-core-only)
|
|
17
|
+
- [React UI (Ready-to-Use)](#react-ui-ready-to-use)
|
|
18
|
+
- [API Reference — Core](#api-reference--core)
|
|
19
|
+
- [`renderSlide()`](#renderslidemarkdown-options)
|
|
20
|
+
- [`renderSlideAsync()`](#renderslideasyncmarkdown-options)
|
|
21
|
+
- [`createEngine()`](#createengineconfig)
|
|
22
|
+
- [`defineTheme()`](#definetheme-definition)
|
|
23
|
+
- [`renderMermaidDiagrams()`](#rendermermaidchartscontainer-theme)
|
|
24
|
+
- [`detectMermaidBlocks()`](#detectmermaidblockhtml)
|
|
25
|
+
- [`highlightCodeBlocks()`](#highlightcodeblockhtml-theme)
|
|
26
|
+
- [`convertTextArrows()`](#converttextarrowstext)
|
|
27
|
+
- [`extractMarpSource()`](#extractmarpsourceraw)
|
|
28
|
+
- [API Reference — React](#api-reference--react)
|
|
29
|
+
- [`<SlideViewer />`](#slideviewer)
|
|
30
|
+
- [`<PresentationView />`](#presentationview)
|
|
31
|
+
- [`<DeckView />`](#deckview)
|
|
32
|
+
- [`<ThemeSwitcher />`](#themeswitcher)
|
|
33
|
+
- [`<NavigationBar />`](#navigationbar)
|
|
34
|
+
- [`useSlideState()`](#useslidestate)
|
|
35
|
+
- [Theme System](#theme-system)
|
|
36
|
+
- [Architecture](#architecture)
|
|
37
|
+
- [Bundle Size](#bundle-size)
|
|
38
|
+
- [Package Structure](#package-structure)
|
|
39
|
+
- [Development](#development)
|
|
40
|
+
- [License](#license)
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Monorepo
|
|
48
|
+
pnpm add @learnwell/presentation-kit --workspace
|
|
49
|
+
|
|
50
|
+
# Standalone
|
|
51
|
+
npm install @learnwell/presentation-kit
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Peer dependencies (optional — only needed for React subpath):**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm install react react-dom
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Imports — Two Subpaths
|
|
63
|
+
|
|
64
|
+
The package provides **two import paths** so you only load what you need:
|
|
65
|
+
|
|
66
|
+
| Import path | What you get | Size | When to use |
|
|
67
|
+
|---|---|---|---|
|
|
68
|
+
| `@learnwell/presentation-kit` | Core engine (headless) | ~36KB | You build your own UI |
|
|
69
|
+
| `@learnwell/presentation-kit/react` | Core engine + React UI components | ~52KB | You want ready-to-use viewer |
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
// ✅ Headless — no React dependency
|
|
73
|
+
import { renderSlide, defineTheme } from '@learnwell/presentation-kit';
|
|
74
|
+
|
|
75
|
+
// ✅ React — full UI components
|
|
76
|
+
import { SlideViewer, ThemeSwitcher } from '@learnwell/presentation-kit/react';
|
|
77
|
+
|
|
78
|
+
// ✅ Mix — core engine + custom UI using React hooks
|
|
79
|
+
import { renderSlide, useSlideState } from '@learnwell/presentation-kit/react';
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
> **Tree-shaking:** If you only import `renderSlide` from the React subpath, bundlers will exclude unused UI components.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Quick Start
|
|
87
|
+
|
|
88
|
+
### Headless (Core Only)
|
|
89
|
+
|
|
90
|
+
For apps that want full control over the UI:
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { renderSlide } from '@learnwell/presentation-kit';
|
|
94
|
+
|
|
95
|
+
const result = renderSlide(marpMarkdown, { theme: 'dark' });
|
|
96
|
+
|
|
97
|
+
// Inject into DOM
|
|
98
|
+
container.innerHTML = `<style>${result.css}${result.themeCss}</style>${result.html}`;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### React UI (Ready-to-Use)
|
|
102
|
+
|
|
103
|
+
For apps that want a complete slide viewer out of the box:
|
|
104
|
+
|
|
105
|
+
```tsx
|
|
106
|
+
import { SlideViewer } from '@learnwell/presentation-kit/react';
|
|
107
|
+
|
|
108
|
+
function MyPage() {
|
|
109
|
+
return (
|
|
110
|
+
<SlideViewer
|
|
111
|
+
markdown={marpMarkdown}
|
|
112
|
+
initialTheme="dark"
|
|
113
|
+
showThemeSwitcher
|
|
114
|
+
showNavigation
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
That's it. You get:
|
|
121
|
+
- Theme switching (Dark / Navy / Light)
|
|
122
|
+
- Presentation mode (single slide + keyboard nav)
|
|
123
|
+
- Deck mode (vertical scroll)
|
|
124
|
+
- Mermaid diagram rendering
|
|
125
|
+
- Copy markdown button
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## API Reference — Core
|
|
130
|
+
|
|
131
|
+
### `renderSlide(markdown, options?)`
|
|
132
|
+
|
|
133
|
+
**Synchronous** slide rendering. Returns instantly.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
function renderSlide(markdown: string, options?: SlideRenderOptions): SlideRenderResult;
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
| Param | Type | Default | Description |
|
|
140
|
+
|---|---|---|---|
|
|
141
|
+
| `markdown` | `string` | — | Marp markdown (with `---` separators) |
|
|
142
|
+
| `options.theme` | `'dark' \| 'light' \| 'navy' \| SlideTheme` | `'dark'` | Theme to apply |
|
|
143
|
+
| `options.enableShiki` | `boolean` | `true` | Detect code blocks (sync: detection only) |
|
|
144
|
+
| `options.enableMermaid` | `boolean` | `true` | Detect mermaid blocks |
|
|
145
|
+
| `options.containerId` | `string` | `'marp-container'` | CSS isolation ID |
|
|
146
|
+
|
|
147
|
+
**Returns:** `{ html, css, themeCss, slideCount, mermaidBlocks }`
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### `renderSlideAsync(markdown, options?)`
|
|
152
|
+
|
|
153
|
+
**Async** render with Shiki syntax highlighting applied.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
function renderSlideAsync(markdown: string, options?: SlideRenderOptions): Promise<SlideRenderAsyncResult>;
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Returns:** `{ ...SlideRenderResult, processedHtml }` — HTML with Shiki-highlighted code blocks.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### `createEngine(config?)`
|
|
164
|
+
|
|
165
|
+
Create a reusable engine instance with default options.
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
const engine = createEngine({ theme: 'navy' });
|
|
169
|
+
const result = engine.render(markdown); // defaults to navy theme
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### `defineTheme(definition)`
|
|
175
|
+
|
|
176
|
+
Define a custom theme with full token control.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
const myTheme = defineTheme({
|
|
180
|
+
name: 'corporate',
|
|
181
|
+
tokens: { background: '#fff', text: '#1a1a2e', /* ...24 tokens */ },
|
|
182
|
+
});
|
|
183
|
+
renderSlide(markdown, { theme: myTheme });
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### `renderMermaidDiagrams(container, theme)`
|
|
189
|
+
|
|
190
|
+
Render mermaid diagrams in a DOM container. Browser only (returns early in SSR).
|
|
191
|
+
|
|
192
|
+
```ts
|
|
193
|
+
await renderMermaidDiagrams(document.getElementById('slides'), 'dark');
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
### `detectMermaidBlocks(html)`
|
|
199
|
+
|
|
200
|
+
Detect mermaid blocks in rendered HTML (sync, no DOM needed).
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
const blocks = detectMermaidBlocks(html);
|
|
204
|
+
// blocks: [{ index: 0, code: 'graph TD...', sanitizedCode: '...' }]
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
### `highlightCodeBlocks(html, theme?)`
|
|
210
|
+
|
|
211
|
+
Async Shiki post-processing for code blocks.
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
const highlighted = await highlightCodeBlocks(html, 'dark');
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
### `convertTextArrows(text)`
|
|
220
|
+
|
|
221
|
+
Convert text arrows (`->`, `-->`, `=>`) to Unicode arrows. Preserves code fences.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
### `extractMarpSource(raw)`
|
|
226
|
+
|
|
227
|
+
Extract clean Marp source from wrapped markdown (strips ` ```markdown ` fences, conversational preamble).
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## API Reference — React
|
|
232
|
+
|
|
233
|
+
### `<SlideViewer />`
|
|
234
|
+
|
|
235
|
+
Complete slide viewer with all features. The main entry point for React apps.
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
import { SlideViewer } from '@learnwell/presentation-kit/react';
|
|
239
|
+
|
|
240
|
+
<SlideViewer
|
|
241
|
+
markdown={marpMarkdown} // Marp markdown source
|
|
242
|
+
initialTheme="dark" // 'dark' | 'light' | 'navy' | SlideTheme
|
|
243
|
+
initialMode="presentation" // 'presentation' | 'deck'
|
|
244
|
+
showThemeSwitcher={true} // Show theme toggle buttons
|
|
245
|
+
showNavigation={true} // Show prev/next/mode controls
|
|
246
|
+
enableKeyboard={true} // Enable keyboard navigation
|
|
247
|
+
themeOptions={[...]} // Custom theme options for switcher
|
|
248
|
+
onThemeChange={(theme) => {}} // Theme change callback
|
|
249
|
+
onSlideChange={(index) => {}} // Slide change callback
|
|
250
|
+
onModeChange={(mode) => {}} // Mode change callback
|
|
251
|
+
onRenderComplete={(result) => {}} // Render complete callback
|
|
252
|
+
className="my-viewer" // CSS class for root container
|
|
253
|
+
/>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Features:**
|
|
257
|
+
- Theme switching (Dark / Navy / Light)
|
|
258
|
+
- Presentation mode (single slide, keyboard: ← → Space Home End)
|
|
259
|
+
- Deck mode (vertical scroll of all slides)
|
|
260
|
+
- Mermaid diagram auto-rendering
|
|
261
|
+
- Copy markdown button
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
### `<PresentationView />`
|
|
266
|
+
|
|
267
|
+
Single slide display. Use this when you want to build your own controls.
|
|
268
|
+
|
|
269
|
+
```tsx
|
|
270
|
+
import { PresentationView } from '@learnwell/presentation-kit/react';
|
|
271
|
+
|
|
272
|
+
<PresentationView
|
|
273
|
+
html={result.html}
|
|
274
|
+
css={result.css}
|
|
275
|
+
themeCss={result.themeCss}
|
|
276
|
+
currentIndex={0}
|
|
277
|
+
slideCount={5}
|
|
278
|
+
/>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
### `<DeckView />`
|
|
284
|
+
|
|
285
|
+
Vertical scroll of all slides. Use this when you want to build your own deck UI.
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
import { DeckView } from '@learnwell/presentation-kit/react';
|
|
289
|
+
|
|
290
|
+
<DeckView
|
|
291
|
+
html={result.html}
|
|
292
|
+
css={result.css}
|
|
293
|
+
themeCss={result.themeCss}
|
|
294
|
+
slideCount={5}
|
|
295
|
+
/>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### `<ThemeSwitcher />`
|
|
301
|
+
|
|
302
|
+
Theme toggle buttons. Use this when you want to add theme switching to a custom UI.
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
import { ThemeSwitcher } from '@learnwell/presentation-kit/react';
|
|
306
|
+
|
|
307
|
+
<ThemeSwitcher
|
|
308
|
+
currentTheme="dark"
|
|
309
|
+
onThemeChange={setTheme}
|
|
310
|
+
themes={[
|
|
311
|
+
{ id: 'dark', label: 'Dark' },
|
|
312
|
+
{ id: 'navy', label: 'Navy' },
|
|
313
|
+
{ id: 'light', label: 'Light' },
|
|
314
|
+
]}
|
|
315
|
+
/>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
### `<NavigationBar />`
|
|
321
|
+
|
|
322
|
+
Slide navigation controls (prev/next, selector, mode toggle, copy).
|
|
323
|
+
|
|
324
|
+
```tsx
|
|
325
|
+
import { NavigationBar } from '@learnwell/presentation-kit/react';
|
|
326
|
+
|
|
327
|
+
<NavigationBar
|
|
328
|
+
currentIndex={2}
|
|
329
|
+
slideCount={10}
|
|
330
|
+
onNavigate={setCurrentIndex}
|
|
331
|
+
mode="presentation"
|
|
332
|
+
onModeChange={setMode}
|
|
333
|
+
markdown={rawMarkdown}
|
|
334
|
+
showCopy={true}
|
|
335
|
+
/>
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
### `useSlideState()`
|
|
341
|
+
|
|
342
|
+
Centralized hook for slide state management. Use this when building a fully custom viewer.
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
import { useSlideState } from '@learnwell/presentation-kit/react';
|
|
346
|
+
|
|
347
|
+
function CustomViewer({ markdown }) {
|
|
348
|
+
const {
|
|
349
|
+
currentIndex, // current slide index
|
|
350
|
+
mode, // 'presentation' | 'deck'
|
|
351
|
+
theme, // current theme
|
|
352
|
+
result, // render result (null before first render)
|
|
353
|
+
slideCount, // total slides
|
|
354
|
+
isReady, // true after first render
|
|
355
|
+
goToSlide, // (index) => void
|
|
356
|
+
nextSlide, // () => void
|
|
357
|
+
prevSlide, // () => void
|
|
358
|
+
setMode, // (mode) => void
|
|
359
|
+
setTheme, // (theme) => void
|
|
360
|
+
} = useSlideState({
|
|
361
|
+
markdown,
|
|
362
|
+
initialTheme: 'dark',
|
|
363
|
+
initialMode: 'presentation',
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
// Full control over rendering and UI
|
|
367
|
+
return <div dangerouslySetInnerHTML={{ __html: result?.html ?? '' }} />;
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Theme System
|
|
374
|
+
|
|
375
|
+
### Built-in Themes
|
|
376
|
+
|
|
377
|
+
| Theme | Background | Use Case |
|
|
378
|
+
|---|---|---|
|
|
379
|
+
| `'dark'` | `#14151b` | Developer tools, modern UI |
|
|
380
|
+
| `'light'` | `#ffffff` | Classroom projectors, print |
|
|
381
|
+
| `'navy'` | `#0f172a` | STEM presentations |
|
|
382
|
+
|
|
383
|
+
### Custom Theme
|
|
384
|
+
|
|
385
|
+
```ts
|
|
386
|
+
import { defineTheme, renderSlide } from '@learnwell/presentation-kit';
|
|
387
|
+
|
|
388
|
+
const myTheme = defineTheme({
|
|
389
|
+
name: 'corporate',
|
|
390
|
+
tokens: {
|
|
391
|
+
background: '#ffffff',
|
|
392
|
+
text: '#1a1a2e',
|
|
393
|
+
heading: '#1a1a2e',
|
|
394
|
+
bold: '#1a1a2e',
|
|
395
|
+
link: '#2563eb',
|
|
396
|
+
codeBg: '#f5f5f5',
|
|
397
|
+
codeText: '#27272a',
|
|
398
|
+
inlineCodeBg: '#f5f5f5',
|
|
399
|
+
inlineCodeText: '#27272a',
|
|
400
|
+
codeBorder: 'rgba(0, 0, 0, 0.08)',
|
|
401
|
+
quoteBg: '#f8f9fa',
|
|
402
|
+
quoteBorder: 'rgba(0, 0, 0, 0.15)',
|
|
403
|
+
quoteText: '#27272a',
|
|
404
|
+
tableHeaderBg: '#f8fafc',
|
|
405
|
+
tableBorder: '#e2e8f0',
|
|
406
|
+
tableRowHover: 'rgba(0, 0, 0, 0.02)',
|
|
407
|
+
tableText: '#3f3f46',
|
|
408
|
+
cardBorder: '1px solid rgba(0, 0, 0, 0.08)',
|
|
409
|
+
cardShadow: '0 4px 16px -2px rgba(0, 0, 0, 0.05)',
|
|
410
|
+
meta: '#71717a',
|
|
411
|
+
mermaidDark: false,
|
|
412
|
+
mermaidVariables: { /* mermaid theme vars */ },
|
|
413
|
+
mermaidThemeCSS: '/* mermaid CSS overrides */',
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
renderSlide(markdown, { theme: myTheme });
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Architecture
|
|
423
|
+
|
|
424
|
+
```
|
|
425
|
+
@learnwell/presentation-kit ← Headless core (no React)
|
|
426
|
+
│
|
|
427
|
+
├── renderSlide() ← Sync render
|
|
428
|
+
├── renderSlideAsync() ← Async render (Shiki)
|
|
429
|
+
├── createEngine() ← Reusable instance
|
|
430
|
+
├── defineTheme() ← Custom themes
|
|
431
|
+
├── renderMermaidDiagrams() ← DOM mermaid rendering
|
|
432
|
+
├── detectMermaidBlocks() ← Mermaid detection
|
|
433
|
+
├── highlightCodeBlocks() ← Shiki post-process
|
|
434
|
+
├── convertTextArrows() ← Arrow utility
|
|
435
|
+
└── extractMarpSource() ← Source cleanup
|
|
436
|
+
|
|
437
|
+
@learnwell/presentation-kit/react ← React UI (optional)
|
|
438
|
+
│
|
|
439
|
+
├── <SlideViewer /> ← Complete viewer (all-in-one)
|
|
440
|
+
├── <PresentationView /> ← Single slide display
|
|
441
|
+
├── <DeckView /> ← Vertical scroll
|
|
442
|
+
├── <ThemeSwitcher /> ← Theme toggle buttons
|
|
443
|
+
├── <NavigationBar /> ← Navigation controls
|
|
444
|
+
└── useSlideState() ← State management hook
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Render pipeline:**
|
|
448
|
+
|
|
449
|
+
```
|
|
450
|
+
markdown
|
|
451
|
+
→ extractMarpSource() strip wrappers
|
|
452
|
+
→ convertTextArrows() → → →, --> → ⟶
|
|
453
|
+
→ marp.render() client-side Marp-core
|
|
454
|
+
→ detectMermaidBlocks() find mermaid syntax
|
|
455
|
+
→ [async] Shiki post-process code blocks
|
|
456
|
+
→ generateScopedCss() theme typography CSS
|
|
457
|
+
→ return { html, css, themeCss, slideCount, mermaidBlocks }
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## Bundle Size
|
|
463
|
+
|
|
464
|
+
| Import | Sync | Lazy | Total |
|
|
465
|
+
|---|---|---|---|
|
|
466
|
+
| Core only (`@learnwell/presentation-kit`) | ~36KB | — | **~36KB** |
|
|
467
|
+
| React UI (`@learnwell/presentation-kit/react`) | ~52KB | — | **~52KB** |
|
|
468
|
+
| + Shiki | +0 | ~3MB | ~3MB |
|
|
469
|
+
| + Mermaid | +0 | ~2MB | ~2MB |
|
|
470
|
+
|
|
471
|
+
> Core and React are bundled together in the React subpath. Shiki and Mermaid are lazy-loaded.
|
|
472
|
+
|
|
473
|
+
---
|
|
474
|
+
|
|
475
|
+
## Package Structure
|
|
476
|
+
|
|
477
|
+
```
|
|
478
|
+
packages/presentation-kit/
|
|
479
|
+
├── src/
|
|
480
|
+
│ ├── core/ # Headless rendering engine
|
|
481
|
+
│ │ ├── render.ts
|
|
482
|
+
│ │ ├── arrow-converter.ts
|
|
483
|
+
│ │ └── source-extractor.ts
|
|
484
|
+
│ ├── plugins/ # Lazy-loaded plugins
|
|
485
|
+
│ │ ├── shiki.ts
|
|
486
|
+
│ │ └── mermaid.ts
|
|
487
|
+
│ ├── themes/ # Theme system
|
|
488
|
+
│ │ ├── dark.ts / light.ts / navy.ts
|
|
489
|
+
│ │ ├── scoped-css.ts
|
|
490
|
+
│ │ └── index.ts
|
|
491
|
+
│ ├── react/ # React UI (subpath export)
|
|
492
|
+
│ │ ├── components/
|
|
493
|
+
│ │ │ ├── SlideViewer.tsx
|
|
494
|
+
│ │ │ ├── PresentationView.tsx
|
|
495
|
+
│ │ │ ├── DeckView.tsx
|
|
496
|
+
│ │ │ ├── ThemeSwitcher.tsx
|
|
497
|
+
│ │ │ └── NavigationBar.tsx
|
|
498
|
+
│ │ ├── hooks/
|
|
499
|
+
│ │ │ └── useSlideState.ts
|
|
500
|
+
│ │ ├── types.ts
|
|
501
|
+
│ │ └── index.ts
|
|
502
|
+
│ ├── engine.ts
|
|
503
|
+
│ ├── types.ts
|
|
504
|
+
│ └── index.ts # Core barrel export
|
|
505
|
+
├── dist/ # Built output
|
|
506
|
+
├── docs/ # Design docs
|
|
507
|
+
├── package.json
|
|
508
|
+
└── README.md
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Development
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
pnpm install
|
|
517
|
+
pnpm typecheck
|
|
518
|
+
pnpm build
|
|
519
|
+
pnpm dev # watch mode
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Input Format
|
|
523
|
+
|
|
524
|
+
Marp-compatible markdown:
|
|
525
|
+
|
|
526
|
+
```markdown
|
|
527
|
+
---
|
|
528
|
+
marp: true
|
|
529
|
+
theme: default
|
|
530
|
+
paginate: true
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
# Slide 1
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
# Slide 2
|
|
538
|
+
|
|
539
|
+
```python
|
|
540
|
+
print("Hello")
|
|
541
|
+
```
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
## License
|
|
547
|
+
|
|
548
|
+
MIT
|