/**
 * External dependencies
 */
import clsx from 'clsx';

/**
 * Internal dependencies
 */
import { NEW_TAB_TARGET, NOFOLLOW_REL } from './constants';
import { getUpdatedLinkAttributes } from './get-updated-link-attributes';
import removeAnchorTag from '../utils/remove-anchor-tag';

/**
 * WordPress dependencies
 */
import { __ } from '@wordpress/i18n';
import { useEffect, useState, useRef, useMemo } from '@wordpress/element';
import { Button, ButtonGroup, PanelBody, TextControl, ToolbarButton, Popover } from '@wordpress/components';
import { AlignmentControl, BlockControls, InspectorControls, RichText, useBlockProps, __experimentalUseBorderProps as useBorderProps, __experimentalUseColorProps as useColorProps, __experimentalGetSpacingClassesAndStyles as useSpacingProps, __experimentalGetShadowClassesAndStyles as useShadowProps, __experimentalLinkControl as LinkControl, __experimentalGetElementClassName, store as blockEditorStore, useBlockEditingMode } from '@wordpress/block-editor';
import { displayShortcut, isKeyboardEvent, ENTER } from '@wordpress/keycodes';
import { link, linkOff } from '@wordpress/icons';
import { createBlock, cloneBlock, getDefaultBlockName, getBlockBindingsSource } from '@wordpress/blocks';
import { useMergeRefs, useRefEffect } from '@wordpress/compose';
import { useSelect, useDispatch } from '@wordpress/data';
import { jsxs as _jsxs } from "react/jsx-runtime";
import { jsx as _jsx } from "react/jsx-runtime";
import { Fragment as _Fragment } from "react/jsx-runtime";
const LINK_SETTINGS = [...LinkControl.DEFAULT_LINK_SETTINGS, {
  id: 'nofollow',
  title: __('Mark as nofollow')
}];
function useEnter(props) {
  const {
    replaceBlocks,
    selectionChange
  } = useDispatch(blockEditorStore);
  const {
    getBlock,
    getBlockRootClientId,
    getBlockIndex
  } = useSelect(blockEditorStore);
  const propsRef = useRef(props);
  propsRef.current = props;
  return useRefEffect(element => {
    function onKeyDown(event) {
      if (event.defaultPrevented || event.keyCode !== ENTER) {
        return;
      }
      const {
        content,
        clientId
      } = propsRef.current;
      if (content.length) {
        return;
      }
      event.preventDefault();
      const topParentListBlock = getBlock(getBlockRootClientId(clientId));
      const blockIndex = getBlockIndex(clientId);
      const head = cloneBlock({
        ...topParentListBlock,
        innerBlocks: topParentListBlock.innerBlocks.slice(0, blockIndex)
      });
      const middle = createBlock(getDefaultBlockName());
      const after = topParentListBlock.innerBlocks.slice(blockIndex + 1);
      const tail = after.length ? [cloneBlock({
        ...topParentListBlock,
        innerBlocks: after
      })] : [];
      replaceBlocks(topParentListBlock.clientId, [head, middle, ...tail], 1);
      // We manually change the selection here because we are replacing
      // a different block than the selected one.
      selectionChange(middle.clientId);
    }
    element.addEventListener('keydown', onKeyDown);
    return () => {
      element.removeEventListener('keydown', onKeyDown);
    };
  }, []);
}
function WidthPanel({
  selectedWidth,
  setAttributes
}) {
  function handleChange(newWidth) {
    // Check if we are toggling the width off
    const width = selectedWidth === newWidth ? undefined : newWidth;

    // Update attributes.
    setAttributes({
      width
    });
  }
  return /*#__PURE__*/_jsx(PanelBody, {
    title: __('Settings'),
    children: /*#__PURE__*/_jsx(ButtonGroup, {
      "aria-label": __('Button width'),
      children: [25, 50, 75, 100].map(widthValue => {
        return /*#__PURE__*/_jsxs(Button, {
          size: "small",
          variant: widthValue === selectedWidth ? 'primary' : undefined,
          onClick: () => handleChange(widthValue),
          children: [widthValue, "%"]
        }, widthValue);
      })
    })
  });
}
function ButtonEdit(props) {
  const {
    attributes,
    setAttributes,
    className,
    isSelected,
    onReplace,
    mergeBlocks,
    clientId,
    context
  } = props;
  const {
    tagName,
    textAlign,
    linkTarget,
    placeholder,
    rel,
    style,
    text,
    url,
    width,
    metadata
  } = attributes;
  const TagName = tagName || 'a';
  function onKeyDown(event) {
    if (isKeyboardEvent.primary(event, 'k')) {
      startEditing(event);
    } else if (isKeyboardEvent.primaryShift(event, 'k')) {
      unlink();
      richTextRef.current?.focus();
    }
  }

  // Use internal state instead of a ref to make sure that the component
  // re-renders when the popover's anchor updates.
  const [popoverAnchor, setPopoverAnchor] = useState(null);
  const borderProps = useBorderProps(attributes);
  const colorProps = useColorProps(attributes);
  const spacingProps = useSpacingProps(attributes);
  const shadowProps = useShadowProps(attributes);
  const ref = useRef();
  const richTextRef = useRef();
  const blockProps = useBlockProps({
    ref: useMergeRefs([setPopoverAnchor, ref]),
    onKeyDown
  });
  const blockEditingMode = useBlockEditingMode();
  const [isEditingURL, setIsEditingURL] = useState(false);
  const isURLSet = !!url;
  const opensInNewTab = linkTarget === NEW_TAB_TARGET;
  const nofollow = !!rel?.includes(NOFOLLOW_REL);
  const isLinkTag = 'a' === TagName;
  function startEditing(event) {
    event.preventDefault();
    setIsEditingURL(true);
  }
  function unlink() {
    setAttributes({
      url: undefined,
      linkTarget: undefined,
      rel: undefined
    });
    setIsEditingURL(false);
  }
  useEffect(() => {
    if (!isSelected) {
      setIsEditingURL(false);
    }
  }, [isSelected]);

  // Memoize link value to avoid overriding the LinkControl's internal state.
  // This is a temporary fix. See https://github.com/WordPress/gutenberg/issues/51256.
  const linkValue = useMemo(() => ({
    url,
    opensInNewTab,
    nofollow
  }), [url, opensInNewTab, nofollow]);
  const useEnterRef = useEnter({
    content: text,
    clientId
  });
  const mergedRef = useMergeRefs([useEnterRef, richTextRef]);
  const {
    lockUrlControls = false
  } = useSelect(select => {
    if (!isSelected) {
      return {};
    }
    const blockBindingsSource = getBlockBindingsSource(metadata?.bindings?.url?.source);
    return {
      lockUrlControls: !!metadata?.bindings?.url && !blockBindingsSource?.canUserEditValue?.({
        select,
        context,
        args: metadata?.bindings?.url?.args
      })
    };
  }, [context, isSelected, metadata?.bindings?.url]);
  return /*#__PURE__*/_jsxs(_Fragment, {
    children: [/*#__PURE__*/_jsx("div", {
      ...blockProps,
      className: clsx(blockProps.className, {
        [`has-custom-width wp-block-button__width-${width}`]: width,
        [`has-custom-font-size`]: blockProps.style.fontSize
      }),
      children: /*#__PURE__*/_jsx(RichText, {
        ref: mergedRef,
        "aria-label": __('Button text'),
        placeholder: placeholder || __('Add text…'),
        value: text,
        onChange: value => setAttributes({
          text: removeAnchorTag(value)
        }),
        withoutInteractiveFormatting: true,
        className: clsx(className, 'wp-block-button__link', colorProps.className, borderProps.className, {
          [`has-text-align-${textAlign}`]: textAlign,
          // For backwards compatibility add style that isn't
          // provided via block support.
          'no-border-radius': style?.border?.radius === 0
        }, __experimentalGetElementClassName('button')),
        style: {
          ...borderProps.style,
          ...colorProps.style,
          ...spacingProps.style,
          ...shadowProps.style
        },
        onReplace: onReplace,
        onMerge: mergeBlocks,
        identifier: "text"
      })
    }), /*#__PURE__*/_jsxs(BlockControls, {
      group: "block",
      children: [blockEditingMode === 'default' && /*#__PURE__*/_jsx(AlignmentControl, {
        value: textAlign,
        onChange: nextAlign => {
          setAttributes({
            textAlign: nextAlign
          });
        }
      }), !isURLSet && isLinkTag && !lockUrlControls && /*#__PURE__*/_jsx(ToolbarButton, {
        name: "link",
        icon: link,
        title: __('Link'),
        shortcut: displayShortcut.primary('k'),
        onClick: startEditing
      }), isURLSet && isLinkTag && !lockUrlControls && /*#__PURE__*/_jsx(ToolbarButton, {
        name: "link",
        icon: linkOff,
        title: __('Unlink'),
        shortcut: displayShortcut.primaryShift('k'),
        onClick: unlink,
        isActive: true
      })]
    }), isLinkTag && isSelected && (isEditingURL || isURLSet) && !lockUrlControls && /*#__PURE__*/_jsx(Popover, {
      placement: "bottom",
      onClose: () => {
        setIsEditingURL(false);
        richTextRef.current?.focus();
      },
      anchor: popoverAnchor,
      focusOnMount: isEditingURL ? 'firstElement' : false,
      __unstableSlotName: "__unstable-block-tools-after",
      shift: true,
      children: /*#__PURE__*/_jsx(LinkControl, {
        value: linkValue,
        onChange: ({
          url: newURL,
          opensInNewTab: newOpensInNewTab,
          nofollow: newNofollow
        }) => setAttributes(getUpdatedLinkAttributes({
          rel,
          url: newURL,
          opensInNewTab: newOpensInNewTab,
          nofollow: newNofollow
        })),
        onRemove: () => {
          unlink();
          richTextRef.current?.focus();
        },
        forceIsEditingLink: isEditingURL,
        settings: LINK_SETTINGS
      })
    }), /*#__PURE__*/_jsx(InspectorControls, {
      children: /*#__PURE__*/_jsx(WidthPanel, {
        selectedWidth: width,
        setAttributes: setAttributes
      })
    }), /*#__PURE__*/_jsx(InspectorControls, {
      group: "advanced",
      children: isLinkTag && /*#__PURE__*/_jsx(TextControl, {
        __next40pxDefaultSize: true,
        __nextHasNoMarginBottom: true,
        label: __('Link rel'),
        value: rel || '',
        onChange: newRel => setAttributes({
          rel: newRel
        })
      })
    })]
  });
}
export default ButtonEdit;
//# sourceMappingURL=edit.js.map