# blockenberg/2.0.7/blocks/gradient-blob/index.js

Blockenberg — 600+ Advanced Gutenberg Blocks &amp; AI Agent for WordPress Block Editor, version 2.0.7. 281 lines.

- Page: https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/gradient-blob/index.js
- Raw: https://pluginprobe.com/plugins/blockenberg/2.0.7/raw/blocks/gradient-blob/index.js
- Modified: 2026-03-06T12:32:40+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/gradient-blob/index.js#L10-L20`.

```javascript
( function () {
    var el                = wp.element.createElement;
    var Fragment          = wp.element.Fragment;
    var registerBlockType = wp.blocks.registerBlockType;
    var __                = wp.i18n.__;
    var InspectorControls = wp.blockEditor.InspectorControls;
    var PanelColorSettings = wp.blockEditor.PanelColorSettings;
    var InnerBlocks       = wp.blockEditor.InnerBlocks;
    var useBlockProps     = wp.blockEditor.useBlockProps;
    var useInnerBlocksProps = wp.blockEditor.useInnerBlocksProps;
    var PanelBody         = wp.components.PanelBody;
    var ToggleControl     = wp.components.ToggleControl;
    var RangeControl      = wp.components.RangeControl;

    var TEMPLATE = [
        ['core/heading',   { level: 2, placeholder: __('Section heading…', 'blockenberg'), textAlign: 'center' }],
        ['core/paragraph', { placeholder: __('Add your content here…', 'blockenberg'),     align: 'center' }],
        ['core/buttons',   { layout: { type: 'flex', justifyContent: 'center' } }, [
            ['core/button', { text: __('Get started', 'blockenberg') }],
        ]],
    ];

    // CSS for animated blob (editor preview)
    var BLOB_ANIM = [
        { top: '10%', left: '15%',  animDelay: '0s' },
        { top: '60%', left: '65%',  animDelay: '-4s' },
        { top: '35%', left: '50%',  animDelay: '-7s' },
        { top: '75%', left: '10%',  animDelay: '-2s' },
        { top: '20%', left: '75%',  animDelay: '-9s' },
    ];

    function buildWrapStyle(a) {
        return {
            position:      'relative',
            overflow:      'hidden',
            minHeight:     a.minHeight + 'px',
            paddingTop:    a.paddingTop + 'px',
            paddingBottom: a.paddingBottom + 'px',
            background:    a.bgColor,
            color:         a.textColor || undefined,
        };
    }

    function buildInnerStyle(a) {
        return {
            position:  'relative',
            zIndex:    1,
            maxWidth:  a.contentMaxWidth + 'px',
            margin:    a.centerContent ? '0 auto' : undefined,
        };
    }

    function buildBlobStyle(a, idx) {
        var info = BLOB_ANIM[idx % BLOB_ANIM.length];
        var colors = [a.color1, a.color2, a.color3];
        var color = colors[idx % colors.length];
        var size = a.blobSize;
        return {
            position:          'absolute',
            top:               info.top,
            left:              info.left,
            width:             size + '%',
            height:            size + '%',
            background:        color,
            borderRadius:      '60% 40% 30% 70% / 60% 30% 70% 40%',
            opacity:           (a.blobOpacity / 100),
            filter:            'blur(' + a.blobBlur + 'px)',
            willChange:        'transform, border-radius',
            animationName:     'bkgb-morph',
            animationDuration: a.animSpeed + 's',
            animationDelay:    info.animDelay,
            animationTimingFunction: 'ease-in-out',
            animationIterationCount: 'infinite',
            animationPlayState: a.paused ? 'paused' : 'running',
            transformOrigin:   'center',
            pointerEvents:     'none',
        };
    }

    registerBlockType('blockenberg/gradient-blob', {
        title: __('Gradient Blob', 'blockenberg'),
        description: __('Section with animated CSS blobs as background.', 'blockenberg'),
        category: 'bkbg-effects',
        icon: 'art',

        edit: function (props) {
            var attributes   = props.attributes;
            var setAttributes = props.setAttributes;
            var numBlobs = Math.min(attributes.numBlobs || 3, 5);

            var wrapStyle = buildWrapStyle(attributes);
            var innerStyle = buildInnerStyle(attributes);

            var blockProps = useBlockProps({ style: wrapStyle, className: 'bkgb-section' });
            var innerBlocksProps = useInnerBlocksProps({ style: innerStyle, className: 'bkgb-inner' }, {
                template: TEMPLATE,
                templateLock: false,
            });

            return el(Fragment, null,
                el(InspectorControls, null,
                    /* ── Blobs ──────────────────────────────────────────────── */
                    el(PanelBody, { title: __('Blobs', 'blockenberg'), initialOpen: true },
                        el(RangeControl, {
                            label: __('Number of blobs', 'blockenberg'),
                            value: attributes.numBlobs,
                            min: 1, max: 5,
                            onChange: function (v) { setAttributes({ numBlobs: v }); },
                        }),
                        el(RangeControl, {
                            label: __('Blob size (%)', 'blockenberg'),
                            value: attributes.blobSize,
                            min: 10, max: 120,
                            onChange: function (v) { setAttributes({ blobSize: v }); },
                        }),
                        el(RangeControl, {
                            label: __('Opacity (%)', 'blockenberg'),
                            value: attributes.blobOpacity,
                            min: 5, max: 100,
                            onChange: function (v) { setAttributes({ blobOpacity: v }); },
                        }),
                        el(RangeControl, {
                            label: __('Blur (px)', 'blockenberg'),
                            value: attributes.blobBlur,
                            min: 0, max: 200,
                            onChange: function (v) { setAttributes({ blobBlur: v }); },
                        }),
                        el(RangeControl, {
                            label: __('Animation speed (s)', 'blockenberg'),
                            value: attributes.animSpeed,
                            min: 3, max: 40,
                            onChange: function (v) { setAttributes({ animSpeed: v }); },
                        }),
                        el(ToggleControl, {
                            label: __('Pause animation', 'blockenberg'),
                            checked: attributes.paused,
                            onChange: function (v) { setAttributes({ paused: v }); },
                            __nextHasNoMarginBottom: true,
                        })
                    ),
                    /* ── Layout ─────────────────────────────────────────────── */
                    el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
                        el(RangeControl, {
                            label: __('Min height (px)', 'blockenberg'),
                            value: attributes.minHeight,
                            min: 100, max: 1200,
                            onChange: function (v) { setAttributes({ minHeight: v }); },
                        }),
                        el(RangeControl, {
                            label: __('Padding top (px)', 'blockenberg'),
                            value: attributes.paddingTop,
                            min: 0, max: 200,
                            onChange: function (v) { setAttributes({ paddingTop: v }); },
                        }),
                        el(RangeControl, {
                            label: __('Padding bottom (px)', 'blockenberg'),
                            value: attributes.paddingBottom,
                            min: 0, max: 200,
                            onChange: function (v) { setAttributes({ paddingBottom: v }); },
                        }),
                        el(RangeControl, {
                            label: __('Content max width (px)', 'blockenberg'),
                            value: attributes.contentMaxWidth,
                            min: 200, max: 1400,
                            onChange: function (v) { setAttributes({ contentMaxWidth: v }); },
                        }),
                        el(ToggleControl, {
                            label: __('Center content', 'blockenberg'),
                            checked: attributes.centerContent,
                            onChange: function (v) { setAttributes({ centerContent: v }); },
                            __nextHasNoMarginBottom: true,
                        })
                    ),
                    /* ── Colors ─────────────────────────────────────────────── */
                    el(PanelColorSettings, {
                        title: __('Colors', 'blockenberg'),
                        initialOpen: false,
                        colorSettings: [
                            {
                                value: attributes.color1,
                                onChange: function (v) { setAttributes({ color1: v || '#c084fc' }); },
                                label: __('Blob color 1', 'blockenberg'),
                            },
                            {
                                value: attributes.color2,
                                onChange: function (v) { setAttributes({ color2: v || '#818cf8' }); },
                                label: __('Blob color 2', 'blockenberg'),
                            },
                            {
                                value: attributes.color3,
                                onChange: function (v) { setAttributes({ color3: v || '#f0abfc' }); },
                                label: __('Blob color 3', 'blockenberg'),
                            },
                            {
                                value: attributes.bgColor,
                                onChange: function (v) { setAttributes({ bgColor: v || '#faf5ff' }); },
                                label: __('Background color', 'blockenberg'),
                            },
                            {
                                value: attributes.textColor,
                                onChange: function (v) { setAttributes({ textColor: v || '' }); },
                                label: __('Text color', 'blockenberg'),
                            },
                        ],
                    })
                ),
                el('section', blockProps,
                    /* Blob layers */
                    Array.from({ length: numBlobs }, function (_, i) {
                        return el('div', {
                            key: i,
                            'aria-hidden': 'true',
                            className: 'bkgb-blob bkgb-blob-' + (i + 1),
                            style: buildBlobStyle(attributes, i),
                        });
                    }),
                    /* InnerBlocks content */
                    el('div', innerBlocksProps)
                )
            );
        },

        save: function (props) {
            var a = props.attributes;
            var numBlobs = Math.min(a.numBlobs || 3, 5);
            var colors = [a.color1, a.color2, a.color3];
            var blobPositions = [
                { top: '10%', left: '15%' },
                { top: '60%', left: '65%' },
                { top: '35%', left: '50%' },
                { top: '75%', left: '10%' },
                { top: '20%', left: '75%' },
            ];
            var blobDelays = ['0s', '-4s', '-7s', '-2s', '-9s'];

            return el('section', {
                className: 'bkgb-section',
                'data-speed': a.animSpeed,
                'data-paused': a.paused ? 'true' : 'false',
                style: {
                    position:      'relative',
                    overflow:      'hidden',
                    minHeight:     a.minHeight + 'px',
                    paddingTop:    a.paddingTop + 'px',
                    paddingBottom: a.paddingBottom + 'px',
                    background:    a.bgColor,
                    color:         a.textColor || undefined,
                    '--bkgb-speed': a.animSpeed + 's',
                    '--bkgb-blur':  a.blobBlur + 'px',
                    '--bkgb-opacity': a.blobOpacity / 100,
                    '--bkgb-size':  a.blobSize + '%',
                },
            },
                Array.from({ length: numBlobs }, function (_, i) {
                    var pos = blobPositions[i % blobPositions.length];
                    return el('div', {
                        key: i,
                        'aria-hidden': 'true',
                        className: 'bkgb-blob bkgb-blob-' + (i + 1),
                        style: {
                            '--bkgb-c': colors[i % colors.length],
                            '--bkgb-delay': blobDelays[i % blobDelays.length],
                            top:   pos.top,
                            left:  pos.left,
                        },
                    });
                }),
                el('div', {
                    className: 'bkgb-inner',
                    style: {
                        position:  'relative',
                        zIndex:    1,
                        maxWidth:  a.contentMaxWidth + 'px',
                        margin:    a.centerContent ? '0 auto' : undefined,
                    },
                }, el(InnerBlocks.Content))
            );
        },
    });
}() );

```
