/** * Title Preview Component * * Live preview of title formats with real-time updates * * @package ThinkRank * @since 1.0.0 */ import { useState, useEffect } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { Card, CardBody, CardHeader, __experimentalSpacer as Spacer } from '@wordpress/components'; /** * Title Preview Component */ const TitlePreview = ({ titleFormats, separator, siteInfo, disabled = false }) => { const [previews, setPreviews] = useState({}); /** * Get separator character */ const getSeparatorChar = (separatorType) => { const separators = { 'pipe': '|', 'dash': '-', 'double_right': '»', 'single_right': '›', 'bullet': '•' }; return separators[separatorType] || '|'; }; /** * Replace template variables with sample data */ const replaceVariables = (template, pageType) => { const sampleData = { '%site_title%': siteInfo.site_name || 'Your Site Name', '%site_name%': siteInfo.site_name || 'Your Site Name', '%site_description%': siteInfo.site_description || 'Your site description', '%tagline%': siteInfo.tagline || 'Your site tagline', '%post_title%': 'Sample Blog Post Title', '%page_title%': 'Sample Page Title', '%category_title%': 'Sample Category', '%tag_title%': 'Sample Tag', '%author_name%': 'John Doe', '%search_term%': 'sample search', '%archive_title%': 'Sample Archive' }; let result = template; Object.keys(sampleData).forEach(variable => { result = result.replace(new RegExp(variable.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), sampleData[variable]); }); return result; }; /** * Generate title preview */ const generatePreview = (template, pageType) => { if (!template) return ''; const separatorChar = ` ${getSeparatorChar(separator)} `; let preview = replaceVariables(template, pageType); // Replace separator placeholders preview = preview.replace(/\s*\|\s*/g, separatorChar); return preview; }; /** * Update previews when formats or separator change */ useEffect(() => { const newPreviews = {}; Object.keys(titleFormats).forEach(pageType => { newPreviews[pageType] = generatePreview(titleFormats[pageType], pageType); }); setPreviews(newPreviews); }, [titleFormats, separator, siteInfo]); /** * Get page type display name */ const getPageTypeLabel = (pageType) => { const labels = { 'homepage_title': __('Homepage', 'thinkrank'), 'post_title': __('Blog Post', 'thinkrank'), 'page_title': __('Page', 'thinkrank'), 'category_title': __('Category', 'thinkrank'), 'tag_title': __('Tag', 'thinkrank'), 'author_title': __('Author', 'thinkrank'), 'search_title': __('Search Results', 'thinkrank'), 'archive_title': __('Archive', 'thinkrank') }; return labels[pageType] || pageType; }; /** * Get title length and status */ const getTitleStatus = (title) => { const length = title.length; let status = 'good'; let message = ''; if (length < 30) { status = 'warning'; message = __('Too short - consider adding more descriptive text', 'thinkrank'); } else if (length > 60) { status = 'warning'; message = __('Too long - may be truncated in search results', 'thinkrank'); } else { status = 'good'; message = __('Good length for SEO', 'thinkrank'); } return { length, status, message }; }; if (disabled) { return (

{__('Title preview is disabled. Enable site identity to see live previews.', 'thinkrank')}

); } return (

{__('Live Title Preview', 'thinkrank')}

{__('See how your titles will appear with current settings', 'thinkrank')}

{Object.keys(previews).map(pageType => { const preview = previews[pageType]; const titleStatus = getTitleStatus(preview); return (
{getPageTypeLabel(pageType)} {titleStatus.length} chars
{preview || __('No title format set', 'thinkrank')}
{titleStatus.message && (

{titleStatus.message}

)}
); })}
{__('SEO Tips:', 'thinkrank')}
  • {__('Keep titles between 30-60 characters for optimal SEO', 'thinkrank')}
  • {__('Include your target keyword near the beginning', 'thinkrank')}
  • {__('Make titles descriptive and compelling for users', 'thinkrank')}
  • {__('Use consistent separators across your site', 'thinkrank')}
); }; export default TitlePreview;