nextjs-slides 0.8.0 → 0.8.1

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.
@@ -156,7 +156,7 @@ function SlideCode({
156
156
  const lang = title?.split(".").pop();
157
157
  const html = highlightCode(children.trim(), lang);
158
158
  return /* @__PURE__ */ jsxs("div", { className: cn("nxs-code-wrapper", className), children: [
159
- title && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground mb-2 text-xs font-medium tracking-wider uppercase", children: title }),
159
+ title && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground mb-2 text-sm font-medium tracking-wider uppercase", children: title }),
160
160
  /* @__PURE__ */ jsx("pre", { className: "nxs-code-block", children: /* @__PURE__ */ jsx("code", { dangerouslySetInnerHTML: { __html: html } }) })
161
161
  ] });
162
162
  }
@@ -194,7 +194,7 @@ function SlideNote({
194
194
  children,
195
195
  className
196
196
  }) {
197
- return /* @__PURE__ */ jsx("p", { className: cn("text-muted-foreground/50 text-sm", className), children });
197
+ return /* @__PURE__ */ jsx("p", { className: cn("text-muted-foreground text-base sm:text-lg", className), children });
198
198
  }
199
199
  function SlideDemo({
200
200
  children,
@@ -207,7 +207,7 @@ function SlideDemo({
207
207
  "data-slide-interactive": true,
208
208
  className: cn("min-w-0 w-full max-w-2xl", className),
209
209
  children: [
210
- label && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground mb-2 text-xs font-medium tracking-wider uppercase", children: label }),
210
+ label && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground mb-2 text-sm font-medium tracking-wider uppercase", children: label }),
211
211
  /* @__PURE__ */ jsx("div", { className: "border-foreground/10 bg-foreground/[0.03] min-w-0 w-full max-w-full border p-4 sm:p-6", children: /* @__PURE__ */ jsx(SlideDemoContent, { children }) })
212
212
  ]
213
213
  }
@@ -233,7 +233,7 @@ function SlideStatement({
233
233
  ),
234
234
  children: [
235
235
  /* @__PURE__ */ jsx("h3", { className: "text-foreground text-lg font-bold sm:text-xl md:text-2xl", children: title }),
236
- description && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 text-sm sm:text-base", children: description })
236
+ description && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-1 text-base sm:text-lg", children: description })
237
237
  ]
238
238
  }
239
239
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/primitives.tsx"],"sourcesContent":["import hljs from 'highlight.js/lib/core';\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport xml from 'highlight.js/lib/languages/xml';\nimport { cn } from './cn';\n\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('xml', xml);\n\nfunction highlightCode(code: string, lang?: string): string {\n if (!lang) return hljs.highlight(code, { language: 'typescript' }).value;\n const language = lang === 'ts' || lang === 'tsx' ? 'typescript' : lang;\n const registered = hljs.getLanguage(language);\n if (!registered)\n return hljs.highlight(code, { language: 'typescript' }).value;\n return hljs.highlight(code, { language }).value;\n}\nimport { SlideDemoContent } from './slide-demo-content';\nimport type { SlideAlign } from './types';\n\n/**\n * Full-viewport slide container with centered content and a decorative border.\n *\n * This is the primary slide primitive — use it as a top-level element in\n * the slides array. For a two-column layout that fills the whole viewport,\n * use {@link SlideSplitLayout} instead.\n *\n * @example\n * ```tsx\n * <Slide align=\"left\">\n * <SlideTitle>My Slide</SlideTitle>\n * <SlideSubtitle>Supporting text</SlideSubtitle>\n * </Slide>\n * ```\n */\nexport function Slide({\n children,\n align = 'center',\n className,\n}: {\n children: React.ReactNode;\n /** Content alignment. `\"center\"` centers both horizontally and text; `\"left\"` aligns to the start. */\n align?: SlideAlign;\n className?: string;\n}) {\n return (\n <div\n className={cn(\n 'nxs-slide relative flex h-dvh w-dvw flex-col justify-center gap-8 px-12 py-20 sm:px-24 md:px-32 lg:px-40',\n align === 'center' && 'items-center text-center',\n align === 'left' && 'items-start text-left',\n className\n )}\n >\n <div\n className=\"border-foreground/10 pointer-events-none absolute inset-4 border sm:inset-6\"\n aria-hidden\n />\n <div\n className={cn(\n 'relative z-10 flex max-w-4xl flex-col gap-6',\n align === 'center' && 'items-center',\n align === 'left' && 'items-start'\n )}\n >\n {children}\n </div>\n </div>\n );\n}\n\n/**\n * Inline two-column grid for use **inside** a `Slide`.\n *\n * Use this when you need a title or other content above two columns.\n * For a full-viewport two-column slide, use `SlideSplitLayout` instead.\n */\nexport function SlideColumns({\n left,\n right,\n className,\n}: {\n left: React.ReactNode;\n right: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn('grid w-full grid-cols-2 gap-8', className)}>\n <div className=\"flex min-w-0 flex-col gap-4\">{left}</div>\n <div className=\"flex min-w-0 flex-col gap-4\">{right}</div>\n </div>\n );\n}\n\n/**\n * Full-viewport two-column slide — a **top-level** alternative to `Slide`.\n *\n * Do **not** nest this inside `Slide`; it renders its own `h-dvh w-dvw`\n * container, border, and padding. To combine a title with two columns,\n * use `SlideColumns` inside a `Slide` instead.\n */\nexport function SlideSplitLayout({\n left,\n right,\n className,\n}: {\n left: React.ReactNode;\n right: React.ReactNode;\n className?: string;\n}) {\n return (\n <div\n className={cn(\n 'nxs-slide nxs-slide-split relative flex h-dvh w-dvw',\n className\n )}\n >\n <div\n className=\"border-foreground/10 pointer-events-none absolute inset-4 border sm:inset-6\"\n aria-hidden\n />\n <div className=\"nxs-slide-split-col relative z-10 flex w-1/2 flex-col justify-center gap-6 px-12 py-16 sm:px-16 md:px-20 lg:px-24\">\n {left}\n </div>\n <div\n className=\"nxs-slide-split-divider bg-foreground/10 absolute top-4 bottom-4 left-1/2 z-10 w-px sm:top-6 sm:bottom-6\"\n aria-hidden\n />\n <div className=\"nxs-slide-split-col relative z-10 flex w-1/2 flex-col justify-center gap-6 px-12 py-16 sm:px-16 md:px-20 lg:px-24\">\n {right}\n </div>\n </div>\n );\n}\n\n/**\n * Primary heading for a slide. Renders an `<h1>` with responsive sizing\n * that scales from `text-4xl` to `text-7xl` across breakpoints.\n *\n * Override the default size with `className` (e.g. `className=\"text-3xl sm:text-4xl\"`).\n */\nexport function SlideTitle({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <h1\n className={cn(\n 'text-foreground text-4xl font-black sm:text-5xl md:text-6xl lg:text-7xl',\n className\n )}\n style={{ letterSpacing: '-0.04em' }}\n >\n {children}\n </h1>\n );\n}\n\n/**\n * Secondary text below a title. Renders a `<p>` in a muted foreground color\n * with responsive sizing (`text-lg` to `text-2xl`).\n */\nexport function SlideSubtitle({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <p\n className={cn(\n 'text-muted-foreground text-lg sm:text-xl md:text-2xl',\n className\n )}\n >\n {children}\n </p>\n );\n}\n\n/**\n * Small pill-shaped label, typically placed above a title to categorise\n * the slide (e.g. component name, topic tag).\n */\nexport function SlideBadge({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n className={cn(\n 'bg-foreground text-background inline-block w-fit shrink-0 rounded-full px-4 py-1.5 text-sm font-semibold tracking-wide',\n className\n )}\n >\n {children}\n </span>\n );\n}\n\n/**\n * Italic accent text for slide headers — use for event names, series labels,\n * or other branding above the title.\n */\nexport function SlideHeaderBadge({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn('flex items-center gap-3', className)}>\n <span className=\"text-foreground text-xl font-semibold tracking-tight italic sm:text-2xl\">\n {children}\n </span>\n </div>\n );\n}\n\n/**\n * Syntax-highlighted code block powered by highlight.js.\n *\n * Pass code as a **string** child. The language is auto-detected from the\n * `title` file extension (e.g. `\"example.tsx\"` → TypeScript); falls back\n * to TypeScript when unspecified. Supports JS, TS, JSX, and TSX.\n *\n * Theme colours are controlled by CSS custom properties (`--sh-*` / `--nxs-code-*`)\n * defined in `nextjs-slides/styles.css`. Override them in `:root` or `.dark`.\n *\n * @example\n * ```tsx\n * <SlideCode title=\"api.ts\">{`export async function fetchData() {\n * return fetch('/api/data');\n * }`}</SlideCode>\n * ```\n */\nexport function SlideCode({\n children,\n className,\n title,\n}: {\n /** Code string to highlight. Leading/trailing whitespace is trimmed automatically. */\n children: string;\n className?: string;\n /** File name shown above the code block. Its extension determines the highlight language. */\n title?: string;\n}) {\n const lang = title?.split('.').pop();\n const html = highlightCode(children.trim(), lang);\n\n return (\n <div className={cn('nxs-code-wrapper', className)}>\n {title && (\n <div className=\"text-muted-foreground mb-2 text-xs font-medium tracking-wider uppercase\">\n {title}\n </div>\n )}\n <pre className=\"nxs-code-block\">\n <code dangerouslySetInnerHTML={{ __html: html }} />\n </pre>\n </div>\n );\n}\n\n/**\n * Bullet-point list container. Wrap {@link SlideListItem} children inside this.\n */\nexport function SlideList({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <ul className={cn('flex flex-col gap-4 text-left', className)}>\n {children}\n </ul>\n );\n}\n\n/**\n * Single bullet item inside a {@link SlideList}. Renders a small dot\n * followed by the content.\n */\nexport function SlideListItem({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <li\n className={cn(\n 'text-foreground/70 flex items-start gap-3 text-lg sm:text-xl',\n className\n )}\n >\n <span\n className=\"bg-foreground/40 mt-2 block h-1.5 w-1.5 shrink-0 rounded-full\"\n aria-hidden\n />\n <span>{children}</span>\n </li>\n );\n}\n\n/**\n * Small footnote text in a faded colour, typically placed at the bottom\n * of a slide for annotations or caveats.\n */\nexport function SlideNote({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <p className={cn('text-muted-foreground/50 text-sm', className)}>\n {children}\n </p>\n );\n}\n\n/**\n * Live interactive component embed. Keyboard navigation (arrow keys, space)\n * is disabled while focus is inside the demo area so the embedded component\n * can handle its own input.\n *\n * The container tracks its maximum height to prevent layout jumps when the\n * child re-renders with different content sizes.\n *\n * @example\n * ```tsx\n * <SlideDemo label=\"Live counter\">\n * <Counter />\n * </SlideDemo>\n * ```\n */\nexport function SlideDemo({\n children,\n className,\n label,\n}: {\n children: React.ReactNode;\n className?: string;\n /** Optional uppercase label shown above the demo area. */\n label?: string;\n}) {\n return (\n <div\n data-slide-interactive\n className={cn('min-w-0 w-full max-w-2xl', className)}\n >\n {label && (\n <div className=\"text-muted-foreground mb-2 text-xs font-medium tracking-wider uppercase\">\n {label}\n </div>\n )}\n <div className=\"border-foreground/10 bg-foreground/[0.03] min-w-0 w-full max-w-full border p-4 sm:p-6\">\n <SlideDemoContent>{children}</SlideDemoContent>\n </div>\n </div>\n );\n}\n\n/**\n * Container for {@link SlideStatement} items. Adds border separators between\n * statements automatically.\n */\nexport function SlideStatementList({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn('flex min-w-0 w-full flex-col', className)}>\n {children}\n </div>\n );\n}\n\n/**\n * Title + description pair for structured content blocks.\n * Use inside a {@link SlideStatementList} for automatic border separators.\n */\nexport function SlideStatement({\n title,\n description,\n className,\n}: {\n /** Bold heading text. */\n title: string;\n /** Optional muted description below the title. */\n description?: string;\n className?: string;\n}) {\n return (\n <div\n className={cn(\n 'border-foreground/10 border-t px-8 py-6 last:border-b sm:px-12 md:px-16',\n className\n )}\n >\n <h3 className=\"text-foreground text-lg font-bold sm:text-xl md:text-2xl\">\n {title}\n </h3>\n {description && (\n <p className=\"text-muted-foreground mt-1 text-sm sm:text-base\">\n {description}\n </p>\n )}\n </div>\n );\n}\n\n/**\n * Speaker card with an avatar circle, name, and role/title.\n * When `avatar` is omitted a placeholder circle is shown.\n *\n * Use inside {@link SlideSpeakerGrid} or {@link SlideSpeakerList} to\n * lay out multiple speakers.\n */\nexport function SlideSpeaker({\n name,\n title,\n avatar,\n className,\n}: {\n name: string;\n title: string;\n /** Image URL or path for the speaker avatar. Falls back to placeholder when omitted. */\n avatar?: string;\n className?: string;\n}) {\n return (\n <div className={cn('flex items-center gap-4', className)}>\n <div\n className={cn(\n 'h-12 w-12 shrink-0 overflow-hidden rounded-full',\n avatar ? 'relative' : 'bg-foreground/15 border-foreground/20 border'\n )}\n aria-hidden\n >\n {avatar ? (\n <img src={avatar} alt=\"\" className=\"h-full w-full object-cover\" />\n ) : null}\n </div>\n <div>\n <p className=\"text-foreground/90 text-sm font-medium tracking-widest uppercase\">\n {name}\n </p>\n <p className=\"text-muted-foreground text-sm tracking-wider uppercase\">\n {title}\n </p>\n </div>\n </div>\n );\n}\n\n/**\n * Two-column responsive grid for laying out {@link SlideSpeaker} cards\n * side by side (stacks to one column on small screens).\n */\nexport function SlideSpeakerGrid({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn('grid grid-cols-1 gap-6 sm:grid-cols-2', className)}>\n {children}\n </div>\n );\n}\n\n/**\n * Vertical stack layout for {@link SlideSpeaker} cards.\n */\nexport function SlideSpeakerList({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return <div className={cn('flex flex-col gap-6', className)}>{children}</div>;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/primitives.tsx"],"sourcesContent":["import hljs from 'highlight.js/lib/core';\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport xml from 'highlight.js/lib/languages/xml';\nimport { cn } from './cn';\n\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('xml', xml);\n\nfunction highlightCode(code: string, lang?: string): string {\n if (!lang) return hljs.highlight(code, { language: 'typescript' }).value;\n const language = lang === 'ts' || lang === 'tsx' ? 'typescript' : lang;\n const registered = hljs.getLanguage(language);\n if (!registered)\n return hljs.highlight(code, { language: 'typescript' }).value;\n return hljs.highlight(code, { language }).value;\n}\nimport { SlideDemoContent } from './slide-demo-content';\nimport type { SlideAlign } from './types';\n\n/**\n * Full-viewport slide container with centered content and a decorative border.\n *\n * This is the primary slide primitive — use it as a top-level element in\n * the slides array. For a two-column layout that fills the whole viewport,\n * use {@link SlideSplitLayout} instead.\n *\n * @example\n * ```tsx\n * <Slide align=\"left\">\n * <SlideTitle>My Slide</SlideTitle>\n * <SlideSubtitle>Supporting text</SlideSubtitle>\n * </Slide>\n * ```\n */\nexport function Slide({\n children,\n align = 'center',\n className,\n}: {\n children: React.ReactNode;\n /** Content alignment. `\"center\"` centers both horizontally and text; `\"left\"` aligns to the start. */\n align?: SlideAlign;\n className?: string;\n}) {\n return (\n <div\n className={cn(\n 'nxs-slide relative flex h-dvh w-dvw flex-col justify-center gap-8 px-12 py-20 sm:px-24 md:px-32 lg:px-40',\n align === 'center' && 'items-center text-center',\n align === 'left' && 'items-start text-left',\n className\n )}\n >\n <div\n className=\"border-foreground/10 pointer-events-none absolute inset-4 border sm:inset-6\"\n aria-hidden\n />\n <div\n className={cn(\n 'relative z-10 flex max-w-4xl flex-col gap-6',\n align === 'center' && 'items-center',\n align === 'left' && 'items-start'\n )}\n >\n {children}\n </div>\n </div>\n );\n}\n\n/**\n * Inline two-column grid for use **inside** a `Slide`.\n *\n * Use this when you need a title or other content above two columns.\n * For a full-viewport two-column slide, use `SlideSplitLayout` instead.\n */\nexport function SlideColumns({\n left,\n right,\n className,\n}: {\n left: React.ReactNode;\n right: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn('grid w-full grid-cols-2 gap-8', className)}>\n <div className=\"flex min-w-0 flex-col gap-4\">{left}</div>\n <div className=\"flex min-w-0 flex-col gap-4\">{right}</div>\n </div>\n );\n}\n\n/**\n * Full-viewport two-column slide — a **top-level** alternative to `Slide`.\n *\n * Do **not** nest this inside `Slide`; it renders its own `h-dvh w-dvw`\n * container, border, and padding. To combine a title with two columns,\n * use `SlideColumns` inside a `Slide` instead.\n */\nexport function SlideSplitLayout({\n left,\n right,\n className,\n}: {\n left: React.ReactNode;\n right: React.ReactNode;\n className?: string;\n}) {\n return (\n <div\n className={cn(\n 'nxs-slide nxs-slide-split relative flex h-dvh w-dvw',\n className\n )}\n >\n <div\n className=\"border-foreground/10 pointer-events-none absolute inset-4 border sm:inset-6\"\n aria-hidden\n />\n <div className=\"nxs-slide-split-col relative z-10 flex w-1/2 flex-col justify-center gap-6 px-12 py-16 sm:px-16 md:px-20 lg:px-24\">\n {left}\n </div>\n <div\n className=\"nxs-slide-split-divider bg-foreground/10 absolute top-4 bottom-4 left-1/2 z-10 w-px sm:top-6 sm:bottom-6\"\n aria-hidden\n />\n <div className=\"nxs-slide-split-col relative z-10 flex w-1/2 flex-col justify-center gap-6 px-12 py-16 sm:px-16 md:px-20 lg:px-24\">\n {right}\n </div>\n </div>\n );\n}\n\n/**\n * Primary heading for a slide. Renders an `<h1>` with responsive sizing\n * that scales from `text-4xl` to `text-7xl` across breakpoints.\n *\n * Override the default size with `className` (e.g. `className=\"text-3xl sm:text-4xl\"`).\n */\nexport function SlideTitle({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <h1\n className={cn(\n 'text-foreground text-4xl font-black sm:text-5xl md:text-6xl lg:text-7xl',\n className\n )}\n style={{ letterSpacing: '-0.04em' }}\n >\n {children}\n </h1>\n );\n}\n\n/**\n * Secondary text below a title. Renders a `<p>` in a muted foreground color\n * with responsive sizing (`text-lg` to `text-2xl`).\n */\nexport function SlideSubtitle({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <p\n className={cn(\n 'text-muted-foreground text-lg sm:text-xl md:text-2xl',\n className\n )}\n >\n {children}\n </p>\n );\n}\n\n/**\n * Small pill-shaped label, typically placed above a title to categorise\n * the slide (e.g. component name, topic tag).\n */\nexport function SlideBadge({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <span\n className={cn(\n 'bg-foreground text-background inline-block w-fit shrink-0 rounded-full px-4 py-1.5 text-sm font-semibold tracking-wide',\n className\n )}\n >\n {children}\n </span>\n );\n}\n\n/**\n * Italic accent text for slide headers — use for event names, series labels,\n * or other branding above the title.\n */\nexport function SlideHeaderBadge({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn('flex items-center gap-3', className)}>\n <span className=\"text-foreground text-xl font-semibold tracking-tight italic sm:text-2xl\">\n {children}\n </span>\n </div>\n );\n}\n\n/**\n * Syntax-highlighted code block powered by highlight.js.\n *\n * Pass code as a **string** child. The language is auto-detected from the\n * `title` file extension (e.g. `\"example.tsx\"` → TypeScript); falls back\n * to TypeScript when unspecified. Supports JS, TS, JSX, and TSX.\n *\n * Theme colours are controlled by CSS custom properties (`--sh-*` / `--nxs-code-*`)\n * defined in `nextjs-slides/styles.css`. Override them in `:root` or `.dark`.\n *\n * @example\n * ```tsx\n * <SlideCode title=\"api.ts\">{`export async function fetchData() {\n * return fetch('/api/data');\n * }`}</SlideCode>\n * ```\n */\nexport function SlideCode({\n children,\n className,\n title,\n}: {\n /** Code string to highlight. Leading/trailing whitespace is trimmed automatically. */\n children: string;\n className?: string;\n /** File name shown above the code block. Its extension determines the highlight language. */\n title?: string;\n}) {\n const lang = title?.split('.').pop();\n const html = highlightCode(children.trim(), lang);\n\n return (\n <div className={cn('nxs-code-wrapper', className)}>\n {title && (\n <div className=\"text-muted-foreground mb-2 text-sm font-medium tracking-wider uppercase\">\n {title}\n </div>\n )}\n <pre className=\"nxs-code-block\">\n <code dangerouslySetInnerHTML={{ __html: html }} />\n </pre>\n </div>\n );\n}\n\n/**\n * Bullet-point list container. Wrap {@link SlideListItem} children inside this.\n */\nexport function SlideList({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <ul className={cn('flex flex-col gap-4 text-left', className)}>\n {children}\n </ul>\n );\n}\n\n/**\n * Single bullet item inside a {@link SlideList}. Renders a small dot\n * followed by the content.\n */\nexport function SlideListItem({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <li\n className={cn(\n 'text-foreground/70 flex items-start gap-3 text-lg sm:text-xl',\n className\n )}\n >\n <span\n className=\"bg-foreground/40 mt-2 block h-1.5 w-1.5 shrink-0 rounded-full\"\n aria-hidden\n />\n <span>{children}</span>\n </li>\n );\n}\n\n/**\n * Small footnote text in a faded colour, typically placed at the bottom\n * of a slide for annotations or caveats.\n */\nexport function SlideNote({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <p className={cn('text-muted-foreground text-base sm:text-lg', className)}>\n {children}\n </p>\n );\n}\n\n/**\n * Live interactive component embed. Keyboard navigation (arrow keys, space)\n * is disabled while focus is inside the demo area so the embedded component\n * can handle its own input.\n *\n * The container tracks its maximum height to prevent layout jumps when the\n * child re-renders with different content sizes.\n *\n * @example\n * ```tsx\n * <SlideDemo label=\"Live counter\">\n * <Counter />\n * </SlideDemo>\n * ```\n */\nexport function SlideDemo({\n children,\n className,\n label,\n}: {\n children: React.ReactNode;\n className?: string;\n /** Optional uppercase label shown above the demo area. */\n label?: string;\n}) {\n return (\n <div\n data-slide-interactive\n className={cn('min-w-0 w-full max-w-2xl', className)}\n >\n {label && (\n <div className=\"text-muted-foreground mb-2 text-sm font-medium tracking-wider uppercase\">\n {label}\n </div>\n )}\n <div className=\"border-foreground/10 bg-foreground/[0.03] min-w-0 w-full max-w-full border p-4 sm:p-6\">\n <SlideDemoContent>{children}</SlideDemoContent>\n </div>\n </div>\n );\n}\n\n/**\n * Container for {@link SlideStatement} items. Adds border separators between\n * statements automatically.\n */\nexport function SlideStatementList({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn('flex min-w-0 w-full flex-col', className)}>\n {children}\n </div>\n );\n}\n\n/**\n * Title + description pair for structured content blocks.\n * Use inside a {@link SlideStatementList} for automatic border separators.\n */\nexport function SlideStatement({\n title,\n description,\n className,\n}: {\n /** Bold heading text. */\n title: string;\n /** Optional muted description below the title. */\n description?: string;\n className?: string;\n}) {\n return (\n <div\n className={cn(\n 'border-foreground/10 border-t px-8 py-6 last:border-b sm:px-12 md:px-16',\n className\n )}\n >\n <h3 className=\"text-foreground text-lg font-bold sm:text-xl md:text-2xl\">\n {title}\n </h3>\n {description && (\n <p className=\"text-muted-foreground mt-1 text-base sm:text-lg\">\n {description}\n </p>\n )}\n </div>\n );\n}\n\n/**\n * Speaker card with an avatar circle, name, and role/title.\n * When `avatar` is omitted a placeholder circle is shown.\n *\n * Use inside {@link SlideSpeakerGrid} or {@link SlideSpeakerList} to\n * lay out multiple speakers.\n */\nexport function SlideSpeaker({\n name,\n title,\n avatar,\n className,\n}: {\n name: string;\n title: string;\n /** Image URL or path for the speaker avatar. Falls back to placeholder when omitted. */\n avatar?: string;\n className?: string;\n}) {\n return (\n <div className={cn('flex items-center gap-4', className)}>\n <div\n className={cn(\n 'h-12 w-12 shrink-0 overflow-hidden rounded-full',\n avatar ? 'relative' : 'bg-foreground/15 border-foreground/20 border'\n )}\n aria-hidden\n >\n {avatar ? (\n <img src={avatar} alt=\"\" className=\"h-full w-full object-cover\" />\n ) : null}\n </div>\n <div>\n <p className=\"text-foreground/90 text-sm font-medium tracking-widest uppercase\">\n {name}\n </p>\n <p className=\"text-muted-foreground text-sm tracking-wider uppercase\">\n {title}\n </p>\n </div>\n </div>\n );\n}\n\n/**\n * Two-column responsive grid for laying out {@link SlideSpeaker} cards\n * side by side (stacks to one column on small screens).\n */\nexport function SlideSpeakerGrid({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return (\n <div className={cn('grid grid-cols-1 gap-6 sm:grid-cols-2', className)}>\n {children}\n </div>\n );\n}\n\n/**\n * Vertical stack layout for {@link SlideSpeaker} cards.\n */\nexport function SlideSpeakerList({\n children,\n className,\n}: {\n children: React.ReactNode;\n className?: string;\n}) {\n return <div className={cn('flex flex-col gap-6', className)}>{children}</div>;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nextjs-slides",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Composable slide deck primitives for Next.js — powered by React 19 ViewTransitions, Tailwind CSS, and highlight.js syntax highlighting.",
5
5
  "license": "MIT",
6
6
  "type": "module",