function pgPostSelectorControl(prop, setAttributes, props, title, help, post_type) {
    const {__} = wp.i18n;
    const el = wp.element.createElement;
    const {Button, Popover, BaseControl, Panel, PanelBody, PanelRow} = wp.components;
    const {useState} = wp.element;
    const LinkControl = wp.blockEditor.LinkControl || wp.blockEditor.__experimentalLinkControl;

    const postId = prop + 'Id';

    title = title || __('Select ' + prop);

    let [isVisible, setIsVisible] = useState(false);
    const toggleVisible = () => {
        setIsVisible((state) => !state);
    };

    const findItemById = function (id) {
        if (props.attributes[prop]) {
            for (let i = 0; i < props.attributes[prop].length; i++) {
                if (props.attributes[prop][i].id === id) return i;
            }
        }
        return -1;
    }

    const moveItem = function (id, add) {
        const idx = findItemById(id);
        if (idx >= 0) {
            if (idx + add >= 0 && (idx + add) < props.attributes[prop].length) {
                const list = props.attributes[prop].slice(0);
                const mi = list[idx];
                list.splice(idx, 1);
                list.splice(idx + add, 0, mi)
                const d = {}
                d[prop] = list;
                setAttributes(d);
            }
        }
    }

    const renderItems = function () {
        var r = [];
        if (props.attributes[prop]) {
            let i = 0;
            props.attributes[prop].forEach(function (item) {
                r.push(el('div', {
                    className: 'pg-posts-control-list-item',
                }, [
                    props[prop + '_' + item.id] ? props[prop + '_' + item.id].title.raw : 'Loading...',
                    el('a', {
                        href: '#',
                        className: 'pg-posts-control-list-item-remove',
                        onClick: function () {
                            const idx = findItemById(item.id);
                            if (idx >= 0) {
                                const list = props.attributes[prop].slice(0);
                                list.splice(idx, 1);
                                const d = {}
                                d[prop] = list;
                                setAttributes(d);
                            }
                        }
                    }, '×'),
                    el('a', {
                        href: '#',
                        className: 'pg-posts-control-list-item-move up dashicons dashicons-arrow-up-alt2',
                        onClick: function () {
                            moveItem(item.id, -1);
                        }
                    }, ''),
                    el('a', {
                        href: '#',
                        className: 'pg-posts-control-list-item-move down dashicons dashicons-arrow-down-alt2',
                        onClick: function () {
                            moveItem(item.id, 1);
                        }
                    }, '')
                ]))
                i++;
            })
        }
        return r;
    }

    return el(Panel, {}, el(PanelBody, {
        title: __(title)
    }, [
        el(BaseControl, {
            help: help && __(help)
        }, [
            el(PanelRow, {},
                el('div', {
                    className: 'pg-posts-control-list'
                }, [
                    props.attributes[prop].length === 0 && el('div', {
                        className: 'pg-posts-control-list-item-empty'
                    }, [__('No posts selected')]),
                    props.attributes[prop].length > 0 && renderItems()
                ])
            ),
            el(PanelRow, {}, [
                el(Button, {
                    onClick: toggleVisible,
                    isSecondary: true
                }, [
                    __('Select a ' + post_type),
                ])
            ])
        ]),
        isVisible && el(Popover, {
            className: 'pg-control-popover'
        }, [
            el('a', {
                href: '#',
                tabIndex: '-1',
                className: 'pg-control-close-popup',
                onClick: function () {
                    setIsVisible(false);
                },
            }, [
                '×'
            ]),
            el(LinkControl, {
                onChange: function (val, p) {
                    if (findItemById(val.id) < 0) {
                        var d = {};
                        d[prop] = props.attributes[prop].slice(0);
                        d[prop].push({id: val.id});
                        setAttributes(d);
                    }
                    setIsVisible(false);
                },
                noDirectEntry: true,
                searchInputPlaceholder: __('Select a post'),
                showInitialSuggestions: true,
                settings: [],
                hasRichPreviews: true,
                suggestionsQuery: post_type ? {
                    type: 'post',
                    subtype: post_type,
                } : {}
            }),
        ])
    ]))
}

function pgMediaImageControl(prop, setAttributes, props, image_size, inline_svg, title, help) {
    const propMedia = prop;

    const {__} = wp.i18n;
    const el = window.wp.element.createElement;
    const {
        BaseControl,
        Button,
        ResponsiveWrapper,
        Panel,
        PanelBody,
        PanelRow,
        TextareaControl,
        Popover
    } = wp.components;
    const {MediaUploadCheck, MediaUpload} = wp.blockEditor;
    const {RawHTML, useState} = wp.element;
    const ResolutionTool = wp.blockEditor?.privateApis?.ResolutionTool;
    const ImageSizeControl = ResolutionTool ? null : (wp.blockEditor.ImageSizeControl || wp.blockEditor.__experimentalImageSizeControl);

    image_size = image_size || 'full';

    let [isEditSVGVisible, setIsEditSVGVisible] = useState({
        visible: false,
        value: ''
    });

    function onSelectMedia(media) {
        var d = {}
        d[prop] = {
            id: media.id,
            url: media?.sizes[image_size]?.url || media.url,
            size: image_size,
            svg: '',
            alt: media.alt || ''
        }
        setAttributes(d);
    }

    function setSVG(svg) {
        var d = {}
        d[prop] = {
            id: 0,
            url: '',
            size: '',
            svg: inline_svg ? svg : '',
            alt: ''
        }
        setAttributes(d);
    }

    function removeMedia() {
        var d = {}
        d[prop] = {
            id: 0,
            url: '',
            size: '',
            svg: '',
            alt: ''
        }
        setAttributes(d);
    }

    function selectMediaSize(url, size) {
        var d = {};
        d[prop] = {
            id: props[prop].id,
            url: url,
            size: size,
            svg: '',
            alt: props[prop].alt || ''
        }
        setAttributes(d);
    }

    function getId() {
        return props.attributes[prop].id || 0;
    }

    function getUrl() {
        return props.attributes[prop].url || '';
    }

    function getAlt() {
        return props.attributes[prop].alt || '';
    }

    function getSVG() {
        if (!inline_svg) return '';
        return props.attributes[prop].svg || '';
    }

    function getResolutionOptions() {
        var r = [];
        Object.keys(props[propMedia].media_details.sizes).forEach(function (k) {
            r.push({
                value: k,
                label: `${k} (${props[propMedia].media_details.sizes[k].width}x${props[propMedia].media_details.sizes[k].height})`
            })
        });
        return r;
    }

    return el(Panel, {}, el(PanelBody, {
        title: __(`${title || prop}`)
    }, [
        el(PanelRow, {}, [
            el(MediaUploadCheck, {}, [
                el(MediaUpload, {
                    onSelect: onSelectMedia,
                    value: getId(),
                    allowedTypes: ['image'],
                    render: (open) => el(Button, {
                        className: getUrl() === '' ? 'editor-post-featured-image__toggle' : 'editor-post-featured-image__preview',
                        style: {
                            maxHeight: '200px',
                            overflow: 'hidden'
                        },
                        onClick: open.open
                    }, [
                        (getUrl() === '' && getSVG() === '') && __('Select an image'),
                        !getSVG() && props[propMedia] && props[propMedia].source_url &&
                        el(ResponsiveWrapper, {
                                naturalWidth: props[propMedia].media_details.width,
                                naturalHeight: props[propMedia].media_details.height,
                                isInline: true
                            },
                            el('img', {
                                src: props[propMedia].source_url
                            })
                        ),
                        getId() === 0 && getUrl() && el('img', {
                            src: getUrl(),
                            style: {
                                width: '100%',
                                display: 'block',
                                objectFit: 'cover',
                                height: '100%',
                                objectPosition: 'center center'
                            }
                        }),
                        inline_svg && getSVG() && el('div', {
                            className: 'pg-control-svg-edit-preview'
                        }, el(RawHTML, {}, getSVG()))
                    ])

                }, []),
            ]),
        ]),

        inline_svg && !getUrl() && !getSVG() && el(PanelRow, {}, [
            el(Button, {
                onClick: function () {
                    setIsEditSVGVisible({visible: true, value: getSVG()});
                },
                style: {
                    marginRight: '4px',
                },
                isLink: true
            }, [
                __('Set inline SVG')
            ]),
        ]),

        (getUrl() || getSVG()) && el(PanelRow, {}, [
            el(MediaUploadCheck, {}, [
                el(MediaUpload, {
                    title: __('Replace image'),
                    onSelect: onSelectMedia,
                    value: getId(),
                    allowedTypes: ['image'],
                    render: (open) => el(Button, {
                        onClick: open.open,
                        isSecondary: true
                    }, [
                        __('Replace image'),
                    ])

                }, []),
            ]),
            inline_svg && el(Button, {
                onClick: function () {
                    setIsEditSVGVisible({visible: true, value: getSVG()});
                },
                style: {
                    marginRight: '6px',
                    marginLeft: '6px'
                },
                isSecondary: true
            }, [
                __('Edit SVG')
            ]),
            el(Button, {
                onClick: removeMedia,
                isLink: true,
                isDestructive: false
            }, [
                __('Remove image')
            ])
        ]),

        getId() !== 0 && props[propMedia] && pgImageSizeControl(prop, setAttributes, props, getResolutionOptions(), function (value) {
                selectMediaSize(props[propMedia].media_details.sizes[value].source_url, value);
            }),

        isEditSVGVisible.visible && el(Popover, {
            className: 'pg-control-svg-edit',
            style: {}
        }, [
            el(BaseControl, {}, [
                el(TextareaControl, {
                    value: getSVG(),
                    help: __('Paste or edit the SVG image code.'),
                    label: __('Edit inline SVG'),
                    className: 'pg-control-svg-edit-code',
                    onChange: function (val) {
                        setSVG(val);
                    },
                }),
            ]),
            el(Button, {
                onClick: function () {
                    setIsEditSVGVisible({...isEditSVGVisible, visible: false});
                },
                style: {
                    marginRight: '6px'
                },
                isSecondary: true
            }, [
                __('Close')
            ]),
            el(Button, {
                onClick: function () {
                    setSVG(isEditSVGVisible.value);
                    setIsEditSVGVisible({...isEditSVGVisible, visible: false});
                },
                isLink: true
            }, [
                __('Cancel')
            ]),
        ]),
        help && el(BaseControl, {
            help: __(help),
        }, [])
    ]))
}

function pgColorControl(prop, setAttributes, props, title, help) {
    const {__} = wp.i18n;
    const el = wp.element.createElement;
    const {Button, Popover, BaseControl, ColorPicker, PanelRow} = wp.components;
    const {useState} = wp.element;

    let [isVisible, setIsVisible] = useState(false);

    const toggleVisible = () => {
        setIsVisible((state) => !state);
    };

    return el(BaseControl, {
        help: help && __(help)
    }, [
        el(PanelRow, {}, [
            el(Button, {
                onClick: toggleVisible,
                isSecondary: true
            }, [
                el('span', {}, __(title || 'Select color')),
                el('span', {
                    style: {
                        backgroundColor: props.attributes[prop],
                        border: '1px solid rgba(0,0,0,0.15)',
                        width: '20px',
                        height: '20px',
                        borderRadius: '50%',
                        marginLeft: '8px'
                    }
                })
            ]),
            props.attributes[prop] !== '' && el(Button, {
                onClick: function () {
                    var d = {}
                    d[prop] = '';
                    setAttributes(d);
                },
                isLink: true,
                isDestructive: false
            }, [
                __('Clear')
            ]),
            isVisible && el(Popover, {
                className: 'pg-control-color-popover'
            }, [
                el('a', {
                    href: '#',
                    tabIndex: -1,
                    className: 'pg-control-close-popup',
                    onClick: function () {
                        setIsVisible(false);
                    },
                }, [
                    '×'
                ]),
                el(ColorPicker, {
                    color: props.attributes[prop],
                    label: __(prop),
                    onChangeComplete: function (value) {
                        var d = {}
                        d[prop] = value.color ? value.color.toRgbString() : ('rgba(' + value.rgb.r + ',' + value.rgb.g + ',' + value.rgb.b + ',' + value.rgb.a + ')');
                        setAttributes(d);
                    }
                }),
            ])
        ]),
    ])
}

function pgUrlControl(prop, setAttributes, props, title, help, post_type) {
    const {__} = wp.i18n;
    const el = wp.element.createElement;
    const {Button, Popover, BaseControl, Panel, PanelBody, PanelRow, SelectControl, Icon} = wp.components;
    const {useState} = wp.element;
    const LinkControl = wp.blockEditor.LinkControl || wp.blockEditor.__experimentalLinkControl;
    const {withSelect, useSelect} = wp.data;

    title = title || prop;

    let linkControlKey = 1;

    let [isVisible, setIsVisible] = useState(false);
    const toggleVisible = () => {
        setIsVisible((state) => !state);
    };

    const getPostTypeOptions = useSelect((select) => {
        const {getPostTypes} = select('core');

        const items = (getPostTypes() || []).filter(function (item) {
            return !item.slug.startsWith('wp_');
        });

        const options = items.map(function (item) {
            return {
                label: item.labels.name,
                value: item.slug,
            };
        });

        options.unshift({value: null, label: '-'});
        return options;
    });

    return el(BaseControl, {
        help: help && __(help),
        label: __(title || prop)
    }, [
        el(PanelRow, {}, [
            el(Button, {
                onClick: toggleVisible,
                isSecondary: true,
                style: {
                    flexGrow: 1,
                    marginRight: '8px'
                }
            }, [
                el(Icon, {icon: 'admin-links', style: {marginRight: '4px'}}),
                !props.attributes[prop].url && el('span', {}, __('Select link')),
                props.attributes[prop].url && el('span', {
                    style: {
                        maxWidth: '170px',
                        display: 'inline-block',
                        textOverflow: 'ellipsis',
                        overflow: 'hidden'
                    }
                }, props.attributes[prop].title || props.attributes[prop].url),
                props.attributes[prop].url && el(Button, {
                    onClick: function (e) {
                        e.preventDefault();
                        e.stopPropagation();

                        var d = {}
                        d[prop] = {
                            post_type: props.attributes[prop].post_type || null,
                            post_id: 0,
                            url: ''
                        };
                        setAttributes(d);
                    },
                    isLink: true,
                    isDestructive: false,
                    style: {
                        fontSize: '16px',
                        textDecoration: 'none',
                        marginLeft: 'auto'
                    }
                }, [
                    __('×')
                ]),
            ]),

        ]),
        isVisible && el(Popover, {}, [
            el('div', {
                style: {
                    margin: '0 16px 16px 16px'
                }
            }, [
                el('a', {
                    href: '#',
                    style: {
                        right: '-15px'
                    },
                    tabIndex: -1,
                    className: 'pg-control-close-popup',
                    onClick: function () {
                        setIsVisible(false);
                    },
                }, [
                    '×'
                ]),
                el(SelectControl, {
                    value: props.attributes[prop].post_type,
                    label: __('Post type'),
                    disabled: post_type !== null,
                    onChange: function (val) {
                        var d = {}
                        d[prop] = {
                            post_type: val === '-' ? null : val,
                            post_id: 0,
                            url: ''
                        };
                        linkControlKey++;
                        //setIsVisible(false);
                        setAttributes(d)
                    },
                    options: getPostTypeOptions
                }),
            ]),
            el(LinkControl, {
                key: props.attributes[prop].post_type || 'none',
                value: {
                    url: props.attributes[prop].url
                },
                onChange: function (val) {
                    var d = {};
                    d[prop] = {
                        post_type: props.attributes[prop].post_type,
                        post_id: val.id,
                        url: val.url,
                        title: val.title
                    };
                    if (val.url === props.attributes[prop].url && !val.id) {
                        d[prop].post_id = props.attributes[prop].post_id;
                        d[prop].title = props.attributes[prop].title;
                    }
                    setIsVisible(false);
                    setAttributes(d)
                },
                noDirectEntry: false,
                searchInputPlaceholder: __('Select a post'),
                showInitialSuggestions: true,
                forceIsEditingLink: true,
                settings: [],
                suggestionsQuery: props.attributes[prop].post_type ? {
                    type: 'post',
                    subtype: props.attributes[prop].post_type,
                } : {}
            }),
        ])
    ])

}

function pgImageSizeControl(prop, setAttributes, props, options, onChange ) {
    const {__} = wp.i18n;
    const el = wp.element.createElement;
    const {ToolsPanelItem, Button, Popover, BaseControl, Panel, PanelBody, PanelRow, SelectControl, Icon} = wp.components;

    const title = __('Image size');

    return el(PanelRow, {}, [el(BaseControl, {
    }, [
        el(SelectControl, {
            label: title,
            value: props.attributes[prop].size,
            options: options,
            onChange: function(value) {
                onChange(value)
            }
        })
        ])
    ])
}

function pgMergeInlineSVGAttributes(svg, props) {
    for (let prop in props) {
        let val = props[prop];
        if (typeof val === 'object') {
            const r = [];
            for (const key in val) {
                r.push(`${key.replace(/([A-Z])/g, function (a) {
                    return '-' + a.toLowerCase();
                })}:${val[key]};`)
            }
            val = r.join('');
        }
        if (prop === 'className') prop = 'class';
        const re = new RegExp('(<svg[^>]*\\s*)(' + prop + '="[^"]*")', 'i');
        if (svg.match(re)) {
            svg = svg.replace(re, '$1' + prop + '="' + val + '"');
        } else {
            svg = svg.replace(/<svg/, '<svg ' + prop + '="' + val + '"')
        }
    }
    return svg;
}

class PgHTMLToReact2 {
    constructor() {
    }

    loadHTML(code) {
        const parser = new DOMParser();
        this.doc = parser.parseFromString(code, "text/html");
        this.removeScripts(this.doc);

        var svgs = this.doc.querySelectorAll('svg');
        for (let i = 0; i < svgs.length; i++) {
            this.cleanNode(svgs[i]);
        }
    }

    cleanNode(node) {
        if (node.attributes) {
            const remove = [];
            for (let i = 0; i < node.attributes.length; i++) {
                let name = node.attributes[i].name;
                if (name.startsWith('on')) remove.push(name);
            }
            remove.forEach(function (a) {
                node.removeAttribute(a);
            })
        }
        for (let i = 0; i < node.childNodes.length; i++) {
            this.cleanNode(node.childNodes[i]);
        }
    }

    attributesToProps(node) {
        const props = {}
        for (let i = 0; i < node.attributes.length; i++) {
            let name = node.attributes[i].name;
            if (name.startsWith('on')) continue;

            if (name === 'class') {
                name = 'className';
            }
            if (name === 'style') {
                const a = (node.attributes[i].value || '').split(';');
                const styles = {}
                a.forEach(function (p) {
                    const b = p.split(':');
                    if (b.length > 1) {
                        const sp = b.shift().trim().replace(/-([a-z])/gi, function (s, g) {
                            return g.toUpperCase();
                        })
                        styles[sp] = b.join(':').trim();
                    }
                })
                props.style = styles;
            } else {
                props[name] = node.attributes[i].value === null ? '' : node.attributes[i].value;
            }
        }
        return props;
    }

    removeScripts(node) {
        var scripts = node.querySelectorAll('script');
        for (let i = 0; i < scripts.length; i++) {
            scripts[i].parentNode.removeChild(scripts[i]);
        }
    }

    render(el, lib) {
        const _this = this;

        el = el || window.wp.element.createElement;
        lib = lib || {}

        const doNode = function (node) {
            if (node.nodeType === 1) {

                let tag = node.tagName.toLowerCase();
                const props = _this.attributesToProps(node);

                const children = [];
                let skip_children = false;

                if (tag === 'svg') {
                    props.dangerouslySetInnerHTML = {__html: node.innerHTML}
                    skip_children = true;
                }

                if (!skip_children) {
                    for (let i = 0; i < node.childNodes.length; i++) {
                        const ch = doNode(node.childNodes[i]);
                        ch && children.push(ch);
                    }
                }
                if (lib[tag]) {
                    tag = lib[tag];
                }

                if (children.length) {
                    return el(tag, props, children);
                } else {
                    return el(tag, props);
                }
            } else if (node.nodeType === 3) {
                return node.data;
            }
        }
        return doNode(this.doc.querySelector('body').children[0]);
    }
}

(function() {

    const pgCreateSVGCache = {}

    function pgCreateSVG(dummytag, dummyprops, svg) {
        const pgReact = new PgHTMLToReact2();
        const el = window.wp.element.createElement;

        let props = pgCreateSVGCache[svg] || null;
        if (!props) {
            const parser = new DOMParser();
            const doc = parser.parseFromString(svg, "image/svg+xml");

            const svgel = doc.querySelector('svg');
            pgReact.removeScripts(doc);
            pgReact.cleanNode(svgel);

            props = pgReact.attributesToProps(svgel);

            props.dangerouslySetInnerHTML = {__html: svgel.innerHTML}
            pgCreateSVGCache[svg] = props;
        }
        return el('svg', props);
    }

    window.pgCreateSVG = pgCreateSVG;
})()

function PgGetServerSideRender2() {
    //Addapted ServerSideRender that properly supports InnerBlocks
    const {useDebounce, usePrevious} = wp.compose;
    const {RawHTML, useEffect, useRef, useState, Fragment} = wp.element;
    const {__, sprintf} = wp.i18n;
    const apiFetch = wp.apiFetch;
    const {addQueryArgs} = wp.url;
    const {Placeholder, Spinner} = wp.components;
    const {InnerBlocks} = wp.blockEditor;
    const SanitizeBlockAttributes = wp.blocks.SanitizeBlockAttributes || wp.blocks.__experimentalSanitizeBlockAttributes;
    const useInnerBlocksProps = wp.blockEditor.useInnerBlocksProps || wp.blockEditor.__experimentalUseInnerBlocksProps;
    const el = wp.element.createElement;

    //Addapted from fast-deep-equal
    function equal(a, b) {
        if (a === b) return true;

        if (a && b && typeof a == 'object' && typeof b == 'object') {
            if (a.constructor !== b.constructor) return false;

            var length, i, keys;
            if (Array.isArray(a)) {
                length = a.length;
                if (length != b.length) return false;
                for (i = length; i-- !== 0;)
                    if (!equal(a[i], b[i])) return false;
                return true;
            }

            if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
            if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
            if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();

            keys = Object.keys(a);
            length = keys.length;
            if (length !== Object.keys(b).length) return false;

            for (i = length; i-- !== 0;)
                if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;

            for (i = length; i-- !== 0;) {
                var key = keys[i];

                if (key === '_owner' && a.$$typeof) {
                    continue;
                }
                if (!equal(a[key], b[key])) return false;
            }

            return true;
        }
        return a !== a && b !== b;
    }

    function rendererPath(block, attributes = null, urlQueryArgs = {}) {
        return addQueryArgs(`/wp/v2/block-renderer/${block}`, {
            context: 'edit',
            ...(null !== attributes ? {attributes} : {}),
            ...urlQueryArgs,
        });
    }

    function DefaultEmptyResponsePlaceholder({className}) {
        return el(Placeholder, {className: className}, __('Block rendered as empty.'));
    }

    function DefaultErrorResponsePlaceholder({response, className}) {
        const errorMessage = sprintf(
            // translators: %s: error message describing the problem
            __('Error loading block: %s'),
            response.errorMsg
        );
        return el(Placeholder, {className: className}, errorMessage);
    }

    function DefaultLoadingResponsePlaceholder({className}) {
        return el(Placeholder, {className: className}, el(Spinner, {}));
    }


    return function (props) {
        const {
            attributes,
            block,
            className,
            httpMethod = 'GET',
            urlQueryArgs,
            EmptyResponsePlaceholder = DefaultEmptyResponsePlaceholder,
            ErrorResponsePlaceholder = DefaultErrorResponsePlaceholder,
            LoadingResponsePlaceholder = DefaultLoadingResponsePlaceholder,
            innerBlocksProps,
            blockProps
        } = props;

        const isMountedRef = useRef(true);
        const fetchRequestRef = useRef();
        const [response, setResponse] = useState(null);
        const prevProps = usePrevious(props);

        const innerAttribute = 'data-wp-inner-blocks';
        const blocksPropsAttribute = 'data-wp-block-props';

        let currentCode = null;
        let currentFunction = null;

        function pgel(tag, props, ...children) {
            if (tag === 'script') return null;

            if (props) {
                if (props.class) {
                    props.className = props.class;
                    delete props.class;
                }

                for (const prop in props) {
                    if (props.hasOwnProperty(prop)) {
                        if (prop.match(/^on[A-Z]+/)) {
                            props[prop] = null;
                        }
                    }
                }
                if (innerAttribute in props) {
                    delete props[innerAttribute];
                    props = {...props, ...innerBlocksProps};
                    return el(tag, props);
                }
                if (blocksPropsAttribute in props) {
                    delete props[blocksPropsAttribute];
                    props = {...props, ...blockProps};
                }
            }
            if (children.length) {
                return el(tag, props, children);
            } else {
                return el(tag, props);
            }
        }

        function fetchData() {
            isMountedRef.needsFetch = false;

            if (!isMountedRef.current) {
                return;
            }
            if (null !== response) {
                setResponse(null);
            }

            const sanitizedAttributes =
                attributes &&
                SanitizeBlockAttributes(block, attributes);

            // If httpMethod is 'POST', send the attributes in the request body instead of the URL.
            // This allows sending a larger attributes object than in a GET request, where the attributes are in the URL.
            const isPostRequest = 'POST' === httpMethod;
            const urlAttributes = isPostRequest
                ? null
                : sanitizedAttributes ?? null;
            const path = rendererPath(block, urlAttributes, urlQueryArgs);
            const data = isPostRequest
                ? {attributes: sanitizedAttributes ?? null}
                : null;

            // Store the latest fetch request so that when we process it, we can
            // check if it is the current request, to avoid race conditions on slow networks.
            const fetchRequest = (fetchRequestRef.current = apiFetch({
                path,
                data,
                method: isPostRequest ? 'POST' : 'GET',
            })
                .then((fetchResponse) => {
                    if (
                        isMountedRef.current &&
                        fetchRequest === fetchRequestRef.current &&
                        fetchResponse
                    ) {
                        setResponse(fetchResponse.rendered);
                    }
                })
                .catch((error) => {
                    if (
                        isMountedRef.current &&
                        fetchRequest === fetchRequestRef.current
                    ) {
                        setResponse({
                            error: true,
                            errorMsg: error.message,
                        });
                    }
                }));

            return fetchRequest;
        }

        const debouncedFetchData = useDebounce(fetchData, 500);

        // When the component unmounts, set isMountedRef to false. This will
        // let the async fetch callbacks know when to stop.
        useEffect(
            () => () => {
                isMountedRef.current = false;
                isMountedRef.needsFetch = false;
            },
            []
        );

        useEffect(() => {
            // Don't debounce the first fetch. This ensures that the first render
            // shows data as soon as possible
            if (prevProps === undefined) {
                fetchData();
            } else if (!equal(prevProps.attributes, props.attributes)) {
                isMountedRef.needsFetch = true;
                debouncedFetchData();
            } else {
                if (isMountedRef.needsFetch) {
                    fetchData();
                }
            }
        });

        if (response === '') {
            return el(EmptyResponsePlaceholder, {...props, ...blockProps});
        } else if (!response) {
            return el(LoadingResponsePlaceholder, {...props, ...blockProps});
        } else if (response.error) {
            return el(ErrorResponsePlaceholder, {response: response, ...props, ...blockProps});
        }

        try {

            if (isMountedRef.currentCode !== response) {
                isMountedRef.currentFunction = new PgHTMLToReact2();
                isMountedRef.currentFunction.loadHTML(response);
                isMountedRef.currentCode = response;
            }
            return isMountedRef.currentFunction.render(pgel);
        } catch (err) {
            //unable to render inline
            console.warn('Unable to compile dynamic block to JSX:', err);
            return el('div', {...blockProps}, [
                el(RawHTML, {className: className}, response),
                el('div', {...innerBlocksProps})
            ])
        }
    }

}

window.PgServerSideRender2 = PgGetServerSideRender2();
