@ai-growth/nextjs
Version:
Seamlessly integrate Sanity CMS with Next.js applications for automated blog routing and rendering
246 lines (245 loc) • 13.5 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// ============================================================================
// THEME DEFAULTS
// ============================================================================
const defaultTheme = {
colors: {
primary: '#0066cc',
secondary: '#666666',
background: '#ffffff',
text: '#333333',
accent: '#ff6b6b',
},
fonts: {
heading: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
body: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
code: 'SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace',
},
spacing: {
xs: '0.25rem',
sm: '0.5rem',
md: '1rem',
lg: '1.5rem',
xl: '2rem',
xxl: '3rem',
},
borderRadius: {
sm: '0.25rem',
md: '0.5rem',
lg: '1rem',
},
};
// ============================================================================
// MAIN TEMPLATE COMPONENT
// ============================================================================
export const DefaultTemplateV2 = ({ content, isLoading = false, error = '', onRetry, className = '', theme = defaultTheme, showMetadata = true, showAuthor = true, }) => {
// Loading state
if (isLoading) {
return _jsx(LoadingPlaceholder, { theme: theme });
}
// Error state
if (error) {
return (_jsx("div", { className: `default-template-v2 error ${className}`, children: _jsx(ErrorDisplay, { error: error, ...(onRetry && { onRetry }), theme: theme }) }));
}
// No content
if (!content) {
return (_jsx("div", { className: `default-template-v2 no-content ${className}`, children: _jsx("div", { style: { textAlign: 'center', padding: theme.spacing.xl }, children: _jsx("h2", { style: { color: theme.colors.text }, children: "No content available" }) }) }));
}
return (_jsxs("article", { className: `default-template-v2 ${className}`, style: {
fontFamily: theme.fonts.body,
color: theme.colors.text,
backgroundColor: theme.colors.background,
lineHeight: 1.6,
}, children: [_jsxs("header", { style: { marginBottom: theme.spacing.xl }, children: [_jsx("h1", { style: {
fontFamily: theme.fonts.heading,
fontSize: '2.5rem',
fontWeight: 'bold',
color: theme.colors.primary,
marginBottom: theme.spacing.md,
lineHeight: 1.2,
}, children: content.title }), content.description && (_jsx("p", { style: {
fontSize: '1.25rem',
color: theme.colors.secondary,
marginBottom: theme.spacing.lg,
fontStyle: 'italic',
}, children: content.description })), showMetadata && (_jsxs("div", { style: {
display: 'flex',
gap: theme.spacing.md,
marginBottom: theme.spacing.lg,
fontSize: '0.875rem',
color: theme.colors.secondary,
flexWrap: 'wrap',
}, children: [content.publishedAt && (_jsxs("span", { children: ["\uD83D\uDCC5 ", new Date(content.publishedAt).toLocaleDateString()] })), content._type && (_jsxs("span", { children: ["\uD83D\uDCDD ", content._type] })), content.readingTime && (_jsxs("span", { children: ["\u23F1\uFE0F ", content.readingTime, " min read"] }))] })), showAuthor && content.author && (_jsx(DefaultAuthor, { author: content.author, theme: theme }))] }), _jsxs("main", { children: [content.image && (_jsx("div", { style: { marginBottom: theme.spacing.xl }, children: _jsx("img", { src: content.image.url || content.image, alt: content.image.alt || content.title, style: {
width: '100%',
height: 'auto',
borderRadius: theme.borderRadius.lg,
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
} }) })), Array.isArray(content.content) ? (content.content.map((block, index) => (_jsx(ContentBlock, { block: block, theme: theme }, block._key || index)))) : typeof content.content === 'string' ? (_jsx("div", { style: {
fontSize: '1.125rem',
lineHeight: 1.7,
marginBottom: theme.spacing.lg,
}, dangerouslySetInnerHTML: { __html: content.content } })) : content.content ? (_jsx("div", { style: { marginBottom: theme.spacing.lg }, children: _jsx("pre", { style: {
fontFamily: theme.fonts.code,
backgroundColor: '#f5f5f5',
padding: theme.spacing.md,
borderRadius: theme.borderRadius.md,
overflow: 'auto',
}, children: JSON.stringify(content.content, null, 2) }) })) : null, content.tags && content.tags.length > 0 && (_jsxs("div", { style: {
marginTop: theme.spacing.xl,
paddingTop: theme.spacing.lg,
borderTop: `1px solid ${theme.colors.secondary}20`,
}, children: [_jsx("h3", { style: {
fontFamily: theme.fonts.heading,
fontSize: '1rem',
fontWeight: '600',
marginBottom: theme.spacing.md,
color: theme.colors.text,
}, children: "Tags" }), _jsx("div", { style: {
display: 'flex',
gap: theme.spacing.sm,
flexWrap: 'wrap',
}, children: content.tags.map((tag, index) => (_jsx("span", { style: {
backgroundColor: theme.colors.accent,
color: 'white',
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
borderRadius: theme.borderRadius.sm,
fontSize: '0.75rem',
fontWeight: '500',
}, children: tag }, index))) })] }))] }), _jsx("footer", { style: {
marginTop: theme.spacing.xxl,
paddingTop: theme.spacing.lg,
borderTop: `1px solid ${theme.colors.secondary}20`,
textAlign: 'center',
fontSize: '0.875rem',
color: theme.colors.secondary,
}, children: content.slug && (_jsxs("p", { children: ["\uD83D\uDCCE ", _jsx("strong", { children: "Slug:" }), " ", content.slug] })) })] }));
};
// ============================================================================
// CONTENT BLOCK RENDERER
// ============================================================================
const ContentBlock = ({ block }) => {
if (!block || !block._type) {
return null;
}
const baseStyle = {
marginBottom: '1.5rem',
};
switch (block._type) {
case 'block':
return (_jsx("div", { style: baseStyle, children: block.children?.map((child, index) => (_jsx("span", { children: child.marks?.includes('strong') ? (_jsx("strong", { children: child.text })) : child.marks?.includes('em') ? (_jsx("em", { children: child.text })) : (child.text) }, index))) }));
case 'image':
return (_jsxs("div", { style: baseStyle, children: [_jsx("img", { src: block.asset?.url || block.url, alt: block.alt || 'Content image', style: {
width: '100%',
height: 'auto',
borderRadius: '0.5rem',
} }), block.caption && (_jsx("p", { style: {
fontSize: '0.875rem',
color: '#666',
textAlign: 'center',
marginTop: '0.5rem',
fontStyle: 'italic',
}, children: block.caption }))] }));
case 'code':
return (_jsx("div", { style: baseStyle, children: _jsx("pre", { style: {
backgroundColor: '#f5f5f5',
padding: '1rem',
borderRadius: '0.5rem',
overflow: 'auto',
fontFamily: 'SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace',
}, children: _jsx("code", { children: block.code }) }) }));
case 'quote':
return (_jsxs("blockquote", { style: {
...baseStyle,
borderLeft: '4px solid #0066cc',
paddingLeft: '1rem',
fontStyle: 'italic',
fontSize: '1.125rem',
color: '#555',
}, children: [block.text, block.author && (_jsxs("cite", { style: {
display: 'block',
marginTop: '0.5rem',
fontSize: '0.875rem',
color: '#666',
}, children: ["\u2014 ", block.author] }))] }));
default:
return (_jsx("div", { style: baseStyle, children: _jsxs("pre", { style: {
backgroundColor: '#f8f8f8',
padding: '0.5rem',
borderRadius: '0.25rem',
fontSize: '0.75rem',
color: '#666',
}, children: ["Unknown block type: ", block._type] }) }));
}
};
// ============================================================================
// AUTHOR COMPONENT
// ============================================================================
const DefaultAuthor = ({ author }) => (_jsxs("div", { style: {
display: 'flex',
alignItems: 'center',
gap: '0.75rem',
padding: '0.75rem',
backgroundColor: '#f8f9fa',
borderRadius: '0.5rem',
border: '1px solid #e9ecef',
}, children: [author.image && (_jsx("img", { src: author.image.url || author.image, alt: author.name || 'Author', style: {
width: '40px',
height: '40px',
borderRadius: '50%',
objectFit: 'cover',
} })), _jsxs("div", { children: [_jsx("div", { style: {
fontWeight: '600',
fontSize: '0.875rem',
color: '#212529',
}, children: author.name || 'Unknown Author' }), author.bio && (_jsx("div", { style: {
fontSize: '0.75rem',
color: '#6c757d',
marginTop: '0.125rem',
}, children: author.bio }))] })] }));
// ============================================================================
// LOADING PLACEHOLDER
// ============================================================================
const LoadingPlaceholder = () => (_jsxs("div", { style: {
padding: '2rem',
textAlign: 'center',
color: '#666',
}, children: [_jsx("div", { style: {
width: '40px',
height: '40px',
border: '3px solid #f3f3f3',
borderTop: '3px solid #0066cc',
borderRadius: '50%',
animation: 'spin 1s linear infinite',
margin: '0 auto 1rem',
} }), _jsx("p", { children: "Loading content..." })] }));
// ============================================================================
// ERROR DISPLAY
// ============================================================================
const ErrorDisplay = ({ error, onRetry }) => (_jsxs("div", { style: {
padding: '2rem',
textAlign: 'center',
color: '#dc3545',
backgroundColor: '#f8d7da',
border: '1px solid #f5c6cb',
borderRadius: '0.5rem',
}, children: [_jsx("div", { style: {
fontSize: '2rem',
marginBottom: '1rem',
}, children: "\u26A0\uFE0F" }), _jsx("h3", { style: {
fontSize: '1.25rem',
fontWeight: '600',
marginBottom: '0.5rem',
}, children: "Content Error" }), _jsx("p", { style: {
marginBottom: '1rem',
color: '#721c24',
}, children: error }), onRetry && (_jsx("button", { onClick: onRetry, style: {
backgroundColor: '#dc3545',
color: 'white',
border: 'none',
padding: '0.5rem 1rem',
borderRadius: '0.25rem',
cursor: 'pointer',
fontSize: '0.875rem',
fontWeight: '500',
}, children: "Try Again" }))] }));
export default DefaultTemplateV2;