# blockenberg/2.0.7/blocks/morphing-text/index.js

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

- Page: https://pluginprobe.com/plugins/blockenberg/2.0.7/code/blocks/morphing-text/index.js
- Raw: https://pluginprobe.com/plugins/blockenberg/2.0.7/raw/blocks/morphing-text/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/morphing-text/index.js#L10-L20`.

```javascript
( function () {
    var el = React.createElement;
    var __ = wp.i18n.__;
    var registerBlockType = wp.blocks.registerBlockType;
    var useBlockProps = wp.blockEditor.useBlockProps;
    var InspectorControls = wp.blockEditor.InspectorControls;
    var PanelBody = wp.components.PanelBody;
    var ToggleControl = wp.components.ToggleControl;
    var RangeControl = wp.components.RangeControl;
    var SelectControl = wp.components.SelectControl;
    var TextControl = wp.components.TextControl;
    var Button = wp.components.Button;
    var PanelColorSettings = wp.blockEditor.PanelColorSettings;

    var _tc, _tv;
    function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
    function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }

    var MORPH_MODES = [
        { value: 'blur',      label: 'Blur — letters blur in/out' },
        { value: 'crossfade', label: 'Crossfade — smooth opacity' },
        { value: 'slide-up',  label: 'Slide Up' },
        { value: 'slide-down',label: 'Slide Down' },
        { value: 'typewriter',label: 'Typewriter — char by char' }
    ];

    var TAGS = ['h1','h2','h3','h4','h5','h6','p','div'].map(function(t){ return { value: t, label: t.toUpperCase() }; });

    function MorphPreview(props) {
        var attr = props.attr;
        var words = attr.words && attr.words.length ? attr.words : ['build websites'];
        var _state = React.useState(0);
        var idx = _state[0]; var setIdx = _state[1];

        React.useEffect(function () {
            var t = setInterval(function () {
                setIdx(function (i) { return (i + 1) % words.length; });
            }, (attr.duration || 2500));
            return function () { clearInterval(t); };
        }, [words.length, attr.duration]);

        var grad = attr.useGradient
            ? 'linear-gradient(90deg,' + (attr.morphColor || '#7c3aed') + ',' + (attr.morphColor2 || '#ec4899') + ')'
            : null;

        var morphStyle = {
            display: 'inline',
            color: !attr.useGradient ? (attr.morphColor || '#7c3aed') : 'transparent',
            background: grad || 'none',
            backgroundClip: grad ? 'text' : undefined,
            WebkitBackgroundClip: grad ? 'text' : undefined,
            WebkitTextFillColor: grad ? 'transparent' : undefined,
            transition: 'all 0.4s ease',
            marginLeft: '0.3em'
        };

        return el('div', {
            className: 'bkbg-mt-wrap',
            style: {
                padding: (attr.paddingV || 32) + 'px ' + (attr.paddingH || 24) + 'px',
                backgroundColor: attr.showBg ? (attr.bgColor || '#fff') : 'transparent',
                borderRadius: (attr.borderRadius || 0) + 'px',
                textAlign: attr.textAlign || 'center'
            }
        },
            el(attr.tag || 'h2', {
                className: 'bkbg-mt-heading',
                style: {
                    margin: 0, padding: 0,
                    color: attr.staticColor || '#1e293b'
                }
            },
                attr.staticBefore && el('span', null, attr.staticBefore),
                el('span', { style: morphStyle }, words[idx]),
                attr.staticAfter && el('span', null, ' ' + attr.staticAfter),
                attr.cursor && el('span', { style: { borderRight: '3px solid currentColor', marginLeft: '2px', animation: 'bkbg-mt-blink 1s step-end infinite' } })
            )
        );
    }

    registerBlockType('blockenberg/morphing-text', {
        title: 'Morphing Text',
        icon: 'editor-textcolor',
        category: 'bkbg-effects',

        edit: function (props) {
            var attr = props.attributes;
            var setAttr = props.setAttributes;

            function updateWord(i, val) {
                var words = attr.words.slice();
                words[i] = val;
                setAttr({ words: words });
            }
            function addWord() { setAttr({ words: attr.words.concat(['new word']) }); }
            function removeWord(i) {
                var words = attr.words.slice();
                words.splice(i, 1);
                setAttr({ words: words });
            }

            return el(React.Fragment, null,
                el(InspectorControls, null,
                    el(PanelBody, { title: 'Words', initialOpen: true },
                        el('p', { style: { fontSize: 12, color: '#6b7280', margin: '0 0 8px' } }, 'The morphing text cycles through these words:'),
                        attr.words.map(function (w, i) {
                            return el('div', { key: i, style: { display: 'flex', gap: 6, marginBottom: 6 } },
                                el(TextControl, { __nextHasNoMarginBottom: true, value: w, onChange: function (v) { updateWord(i, v); } }),
                                el(Button, { variant: 'tertiary', isSmall: true, isDestructive: true, onClick: function () { removeWord(i); }, disabled: attr.words.length <= 1 }, '✕')
                            );
                        }),
                        el(Button, { variant: 'secondary', isSmall: true, onClick: addWord, style: { marginTop: 4 } }, '+ Add Word')
                    ),
                    el(PanelBody, { title: 'Static Text', initialOpen: false },
                        el(TextControl, { __nextHasNoMarginBottom: true, label: 'Text Before', value: attr.staticBefore, onChange: function (v) { setAttr({ staticBefore: v }); } }),
                        el(TextControl, { __nextHasNoMarginBottom: true, label: 'Text After', value: attr.staticAfter, onChange: function (v) { setAttr({ staticAfter: v }); } })
                    ),
                    el(PanelBody, { title: 'Animation', initialOpen: true },
                        el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Morph Mode', value: attr.morphMode, options: MORPH_MODES, onChange: function (v) { setAttr({ morphMode: v }); } }),
                        el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Word Duration (ms)', value: attr.duration, min: 500, max: 8000, step: 100, onChange: function (v) { setAttr({ duration: v }); } }),
                        el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Pause Between (ms)', value: attr.pauseDuration, min: 0, max: 5000, step: 100, onChange: function (v) { setAttr({ pauseDuration: v }); } }),
                        el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Loop', checked: attr.loop, onChange: function (v) { setAttr({ loop: v }); } }),
                        el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Blinking Cursor', checked: attr.cursor, onChange: function (v) { setAttr({ cursor: v }); } })
                    ),
                    el(PanelBody, { title: 'Typography', initialOpen: false },
                        el(SelectControl, { __nextHasNoMarginBottom: true, label: 'HTML Tag', value: attr.tag, options: TAGS, onChange: function (v) { setAttr({ tag: v }); } }),
                        el(getTypoControl(), {
                            label: __('Heading', 'blockenberg'),
                            value: attr.headingTypo,
                            onChange: function (v) { setAttr({ headingTypo: v }); }
                        }),
                        el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Text Align', value: attr.textAlign, options: [{value:'left',label:'Left'},{value:'center',label:'Center'},{value:'right',label:'Right'}], onChange: function (v) { setAttr({ textAlign: v }); } })
                    ),
                    el(PanelBody, { title: 'Background', initialOpen: false },
                        el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show Background', checked: attr.showBg, onChange: function (v) { setAttr({ showBg: v }); } }),
                        el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Padding Vertical (px)', value: attr.paddingV, min: 0, max: 120, onChange: function (v) { setAttr({ paddingV: v }); } }),
                        el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Padding Horizontal (px)', value: attr.paddingH, min: 0, max: 120, onChange: function (v) { setAttr({ paddingH: v }); } }),
                        el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Border Radius (px)', value: attr.borderRadius, min: 0, max: 60, onChange: function (v) { setAttr({ borderRadius: v }); } })
                    ),
                    el(PanelColorSettings, {
                        title: 'Colors',
                        initialOpen: false,
                        colorSettings: [
                            { value: attr.staticColor, onChange: function (v) { setAttr({ staticColor: v || '#1e293b' }); }, label: 'Static Text Color' },
                            { value: attr.morphColor,  onChange: function (v) { setAttr({ morphColor:  v || '#7c3aed' }); }, label: 'Morph Color 1' },
                            { value: attr.morphColor2, onChange: function (v) { setAttr({ morphColor2: v || '#ec4899' }); }, label: 'Morph Color 2 (gradient)' },
                            attr.showBg && { value: attr.bgColor, onChange: function (v) { setAttr({ bgColor: v || '#fff' }); }, label: 'Background' }
                        ].filter(Boolean)
                    }),
                    el(PanelBody, { title: 'Morph Color Style', initialOpen: false },
                        el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Use Gradient on Morphing Word', checked: attr.useGradient, onChange: function (v) { setAttr({ useGradient: v }); } })
                    )
                ),

                el('div', useBlockProps((function () {
                    var _tvf = getTypoCssVars();
                    var s = {};
                    Object.assign(s, _tvf(attr.headingTypo, '--bkbg-mrt-hd-'));
                    return { style: s };
                })()),
                    el(MorphPreview, { attr: attr })
                )
            );
        },

        deprecated: [{
            save: function (props) {
                return el('div', useBlockProps.save(),
                    el('div', { className: 'bkbg-mt-app', 'data-opts': JSON.stringify(props.attributes) })
                );
            }
        }],

        save: function (props) {
            var a = props.attributes;
            var blockProps = useBlockProps.save((function () {
                var _tvf = getTypoCssVars();
                var s = {};
                Object.assign(s, _tvf(a.headingTypo, '--bkbg-mrt-hd-'));
                return { style: s };
            })());
            return el('div', blockProps,
                el('div', { className: 'bkbg-mt-app', 'data-opts': JSON.stringify(a) })
            );
        }
    });
}() );

```
