create-slide-deck 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 (105) hide show
  1. package/dist/index.js +119 -0
  2. package/package.json +36 -0
  3. package/template-full/README.md +99 -0
  4. package/template-full/package.json +47 -0
  5. package/template-full/src/reveal/components/auto-layout.ts +229 -0
  6. package/template-full/src/reveal/components/charts.tsx +213 -0
  7. package/template-full/src/reveal/core/blocks.ts +172 -0
  8. package/template-full/src/reveal/core/deck-init.ts +60 -0
  9. package/template-full/src/reveal/core/design.ts +46 -0
  10. package/template-full/src/reveal/core/layout.ts +187 -0
  11. package/template-full/src/reveal/core/mount-registry.ts +41 -0
  12. package/template-full/src/reveal/core/presets.ts +189 -0
  13. package/template-full/src/reveal/core/runtime.ts +141 -0
  14. package/template-full/src/reveal/core/types.ts +114 -0
  15. package/template-full/src/reveal/data/algorithms.ts +78 -0
  16. package/template-full/src/reveal/data/benchmark.ts +79 -0
  17. package/template-full/src/reveal/decks/demo-showcase/components/demo-arc-progress.tsx +153 -0
  18. package/template-full/src/reveal/decks/demo-showcase/components/demo-before-after.tsx +164 -0
  19. package/template-full/src/reveal/decks/demo-showcase/components/demo-bigtext.tsx +70 -0
  20. package/template-full/src/reveal/decks/demo-showcase/components/demo-card-flip.tsx +118 -0
  21. package/template-full/src/reveal/decks/demo-showcase/components/demo-chat-bubbles.tsx +257 -0
  22. package/template-full/src/reveal/decks/demo-showcase/components/demo-code.tsx +136 -0
  23. package/template-full/src/reveal/decks/demo-showcase/components/demo-concept-map.tsx +336 -0
  24. package/template-full/src/reveal/decks/demo-showcase/components/demo-counter.tsx +194 -0
  25. package/template-full/src/reveal/decks/demo-showcase/components/demo-cover.tsx +188 -0
  26. package/template-full/src/reveal/decks/demo-showcase/components/demo-dark-dashboard.tsx +166 -0
  27. package/template-full/src/reveal/decks/demo-showcase/components/demo-eval-matrix.tsx +191 -0
  28. package/template-full/src/reveal/decks/demo-showcase/components/demo-force-graph.tsx +169 -0
  29. package/template-full/src/reveal/decks/demo-showcase/components/demo-fullbleed-bars.tsx +109 -0
  30. package/template-full/src/reveal/decks/demo-showcase/components/demo-fullbleed-flow.tsx +177 -0
  31. package/template-full/src/reveal/decks/demo-showcase/components/demo-heatmap.tsx +135 -0
  32. package/template-full/src/reveal/decks/demo-showcase/components/demo-icon-wall.tsx +143 -0
  33. package/template-full/src/reveal/decks/demo-showcase/components/demo-math.tsx +103 -0
  34. package/template-full/src/reveal/decks/demo-showcase/components/demo-number-morph.tsx +126 -0
  35. package/template-full/src/reveal/decks/demo-showcase/components/demo-path.tsx +185 -0
  36. package/template-full/src/reveal/decks/demo-showcase/components/demo-radar.tsx +124 -0
  37. package/template-full/src/reveal/decks/demo-showcase/components/demo-rough.tsx +169 -0
  38. package/template-full/src/reveal/decks/demo-showcase/components/demo-sankey.tsx +144 -0
  39. package/template-full/src/reveal/decks/demo-showcase/components/demo-screenshot-annotate.tsx +181 -0
  40. package/template-full/src/reveal/decks/demo-showcase/components/demo-stacked-cards.tsx +159 -0
  41. package/template-full/src/reveal/decks/demo-showcase/components/demo-tabs.tsx +206 -0
  42. package/template-full/src/reveal/decks/demo-showcase/components/demo-timeline.tsx +162 -0
  43. package/template-full/src/reveal/decks/demo-showcase/components/demo-treemap.tsx +161 -0
  44. package/template-full/src/reveal/decks/demo-showcase/components/demo-zoom-focus.tsx +223 -0
  45. package/template-full/src/reveal/decks/demo-showcase/components/registry.ts +63 -0
  46. package/template-full/src/reveal/decks/demo-showcase/demo.css +237 -0
  47. package/template-full/src/reveal/decks/demo-showcase/index.html +24 -0
  48. package/template-full/src/reveal/decks/demo-showcase/main.ts +7 -0
  49. package/template-full/src/reveal/decks/demo-showcase/slides.ts +271 -0
  50. package/template-full/src/reveal/decks/fse26-rca/components/aws-cascade.tsx +295 -0
  51. package/template-full/src/reveal/decks/fse26-rca/components/bench-compare.tsx +64 -0
  52. package/template-full/src/reveal/decks/fse26-rca/components/bench-deficiency.tsx +104 -0
  53. package/template-full/src/reveal/decks/fse26-rca/components/bench-loop.tsx +402 -0
  54. package/template-full/src/reveal/decks/fse26-rca/components/bench-needs.tsx +78 -0
  55. package/template-full/src/reveal/decks/fse26-rca/components/closing-takeaway.tsx +165 -0
  56. package/template-full/src/reveal/decks/fse26-rca/components/cloud-incidents.tsx +88 -0
  57. package/template-full/src/reveal/decks/fse26-rca/components/failure-modes.tsx +59 -0
  58. package/template-full/src/reveal/decks/fse26-rca/components/fault-heatmap.tsx +85 -0
  59. package/template-full/src/reveal/decks/fse26-rca/components/hierarchy-tree.tsx +93 -0
  60. package/template-full/src/reveal/decks/fse26-rca/components/incident-hard.tsx +72 -0
  61. package/template-full/src/reveal/decks/fse26-rca/components/rca-pipeline.tsx +193 -0
  62. package/template-full/src/reveal/decks/fse26-rca/components/registry.ts +37 -0
  63. package/template-full/src/reveal/decks/fse26-rca/components/simple-rca.tsx +216 -0
  64. package/template-full/src/reveal/decks/fse26-rca/components/sota-collapse.tsx +63 -0
  65. package/template-full/src/reveal/decks/fse26-rca/components/srca-results.tsx +115 -0
  66. package/template-full/src/reveal/decks/fse26-rca/images/aws-outage-2025-deployflow.png +0 -0
  67. package/template-full/src/reveal/decks/fse26-rca/images/aws-post-event-summary.png +0 -0
  68. package/template-full/src/reveal/decks/fse26-rca/images/bbc-crowdstrike.png +0 -0
  69. package/template-full/src/reveal/decks/fse26-rca/images/cnn-meta-outage-2021.png +0 -0
  70. package/template-full/src/reveal/decks/fse26-rca/images/cover.png +0 -0
  71. package/template-full/src/reveal/decks/fse26-rca/images/nyt-facebook-2021.png +0 -0
  72. package/template-full/src/reveal/decks/fse26-rca/images/qr-repo.png +0 -0
  73. package/template-full/src/reveal/decks/fse26-rca/images/verge-crowdstrike-2024.png +0 -0
  74. package/template-full/src/reveal/decks/fse26-rca/images/wiki-meta-outage-2021.png +0 -0
  75. package/template-full/src/reveal/decks/fse26-rca/index.html +30 -0
  76. package/template-full/src/reveal/decks/fse26-rca/main.ts +8 -0
  77. package/template-full/src/reveal/decks/fse26-rca/slides.ts +175 -0
  78. package/template-full/src/reveal/env.d.ts +38 -0
  79. package/template-full/src/reveal/theme.css +762 -0
  80. package/template-full/src/reveal/tools/dev.mjs +120 -0
  81. package/template-full/src/reveal/tools/export-pdf.mjs +86 -0
  82. package/template-full/src/reveal/tools/preview.mjs +132 -0
  83. package/template-full/tsconfig.json +19 -0
  84. package/template-full/vite.config.ts +95 -0
  85. package/template-minimal/package.json +42 -0
  86. package/template-minimal/src/reveal/components/auto-layout.ts +229 -0
  87. package/template-minimal/src/reveal/components/charts.tsx +213 -0
  88. package/template-minimal/src/reveal/core/blocks.ts +172 -0
  89. package/template-minimal/src/reveal/core/deck-init.ts +60 -0
  90. package/template-minimal/src/reveal/core/design.ts +46 -0
  91. package/template-minimal/src/reveal/core/layout.ts +187 -0
  92. package/template-minimal/src/reveal/core/mount-registry.ts +41 -0
  93. package/template-minimal/src/reveal/core/presets.ts +189 -0
  94. package/template-minimal/src/reveal/core/runtime.ts +141 -0
  95. package/template-minimal/src/reveal/core/types.ts +114 -0
  96. package/template-minimal/src/reveal/data/.gitkeep +0 -0
  97. package/template-minimal/src/reveal/decks/my-deck/components/example-component.tsx +28 -0
  98. package/template-minimal/src/reveal/decks/my-deck/components/registry.ts +9 -0
  99. package/template-minimal/src/reveal/decks/my-deck/index.html +14 -0
  100. package/template-minimal/src/reveal/decks/my-deck/main.ts +5 -0
  101. package/template-minimal/src/reveal/decks/my-deck/slides.ts +34 -0
  102. package/template-minimal/src/reveal/env.d.ts +38 -0
  103. package/template-minimal/src/reveal/theme.css +762 -0
  104. package/template-minimal/tsconfig.json +19 -0
  105. package/template-minimal/vite.config.ts +95 -0
@@ -0,0 +1,223 @@
1
+ import React from "react";
2
+ import type { SlideComponentProps } from "../../../core/types.ts";
3
+ import { CANVAS, useRevealStep } from "../../../core/presets.ts";
4
+
5
+ const anime = typeof window !== "undefined" ? (window as any).anime : null;
6
+
7
+ const COLORS = {
8
+ idle: "#e5e7eb",
9
+ idleStroke: "#cbd5e1",
10
+ blue: "#4361ee",
11
+ purple: "#7c3aed",
12
+ green: "#059669",
13
+ text: "#313131",
14
+ line: "#d1d5db",
15
+ };
16
+
17
+ // id, x, y, label, focusColor, cluster (1 = gateway cluster, 2 = orders cluster)
18
+ const NODES = [
19
+ { id: "gateway", x: 230, y: 150, label: "Gateway", color: COLORS.blue, cluster: 1 },
20
+ { id: "auth", x: 430, y: 90, label: "Auth", color: COLORS.blue, cluster: 1 },
21
+ { id: "users", x: 430, y: 230, label: "Users", color: COLORS.blue, cluster: 1 },
22
+ { id: "orders", x: 720, y: 150, label: "Orders", color: COLORS.purple, cluster: 2 },
23
+ { id: "products", x: 940, y: 110, label: "Products", color: COLORS.purple, cluster: 2 },
24
+ { id: "database", x: 940, y: 320, label: "Database", color: COLORS.green, cluster: 2 },
25
+ { id: "cache", x: 620, y: 410, label: "Cache", color: COLORS.green, cluster: 0 },
26
+ { id: "queue", x: 300, y: 410, label: "Queue", color: COLORS.green, cluster: 0 },
27
+ ];
28
+
29
+ const LINKS: [string, string][] = [
30
+ ["gateway", "auth"],
31
+ ["gateway", "users"],
32
+ ["gateway", "orders"],
33
+ ["auth", "users"],
34
+ ["orders", "products"],
35
+ ["orders", "database"],
36
+ ["products", "database"],
37
+ ["orders", "cache"],
38
+ ["users", "queue"],
39
+ ["gateway", "queue"],
40
+ ];
41
+
42
+ const ANNOTATIONS: Record<string, string> = {
43
+ gateway: "Edge router, 12k rps",
44
+ auth: "JWT, p99 18ms",
45
+ users: "Profile store, OK",
46
+ orders: "p99 2.8s — degraded",
47
+ products: "Catalog cache miss",
48
+ database: "Pool exhausted 50/50",
49
+ };
50
+
51
+ // Per-step camera transform on the 1200x560 base canvas.
52
+ // scale s, then translate so the region of interest is centered.
53
+ const CAMERAS: Record<number, { s: number; tx: number; ty: number }> = {
54
+ 0: { s: 1, tx: 0, ty: 0 },
55
+ 1: { s: 2.0, tx: -330, ty: -130 },
56
+ 2: { s: 2.0, tx: -1010, ty: -210 },
57
+ 3: { s: 1, tx: 0, ty: 0 },
58
+ };
59
+
60
+ function nodeById(id: string) {
61
+ for (let i = 0; i < NODES.length; i++) if (NODES[i].id === id) return NODES[i];
62
+ return null;
63
+ }
64
+
65
+ // Which clusters are "focused" (colored) at a given step.
66
+ function focusedClusters(step: number): Record<number, boolean> {
67
+ if (step === 1) return { 1: true };
68
+ if (step === 2) return { 2: true };
69
+ if (step >= 3) return { 1: true, 2: true };
70
+ return {};
71
+ }
72
+
73
+ // Detail annotations are visible only while zoomed into a single cluster.
74
+ function annotationsVisible(step: number) {
75
+ return step === 1 || step === 2;
76
+ }
77
+
78
+ export default function DemoZoomFocus(props: SlideComponentProps) {
79
+ const Reveal = props.Reveal;
80
+ const ref = useRevealStep(Reveal);
81
+ const step = ref[0], ready = ref[1], instant = ref[2];
82
+ const camRef = React.useRef<SVGGElement>(null);
83
+ const lastStep = React.useRef<number | null>(null);
84
+
85
+ React.useEffect(function () {
86
+ const g = camRef.current;
87
+ if (!g) return;
88
+ const s = step < 0 ? 0 : step;
89
+ const cam = CAMERAS[s] || CAMERAS[0];
90
+ const transform =
91
+ "translate(" + cam.tx + "px," + cam.ty + "px) scale(" + cam.s + ")";
92
+
93
+ // Skip animation on first paint / slide reset / no actual change.
94
+ if (instant || lastStep.current === null || lastStep.current === s) {
95
+ g.style.transform = transform;
96
+ lastStep.current = s;
97
+ return;
98
+ }
99
+ lastStep.current = s;
100
+
101
+ if (!anime || !anime.animate) {
102
+ g.style.transform = transform;
103
+ return;
104
+ }
105
+ anime.animate(g, {
106
+ translateX: cam.tx,
107
+ translateY: cam.ty,
108
+ scale: cam.s,
109
+ duration: 800,
110
+ ease: "inOutQuad",
111
+ });
112
+ }, [step, instant]);
113
+
114
+ const s = step < 0 ? 0 : step;
115
+ const focus = focusedClusters(s);
116
+ const showAnno = annotationsVisible(s);
117
+
118
+ return (
119
+ <div
120
+ style={{
121
+ width: "100%",
122
+ height: "100%",
123
+ background: "#ffffff",
124
+ opacity: ready ? 1 : 0,
125
+ transition: "opacity 0.2s ease",
126
+ fontFamily: CANVAS.fontFamily,
127
+ overflow: "hidden",
128
+ }}
129
+ >
130
+ <svg viewBox="0 0 1200 560" style={{ width: "100%", height: "100%", display: "block" }}>
131
+ <g
132
+ ref={camRef}
133
+ style={{
134
+ transformOrigin: "0px 0px",
135
+ transformBox: "view-box",
136
+ willChange: "transform",
137
+ }}
138
+ >
139
+ {LINKS.map(function (lk, i: number) {
140
+ const a = nodeById(lk[0]);
141
+ const b = nodeById(lk[1]);
142
+ if (!a || !b) return null;
143
+ return (
144
+ <line
145
+ key={"lk" + i}
146
+ x1={a.x}
147
+ y1={a.y}
148
+ x2={b.x}
149
+ y2={b.y}
150
+ stroke={COLORS.line}
151
+ strokeWidth={1.5}
152
+ />
153
+ );
154
+ })}
155
+
156
+ {NODES.map(function (n) {
157
+ const lit = n.cluster !== 0 && focus[n.cluster];
158
+ const fill = lit ? n.color : COLORS.idle;
159
+ const stroke = lit ? n.color : COLORS.idleStroke;
160
+ const labelColor = lit ? "#ffffff" : COLORS.text;
161
+ return (
162
+ <g key={n.id} style={{ transition: instant ? "none" : "all 0.4s ease" }}>
163
+ <circle
164
+ cx={n.x}
165
+ cy={n.y}
166
+ r={34}
167
+ fill={fill}
168
+ stroke={stroke}
169
+ strokeWidth={2}
170
+ style={{ transition: instant ? "none" : "fill 0.4s ease, stroke 0.4s ease" }}
171
+ />
172
+ <text
173
+ x={n.x}
174
+ y={n.y}
175
+ textAnchor="middle"
176
+ dominantBaseline="central"
177
+ style={{
178
+ fontFamily: CANVAS.fontFamily,
179
+ fontSize: 15,
180
+ fontWeight: 700,
181
+ fill: labelColor,
182
+ transition: instant ? "none" : "fill 0.4s ease",
183
+ }}
184
+ >
185
+ {n.label}
186
+ </text>
187
+
188
+ {showAnno && lit && ANNOTATIONS[n.id] ? (
189
+ <g style={{ opacity: 1, transition: instant ? "none" : "opacity 0.4s ease" }}>
190
+ <rect
191
+ x={n.x - 60}
192
+ y={n.y + 40}
193
+ width={120}
194
+ height={26}
195
+ rx={6}
196
+ fill="#ffffff"
197
+ stroke={n.color}
198
+ strokeWidth={1}
199
+ />
200
+ <text
201
+ x={n.x}
202
+ y={n.y + 53}
203
+ textAnchor="middle"
204
+ dominantBaseline="central"
205
+ style={{
206
+ fontFamily: CANVAS.fontFamily,
207
+ fontSize: 14,
208
+ fontWeight: 600,
209
+ fill: n.color,
210
+ }}
211
+ >
212
+ {ANNOTATIONS[n.id]}
213
+ </text>
214
+ </g>
215
+ ) : null}
216
+ </g>
217
+ );
218
+ })}
219
+ </g>
220
+ </svg>
221
+ </div>
222
+ );
223
+ }
@@ -0,0 +1,63 @@
1
+ import type { ComponentType } from "react";
2
+ import type { SlideComponentProps } from "../../../core/types.ts";
3
+ import DemoCover from "./demo-cover.tsx";
4
+ import DemoForceGraph from "./demo-force-graph.tsx";
5
+ import DemoSankey from "./demo-sankey.tsx";
6
+ import DemoCounter from "./demo-counter.tsx";
7
+ import DemoRough from "./demo-rough.tsx";
8
+ import DemoIconWall from "./demo-icon-wall.tsx";
9
+ import DemoCode from "./demo-code.tsx";
10
+ import DemoRadar from "./demo-radar.tsx";
11
+ import DemoTimeline from "./demo-timeline.tsx";
12
+ import DemoCardFlip from "./demo-card-flip.tsx";
13
+ import DemoMath from "./demo-math.tsx";
14
+ import DemoTreemap from "./demo-treemap.tsx";
15
+ import DemoTabs from "./demo-tabs.tsx";
16
+ import DemoPath from "./demo-path.tsx";
17
+ import DemoHeatmap from "./demo-heatmap.tsx";
18
+ import DemoFullbleedBars from "./demo-fullbleed-bars.tsx";
19
+ import DemoDashboard from "./demo-dark-dashboard.tsx";
20
+ import DemoBigText from "./demo-bigtext.tsx";
21
+ import DemoBeforeAfter from "./demo-before-after.tsx";
22
+ import DemoScreenshotAnnotate from "./demo-screenshot-annotate.tsx";
23
+ import DemoFullbleedFlow from "./demo-fullbleed-flow.tsx";
24
+ import DemoZoomFocus from "./demo-zoom-focus.tsx";
25
+ import DemoChatBubbles from "./demo-chat-bubbles.tsx";
26
+ import DemoStackedCards from "./demo-stacked-cards.tsx";
27
+ import DemoConceptMap from "./demo-concept-map.tsx";
28
+ import DemoNumberMorph from "./demo-number-morph.tsx";
29
+ import DemoArcProgress from "./demo-arc-progress.tsx";
30
+ import DemoEvalMatrix from "./demo-eval-matrix.tsx";
31
+
32
+ export const components = {
33
+ DemoCover,
34
+ DemoForceGraph,
35
+ DemoSankey,
36
+ DemoCounter,
37
+ DemoRough,
38
+ DemoIconWall,
39
+ DemoCode,
40
+ DemoRadar,
41
+ DemoTimeline,
42
+ DemoCardFlip,
43
+ DemoMath,
44
+ DemoTreemap,
45
+ DemoTabs,
46
+ DemoPath,
47
+ DemoHeatmap,
48
+ DemoFullbleedBars,
49
+ DemoDashboard,
50
+ DemoBigText,
51
+ DemoBeforeAfter,
52
+ DemoScreenshotAnnotate,
53
+ DemoFullbleedFlow,
54
+ DemoZoomFocus,
55
+ DemoChatBubbles,
56
+ DemoStackedCards,
57
+ DemoConceptMap,
58
+ DemoNumberMorph,
59
+ DemoArcProgress,
60
+ DemoEvalMatrix,
61
+ } satisfies Record<string, ComponentType<SlideComponentProps>>;
62
+
63
+ export type ComponentName = keyof typeof components;
@@ -0,0 +1,237 @@
1
+ /* Demo deck supplementary styles */
2
+
3
+ /* KaTeX essential overrides */
4
+ .katex-display {
5
+ margin: 0.5em 0;
6
+ }
7
+ .katex {
8
+ font-size: 1.4em;
9
+ }
10
+
11
+ /* Prism code block dark theme */
12
+ .demo-code-block {
13
+ background: #1e1e1e;
14
+ border-radius: 12px;
15
+ padding: 24px 28px;
16
+ font-family: "JetBrains Mono", "Fira Code", Consolas, monospace;
17
+ font-size: 15px;
18
+ line-height: 1.6;
19
+ overflow: hidden;
20
+ box-shadow: 0 4px 24px rgba(0,0,0,0.3);
21
+ }
22
+ .demo-code-block .token.keyword { color: #569cd6; }
23
+ .demo-code-block .token.string { color: #ce9178; }
24
+ .demo-code-block .token.function { color: #dcdcaa; }
25
+ .demo-code-block .token.comment { color: #6a9955; font-style: italic; }
26
+ .demo-code-block .token.number { color: #b5cea8; }
27
+ .demo-code-block .token.operator { color: #d4d4d4; }
28
+ .demo-code-block .token.punctuation { color: #d4d4d4; }
29
+ .demo-code-block .token.class-name { color: #4ec9b0; }
30
+ .demo-code-block .token.boolean { color: #569cd6; }
31
+ .demo-code-block .token.template-string { color: #ce9178; }
32
+
33
+ /* Card flip 3D */
34
+ .flip-card {
35
+ perspective: 1000px;
36
+ width: 280px;
37
+ height: 350px;
38
+ }
39
+ .flip-card-inner {
40
+ position: relative;
41
+ width: 100%;
42
+ height: 100%;
43
+ transition: transform 0.6s ease;
44
+ transform-style: preserve-3d;
45
+ }
46
+ .flip-card-inner.flipped {
47
+ transform: rotateY(180deg);
48
+ }
49
+ .flip-card-inner.instant {
50
+ transition: none;
51
+ }
52
+ .flip-card-face {
53
+ position: absolute;
54
+ width: 100%;
55
+ height: 100%;
56
+ backface-visibility: hidden;
57
+ border-radius: 16px;
58
+ display: flex;
59
+ flex-direction: column;
60
+ align-items: center;
61
+ justify-content: center;
62
+ padding: 30px;
63
+ box-sizing: border-box;
64
+ }
65
+ .flip-card-front {
66
+ background: #fff;
67
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
68
+ }
69
+ .flip-card-back {
70
+ background: linear-gradient(135deg, #4361ee, #3a0ca3);
71
+ color: #fff;
72
+ transform: rotateY(180deg);
73
+ }
74
+
75
+ /* Demo grid for icon wall */
76
+ .demo-icon-grid {
77
+ display: grid;
78
+ grid-template-columns: repeat(4, 1fr);
79
+ gap: 16px;
80
+ max-width: 700px;
81
+ margin: 0 auto;
82
+ }
83
+ .demo-icon-cell {
84
+ display: flex;
85
+ flex-direction: column;
86
+ align-items: center;
87
+ justify-content: center;
88
+ padding: 20px 10px;
89
+ border-radius: 12px;
90
+ background: #f8f9fa;
91
+ transition: background 0.3s ease, transform 0.3s ease;
92
+ }
93
+ .demo-icon-cell.colored {
94
+ background: #fff;
95
+ box-shadow: 0 2px 12px rgba(0,0,0,0.06);
96
+ }
97
+ .demo-icon-cell .icon-label {
98
+ margin-top: 10px;
99
+ font-size: 13px;
100
+ color: #666;
101
+ font-weight: 500;
102
+ }
103
+
104
+ /* Tab bar for demo-tabs */
105
+ .demo-tab-bar {
106
+ display: flex;
107
+ gap: 0;
108
+ border-bottom: 2px solid #eee;
109
+ margin-bottom: 24px;
110
+ }
111
+ .demo-tab-btn {
112
+ padding: 12px 28px;
113
+ border: none;
114
+ background: none;
115
+ font-size: 16px;
116
+ font-weight: 600;
117
+ color: #999;
118
+ cursor: pointer;
119
+ position: relative;
120
+ transition: color 0.3s ease;
121
+ }
122
+ .demo-tab-btn.active {
123
+ color: #4361ee;
124
+ }
125
+ .demo-tab-content {
126
+ background: #fff;
127
+ border-radius: 12px;
128
+ padding: 32px;
129
+ min-height: 360px;
130
+ box-shadow: 0 2px 16px rgba(0,0,0,0.05);
131
+ }
132
+
133
+ /* Counter cards */
134
+ .demo-counter-row {
135
+ display: flex;
136
+ gap: 24px;
137
+ justify-content: center;
138
+ }
139
+ .demo-counter-card {
140
+ background: #fff;
141
+ border-radius: 16px;
142
+ padding: 28px 24px;
143
+ width: 220px;
144
+ text-align: center;
145
+ box-shadow: 0 4px 20px rgba(0,0,0,0.06);
146
+ border-top: 4px solid;
147
+ }
148
+ .demo-counter-value {
149
+ font-size: 42px;
150
+ font-weight: 800;
151
+ line-height: 1.2;
152
+ }
153
+ .demo-counter-label {
154
+ font-size: 14px;
155
+ color: #888;
156
+ margin-top: 6px;
157
+ font-weight: 600;
158
+ text-transform: uppercase;
159
+ letter-spacing: 1px;
160
+ }
161
+ .demo-progress-bar {
162
+ height: 6px;
163
+ border-radius: 3px;
164
+ background: #eee;
165
+ margin-top: 16px;
166
+ overflow: hidden;
167
+ }
168
+ .demo-progress-fill {
169
+ height: 100%;
170
+ border-radius: 3px;
171
+ width: 0%;
172
+ transition: width 1s ease;
173
+ }
174
+
175
+ /* Cover slide */
176
+ .demo-cover {
177
+ width: 100%;
178
+ height: 100%;
179
+ display: flex;
180
+ flex-direction: column;
181
+ align-items: center;
182
+ justify-content: center;
183
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
184
+ color: #fff;
185
+ position: relative;
186
+ overflow: hidden;
187
+ }
188
+ .demo-cover-title {
189
+ font-size: 64px;
190
+ font-weight: 800;
191
+ letter-spacing: -1px;
192
+ margin: 0;
193
+ }
194
+ .demo-cover-title span {
195
+ display: inline-block;
196
+ opacity: 0;
197
+ }
198
+ .demo-cover-subtitle {
199
+ font-size: 22px;
200
+ color: rgba(255,255,255,0.6);
201
+ margin-top: 16px;
202
+ font-weight: 400;
203
+ }
204
+ .demo-cover-dot {
205
+ position: absolute;
206
+ border-radius: 50%;
207
+ opacity: 0;
208
+ }
209
+
210
+ /* Formula cards */
211
+ .demo-formula-card {
212
+ background: #fff;
213
+ border-radius: 16px;
214
+ padding: 24px 40px;
215
+ max-width: 900px;
216
+ margin: 0 auto 16px;
217
+ box-shadow: 0 2px 12px rgba(0,0,0,0.05);
218
+ }
219
+ .demo-formula-label {
220
+ font-size: 16px;
221
+ font-weight: 700;
222
+ color: #4361ee;
223
+ margin-bottom: 8px;
224
+ }
225
+
226
+ /* Rough diagram */
227
+ .demo-rough-container {
228
+ width: 100%;
229
+ height: 100%;
230
+ display: flex;
231
+ align-items: center;
232
+ justify-content: center;
233
+ }
234
+ .demo-rough-container svg {
235
+ width: 1100px;
236
+ height: 500px;
237
+ }
@@ -0,0 +1,24 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Component Showcase — Demo Deck</title>
7
+ </head>
8
+ <body>
9
+ <svg class="global-svg-defs" width="0" height="0" aria-hidden="true" focusable="false">
10
+ <defs>
11
+ <marker id="arrow-gray" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="8.5" markerHeight="8.5" orient="auto-start-reverse">
12
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#BFBFBF"></path>
13
+ </marker>
14
+ <marker id="arrow-red" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="8.5" markerHeight="8.5" orient="auto-start-reverse">
15
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#C00000"></path>
16
+ </marker>
17
+ </defs>
18
+ </svg>
19
+ <div class="reveal">
20
+ <div class="slides"></div>
21
+ </div>
22
+ <script type="module" src="./main.ts"></script>
23
+ </body>
24
+ </html>
@@ -0,0 +1,7 @@
1
+ import "katex/dist/katex.min.css";
2
+ import "./demo.css";
3
+ import { components } from "./components/registry.ts";
4
+ import { buildSlides } from "./slides.ts";
5
+ import { initDeck } from "../../core/deck-init.ts";
6
+
7
+ initDeck({ buildSlides, components });