(function ($, undefined) {
  acf.jsxNameReplacements = {
    "accent-height": "accentHeight",
    "accentheight": "accentHeight",
    "accept-charset": "acceptCharset",
    "acceptcharset": "acceptCharset",
    "accesskey": "accessKey",
    "alignment-baseline": "alignmentBaseline",
    "alignmentbaseline": "alignmentBaseline",
    "allowedblocks": "allowedBlocks",
    "allowfullscreen": "allowFullScreen",
    "allowreorder": "allowReorder",
    "arabic-form": "arabicForm",
    "arabicform": "arabicForm",
    "attributename": "attributeName",
    "attributetype": "attributeType",
    "autocapitalize": "autoCapitalize",
    "autocomplete": "autoComplete",
    "autocorrect": "autoCorrect",
    "autofocus": "autoFocus",
    "autoplay": "autoPlay",
    "autoreverse": "autoReverse",
    "autosave": "autoSave",
    "basefrequency": "baseFrequency",
    "baseline-shift": "baselineShift",
    "baselineshift": "baselineShift",
    "baseprofile": "baseProfile",
    "calcmode": "calcMode",
    "cap-height": "capHeight",
    "capheight": "capHeight",
    "cellpadding": "cellPadding",
    "cellspacing": "cellSpacing",
    "charset": "charSet",
    "class": "className",
    "classid": "classID",
    "classname": "className",
    "clip-path": "clipPath",
    "clip-rule": "clipRule",
    "clippath": "clipPath",
    "clippathunits": "clipPathUnits",
    "cliprule": "clipRule",
    "color-interpolation": "colorInterpolation",
    "color-interpolation-filters": "colorInterpolationFilters",
    "color-profile": "colorProfile",
    "color-rendering": "colorRendering",
    "colorinterpolation": "colorInterpolation",
    "colorinterpolationfilters": "colorInterpolationFilters",
    "colorprofile": "colorProfile",
    "colorrendering": "colorRendering",
    "colspan": "colSpan",
    "contenteditable": "contentEditable",
    "contentscripttype": "contentScriptType",
    "contentstyletype": "contentStyleType",
    "contextmenu": "contextMenu",
    "controlslist": "controlsList",
    "crossorigin": "crossOrigin",
    "dangerouslysetinnerhtml": "dangerouslySetInnerHTML",
    "datetime": "dateTime",
    "defaultchecked": "defaultChecked",
    "defaultvalue": "defaultValue",
    "diffuseconstant": "diffuseConstant",
    "disablepictureinpicture": "disablePictureInPicture",
    "disableremoteplayback": "disableRemotePlayback",
    "dominant-baseline": "dominantBaseline",
    "dominantbaseline": "dominantBaseline",
    "edgemode": "edgeMode",
    "enable-background": "enableBackground",
    "enablebackground": "enableBackground",
    "enctype": "encType",
    "enterkeyhint": "enterKeyHint",
    "externalresourcesrequired": "externalResourcesRequired",
    "fill-opacity": "fillOpacity",
    "fill-rule": "fillRule",
    "fillopacity": "fillOpacity",
    "fillrule": "fillRule",
    "filterres": "filterRes",
    "filterunits": "filterUnits",
    "flood-color": "floodColor",
    "flood-opacity": "floodOpacity",
    "floodcolor": "floodColor",
    "floodopacity": "floodOpacity",
    "font-family": "fontFamily",
    "font-size": "fontSize",
    "font-size-adjust": "fontSizeAdjust",
    "font-stretch": "fontStretch",
    "font-style": "fontStyle",
    "font-variant": "fontVariant",
    "font-weight": "fontWeight",
    "fontfamily": "fontFamily",
    "fontsize": "fontSize",
    "fontsizeadjust": "fontSizeAdjust",
    "fontstretch": "fontStretch",
    "fontstyle": "fontStyle",
    "fontvariant": "fontVariant",
    "fontweight": "fontWeight",
    "for": "htmlFor",
    "formaction": "formAction",
    "formenctype": "formEncType",
    "formmethod": "formMethod",
    "formnovalidate": "formNoValidate",
    "formtarget": "formTarget",
    "frameborder": "frameBorder",
    "glyph-name": "glyphName",
    "glyph-orientation-horizontal": "glyphOrientationHorizontal",
    "glyph-orientation-vertical": "glyphOrientationVertical",
    "glyphname": "glyphName",
    "glyphorientationhorizontal": "glyphOrientationHorizontal",
    "glyphorientationvertical": "glyphOrientationVertical",
    "glyphref": "glyphRef",
    "gradienttransform": "gradientTransform",
    "gradientunits": "gradientUnits",
    "horiz-adv-x": "horizAdvX",
    "horiz-origin-x": "horizOriginX",
    "horizadvx": "horizAdvX",
    "horizoriginx": "horizOriginX",
    "hreflang": "hrefLang",
    "htmlfor": "htmlFor",
    "http-equiv": "httpEquiv",
    "httpequiv": "httpEquiv",
    "image-rendering": "imageRendering",
    "imagerendering": "imageRendering",
    "innerhtml": "innerHTML",
    "inputmode": "inputMode",
    "itemid": "itemID",
    "itemprop": "itemProp",
    "itemref": "itemRef",
    "itemscope": "itemScope",
    "itemtype": "itemType",
    "kernelmatrix": "kernelMatrix",
    "kernelunitlength": "kernelUnitLength",
    "keyparams": "keyParams",
    "keypoints": "keyPoints",
    "keysplines": "keySplines",
    "keytimes": "keyTimes",
    "keytype": "keyType",
    "lengthadjust": "lengthAdjust",
    "letter-spacing": "letterSpacing",
    "letterspacing": "letterSpacing",
    "lighting-color": "lightingColor",
    "lightingcolor": "lightingColor",
    "limitingconeangle": "limitingConeAngle",
    "marginheight": "marginHeight",
    "marginwidth": "marginWidth",
    "marker-end": "markerEnd",
    "marker-mid": "markerMid",
    "marker-start": "markerStart",
    "markerend": "markerEnd",
    "markerheight": "markerHeight",
    "markermid": "markerMid",
    "markerstart": "markerStart",
    "markerunits": "markerUnits",
    "markerwidth": "markerWidth",
    "maskcontentunits": "maskContentUnits",
    "maskunits": "maskUnits",
    "maxlength": "maxLength",
    "mediagroup": "mediaGroup",
    "minlength": "minLength",
    "nomodule": "noModule",
    "novalidate": "noValidate",
    "numoctaves": "numOctaves",
    "overline-position": "overlinePosition",
    "overline-thickness": "overlineThickness",
    "overlineposition": "overlinePosition",
    "overlinethickness": "overlineThickness",
    "paint-order": "paintOrder",
    "paintorder": "paintOrder",
    "panose-1": "panose1",
    "pathlength": "pathLength",
    "patterncontentunits": "patternContentUnits",
    "patterntransform": "patternTransform",
    "patternunits": "patternUnits",
    "playsinline": "playsInline",
    "pointer-events": "pointerEvents",
    "pointerevents": "pointerEvents",
    "pointsatx": "pointsAtX",
    "pointsaty": "pointsAtY",
    "pointsatz": "pointsAtZ",
    "preservealpha": "preserveAlpha",
    "preserveaspectratio": "preserveAspectRatio",
    "primitiveunits": "primitiveUnits",
    "radiogroup": "radioGroup",
    "readonly": "readOnly",
    "referrerpolicy": "referrerPolicy",
    "refx": "refX",
    "refy": "refY",
    "rendering-intent": "renderingIntent",
    "renderingintent": "renderingIntent",
    "repeatcount": "repeatCount",
    "repeatdur": "repeatDur",
    "requiredextensions": "requiredExtensions",
    "requiredfeatures": "requiredFeatures",
    "rowspan": "rowSpan",
    "shape-rendering": "shapeRendering",
    "shaperendering": "shapeRendering",
    "specularconstant": "specularConstant",
    "specularexponent": "specularExponent",
    "spellcheck": "spellCheck",
    "spreadmethod": "spreadMethod",
    "srcdoc": "srcDoc",
    "srclang": "srcLang",
    "srcset": "srcSet",
    "startoffset": "startOffset",
    "stddeviation": "stdDeviation",
    "stitchtiles": "stitchTiles",
    "stop-color": "stopColor",
    "stop-opacity": "stopOpacity",
    "stopcolor": "stopColor",
    "stopopacity": "stopOpacity",
    "strikethrough-position": "strikethroughPosition",
    "strikethrough-thickness": "strikethroughThickness",
    "strikethroughposition": "strikethroughPosition",
    "strikethroughthickness": "strikethroughThickness",
    "stroke-dasharray": "strokeDasharray",
    "stroke-dashoffset": "strokeDashoffset",
    "stroke-linecap": "strokeLinecap",
    "stroke-linejoin": "strokeLinejoin",
    "stroke-miterlimit": "strokeMiterlimit",
    "stroke-opacity": "strokeOpacity",
    "stroke-width": "strokeWidth",
    "strokedasharray": "strokeDasharray",
    "strokedashoffset": "strokeDashoffset",
    "strokelinecap": "strokeLinecap",
    "strokelinejoin": "strokeLinejoin",
    "strokemiterlimit": "strokeMiterlimit",
    "strokeopacity": "strokeOpacity",
    "strokewidth": "strokeWidth",
    "suppresscontenteditablewarning": "suppressContentEditableWarning",
    "suppresshydrationwarning": "suppressHydrationWarning",
    "surfacescale": "surfaceScale",
    "systemlanguage": "systemLanguage",
    "tabindex": "tabIndex",
    "tablevalues": "tableValues",
    "targetx": "targetX",
    "targety": "targetY",
    "templatelock": "templateLock",
    "text-anchor": "textAnchor",
    "text-decoration": "textDecoration",
    "text-rendering": "textRendering",
    "textanchor": "textAnchor",
    "textdecoration": "textDecoration",
    "textlength": "textLength",
    "textrendering": "textRendering",
    "underline-position": "underlinePosition",
    "underline-thickness": "underlineThickness",
    "underlineposition": "underlinePosition",
    "underlinethickness": "underlineThickness",
    "unicode-bidi": "unicodeBidi",
    "unicode-range": "unicodeRange",
    "unicodebidi": "unicodeBidi",
    "unicoderange": "unicodeRange",
    "units-per-em": "unitsPerEm",
    "unitsperem": "unitsPerEm",
    "usemap": "useMap",
    "v-alphabetic": "vAlphabetic",
    "v-hanging": "vHanging",
    "v-ideographic": "vIdeographic",
    "v-mathematical": "vMathematical",
    "valphabetic": "vAlphabetic",
    "vector-effect": "vectorEffect",
    "vectoreffect": "vectorEffect",
    "vert-adv-y": "vertAdvY",
    "vert-origin-x": "vertOriginX",
    "vert-origin-y": "vertOriginY",
    "vertadvy": "vertAdvY",
    "vertoriginx": "vertOriginX",
    "vertoriginy": "vertOriginY",
    "vhanging": "vHanging",
    "videographic": "vIdeographic",
    "viewbox": "viewBox",
    "viewtarget": "viewTarget",
    "vmathematical": "vMathematical",
    "word-spacing": "wordSpacing",
    "wordspacing": "wordSpacing",
    "writing-mode": "writingMode",
    "writingmode": "writingMode",
    "x-height": "xHeight",
    "xchannelselector": "xChannelSelector",
    "xheight": "xHeight",
    "xlink:actuate": "xlinkActuate",
    "xlink:arcrole": "xlinkArcrole",
    "xlink:href": "xlinkHref",
    "xlink:role": "xlinkRole",
    "xlink:show": "xlinkShow",
    "xlink:title": "xlinkTitle",
    "xlink:type": "xlinkType",
    "xlinkactuate": "xlinkActuate",
    "xlinkarcrole": "xlinkArcrole",
    "xlinkhref": "xlinkHref",
    "xlinkrole": "xlinkRole",
    "xlinkshow": "xlinkShow",
    "xlinktitle": "xlinkTitle",
    "xlinktype": "xlinkType",
    "xml:base": "xmlBase",
    "xml:lang": "xmlLang",
    "xml:space": "xmlSpace",
    "xmlbase": "xmlBase",
    "xmllang": "xmlLang",
    "xmlns:xlink": "xmlnsXlink",
    "xmlnsxlink": "xmlnsXlink",
    "xmlspace": "xmlSpace",
    "ychannelselector": "yChannelSelector",
    "zoomandpan": "zoomAndPan"
  };
})(jQuery);

(function ($, undefined) {
  // Dependencies.
  const {
    BlockControls,
    InspectorControls,
    InnerBlocks
  } = wp.blockEditor;
  const {
    Toolbar,
    IconButton,
    Placeholder,
    Spinner
  } = wp.components;
  const {
    Fragment
  } = wp.element;
  const {
    Component
  } = React;
  const {
    withSelect
  } = wp.data;
  const {
    createHigherOrderComponent
  } = wp.compose;
  /**
   * Storage for registered block types.
   *
   * @since 5.8.0
   * @var object
   */

  const blockTypes = {};
  /**
   * Returns a block type for the given name.
   *
   * @date	20/2/19
   * @since	5.8.0
   *
   * @param	string name The block name.
   * @return	(object|false)
   */

  function getBlockType(name) {
    return blockTypes[name] || false;
  }
  /**
   * Returns true if a block exists for the given name.
   *
   * @date	20/2/19
   * @since	5.8.0
   *
   * @param	string name The block name.
   * @return	bool
   */


  function isBlockType(name) {
    return !!blockTypes[name];
  }
  /**
   * Returns true if the provided block is new.
   *
   * @date	31/07/2020
   * @since	5.9.0
   *
   * @param	object props The block props.
   * @return	bool
   */


  function isNewBlock(props) {
    return !props.attributes.id;
  }
  /**
   * Returns true if the provided block is a duplicate:
   * True when there are is another block with the same "id", but a different "clientId".
   * 
   * @date	31/07/2020
   * @since	5.9.0
   *
   * @param	object props The block props.
   * @return	bool
   */


  function isDuplicateBlock(props) {
    return getBlocks().filter(block => block.attributes.id === props.attributes.id).filter(block => block.clientId !== props.clientId).length;
  }
  /**
   * Registers a block type.
   *
   * @date	19/2/19
   * @since	5.8.0
   *
   * @param	object blockType The block type settings localized from PHP.
   * @return	object The result from wp.blocks.registerBlockType().
   */


  function registerBlockType(blockType) {
    // Bail ealry if is excluded post_type.
    var allowedTypes = blockType.post_types || [];

    if (allowedTypes.length) {
      // Always allow block to appear on "Edit reusable Block" screen.
      allowedTypes.push('wp_block'); // Check post type.

      var postType = acf.get('postType');

      if (allowedTypes.indexOf(postType) === -1) {
        return false;
      }
    } // Handle svg HTML.


    if (typeof blockType.icon === 'string' && blockType.icon.substr(0, 4) === '<svg') {
      const iconHTML = blockType.icon;
      blockType.icon = /*#__PURE__*/React.createElement(Div, null, iconHTML);
    } // Remove icon if empty to allow for default "block".
    // Avoids JS error preventing block from being registered.


    if (!blockType.icon) {
      delete blockType.icon;
    } // Check category exists and fallback to "common".


    var category = wp.blocks.getCategories().filter(cat => cat.slug === blockType.category).pop();

    if (!category) {
      //console.warn( `The block "${blockType.name}" is registered with an unknown category "${blockType.category}".` );
      blockType.category = 'common';
    } // Define block type attributes.
    // Leave default undefined to allow WP to serialize attributes in HTML comments.
    // See https://github.com/WordPress/gutenberg/issues/7342


    let attributes = {
      id: {
        type: 'string'
      },
      name: {
        type: 'string'
      },
      data: {
        type: 'object'
      },
      align: {
        type: 'string'
      },
      mode: {
        type: 'string'
      }
    }; // Append edit and save functions.

    let ThisBlockEdit = BlockEdit;
    let ThisBlockSave = BlockSave; // Apply align_text functionality.

    if (blockType.supports.align_text) {
      attributes = withAlignTextAttributes(attributes);
      ThisBlockEdit = withAlignTextComponent(ThisBlockEdit, blockType);
    } // Apply align_content functionality.


    if (blockType.supports.align_content) {
      attributes = withAlignContentAttributes(attributes);
      ThisBlockEdit = withAlignContentComponent(ThisBlockEdit, blockType);
    } // Merge in block settings.


    blockType = acf.parseArgs(blockType, {
      title: '',
      name: '',
      category: '',
      attributes: attributes,
      edit: function (props) {
        return /*#__PURE__*/React.createElement(ThisBlockEdit, props);
      },
      save: function (props) {
        return /*#__PURE__*/React.createElement(ThisBlockSave, props);
      }
    }); // Add to storage.

    blockTypes[blockType.name] = blockType; // Register with WP.

    var result = wp.blocks.registerBlockType(blockType.name, blockType); // Fix bug in 'core/anchor/attribute' filter overwriting attribute.
    // See https://github.com/WordPress/gutenberg/issues/15240

    if (result.attributes.anchor) {
      result.attributes.anchor = {
        type: 'string'
      };
    } // Return result.


    return result;
  }
  /**
   * Returns the wp.data.select() response with backwards compatibility.
   *
   * @date	17/06/2020
   * @since	5.9.0
   *
   * @param	string selector The selector name.
   * @return	mixed
   */


  function select(selector) {
    if (selector === 'core/block-editor') {
      return wp.data.select('core/block-editor') || wp.data.select('core/editor');
    }

    return wp.data.select(selector);
  }
  /**
   * Returns the wp.data.dispatch() response with backwards compatibility.
   *
   * @date	17/06/2020
   * @since	5.9.0
   *
   * @param	string selector The selector name.
   * @return	mixed
   */


  function dispatch(selector) {
    return wp.data.dispatch(selector);
  }
  /**
   * Returns an array of all blocks for the given args.
   *
   * @date	27/2/19
   * @since	5.7.13
   *
   * @param	object args An object of key=>value pairs used to filter results.
   * @return	array.
   */


  function getBlocks(args) {
    // Get all blocks (avoid deprecated warning).
    let blocks = select('core/block-editor').getBlocks(); // Append innerBlocks.

    let i = 0;

    while (i < blocks.length) {
      blocks = blocks.concat(blocks[i].innerBlocks);
      i++;
    } // Loop over args and filter.


    for (var k in args) {
      blocks = blocks.filter(block => block.attributes[k] === args[k]);
    } // Return results.


    return blocks;
  } // Data storage for AJAX requests.


  const ajaxQueue = {};
  /**
   * Fetches a JSON result from the AJAX API.
   *
   * @date	28/2/19
   * @since	5.7.13
   *
   * @param	object block The block props.
   * @query	object The query args used in AJAX callback.
   * @return	object The AJAX promise.
   */

  function fetchBlock(args) {
    const {
      attributes = {},
      query = {},
      delay = 0
    } = args; // Use storage or default data.

    const {
      id
    } = attributes;
    const data = ajaxQueue[id] || {
      query: {},
      timeout: false,
      promise: $.Deferred()
    }; // Append query args to storage.

    data.query = { ...data.query,
      ...query
    }; // Set fresh timeout.

    clearTimeout(data.timeout);
    data.timeout = setTimeout(function () {
      $.ajax({
        url: acf.get('ajaxurl'),
        dataType: 'json',
        type: 'post',
        cache: false,
        data: acf.prepareForAjax({
          action: 'acf/ajax/fetch-block',
          block: JSON.stringify(attributes),
          query: data.query
        })
      }).always(function () {
        // Clean up queue after AJAX request is complete.
        ajaxQueue[id] = null;
      }).done(function () {
        data.promise.resolve.apply(this, arguments);
      }).fail(function () {
        data.promise.reject.apply(this, arguments);
      });
    }, delay); // Update storage.

    ajaxQueue[id] = data; // Return promise.

    return data.promise;
  }
  /**
   * Returns true if both object are the same.
   *
   * @date	19/05/2020
   * @since	5.9.0
   *
   * @param	object obj1
   * @param	object obj2
   * @return	bool
   */


  function compareObjects(obj1, obj2) {
    return JSON.stringify(obj1) === JSON.stringify(obj2);
  }
  /**
   * Converts HTML into a React element.
   *
   * @date	19/05/2020
   * @since	5.9.0
   *
   * @param	string html The HTML to convert.
   * @return	object Result of React.createElement().
   */


  acf.parseJSX = function (html) {
    return parseNode($(html)[0]);
  };
  /**
   * Converts a DOM node into a React element.
   *
   * @date	19/05/2020
   * @since	5.9.0
   *
   * @param	DOM node The DOM node.
   * @return	object Result of React.createElement().
   */


  function parseNode(node) {
    // Get node name.
    var nodeName = parseNodeName(node.nodeName.toLowerCase());

    if (!nodeName) {
      return null;
    } // Get node attributes in React friendly format.


    var nodeAttrs = {};
    acf.arrayArgs(node.attributes).map(parseNodeAttr).forEach(function (attr) {
      nodeAttrs[attr.name] = attr.value;
    }); // Define args for React.createElement().

    var args = [nodeName, nodeAttrs];
    acf.arrayArgs(node.childNodes).forEach(function (child) {
      if (child instanceof Text) {
        var text = child.textContent;

        if (text) {
          args.push(text);
        }
      } else {
        args.push(parseNode(child));
      }
    }); // Return element.

    return React.createElement.apply(this, args);
  }

  ;
  /**
   * Converts a node or attribute name into it's JSX compliant name
   *
   * @date     05/07/2021
   * @since    5.9.8
   *
   * @param    string name The node or attribute name.
   * @returns  string
   */

  function getJSXName(name) {
    var replacement = acf.isget(acf, 'jsxNameReplacements', name);
    if (replacement) return replacement;
    return name;
  }
  /**
   * Converts the given name into a React friendly name or component.
   *
   * @date	19/05/2020
   * @since	5.9.0
   *
   * @param	string name The node name in lowercase.
   * @return	mixed
   */


  function parseNodeName(name) {
    switch (name) {
      case 'innerblocks':
        return InnerBlocks;

      case 'script':
        return Script;

      case '#comment':
        return null;

      default:
        // Replace names for JSX counterparts.
        name = getJSXName(name);
    }

    return name;
  }
  /**
   * Converts the given attribute into a React friendly name and value object.
   *
   * @date	19/05/2020
   * @since	5.9.0
   *
   * @param	obj nodeAttr The node attribute.
   * @return	obj
   */


  function parseNodeAttr(nodeAttr) {
    var name = nodeAttr.name;
    var value = nodeAttr.value;

    switch (name) {
      // Class.
      case 'class':
        name = 'className';
        break;
      // Style.

      case 'style':
        var css = {};
        value.split(';').forEach(function (s) {
          var pos = s.indexOf(':');

          if (pos > 0) {
            var ruleName = s.substr(0, pos).trim();
            var ruleValue = s.substr(pos + 1).trim(); // Rename core properties, but not CSS variables.

            if (ruleName.charAt(0) !== '-') {
              ruleName = acf.strCamelCase(ruleName);
            }

            css[ruleName] = ruleValue;
          }
        });
        value = css;
        break;
      // Default.

      default:
        // No formatting needed for "data-x" attributes.
        if (name.indexOf('data-') === 0) {
          break;
        } // Replace names for JSX counterparts.


        name = getJSXName(name); // Convert JSON values.

        var c1 = value.charAt(0);

        if (c1 === '[' || c1 === '{') {
          value = JSON.parse(value);
        } // Convert bool values.


        if (value === 'true' || value === 'false') {
          value = value === 'true';
        }

        break;
    }

    return {
      name: name,
      value: value
    };
  }
  /**
   * Higher Order Component used to set default block attribute values.
   * 
   * By modifying block attributes directly, instead of defining defaults in registerBlockType(), 
   * WordPress will include them always within the saved block serialized JSON.
   *
   * @date	31/07/2020
   * @since	5.9.0
   *
   * @param	Component BlockListBlock The BlockListBlock Component.
   * @return	Component
   */


  var withDefaultAttributes = createHigherOrderComponent(function (BlockListBlock) {
    return class WrappedBlockEdit extends Component {
      constructor(props) {
        super(props); // Extract vars.

        const {
          name,
          attributes
        } = this.props; // Only run on ACF Blocks.

        const blockType = getBlockType(name);

        if (!blockType) {
          return;
        } // Set unique ID and default attributes for newly added blocks.


        if (isNewBlock(props)) {
          attributes.id = acf.uniqid('block_');

          for (let attribute in blockType.attributes) {
            if (attributes[attribute] === undefined && blockType[attribute] !== undefined) {
              attributes[attribute] = blockType[attribute];
            }
          }

          return;
        } // Generate new ID for duplicated blocks.


        if (isDuplicateBlock(props)) {
          attributes.id = acf.uniqid('block_');
          return;
        }
      }

      render() {
        return /*#__PURE__*/React.createElement(BlockListBlock, this.props);
      }

    };
  }, 'withDefaultAttributes');
  wp.hooks.addFilter('editor.BlockListBlock', 'acf/with-default-attributes', withDefaultAttributes);
  /**
   * The BlockSave functional component.
   *
   * @date	08/07/2020
   * @since	5.9.0
   */

  function BlockSave() {
    return /*#__PURE__*/React.createElement(InnerBlocks.Content, null);
  }
  /**
   * The BlockEdit component.
   *
   * @date	19/2/19
   * @since	5.7.12
   */


  class BlockEdit extends Component {
    constructor(props) {
      super(props);
      this.setup();
    }

    setup() {
      const {
        name,
        attributes
      } = this.props;
      const blockType = getBlockType(name); // Restrict current mode.

      function restrictMode(modes) {
        if (modes.indexOf(attributes.mode) === -1) {
          attributes.mode = modes[0];
        }
      }

      switch (blockType.mode) {
        case 'edit':
          restrictMode(['edit', 'preview']);
          break;

        case 'preview':
          restrictMode(['preview', 'edit']);
          break;

        default:
          restrictMode(['auto']);
          break;
      }
    }

    render() {
      const {
        name,
        attributes,
        setAttributes
      } = this.props;
      const {
        mode
      } = attributes;
      const blockType = getBlockType(name); // Show toggle only for edit/preview modes.

      let showToggle = blockType.supports.mode;

      if (mode === 'auto') {
        showToggle = false;
      } // Configure toggle variables.


      const toggleText = mode === 'preview' ? acf.__('Switch to Edit') : acf.__('Switch to Preview');
      const toggleIcon = mode === 'preview' ? 'edit' : 'welcome-view-site';

      function toggleMode() {
        setAttributes({
          mode: mode === 'preview' ? 'edit' : 'preview'
        });
      } // Return template.


      return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(BlockControls, null, showToggle && /*#__PURE__*/React.createElement(Toolbar, null, /*#__PURE__*/React.createElement(IconButton, {
        className: "components-icon-button components-toolbar__control",
        label: toggleText,
        icon: toggleIcon,
        onClick: toggleMode
      }))), /*#__PURE__*/React.createElement(InspectorControls, null, mode === 'preview' && /*#__PURE__*/React.createElement("div", {
        className: "acf-block-component acf-block-panel"
      }, /*#__PURE__*/React.createElement(BlockForm, this.props))), /*#__PURE__*/React.createElement(BlockBody, this.props));
    }

  }
  /**
   * The BlockBody component.
   *
   * @date	19/2/19
   * @since	5.7.12
   */


  class _BlockBody extends Component {
    render() {
      const {
        attributes,
        isSelected
      } = this.props;
      const {
        mode
      } = attributes;
      return /*#__PURE__*/React.createElement("div", {
        className: "acf-block-component acf-block-body"
      }, mode === 'auto' && isSelected ? /*#__PURE__*/React.createElement(BlockForm, this.props) : mode === 'auto' && !isSelected ? /*#__PURE__*/React.createElement(BlockPreview, this.props) : mode === 'preview' ? /*#__PURE__*/React.createElement(BlockPreview, this.props) : /*#__PURE__*/React.createElement(BlockForm, this.props));
    }

  } // Append blockIndex to component props.


  const BlockBody = withSelect(function (select, ownProps) {
    const {
      clientId
    } = ownProps; // Use optional rootClientId to allow discoverability of child blocks.

    const rootClientId = select('core/block-editor').getBlockRootClientId(clientId);
    const index = select('core/block-editor').getBlockIndex(clientId, rootClientId);
    return {
      index
    };
  })(_BlockBody);
  /**
   * A react component to append HTMl.
   *
   * @date	19/2/19
   * @since	5.7.12
   *
   * @param	string children The html to insert.
   * @return	void
   */

  class Div extends Component {
    render() {
      return /*#__PURE__*/React.createElement("div", {
        dangerouslySetInnerHTML: {
          __html: this.props.children
        }
      });
    }

  }
  /**
   * A react Component for inline scripts.
   * 
   * This Component uses a combination of React references and jQuery to append the
   * inline <script> HTML each time the component is rendered.
   *
   * @date	29/05/2020
   * @since	5.9.0
   *
   * @param	type Var Description.
   * @return	type Description.
   */


  class Script extends Component {
    render() {
      return /*#__PURE__*/React.createElement("div", {
        ref: el => this.el = el
      });
    }

    setHTML(html) {
      $(this.el).html(`<script>${html}</script>`);
    }

    componentDidUpdate() {
      this.setHTML(this.props.children);
    }

    componentDidMount() {
      this.setHTML(this.props.children);
    }

  } // Data storage for DynamicHTML components.


  const store = {};
  /**
   * DynamicHTML Class.
   *
   * A react componenet to load and insert dynamic HTML.
   *
   * @date	19/2/19
   * @since	5.7.12
   *
   * @param	void
   * @return	void
   */

  class DynamicHTML extends Component {
    constructor(props) {
      super(props); // Bind callbacks.

      this.setRef = this.setRef.bind(this); // Define default props and call setup().

      this.id = '';
      this.el = false;
      this.subscribed = true;
      this.renderMethod = 'jQuery';
      this.setup(props); // Load state.

      this.loadState();
    }

    setup(props) {// Do nothing.
    }

    fetch() {// Do nothing.
    }

    loadState() {
      this.state = store[this.id] || {};
    }

    setState(state) {
      store[this.id] = { ...this.state,
        ...state
      }; // Update component state if subscribed.
      // - Allows AJAX callback to update store without modifying state of an unmounted component.

      if (this.subscribed) {
        super.setState(state);
      }
    }

    setHtml(html) {
      html = html ? html.trim() : ''; // Bail early if html has not changed.

      if (html === this.state.html) {
        return;
      } // Update state.


      var state = {
        html: html
      };

      if (this.renderMethod === 'jsx') {
        state.jsx = acf.parseJSX(html);
        state.$el = $(this.el);
      } else {
        state.$el = $(html);
      }

      this.setState(state);
    }

    setRef(el) {
      this.el = el;
    }

    render() {
      // Render JSX.
      if (this.state.jsx) {
        return /*#__PURE__*/React.createElement("div", {
          ref: this.setRef
        }, this.state.jsx);
      } // Return HTML.


      return /*#__PURE__*/React.createElement("div", {
        ref: this.setRef
      }, /*#__PURE__*/React.createElement(Placeholder, null, /*#__PURE__*/React.createElement(Spinner, null)));
    }

    shouldComponentUpdate(nextProps, nextState) {
      if (nextProps.index !== this.props.index) {
        this.componentWillMove();
      }

      return nextState.html !== this.state.html;
    }

    display(context) {
      // This method is called after setting new HTML and the Component render.
      // The jQuery render method simply needs to move $el into place.
      if (this.renderMethod === 'jQuery') {
        var $el = this.state.$el;
        var $prevParent = $el.parent();
        var $thisParent = $(this.el); // Move $el into place.

        $thisParent.html($el); // Special case for reusable blocks.
        // Multiple instances of the same reusable block share the same block id.
        // This causes all instances to share the same state (cool), which unfortunately
        // pulls $el back and forth between the last rendered reusable block.
        // This simple fix leaves a "clone" behind :)

        if ($prevParent.length && $prevParent[0] !== $thisParent[0]) {
          $prevParent.html($el.clone());
        }
      } // Call context specific method.


      switch (context) {
        case 'append':
          this.componentDidAppend();
          break;

        case 'remount':
          this.componentDidRemount();
          break;
      }
    }

    componentDidMount() {
      // Fetch on first load.
      if (this.state.html === undefined) {
        //console.log('componentDidMount', this.id);
        this.fetch(); // Or remount existing HTML.
      } else {
        this.display('remount');
      }
    }

    componentDidUpdate(prevProps, prevState) {
      // HTML has changed.
      this.display('append');
    }

    componentDidAppend() {
      acf.doAction('append', this.state.$el);
    }

    componentWillUnmount() {
      acf.doAction('unmount', this.state.$el); // Unsubscribe this component from state.

      this.subscribed = false;
    }

    componentDidRemount() {
      this.subscribed = true; // Use setTimeout to avoid incorrect timing of events.
      // React will unmount and mount components in DOM order.
      // This means a new component can be mounted before an old one is unmounted.
      // ACF shares $el across new/old components which is un-React-like.
      // This timout ensures that unmounting occurs before remounting.

      setTimeout(() => {
        acf.doAction('remount', this.state.$el);
      });
    }

    componentWillMove() {
      acf.doAction('unmount', this.state.$el);
      setTimeout(() => {
        acf.doAction('remount', this.state.$el);
      });
    }

  }
  /**
   * BlockForm Class.
   *
   * A react componenet to handle the block form.
   *
   * @date	19/2/19
   * @since	5.7.12
   *
   * @param	string id the block id.
   * @return	void
   */


  class BlockForm extends DynamicHTML {
    setup(props) {
      this.id = `BlockForm-${props.attributes.id}`;
    }

    fetch() {
      // Extract props.
      const {
        attributes
      } = this.props; // Request AJAX and update HTML on complete.

      fetchBlock({
        attributes: attributes,
        query: {
          form: true
        }
      }).done(json => {
        this.setHtml(json.data.form);
      });
    }

    componentDidAppend() {
      super.componentDidAppend(); // Extract props.

      const {
        attributes,
        setAttributes
      } = this.props;
      const {
        $el
      } = this.state; // Callback for updating block data.

      function serializeData(silent = false) {
        const data = acf.serialize($el, `acf-${attributes.id}`);

        if (silent) {
          attributes.data = data;
        } else {
          setAttributes({
            data: data
          });
        }
      } // Add events.


      var timeout = false;
      $el.on('change keyup', function () {
        clearTimeout(timeout);
        timeout = setTimeout(serializeData, 300);
      }); // Ensure newly added block is saved with data.
      // Do it silently to avoid triggering a preview render.

      if (!attributes.data) {
        serializeData(true);
      }
    }

  }
  /**
   * BlockPreview Class.
   *
   * A react componenet to handle the block preview.
   *
   * @date	19/2/19
   * @since	5.7.12
   *
   * @param	string id the block id.
   * @return	void
   */


  class BlockPreview extends DynamicHTML {
    setup(props) {
      this.id = `BlockPreview-${props.attributes.id}`;
      var blockType = getBlockType(props.name);

      if (blockType.supports.jsx) {
        this.renderMethod = 'jsx';
      } //console.log('setup', this.id);

    }

    fetch(args = {}) {
      const {
        attributes = this.props.attributes,
        delay = 0
      } = args; // Remember attributes used to fetch HTML.

      this.setState({
        prevAttributes: attributes
      }); // Try preloaded data first.

      if (this.state.html === undefined) {
        const preloadedBlocks = acf.get('preloadedBlocks');

        if (preloadedBlocks && preloadedBlocks[attributes.id]) {
          this.setHtml(preloadedBlocks[attributes.id]);
          return;
        }
      } // Request AJAX and update HTML on complete.


      fetchBlock({
        attributes: attributes,
        query: {
          preview: true
        },
        delay: delay
      }).done(json => {
        this.setHtml(json.data.preview);
      });
    }

    componentDidAppend() {
      super.componentDidAppend(); // Extract props.

      const {
        attributes
      } = this.props;
      const {
        $el
      } = this.state; // Generate action friendly type.

      const type = attributes.name.replace('acf/', ''); // Do action.

      acf.doAction('render_block_preview', $el, attributes);
      acf.doAction(`render_block_preview/type=${type}`, $el, attributes);
    }

    shouldComponentUpdate(nextProps, nextState) {
      const nextAttributes = nextProps.attributes;
      const thisAttributes = this.props.attributes; // Update preview if block data has changed.

      if (!compareObjects(nextAttributes, thisAttributes)) {
        let delay = 0; // Delay fetch when editing className or anchor to simulate conscistent logic to custom fields.

        if (nextAttributes.className !== thisAttributes.className) {
          delay = 300;
        }

        if (nextAttributes.anchor !== thisAttributes.anchor) {
          delay = 300;
        }

        this.fetch({
          attributes: nextAttributes,
          delay: delay
        });
      }

      return super.shouldComponentUpdate(nextProps, nextState);
    }

    componentDidRemount() {
      super.componentDidRemount(); // Update preview if data has changed since last render (changing from "edit" to "preview").

      if (!compareObjects(this.state.prevAttributes, this.props.attributes)) {
        //console.log('componentDidRemount', this.id);
        this.fetch();
      }
    }

  }
  /**
   * Initializes ACF Blocks logic and registration.
   *
   * @since 5.9.0
   */


  function initialize() {
    // Add support for WordPress versions before 5.2.
    if (!wp.blockEditor) {
      wp.blockEditor = wp.editor;
    } // Register block types.


    var blockTypes = acf.get('blockTypes');

    if (blockTypes) {
      blockTypes.map(registerBlockType);
    }
  } // Run the initialize callback during the "prepare" action.
  // This ensures that all localized data is available and that blocks are registered before the WP editor has been instantiated.


  acf.addAction('prepare', initialize);
  /**
   * Returns a valid vertical alignment.
   *
   * @date	07/08/2020
   * @since	5.9.0
   *
   * @param	string align A vertical alignment.
   * @return	string
   */

  function validateVerticalAlignment(align) {
    const ALIGNMENTS = ['top', 'center', 'bottom'];
    const DEFAULT = 'top';
    return ALIGNMENTS.includes(align) ? align : DEFAULT;
  }
  /**
   * Returns a valid horizontal alignment.
   *
   * @date	07/08/2020
   * @since	5.9.0
   *
   * @param	string align A horizontal alignment.
   * @return	string
   */


  function validateHorizontalAlignment(align) {
    const ALIGNMENTS = ['left', 'center', 'right'];
    const DEFAULT = acf.get('rtl') ? 'right' : 'left';
    return ALIGNMENTS.includes(align) ? align : DEFAULT;
  }
  /**
   * Returns a valid matrix alignment.
   *
   * Written for "upgrade-path" compatibility from vertical alignment to matrix alignment. 
   * 
   * @date	07/08/2020
   * @since	5.9.0
   *
   * @param	string align A matrix alignment.
   * @return	string
   */


  function validateMatrixAlignment(align) {
    const DEFAULT = 'center center';

    if (align) {
      const [y, x] = align.split(' ');
      return validateVerticalAlignment(y) + ' ' + validateHorizontalAlignment(x);
    }

    return DEFAULT;
  } // Dependencies.


  const {
    AlignmentToolbar,
    BlockVerticalAlignmentToolbar
  } = wp.blockEditor;
  const BlockAlignmentMatrixToolbar = wp.blockEditor.__experimentalBlockAlignmentMatrixToolbar || wp.blockEditor.BlockAlignmentMatrixToolbar; // Gutenberg v10.x begins transition from Toolbar components to Control components.

  const BlockAlignmentMatrixControl = wp.blockEditor.__experimentalBlockAlignmentMatrixControl || wp.blockEditor.BlockAlignmentMatrixControl;
  /**
   * Appends extra attributes for block types that support align_content.
   *
   * @date	08/07/2020
   * @since	5.9.0
   *
   * @param	object attributes The block type attributes.
   * @return	object
   */

  function withAlignContentAttributes(attributes) {
    attributes.align_content = {
      type: 'string'
    };
    return attributes;
  }
  /**
   * A higher order component adding align_content editing functionality.
   *
   * @date	08/07/2020
   * @since	5.9.0
   *
   * @param	component OriginalBlockEdit The original BlockEdit component.
   * @param	object blockType The block type settings.
   * @return	component
   */


  function withAlignContentComponent(OriginalBlockEdit, blockType) {
    // Determine alignment vars
    let type = blockType.supports.align_content;
    let AlignmentComponent, validateAlignment;

    switch (type) {
      case 'matrix':
        AlignmentComponent = BlockAlignmentMatrixControl || BlockAlignmentMatrixToolbar;
        validateAlignment = validateMatrixAlignment;
        break;

      default:
        AlignmentComponent = BlockVerticalAlignmentToolbar;
        validateAlignment = validateVerticalAlignment;
        break;
    } // Ensure alignment component exists.


    if (AlignmentComponent === undefined) {
      console.warn(`The "${type}" alignment component was not found.`);
      return OriginalBlockEdit;
    } // Ensure correct block attribute data is sent in intial preview AJAX request.


    blockType.align_content = validateAlignment(blockType.align_content); // Return wrapped component.

    return class WrappedBlockEdit extends Component {
      render() {
        const {
          attributes,
          setAttributes
        } = this.props;
        const {
          align_content
        } = attributes;

        function onChangeAlignContent(align_content) {
          setAttributes({
            align_content: validateAlignment(align_content)
          });
        }

        return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(BlockControls, {
          group: "block"
        }, /*#__PURE__*/React.createElement(AlignmentComponent, {
          label: acf.__('Change content alignment'),
          value: validateAlignment(align_content),
          onChange: onChangeAlignContent
        })), /*#__PURE__*/React.createElement(OriginalBlockEdit, this.props));
      }

    };
  }
  /**
   * Appends extra attributes for block types that support align_text.
   *
   * @date	08/07/2020
   * @since	5.9.0
   *
   * @param	object attributes The block type attributes.
   * @return	object
   */


  function withAlignTextAttributes(attributes) {
    attributes.align_text = {
      type: 'string'
    };
    return attributes;
  }
  /**
   * A higher order component adding align_text editing functionality.
   *
   * @date	08/07/2020
   * @since	5.9.0
   *
   * @param	component OriginalBlockEdit The original BlockEdit component.
   * @param	object blockType The block type settings.
   * @return	component
   */


  function withAlignTextComponent(OriginalBlockEdit, blockType) {
    const validateAlignment = validateHorizontalAlignment; // Ensure correct block attribute data is sent in intial preview AJAX request.

    blockType.align_text = validateAlignment(blockType.align_text); // Return wrapped component.

    return class WrappedBlockEdit extends Component {
      render() {
        const {
          attributes,
          setAttributes
        } = this.props;
        const {
          align_text
        } = attributes;

        function onChangeAlignText(align_text) {
          setAttributes({
            align_text: validateAlignment(align_text)
          });
        }

        return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(BlockControls, null, /*#__PURE__*/React.createElement(AlignmentToolbar, {
          value: validateAlignment(align_text),
          onChange: onChangeAlignText
        })), /*#__PURE__*/React.createElement(OriginalBlockEdit, this.props));
      }

    };
  }
})(jQuery);