nextjs-slides 0.6.0 → 0.7.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,8 +35,8 @@ 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";
38
+ @import 'tailwindcss';
39
+ @import 'nextjs-slides/styles.css';
41
40
 
42
41
  @source "../node_modules/nextjs-slides/dist";
43
42
  ```
@@ -54,7 +53,7 @@ import {
54
53
  SlideSubtitle,
55
54
  SlideBadge,
56
55
  SlideCode,
57
- } from "nextjs-slides";
56
+ } from 'nextjs-slides';
58
57
 
59
58
  export const slides = [
60
59
  <Slide key="intro">
@@ -75,8 +74,8 @@ console.log(greeting);`}</SlideCode>
75
74
 
76
75
  ```tsx
77
76
  // app/slides/layout.tsx
78
- import { SlideDeck } from "nextjs-slides";
79
- import { slides } from "./slides";
77
+ import { SlideDeck } from 'nextjs-slides';
78
+ import { slides } from './slides';
80
79
 
81
80
  export default function SlidesLayout({
82
81
  children,
@@ -93,17 +92,17 @@ export default function SlidesLayout({
93
92
 
94
93
  ```tsx
95
94
  // app/slides/page.tsx
96
- import { redirect } from "next/navigation";
95
+ import { redirect } from 'next/navigation';
97
96
 
98
97
  export default function SlidesPage() {
99
- redirect("/slides/1");
98
+ redirect('/slides/1');
100
99
  }
101
100
  ```
102
101
 
103
102
  ```tsx
104
103
  // app/slides/[page]/page.tsx
105
- import { getSlide, generateSlideParams } from "nextjs-slides";
106
- import { slides } from "../slides";
104
+ import { getSlide, generateSlideParams } from 'nextjs-slides';
105
+ import { slides } from '../slides';
107
106
 
108
107
  export const generateStaticParams = () => generateSlideParams(slides);
109
108
 
@@ -120,17 +119,17 @@ That's it. Navigate to `/slides` and you have a full slide deck.
120
119
 
121
120
  ## `<SlideDeck>` Props
122
121
 
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) |
122
+ | Prop | Type | Default | Description |
123
+ | -------------- | --------------------------------- | ------------ | ------------------------------------------------------ |
124
+ | `slides` | `ReactNode[]` | **required** | Your slides array |
125
+ | `speakerNotes` | `(string \| ReactNode \| null)[]` | — | Notes per slide (same index). See Speaker Notes below. |
126
+ | `syncEndpoint` | `string` | — | API route for presenter ↔ phone sync. |
127
+ | `basePath` | `string` | `"/slides"` | URL prefix for slide routes |
128
+ | `exitUrl` | `string` | — | URL for exit button (×). Shows in top-right when set. |
129
+ | `showProgress` | `boolean` | `true` | Show dot progress indicator |
130
+ | `showCounter` | `boolean` | `true` | Show "3 / 10" counter |
131
+ | `className` | `string` | — | Additional class for the deck container |
132
+ | `children` | `React.ReactNode` | **required** | Route content (from Next.js) |
134
133
 
135
134
  ## Primitives
136
135
 
@@ -196,20 +195,20 @@ Slide 4 notes. Slide 3 had none.
196
195
  **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
196
 
198
197
  ```ts
199
- parseSpeakerNotes(markdown, { stripLeadingTitle: true })
198
+ parseSpeakerNotes(markdown, { stripLeadingTitle: true });
200
199
  ```
201
200
 
202
201
  Parse the file and pass it to `SlideDeck`. Include `syncEndpoint` so the phone can follow along:
203
202
 
204
203
  ```tsx
205
204
  // 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";
205
+ import fs from 'fs';
206
+ import path from 'path';
207
+ import { SlideDeck, parseSpeakerNotes } from 'nextjs-slides';
208
+ import { slides } from './slides';
210
209
 
211
210
  const notes = parseSpeakerNotes(
212
- fs.readFileSync(path.join(process.cwd(), "app/slides/notes.md"), "utf-8")
211
+ fs.readFileSync(path.join(process.cwd(), 'app/slides/notes.md'), 'utf-8')
213
212
  );
214
213
 
215
214
  export default function SlidesLayout({
@@ -218,7 +217,11 @@ export default function SlidesLayout({
218
217
  children: React.ReactNode;
219
218
  }) {
220
219
  return (
221
- <SlideDeck slides={slides} speakerNotes={notes} syncEndpoint="/api/nxs-sync">
220
+ <SlideDeck
221
+ slides={slides}
222
+ speakerNotes={notes}
223
+ syncEndpoint="/api/nxs-sync"
224
+ >
222
225
  {children}
223
226
  </SlideDeck>
224
227
  );
@@ -237,19 +240,19 @@ Open `/notes` on your phone while presenting on your laptop. The phone shows the
237
240
 
238
241
  ```ts
239
242
  // app/api/nxs-sync/route.ts
240
- export { GET, POST } from "nextjs-slides/sync";
243
+ export { GET, POST } from 'nextjs-slides/sync';
241
244
  ```
242
245
 
243
246
  **2. Create the notes page** (same `notes.md`, same `parseSpeakerNotes` — indices must match slides):
244
247
 
245
248
  ```tsx
246
249
  // app/notes/page.tsx
247
- import fs from "fs";
248
- import path from "path";
249
- import { parseSpeakerNotes, SlideNotesView } from "nextjs-slides";
250
+ import fs from 'fs';
251
+ import path from 'path';
252
+ import { parseSpeakerNotes, SlideNotesView } from 'nextjs-slides';
250
253
 
251
254
  const notes = parseSpeakerNotes(
252
- fs.readFileSync(path.join(process.cwd(), "app/slides/notes.md"), "utf-8")
255
+ fs.readFileSync(path.join(process.cwd(), 'app/slides/notes.md'), 'utf-8')
253
256
  );
254
257
 
255
258
  export default function NotesPage() {
@@ -284,7 +287,12 @@ The notes view auto-follows the deck during slides. Once you tap "Next" past the
284
287
  Use `basePath` for a different URL, `exitUrl` for an exit button (×), and `className` for scoped font/syntax overrides:
285
288
 
286
289
  ```tsx
287
- <SlideDeck slides={slides} basePath="/slides-alt" exitUrl="/" className="slides-alt-deck">
290
+ <SlideDeck
291
+ slides={slides}
292
+ basePath="/slides-alt"
293
+ exitUrl="/"
294
+ className="slides-alt-deck"
295
+ >
288
296
  {children}
289
297
  </SlideDeck>
290
298
  ```
@@ -316,13 +324,16 @@ Install `geist`, wire the fonts in your layout, and add the theme variables:
316
324
 
317
325
  ```tsx
318
326
  // app/layout.tsx
319
- import { GeistSans } from "geist/font/sans";
320
- import { GeistMono } from "geist/font/mono";
321
- import { GeistPixelSquare } from "geist/font/pixel";
327
+ import { GeistSans } from 'geist/font/sans';
328
+ import { GeistMono } from 'geist/font/mono';
329
+ import { GeistPixelSquare } from 'geist/font/pixel';
322
330
 
323
331
  export default function RootLayout({ children }) {
324
332
  return (
325
- <html lang="en" className={`${GeistSans.variable} ${GeistMono.variable} ${GeistPixelSquare.variable}`}>
333
+ <html
334
+ lang="en"
335
+ className={`${GeistSans.variable} ${GeistMono.variable} ${GeistPixelSquare.variable}`}
336
+ >
326
337
  <body className={GeistSans.className}>{children}</body>
327
338
  </html>
328
339
  );
@@ -333,7 +344,9 @@ export default function RootLayout({ children }) {
333
344
  /* globals.css @theme inline */
334
345
  --font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
335
346
  --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;
347
+ --font-pixel:
348
+ var(--font-geist-pixel-square), var(--font-geist-sans), ui-sans-serif,
349
+ system-ui, sans-serif;
337
350
  ```
338
351
 
339
352
  Use `className="font-pixel"` on primitives where you want the pixel display font.
@@ -346,6 +359,8 @@ Slide transitions use the React 19 `<ViewTransition>` component with `addTransit
346
359
 
347
360
  **SlideCode syntax highlighting looks broken or colorless** — Ensure you import `nextjs-slides/styles.css` in your root layout or global CSS (see Quick Start). The `--sh-*` variables must be in scope for highlight.js tokens to display correctly.
348
361
 
362
+ **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.
363
+
349
364
  **`@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`.
350
365
 
351
366
  **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.
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 };