@progress/sitefinity-nextjs-sdk
Version:
Provides OOB widgets developed using the Next.js framework, which includes an abstraction layer for Sitefinity communication. Additionally, it offers an expanded API, typings, and tools for further development and integration.
84 lines (83 loc) • 6.37 kB
JavaScript
'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useRef, useState } from 'react';
function getPageFromUrl() {
if (typeof window === 'undefined') {
return 1;
}
const params = new URLSearchParams(window.location.search);
const page = parseInt(params.get('page') || '1', 10);
return page > 0 ? page : 1;
}
function buildPageUrl(page) {
if (typeof window === 'undefined') {
return `?page=${page}`;
}
const params = new URLSearchParams(window.location.search);
params.set('page', String(page));
return window.location.pathname + '?' + params.toString();
}
const DISPLAY_PAGES_COUNT = 10;
function computePagerWindow(currentPage, totalPages) {
let startPage = 1;
if (currentPage > DISPLAY_PAGES_COUNT) {
startPage = Math.floor((currentPage - 1) / DISPLAY_PAGES_COUNT) * DISPLAY_PAGES_COUNT + 1;
}
const endPage = Math.min(totalPages, startPage + DISPLAY_PAGES_COUNT - 1);
const isPreviousVisible = startPage > DISPLAY_PAGES_COUNT;
const isNextVisible = endPage < totalPages;
const previousPageIndex = startPage - 1;
const nextPageIndex = endPage + 1;
return { startPage, endPage, isPreviousVisible, isNextVisible, previousPageIndex, nextPageIndex };
}
export function ResultsDefaultView(props) {
const containerRef = useRef(null);
const pageSize = props.pageSize;
const totalCount = props.searchResults?.length ?? 0;
const totalPages = Math.ceil(totalCount / pageSize);
const [currentPage, setCurrentPage] = useState(1);
useEffect(() => {
setCurrentPage(getPageFromUrl());
const handlePopState = (e) => {
const page = (e.state && e.state.page) ? e.state.page : getPageFromUrl();
setCurrentPage(page);
};
window.addEventListener('popstate', handlePopState);
return () => window.removeEventListener('popstate', handlePopState);
}, []);
useEffect(() => {
setCurrentPage(getPageFromUrl());
}, [props.searchResults]);
function navigateToPage(page) {
if (page < 1) {
page = 1;
}
if (totalPages > 0 && page > totalPages) {
page = totalPages;
}
history.pushState({ page }, '', buildPageUrl(page));
setCurrentPage(page);
if (containerRef.current) {
containerRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
const clampedPage = Math.max(1, Math.min(currentPage, totalPages || 1));
const start = (clampedPage - 1) * pageSize;
const end = start + pageSize;
const pagedResults = props.searchResults?.slice(start, end);
const displayEnd = Math.min(end, totalCount);
const { startPage, endPage, isPreviousVisible, isNextVisible, previousPageIndex, nextPageIndex } = computePagerWindow(clampedPage, totalPages);
return (_jsx(_Fragment, { children: (props.widgetContext.requestContext.isEdit || props.searchResults !== null) && (_jsxs("div", { ref: containerRef, "data-sf-role": "ai-results", ...props.attributes, children: [_jsx("div", { className: "d-flex align-items-center justify-content-between my-3", children: _jsx("h1", { role: "alert", "aria-live": "assertive", children: props.resultsHeader }) }), _jsx("div", { children: _jsxs("h4", { children: [totalCount, " ", props.resultsNumberLabel] }) }), props.searchResults !== null && (_jsxs(_Fragment, { children: [_jsx("div", { className: "mt-5", children: pagedResults?.map((item, idx) => {
const hasLink = !!item.Link;
return (_jsx("div", { className: "mb-5", "data-sf-role": "result-item", children: _jsxs("div", { className: "flex-grow-1", children: [_jsx("h3", { className: "mb-1", children: item.Title }), hasLink && (_jsx("a", { className: "text-decoration-none", href: item.Link, children: item.Link }))] }) }, idx));
}) }), totalPages > 1 && (_jsxs("div", { className: "d-flex align-items-center justify-content-between", "data-sf-role": "pager-container", children: [_jsx("div", { children: _jsx("nav", { role: "navigation", "aria-label": "Pagination", children: _jsxs("ul", { className: "pagination", "data-sf-role": "pagination", children: [isPreviousVisible && (_jsx("li", { className: "page-item", children: _jsx("a", { suppressHydrationWarning: true, className: "page-link", href: buildPageUrl(previousPageIndex), "aria-label": "Previous", onClick: (e) => {
e.preventDefault();
navigateToPage(previousPageIndex);
}, children: _jsx("span", { "aria-hidden": "true", children: "\u00AB" }) }) })), Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i).map(page => (_jsx("li", { className: `page-item${clampedPage === page ? ' active' : ''}`, children: _jsx("a", { suppressHydrationWarning: true, className: "page-link", href: buildPageUrl(page), "aria-label": clampedPage === page ? `Page ${page}` : `Go to page ${page}`, "aria-current": clampedPage === page ? 'true' : undefined, onClick: (e) => {
e.preventDefault();
navigateToPage(page);
}, children: page }) }, page))), isNextVisible && (_jsx("li", { className: "page-item", children: _jsx("a", { suppressHydrationWarning: true, className: "page-link", href: buildPageUrl(nextPageIndex), "aria-label": "Next", onClick: (e) => {
e.preventDefault();
navigateToPage(nextPageIndex);
}, children: _jsx("span", { "aria-hidden": "true", children: "\u00BB" }) }) }))] }) }) }), totalCount > 0 && (_jsx("div", { className: "mb-3", children: _jsxs("em", { className: "text-muted", children: [_jsxs("span", { "data-sf-role": "pager-summary", children: [start + 1, " - ", displayEnd] }), ' ', _jsxs("span", { children: ["of ", totalCount, " ", props.resultsNumberLabel] })] }) }))] }))] }))] })) }));
}