# blockenberg/2.0.7/blocks/google-map/index.js

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

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

```javascript
( function () {
    var el                = wp.element.createElement;
    var Fragment          = wp.element.Fragment;
    var useState          = wp.element.useState;
    var __                = wp.i18n.__;
    var registerBlockType = wp.blocks.registerBlockType;
    var InspectorControls = wp.blockEditor.InspectorControls;
    var useBlockProps     = wp.blockEditor.useBlockProps;
    var RichText          = wp.blockEditor.RichText;
    var PanelBody         = wp.components.PanelBody;
    var ColorPicker       = wp.components.ColorPicker;
    var Popover           = wp.components.Popover;
    var Button            = wp.components.Button;
    var ToggleControl     = wp.components.ToggleControl;
    var RangeControl      = wp.components.RangeControl;
    var SelectControl     = wp.components.SelectControl;
    var TextControl       = wp.components.TextControl;
    var TextareaControl   = wp.components.TextareaControl;
    var Notice            = wp.components.Notice;

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

    // ── Color swatch control (same pattern as flip-card / blockquote) ───────────
    function makeColorControl(openKey, setOpenKey) {
        return function renderColorControl(key, label, value, onChange) {
            var isOpen = openKey === key;
            return el('div', {
                key: key,
                style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 0', gap: '8px' }
            },
                el('span', { style: { fontSize: '12px', color: '#1e1e1e', flex: 1, lineHeight: 1.4 } }, label),
                el('div', { style: { position: 'relative', flexShrink: 0 } },
                    el('button', {
                        type: 'button',
                        title: value || 'none',
                        onClick: function () { setOpenKey(isOpen ? null : key); },
                        style: {
                            width: '28px', height: '28px', borderRadius: '4px',
                            border: isOpen ? '2px solid #007cba' : '2px solid #ddd',
                            cursor: 'pointer', padding: 0, display: 'block',
                            background: value || '#ffffff', flexShrink: 0
                        }
                    }),
                    isOpen && el(Popover, { position: 'bottom left', onClose: function () { setOpenKey(null); } },
                        el('div', { style: { padding: '8px' }, onMouseDown: function (e) { e.stopPropagation(); } },
                            el('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '6px' } },
                                el('strong', { style: { fontSize: '12px' } }, label),
                                el(Button, { icon: 'no-alt', isSmall: true, onClick: function () { setOpenKey(null); } })
                            ),
                            el(ColorPicker, { color: value, enableAlpha: true, onChange: onChange })
                        )
                    )
                )
            );
        };
    }

    // ── Section sub-header ───────────────────────────────────────────────────────
    function sectionLabel(text) {
        return el('p', {
            style: { margin: '8px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', color: '#888', letterSpacing: '.5px' }
        }, text);
    }

    // ── Build Google Maps embed URL ─────────────────────────────────────────────
    // With API key: uses Embed API v1 (full zoom + maptype support)
    // Without API key: uses legacy iframe embed (limited but no key needed)
    function buildEmbedUrl(a) {
        var q = encodeURIComponent(a.address || 'New York');
        if (a.apiKey) {
            return 'https://www.google.com/maps/embed/v1/place'
                + '?key=' + encodeURIComponent(a.apiKey)
                + '&q=' + q
                + '&zoom=' + a.zoom
                + '&maptype=' + a.mapType
                + '&language=en';
        }
        // Fallback: legacy Maps embed (zoom and type work with some limitations)
        var typeMap = { roadmap: 'm', satellite: 'k', terrain: 'p', hybrid: 'h' };
        return 'https://maps.google.com/maps'
            + '?q=' + q
            + '&z=' + a.zoom
            + '&t=' + (typeMap[a.mapType] || 'm')
            + '&output=embed'
            + '&hl=en';
    }

    // ── Build box-shadow css value ───────────────────────────────────────────────
    function buildShadow(a) {
        if (!a.showShadow) return 'none';
        return a.shadowH + 'px ' + a.shadowV + 'px ' + a.shadowBlur + 'px ' + a.shadowSpread + 'px ' + a.shadowColor;
    }

    // ── Build wrapper inline style ───────────────────────────────────────────────
    function buildWrapStyle(a) {
        return {
            height: a.mapHeight + 'px',
            borderRadius: a.borderRadius + 'px',
            overflow: 'hidden',
            border: a.showBorder ? (a.borderWidth + 'px ' + a.borderStyle + ' ' + a.borderColor) : 'none',
            boxShadow: buildShadow(a),
            maxWidth: a.maxWidth > 0 ? a.maxWidth + 'px' : '100%',
            margin: '0 auto'
        };
    }

    // ────────────────────────────────────────────────────────────────────────────
    registerBlockType('blockenberg/google-map', {
        title: __('Google Map', 'blockenberg'),
        icon: 'location-alt',
        category: 'bkbg-business',

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

            // Color picker popover state
            var openColorKeyState = useState(null);
            var openColorKey      = openColorKeyState[0];
            var setOpenColorKey   = openColorKeyState[1];
            var renderColorControl = makeColorControl(openColorKey, setOpenColorKey);

            // ── Options ───────────────────────────────────────────────────────
            var mapTypeOptions = [
                { label: __('Roadmap (default)', 'blockenberg'), value: 'roadmap' },
                { label: __('Satellite', 'blockenberg'),          value: 'satellite' },
                { label: __('Hybrid (satellite + labels)', 'blockenberg'), value: 'hybrid' },
                { label: __('Terrain', 'blockenberg'),            value: 'terrain' }
            ];
            var borderStyleOptions = [
                { label: __('Solid',  'blockenberg'), value: 'solid'  },
                { label: __('Dashed', 'blockenberg'), value: 'dashed' },
                { label: __('Dotted', 'blockenberg'), value: 'dotted' }
            ];
            var textAlignOptions = [
                { label: __('Left',   'blockenberg'), value: 'left'   },
                { label: __('Center', 'blockenberg'), value: 'center' },
                { label: __('Right',  'blockenberg'), value: 'right'  }
            ];
            var fontWeightOptions = [
                { label: '300 — Light',      value: 300 },
                { label: '400 — Regular',    value: 400 },
                { label: '500 — Medium',     value: 500 },
                { label: '600 — Semi Bold',  value: 600 },
                { label: '700 — Bold',       value: 700 }
            ];

            var embedUrl  = buildEmbedUrl(a);
            var wrapStyle = buildWrapStyle(a);

            // ── Inspector ─────────────────────────────────────────────────────
            var inspector = el(InspectorControls, {},

                // ── Map Settings ──────────────────────────────────────────────
                el(PanelBody, { title: __('Map Settings', 'blockenberg'), initialOpen: true },
                    el(TextControl, {
                        label:    __('Address or Place Name', 'blockenberg'),
                        help:     __('Any address, city, landmark, or coordinates.', 'blockenberg'),
                        value:    a.address,
                        onChange: function (v) { setAttributes({ address: v }); }
                    }),
                    el(RangeControl, {
                        label:    __('Zoom Level', 'blockenberg'),
                        help:     __('1 = world, 14 = street, 20 = building', 'blockenberg'),
                        value:    a.zoom, min: 1, max: 21,
                        onChange: function (v) { setAttributes({ zoom: v }); }
                    }),
                    el(SelectControl, {
                        label:    __('Map Type', 'blockenberg'),
                        value:    a.mapType,
                        options:  mapTypeOptions,
                        onChange: function (v) { setAttributes({ mapType: v }); }
                    }),
                    el('hr', {}),
                    el(ToggleControl, {
                        label:    __('Allow fullscreen', 'blockenberg'),
                        checked:  a.allowFullscreen,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ allowFullscreen: v }); }
                    }),
                    el(ToggleControl, {
                        label:    __('Lazy-load iframe', 'blockenberg'),
                        help:     __('Defers loading until the map is near the viewport.', 'blockenberg'),
                        checked:  a.lazyLoad,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ lazyLoad: v }); }
                    }),
                    el('hr', {}),
                    el(TextControl, {
                        label:    __('Google Maps API Key (optional)', 'blockenberg'),
                        help:     __('Required for satellite/terrain/hybrid types and precise zoom. Leave empty for basic embed.', 'blockenberg'),
                        value:    a.apiKey,
                        type:     'password',
                        onChange: function (v) { setAttributes({ apiKey: v }); }
                    })
                ),

                // ── Dimensions ────────────────────────────────────────────────
                el(PanelBody, { title: __('Dimensions', 'blockenberg'), initialOpen: false },
                    el(RangeControl, {
                        label:    __('Map Height (px)', 'blockenberg'),
                        value:    a.mapHeight, min: 150, max: 900,
                        onChange: function (v) { setAttributes({ mapHeight: v }); }
                    }),
                    el(RangeControl, {
                        label:    __('Max Width (px, 0 = full)', 'blockenberg'),
                        help:     __('Set a max-width and the map will be centered.', 'blockenberg'),
                        value:    a.maxWidth, min: 0, max: 1600, step: 10,
                        onChange: function (v) { setAttributes({ maxWidth: v }); }
                    }),
                    el(RangeControl, {
                        label:    __('Corner Radius (px)', 'blockenberg'),
                        value:    a.borderRadius, min: 0, max: 48,
                        onChange: function (v) { setAttributes({ borderRadius: v }); }
                    })
                ),

                // ── Border & Shadow ───────────────────────────────────────────
                el(PanelBody, { title: __('Border & Shadow', 'blockenberg'), initialOpen: false },
                    el(ToggleControl, {
                        label:    __('Show Border', 'blockenberg'),
                        checked:  a.showBorder,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ showBorder: v }); }
                    }),
                    a.showBorder && el(Fragment, {},
                        renderColorControl('borderColor', __('Border Color', 'blockenberg'), a.borderColor, function (c) { setAttributes({ borderColor: c }); }),
                        el(RangeControl, {
                            label:    __('Border Width (px)', 'blockenberg'),
                            value:    a.borderWidth, min: 1, max: 12,
                            onChange: function (v) { setAttributes({ borderWidth: v }); }
                        }),
                        el(SelectControl, {
                            label:    __('Border Style', 'blockenberg'),
                            value:    a.borderStyle,
                            options:  borderStyleOptions,
                            onChange: function (v) { setAttributes({ borderStyle: v }); }
                        })
                    ),
                    el('hr', {}),
                    el(ToggleControl, {
                        label:    __('Show Shadow', 'blockenberg'),
                        checked:  a.showShadow,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ showShadow: v }); }
                    }),
                    a.showShadow && el(Fragment, {},
                        renderColorControl('shadowColor', __('Shadow Color', 'blockenberg'), a.shadowColor, function (c) { setAttributes({ shadowColor: c }); }),
                        el(RangeControl, { label: __('Horizontal (px)', 'blockenberg'), value: a.shadowH,      min: -60, max: 60, onChange: function (v) { setAttributes({ shadowH:      v }); } }),
                        el(RangeControl, { label: __('Vertical (px)',   'blockenberg'), value: a.shadowV,      min: -60, max: 60, onChange: function (v) { setAttributes({ shadowV:      v }); } }),
                        el(RangeControl, { label: __('Blur (px)',       'blockenberg'), value: a.shadowBlur,   min: 0,   max: 80, onChange: function (v) { setAttributes({ shadowBlur:   v }); } }),
                        el(RangeControl, { label: __('Spread (px)',     'blockenberg'), value: a.shadowSpread, min: -20, max: 40, onChange: function (v) { setAttributes({ shadowSpread: v }); } })
                    )
                ),

                // ── Caption ───────────────────────────────────────────────────
                el(PanelBody, { title: __('Caption', 'blockenberg'), initialOpen: false },
                    el(ToggleControl, {
                        label:    __('Show Caption', 'blockenberg'),
                        checked:  a.showCaption,
                        __nextHasNoMarginBottom: true,
                        onChange: function (v) { setAttributes({ showCaption: v }); }
                    }),
                    ),
                el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
                    a.showCaption && el(Fragment, {},
                                            _tc()({ label: __('Caption', 'blockenberg'), value: a.typoCaption, onChange: function (v) { setAttributes({ typoCaption: v }); } }),
                                            renderColorControl('captionColor', __('Text Color', 'blockenberg'), a.captionColor, function (c) { setAttributes({ captionColor: c }); }),
                                            el(SelectControl, {
                                                label:    __('Alignment', 'blockenberg'),
                                                value:    a.captionAlign,
                                                options:  textAlignOptions,
                                                onChange: function (v) { setAttributes({ captionAlign: v }); }
                                            }),
                                            el(RangeControl, {
                                                label:    __('Spacing Above (px)', 'blockenberg'),
                                                value:    a.captionSpacing, min: 0, max: 40,
                                                onChange: function (v) { setAttributes({ captionSpacing: v }); }
                                            })
                                        )
                )
            );

            // ── Editor preview ────────────────────────────────────────────────
            return el(Fragment, {},
                inspector,
                el('div', useBlockProps({ className: 'bkbg-gm-outer', style: Object.assign({}, _tv()(a.typoCaption, '--bkbg-gm-cap-')) }),
                    el('div', { className: 'bkbg-gm-wrap', style: wrapStyle },
                        el('iframe', {
                            src:             embedUrl,
                            width:           '100%',
                            height:          '100%',
                            style:           { border: 'none', display: 'block' },
                            allowFullScreen: a.allowFullscreen,
                            loading:         a.lazyLoad ? 'lazy' : 'eager',
                            referrerPolicy:  'no-referrer-when-downgrade',
                            title:           a.address || 'Google Map'
                        })
                    ),
                    a.showCaption && el(RichText, {
                        tagName:        'p',
                        className:      'bkbg-gm-caption',
                        value:          a.caption,
                        placeholder:    __('Caption text…', 'blockenberg'),
                        onChange:       function (v) { setAttributes({ caption: v }); },
                        allowedFormats: ['core/bold', 'core/italic', 'core/link'],
                        style: {
                            color:      a.captionColor,
                            textAlign:  a.captionAlign,
                            marginTop:  a.captionSpacing + 'px',
                            marginBottom: 0,
                            padding: 0
                        }
                    })
                )
            );
        },

        // ── Save ────────────────────────────────────────────────────────────────
        save: function (props) {
            var a             = props.attributes;
            var RichTextContent = wp.blockEditor.RichText.Content;
            var embedUrl      = buildEmbedUrl(a);
            var wrapStyle     = buildWrapStyle(a);

            return el('div', wp.blockEditor.useBlockProps.save({ className: 'bkbg-gm-outer', style: Object.assign({}, _tv()(a.typoCaption, '--bkbg-gm-cap-')) }),
                el('div', { className: 'bkbg-gm-wrap', style: wrapStyle },
                    el('iframe', {
                        src:             embedUrl,
                        width:           '100%',
                        height:          '100%',
                        style:           { border: 'none', display: 'block' },
                        allowFullScreen: a.allowFullscreen ? true : undefined,
                        loading:         a.lazyLoad ? 'lazy' : 'eager',
                        referrerPolicy:  'no-referrer-when-downgrade',
                        title:           a.address || 'Google Map'
                    })
                ),
                a.showCaption && el(RichTextContent, {
                    tagName:   'p',
                    className: 'bkbg-gm-caption',
                    value:     a.caption,
                    style: {
                        color:        a.captionColor,
                        textAlign:    a.captionAlign,
                        marginTop:    a.captionSpacing + 'px',
                        marginBottom: 0,
                        padding: 0
                    }
                })
            );
        }
    });
}() );

```
