polen
Version:
A framework for delightful GraphQL developer portals
71 lines • 4.14 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { CRITICALITY_CONFIG, isCriticalityBreaking, isCriticalityDangerous, isCriticalitySafe, } from '#lib/graphql-change/criticality';
import { Box, Flex, Text } from '@radix-ui/themes';
import { useEffect, useState } from 'react';
import { renderDate } from './Changelog.js';
const calculateCounts = (version) => {
return {
breaking: version.changes.filter(isCriticalityBreaking).length,
dangerous: version.changes.filter(isCriticalityDangerous).length,
safe: version.changes.filter(isCriticalitySafe).length,
};
};
const SidebarEntry = ({ version, counts, isActive }) => {
const dateId = version.date.toISOString();
return (_jsx(Box, { mb: '2', children: _jsxs("a", { href: `#${dateId}`, style: {
textDecoration: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '0.5rem 0.75rem',
borderRadius: '4px',
backgroundColor: isActive ? 'var(--gray-a3)' : 'transparent',
color: 'inherit',
transition: 'background-color 0.2s',
}, onClick: (e) => {
e.preventDefault();
document.getElementById(dateId)?.scrollIntoView({ behavior: 'smooth' });
}, children: [_jsx(Text, { size: '2', weight: isActive ? 'medium' : 'regular', children: renderDate(version.date) }), _jsxs(Flex, { gap: '2', align: 'center', children: [counts.breaking > 0 && (_jsx(Text, { size: '1', weight: 'medium', style: { color: CRITICALITY_CONFIG.BREAKING.color }, children: counts.breaking })), counts.dangerous > 0 && (_jsx(Text, { size: '1', weight: 'medium', style: { color: CRITICALITY_CONFIG.DANGEROUS.color }, children: counts.dangerous })), counts.safe > 0 && (_jsx(Text, { size: '1', weight: 'medium', style: { color: CRITICALITY_CONFIG.NON_BREAKING.color }, children: counts.safe }))] })] }) }));
};
export const ChangelogLayout = ({ children, versions }) => {
const [activeVersion, setActiveVersion] = useState(null);
// Calculate counts for all versions (SSR-safe)
const versionsWithCounts = versions.map(version => ({
version,
counts: calculateCounts(version),
}));
// Set up scroll spy after hydration
useEffect(() => {
const handleScroll = () => {
const scrollPosition = window.scrollY + 100; // Offset for header
// Find the current version based on scroll position
let currentVersion = null;
for (const { version } of versionsWithCounts) {
const element = document.getElementById(version.date.toISOString());
if (element) {
const { top } = element.getBoundingClientRect();
if (top <= 100) {
currentVersion = version.date.toISOString();
}
}
}
setActiveVersion(currentVersion);
};
// Initial check
handleScroll();
// Add scroll listener
window.addEventListener('scroll', handleScroll, { passive: true });
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, [versionsWithCounts]);
return (_jsxs(Flex, { gap: '6', style: { position: 'relative' }, children: [_jsxs(Box, { style: {
position: 'sticky',
top: '2rem',
height: 'fit-content',
minWidth: '250px',
maxHeight: 'calc(100vh - 4rem)',
overflowY: 'auto',
}, children: [_jsx(Text, { size: '2', weight: 'medium', mb: '3', style: { display: 'block' }, children: "Releases" }), versionsWithCounts.map(({ version, counts }) => (_jsx(SidebarEntry, { version: version, counts: counts, isActive: activeVersion === version.date.toISOString() }, version.date.toISOString())))] }), _jsx(Box, { style: { flex: 1, minWidth: 0 }, children: children })] }));
};
//# sourceMappingURL=ChangelogLayout.js.map