@honeydeck/honeydeck 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/AGENTS.md +25 -0
  2. package/DEVELOPMENT.md +522 -0
  3. package/LICENSE +21 -0
  4. package/Readme.md +49 -0
  5. package/SPEC.md +88 -0
  6. package/docs/components.md +63 -0
  7. package/docs/configuration.md +91 -0
  8. package/docs/getting-started.md +116 -0
  9. package/docs/kit-authoring.md +207 -0
  10. package/docs/kits.md +387 -0
  11. package/docs/local-development.md +95 -0
  12. package/docs/mermaid.md +198 -0
  13. package/docs/mobile.md +108 -0
  14. package/docs/navigation.md +93 -0
  15. package/docs/next-steps.md +377 -0
  16. package/docs/pdf-export.md +91 -0
  17. package/docs/presenter-mode.md +104 -0
  18. package/docs/slides.md +130 -0
  19. package/docs/slidev-migration.md +42 -0
  20. package/docs/steps-and-reveals.md +171 -0
  21. package/package.json +134 -0
  22. package/skills/SPEC.md +21 -0
  23. package/skills/honeydeck/SKILL.md +65 -0
  24. package/skills/presentation-writing/SKILL.md +75 -0
  25. package/skills/slidev-migration/SKILL.md +153 -0
  26. package/src/SPEC.md +89 -0
  27. package/src/assets.d.ts +30 -0
  28. package/src/cli/SPEC.md +230 -0
  29. package/src/cli/args.ts +3 -0
  30. package/src/cli/banner.ts +9 -0
  31. package/src/cli/bin.js +5 -0
  32. package/src/cli/build.ts +229 -0
  33. package/src/cli/deck-path.ts +32 -0
  34. package/src/cli/dev.ts +263 -0
  35. package/src/cli/index.ts +126 -0
  36. package/src/cli/init.ts +369 -0
  37. package/src/cli/pdf.ts +923 -0
  38. package/src/cli/skill.ts +75 -0
  39. package/src/cli/templates/SPEC.md +70 -0
  40. package/src/cli/templates/deck-mdx.ts +15 -0
  41. package/src/cli/templates/package-json.ts +36 -0
  42. package/src/cli/templates/sparkle-button.ts +15 -0
  43. package/src/cli/templates/starter/components/SparkleButton.tsx +84 -0
  44. package/src/cli/templates/starter/deck.mdx +153 -0
  45. package/src/cli/templates/starter/styles.css +14 -0
  46. package/src/cli/templates/styles-css.ts +14 -0
  47. package/src/defaults.ts +1 -0
  48. package/src/layouts/ColorModeImage.tsx +55 -0
  49. package/src/layouts/SPEC.md +393 -0
  50. package/src/layouts/SlideFrame.tsx +48 -0
  51. package/src/layouts/bee/Blank.tsx +12 -0
  52. package/src/layouts/bee/Cover.tsx +70 -0
  53. package/src/layouts/bee/Default.tsx +42 -0
  54. package/src/layouts/bee/Image/Image.tsx +151 -0
  55. package/src/layouts/bee/Image/placeholder-dark.webp +0 -0
  56. package/src/layouts/bee/Image/placeholder-vertical-dark.webp +0 -0
  57. package/src/layouts/bee/Image/placeholder-vertical.webp +0 -0
  58. package/src/layouts/bee/Image/placeholder.webp +0 -0
  59. package/src/layouts/bee/ImageLeft.tsx +27 -0
  60. package/src/layouts/bee/ImageRight.tsx +27 -0
  61. package/src/layouts/bee/ImageSide.tsx +107 -0
  62. package/src/layouts/bee/Section.tsx +40 -0
  63. package/src/layouts/bee/TwoCol.tsx +108 -0
  64. package/src/layouts/bee/index.ts +40 -0
  65. package/src/layouts/clean/Blank.tsx +12 -0
  66. package/src/layouts/clean/Cover.tsx +58 -0
  67. package/src/layouts/clean/Default.tsx +33 -0
  68. package/src/layouts/clean/Image/Image.tsx +103 -0
  69. package/src/layouts/clean/ImageLeft.tsx +27 -0
  70. package/src/layouts/clean/ImageRight.tsx +27 -0
  71. package/src/layouts/clean/ImageSide.tsx +113 -0
  72. package/src/layouts/clean/Section.tsx +35 -0
  73. package/src/layouts/clean/TwoCol.tsx +63 -0
  74. package/src/layouts/clean/index.ts +40 -0
  75. package/src/layouts/index.ts +60 -0
  76. package/src/layouts/placeholders.ts +9 -0
  77. package/src/layouts/utils.ts +13 -0
  78. package/src/remark/SPEC.md +49 -0
  79. package/src/remark/h1-extract.ts +124 -0
  80. package/src/remark/index.ts +4 -0
  81. package/src/remark/shiki-code-blocks.ts +325 -0
  82. package/src/remark/step-numbering.ts +412 -0
  83. package/src/runtime/Deck.tsx +533 -0
  84. package/src/runtime/SPEC.md +256 -0
  85. package/src/runtime/SlideCanvas.tsx +95 -0
  86. package/src/runtime/TimelineContext.tsx +122 -0
  87. package/src/runtime/app-shell/index.html +31 -0
  88. package/src/runtime/app-shell/main.tsx +42 -0
  89. package/src/runtime/aspectRatio.ts +34 -0
  90. package/src/runtime/colorMode.ts +23 -0
  91. package/src/runtime/components/BrowserFrame.tsx +233 -0
  92. package/src/runtime/components/Button.tsx +57 -0
  93. package/src/runtime/components/CodeBlock.tsx +210 -0
  94. package/src/runtime/components/ColorModeCycleButton.tsx +59 -0
  95. package/src/runtime/components/ErrorBoundary.tsx +125 -0
  96. package/src/runtime/components/Keyboard.tsx +87 -0
  97. package/src/runtime/components/ListStyle.tsx +203 -0
  98. package/src/runtime/components/NavBar.tsx +223 -0
  99. package/src/runtime/components/NavBarButton.tsx +47 -0
  100. package/src/runtime/components/NavBarDivider.tsx +3 -0
  101. package/src/runtime/components/Notes.tsx +171 -0
  102. package/src/runtime/components/Reveal.tsx +82 -0
  103. package/src/runtime/components/RevealGroup.tsx +193 -0
  104. package/src/runtime/components/SPEC.md +263 -0
  105. package/src/runtime/components/SlideNumberBadge.tsx +11 -0
  106. package/src/runtime/components/TimelineSteps.tsx +115 -0
  107. package/src/runtime/components/index.ts +55 -0
  108. package/src/runtime/index.ts +42 -0
  109. package/src/runtime/inputOwnership.ts +68 -0
  110. package/src/runtime/keyboardTarget.ts +7 -0
  111. package/src/runtime/lastSlideRoute.ts +56 -0
  112. package/src/runtime/navigation.ts +211 -0
  113. package/src/runtime/router.ts +157 -0
  114. package/src/runtime/slideData.ts +137 -0
  115. package/src/runtime/sync.ts +267 -0
  116. package/src/runtime/types.ts +182 -0
  117. package/src/runtime/useKeyboardNav.ts +138 -0
  118. package/src/runtime/useSwipeNav.ts +257 -0
  119. package/src/runtime/views/DocsView.tsx +74 -0
  120. package/src/runtime/views/OverviewView.tsx +386 -0
  121. package/src/runtime/views/PresenterNotesPanel.tsx +76 -0
  122. package/src/runtime/views/PresenterView.tsx +340 -0
  123. package/src/runtime/views/SPEC.md +152 -0
  124. package/src/runtime/views/docs/ComponentsTab.tsx +178 -0
  125. package/src/runtime/views/docs/DocsHeader.tsx +101 -0
  126. package/src/runtime/views/docs/Intro.tsx +20 -0
  127. package/src/runtime/views/docs/LayoutsTab.tsx +324 -0
  128. package/src/runtime/views/docs/ThemeTab.tsx +110 -0
  129. package/src/runtime/views/index.ts +7 -0
  130. package/src/runtime/views/overviewGrid.ts +106 -0
  131. package/src/runtime/views/presenterPreview.ts +27 -0
  132. package/src/runtime/virtual-modules.d.ts +98 -0
  133. package/src/theme/SPEC.md +179 -0
  134. package/src/theme/base.css +623 -0
  135. package/src/theme/bee.css +35 -0
  136. package/src/theme/clean.css +38 -0
  137. package/src/vite-plugin/SPEC.md +114 -0
  138. package/src/vite-plugin/component-doc-crawler.ts +350 -0
  139. package/src/vite-plugin/deck-loader.ts +148 -0
  140. package/src/vite-plugin/index.ts +373 -0
  141. package/src/vite-plugin/layout-demo-crawler.ts +802 -0
  142. package/src/vite-plugin/splitter.ts +353 -0
  143. package/src/vite-plugin/token-manifest.ts +163 -0
  144. package/src/vite-plugin/virtual-modules.ts +587 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * `honeydeck skill` — install Honeydeck agent skills.
3
+ */
4
+
5
+ import { execFileSync } from "node:child_process";
6
+ import { dirname, resolve } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import * as p from "@clack/prompts";
9
+ import { hasHelpFlag } from "./args.ts";
10
+
11
+ export function printSkillHelp(): void {
12
+ console.log(`
13
+ ✨ honeydeck skill — install Honeydeck agent skills
14
+
15
+ Usage:
16
+ honeydeck skill [options]
17
+
18
+ Options:
19
+ -h, --help Show this help page
20
+
21
+ Behavior:
22
+ Opens the skills installer via npx skills add for bundled Honeydeck skills.
23
+
24
+ Examples:
25
+ honeydeck skill
26
+ `);
27
+ }
28
+
29
+ function packageRoot(): string {
30
+ return resolve(dirname(fileURLToPath(import.meta.url)), "../..");
31
+ }
32
+
33
+ export type InstallHoneydeckAgentSkillsOptions = {
34
+ /** Show the normal `skills` CLI prompts for scope and agent selection. */
35
+ interactive?: boolean;
36
+ };
37
+
38
+ function runSkillsAdd(
39
+ projectDir: string,
40
+ args: string[],
41
+ options: InstallHoneydeckAgentSkillsOptions,
42
+ ): void {
43
+ execFileSync("npx", ["skills", "add", packageRoot(), "--copy", ...args], {
44
+ cwd: projectDir,
45
+ stdio: options.interactive ? "inherit" : "pipe",
46
+ });
47
+ }
48
+
49
+ export function openHoneydeckAgentSkillsInstaller(projectDir: string): void {
50
+ // Let the skills CLI offer the bundled Honeydeck skills interactively.
51
+ runSkillsAdd(projectDir, [], { interactive: true });
52
+ }
53
+
54
+ export async function runSkill(args: string[]): Promise<void> {
55
+ if (hasHelpFlag(args)) {
56
+ printSkillHelp();
57
+ return;
58
+ }
59
+
60
+ p.intro(" ✨ honeydeck skill — Install Honeydeck agent skills");
61
+ p.log.info(
62
+ "Opening `npx skills add` so you can choose skill, scope, and agents.",
63
+ );
64
+
65
+ try {
66
+ openHoneydeckAgentSkillsInstaller(process.cwd());
67
+ p.outro(" 🤖 Ready! Ask your agent to help with Honeydeck presentations.");
68
+ } catch (_err) {
69
+ p.log.warn("Could not install skills automatically.");
70
+ p.log.info(
71
+ "Install manually with: npx skills add <honeydeck-repo-url> --copy",
72
+ );
73
+ process.exit(1);
74
+ }
75
+ }
@@ -0,0 +1,70 @@
1
+ # Honeydeck Starter Template Specification
2
+
3
+ > Observable behavior for generated projects and starter files owned by CLI templates.
4
+
5
+ ## Generated Project Structure
6
+
7
+ Generated user projects created by `honeydeck init`:
8
+
9
+ ```txt
10
+ awesome-talk/
11
+ package.json ← scripts, dependencies, package metadata
12
+ deck.mdx ← root deck file (tutorial-style starter)
13
+ styles.css ← explicit Tailwind + Honeydeck theme imports; imported by deck.mdx
14
+ .gitignore ← default ignored files
15
+ components/
16
+ SparkleButton.tsx ← fun demo component
17
+ public/ ← static assets
18
+ ```
19
+
20
+ The `package.json` includes package metadata (`name`, `version`, `private`, `type`), scripts, runtime dependencies (`honeydeck`, `react`, `react-dom`), and dev dependencies (`tailwindcss`, `typescript`, React types). The generated `honeydeck` dependency version is derived from the current package version so freshly initialized projects install the same Honeydeck release line as the CLI that created them. Scripts include at least:
21
+
22
+ ```json
23
+ {
24
+ "scripts": {
25
+ "dev": "honeydeck dev",
26
+ "build": "honeydeck build",
27
+ "pdf": "honeydeck pdf"
28
+ }
29
+ }
30
+ ```
31
+
32
+ `honeydeck init` installs dependencies with `npm install` by default and can skip installation with `--skip-install`. It also offers to open the Honeydeck agent skills installer and tells users that accepting runs `npx skills add`. Users can skip the prompt with `--skip-skill`, open the installer without the Honeydeck confirmation prompt with `--install-skill`, install from the local package with `honeydeck skill`, or install the same skills later from the Honeydeck repository with `npx skills add <honeydeck-repo-url> --copy`.
33
+
34
+ ---
35
+
36
+ ---
37
+
38
+ ## Generated Starter Project
39
+
40
+ ### `deck.mdx`
41
+
42
+ Generated starter tree includes `package.json`, `deck.mdx`, `styles.css`, `.gitignore`, `public/`, and `components/SparkleButton.tsx`.
43
+
44
+ Tutorial-style `deck.mdx` imports `./styles.css` so styling stays explicit and user-controlled. It demonstrates:
45
+
46
+ - Deck frontmatter, including `colorMode: system`
47
+ - Slide separators
48
+ - Built-in layouts via per-slide `layout:` (`Default`, `Section`, `TwoCol`, `Cover`, `Blank`)
49
+ - Code highlighting with step-through
50
+ - Custom interactive component (`SparkleButton`)
51
+ - Reveal/timeline features
52
+ - Presenter notes with `<Notes>`
53
+ - Keyboard navigation hints
54
+ - Design tokens
55
+ - PDF export commands
56
+
57
+ ### `styles.css`
58
+
59
+ Generated `styles.css` is the explicit styling entry point:
60
+
61
+ ```css
62
+ @import "tailwindcss";
63
+ @import "@honeydeck/honeydeck/theme.css";
64
+ ```
65
+
66
+ Users may add kit theme layers or overrides after the base theme import.
67
+
68
+ ### `components/SparkleButton.tsx`
69
+
70
+ Generated starter projects include a small dependency-free interactive React component. It demonstrates that slides can import local components, use client-side state, and add playful behavior without extra Honeydeck configuration. Like a button that spawns a small confetti effect.
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Template generator for the tutorial-style starter deck.mdx.
3
+ * Demonstrates core Honeydeck features so users can learn by reading and running.
4
+ */
5
+
6
+ import { readFileSync } from "node:fs";
7
+
8
+ const STARTER_DECK_TEMPLATE = readFileSync(
9
+ new URL("./starter/deck.mdx", import.meta.url),
10
+ "utf-8",
11
+ );
12
+
13
+ export function generateDeckMdx(projectName: string): string {
14
+ return STARTER_DECK_TEMPLATE.replaceAll("Honeydeck Starter", projectName);
15
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Template generator for package.json in a new honeydeck project.
3
+ */
4
+
5
+ import { readFileSync } from "node:fs";
6
+
7
+ const packageJson = JSON.parse(
8
+ readFileSync(new URL("../../../package.json", import.meta.url), "utf-8"),
9
+ ) as { version: string };
10
+
11
+ export function generatePackageJson(projectName: string): string {
12
+ const pkg = {
13
+ name: projectName,
14
+ version: "0.1.0",
15
+ private: true,
16
+ type: "module",
17
+ scripts: {
18
+ dev: "honeydeck dev",
19
+ build: "honeydeck build",
20
+ pdf: "honeydeck pdf",
21
+ },
22
+ dependencies: {
23
+ "@honeydeck/honeydeck": `^${packageJson.version}`,
24
+ react: "^19.0.0",
25
+ "react-dom": "^19.0.0",
26
+ },
27
+ devDependencies: {
28
+ tailwindcss: "^4.0.0",
29
+ typescript: "^5.0.0",
30
+ "@types/react": "^19.0.0",
31
+ "@types/react-dom": "^19.0.0",
32
+ },
33
+ };
34
+
35
+ return `${JSON.stringify(pkg, null, 2)}\n`;
36
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Template generator for the SparkleButton component.
3
+ * A dependency-free confetti button demonstrating interactive React in slides.
4
+ */
5
+
6
+ import { readFileSync } from "node:fs";
7
+
8
+ const SPARKLE_BUTTON_TEMPLATE = readFileSync(
9
+ new URL("./starter/components/SparkleButton.tsx", import.meta.url),
10
+ "utf-8",
11
+ );
12
+
13
+ export function generateSparkleButton(): string {
14
+ return SPARKLE_BUTTON_TEMPLATE;
15
+ }
@@ -0,0 +1,84 @@
1
+ import type { CSSProperties } from "react";
2
+ import { useState } from "react";
3
+
4
+ type Particle = {
5
+ id: number;
6
+ color: string;
7
+ x: number;
8
+ y: number;
9
+ rotate: number;
10
+ };
11
+
12
+ export function SparkleButton() {
13
+ const [particles, setParticles] = useState<Particle[]>([]);
14
+
15
+ function launch() {
16
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
17
+ return;
18
+ }
19
+
20
+ const colors = ["#facc15", "#38bdf8", "#a78bfa", "#fb7185", "#34d399"];
21
+ const next = Array.from({ length: 28 }, (_, index) => {
22
+ const angle = (Math.PI * 2 * index) / 28;
23
+ const distance = 56 + Math.random() * 96;
24
+
25
+ return {
26
+ id: Date.now() + index,
27
+ color: colors[index % colors.length],
28
+ x: Math.cos(angle) * distance,
29
+ y: Math.sin(angle) * distance,
30
+ rotate: Math.random() * 360,
31
+ };
32
+ });
33
+
34
+ setParticles(next);
35
+ window.setTimeout(() => setParticles([]), 900);
36
+ }
37
+
38
+ return (
39
+ <div className="relative inline-flex items-center justify-center">
40
+ <button
41
+ type="button"
42
+ onClick={launch}
43
+ className="rounded-full bg-primary px-6 py-3 font-bold text-primary-foreground shadow-lg transition hover:scale-105 focus:outline-none focus:ring-4 focus:ring-primary/30"
44
+ >
45
+ Launch confetti
46
+ </button>
47
+
48
+ {particles.map((particle) => (
49
+ <span
50
+ key={particle.id}
51
+ className="pointer-events-none absolute left-1/2 top-1/2 h-2.5 w-2.5 rounded-full"
52
+ style={
53
+ {
54
+ backgroundColor: particle.color,
55
+ "--sparkle-x": `${particle.x}px`,
56
+ "--sparkle-y": `${particle.y}px`,
57
+ "--sparkle-rotate": `${particle.rotate}deg`,
58
+ animation:
59
+ "honeydeck-sparkle 900ms cubic-bezier(.16,1,.3,1) forwards",
60
+ } as CSSProperties
61
+ }
62
+ />
63
+ ))}
64
+
65
+ <style>{`
66
+ @keyframes honeydeck-sparkle {
67
+ 0% {
68
+ opacity: 1;
69
+ transform: translate(-50%, -50%) scale(1) rotate(0deg);
70
+ }
71
+ 100% {
72
+ opacity: 0;
73
+ transform: translate(
74
+ calc(-50% + var(--sparkle-x)),
75
+ calc(-50% + var(--sparkle-y))
76
+ )
77
+ scale(0)
78
+ rotate(var(--sparkle-rotate));
79
+ }
80
+ }
81
+ `}</style>
82
+ </div>
83
+ );
84
+ }
@@ -0,0 +1,153 @@
1
+ ---
2
+ title: demo-deck
3
+ description: A clean Honeydeck starter deck
4
+ # Define the color mode for your slides: light, dark, system.
5
+ colorMode: system
6
+ # Swap layouts for a custom layout map or the included bee theme (also update css).
7
+ # - Custom layouts: layouts: "./layouts"
8
+ # - Bee layouts: layouts: "@honeydeck/honeydeck/layouts/bee"
9
+ # Run dev server and check: http://localhost:4201/#/layouts
10
+ layouts: "@honeydeck/honeydeck/layouts"
11
+ # --- Frontmatter for first slide.
12
+ layout: Cover
13
+ author: Built with Honeydeck ✨
14
+ ---
15
+
16
+ import './styles.css'
17
+ import { Reveal, RevealGroup, Notes, Keyboard } from '@honeydeck/honeydeck'
18
+ import { Left, Right } from '@honeydeck/honeydeck/layouts/TwoCol'
19
+ import { SparkleButton } from './components/SparkleButton'
20
+
21
+ # Honeydeck Starter Deck 🐝
22
+
23
+ Press → for next slide
24
+
25
+ <Notes>
26
+ Welcome to Honeydeck 🎉
27
+ Open presenter mode with "p" to see this note.
28
+ </Notes>
29
+
30
+ ---
31
+
32
+ # Start with plain Markdown 📝
33
+
34
+ All you need is `---` for new slides.
35
+
36
+ ```mdx
37
+ ---
38
+
39
+ # Slide 😎
40
+
41
+ ```
42
+
43
+ <Reveal>
44
+ You can press <Keyboard>↓</Keyboard> to skip revealed content and jump to the next slide.
45
+ </Reveal>
46
+
47
+ ---
48
+
49
+ # Grow into React when needed ⚛️
50
+
51
+ When Markdown is not enough, use React.
52
+
53
+ <div className='p-8'>
54
+ <SparkleButton />
55
+ </div>
56
+
57
+ ---
58
+ layout: Section
59
+ ---
60
+
61
+ # Structure your talk with layouts
62
+
63
+ See all at [/#/layouts](/#/layouts)
64
+
65
+ <div className='absolute bottom-8 left-8'>
66
+ 👇 did you notice this bar?
67
+ </div>
68
+
69
+ ---
70
+
71
+ # Code step-through 🧑‍💻
72
+
73
+ Add line groups to a code fence and Honeydeck turns them into timeline steps.
74
+
75
+ `{0|1-2|4-6|all}`
76
+
77
+ ```ts {0|1-2|4-6|all}
78
+ // Step 1: define your story beats
79
+ const beats = ['hook', 'demo', 'takeaway']
80
+
81
+ // Step 2: choose what the audience sees now
82
+ const currentBeat = beats[0]
83
+ console.log(currentBeat)
84
+ ```
85
+
86
+ <Notes>
87
+ Walk through each highlighted step. The code fence metadata controls which
88
+ lines are emphasized.
89
+ </Notes>
90
+
91
+ ---
92
+
93
+ # Theme tokens and CSS variables 🎨
94
+
95
+ Honeydeck starts clean by default and exposes friendly CSS variables. Override a few and the whole deck changes.
96
+
97
+ <div className="grid grid-cols-2 gap-4 mb-8">
98
+ <div className="rounded-honeydeck bg-primary p-5 text-primary-foreground">--honeydeck-primary</div>
99
+ <div className="rounded-honeydeck bg-accent p-5 text-accent-foreground">--honeydeck-accent</div>
100
+ <div className="rounded-honeydeck border border-border bg-surface p-5 text-surface-foreground">--honeydeck-surface</div>
101
+ <div className="rounded-honeydeck border border-border bg-background p-5 text-foreground">--honeydeck-background</div>
102
+ </div>
103
+
104
+ Change them in `styles.css`.
105
+
106
+ Read more at [honeydeck.dev](https://honeydeck.dev)
107
+
108
+ ---
109
+
110
+ # Presenter mode + notes 🎤
111
+
112
+ Speaker notes stay hidden from the audience but show up in presenter mode.
113
+
114
+ ```mdx
115
+ <Notes>
116
+ Mention the surprising part here.
117
+ Keep yourself on track.
118
+ </Notes>
119
+ ```
120
+
121
+ Press <Keyboard>p</Keyboard> to open presenter mode, with current slide, next preview, notes, and a timer.
122
+
123
+ <Notes>
124
+
125
+ This is a real note for the presenter. It should show in presenter mode and never render on the audience slide.
126
+
127
+ </Notes>
128
+
129
+ ---
130
+
131
+ # PDF export 📚
132
+
133
+ Export your presentation with one command.
134
+
135
+ ```bash
136
+ # Export with default settings
137
+ npm run pdf
138
+
139
+ # Export every reveal step as a separate page
140
+ npx honeydeck pdf --steps all
141
+
142
+ # Force dark mode
143
+ npx honeydeck pdf --mode dark
144
+ ```
145
+
146
+ ---
147
+ layout: Cover
148
+ author: Happy presenting 🎞️
149
+ ---
150
+
151
+ # Get started 🚀
152
+
153
+ Edit `deck.mdx`, open the [theme reference](/#/theme), and build something fun.
@@ -0,0 +1,14 @@
1
+ @import "tailwindcss";
2
+ @import "@honeydeck/honeydeck/theme.css";
3
+
4
+ /*
5
+ * honeydeck/theme.css is the clean black/white/grey default.
6
+ * Bee theme: uncomment the next line.
7
+ * Custom theme: import your CSS here or override --honeydeck-* tokens below.
8
+ */
9
+ /* @import "@honeydeck/honeydeck/themes/bee.css"; */
10
+
11
+ /* Slightly dim images in dark mode */
12
+ [data-honeydeck-color-mode="dark"] img {
13
+ opacity: 0.9;
14
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Template generator for styles.css in a new honeydeck project.
3
+ */
4
+
5
+ import { readFileSync } from "node:fs";
6
+
7
+ const STARTER_STYLES_TEMPLATE = readFileSync(
8
+ new URL("./starter/styles.css", import.meta.url),
9
+ "utf-8",
10
+ );
11
+
12
+ export function generateStylesCss(): string {
13
+ return STARTER_STYLES_TEMPLATE;
14
+ }
@@ -0,0 +1 @@
1
+ export const DEFAULT_DECK_ENTRY = "deck.mdx";
@@ -0,0 +1,55 @@
1
+ import type { ImgHTMLAttributes } from "react";
2
+ import { cn } from "./utils.ts";
3
+
4
+ export type DarkModeImageFrontmatter = {
5
+ /** Image URL or import used in light mode. */
6
+ image?: string;
7
+ /** Optional image URL or import used in dark mode. */
8
+ darkImage?: string;
9
+ };
10
+
11
+ export type ColorModeImageProps = Omit<
12
+ ImgHTMLAttributes<HTMLImageElement>,
13
+ "src"
14
+ > & {
15
+ src?: string;
16
+ darkSrc?: string;
17
+ };
18
+
19
+ export function ColorModeImage({
20
+ src,
21
+ darkSrc,
22
+ alt = "",
23
+ className,
24
+ ...props
25
+ }: ColorModeImageProps) {
26
+ if (!src && !darkSrc) return null;
27
+
28
+ return (
29
+ <>
30
+ {src ? (
31
+ <img
32
+ {...props}
33
+ src={src}
34
+ alt={alt}
35
+ className={cn(
36
+ "block",
37
+ darkSrc && "[[data-honeydeck-color-mode=dark]_&]:hidden",
38
+ className,
39
+ )}
40
+ />
41
+ ) : null}
42
+ {darkSrc ? (
43
+ <img
44
+ {...props}
45
+ src={darkSrc}
46
+ alt={alt}
47
+ className={cn(
48
+ "hidden [[data-honeydeck-color-mode=dark]_&]:block",
49
+ className,
50
+ )}
51
+ />
52
+ ) : null}
53
+ </>
54
+ );
55
+ }