frontblocks-counter-option.jsx
3 months ago
frontblocks-counter-runtime.js
6 months ago
frontblocks-counter.css
10 months ago
frontblocks-counter.js
3 months ago
frontblocks-counter-option.jsx
145 lines
| 1 | const { createHigherOrderComponent } = wp.compose; |
| 2 | const { Fragment, useEffect } = wp.element; |
| 3 | const { InspectorControls } = wp.blockEditor; |
| 4 | const { PanelBody, ToggleControl, TextControl } = wp.components; |
| 5 | const { select, dispatch } = wp.data; |
| 6 | const { __ } = wp.i18n; |
| 7 | |
| 8 | const COUNTER_BLOCKS = [ |
| 9 | 'generateblocks/text', |
| 10 | 'generateblocks/headline', |
| 11 | 'core/heading', |
| 12 | 'core/paragraph', |
| 13 | ]; |
| 14 | |
| 15 | wp.hooks.addFilter( |
| 16 | 'blocks.registerBlockType', |
| 17 | 'frontblocks/add-counter-attribute', |
| 18 | ( settings, name ) => { |
| 19 | if ( ! COUNTER_BLOCKS.includes( name ) ) { |
| 20 | return settings; |
| 21 | } |
| 22 | settings.attributes = Object.assign( settings.attributes, { |
| 23 | isCounterActive: { |
| 24 | type: 'boolean', |
| 25 | default: false, |
| 26 | }, |
| 27 | animationDuration: { |
| 28 | type: 'number', |
| 29 | default: 2000, |
| 30 | }, |
| 31 | finalNumber: { |
| 32 | type: 'string', |
| 33 | default: '', |
| 34 | }, |
| 35 | numberPrefix: { |
| 36 | type: 'string', |
| 37 | default: '', |
| 38 | }, |
| 39 | numberSuffix: { |
| 40 | type: 'string', |
| 41 | default: '', |
| 42 | }, |
| 43 | } ); |
| 44 | return settings; |
| 45 | } |
| 46 | ); |
| 47 | |
| 48 | const withCounterControl = createHigherOrderComponent( ( BlockEdit ) => { |
| 49 | return ( props ) => { |
| 50 | if ( ! COUNTER_BLOCKS.includes( props.name ) ) { |
| 51 | return <BlockEdit { ...props } />; |
| 52 | } |
| 53 | |
| 54 | const { attributes, setAttributes, clientId } = props; |
| 55 | const { isCounterActive, animationDuration, finalNumber, numberPrefix, numberSuffix } = attributes; |
| 56 | |
| 57 | const durationInSeconds = animationDuration / 1000; |
| 58 | |
| 59 | useEffect( () => { |
| 60 | if ( isCounterActive && finalNumber ) { |
| 61 | const block = select( 'core/block-editor' ).getBlock( clientId ); |
| 62 | if ( ! block ) return; |
| 63 | |
| 64 | const formattedNumber = `${ numberPrefix }${ finalNumber }${ numberSuffix }`; |
| 65 | |
| 66 | if ( block.attributes.content !== formattedNumber ) { |
| 67 | dispatch( 'core/block-editor' ).updateBlockAttributes( clientId, { |
| 68 | content: formattedNumber, |
| 69 | } ); |
| 70 | } |
| 71 | } |
| 72 | }, [ isCounterActive, finalNumber, numberPrefix, numberSuffix, clientId ] ); |
| 73 | |
| 74 | return ( |
| 75 | <Fragment> |
| 76 | <BlockEdit { ...props } /> |
| 77 | <InspectorControls> |
| 78 | <PanelBody |
| 79 | title={ __( 'FrontBlocks - Counter Effect', 'frontblocks' ) } |
| 80 | initialOpen={ false } |
| 81 | > |
| 82 | <ToggleControl |
| 83 | label={ __( 'Activate Counter Effect', 'frontblocks' ) } |
| 84 | help={ isCounterActive ? |
| 85 | __( 'The number will animate on scroll.', 'frontblocks' ) : |
| 86 | __( 'Enable to activate counting animation.', 'frontblocks' ) |
| 87 | } |
| 88 | checked={ isCounterActive } |
| 89 | onChange={ ( val ) => setAttributes( { isCounterActive: val } ) } |
| 90 | /> |
| 91 | |
| 92 | { isCounterActive && ( |
| 93 | <> |
| 94 | <TextControl |
| 95 | label={ __( 'Final Number', 'frontblocks' ) } |
| 96 | value={ finalNumber } |
| 97 | onChange={ ( val ) => setAttributes( { finalNumber: val } ) } |
| 98 | help={ __( 'Number to count up to (e.g.: 100).', 'frontblocks' ) } |
| 99 | /> |
| 100 | |
| 101 | <TextControl |
| 102 | label={ __( 'Number Prefix', 'frontblocks' ) } |
| 103 | value={ numberPrefix } |
| 104 | onChange={ ( val ) => setAttributes( { numberPrefix: val } ) } |
| 105 | help={ __( 'Text before the number (e.g.: $, €).', 'frontblocks' ) } |
| 106 | /> |
| 107 | |
| 108 | <TextControl |
| 109 | label={ __( 'Number Suffix', 'frontblocks' ) } |
| 110 | value={ numberSuffix } |
| 111 | onChange={ ( val ) => setAttributes( { numberSuffix: val } ) } |
| 112 | help={ __( 'Text after the number (e.g.: %, +).', 'frontblocks' ) } |
| 113 | /> |
| 114 | |
| 115 | <TextControl |
| 116 | label={ __( 'Animation Duration (seconds)', 'frontblocks' ) } |
| 117 | value={ durationInSeconds } |
| 118 | onChange={ ( val ) => { |
| 119 | const seconds = parseFloat( val ); |
| 120 | const milliseconds = isNaN( seconds ) ? 0 : seconds * 1000; |
| 121 | setAttributes( { animationDuration: milliseconds } ); |
| 122 | } } |
| 123 | type="number" |
| 124 | step="0.1" |
| 125 | help={ __( 'Duration of the animation.', 'frontblocks' ) } |
| 126 | /> |
| 127 | </> |
| 128 | ) } |
| 129 | |
| 130 | <p style={ { marginTop: '10px', fontSize: '12px', color: '#777' } }> |
| 131 | <small>{ __( "Text must begin with a number (e.g., '123', '+500', '€100').", 'frontblocks' ) }</small> |
| 132 | </p> |
| 133 | </PanelBody> |
| 134 | </InspectorControls> |
| 135 | </Fragment> |
| 136 | ); |
| 137 | }; |
| 138 | }, 'withCounterControl' ); |
| 139 | |
| 140 | wp.hooks.addFilter( |
| 141 | 'editor.BlockEdit', |
| 142 | 'frontblocks/counter-control', |
| 143 | withCounterControl |
| 144 | ); |
| 145 |