PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 4.0.8
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v4.0.8
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / src / blocks / live-filter / Render.js

Render.js in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.8, at src/blocks/live-filter/Render.js

212 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useRef, useState, useEffect, useMemo } from "@wordpress/element";
2 import { useDeviceType } from "../../controls/controls";
3 import { KebabMenuIcon, LeftArrow, MoreArrowIcon, RightArrow } from "../../icons/arrowIcons";
4 import { usePanelBodyContext } from "../../context";
5 export default function Render({ attributes }) {
6 const {
7 selectedTerms,
8 taxonomyLimit,
9 taxonomyStyle,
10 allTextLabel,
11 filterType,
12 headingLabel,
13 headingTag,
14 headingStyle,
15 allTaxonomies,
16 taxonomyType,
17 selectTermsType,
18 excludeTerms,
19 } = attributes;
20
21 const { togglePanelBody } = usePanelBodyContext();
22
23 const [activeItem, setActiveItem] = useState("all");
24 const [isDropdownOpen, setIsDropdownOpen] = useState(false);
25 const dropdownRef = useRef(null);
26 const deviceType = useDeviceType();
27 const HeadingTag = headingTag || "h2";
28 const moreAnchorRef = useRef(null);
29
30 //.........
31
32 const limit = taxonomyLimit.device?.[deviceType]; // e.g., 5
33 const [currentPage, setCurrentPage] = useState(0);
34 const allItem = {
35 id: "all",
36 label: allTextLabel,
37 };
38
39 let allTerms = [];
40 allTaxonomies?.forEach((taxonomy) => {
41 if (taxonomyType === taxonomy.name) {
42 allTerms = [...allTerms, ...taxonomy.terms_items];
43 }
44 })
45 const updatedSelectedTerms = {
46 specific: selectedTerms && selectedTerms.length > 0 ? selectedTerms : allTerms,
47 exclude: allTerms.filter( ( term ) => !excludeTerms.some( ex => ex.id === term.id ) ),
48 all: allTerms,
49 };
50
51 const newSelectedTerms = [allItem, ...updatedSelectedTerms[selectTermsType]];
52 // Split the array into chunks
53 const paginatedTerms = useMemo(() => {
54 const chunks = [];
55 for (let i = 0; i < newSelectedTerms.length; i += limit) {
56 chunks.push(newSelectedTerms.slice(i, i + limit));
57 }
58 return chunks;
59 }, [newSelectedTerms, limit]);
60
61 // current page’s terms
62 const currentTerms = paginatedTerms[currentPage] || [];
63
64 // handle next/prev
65 const nextPage = () => {
66 if (currentPage < paginatedTerms.length - 1) {
67 setCurrentPage((p) => p + 1);
68 }
69 };
70
71 const prevPage = () => {
72 if (currentPage > 0) {
73 setCurrentPage((p) => p - 1);
74 }
75 };
76
77 const handleNavClick = (id) => {
78 setActiveItem(id);
79 setIsDropdownOpen(false);
80 };
81
82 let displayTaxonomies;
83 let moreTaxonomies;
84
85 if (filterType === "button") {
86 displayTaxonomies = currentTerms;
87
88 moreTaxonomies = updatedSelectedTerms[selectTermsType].slice(limit);
89 } else {
90 displayTaxonomies = [];
91 moreTaxonomies = updatedSelectedTerms[selectTermsType];
92 }
93
94 const handleDropdownItemClick = (id) => {
95 setActiveItem(id);
96 setIsDropdownOpen(false);
97 };
98
99 const handleMoreClick = (e) => {
100 e.preventDefault();
101 if ( taxonomyStyle !== "navigation" ) {
102 setIsDropdownOpen(!isDropdownOpen);
103 }
104 };
105
106 useEffect(() => {
107 const handleClickOutside = (event) => {
108 if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
109 setIsDropdownOpen(false);
110 }
111 };
112
113 document.addEventListener("mousedown", handleClickOutside);
114 return () => {
115 document.removeEventListener("mousedown", handleClickOutside);
116 };
117 }, []);
118
119 return (
120 <div className="sps-live-filter-layout-two">
121 <nav className="sps-live-filter-navbar">
122 { headingLabel && <HeadingTag
123 onClick={() => togglePanelBody("heading")}
124 className={`sps-live-filter-latest-post-btn ${headingStyle}`}
125 >
126 {headingLabel}
127 </HeadingTag> }
128 <div className="sps-live-filter-nav-container">
129 <ul className="sps-live-filter-nav-menu">
130 {displayTaxonomies.filter( item => item.label ).map((item) => (
131 <li key={item?.id} className="sps-live-filter-nav-item">
132 <a
133 href={"#"}
134 className={`sps-live-filter-nav-link ${activeItem === item?.id ? "active" : ""}`}
135 onClick={(e) => {
136 e.preventDefault();
137 handleNavClick(item?.id);
138 }}
139 rel={"noopener noreferrer"}
140 >
141 {item?.label}
142 </a>
143 </li>
144 ))}
145
146 {moreTaxonomies.length > 0 ? (
147 <li
148 ref={dropdownRef}
149 className={`sps-live-filter-nav-item sps-live-filter-dropdown ${
150 isDropdownOpen ? "active" : ""
151 }`}
152 >
153 <a
154 ref={moreAnchorRef}
155 href="#"
156 className="sps-live-filter-nav-link"
157 onClick={ handleMoreClick }
158 >
159 {taxonomyStyle === "kebabMenu" && <KebabMenuIcon />}
160
161 {taxonomyStyle == "more" && (
162 <>
163 {filterType === "button" ? "More" : allTextLabel}
164 <span className="sps-live-filter-dropdown-arrow">
165 <MoreArrowIcon />
166 </span>
167 </>
168 )}
169
170 {taxonomyStyle === "navigation" && (
171 <>
172 <span onClick={ prevPage } disabled={currentPage === 0}>
173 <LeftArrow />
174 </span>
175 <span
176 onClick={ nextPage }
177 disabled={currentPage === paginatedTerms.length - 1}
178 >
179 <RightArrow />
180 </span>
181 </>
182 )}
183 </a>
184
185 <div className="sps-live-filter-dropdown-menu">
186 {moreTaxonomies.map((item) => (
187 <a
188 key={item?.id}
189 href="#"
190 className={`sps-live-filter-dropdown-item ${
191 activeItem === item?.id ? "active" : ""
192 }`}
193 onClick={(e) => {
194 e.preventDefault();
195 handleDropdownItemClick(item?.id);
196 }}
197 >
198 {item?.label}
199 </a>
200 ))}
201 </div>
202 </li>
203 ) : (
204 ""
205 )}
206 </ul>
207 </div>
208 </nav>
209 </div>
210 );
211 }
212