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,41 @@
1
+ import React from "react";
2
+ import { createRoot, type Root } from "react-dom/client";
3
+ import type { ComponentRegistry, MountContext } from "./types.ts";
4
+
5
+ const roots = new WeakMap<Element, Root>();
6
+
7
+ let registeredComponents: ComponentRegistry = {};
8
+
9
+ export function registerComponents(components: ComponentRegistry): void {
10
+ registeredComponents = components;
11
+ }
12
+
13
+ export function hydrate(root: Element, ctx: MountContext): void {
14
+ root.querySelectorAll<HTMLElement>(".block-mount[data-mount-library]").forEach((el) => {
15
+ if (roots.has(el)) return;
16
+ const exportName = el.dataset.mountExport;
17
+ if (!exportName) return;
18
+ const Component = registeredComponents[exportName];
19
+ if (!Component) {
20
+ console.warn(`[mount-registry] component '${exportName}' not found in registry`);
21
+ return;
22
+ }
23
+ const propsStr = el.dataset.mountProps;
24
+ const extraProps = propsStr ? JSON.parse(propsStr) : {};
25
+ const reactRoot = createRoot(el);
26
+ reactRoot.render(
27
+ React.createElement(Component, { ...extraProps, Reveal: ctx.Reveal })
28
+ );
29
+ roots.set(el, reactRoot);
30
+ });
31
+ }
32
+
33
+ export function cleanup(root: Element): void {
34
+ root.querySelectorAll<HTMLElement>(".block-mount[data-mount-library]").forEach((el) => {
35
+ const reactRoot = roots.get(el);
36
+ if (reactRoot) {
37
+ reactRoot.unmount();
38
+ roots.delete(el);
39
+ }
40
+ });
41
+ }
@@ -0,0 +1,189 @@
1
+ import React, { useState, useEffect, type ReactNode, type CSSProperties } from "react";
2
+ import type { RevealInstance } from "./types.ts";
3
+
4
+ export const MIN_FONT = 14;
5
+
6
+ export const FONT = {
7
+ hero: 64,
8
+ heading: 40,
9
+ title: 20,
10
+ body: 16,
11
+ caption: 14,
12
+ } as const;
13
+
14
+ export const COLOR = {
15
+ text: "#313131",
16
+ muted: "#767676",
17
+ bg: "#ffffff",
18
+ bgSubtle: "rgba(67, 97, 238, 0.04)",
19
+ border: "#e5e7eb",
20
+ blue: "#4361ee",
21
+ purple: "#7c3aed",
22
+ pink: "#f72585",
23
+ cyan: "#4cc9f0",
24
+ green: "#059669",
25
+ orange: "#f78166",
26
+ success: "#059669",
27
+ danger: "#dc2626",
28
+ warn: "#d97706",
29
+ series: ["#4361ee", "#7c3aed", "#f72585", "#4cc9f0", "#059669", "#f78166"],
30
+ } as const;
31
+
32
+ export const NODE = {
33
+ radius: 42,
34
+ radiusAccent: 46,
35
+ iconSize: 28,
36
+ strokeWidth: 3,
37
+ strokeWidthAccent: 4,
38
+ labelFont: 20,
39
+ subFont: 15,
40
+ labelColor: "#313131",
41
+ } as const;
42
+
43
+ export const DETAIL = {
44
+ width: 580,
45
+ height: 220,
46
+ margin: 14,
47
+ scanStep: 14,
48
+ illustrationRatio: 0.5,
49
+ titleFont: 20,
50
+ bodyFont: 16,
51
+ titleColor: "#313131",
52
+ bodyColor: "#767676",
53
+ bgOpacity: 0.85,
54
+ } as const;
55
+
56
+ export const TAG = {
57
+ font: 14,
58
+ pillFont: 14,
59
+ pillHeight: 24,
60
+ pillRadius: 12,
61
+ } as const;
62
+
63
+ export const EDGE = {
64
+ color: "#BFBFBF",
65
+ colorCascade: "#C00000",
66
+ width: 2.5,
67
+ markerSize: 7,
68
+ } as const;
69
+
70
+ export const CANVAS = {
71
+ fontFamily: "Aptos, Arial, sans-serif",
72
+ } as const;
73
+
74
+ export function annotationStyle(): CSSProperties {
75
+ return {
76
+ width: "100%",
77
+ height: "100%",
78
+ display: "flex",
79
+ flexDirection: "row",
80
+ alignItems: "center",
81
+ justifyContent: "center",
82
+ fontFamily: CANVAS.fontFamily,
83
+ gap: 20,
84
+ padding: "12px 24px",
85
+ boxSizing: "border-box",
86
+ };
87
+ }
88
+
89
+ export function illustrationStyle(): CSSProperties {
90
+ return {
91
+ flex: "0 0 auto",
92
+ width: (DETAIL.illustrationRatio * 100) + "%",
93
+ maxHeight: "100%",
94
+ };
95
+ }
96
+
97
+ export function annotationTitleStyle(): CSSProperties {
98
+ return {
99
+ fontSize: DETAIL.titleFont,
100
+ fontWeight: 800,
101
+ color: DETAIL.titleColor,
102
+ lineHeight: 1.4,
103
+ };
104
+ }
105
+
106
+ export function annotationBodyStyle(): CSSProperties {
107
+ return {
108
+ fontSize: DETAIL.bodyFont,
109
+ fontWeight: 700,
110
+ color: DETAIL.bodyColor,
111
+ lineHeight: 1.3,
112
+ };
113
+ }
114
+
115
+ export function vis(cur: number, req: number, instant: boolean): CSSProperties {
116
+ const show = cur >= req ? 1 : 0;
117
+ return { opacity: show, transition: instant ? "none" : "opacity 0.45s ease" };
118
+ }
119
+
120
+ export function visExact(cur: number, req: number, instant: boolean): CSSProperties {
121
+ const show = cur === req ? 1 : 0;
122
+ return { opacity: show, transition: instant ? "none" : "opacity 0.35s ease" };
123
+ }
124
+
125
+ export function getStep(Reveal: RevealInstance): number {
126
+ if (!Reveal) return -1;
127
+ const slide = Reveal.getCurrentSlide();
128
+ if (!slide) return -1;
129
+ const visible = slide.querySelectorAll(".fragment.visible[data-fragment-index]");
130
+ let max = -1;
131
+ visible.forEach(function (el) {
132
+ const idx = parseInt(el.getAttribute("data-fragment-index") || "", 10);
133
+ if (!isNaN(idx) && idx > max) max = idx;
134
+ });
135
+ return max;
136
+ }
137
+
138
+ export function useRevealStep(Reveal: RevealInstance | null): [number, boolean, boolean] {
139
+ const [step, setStep] = useState(-1);
140
+ const [ready, setReady] = useState(false);
141
+ const [instant, setInstant] = useState(true);
142
+
143
+ useEffect(function () {
144
+ if (!Reveal) return;
145
+ const sync = function () { setStep(getStep(Reveal)); };
146
+ const onFragment = function () { setInstant(false); sync(); };
147
+ const onSlideChanged = function () {
148
+ setInstant(true);
149
+ setReady(false);
150
+ setStep(-1);
151
+ requestAnimationFrame(function () {
152
+ sync();
153
+ setReady(true);
154
+ requestAnimationFrame(function () { setInstant(false); });
155
+ });
156
+ };
157
+ Reveal.on("fragmentshown", onFragment);
158
+ Reveal.on("fragmenthidden", onFragment);
159
+ Reveal.on("slidechanged", onSlideChanged);
160
+ requestAnimationFrame(function () {
161
+ sync();
162
+ setReady(true);
163
+ requestAnimationFrame(function () { setInstant(false); });
164
+ });
165
+ return function () {
166
+ Reveal.off("fragmentshown", onFragment);
167
+ Reveal.off("fragmenthidden", onFragment);
168
+ Reveal.off("slidechanged", onSlideChanged);
169
+ };
170
+ }, [Reveal]);
171
+
172
+ return [step, ready, instant];
173
+ }
174
+
175
+ interface SlideCanvasProps {
176
+ Reveal: RevealInstance;
177
+ W?: number;
178
+ H?: number;
179
+ children: (step: number, instant: boolean) => ReactNode;
180
+ }
181
+
182
+ export function SlideCanvas(props: SlideCanvasProps) {
183
+ const [step, ready, instant] = useRevealStep(props.Reveal);
184
+ return React.createElement("svg", {
185
+ viewBox: "0 0 " + (props.W || 1200) + " " + (props.H || 560),
186
+ style: { width: "100%", height: "100%", display: "block",
187
+ opacity: ready ? 1 : 0, transition: "opacity 0.2s ease" },
188
+ }, props.children(step, instant));
189
+ }
@@ -0,0 +1,141 @@
1
+ import type { RevealInstance, ComponentRegistry, MountContext } from "./types.ts";
2
+ import * as mountRegistry from "./mount-registry.ts";
3
+
4
+ declare global {
5
+ interface SVGPathElement {
6
+ _rcaDrawable?: any;
7
+ }
8
+ }
9
+
10
+ function connectorLength(path: SVGPathElement): number {
11
+ try {
12
+ return path.getTotalLength();
13
+ } catch {
14
+ return 0;
15
+ }
16
+ }
17
+
18
+ function prepareConnector(path: SVGPathElement, anime: any): void {
19
+ if (anime?.svg?.createDrawable) {
20
+ const isVisible = path.classList.contains("visible");
21
+ path._rcaDrawable = anime.svg.createDrawable(path, 0, isVisible ? 1 : 0)[0];
22
+ return;
23
+ }
24
+ const length = connectorLength(path);
25
+ if (!length) return;
26
+ path.dataset.length = String(length);
27
+ path.style.strokeDasharray = String(length);
28
+ path.style.strokeDashoffset = path.classList.contains("visible") ? "0" : String(length);
29
+ }
30
+
31
+ function animateConnector(path: SVGPathElement, anime: any): void {
32
+ if (anime?.svg?.createDrawable) {
33
+ const drawable = path._rcaDrawable || anime.svg.createDrawable(path, 0, 0)[0];
34
+ path._rcaDrawable = drawable;
35
+ anime.animate(drawable, {
36
+ draw: ["0 0", "0 1"],
37
+ duration: 420,
38
+ ease: "outCubic",
39
+ });
40
+ return;
41
+ }
42
+ const length = Number(path.dataset.length || connectorLength(path));
43
+ if (!length) return;
44
+ path.style.strokeDasharray = String(length);
45
+ path.style.strokeDashoffset = String(length);
46
+ anime.animate(path, {
47
+ strokeDashoffset: [length, 0],
48
+ duration: 420,
49
+ ease: "outCubic",
50
+ });
51
+ }
52
+
53
+ function resetConnector(path: SVGPathElement): void {
54
+ if (path._rcaDrawable) {
55
+ path._rcaDrawable.setAttribute("draw", "0 0");
56
+ return;
57
+ }
58
+ const length = Number(path.dataset.length || connectorLength(path));
59
+ if (!length) return;
60
+ path.style.strokeDashoffset = String(length);
61
+ }
62
+
63
+ function animateNode(fragment: Element, anime: any): void {
64
+ if (!fragment.querySelector(".icon-node, .claim, .large-stat, .pill, .result-box, .chart-shell")) return;
65
+ anime.animate(fragment, {
66
+ opacity: [0, 1],
67
+ scale: [0.965, 1],
68
+ duration: 260,
69
+ ease: "outQuad",
70
+ });
71
+ }
72
+
73
+ function prepareSlide(slide: Element, anime: any): void {
74
+ slide.querySelectorAll<SVGPathElement>("path[data-connector='true']").forEach((path) => prepareConnector(path, anime));
75
+ }
76
+
77
+ function connectorsForFragment(fragment: Element): SVGPathElement[] {
78
+ const slide = fragment.closest("section");
79
+ const index = fragment.getAttribute("data-fragment-index");
80
+ if (!slide || index === null) return [];
81
+ return [...slide.querySelectorAll<SVGPathElement>(`path[data-connector='true'][data-fragment-index="${index}"]`)];
82
+ }
83
+
84
+ export function installRuntime(
85
+ Reveal: RevealInstance,
86
+ anime: any,
87
+ components: ComponentRegistry
88
+ ): void {
89
+ if (!Reveal || !anime?.animate) return;
90
+
91
+ mountRegistry.registerComponents(components);
92
+
93
+ const ctx: MountContext = { anime, Reveal };
94
+
95
+ Reveal.on("ready", (event: any) => {
96
+ prepareSlide(event.currentSlide, anime);
97
+ mountRegistry.hydrate(event.currentSlide, ctx);
98
+ });
99
+
100
+ Reveal.on("slidechanged", (event: any) => {
101
+ const mounts: NodeListOf<HTMLElement> = event.currentSlide.querySelectorAll(".block-mount");
102
+ mounts.forEach((el: HTMLElement) => { el.style.visibility = "hidden"; });
103
+
104
+ prepareSlide(event.currentSlide, anime);
105
+ mountRegistry.hydrate(event.currentSlide, ctx);
106
+
107
+ requestAnimationFrame(() => {
108
+ requestAnimationFrame(() => {
109
+ mounts.forEach((el: HTMLElement) => { el.style.visibility = ""; });
110
+ });
111
+ });
112
+ });
113
+
114
+ Reveal.on("fragmentshown", (event: any) => {
115
+ const fragment = event.fragment as Element;
116
+ if (fragment.matches("path[data-connector='true']")) {
117
+ animateConnector(fragment as unknown as SVGPathElement, anime);
118
+ } else {
119
+ connectorsForFragment(fragment).forEach((path) => {
120
+ animateConnector(path, anime);
121
+ });
122
+ animateNode(fragment, anime);
123
+ mountRegistry.hydrate(fragment, ctx);
124
+ }
125
+ });
126
+
127
+ Reveal.on("fragmenthidden", (event: any) => {
128
+ const fragment = event.fragment as Element;
129
+ if (fragment.matches("path[data-connector='true']")) {
130
+ resetConnector(fragment as unknown as SVGPathElement);
131
+ } else {
132
+ connectorsForFragment(fragment).forEach(resetConnector);
133
+ }
134
+ });
135
+
136
+ document.querySelectorAll<Element>(".reveal .slides section").forEach((slide) => {
137
+ prepareSlide(slide, anime);
138
+ });
139
+ const initialSlide = Reveal.getCurrentSlide();
140
+ if (initialSlide) mountRegistry.hydrate(initialSlide, ctx);
141
+ }
@@ -0,0 +1,114 @@
1
+ import type { ComponentType } from "react";
2
+
3
+ export interface SlideComponentProps {
4
+ Reveal: RevealInstance;
5
+ anime?: typeof import("animejs");
6
+ }
7
+
8
+ export interface RevealInstance {
9
+ initialize(): Promise<void>;
10
+ on(event: string, callback: (e: any) => void): void;
11
+ off(event: string, callback: (e: any) => void): void;
12
+ getCurrentSlide(): HTMLElement | null;
13
+ getState(): { indexh: number; indexf: number };
14
+ }
15
+
16
+ export interface Slide {
17
+ className?: string;
18
+ attrs?: Record<string, string | number>;
19
+ html: string;
20
+ notes: string;
21
+ }
22
+
23
+ export type LayerName = "background" | "connector" | "content" | "overlay" | "chrome";
24
+
25
+ export interface BlockOptions {
26
+ id?: string;
27
+ kind?: "html" | "svg" | "image" | "mount";
28
+ html?: string;
29
+ src?: string;
30
+ alt?: string;
31
+ x?: number;
32
+ y?: number;
33
+ w?: number;
34
+ h?: number;
35
+ layer?: LayerName;
36
+ fragment?: boolean | number | null;
37
+ animation?: string;
38
+ className?: string;
39
+ attrs?: Record<string, string | number | boolean>;
40
+ css?: Record<string, string | number>;
41
+ styleText?: string;
42
+ flow?: boolean;
43
+ mount?: MountSpec | null;
44
+ }
45
+
46
+ export interface Block extends Required<Pick<BlockOptions, "kind" | "html" | "alt" | "layer" | "animation" | "className" | "flow">> {
47
+ id?: string;
48
+ src?: string;
49
+ x?: number;
50
+ y?: number;
51
+ w?: number;
52
+ h?: number;
53
+ fragment: boolean | number | null;
54
+ attrs: Record<string, string | number | boolean>;
55
+ css: Record<string, string | number>;
56
+ styleText: string;
57
+ mount: MountSpec | null;
58
+ }
59
+
60
+ export interface MountSpec {
61
+ library: string;
62
+ exportName?: string;
63
+ props?: Record<string, unknown>;
64
+ }
65
+
66
+ export interface StepNote {
67
+ step: string;
68
+ visible: string;
69
+ say: string;
70
+ why?: string;
71
+ next?: string;
72
+ }
73
+
74
+ export interface SlideOptions {
75
+ className?: string;
76
+ attrs?: Record<string, string | number>;
77
+ html?: string;
78
+ blocks?: (Block | string)[];
79
+ notes?: string | (string | StepNote)[];
80
+ }
81
+
82
+ export interface ReactSlideOptions<C extends string = string> {
83
+ title?: string;
84
+ component: C;
85
+ steps?: number;
86
+ notes?: string;
87
+ page?: number;
88
+ x?: number;
89
+ y?: number;
90
+ w?: number;
91
+ h?: number;
92
+ }
93
+
94
+ export interface BlockSlideOptions {
95
+ title?: string;
96
+ blocks?: (Block | string)[];
97
+ page?: number;
98
+ notes?: string;
99
+ html?: string;
100
+ className?: string;
101
+ attrs?: Record<string, string | number>;
102
+ }
103
+
104
+ export type ComponentRegistry = Record<string, ComponentType<SlideComponentProps>>;
105
+
106
+ export interface MountContext {
107
+ Reveal: RevealInstance;
108
+ anime: typeof import("animejs");
109
+ }
110
+
111
+ export interface DeckConfig<C extends ComponentRegistry = ComponentRegistry> {
112
+ buildSlides: (() => Promise<Slide[]> | Slide[]) | Slide[];
113
+ components: C;
114
+ }
@@ -0,0 +1,78 @@
1
+ export interface AlgoEntry {
2
+ name: string;
3
+ t1: number;
4
+ t3: number;
5
+ t5: number;
6
+ time: string;
7
+ color: string;
8
+ cat: string;
9
+ }
10
+
11
+ export interface HeatmapRow {
12
+ fault: string;
13
+ mrr: number[];
14
+ }
15
+
16
+ export interface HeatmapGroup {
17
+ name: string;
18
+ step: number;
19
+ color: string;
20
+ rows: HeatmapRow[];
21
+ }
22
+
23
+ export const ALGOS: AlgoEntry[] = [
24
+ { name: "MicroRCA", t1: 0.37, t3: 0.50, t5: 0.64, time: "35.6", color: "#76B82A", cat: "full" },
25
+ { name: "Baro", t1: 0.36, t3: 0.50, t5: 0.58, time: "1.0", color: "#00A6D6", cat: "full" },
26
+ { name: "MicroDig", t1: 0.35, t3: 0.61, t5: 0.67, time: "19.0", color: "#00A6D6", cat: "full" },
27
+ { name: "MicroHECL", t1: 0.34, t3: 0.34, t5: 0.34, time: "34.8", color: "#00A6D6", cat: "full" },
28
+ { name: "SimpleRCA", t1: 0.28, t3: 0.60, t5: 0.80, time: "0.9", color: "#C00000", cat: "full" },
29
+ { name: "CausalRCA", t1: 0.22, t3: 0.40, t5: 0.42, time: "927", color: "#00A6D6", cat: "full" },
30
+ { name: "Shapleyiq", t1: 0.22, t3: 0.36, t5: 0.52, time: "42.7", color: "#767676", cat: "full" },
31
+ { name: "Eadro", t1: 0.16, t3: 0.16, t5: 0.16, time: "32.8", color: "#767676", cat: "test" },
32
+ { name: "DiagFusion", t1: 0.13, t3: 0.17, t5: 0.22, time: "3.0", color: "#767676", cat: "test" },
33
+ { name: "MicroRank", t1: 0.04, t3: 0.18, t5: 0.25, time: "36.3", color: "#767676", cat: "full" },
34
+ { name: "Nezha", t1: 0.04, t3: 0.08, t5: 0.08, time: "94.6", color: "#767676", cat: "full" },
35
+ { name: "Art", t1: 0.04, t3: 0.08, t5: 0.10, time: "8.1", color: "#767676", cat: "test" },
36
+ ];
37
+
38
+ export const HEATMAP_ALGOS: string[] = ["Baro","SimpleRCA","MicroRCA","MicroDig","Shapleyiq","MicroHECL","CausalRCA","MicroRank","Nezha","DiagFusion","Eadro","Art"];
39
+
40
+ export const HEATMAP_GROUPS: HeatmapGroup[] = [
41
+ { name: "Lifecycle", step: 0, color: "#76B82A", rows: [
42
+ { fault: "ContainerKill", mrr: [0.87,0.75,0.85,0.70,0.05,0.60,0.55,0.10,0.05,0.08,0.10,0.05] },
43
+ { fault: "PodKill", mrr: [0.82,0.80,0.78,0.65,0.15,0.55,0.50,0.08,0.10,0.06,0.08,0.04] },
44
+ { fault: "PodFailure", mrr: [0.75,0.70,0.72,0.60,0.10,0.50,0.45,0.06,0.08,0.05,0.07,0.03] },
45
+ ]},
46
+ { name: "Resource", step: 1, color: "#76B82A", rows: [
47
+ { fault: "JVMCPUStress", mrr: [0.80,0.65,0.60,0.55,0.18,0.35,0.30,0.04,0.02,0.04,0.05,0.02] },
48
+ { fault: "JVMMemoryStress", mrr: [0.95,0.76,0.70,0.60,0.20,0.40,0.35,0.05,0.02,0.04,0.06,0.02] },
49
+ ]},
50
+ { name: "HTTP", step: 2, color: "#00A6D6", rows: [
51
+ { fault: "HTTPReqAbort", mrr: [0.50,0.40,0.45,0.55,0.50,0.30,0.25,0.05,0.03,0.10,0.08,0.04] },
52
+ { fault: "HTTPReqDelay", mrr: [0.55,0.50,0.50,0.60,0.92,0.35,0.28,0.06,0.03,0.08,0.06,0.03] },
53
+ { fault: "HTTPReqRepMethod", mrr: [0.45,0.35,0.40,0.50,0.30,0.25,0.20,0.04,0.02,0.08,0.06,0.03] },
54
+ { fault: "HTTPReqRepPath", mrr: [0.40,0.30,0.38,0.45,0.28,0.22,0.18,0.04,0.02,0.07,0.05,0.03] },
55
+ { fault: "HTTPRespAbort", mrr: [0.48,0.38,0.42,0.50,0.45,0.28,0.22,0.05,0.03,0.09,0.07,0.04] },
56
+ { fault: "HTTPRespDelay", mrr: [0.55,0.45,0.50,0.55,0.97,0.30,0.25,0.04,0.02,0.10,0.08,0.03] },
57
+ { fault: "HTTPRespPatchBody",mrr: [0.35,0.25,0.35,0.40,0.30,0.20,0.18,0.04,0.02,0.08,0.06,0.03] },
58
+ { fault: "HTTPRespRepBody", mrr: [0.38,0.28,0.36,0.42,0.32,0.22,0.20,0.05,0.02,0.09,0.06,0.03] },
59
+ { fault: "HTTPRespRepCode", mrr: [0.30,0.20,0.30,0.25,0.25,0.20,0.18,0.06,0.03,0.10,0.08,0.04] },
60
+ ]},
61
+ { name: "JVM", step: 3, color: "#7B61FF", rows: [
62
+ { fault: "JVMException", mrr: [0.45,0.35,0.40,0.50,0.25,0.30,0.22,0.05,0.02,0.06,0.05,0.03] },
63
+ { fault: "JVMLatency", mrr: [0.50,0.40,0.45,0.55,0.60,0.32,0.25,0.05,0.02,0.07,0.06,0.03] },
64
+ { fault: "JVMMySQLLatency", mrr: [0.42,0.30,0.38,0.45,0.55,0.28,0.20,0.04,0.01,0.06,0.05,0.02] },
65
+ { fault: "JVMReturn", mrr: [0.10,0.08,0.12,0.10,0.15,0.10,0.08,0.03,0.01,0.05,0.03,0.02] },
66
+ ]},
67
+ { name: "Network", step: 4, color: "#E8912D", rows: [
68
+ { fault: "NetworkBandwidth", mrr: [0.25,0.18,0.28,0.22,0.38,0.18,0.15,0.05,0.02,0.07,0.05,0.03] },
69
+ { fault: "NetworkCorrupt", mrr: [0.20,0.15,0.25,0.20,0.40,0.20,0.15,0.05,0.02,0.08,0.05,0.03] },
70
+ { fault: "NetworkDelay", mrr: [0.22,0.16,0.24,0.20,0.42,0.18,0.14,0.04,0.02,0.07,0.05,0.03] },
71
+ { fault: "NetworkLoss", mrr: [0.15,0.10,0.20,0.15,0.35,0.15,0.12,0.04,0.02,0.06,0.04,0.02] },
72
+ { fault: "NetworkPartition", mrr: [0.18,0.12,0.22,0.18,0.30,0.16,0.13,0.04,0.02,0.06,0.04,0.02] },
73
+ ]},
74
+ { name: "Blind spots", step: 5, color: "#C00000", rows: [
75
+ { fault: "DNSRandom", mrr: [0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00] },
76
+ { fault: "TimeSkew", mrr: [0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00] },
77
+ ]},
78
+ ];
@@ -0,0 +1,79 @@
1
+ export interface BenchDim {
2
+ label: string;
3
+ ours: number;
4
+ oursF: string;
5
+ best: number;
6
+ bestF: string;
7
+ bestDs: string;
8
+ higher: boolean;
9
+ }
10
+
11
+ export interface FailureBar {
12
+ key: string;
13
+ label: string;
14
+ pct: number;
15
+ color: string;
16
+ reveal: number;
17
+ }
18
+
19
+ export interface FailureDesc {
20
+ reveal: number;
21
+ color: string;
22
+ title: string;
23
+ text: string;
24
+ }
25
+
26
+ export interface FailureModes {
27
+ bars: FailureBar[];
28
+ descs: FailureDesc[];
29
+ }
30
+
31
+ export interface FaultType {
32
+ label: string;
33
+ pct: number;
34
+ color: string;
35
+ title: string;
36
+ desc: string;
37
+ detail: string;
38
+ }
39
+
40
+ export const BENCH_DIMS: BenchDim[] = [
41
+ { label: "Validated cases", ours: 1430, oursF: "1,430", best: 159, bestF: "159", bestDs: "AIOps-21", higher: true },
42
+ { label: "Services", ours: 50, oursF: "50", best: 69, bestF: "69", bestDs: "RE2-TT", higher: false },
43
+ { label: "Service coverage", ours: 84, oursF: "84%", best: 61, bestF: "61%", bestDs: "Nezha-TT", higher: true },
44
+ { label: "Max call depth", ours: 7, oursF: "7", best: 5, bestF: "5", bestDs: "RE2-TT", higher: true },
45
+ { label: "QPS (avg)", ours: 16.47, oursF: "16.47", best: 4.35, bestF: "4.35", bestDs: "RE2-TT", higher: true },
46
+ { label: "Log lines", ours: 154.7, oursF: "154.7M", best: 21.3, bestF: "21.3M", bestDs: "RE2-TT", higher: true },
47
+ { label: "Traces", ours: 11.2, oursF: "11.2M", best: 3.1, bestF: "3.1M", bestDs: "GAIA", higher: true },
48
+ { label: "Fault types", ours: 25, oursF: "25", best: 6, bestF: "~6", bestDs: "most", higher: true },
49
+ ];
50
+
51
+ export const FAILURE_MODES: FailureModes = {
52
+ bars: [
53
+ { key: "modeling", label: "Modeling Bottlenecks", pct: 47.4, color: "#C07070", reveal: 2 },
54
+ { key: "scalability", label: "Scalability Issues", pct: 39.8, color: "#1B556B", reveal: 0 },
55
+ { key: "signal", label: "Signal-Loss Blind Spots", pct: 5.8, color: "#E8912D", reveal: 1 },
56
+ { key: "infra", label: "Infrastructure-Level Blind Spots", pct: 4.2, color: "#999933", reveal: 1 },
57
+ { key: "semantic", label: "Semantic-Gap Blind Spots", pct: 2.9, color: "#76B82A", reveal: 1 },
58
+ ],
59
+ descs: [
60
+ { reveal: 0, color: "#1B556B", title: "Scalability", text: "CausalRCA: 927s, Nezha: 94.6s per case" },
61
+ { reveal: 1, color: "#E8912D", title: "Observability blind spots", text: "Signal loss, infrastructure & semantic gaps" },
62
+ { reveal: 2, color: "#C07070", title: "Modeling", text: "Wrong assumptions about fault propagation" },
63
+ ],
64
+ };
65
+
66
+ export const FAULT_TYPES: FaultType[] = [
67
+ { label: "Type I", pct: 68, color: "#C00000",
68
+ title: "Localized",
69
+ desc: "Only injected service shows anomaly",
70
+ detail: "trivially easy to find" },
71
+ { label: "Type II", pct: 18, color: "#767676",
72
+ title: "Under-expressed",
73
+ desc: "No service shows any signal",
74
+ detail: "impossible for any method" },
75
+ { label: "Type III", pct: 14, color: "#76B82A",
76
+ title: "Propagated",
77
+ desc: "Downstream services are louder",
78
+ detail: "requires causal reasoning" },
79
+ ];