ccwrap 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.
- package/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +181 -0
- package/dist/data/commentary.d.ts +13 -0
- package/dist/data/commentary.js +102 -0
- package/dist/data/parser.d.ts +2 -0
- package/dist/data/parser.js +358 -0
- package/dist/data/types.d.ts +109 -0
- package/dist/data/types.js +1 -0
- package/dist/render.d.ts +2 -0
- package/dist/render.js +60 -0
- package/dist/video/Composition.d.ts +8 -0
- package/dist/video/Composition.js +50 -0
- package/dist/video/Root.d.ts +2 -0
- package/dist/video/Root.js +81 -0
- package/dist/video/components/AnimatedNumber.d.ts +10 -0
- package/dist/video/components/AnimatedNumber.js +16 -0
- package/dist/video/components/FadeIn.d.ts +8 -0
- package/dist/video/components/FadeIn.js +18 -0
- package/dist/video/components/GlowOrb.d.ts +8 -0
- package/dist/video/components/GlowOrb.js +19 -0
- package/dist/video/components/ParticleField.d.ts +5 -0
- package/dist/video/components/ParticleField.js +36 -0
- package/dist/video/index.d.ts +1 -0
- package/dist/video/index.js +3 -0
- package/dist/video/slides/ArchetypeSlide.d.ts +7 -0
- package/dist/video/slides/ArchetypeSlide.js +34 -0
- package/dist/video/slides/BusiestDaySlide.d.ts +7 -0
- package/dist/video/slides/BusiestDaySlide.js +23 -0
- package/dist/video/slides/CostSlide.d.ts +7 -0
- package/dist/video/slides/CostSlide.js +12 -0
- package/dist/video/slides/IntroSlide.d.ts +5 -0
- package/dist/video/slides/IntroSlide.js +21 -0
- package/dist/video/slides/ModelSlide.d.ts +7 -0
- package/dist/video/slides/ModelSlide.js +45 -0
- package/dist/video/slides/PeakHoursSlide.d.ts +7 -0
- package/dist/video/slides/PeakHoursSlide.js +48 -0
- package/dist/video/slides/SessionSlide.d.ts +7 -0
- package/dist/video/slides/SessionSlide.js +22 -0
- package/dist/video/slides/SummarySlide.d.ts +7 -0
- package/dist/video/slides/SummarySlide.js +52 -0
- package/dist/video/slides/TokensSlide.d.ts +7 -0
- package/dist/video/slides/TokensSlide.js +25 -0
- package/dist/video/styles.d.ts +45 -0
- package/dist/video/styles.js +84 -0
- package/package.json +58 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { interpolate, useCurrentFrame } from "remotion";
|
|
3
|
+
export const AnimatedNumber = ({ value, decimals = 0, prefix = "", suffix = "", style = {}, startFrame = 10, duration = 30 }) => {
|
|
4
|
+
const frame = useCurrentFrame();
|
|
5
|
+
const progress = interpolate(frame, [startFrame, startFrame + duration], [0, 1], {
|
|
6
|
+
extrapolateLeft: "clamp",
|
|
7
|
+
extrapolateRight: "clamp",
|
|
8
|
+
});
|
|
9
|
+
// Eased progress for smoother counting
|
|
10
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
11
|
+
const displayValue = Math.round(value * eased * Math.pow(10, decimals)) / Math.pow(10, decimals);
|
|
12
|
+
const formatted = decimals > 0
|
|
13
|
+
? displayValue.toLocaleString(undefined, { minimumFractionDigits: decimals, maximumFractionDigits: decimals })
|
|
14
|
+
: displayValue.toLocaleString();
|
|
15
|
+
return (_jsxs("span", { style: style, children: [prefix, formatted, suffix] }));
|
|
16
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { interpolate, useCurrentFrame } from "remotion";
|
|
3
|
+
export const FadeIn = ({ children, delay = 0, duration = 15, slideUp = 30, style = {} }) => {
|
|
4
|
+
const frame = useCurrentFrame();
|
|
5
|
+
const opacity = interpolate(frame, [delay, delay + duration], [0, 1], {
|
|
6
|
+
extrapolateLeft: "clamp",
|
|
7
|
+
extrapolateRight: "clamp",
|
|
8
|
+
});
|
|
9
|
+
const translateY = interpolate(frame, [delay, delay + duration], [slideUp, 0], {
|
|
10
|
+
extrapolateLeft: "clamp",
|
|
11
|
+
extrapolateRight: "clamp",
|
|
12
|
+
});
|
|
13
|
+
return (_jsx("div", { style: {
|
|
14
|
+
opacity,
|
|
15
|
+
transform: `translateY(${translateY}px)`,
|
|
16
|
+
...style,
|
|
17
|
+
}, children: children }));
|
|
18
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { interpolate, useCurrentFrame } from "remotion";
|
|
3
|
+
export const GlowOrb = ({ color, size, x, y, speed = 0.5 }) => {
|
|
4
|
+
const frame = useCurrentFrame();
|
|
5
|
+
const floatY = interpolate(Math.sin(frame * 0.02 * speed), [-1, 1], [-20, 20]);
|
|
6
|
+
const floatX = interpolate(Math.cos(frame * 0.015 * speed), [-1, 1], [-15, 15]);
|
|
7
|
+
return (_jsx("div", { style: {
|
|
8
|
+
position: "absolute",
|
|
9
|
+
left: `${x}%`,
|
|
10
|
+
top: `${y}%`,
|
|
11
|
+
width: size,
|
|
12
|
+
height: size,
|
|
13
|
+
borderRadius: "50%",
|
|
14
|
+
background: `radial-gradient(circle, ${color}40, ${color}00)`,
|
|
15
|
+
filter: "blur(40px)",
|
|
16
|
+
transform: `translate(${floatX}px, ${floatY}px)`,
|
|
17
|
+
pointerEvents: "none",
|
|
18
|
+
} }));
|
|
19
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { useCurrentFrame, interpolate } from "remotion";
|
|
4
|
+
import { colors } from "../styles";
|
|
5
|
+
export const ParticleField = ({ count = 40, seed = 42 }) => {
|
|
6
|
+
const frame = useCurrentFrame();
|
|
7
|
+
const particles = useMemo(() => {
|
|
8
|
+
const rng = (s) => {
|
|
9
|
+
let x = Math.sin(s) * 10000;
|
|
10
|
+
return x - Math.floor(x);
|
|
11
|
+
};
|
|
12
|
+
const particleColors = [colors.primary, colors.secondary, colors.accent, colors.gold, colors.pink];
|
|
13
|
+
return Array.from({ length: count }, (_, i) => ({
|
|
14
|
+
x: rng(seed + i * 7) * 100,
|
|
15
|
+
y: rng(seed + i * 13) * 100,
|
|
16
|
+
size: rng(seed + i * 17) * 3 + 1,
|
|
17
|
+
speed: rng(seed + i * 23) * 2 + 0.5,
|
|
18
|
+
opacity: rng(seed + i * 29) * 0.5 + 0.2,
|
|
19
|
+
color: particleColors[Math.floor(rng(seed + i * 31) * particleColors.length)],
|
|
20
|
+
}));
|
|
21
|
+
}, [count, seed]);
|
|
22
|
+
return (_jsx("div", { style: { position: "absolute", inset: 0, overflow: "hidden", pointerEvents: "none" }, children: particles.map((p, i) => {
|
|
23
|
+
const y = (p.y + frame * p.speed * 0.3) % 110 - 5;
|
|
24
|
+
const twinkle = interpolate(Math.sin(frame * 0.1 + i), [-1, 1], [p.opacity * 0.5, p.opacity]);
|
|
25
|
+
return (_jsx("div", { style: {
|
|
26
|
+
position: "absolute",
|
|
27
|
+
left: `${p.x}%`,
|
|
28
|
+
top: `${y}%`,
|
|
29
|
+
width: p.size,
|
|
30
|
+
height: p.size,
|
|
31
|
+
borderRadius: "50%",
|
|
32
|
+
backgroundColor: p.color,
|
|
33
|
+
opacity: twinkle,
|
|
34
|
+
} }, i));
|
|
35
|
+
}) }));
|
|
36
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCurrentFrame, spring, useVideoConfig, interpolate } from "remotion";
|
|
3
|
+
import { baseSlide, gradientBg, getColors, glowText, label } from "../styles";
|
|
4
|
+
import { FadeIn } from "../components/FadeIn";
|
|
5
|
+
import { ParticleField } from "../components/ParticleField";
|
|
6
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
7
|
+
function getArchetypeColor(archetype, mode) {
|
|
8
|
+
const c = getColors(mode);
|
|
9
|
+
if (archetype.includes("Night"))
|
|
10
|
+
return c.primary;
|
|
11
|
+
if (archetype.includes("Weekend"))
|
|
12
|
+
return c.secondary;
|
|
13
|
+
if (archetype.includes("Marathon"))
|
|
14
|
+
return c.accent;
|
|
15
|
+
if (archetype.includes("Streak"))
|
|
16
|
+
return c.gold;
|
|
17
|
+
if (archetype.includes("Whale"))
|
|
18
|
+
return mode === "dark" ? c.accent : "#10b981";
|
|
19
|
+
if (archetype.includes("Connoisseur"))
|
|
20
|
+
return c.gold;
|
|
21
|
+
if (archetype.includes("Serial"))
|
|
22
|
+
return c.pink;
|
|
23
|
+
return c.secondary;
|
|
24
|
+
}
|
|
25
|
+
export const ArchetypeSlide = ({ stats, commentary, mode }) => {
|
|
26
|
+
const frame = useCurrentFrame();
|
|
27
|
+
const { fps } = useVideoConfig();
|
|
28
|
+
const c = getColors(mode);
|
|
29
|
+
const color = getArchetypeColor(stats.archetype, mode);
|
|
30
|
+
const revealScale = spring({ frame: Math.max(0, frame - 20), fps, from: 0, to: 1, config: { damping: 8, stiffness: 80 } });
|
|
31
|
+
const glowIntensity = interpolate(Math.sin(frame * 0.08), [-1, 1], [0.5, 1]);
|
|
32
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(200, c), color: c.text }, children: [_jsx(ParticleField, { count: 40, seed: 333 }), _jsx(GlowOrb, { color: color, size: 350, x: 50, y: 45, speed: 0.3 }), _jsx(GlowOrb, { color: c.primary, size: 180, x: 15, y: 20 }), _jsx(GlowOrb, { color: c.accent, size: 180, x: 85, y: 80 }), _jsx(FadeIn, { delay: 5, children: _jsx("div", { style: { ...label, color, zIndex: 1, letterSpacing: "0.3em" }, children: mode === "dark" ? "Your Classification" : "You Are..." }) }), _jsxs("div", { style: { transform: `scale(${revealScale})`, opacity: revealScale, zIndex: 1, marginTop: 24, textAlign: "center" }, children: [_jsx("div", { style: { width: 90, height: 3, background: `linear-gradient(90deg, transparent, ${color}, transparent)`, margin: "0 auto 18px", opacity: glowIntensity } }), _jsx("div", { style: { fontSize: 68, fontWeight: 900, lineHeight: 1.1, ...glowText(color), background: `linear-gradient(135deg, ${color}, ${c.text}, ${color})`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", filter: `brightness(${0.8 + glowIntensity * 0.4})` }, children: stats.archetype }), _jsx("div", { style: { width: 90, height: 3, background: `linear-gradient(90deg, transparent, ${color}, transparent)`, margin: "18px auto 0", opacity: glowIntensity } })] }), _jsx(FadeIn, { delay: 40, children: _jsx("div", { style: { fontSize: 18, color: c.textMuted, maxWidth: 580, textAlign: "center", lineHeight: 1.5, marginTop: 28, zIndex: 1, padding: "8px 18px", borderRadius: 10, background: "rgba(0,0,0,0.35)" }, children: commentary }) }), _jsx(FadeIn, { delay: 55, style: { zIndex: 1, marginTop: 28 }, children: _jsxs("div", { style: { display: "flex", gap: 14 }, children: [_jsx(Badge, { label: "Night Owl", value: `${stats.nightOwlScore}%`, color: c.primary, textColor: c.textMuted }), _jsx(Badge, { label: "Weekend", value: `${stats.weekendWarriorScore}%`, color: c.secondary, textColor: c.textMuted }), _jsx(Badge, { label: "Streak", value: `${stats.streakDays}d`, color: c.gold, textColor: c.textMuted })] }) })] }));
|
|
33
|
+
};
|
|
34
|
+
const Badge = ({ label: l, value, color, textColor }) => (_jsxs("div", { style: { background: `${color}20`, border: `1px solid ${color}50`, borderRadius: 12, padding: "10px 20px", textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 22, fontWeight: 700, color }, children: value }), _jsx("div", { style: { fontSize: 11, color: textColor, marginTop: 2, textTransform: "uppercase" }, children: l })] }));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCurrentFrame, interpolate } from "remotion";
|
|
3
|
+
import { baseSlide, gradientBg, getColors, glowText, label, memeCaption } from "../styles";
|
|
4
|
+
import { FadeIn } from "../components/FadeIn";
|
|
5
|
+
import { AnimatedNumber } from "../components/AnimatedNumber";
|
|
6
|
+
import { ParticleField } from "../components/ParticleField";
|
|
7
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
8
|
+
function formatDate(dateStr) {
|
|
9
|
+
const d = new Date(dateStr + "T00:00:00");
|
|
10
|
+
return d.toLocaleDateString("en-US", { weekday: "long", month: "long", day: "numeric" });
|
|
11
|
+
}
|
|
12
|
+
export const BusiestDaySlide = ({ stats, commentary, mode }) => {
|
|
13
|
+
const frame = useCurrentFrame();
|
|
14
|
+
const c = getColors(mode);
|
|
15
|
+
const day = stats.busiestDay;
|
|
16
|
+
const recentDays = stats.dailyActivity.slice(-14);
|
|
17
|
+
const maxTokens = Math.max(...recentDays.map(d => d.tokenCount), 1);
|
|
18
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(45, c), color: c.text }, children: [_jsx(ParticleField, { count: 30, seed: 55 }), _jsx(GlowOrb, { color: c.accent, size: 250, x: 50, y: 30 }), _jsx(GlowOrb, { color: c.pink, size: 180, x: 25, y: 70 }), _jsx(FadeIn, { delay: 5, children: _jsx("div", { style: { ...label, color: c.accent, zIndex: 1 }, children: mode === "dark" ? "Peak Destruction Day" : "Your Biggest Day" }) }), _jsx(FadeIn, { delay: 12, children: _jsx("div", { style: { fontSize: 44, fontWeight: 900, ...glowText(c.accent), color: c.text, zIndex: 1, marginTop: 16 }, children: formatDate(day.date) }) }), _jsx(FadeIn, { delay: 25, children: _jsxs("div", { style: { display: "flex", gap: 48, marginTop: 24, zIndex: 1 }, children: [_jsxs("div", { style: { textAlign: "center" }, children: [_jsx(AnimatedNumber, { value: day.tokenCount, style: { fontSize: 40, fontWeight: 800, color: c.accent }, startFrame: 25, duration: 25 }), _jsx("div", { style: { fontSize: 13, color: c.textMuted, marginTop: 4 }, children: "TOKENS" })] }), _jsxs("div", { style: { textAlign: "center" }, children: [_jsx(AnimatedNumber, { value: day.messageCount, style: { fontSize: 40, fontWeight: 800, color: c.pink }, startFrame: 28, duration: 25 }), _jsx("div", { style: { fontSize: 13, color: c.textMuted, marginTop: 4 }, children: "MESSAGES" })] }), _jsxs("div", { style: { textAlign: "center" }, children: [_jsx(AnimatedNumber, { value: day.sessions, style: { fontSize: 40, fontWeight: 800, color: c.secondary }, startFrame: 31, duration: 25 }), _jsx("div", { style: { fontSize: 13, color: c.textMuted, marginTop: 4 }, children: "SESSIONS" })] })] }) }), _jsx(FadeIn, { delay: 45, style: { width: "88%", marginTop: 28, zIndex: 1 }, children: _jsx("div", { style: { display: "flex", alignItems: "flex-end", gap: 4, height: 100 }, children: recentDays.map((d, i) => {
|
|
19
|
+
const barHeight = interpolate(frame, [48 + i, 68 + i], [0, (d.tokenCount / maxTokens) * 100], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
|
|
20
|
+
const isBusiest = d.date === day.date;
|
|
21
|
+
return (_jsx("div", { style: { flex: 1, height: barHeight, borderRadius: 3, background: isBusiest ? `linear-gradient(180deg, ${c.accent}, ${c.pink})` : `${c.primary}90`, boxShadow: isBusiest ? `0 0 8px ${c.accent}80` : undefined } }, d.date));
|
|
22
|
+
}) }) }), _jsx(FadeIn, { delay: 60, children: _jsx("div", { style: { ...memeCaption, color: c.textMuted, zIndex: 1 }, children: commentary }) })] }));
|
|
23
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { baseSlide, gradientBg, getColors, glowText, bigNumber, label, memeCaption } from "../styles";
|
|
3
|
+
import { FadeIn } from "../components/FadeIn";
|
|
4
|
+
import { AnimatedNumber } from "../components/AnimatedNumber";
|
|
5
|
+
import { ParticleField } from "../components/ParticleField";
|
|
6
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
7
|
+
export const CostSlide = ({ stats, commentary, mode }) => {
|
|
8
|
+
const c = getColors(mode);
|
|
9
|
+
const costColor = mode === "dark" ? c.accent : "#10b981";
|
|
10
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(320, c), color: c.text }, children: [_jsx(ParticleField, { count: 25, seed: 42 }), _jsx(GlowOrb, { color: costColor, size: 280, x: 50, y: 35 }), _jsx(GlowOrb, { color: c.primary, size: 160, x: 80, y: 75 }), _jsx(FadeIn, { delay: 5, children: _jsx("div", { style: { ...label, color: costColor, zIndex: 1 }, children: mode === "dark" ? "The Price of Progress" : "Estimated Cost" }) }), _jsx(AnimatedNumber, { value: stats.totalCost, decimals: 2, prefix: "$", style: { ...bigNumber, ...glowText(costColor), color: costColor, display: "block", textAlign: "center", zIndex: 1, marginTop: 20 }, startFrame: 10, duration: 35 }), _jsx(FadeIn, { delay: 40, children: _jsx("div", { style: { display: "flex", gap: 50, marginTop: 36, zIndex: 1 }, children: mode === "dark" ? (_jsxs(_Fragment, { children: [_jsx(Metric, { icon: "\uD83D\uDCA7", value: `${stats.waterLiters.toLocaleString(undefined, { maximumFractionDigits: 1 })}L`, label: "Water" }), _jsx(Metric, { icon: "\uD83C\uDFED", value: `${(stats.co2Grams / 1000).toLocaleString(undefined, { maximumFractionDigits: 1 })}kg`, label: "CO\u2082" }), _jsx(Metric, { icon: "\u26A1", value: `${stats.kwhUsed.toLocaleString(undefined, { maximumFractionDigits: 1 })}`, label: "kWh" })] })) : (_jsxs(_Fragment, { children: [_jsx(Metric, { icon: "\u2615", value: stats.coffeeEquivalent.toLocaleString(), label: "Coffees" }), _jsx(Metric, { icon: "\uD83C\uDFC3", value: stats.marathonEquivalent.toLocaleString(undefined, { maximumFractionDigits: 1 }), label: "Marathons" }), _jsx(Metric, { icon: "\uD83D\uDCD6", value: stats.warAndPeaceEquivalent.toLocaleString(undefined, { maximumFractionDigits: 1 }), label: "War & Peaces" })] })) }) }), _jsx(FadeIn, { delay: 55, children: _jsx("div", { style: { ...memeCaption, color: c.textMuted, zIndex: 1 }, children: commentary }) })] }));
|
|
11
|
+
};
|
|
12
|
+
const Metric = ({ icon, value, label: l }) => (_jsxs("div", { style: { textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 36 }, children: icon }), _jsx("div", { style: { fontSize: 30, fontWeight: 800, color: "#f1f5f9", marginTop: 6 }, children: value }), _jsx("div", { style: { fontSize: 13, color: "inherit", opacity: 0.7, marginTop: 3, textTransform: "uppercase", letterSpacing: "0.1em" }, children: l })] }));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";
|
|
3
|
+
import { baseSlide, gradientBg, getColors } from "../styles";
|
|
4
|
+
import { FadeIn } from "../components/FadeIn";
|
|
5
|
+
import { ParticleField } from "../components/ParticleField";
|
|
6
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
7
|
+
export const IntroSlide = ({ mode, periodLabel }) => {
|
|
8
|
+
const frame = useCurrentFrame();
|
|
9
|
+
const { fps } = useVideoConfig();
|
|
10
|
+
const c = getColors(mode);
|
|
11
|
+
const logoScale = spring({ frame, fps, from: 0, to: 1, config: { damping: 12, stiffness: 100 } });
|
|
12
|
+
const titleOpacity = interpolate(frame, [20, 40], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
|
|
13
|
+
const taglineScale = spring({ frame: Math.max(0, frame - 35), fps, from: 0.5, to: 1, config: { damping: 8 } });
|
|
14
|
+
const taglineOpacity = interpolate(frame, [35, 50], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
|
|
15
|
+
const rotation = interpolate(frame, [0, 150], [0, 360], { extrapolateRight: "extend" });
|
|
16
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(135, c), color: c.text }, children: [_jsx(ParticleField, { count: 40 }), _jsx(GlowOrb, { color: c.primary, size: 250, x: 15, y: 25 }), _jsx(GlowOrb, { color: c.secondary, size: 200, x: 80, y: 70 }), _jsx(GlowOrb, { color: c.accent, size: 150, x: 50, y: 15, speed: 0.3 }), _jsx("div", { style: { position: "absolute", width: 180, height: 180, borderRadius: "50%", border: `2px solid ${c.primary}30`, transform: `scale(${logoScale}) rotate(${rotation}deg)` } }), _jsx("div", { style: { position: "absolute", width: 150, height: 150, borderRadius: "50%", border: `1px solid ${c.secondary}20`, transform: `scale(${logoScale}) rotate(-${rotation * 0.7}deg)` } }), _jsx("div", { style: { transform: `scale(${logoScale})`, fontSize: 72, fontWeight: 900, background: `linear-gradient(135deg, ${c.primary}, ${c.secondary})`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", zIndex: 1 }, children: "</>" }), _jsxs("div", { style: { opacity: titleOpacity, fontSize: 48, fontWeight: 800, marginTop: 24, letterSpacing: "-0.02em", zIndex: 1 }, children: [_jsx("span", { style: { color: c.text }, children: "Claude Code " }), _jsx("span", { style: { background: `linear-gradient(90deg, ${c.primary}, ${c.accent})`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent" }, children: "Wrapped" })] }), _jsx(FadeIn, { delay: 35, children: _jsx("div", { style: { opacity: taglineOpacity, transform: `scale(${taglineScale})`, fontSize: 22, fontWeight: 500, color: c.textMuted, marginTop: 20, zIndex: 1 }, children: periodLabel.startsWith("Your ")
|
|
17
|
+
? mode === "dark"
|
|
18
|
+
? `${periodLabel} in AI. The planet remembers.`
|
|
19
|
+
: `${periodLabel} in AI-assisted coding`
|
|
20
|
+
: periodLabel }) })] }));
|
|
21
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";
|
|
3
|
+
import { baseSlide, gradientBg, getColors, glowText, label, memeCaption } from "../styles";
|
|
4
|
+
import { FadeIn } from "../components/FadeIn";
|
|
5
|
+
import { ParticleField } from "../components/ParticleField";
|
|
6
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
7
|
+
function getModelVersion(model) {
|
|
8
|
+
// Extract version like "4.6", "4.5", "3.5" from model ID
|
|
9
|
+
const match = model.match(/(\d+)[.-](\d+)/);
|
|
10
|
+
if (match)
|
|
11
|
+
return `${match[1]}.${match[2]}`;
|
|
12
|
+
return "";
|
|
13
|
+
}
|
|
14
|
+
function getModelDisplayName(model) {
|
|
15
|
+
const version = getModelVersion(model);
|
|
16
|
+
if (model.includes("opus"))
|
|
17
|
+
return version ? `Opus ${version}` : "Opus";
|
|
18
|
+
if (model.includes("sonnet"))
|
|
19
|
+
return version ? `Sonnet ${version}` : "Sonnet";
|
|
20
|
+
if (model.includes("haiku"))
|
|
21
|
+
return version ? `Haiku ${version}` : "Haiku";
|
|
22
|
+
return model;
|
|
23
|
+
}
|
|
24
|
+
function getModelColor(model, mode) {
|
|
25
|
+
const c = getColors(mode);
|
|
26
|
+
if (model.includes("opus"))
|
|
27
|
+
return c.gold;
|
|
28
|
+
if (model.includes("sonnet"))
|
|
29
|
+
return c.primary;
|
|
30
|
+
if (model.includes("haiku"))
|
|
31
|
+
return c.secondary;
|
|
32
|
+
return c.accent;
|
|
33
|
+
}
|
|
34
|
+
export const ModelSlide = ({ stats, commentary, mode }) => {
|
|
35
|
+
const frame = useCurrentFrame();
|
|
36
|
+
const { fps } = useVideoConfig();
|
|
37
|
+
const c = getColors(mode);
|
|
38
|
+
const favoriteColor = getModelColor(stats.favoriteModel, mode);
|
|
39
|
+
const revealScale = spring({ frame: Math.max(0, frame - 15), fps, from: 0.3, to: 1, config: { damping: 10 } });
|
|
40
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(260, c), color: c.text }, children: [_jsx(ParticleField, { count: 35, seed: 77 }), _jsx(GlowOrb, { color: favoriteColor, size: 300, x: 50, y: 40 }), _jsx(FadeIn, { delay: 5, children: _jsx("div", { style: { ...label, color: favoriteColor, zIndex: 1 }, children: mode === "dark" ? "Your Weapon of Choice" : "Your #1 Model" }) }), _jsx(FadeIn, { delay: 15, children: _jsx("div", { style: { fontSize: 90, fontWeight: 900, ...glowText(favoriteColor), background: `linear-gradient(135deg, ${favoriteColor}, ${c.text})`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", transform: `scale(${revealScale})`, zIndex: 1, marginTop: 12 }, children: getModelDisplayName(stats.favoriteModel) }) }), _jsx(FadeIn, { delay: 30, children: _jsx("div", { style: { ...memeCaption, color: c.textMuted, zIndex: 1 }, children: commentary }) }), _jsx(FadeIn, { delay: 40, style: { width: "85%", marginTop: 28, zIndex: 1 }, children: _jsx("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: stats.modelUsage.slice(0, 4).map((m, i) => {
|
|
41
|
+
const barWidth = interpolate(frame, [45 + i * 5, 65 + i * 5], [0, m.percentage], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
|
|
42
|
+
const modelColor = getModelColor(m.model, mode);
|
|
43
|
+
return (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [_jsx("div", { style: { width: 100, fontSize: 14, color: c.textMuted, textAlign: "right", fontWeight: 500 }, children: getModelDisplayName(m.model) }), _jsx("div", { style: { flex: 1, height: 24, borderRadius: 12, background: `${c.text}20`, overflow: "hidden" }, children: _jsx("div", { style: { width: `${barWidth}%`, height: "100%", borderRadius: 12, background: `linear-gradient(90deg, ${modelColor}, ${modelColor}cc)`, boxShadow: `0 0 8px ${modelColor}60` } }) }), _jsxs("div", { style: { width: 44, fontSize: 14, color: c.textMuted, fontWeight: 600 }, children: [m.percentage.toFixed(0), "%"] })] }, m.model));
|
|
44
|
+
}) }) })] }));
|
|
45
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCurrentFrame, interpolate } from "remotion";
|
|
3
|
+
import { baseSlide, gradientBg, getColors, glowText, label, memeCaption } from "../styles";
|
|
4
|
+
import { FadeIn } from "../components/FadeIn";
|
|
5
|
+
import { ParticleField } from "../components/ParticleField";
|
|
6
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
7
|
+
function formatHour(hour) {
|
|
8
|
+
if (hour === 0)
|
|
9
|
+
return "12am";
|
|
10
|
+
if (hour === 12)
|
|
11
|
+
return "12pm";
|
|
12
|
+
return hour < 12 ? `${hour}am` : `${hour - 12}pm`;
|
|
13
|
+
}
|
|
14
|
+
function getTimeTitle(hour, mode) {
|
|
15
|
+
if (mode === "dark") {
|
|
16
|
+
if (hour >= 22 || hour < 5)
|
|
17
|
+
return "Midnight Burner";
|
|
18
|
+
if (hour >= 5 && hour < 9)
|
|
19
|
+
return "Dawn Polluter";
|
|
20
|
+
if (hour >= 17)
|
|
21
|
+
return "After-Dark Emitter";
|
|
22
|
+
return "Daytime Drainer";
|
|
23
|
+
}
|
|
24
|
+
if (hour >= 5 && hour < 9)
|
|
25
|
+
return "Early Bird";
|
|
26
|
+
if (hour >= 9 && hour < 12)
|
|
27
|
+
return "Morning Person";
|
|
28
|
+
if (hour >= 12 && hour < 14)
|
|
29
|
+
return "Lunch Coder";
|
|
30
|
+
if (hour >= 14 && hour < 17)
|
|
31
|
+
return "Afternoon Warrior";
|
|
32
|
+
if (hour >= 17 && hour < 20)
|
|
33
|
+
return "After-Hours Hacker";
|
|
34
|
+
if (hour >= 20 && hour < 23)
|
|
35
|
+
return "Night Coder";
|
|
36
|
+
return "Midnight Demon";
|
|
37
|
+
}
|
|
38
|
+
export const PeakHoursSlide = ({ stats, commentary, mode }) => {
|
|
39
|
+
const frame = useCurrentFrame();
|
|
40
|
+
const c = getColors(mode);
|
|
41
|
+
const maxActivity = Math.max(...stats.hourlyActivity.map(h => h.tokenCount), 1);
|
|
42
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(280, c), color: c.text }, children: [_jsx(ParticleField, { count: 20, seed: 200 }), _jsx(GlowOrb, { color: c.secondary, size: 250, x: 50, y: 30 }), _jsx(GlowOrb, { color: c.primary, size: 180, x: 20, y: 70 }), _jsx(FadeIn, { delay: 5, children: _jsx("div", { style: { ...label, color: c.secondary, zIndex: 1 }, children: mode === "dark" ? "Peak Power Draw" : "Peak Coding Hours" }) }), _jsxs(FadeIn, { delay: 12, children: [_jsx("div", { style: { fontSize: 56, fontWeight: 900, ...glowText(c.secondary), color: c.text, zIndex: 1, marginTop: 12 }, children: getTimeTitle(stats.busiestHour, mode) }), _jsxs("div", { style: { fontSize: 18, color: c.textMuted, textAlign: "center", marginTop: 8, zIndex: 1 }, children: ["Your peak: ", _jsx("span", { style: { color: c.secondary, fontWeight: 700 }, children: formatHour(stats.busiestHour) })] })] }), _jsx(FadeIn, { delay: 25, style: { marginTop: 32, zIndex: 1 }, children: _jsxs("div", { style: { width: 700, height: 180 }, children: [_jsx("div", { style: { display: "flex", alignItems: "flex-end", gap: 3, height: 150 }, children: stats.hourlyActivity.map((h, i) => {
|
|
43
|
+
const barHeight = interpolate(frame, [28 + i * 0.5, 48 + i * 0.5], [0, (h.tokenCount / maxActivity) * 150], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
|
|
44
|
+
const isPeak = h.hour === stats.busiestHour;
|
|
45
|
+
const isNight = h.hour >= 22 || h.hour < 5;
|
|
46
|
+
return (_jsx("div", { style: { flex: 1 }, children: _jsx("div", { style: { width: "100%", height: barHeight, borderRadius: 3, background: isPeak ? `linear-gradient(180deg, ${c.secondary}, ${c.primary})` : isNight ? `${c.primary}cc` : `${c.text}60`, boxShadow: isPeak ? `0 0 8px ${c.secondary}80` : undefined } }) }, i));
|
|
47
|
+
}) }), _jsx("div", { style: { display: "flex", justifyContent: "space-between", marginTop: 6 }, children: [0, 6, 12, 18, 23].map(h => _jsx("div", { style: { fontSize: 12, color: c.textMuted }, children: formatHour(h) }, h)) })] }) }), _jsx(FadeIn, { delay: 55, children: _jsx("div", { style: { ...memeCaption, color: c.textMuted, zIndex: 1 }, children: commentary }) })] }));
|
|
48
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCurrentFrame, spring, useVideoConfig } from "remotion";
|
|
3
|
+
import { baseSlide, gradientBg, getColors, glowText, label, memeCaption } from "../styles";
|
|
4
|
+
import { FadeIn } from "../components/FadeIn";
|
|
5
|
+
import { ParticleField } from "../components/ParticleField";
|
|
6
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
7
|
+
function formatDuration(minutes) {
|
|
8
|
+
if (minutes < 60)
|
|
9
|
+
return `${Math.round(minutes)} min`;
|
|
10
|
+
const hours = Math.floor(minutes / 60);
|
|
11
|
+
const mins = Math.round(minutes % 60);
|
|
12
|
+
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
|
|
13
|
+
}
|
|
14
|
+
export const SessionSlide = ({ stats, commentary, mode }) => {
|
|
15
|
+
const frame = useCurrentFrame();
|
|
16
|
+
const { fps } = useVideoConfig();
|
|
17
|
+
const c = getColors(mode);
|
|
18
|
+
const pulse = spring({ frame: frame % 40, fps, from: 1, to: 1.04, config: { damping: 5 } });
|
|
19
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(160, c), color: c.text }, children: [_jsx(ParticleField, { count: 25, seed: 123 }), _jsx(GlowOrb, { color: c.pink, size: 300, x: 50, y: 40 }), _jsx(GlowOrb, { color: c.primary, size: 180, x: 75, y: 20 }), _jsx(FadeIn, { delay: 5, children: _jsx("div", { style: { ...label, color: c.pink, zIndex: 1 }, children: mode === "dark" ? "Endurance Test" : "Marathon Session" }) }), _jsxs(FadeIn, { delay: 12, children: [_jsx("div", { style: { fontSize: 80, fontWeight: 900, ...glowText(c.pink), color: c.text, zIndex: 1, marginTop: 16, transform: `scale(${pulse})` }, children: formatDuration(stats.longestSession.durationMinutes) }), _jsx("div", { style: { fontSize: 18, color: c.textMuted, zIndex: 1, marginTop: 8 }, children: "longest session" })] }), _jsx(FadeIn, { delay: 30, children: _jsxs("div", { style: { display: "flex", gap: 36, marginTop: 32, zIndex: 1 }, children: [_jsx(Pill, { label: "Sessions", value: stats.totalSessions, color: c.primary, textColor: c.textMuted }), _jsx(Pill, { label: "Avg", value: `${stats.avgSessionMinutes}m`, color: c.secondary, textColor: c.textMuted }), _jsx(Pill, { label: "Messages", value: stats.totalMessages, color: mode === "dark" ? c.textMuted : "#10b981", textColor: c.textMuted }), _jsx(Pill, { label: "Streak", value: `${stats.streakDays}d`, color: c.gold, textColor: c.textMuted })] }) }), _jsx(FadeIn, { delay: 50, children: _jsxs("div", { style: { display: "flex", gap: 14, marginTop: 24, zIndex: 1 }, children: [_jsx(Chip, { label: "Active Days", value: stats.totalDaysActive, color: c.accent, textColor: c.textMuted }), _jsx(Chip, { label: "Night Owl", value: `${stats.nightOwlScore}%`, color: c.primary, textColor: c.textMuted }), _jsx(Chip, { label: "Weekend", value: `${stats.weekendWarriorScore}%`, color: c.secondary, textColor: c.textMuted })] }) }), _jsx(FadeIn, { delay: 60, children: _jsx("div", { style: { ...memeCaption, color: c.textMuted, zIndex: 1 }, children: commentary }) })] }));
|
|
20
|
+
};
|
|
21
|
+
const Pill = ({ label: l, value, color, textColor }) => (_jsxs("div", { style: { textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 34, fontWeight: 800, color, ...glowText(color) }, children: typeof value === "number" ? value.toLocaleString() : value }), _jsx("div", { style: { fontSize: 12, color: textColor, marginTop: 3, textTransform: "uppercase", letterSpacing: "0.1em" }, children: l })] }));
|
|
22
|
+
const Chip = ({ label: l, value, color, textColor }) => (_jsxs("div", { style: { background: `${color}20`, border: `1px solid ${color}50`, borderRadius: 10, padding: "8px 18px", textAlign: "center" }, children: [_jsx("div", { style: { fontSize: 24, fontWeight: 700, color }, children: typeof value === "number" ? value.toLocaleString() : value }), _jsx("div", { style: { fontSize: 11, color: textColor, marginTop: 2 }, children: l })] }));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCurrentFrame, interpolate, spring, useVideoConfig } from "remotion";
|
|
3
|
+
import { baseSlide, gradientBg, getColors, glowText } from "../styles";
|
|
4
|
+
import { FadeIn } from "../components/FadeIn";
|
|
5
|
+
import { ParticleField } from "../components/ParticleField";
|
|
6
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
7
|
+
function formatNumber(n) {
|
|
8
|
+
if (n >= 1_000_000)
|
|
9
|
+
return `${(n / 1_000_000).toFixed(1)}M`;
|
|
10
|
+
if (n >= 1_000)
|
|
11
|
+
return `${(n / 1_000).toFixed(1)}K`;
|
|
12
|
+
return n.toString();
|
|
13
|
+
}
|
|
14
|
+
function getModelShortName(model) {
|
|
15
|
+
const match = model.match(/(\d+)[.-](\d+)/);
|
|
16
|
+
const version = match ? ` ${match[1]}.${match[2]}` : "";
|
|
17
|
+
if (model.includes("opus"))
|
|
18
|
+
return `Opus${version}`;
|
|
19
|
+
if (model.includes("sonnet"))
|
|
20
|
+
return `Sonnet${version}`;
|
|
21
|
+
if (model.includes("haiku"))
|
|
22
|
+
return `Haiku${version}`;
|
|
23
|
+
return model.split("-").slice(0, 2).join(" ");
|
|
24
|
+
}
|
|
25
|
+
function getSummaryTitle(periodLabel, mode) {
|
|
26
|
+
const suffixMap = {
|
|
27
|
+
"Your week": ["Your Week in Review", "Your Week's Impact"],
|
|
28
|
+
"Your month": ["Your Month in Review", "Your Month's Impact"],
|
|
29
|
+
"Your quarter": ["Your Quarter in Review", "Your Quarter's Impact"],
|
|
30
|
+
"Your all-time": ["Your All-Time Recap", "Your All-Time Impact"],
|
|
31
|
+
};
|
|
32
|
+
const match = suffixMap[periodLabel];
|
|
33
|
+
if (match)
|
|
34
|
+
return mode === "dark" ? match[1] : match[0];
|
|
35
|
+
return periodLabel; // custom date range string
|
|
36
|
+
}
|
|
37
|
+
export const SummarySlide = ({ stats, commentary, mode }) => {
|
|
38
|
+
const frame = useCurrentFrame();
|
|
39
|
+
const { fps } = useVideoConfig();
|
|
40
|
+
const c = getColors(mode);
|
|
41
|
+
const cardScale = spring({ frame: Math.max(0, frame - 5), fps, from: 0.85, to: 1, config: { damping: 12 } });
|
|
42
|
+
const cardOpacity = interpolate(frame, [5, 20], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
|
|
43
|
+
const rotation = interpolate(Math.sin(frame * 0.02), [-1, 1], [-0.8, 0.8]);
|
|
44
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(135, c), color: c.text }, children: [_jsx(ParticleField, { count: 50, seed: 444 }), _jsx(GlowOrb, { color: c.primary, size: 240, x: 25, y: 20 }), _jsx(GlowOrb, { color: c.secondary, size: 200, x: 75, y: 75 }), _jsx(GlowOrb, { color: c.accent, size: 170, x: 50, y: 50, speed: 0.2 }), _jsxs("div", { style: {
|
|
45
|
+
opacity: cardOpacity, transform: `scale(${cardScale}) rotate(${rotation}deg)`,
|
|
46
|
+
background: `linear-gradient(145deg, ${c.bgGradient1}ee, ${c.bgGradient3}ee)`,
|
|
47
|
+
border: `1px solid ${c.primary}50`, borderRadius: 24, padding: "36px 44px",
|
|
48
|
+
maxWidth: 620, width: "92%",
|
|
49
|
+
boxShadow: `0 0 36px ${c.primary}20, 0 12px 36px rgba(0,0,0,0.5)`, zIndex: 1,
|
|
50
|
+
}, children: [_jsx("div", { style: { textAlign: "center", marginBottom: 20 }, children: _jsx("div", { style: { fontSize: 28, fontWeight: 900, ...glowText(c.primary), background: `linear-gradient(90deg, ${c.primary}, ${c.secondary})`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent" }, children: getSummaryTitle(stats.periodLabel, mode) }) }), _jsx(FadeIn, { delay: 15, children: _jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "14px 36px" }, children: [_jsx(Row, { label: "Tokens", value: formatNumber(stats.totalTokens), color: c.gold, textColor: c.textMuted }), _jsx(Row, { label: "Cost", value: `$${stats.totalCost.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`, color: mode === "dark" ? c.accent : "#10b981", textColor: c.textMuted }), _jsx(Row, { label: "Sessions", value: stats.totalSessions.toLocaleString(), color: c.primary, textColor: c.textMuted }), _jsx(Row, { label: "Messages", value: formatNumber(stats.totalMessages), color: c.pink, textColor: c.textMuted }), _jsx(Row, { label: "Active Days", value: stats.totalDaysActive.toLocaleString(), color: c.secondary, textColor: c.textMuted }), _jsx(Row, { label: "Fav Model", value: getModelShortName(stats.favoriteModel), color: c.accent, textColor: c.textMuted }), mode === "dark" && _jsxs(_Fragment, { children: [_jsx(Row, { label: "Water", value: `${stats.waterLiters.toLocaleString(undefined, { maximumFractionDigits: 1 })}L`, color: c.secondary, textColor: c.textMuted }), _jsx(Row, { label: "CO\u2082", value: `${(stats.co2Grams / 1000).toLocaleString(undefined, { maximumFractionDigits: 1 })}kg`, color: c.textMuted, textColor: c.textMuted })] })] }) }), _jsx(FadeIn, { delay: 30, children: _jsxs("div", { style: { marginTop: 20, textAlign: "center", padding: "12px 20px", background: `linear-gradient(135deg, ${c.primary}20, ${c.accent}20)`, borderRadius: 12, border: `1px solid ${c.primary}40` }, children: [_jsx("div", { style: { fontSize: 12, color: c.textMuted, textTransform: "uppercase", letterSpacing: "0.15em" }, children: "Your Archetype" }), _jsx("div", { style: { fontSize: 26, fontWeight: 800, background: `linear-gradient(90deg, ${c.primary}, ${c.accent})`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", marginTop: 3 }, children: stats.archetype })] }) }), _jsx(FadeIn, { delay: 40, children: _jsx("div", { style: { textAlign: "center", marginTop: 16, fontSize: 15, fontStyle: "italic", color: c.textMuted }, children: commentary }) }), _jsx(FadeIn, { delay: 50, children: _jsxs("div", { style: { textAlign: "center", marginTop: 14, fontSize: 12, color: c.textDim }, children: ["ccwrapped", mode === "dark" ? " — know your impact" : " — put meme software on the map"] }) })] })] }));
|
|
51
|
+
};
|
|
52
|
+
const Row = ({ label, value, color, textColor }) => (_jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [_jsx("div", { style: { fontSize: 14, color: textColor }, children: label }), _jsx("div", { style: { fontSize: 20, fontWeight: 700, color }, children: value })] }));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCurrentFrame } from "remotion";
|
|
3
|
+
import { baseSlide, gradientBg, getColors, glowText, bigNumber, label, memeCaption } from "../styles";
|
|
4
|
+
import { FadeIn } from "../components/FadeIn";
|
|
5
|
+
import { AnimatedNumber } from "../components/AnimatedNumber";
|
|
6
|
+
import { ParticleField } from "../components/ParticleField";
|
|
7
|
+
import { GlowOrb } from "../components/GlowOrb";
|
|
8
|
+
function formatTokens(n) {
|
|
9
|
+
if (n >= 1_000_000_000)
|
|
10
|
+
return { value: Math.round(n / 1_000_000_000 * 10) / 10, suffix: "B" };
|
|
11
|
+
if (n >= 1_000_000)
|
|
12
|
+
return { value: Math.round(n / 1_000_000 * 10) / 10, suffix: "M" };
|
|
13
|
+
if (n >= 1_000)
|
|
14
|
+
return { value: Math.round(n / 1_000 * 10) / 10, suffix: "K" };
|
|
15
|
+
return { value: n, suffix: "" };
|
|
16
|
+
}
|
|
17
|
+
export const TokensSlide = ({ stats, commentary, mode }) => {
|
|
18
|
+
const frame = useCurrentFrame();
|
|
19
|
+
const c = getColors(mode);
|
|
20
|
+
const formatted = formatTokens(stats.totalTokens);
|
|
21
|
+
const shake = frame > 30 && frame < 45 ? Math.sin(frame * 2) * 2 : 0;
|
|
22
|
+
const accentColor = mode === "dark" ? c.accent : c.gold;
|
|
23
|
+
return (_jsxs("div", { style: { ...baseSlide, ...gradientBg(200, c), color: c.text }, children: [_jsx(ParticleField, { count: 35, seed: 99 }), _jsx(GlowOrb, { color: accentColor, size: 300, x: 50, y: 40 }), _jsx(GlowOrb, { color: c.accent, size: 180, x: 20, y: 75 }), _jsx(FadeIn, { delay: 5, children: _jsx("div", { style: { ...label, color: accentColor, zIndex: 1 }, children: "Total Tokens Consumed" }) }), _jsx("div", { style: { transform: `translateX(${shake}px)`, zIndex: 1, marginTop: 20 }, children: _jsx(AnimatedNumber, { value: formatted.value, decimals: formatted.suffix ? 1 : 0, suffix: formatted.suffix, style: { ...bigNumber, ...glowText(accentColor), background: `linear-gradient(135deg, ${accentColor}, ${c.text})`, WebkitBackgroundClip: "text", WebkitTextFillColor: "transparent", display: "block", textAlign: "center" }, startFrame: 10, duration: 40 }) }), _jsx(FadeIn, { delay: 45, children: _jsxs("div", { style: { display: "flex", gap: 50, marginTop: 32, zIndex: 1 }, children: [_jsx(StatBox, { label: "Input", value: formatTokens(stats.totalInputTokens), color: c.secondary }), _jsx(StatBox, { label: "Output", value: formatTokens(stats.totalOutputTokens), color: mode === "dark" ? c.textMuted : "#10b981" }), mode === "dark" && _jsx(StatBox, { label: "Water", value: { value: stats.waterLiters, suffix: "L" }, color: c.secondary }), mode === "dark" && _jsx(StatBox, { label: "Energy", value: { value: stats.kwhUsed, suffix: " kWh" }, color: c.gold })] }) }), _jsx(FadeIn, { delay: 55, children: _jsx("div", { style: { ...memeCaption, color: c.textMuted, zIndex: 1 }, children: commentary }) })] }));
|
|
24
|
+
};
|
|
25
|
+
const StatBox = ({ label: l, value, color }) => (_jsxs("div", { style: { textAlign: "center" }, children: [_jsxs("div", { style: { fontSize: 36, fontWeight: 800, color, ...glowText(color) }, children: [value.value.toLocaleString(undefined, { maximumFractionDigits: value.suffix ? 1 : 0 }), value.suffix] }), _jsx("div", { style: { fontSize: 13, color: "inherit", opacity: 0.7, marginTop: 4, textTransform: "uppercase", letterSpacing: "0.1em" }, children: l })] }));
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
declare const sassyColors: {
|
|
3
|
+
bg: string;
|
|
4
|
+
bgGradient1: string;
|
|
5
|
+
bgGradient2: string;
|
|
6
|
+
bgGradient3: string;
|
|
7
|
+
primary: string;
|
|
8
|
+
secondary: string;
|
|
9
|
+
accent: string;
|
|
10
|
+
gold: string;
|
|
11
|
+
green: string;
|
|
12
|
+
pink: string;
|
|
13
|
+
text: string;
|
|
14
|
+
textMuted: string;
|
|
15
|
+
textDim: string;
|
|
16
|
+
};
|
|
17
|
+
export type ColorScheme = typeof sassyColors;
|
|
18
|
+
export declare function getColors(mode: "sassy" | "dark"): ColorScheme;
|
|
19
|
+
export declare const colors: {
|
|
20
|
+
bg: string;
|
|
21
|
+
bgGradient1: string;
|
|
22
|
+
bgGradient2: string;
|
|
23
|
+
bgGradient3: string;
|
|
24
|
+
primary: string;
|
|
25
|
+
secondary: string;
|
|
26
|
+
accent: string;
|
|
27
|
+
gold: string;
|
|
28
|
+
green: string;
|
|
29
|
+
pink: string;
|
|
30
|
+
text: string;
|
|
31
|
+
textMuted: string;
|
|
32
|
+
textDim: string;
|
|
33
|
+
};
|
|
34
|
+
export declare const fonts: {
|
|
35
|
+
heading: string;
|
|
36
|
+
body: string;
|
|
37
|
+
mono: string;
|
|
38
|
+
};
|
|
39
|
+
export declare const baseSlide: CSSProperties;
|
|
40
|
+
export declare const gradientBg: (angle: number, c: ColorScheme) => CSSProperties;
|
|
41
|
+
export declare const glowText: (color: string) => CSSProperties;
|
|
42
|
+
export declare const bigNumber: CSSProperties;
|
|
43
|
+
export declare const label: CSSProperties;
|
|
44
|
+
export declare const memeCaption: CSSProperties;
|
|
45
|
+
export {};
|