PluginProbe
Parse.ly / 3.24.2
Parse.ly v3.24.2
3.24.2 3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 All 106 releases
wp-parsely / src / content-helper / common / components / loading / component.tsx

component.tsx in Parse.ly 3.24.2, at src/content-helper/common/components/loading/component.tsx

132 lines 3.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * WordPress dependencies
3 */
4 import { Spinner } from '@wordpress/components';
5 import { useEffect, useState } from '@wordpress/element';
6 import { __ } from '@wordpress/i18n';
7
8 /**
9 * TypewriterText component that animates text with a typewriter effect.
10 *
11 * @since 3.19.0
12 *
13 * @param {Object} props The component's props.
14 * @param {string} props.message The message to display with typewriter effect.
15 */
16 const TypewriterText = ( { message }: { message: string } ): JSX.Element => {
17 const [ displayText, setDisplayText ] = useState( '' );
18 const [ currentIndex, setCurrentIndex ] = useState( 0 );
19 const [ isTyping, setIsTyping ] = useState( true );
20
21 useEffect( () => {
22 // Reset when message changes
23 setDisplayText( '' );
24 setCurrentIndex( 0 );
25 setIsTyping( true );
26 }, [ message ] );
27
28 useEffect( () => {
29 if ( ! isTyping ) {
30 return;
31 }
32
33 if ( currentIndex < message.length ) {
34 // Still typing the message.
35 const typingTimeout = setTimeout( () => {
36 setDisplayText( ( prev ) => prev + message.charAt( currentIndex ) );
37 setCurrentIndex( ( prev ) => prev + 1 );
38 }, 50 ); // Typing speed.
39
40 return () => clearTimeout( typingTimeout );
41 }
42 }, [ currentIndex, isTyping, message ] );
43
44 return (
45 <div className="wp-parsely-typewriter-text">
46 { displayText }
47 </div>
48 );
49 };
50
51 /**
52 * Defines the props structure for Loading.
53 *
54 * @since 3.19.0
55 */
56 type LoadingProps = {
57 className?: string;
58 loading?: boolean;
59 showSpinner?: boolean;
60 messages?: string[];
61 randomOrder?: boolean;
62 children?: React.ReactNode;
63 typewriter: boolean;
64 };
65
66 /**
67 * Loading component that displays a spinner and a message.
68 *
69 * @since 3.19.0
70 *
71 * @param {LoadingProps} props The component's props.
72 */
73 export const Loading = ( {
74 className = '',
75 loading = true,
76 showSpinner = true,
77 randomOrder = false,
78 messages = [ __( 'Loading…', 'wp-parsely' ) ],
79 children,
80 typewriter = false,
81 }: LoadingProps ): JSX.Element => {
82 const [ currentMessage, setCurrentMessage ] = useState<string>( '' );
83 const [ currentIndex, setCurrentIndex ] = useState( 0 );
84
85 useEffect( () => {
86 if ( ! loading ) {
87 return;
88 }
89
90 if ( '' === currentMessage ) {
91 setCurrentMessage( messages[ randomOrder ? Math.floor( Math.random() * messages.length ) : 0 ] );
92 }
93
94 const updateMessage = () => {
95 if ( randomOrder ) {
96 // Pick a random message different from the current one.
97 let nextIndex;
98 do {
99 nextIndex = Math.floor( Math.random() * messages.length );
100 } while ( messages.length > 1 && nextIndex === currentIndex );
101 setCurrentIndex( nextIndex );
102 setCurrentMessage( messages[ nextIndex ] );
103 } else {
104 // Move to next message sequentially.
105 const nextIndex = ( currentIndex + 1 ) % messages.length;
106 setCurrentIndex( nextIndex );
107 setCurrentMessage( messages[ nextIndex ] );
108 }
109 };
110
111 // Calculate pause duration based on message length (100ms per character).
112 const pauseDuration = currentMessage.length * 100;
113
114 const intervalId = setInterval( updateMessage, pauseDuration );
115
116 return () => clearInterval( intervalId );
117 }, [ loading, messages, currentIndex, currentMessage, randomOrder ] );
118
119 return (
120 <div className={ `wp-parsely-loading ${ className }` }>
121 { showSpinner && <Spinner /> }
122 <div className="wp-parsely-loading-message">
123 { children ? children : (
124 <>
125 { typewriter ? <TypewriterText message={ currentMessage } /> : currentMessage }
126 </>
127 ) }
128 </div>
129 </div>
130 );
131 };
132