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 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 "tailwindcss";
40
- @import "nextjs-slides/styles.css";
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 class nameswithout it, slide styles won't apply.
42
+ The stylesheet includes an `@source` directive that tells Tailwind v4 to scan the library's component files for utility classesno 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 "nextjs-slides";
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 "nextjs-slides";
79
- import { slides } from "./slides";
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 "next/navigation";
93
+ import { redirect } from 'next/navigation';
97
94
 
98
95
  export default function SlidesPage() {
99
- redirect("/slides/1");
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 "nextjs-slides";
106
- import { slides } from "../slides";
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
- - **`<SlideSplitLayout>`** — Two-column layout with vertical divider. Stacks vertically below 1024px. Props: `left`, `right`, `className`.
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 "fs";
207
- import path from "path";
208
- import { SlideDeck, parseSpeakerNotes } from "nextjs-slides";
209
- import { slides } from "./slides";
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(), "app/slides/notes.md"), "utf-8")
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 slides={slides} speakerNotes={notes} syncEndpoint="/api/nxs-sync">
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 "nextjs-slides/sync";
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 "fs";
248
- import path from "path";
249
- import { parseSpeakerNotes, SlideNotesView } from "nextjs-slides";
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(), "app/slides/notes.md"), "utf-8")
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 slides={slides} basePath="/slides-alt" exitUrl="/" className="slides-alt-deck">
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 "geist/font/sans";
320
- import { GeistMono } from "geist/font/mono";
321
- import { GeistPixelSquare } from "geist/font/pixel";
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 lang="en" className={`${GeistSans.variable} ${GeistMono.variable} ${GeistPixelSquare.variable}`}>
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: var(--font-geist-pixel-square), var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
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
- **`@source` path not found** — The `@source "../node_modules/nextjs-slides/dist"` path is relative to your CSS file. If your `globals.css` lives in `app/`, use `../node_modules/...`. If it lives in the project root, use `./node_modules/nextjs-slides/dist`.
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
@@ -1,5 +1,6 @@
1
1
  import { ClassValue } from 'clsx';
2
2
 
3
+ /** Merge Tailwind classes with `clsx` + `tailwind-merge` (internal utility). */
3
4
  declare function cn(...inputs: ClassValue[]): string;
4
5
 
5
6
  export { cn };
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;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;","names":[]}
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":[]}
@@ -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 }, slides: React.ReactNode[]): 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,SAAS,QAA0B,QAA4C;AAC7F,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":[]}
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 { SlideTitle, SlideSubtitle, SlideBadge, SlideHeaderBadge, SlideNote } from "./primitives";
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 { SlideTitle, SlideSubtitle, SlideBadge, SlideHeaderBadge, SlideNote } 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,wBAAwB;AAGxC,SAAS,YAAY,eAAe,YAAY,kBAAkB,iBAAiB;AAGnF,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
+ {"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 },\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 (options?.stripLeadingTitle && sections[0] && /^#+\\s+.+$/.test(sections[0].replace(/\\n.*/s, ''))) {\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,MAAI,SAAS,qBAAqB,SAAS,CAAC,KAAK,YAAY,KAAK,SAAS,CAAC,EAAE,QAAQ,SAAS,EAAE,CAAC,GAAG;AACnG,eAAW,SAAS,MAAM,CAAC;AAAA,EAC7B;AAEA,SAAO;AACT;","names":[]}
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":[]}
@@ -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
- declare function SlideTitle({ children, className }: {
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
- declare function SlideSubtitle({ children, className }: {
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
- declare function SlideBadge({ children, className }: {
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
- declare function SlideHeaderBadge({ children, className }: {
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
- declare function SlideCode({ children, className, title }: {
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
- declare function SlideList({ children, className }: {
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
- declare function SlideListItem({ children, className }: {
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
- declare function SlideNote({ children, className }: {
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
- declare function SlideStatementList({ children, className }: {
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
- declare function SlideSpeakerGrid({ children, className }: {
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
- declare function SlideSpeakerList({ children, className }: {
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 };