HEX
Server: Apache
System: Linux outside 5.4.8_Algonet_ZeroMAC_0.9.4.8 #6 SMP Mon Feb 3 20:36:07 CET 2020 x86_64
User: server (1002)
PHP: 8.3.20
Disabled: exec,passthru,shell_exec,system,proc_open,popen,curl_multi_exec,parse_ini_file,show_source
Upload Files
File: /home/muoapartman/www/wp-content/plugins/animated-blocks/src/animate/index.js
// Import styles
import './styles/style.scss';
import './styles/editor.scss';

// Internal dependencies
import classnames from 'classnames';
import { animations } from './animations';
import icon from '../../block/icon.js';

// WordPress dependencies
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, InspectorControls, InnerBlocks, store as blockEditorStore } from '@wordpress/block-editor';
import { PanelBody, TextControl, SelectControl, ToggleControl, RangeControl, BaseControl } from '@wordpress/components';
import { Fragment, useState, useEffect } from '@wordpress/element';
import { useSelect } from '@wordpress/data';

// External dependencies
import Select from 'react-select';
import reactSelectStyles from 'gutenberg-react-select-styles';

/**
 * Register: Animated Block
 *
 * @link https://wordpress.org/gutenberg/handbook/block-api/
 * @param  {string}   name     Block name
 * @param  {Object}   settings Block settings
 */
registerBlockType( 'ab/animate', {
	icon: icon,

	/**
	 * Define the edit interface
	 *
	 * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
	 */
	edit( { attributes, setAttributes, clientId } ) {
		const { animation, customClass, duration, delay, offsetTop, threshold, hideEl } = attributes;
		const [ animateDemo, setAnimateDemo ] = useState('');
		const [ selectedOption, setSelectedOption ] = useState('');

		useEffect( () => {
			// Set the selected option object
			if ( animation ) {
				setSelectedOption( animations.filter(x => x.value === animation) );
			}

			// Convert seconds to milliseconds from plugin version 1.1.0
			if ( typeof duration == "number" && duration <= 10 ) {
				console.log('convert duration');
				let newDuration = String( duration * 1000 );
	    	setAttributes( { duration: newDuration } );
	    }

	    if ( typeof delay == "number" && delay <= 10 ) {
				console.log('convert delay');
				let newDelay = String( delay * 1000 );
	    	setAttributes( { delay: newDelay } );
	    }
		}, [] );

		// Return InnerBlocks block count
		const { hasChildBlocks } = useSelect(
			( select ) => {
				const { getBlockOrder } = select(
					blockEditorStore
				);

				return {
					hasChildBlocks: getBlockOrder( clientId ).length > 0
				};
			},
			[ clientId ]
		);

		// Handle animation selection
		const handleSelectChange = ( selectedAnimation ) => {
			if ( ! selectedAnimation ) {
				setAttributes( { animation: undefined } );
				setSelectedOption( undefined );
				return;
			}
			setAttributes( { animation: selectedAnimation.value } );
			setSelectedOption( selectedAnimation );
			setAnimateDemo( selectedAnimation.value );
		};

		const blockProps = useBlockProps();

		return (
			<Fragment>
				<InspectorControls>
					<PanelBody>
						<BaseControl id="ab-animation-options" label="Animation">
							<Select
								name="animation"
								value={ selectedOption }
								options={ animations }
								onChange={ handleSelectChange }
								isClearable={ true }
								styles={ reactSelectStyles }
							/>
						</BaseControl>

            <TextControl
              label={ __( 'Custom animation' ) }
              value={ customClass }
              onChange={ ( value ) => setAttributes( { customClass: value } ) }
							help={ __( 'Add a custom CSS class name.' ) }
            />

						<TextControl
	            label={ __( 'Duration (ms)' ) }
							type="number"
	            value={ duration }
	            onChange={ ( value ) => setAttributes( { duration: value } ) }
							help={ __( 'The number of milliseconds that the animation takes to complete.' ) }
		        />

						<TextControl
							label={ __( 'Delay (ms)' ) }
							type="number"
							value={ delay }
							onChange={ ( value ) => setAttributes( { delay: value } ) }
							help={ __( 'The number of milliseconds to wait before animating.' ) }
						/>

		        <RangeControl
	            label={ __( 'Threshold (%)' ) }
	            value={ threshold }
							initialPosition={ 50 }
	            onChange={ ( value ) => setAttributes( { threshold: value } ) }
	            min={ 1 }
	            max={ 100 }
							help={ __( 'The percentage of the block at which the animation begins.' ) }
		        />

						<ToggleControl
	            label={ __( 'Start with opacity 0' ) }
	            checked={ hideEl }
	            onChange={ ( value ) => setAttributes( { hideEl: value } ) }
		        />
					</PanelBody>
				</InspectorControls>

				<InspectorControls __experimentalGroup="advanced">
					<TextControl
						label={ __( 'Offset (px)' ) }
						type="number"
						value={ offsetTop }
						onChange={ ( value ) => setAttributes( { offsetTop: value } ) }
						help={ __( 'The number of pixels the animated block should be offset from the top of the page. Use this option when a page has a top fixed navigation bar.' ) }
					/>
				</InspectorControls>

				<div {...blockProps}>
					<div
						className={ classnames(
							'sb-animate-demo',
							'animated',
							animateDemo
						) }
						data-ab-animation={ animation }
						style={ { "animation-duration": duration ? (duration / 1000) + "s" : undefined } }
					>
						<InnerBlocks
							renderAppender={ hasChildBlocks ? undefined : InnerBlocks.ButtonBlockAppender }
						/>
					</div>
				</div>
			</Fragment>
		);
	},

	/**
	 * Define the final markup
	 *
	 * @link https://wordpress.org/gutenberg/handbook/block-api/block-edit-save/
	 */
	save( { attributes } ) {
		const { animation, customClass, duration, delay, offsetTop, threshold, hideEl } = attributes;

		const animationClasses = (animation || customClass) ? [animation, customClass].filter(Boolean).join(" ") : undefined;

		const blockProps = useBlockProps.save( {
  		className: hideEl && "ab-is-hidden",
			"data-scroll-class": animationClasses,
			"data-scroll-delay": ( delay > 0 ) ? delay : undefined,
			"data-scroll-threshold": threshold,
			"data-scroll-offset-top": offsetTop,
			style: { "animation-duration": duration ? (duration / 1000) + "s" : undefined }
  	} );

		return (
			<div {...blockProps}>
				<InnerBlocks.Content />
			</div>
		);
	},

	deprecated: [
		// v1.1.0
		{
			attributes: {
				animation: {
					type: 'string'
				},
				customClass: {
					type: 'string'
				},
				duration: {
					type: 'number'
				},
				delay: {
					type: 'number',
					default: 0
				},
				offsetTop: {
					type: 'number'
				},
				threshold: {
					type: 'number'
				},
				hideEl: {
					type: 'boolean',
					default: false
				}
			},

			save( { attributes } ) {
				const { animation, customClass, duration, delay, offsetTop, threshold, hideEl } = attributes;

				const animationClasses = (animation || customClass) ? [animation, customClass].filter(Boolean).join(" ") : undefined;

				const blockProps = useBlockProps.save( {
		  		className: hideEl && "ab-is-hidden",
					"data-scroll-class": animationClasses,
					"data-scroll-delay": ( delay > 0 ) ? delay : undefined,
					"data-scroll-threshold": threshold,
					style: { "animation-duration": (duration && duration !== 1) ? duration + "s" : undefined }
		  	} );

				return (
					<div {...blockProps}>
						<InnerBlocks.Content />
					</div>
				);
			}
		},

		// v1.0.7
		{
			attributes: {
				animation: {
					type: 'string'
				},
				customClass: {
					type: 'string'
				},
				delay: {
					type: 'number',
					default: 0
				},
				threshold: {
					type: 'number',
					default: 50
				},
				hideEl: {
					type: 'boolean',
					default: false
				}
			},

			save( { attributes } ) {
				const { animation = '', customClass = '', delay, threshold, hideEl } = attributes;

				return (
					<div
					className={ classnames( { 'scroll-hide': hideEl } ) }
					data-scroll-class={ `${animation} ${customClass}` }
					data-scroll-delay={ ( delay > 0 ) ? delay : 0 }
					data-scroll-threshold={ threshold }
					>
						<InnerBlocks.Content />
					</div>
				);
			}
		}
	]
} );