nextjs-slides 0.6.1 → 0.8.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 +58 -44
- package/dist/cn.d.ts +1 -0
- package/dist/cn.js.map +1 -1
- package/dist/get-slide.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +9 -2
- package/dist/index.js.map +1 -1
- package/dist/parse-speaker-notes.js.map +1 -1
- package/dist/primitives.d.ts +134 -12
- package/dist/primitives.js +152 -36
- package/dist/primitives.js.map +1 -1
- package/dist/slide-deck.d.ts +29 -0
- package/dist/slide-deck.js +25 -5
- package/dist/slide-deck.js.map +1 -1
- package/dist/slide-demo-content.d.ts +7 -0
- package/dist/slide-demo-content.js +3 -1
- package/dist/slide-demo-content.js.map +1 -1
- package/dist/slide-link.d.ts +11 -0
- package/dist/slide-link.js.map +1 -1
- package/dist/slide-notes-view.js +7 -1
- package/dist/slide-notes-view.js.map +1 -1
- package/dist/slides.css +39 -34
- package/dist/types.d.ts +3 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -28,7 +28,6 @@ Open http://localhost:3000 — choose "Geist deck" or "Alternate deck" (Playfair
|
|
|
28
28
|
|
|
29
29
|
Peer dependencies: `next >=15`, `react >=19`, `tailwindcss >=4`.
|
|
30
30
|
|
|
31
|
-
|
|
32
31
|
## Quick Start
|
|
33
32
|
|
|
34
33
|
### 1. Import the stylesheet
|
|
@@ -36,13 +35,11 @@ Peer dependencies: `next >=15`, `react >=19`, `tailwindcss >=4`.
|
|
|
36
35
|
In your root layout or global CSS:
|
|
37
36
|
|
|
38
37
|
```css
|
|
39
|
-
@import
|
|
40
|
-
@import
|
|
41
|
-
|
|
42
|
-
@source "../node_modules/nextjs-slides/dist";
|
|
38
|
+
@import 'tailwindcss';
|
|
39
|
+
@import 'nextjs-slides/styles.css';
|
|
43
40
|
```
|
|
44
41
|
|
|
45
|
-
The `@source` directive tells Tailwind v4 to scan the library for
|
|
42
|
+
The stylesheet includes an `@source` directive that tells Tailwind v4 to scan the library's component files for utility classes — no extra configuration needed.
|
|
46
43
|
|
|
47
44
|
### 2. Define your slides
|
|
48
45
|
|
|
@@ -54,7 +51,7 @@ import {
|
|
|
54
51
|
SlideSubtitle,
|
|
55
52
|
SlideBadge,
|
|
56
53
|
SlideCode,
|
|
57
|
-
} from
|
|
54
|
+
} from 'nextjs-slides';
|
|
58
55
|
|
|
59
56
|
export const slides = [
|
|
60
57
|
<Slide key="intro">
|
|
@@ -75,8 +72,8 @@ console.log(greeting);`}</SlideCode>
|
|
|
75
72
|
|
|
76
73
|
```tsx
|
|
77
74
|
// app/slides/layout.tsx
|
|
78
|
-
import { SlideDeck } from
|
|
79
|
-
import { slides } from
|
|
75
|
+
import { SlideDeck } from 'nextjs-slides';
|
|
76
|
+
import { slides } from './slides';
|
|
80
77
|
|
|
81
78
|
export default function SlidesLayout({
|
|
82
79
|
children,
|
|
@@ -93,17 +90,17 @@ export default function SlidesLayout({
|
|
|
93
90
|
|
|
94
91
|
```tsx
|
|
95
92
|
// app/slides/page.tsx
|
|
96
|
-
import { redirect } from
|
|
93
|
+
import { redirect } from 'next/navigation';
|
|
97
94
|
|
|
98
95
|
export default function SlidesPage() {
|
|
99
|
-
redirect(
|
|
96
|
+
redirect('/slides/1');
|
|
100
97
|
}
|
|
101
98
|
```
|
|
102
99
|
|
|
103
100
|
```tsx
|
|
104
101
|
// app/slides/[page]/page.tsx
|
|
105
|
-
import { getSlide, generateSlideParams } from
|
|
106
|
-
import { slides } from
|
|
102
|
+
import { getSlide, generateSlideParams } from 'nextjs-slides';
|
|
103
|
+
import { slides } from '../slides';
|
|
107
104
|
|
|
108
105
|
export const generateStaticParams = () => generateSlideParams(slides);
|
|
109
106
|
|
|
@@ -120,24 +117,25 @@ That's it. Navigate to `/slides` and you have a full slide deck.
|
|
|
120
117
|
|
|
121
118
|
## `<SlideDeck>` Props
|
|
122
119
|
|
|
123
|
-
| Prop | Type | Default | Description
|
|
124
|
-
| -------------- | --------------------------------- | ------------ |
|
|
125
|
-
| `slides` | `ReactNode[]` | **required** | Your slides array
|
|
126
|
-
| `speakerNotes` | `(string \| ReactNode \| null)[]` | — | Notes per slide (same index). See Speaker Notes below.
|
|
127
|
-
| `syncEndpoint` | `string` | — | API route for presenter ↔ phone sync.
|
|
128
|
-
| `basePath` | `string` | `"/slides"` | URL prefix for slide routes
|
|
129
|
-
| `exitUrl` | `string` | — | URL for exit button (×). Shows in top-right when set.
|
|
130
|
-
| `showProgress` | `boolean` | `true` | Show dot progress indicator
|
|
131
|
-
| `showCounter` | `boolean` | `true` | Show "3 / 10" counter
|
|
132
|
-
| `className` | `string` | — | Additional class for the deck container
|
|
133
|
-
| `children` | `React.ReactNode` | **required** | Route content (from Next.js)
|
|
120
|
+
| Prop | Type | Default | Description |
|
|
121
|
+
| -------------- | --------------------------------- | ------------ | ------------------------------------------------------ |
|
|
122
|
+
| `slides` | `ReactNode[]` | **required** | Your slides array |
|
|
123
|
+
| `speakerNotes` | `(string \| ReactNode \| null)[]` | — | Notes per slide (same index). See Speaker Notes below. |
|
|
124
|
+
| `syncEndpoint` | `string` | — | API route for presenter ↔ phone sync. |
|
|
125
|
+
| `basePath` | `string` | `"/slides"` | URL prefix for slide routes |
|
|
126
|
+
| `exitUrl` | `string` | — | URL for exit button (×). Shows in top-right when set. |
|
|
127
|
+
| `showProgress` | `boolean` | `true` | Show dot progress indicator |
|
|
128
|
+
| `showCounter` | `boolean` | `true` | Show "3 / 10" counter |
|
|
129
|
+
| `className` | `string` | — | Additional class for the deck container |
|
|
130
|
+
| `children` | `React.ReactNode` | **required** | Route content (from Next.js) |
|
|
134
131
|
|
|
135
132
|
## Primitives
|
|
136
133
|
|
|
137
134
|
### Layout
|
|
138
135
|
|
|
139
136
|
- **`<Slide>`** — Full-screen slide container with decorative border. Props: `align` (`"center"` | `"left"`), `className`.
|
|
140
|
-
- **`<
|
|
137
|
+
- **`<SlideColumns>`** — Inline two-column grid for use **inside** `<Slide>` when you need a spanning title above two columns. Props: `left`, `right`, `className`.
|
|
138
|
+
- **`<SlideSplitLayout>`** — Full-viewport two-column layout with vertical divider — a **top-level** alternative to `<Slide>` (do not nest inside `<Slide>`). Props: `left`, `right`, `className`.
|
|
141
139
|
|
|
142
140
|
### Typography
|
|
143
141
|
|
|
@@ -196,20 +194,20 @@ Slide 4 notes. Slide 3 had none.
|
|
|
196
194
|
**Leading document title:** If the file starts with `# My Title` (a single heading line), use `stripLeadingTitle: true` so that block isn't treated as slide 1:
|
|
197
195
|
|
|
198
196
|
```ts
|
|
199
|
-
parseSpeakerNotes(markdown, { stripLeadingTitle: true })
|
|
197
|
+
parseSpeakerNotes(markdown, { stripLeadingTitle: true });
|
|
200
198
|
```
|
|
201
199
|
|
|
202
200
|
Parse the file and pass it to `SlideDeck`. Include `syncEndpoint` so the phone can follow along:
|
|
203
201
|
|
|
204
202
|
```tsx
|
|
205
203
|
// app/slides/layout.tsx
|
|
206
|
-
import fs from
|
|
207
|
-
import path from
|
|
208
|
-
import { SlideDeck, parseSpeakerNotes } from
|
|
209
|
-
import { slides } from
|
|
204
|
+
import fs from 'fs';
|
|
205
|
+
import path from 'path';
|
|
206
|
+
import { SlideDeck, parseSpeakerNotes } from 'nextjs-slides';
|
|
207
|
+
import { slides } from './slides';
|
|
210
208
|
|
|
211
209
|
const notes = parseSpeakerNotes(
|
|
212
|
-
fs.readFileSync(path.join(process.cwd(),
|
|
210
|
+
fs.readFileSync(path.join(process.cwd(), 'app/slides/notes.md'), 'utf-8')
|
|
213
211
|
);
|
|
214
212
|
|
|
215
213
|
export default function SlidesLayout({
|
|
@@ -218,7 +216,11 @@ export default function SlidesLayout({
|
|
|
218
216
|
children: React.ReactNode;
|
|
219
217
|
}) {
|
|
220
218
|
return (
|
|
221
|
-
<SlideDeck
|
|
219
|
+
<SlideDeck
|
|
220
|
+
slides={slides}
|
|
221
|
+
speakerNotes={notes}
|
|
222
|
+
syncEndpoint="/api/nxs-sync"
|
|
223
|
+
>
|
|
222
224
|
{children}
|
|
223
225
|
</SlideDeck>
|
|
224
226
|
);
|
|
@@ -237,19 +239,19 @@ Open `/notes` on your phone while presenting on your laptop. The phone shows the
|
|
|
237
239
|
|
|
238
240
|
```ts
|
|
239
241
|
// app/api/nxs-sync/route.ts
|
|
240
|
-
export { GET, POST } from
|
|
242
|
+
export { GET, POST } from 'nextjs-slides/sync';
|
|
241
243
|
```
|
|
242
244
|
|
|
243
245
|
**2. Create the notes page** (same `notes.md`, same `parseSpeakerNotes` — indices must match slides):
|
|
244
246
|
|
|
245
247
|
```tsx
|
|
246
248
|
// app/notes/page.tsx
|
|
247
|
-
import fs from
|
|
248
|
-
import path from
|
|
249
|
-
import { parseSpeakerNotes, SlideNotesView } from
|
|
249
|
+
import fs from 'fs';
|
|
250
|
+
import path from 'path';
|
|
251
|
+
import { parseSpeakerNotes, SlideNotesView } from 'nextjs-slides';
|
|
250
252
|
|
|
251
253
|
const notes = parseSpeakerNotes(
|
|
252
|
-
fs.readFileSync(path.join(process.cwd(),
|
|
254
|
+
fs.readFileSync(path.join(process.cwd(), 'app/slides/notes.md'), 'utf-8')
|
|
253
255
|
);
|
|
254
256
|
|
|
255
257
|
export default function NotesPage() {
|
|
@@ -284,7 +286,12 @@ The notes view auto-follows the deck during slides. Once you tap "Next" past the
|
|
|
284
286
|
Use `basePath` for a different URL, `exitUrl` for an exit button (×), and `className` for scoped font/syntax overrides:
|
|
285
287
|
|
|
286
288
|
```tsx
|
|
287
|
-
<SlideDeck
|
|
289
|
+
<SlideDeck
|
|
290
|
+
slides={slides}
|
|
291
|
+
basePath="/slides-alt"
|
|
292
|
+
exitUrl="/"
|
|
293
|
+
className="slides-alt-deck"
|
|
294
|
+
>
|
|
288
295
|
{children}
|
|
289
296
|
</SlideDeck>
|
|
290
297
|
```
|
|
@@ -316,13 +323,16 @@ Install `geist`, wire the fonts in your layout, and add the theme variables:
|
|
|
316
323
|
|
|
317
324
|
```tsx
|
|
318
325
|
// app/layout.tsx
|
|
319
|
-
import { GeistSans } from
|
|
320
|
-
import { GeistMono } from
|
|
321
|
-
import { GeistPixelSquare } from
|
|
326
|
+
import { GeistSans } from 'geist/font/sans';
|
|
327
|
+
import { GeistMono } from 'geist/font/mono';
|
|
328
|
+
import { GeistPixelSquare } from 'geist/font/pixel';
|
|
322
329
|
|
|
323
330
|
export default function RootLayout({ children }) {
|
|
324
331
|
return (
|
|
325
|
-
<html
|
|
332
|
+
<html
|
|
333
|
+
lang="en"
|
|
334
|
+
className={`${GeistSans.variable} ${GeistMono.variable} ${GeistPixelSquare.variable}`}
|
|
335
|
+
>
|
|
326
336
|
<body className={GeistSans.className}>{children}</body>
|
|
327
337
|
</html>
|
|
328
338
|
);
|
|
@@ -333,7 +343,9 @@ export default function RootLayout({ children }) {
|
|
|
333
343
|
/* globals.css @theme inline */
|
|
334
344
|
--font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
|
|
335
345
|
--font-mono: var(--font-geist-mono), ui-monospace, monospace;
|
|
336
|
-
--font-pixel:
|
|
346
|
+
--font-pixel:
|
|
347
|
+
var(--font-geist-pixel-square), var(--font-geist-sans), ui-sans-serif,
|
|
348
|
+
system-ui, sans-serif;
|
|
337
349
|
```
|
|
338
350
|
|
|
339
351
|
Use `className="font-pixel"` on primitives where you want the pixel display font.
|
|
@@ -348,10 +360,12 @@ Slide transitions use the React 19 `<ViewTransition>` component with `addTransit
|
|
|
348
360
|
|
|
349
361
|
**Split layout not stacking on small screens** — Import `nextjs-slides/styles.css` without a layer: `@import "nextjs-slides/styles.css"` (not `layer(base)`). Layered imports can be overridden by Tailwind utilities. Also ensure the library CSS loads after Tailwind.
|
|
350
362
|
|
|
351
|
-
|
|
363
|
+
**Slide utility classes not applying** — The library's stylesheet includes `@source "./*.js"` so Tailwind v4 automatically scans the library's component files. If styles still don't apply, make sure `nextjs-slides/styles.css` is imported _after_ `tailwindcss` in your CSS. As a fallback, you can manually add `@source "../node_modules/nextjs-slides/dist"` (path relative to your CSS file) in your global CSS.
|
|
352
364
|
|
|
353
365
|
**SlideCode error "Could not find the language '…'"** — Only JavaScript, TypeScript, and HTML/XML are registered. Unrecognized file extensions in the `title` prop (e.g. `.terminal`, `.sh`, `.py`) will fall back to TypeScript highlighting. If you previously saw this error, update the package — the fix gracefully handles unknown languages instead of throwing.
|
|
354
366
|
|
|
367
|
+
**`SlideSplitLayout` nested inside `Slide` breaks layout** — `SlideSplitLayout` is a full-viewport component (`h-dvh w-dvw`) that replaces `Slide`, not a child of it. Nesting it inside `Slide` creates a viewport-sized container inside another viewport-sized container with padding, which overflows. If you need a title above two columns, use `<SlideColumns>` inside `<Slide>` instead.
|
|
368
|
+
|
|
355
369
|
**Exit animation (deck-unveil) not running** — Ensure `SlideDeck` is the direct child of the layout. Wrapping it in a `<div>` can prevent the ViewTransition exit from firing. Use the `className` prop for scoped styling instead.
|
|
356
370
|
|
|
357
371
|
**Notes out of sync** — Ensure `syncEndpoint` is set and both layout and notes page use the same `notes.md`. On serverless (Vercel), in-memory sync can hit different instances; use a shared store for production.
|
package/dist/cn.d.ts
CHANGED
package/dist/cn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cn.ts"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":"AAAA,SAAS,YAA6B;AACtC,SAAS,eAAe;
|
|
1
|
+
{"version":3,"sources":["../src/cn.ts"],"sourcesContent":["import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/** Merge Tailwind classes with `clsx` + `tailwind-merge` (internal utility). */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":"AAAA,SAAS,YAA6B;AACtC,SAAS,eAAe;AAGjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;","names":[]}
|
package/dist/get-slide.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/get-slide.tsx"],"sourcesContent":["import { notFound } from 'next/navigation';\n\n/**\n * Resolves the current slide from params and the slides array.\n * Use in your `[page]/page.tsx` dynamic route.\n *\n * @example\n * ```tsx\n * import { getSlide } from 'nextjs-slides';\n * import { slides } from '../slides';\n *\n * export default async function SlidePage({ params }: { params: Promise<{ page: string }> }) {\n * return getSlide(await params, slides);\n * }\n * ```\n */\nexport function getSlide(params: { page: string }
|
|
1
|
+
{"version":3,"sources":["../src/get-slide.tsx"],"sourcesContent":["import { notFound } from 'next/navigation';\n\n/**\n * Resolves the current slide from params and the slides array.\n * Use in your `[page]/page.tsx` dynamic route.\n *\n * @example\n * ```tsx\n * import { getSlide } from 'nextjs-slides';\n * import { slides } from '../slides';\n *\n * export default async function SlidePage({ params }: { params: Promise<{ page: string }> }) {\n * return getSlide(await params, slides);\n * }\n * ```\n */\nexport function getSlide(\n params: { page: string },\n slides: React.ReactNode[]\n): React.ReactNode {\n const index = Number(params.page) - 1;\n\n if (isNaN(index) || index < 0 || index >= slides.length) {\n notFound();\n }\n\n return slides[index];\n}\n\n/**\n * Generates static params for all slides. Use with `generateStaticParams`.\n *\n * @example\n * ```tsx\n * import { generateSlideParams } from 'nextjs-slides';\n * import { slides } from '../slides';\n *\n * export const generateStaticParams = () => generateSlideParams(slides);\n * ```\n */\nexport function generateSlideParams(slides: React.ReactNode[]) {\n return slides.map((_, i) => ({ page: String(i + 1) }));\n}\n"],"mappings":"AAAA,SAAS,gBAAgB;AAgBlB,SAAS,SACd,QACA,QACiB;AACjB,QAAM,QAAQ,OAAO,OAAO,IAAI,IAAI;AAEpC,MAAI,MAAM,KAAK,KAAK,QAAQ,KAAK,SAAS,OAAO,QAAQ;AACvD,aAAS;AAAA,EACX;AAEA,SAAO,OAAO,KAAK;AACrB;AAaO,SAAS,oBAAoB,QAA2B;AAC7D,SAAO,OAAO,IAAI,CAAC,GAAG,OAAO,EAAE,MAAM,OAAO,IAAI,CAAC,EAAE,EAAE;AACvD;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { SlideDeck } from './slide-deck.js';
|
|
2
2
|
export { generateSlideParams, getSlide } from './get-slide.js';
|
|
3
|
-
export { Slide, SlideBadge, SlideCode, SlideDemo, SlideHeaderBadge, SlideList, SlideListItem, SlideNote, SlideSpeaker, SlideSpeakerGrid, SlideSpeakerList, SlideSplitLayout, SlideStatement, SlideStatementList, SlideSubtitle, SlideTitle } from './primitives.js';
|
|
3
|
+
export { Slide, SlideBadge, SlideCode, SlideColumns, SlideDemo, SlideHeaderBadge, SlideList, SlideListItem, SlideNote, SlideSpeaker, SlideSpeakerGrid, SlideSpeakerList, SlideSplitLayout, SlideStatement, SlideStatementList, SlideSubtitle, SlideTitle } from './primitives.js';
|
|
4
4
|
export { SlideLink } from './slide-link.js';
|
|
5
5
|
export { parseSpeakerNotes } from './parse-speaker-notes.js';
|
|
6
6
|
export { SlideNotesView } from './slide-notes-view.js';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { SlideDeck } from "./slide-deck";
|
|
2
2
|
import { getSlide, generateSlideParams } from "./get-slide";
|
|
3
|
-
import { Slide, SlideSplitLayout } from "./primitives";
|
|
4
|
-
import {
|
|
3
|
+
import { Slide, SlideColumns, SlideSplitLayout } from "./primitives";
|
|
4
|
+
import {
|
|
5
|
+
SlideTitle,
|
|
6
|
+
SlideSubtitle,
|
|
7
|
+
SlideBadge,
|
|
8
|
+
SlideHeaderBadge,
|
|
9
|
+
SlideNote
|
|
10
|
+
} from "./primitives";
|
|
5
11
|
import { SlideCode, SlideList, SlideListItem, SlideDemo } from "./primitives";
|
|
6
12
|
import { SlideStatementList, SlideStatement } from "./primitives";
|
|
7
13
|
import { SlideSpeaker, SlideSpeakerGrid, SlideSpeakerList } from "./primitives";
|
|
@@ -12,6 +18,7 @@ export {
|
|
|
12
18
|
Slide,
|
|
13
19
|
SlideBadge,
|
|
14
20
|
SlideCode,
|
|
21
|
+
SlideColumns,
|
|
15
22
|
SlideDeck,
|
|
16
23
|
SlideDemo,
|
|
17
24
|
SlideHeaderBadge,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Provider\nexport { SlideDeck } from './slide-deck';\n\n// Routing helpers\nexport { getSlide, generateSlideParams } from './get-slide';\n\n// Primitives — Layout\nexport { Slide, SlideSplitLayout } from './primitives';\n\n// Primitives — Typography\nexport {
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Provider\nexport { SlideDeck } from './slide-deck';\n\n// Routing helpers\nexport { getSlide, generateSlideParams } from './get-slide';\n\n// Primitives — Layout\nexport { Slide, SlideColumns, SlideSplitLayout } from './primitives';\n\n// Primitives — Typography\nexport {\n SlideTitle,\n SlideSubtitle,\n SlideBadge,\n SlideHeaderBadge,\n SlideNote,\n} from './primitives';\n\n// Primitives — Content\nexport { SlideCode, SlideList, SlideListItem, SlideDemo } from './primitives';\n\n// Primitives — Statements\nexport { SlideStatementList, SlideStatement } from './primitives';\n\n// Primitives — Speakers\nexport { SlideSpeaker, SlideSpeakerGrid, SlideSpeakerList } from './primitives';\n\n// Navigation\nexport { SlideLink } from './slide-link';\n\n// Utilities\nexport { parseSpeakerNotes } from './parse-speaker-notes';\n\n// Speaker notes\nexport { SlideNotesView } from './slide-notes-view';\n\n// Types\nexport type { SlideAlign, SlideLinkVariant, SlideDeckConfig } from './types';\n"],"mappings":"AACA,SAAS,iBAAiB;AAG1B,SAAS,UAAU,2BAA2B;AAG9C,SAAS,OAAO,cAAc,wBAAwB;AAGtD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,WAAW,WAAW,eAAe,iBAAiB;AAG/D,SAAS,oBAAoB,sBAAsB;AAGnD,SAAS,cAAc,kBAAkB,wBAAwB;AAGjE,SAAS,iBAAiB;AAG1B,SAAS,yBAAyB;AAGlC,SAAS,sBAAsB;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/parse-speaker-notes.ts"],"sourcesContent":["/**\n * Parse speaker notes from a markdown string.\n *\n * Format: one section per slide, separated by `---` on its own line.\n * Sections map to slides by position: notes[0] = slide 1, notes[1] = slide 2, etc.\n * Empty sections produce `null` (no notes for that slide).\n *\n * @param stripLeadingTitle - If true, removes a leading section that is a single\n * markdown heading (# Title). Use when the file starts with a document title.\n *\n * @example\n * ```md\n * Welcome everyone. This is the opening slide.\n *\n * ---\n *\n * Talk about the base container here.\n *\n * ---\n *\n * ---\n *\n * Slide 4 notes. Slide 3 had none.\n * ```\n *\n * @example\n * ```tsx\n * const notes = parseSpeakerNotes(markdown, { stripLeadingTitle: true });\n * ```\n */\nexport function parseSpeakerNotes(\n markdown: string,\n options?: { stripLeadingTitle?: boolean }
|
|
1
|
+
{"version":3,"sources":["../src/parse-speaker-notes.ts"],"sourcesContent":["/**\n * Parse speaker notes from a markdown string.\n *\n * Format: one section per slide, separated by `---` on its own line.\n * Sections map to slides by position: notes[0] = slide 1, notes[1] = slide 2, etc.\n * Empty sections produce `null` (no notes for that slide).\n *\n * @param stripLeadingTitle - If true, removes a leading section that is a single\n * markdown heading (# Title). Use when the file starts with a document title.\n *\n * @example\n * ```md\n * Welcome everyone. This is the opening slide.\n *\n * ---\n *\n * Talk about the base container here.\n *\n * ---\n *\n * ---\n *\n * Slide 4 notes. Slide 3 had none.\n * ```\n *\n * @example\n * ```tsx\n * const notes = parseSpeakerNotes(markdown, { stripLeadingTitle: true });\n * ```\n */\nexport function parseSpeakerNotes(\n markdown: string,\n options?: { stripLeadingTitle?: boolean }\n): (string | null)[] {\n let sections = markdown.split(/^---$/m).map((section) => {\n const trimmed = section.trim();\n return trimmed.length > 0 ? trimmed : null;\n });\n\n if (\n options?.stripLeadingTitle &&\n sections[0] &&\n /^#+\\s+.+$/.test(sections[0].replace(/\\n.*/s, ''))\n ) {\n sections = sections.slice(1);\n }\n\n return sections;\n}\n"],"mappings":"AA8BO,SAAS,kBACd,UACA,SACmB;AACnB,MAAI,WAAW,SAAS,MAAM,QAAQ,EAAE,IAAI,CAAC,YAAY;AACvD,UAAM,UAAU,QAAQ,KAAK;AAC7B,WAAO,QAAQ,SAAS,IAAI,UAAU;AAAA,EACxC,CAAC;AAED,MACE,SAAS,qBACT,SAAS,CAAC,KACV,YAAY,KAAK,SAAS,CAAC,EAAE,QAAQ,SAAS,EAAE,CAAC,GACjD;AACA,eAAW,SAAS,MAAM,CAAC;AAAA,EAC7B;AAEA,SAAO;AACT;","names":[]}
|
package/dist/primitives.d.ts
CHANGED
|
@@ -1,63 +1,178 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { SlideAlign } from './types.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Full-viewport slide container with centered content and a decorative border.
|
|
6
|
+
*
|
|
7
|
+
* This is the primary slide primitive — use it as a top-level element in
|
|
8
|
+
* the slides array. For a two-column layout that fills the whole viewport,
|
|
9
|
+
* use {@link SlideSplitLayout} instead.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Slide align="left">
|
|
14
|
+
* <SlideTitle>My Slide</SlideTitle>
|
|
15
|
+
* <SlideSubtitle>Supporting text</SlideSubtitle>
|
|
16
|
+
* </Slide>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
4
19
|
declare function Slide({ children, align, className, }: {
|
|
5
20
|
children: React.ReactNode;
|
|
21
|
+
/** Content alignment. `"center"` centers both horizontally and text; `"left"` aligns to the start. */
|
|
6
22
|
align?: SlideAlign;
|
|
7
23
|
className?: string;
|
|
8
24
|
}): react_jsx_runtime.JSX.Element;
|
|
25
|
+
/**
|
|
26
|
+
* Inline two-column grid for use **inside** a `Slide`.
|
|
27
|
+
*
|
|
28
|
+
* Use this when you need a title or other content above two columns.
|
|
29
|
+
* For a full-viewport two-column slide, use `SlideSplitLayout` instead.
|
|
30
|
+
*/
|
|
31
|
+
declare function SlideColumns({ left, right, className, }: {
|
|
32
|
+
left: React.ReactNode;
|
|
33
|
+
right: React.ReactNode;
|
|
34
|
+
className?: string;
|
|
35
|
+
}): react_jsx_runtime.JSX.Element;
|
|
36
|
+
/**
|
|
37
|
+
* Full-viewport two-column slide — a **top-level** alternative to `Slide`.
|
|
38
|
+
*
|
|
39
|
+
* Do **not** nest this inside `Slide`; it renders its own `h-dvh w-dvw`
|
|
40
|
+
* container, border, and padding. To combine a title with two columns,
|
|
41
|
+
* use `SlideColumns` inside a `Slide` instead.
|
|
42
|
+
*/
|
|
9
43
|
declare function SlideSplitLayout({ left, right, className, }: {
|
|
10
44
|
left: React.ReactNode;
|
|
11
45
|
right: React.ReactNode;
|
|
12
46
|
className?: string;
|
|
13
47
|
}): react_jsx_runtime.JSX.Element;
|
|
14
|
-
|
|
48
|
+
/**
|
|
49
|
+
* Primary heading for a slide. Renders an `<h1>` with responsive sizing
|
|
50
|
+
* that scales from `text-4xl` to `text-7xl` across breakpoints.
|
|
51
|
+
*
|
|
52
|
+
* Override the default size with `className` (e.g. `className="text-3xl sm:text-4xl"`).
|
|
53
|
+
*/
|
|
54
|
+
declare function SlideTitle({ children, className, }: {
|
|
15
55
|
children: React.ReactNode;
|
|
16
56
|
className?: string;
|
|
17
57
|
}): react_jsx_runtime.JSX.Element;
|
|
18
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Secondary text below a title. Renders a `<p>` in a muted foreground color
|
|
60
|
+
* with responsive sizing (`text-lg` to `text-2xl`).
|
|
61
|
+
*/
|
|
62
|
+
declare function SlideSubtitle({ children, className, }: {
|
|
19
63
|
children: React.ReactNode;
|
|
20
64
|
className?: string;
|
|
21
65
|
}): react_jsx_runtime.JSX.Element;
|
|
22
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Small pill-shaped label, typically placed above a title to categorise
|
|
68
|
+
* the slide (e.g. component name, topic tag).
|
|
69
|
+
*/
|
|
70
|
+
declare function SlideBadge({ children, className, }: {
|
|
23
71
|
children: React.ReactNode;
|
|
24
72
|
className?: string;
|
|
25
73
|
}): react_jsx_runtime.JSX.Element;
|
|
26
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Italic accent text for slide headers — use for event names, series labels,
|
|
76
|
+
* or other branding above the title.
|
|
77
|
+
*/
|
|
78
|
+
declare function SlideHeaderBadge({ children, className, }: {
|
|
27
79
|
children: React.ReactNode;
|
|
28
80
|
className?: string;
|
|
29
81
|
}): react_jsx_runtime.JSX.Element;
|
|
30
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Syntax-highlighted code block powered by highlight.js.
|
|
84
|
+
*
|
|
85
|
+
* Pass code as a **string** child. The language is auto-detected from the
|
|
86
|
+
* `title` file extension (e.g. `"example.tsx"` → TypeScript); falls back
|
|
87
|
+
* to TypeScript when unspecified. Supports JS, TS, JSX, and TSX.
|
|
88
|
+
*
|
|
89
|
+
* Theme colours are controlled by CSS custom properties (`--sh-*` / `--nxs-code-*`)
|
|
90
|
+
* defined in `nextjs-slides/styles.css`. Override them in `:root` or `.dark`.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```tsx
|
|
94
|
+
* <SlideCode title="api.ts">{`export async function fetchData() {
|
|
95
|
+
* return fetch('/api/data');
|
|
96
|
+
* }`}</SlideCode>
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
declare function SlideCode({ children, className, title, }: {
|
|
100
|
+
/** Code string to highlight. Leading/trailing whitespace is trimmed automatically. */
|
|
31
101
|
children: string;
|
|
32
102
|
className?: string;
|
|
103
|
+
/** File name shown above the code block. Its extension determines the highlight language. */
|
|
33
104
|
title?: string;
|
|
34
105
|
}): react_jsx_runtime.JSX.Element;
|
|
35
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Bullet-point list container. Wrap {@link SlideListItem} children inside this.
|
|
108
|
+
*/
|
|
109
|
+
declare function SlideList({ children, className, }: {
|
|
36
110
|
children: React.ReactNode;
|
|
37
111
|
className?: string;
|
|
38
112
|
}): react_jsx_runtime.JSX.Element;
|
|
39
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Single bullet item inside a {@link SlideList}. Renders a small dot
|
|
115
|
+
* followed by the content.
|
|
116
|
+
*/
|
|
117
|
+
declare function SlideListItem({ children, className, }: {
|
|
40
118
|
children: React.ReactNode;
|
|
41
119
|
className?: string;
|
|
42
120
|
}): react_jsx_runtime.JSX.Element;
|
|
43
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Small footnote text in a faded colour, typically placed at the bottom
|
|
123
|
+
* of a slide for annotations or caveats.
|
|
124
|
+
*/
|
|
125
|
+
declare function SlideNote({ children, className, }: {
|
|
44
126
|
children: React.ReactNode;
|
|
45
127
|
className?: string;
|
|
46
128
|
}): react_jsx_runtime.JSX.Element;
|
|
129
|
+
/**
|
|
130
|
+
* Live interactive component embed. Keyboard navigation (arrow keys, space)
|
|
131
|
+
* is disabled while focus is inside the demo area so the embedded component
|
|
132
|
+
* can handle its own input.
|
|
133
|
+
*
|
|
134
|
+
* The container tracks its maximum height to prevent layout jumps when the
|
|
135
|
+
* child re-renders with different content sizes.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```tsx
|
|
139
|
+
* <SlideDemo label="Live counter">
|
|
140
|
+
* <Counter />
|
|
141
|
+
* </SlideDemo>
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
47
144
|
declare function SlideDemo({ children, className, label, }: {
|
|
48
145
|
children: React.ReactNode;
|
|
49
146
|
className?: string;
|
|
147
|
+
/** Optional uppercase label shown above the demo area. */
|
|
50
148
|
label?: string;
|
|
51
149
|
}): react_jsx_runtime.JSX.Element;
|
|
52
|
-
|
|
150
|
+
/**
|
|
151
|
+
* Container for {@link SlideStatement} items. Adds border separators between
|
|
152
|
+
* statements automatically.
|
|
153
|
+
*/
|
|
154
|
+
declare function SlideStatementList({ children, className, }: {
|
|
53
155
|
children: React.ReactNode;
|
|
54
156
|
className?: string;
|
|
55
157
|
}): react_jsx_runtime.JSX.Element;
|
|
158
|
+
/**
|
|
159
|
+
* Title + description pair for structured content blocks.
|
|
160
|
+
* Use inside a {@link SlideStatementList} for automatic border separators.
|
|
161
|
+
*/
|
|
56
162
|
declare function SlideStatement({ title, description, className, }: {
|
|
163
|
+
/** Bold heading text. */
|
|
57
164
|
title: string;
|
|
165
|
+
/** Optional muted description below the title. */
|
|
58
166
|
description?: string;
|
|
59
167
|
className?: string;
|
|
60
168
|
}): react_jsx_runtime.JSX.Element;
|
|
169
|
+
/**
|
|
170
|
+
* Speaker card with an avatar circle, name, and role/title.
|
|
171
|
+
* When `avatar` is omitted a placeholder circle is shown.
|
|
172
|
+
*
|
|
173
|
+
* Use inside {@link SlideSpeakerGrid} or {@link SlideSpeakerList} to
|
|
174
|
+
* lay out multiple speakers.
|
|
175
|
+
*/
|
|
61
176
|
declare function SlideSpeaker({ name, title, avatar, className, }: {
|
|
62
177
|
name: string;
|
|
63
178
|
title: string;
|
|
@@ -65,13 +180,20 @@ declare function SlideSpeaker({ name, title, avatar, className, }: {
|
|
|
65
180
|
avatar?: string;
|
|
66
181
|
className?: string;
|
|
67
182
|
}): react_jsx_runtime.JSX.Element;
|
|
68
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Two-column responsive grid for laying out {@link SlideSpeaker} cards
|
|
185
|
+
* side by side (stacks to one column on small screens).
|
|
186
|
+
*/
|
|
187
|
+
declare function SlideSpeakerGrid({ children, className, }: {
|
|
69
188
|
children: React.ReactNode;
|
|
70
189
|
className?: string;
|
|
71
190
|
}): react_jsx_runtime.JSX.Element;
|
|
72
|
-
|
|
191
|
+
/**
|
|
192
|
+
* Vertical stack layout for {@link SlideSpeaker} cards.
|
|
193
|
+
*/
|
|
194
|
+
declare function SlideSpeakerList({ children, className, }: {
|
|
73
195
|
children: React.ReactNode;
|
|
74
196
|
className?: string;
|
|
75
197
|
}): react_jsx_runtime.JSX.Element;
|
|
76
198
|
|
|
77
|
-
export { Slide, SlideBadge, SlideCode, SlideDemo, SlideHeaderBadge, SlideList, SlideListItem, SlideNote, SlideSpeaker, SlideSpeakerGrid, SlideSpeakerList, SlideSplitLayout, SlideStatement, SlideStatementList, SlideSubtitle, SlideTitle };
|
|
199
|
+
export { Slide, SlideBadge, SlideCode, SlideColumns, SlideDemo, SlideHeaderBadge, SlideList, SlideListItem, SlideNote, SlideSpeaker, SlideSpeakerGrid, SlideSpeakerList, SlideSplitLayout, SlideStatement, SlideStatementList, SlideSubtitle, SlideTitle };
|