@ai-growth/nextjs
Version:
Seamlessly integrate Sanity CMS with Next.js applications for automated blog routing and rendering
170 lines (169 loc) • 7.23 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useIsCmsRoute = exports.useCmsRouteState = exports.CmsRouteHandler = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const router_1 = require("next/router");
const DefaultTemplate_1 = require("./DefaultTemplate");
const cms_content_1 = require("../utils/cms-content");
const route_config_1 = require("../utils/route-config");
/**
* CMS Route Handler for Next.js App Router
*
* This component handles CMS routing by checking if the current route is a CMS route,
* fetching content accordingly, and rendering the appropriate template or children.
*/
const CmsRouteHandler = ({ children, customTemplate, loadingComponent, errorComponent, contentOptions = {}, className, showLoading = true, showErrors = true, onRouteChange, onContentLoaded, onContentError, }) => {
const router = (0, router_1.useRouter)();
const [state, setState] = (0, react_1.useState)({
isCmsRoute: false,
isLoading: false,
currentSlug: '',
content: null,
error: null,
});
// Fetch content for CMS routes
const fetchContent = (0, react_1.useCallback)(async (path) => {
setState(prev => ({ ...prev, isLoading: true, error: null }));
try {
const result = await (0, cms_content_1.validateContentRoute)(path, contentOptions);
if (result.isValid && result.content) {
setState(prev => ({
...prev,
isLoading: false,
content: result.content || null,
error: null,
}));
onContentLoaded?.(result.content);
}
else {
const errorMessage = result.error || 'Content not found';
setState(prev => ({
...prev,
isLoading: false,
content: null,
error: errorMessage,
}));
onContentError?.(errorMessage);
}
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
setState(prev => ({
...prev,
isLoading: false,
content: null,
error: errorMessage,
}));
onContentError?.(errorMessage);
}
}, [contentOptions, onContentLoaded, onContentError]);
// Handle route changes
(0, react_1.useEffect)(() => {
if (!router.isReady)
return;
const currentPath = router.asPath;
const isCms = (0, route_config_1.isValidCmsRoute)(currentPath);
// Avoid unnecessary updates
if (state.currentSlug === currentPath && state.isCmsRoute === isCms) {
return;
}
setState(prev => ({
...prev,
isCmsRoute: isCms,
currentSlug: currentPath,
}));
onRouteChange?.(currentPath, isCms);
if (isCms) {
fetchContent(currentPath);
}
}, [router.isReady, router.asPath, state.currentSlug, state.isCmsRoute, onRouteChange]);
// Separate effect for fetchContent to avoid dependency issues
(0, react_1.useEffect)(() => {
if (state.isCmsRoute && state.currentSlug && !state.isLoading && !state.content && !state.error) {
fetchContent(state.currentSlug);
}
}, [state.isCmsRoute, state.currentSlug, state.isLoading, state.content, state.error, fetchContent]);
// Retry function
const handleRetry = (0, react_1.useCallback)(() => {
if (state.currentSlug) {
fetchContent(state.currentSlug);
}
}, [state.currentSlug, fetchContent]);
// If router is not ready, render children
if (!router.isReady) {
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
}
// If not a CMS route, render children
if (!state.isCmsRoute) {
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
}
// CMS route handling
const TemplateComponent = customTemplate || DefaultTemplate_1.DefaultTemplate;
// Show loading state
if (state.isLoading && showLoading) {
if (loadingComponent) {
return (0, jsx_runtime_1.jsx)("div", { className: className, children: loadingComponent });
}
return ((0, jsx_runtime_1.jsx)("div", { className: className, children: (0, jsx_runtime_1.jsx)(TemplateComponent, { content: null, isLoading: true, error: "", onRetry: handleRetry }) }));
}
// Show error state
if (state.error && showErrors) {
if (errorComponent) {
const ErrorComponent = errorComponent;
return ((0, jsx_runtime_1.jsx)("div", { className: className, children: (0, jsx_runtime_1.jsx)(ErrorComponent, { error: state.error, onRetry: handleRetry }) }));
}
return ((0, jsx_runtime_1.jsx)("div", { className: className, children: (0, jsx_runtime_1.jsx)(TemplateComponent, { content: null, isLoading: false, error: state.error, onRetry: handleRetry }) }));
}
// Show content
if (state.content) {
return ((0, jsx_runtime_1.jsx)("div", { className: className, children: (0, jsx_runtime_1.jsx)(TemplateComponent, { content: state.content, isLoading: false, error: "", onRetry: handleRetry }) }));
}
// Fallback: render children if no CMS content and not showing errors
if (!showErrors) {
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
}
// Default fallback
return ((0, jsx_runtime_1.jsx)("div", { className: className, children: (0, jsx_runtime_1.jsx)(TemplateComponent, { content: null, isLoading: false, error: "", onRetry: handleRetry }) }));
};
exports.CmsRouteHandler = CmsRouteHandler;
// Hooks para compatibilidade com testes existentes
const useCmsRouteState = () => {
const router = (0, router_1.useRouter)();
const [state, setState] = (0, react_1.useState)({
isCmsRoute: false,
isLoading: false,
currentSlug: '',
content: null,
error: null,
});
(0, react_1.useEffect)(() => {
if (!router.isReady)
return;
const currentPath = router.asPath;
const isCms = (0, route_config_1.isValidCmsRoute)(currentPath);
setState(prev => ({
...prev,
isCmsRoute: isCms,
currentSlug: currentPath,
}));
}, [router.isReady, router.asPath]);
return state;
};
exports.useCmsRouteState = useCmsRouteState;
const useIsCmsRoute = () => {
const router = (0, router_1.useRouter)();
const [isCmsRoute, setIsCmsRoute] = (0, react_1.useState)(false);
(0, react_1.useEffect)(() => {
if (!router.isReady) {
setIsCmsRoute(false);
return;
}
const currentPath = router.asPath;
const isCms = (0, route_config_1.isValidCmsRoute)(currentPath);
setIsCmsRoute(isCms);
}, [router.isReady, router.asPath]);
return isCmsRoute;
};
exports.useIsCmsRoute = useIsCmsRoute;
exports.default = exports.CmsRouteHandler;