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 / news-ticker / cutomTypewriter.js

cutomTypewriter.js in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.8, at src/blocks/news-ticker/cutomTypewriter.js

92 lines 2.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useEffect, useRef, useState } from "@wordpress/element";
2 import { stringTrim } from "../shared/helpFn";
3
4 const NewsTickerTypewriter = ({ posts = [], limit = "", className = "", showImage = false }) => {
5 const [currentText, setCurrentText] = useState("");
6 const [isDeleting, setIsDeleting] = useState(false);
7 const [placeholderImg, setPlaceholderImg] = useState("");
8 const animationRef = useRef(null);
9 const stateRef = useRef({
10 postIndex: 0,
11 charIndex: 0,
12 delay: 60,
13 lastTime: 0,
14 });
15
16 useEffect(() => {
17 setPlaceholderImg(
18 window.location.origin + "/wp-content/plugins/smart-post-show-pro/public/assets/img/placeholder.png"
19 );
20 }, []);
21
22 useEffect(() => {
23 if (!posts.length) return;
24
25 const animate = (timestamp) => {
26 const state = stateRef.current;
27
28 if (!state.lastTime) state.lastTime = timestamp;
29 const delta = timestamp - state.lastTime;
30
31 // if (!isPaused && delta >= state.delay) {
32 const { title, url, target } = posts[state.postIndex];
33 const limitTitle = stringTrim(title, limit);
34
35 if (delta >= state.delay) {
36 let newCharIndex = isDeleting ? state.charIndex - 1 : state.charIndex + 1;
37 const newText = limitTitle.substring(0, newCharIndex);
38
39 setCurrentText(newText);
40 state.charIndex = newCharIndex;
41 state.delay = isDeleting ? 20 : 60;
42
43 if (!isDeleting && newText === limitTitle) {
44 state.delay = 1500; // Pause after full text
45 setIsDeleting(true);
46 } else if (isDeleting && newCharIndex === 0) {
47 setIsDeleting(false);
48 state.postIndex = (state.postIndex + 1) % posts.length;
49 state.delay = 800; // Pause before next word
50 }
51
52 state.lastTime = timestamp;
53 }
54
55 animationRef.current = requestAnimationFrame(animate);
56 };
57
58 animationRef.current = requestAnimationFrame(animate);
59
60 return () => {
61 if (animationRef.current) {
62 cancelAnimationFrame(animationRef.current);
63 }
64 };
65 }, [posts, isDeleting]);
66 // }, [posts, isDeleting, isPaused]);
67
68 if (!posts?.length) return null;
69
70 const currentPost = posts[stateRef.current.postIndex] || {};
71 const { url, target, post_thumbnail_url } = currentPost;
72
73 return (
74 <div
75 className={`sps-news-ticker-typewriter-js`}
76 // onMouseEnter={() => setIsPaused(true)}
77 // onMouseLeave={() => setIsPaused(false)}
78 >
79 <span className={`${className}`}>
80 {showImage && (
81 <img src={post_thumbnail_url || placeholderImg} className="sp-ticker-img sp-img-circle" />
82 )}
83 <a className="sp-smart-post-ticker-title" href={url} target={target} rel="noopener noreferrer">
84 {currentText}
85 </a>
86 </span>
87 </div>
88 );
89 };
90
91 export default NewsTickerTypewriter;
92