import type { AnySupportedStyle, SupportedFramework } from '@/types/docs'; import { navigate } from 'astro:transitions/client'; import { getAvailableStyles, getDefaultStyle, SUPPORTED_FRAMEWORKS } from '@/types/docs'; import { findFirstGuide, findGuideBySlug, getValidStylesForGuide } from '@/utils/docs/sidebar'; interface SelectorProps { currentFramework: SupportedFramework; currentStyle: AnySupportedStyle; } /** * Extract the current guide slug from the docs URL. * URL format: /docs/framework/{framework}/style/{style}/{slug}/ * @returns The guide slug (everything after the style parameter) */ function getCurrentGuideSlug(): string { const pathParts = window.location.pathname.split('/').filter(Boolean); const styleIndex = pathParts.indexOf('style'); const slugParts = pathParts.slice(styleIndex + 2); // Everything after the style value return slugParts.join('/'); } export function Selectors({ currentFramework, currentStyle }: SelectorProps) { const handleFrameworkChange = (event: React.ChangeEvent) => { const newFramework = event.target.value as SupportedFramework; // Get current guide slug from URL const currentGuideSlug = getCurrentGuideSlug(); // Find the current guide in the sidebar const currentGuide = findGuideBySlug(currentGuideSlug); if (!currentGuide) { // No current guide found, redirect to first guide of new framework const firstGuide = findFirstGuide(newFramework, getDefaultStyle(newFramework)); if (firstGuide) { navigate(`/docs/framework/${newFramework}/style/${getDefaultStyle(newFramework)}/${firstGuide}/`); } else { navigate('/docs/'); } return; } // Check if guide is available for the new framework if (currentGuide.frameworks && !currentGuide.frameworks.includes(newFramework)) { // Guide not available in new framework, redirect to first guide const firstGuide = findFirstGuide(newFramework, getDefaultStyle(newFramework)); if (firstGuide) { navigate(`/docs/framework/${newFramework}/style/${getDefaultStyle(newFramework)}/${firstGuide}/`); } else { navigate('/docs/'); } return; } // Get valid styles for this guide in the new framework const validStyles = getValidStylesForGuide(currentGuide, newFramework); if (validStyles.length === 0) { // Guide not available in new framework, go to first guide const firstGuide = findFirstGuide(newFramework, getDefaultStyle(newFramework)); if (firstGuide) { navigate(`/docs/framework/${newFramework}/style/${getDefaultStyle(newFramework)}/${firstGuide}/`); } else { navigate('/docs/'); } return; } // Pick best style: current if still valid, otherwise first valid const newStyle = validStyles.includes(currentStyle) ? currentStyle : validStyles[0]; // Navigate to same guide with adjusted framework/style navigate(`/docs/framework/${newFramework}/style/${newStyle}/${currentGuideSlug}/`); }; const handleStyleChange = (event: React.ChangeEvent) => { const newStyle = event.target.value as AnySupportedStyle; // Get current guide slug from URL const currentGuideSlug = getCurrentGuideSlug(); // Find the current guide in the sidebar const currentGuide = findGuideBySlug(currentGuideSlug); if (!currentGuide) { // No current guide found, redirect to first guide of new style const firstGuide = findFirstGuide(currentFramework, newStyle); if (firstGuide) { navigate(`/docs/framework/${currentFramework}/style/${newStyle}/${firstGuide}/`); } else { navigate('/docs/'); } return; } // Check if guide is valid for current framework and new style const validStyles = getValidStylesForGuide(currentGuide, currentFramework); if (!validStyles.includes(newStyle)) { // Guide not available for new style, go to first guide const firstGuide = findFirstGuide(currentFramework, newStyle); if (firstGuide) { navigate(`/docs/framework/${currentFramework}/style/${newStyle}/${firstGuide}/`); } else { navigate('/docs/'); } return; } // Guide supports the new style, navigate to it navigate(`/docs/framework/${currentFramework}/style/${newStyle}/${currentGuideSlug}/`); }; const availableStyles = getAvailableStyles(currentFramework); return (
); }