diff --git a/packages/js/email-editor/src/components/personalization-tags/index.scss b/packages/js/email-editor/src/components/personalization-tags/index.scss index ba0d92c673..308571dae5 100644 --- a/packages/js/email-editor/src/components/personalization-tags/index.scss +++ b/packages/js/email-editor/src/components/personalization-tags/index.scss @@ -71,3 +71,17 @@ } } } + +.mailpoet-personalization-tag-popover { + align-items: center; + display: flex; + justify-content: center; + + .mailpoet-personalization-tag-popover__content { + padding: 8px; + width: 400px; + } + .mailpoet-personalization-tag-popover__content-button { + text-align: center; + } +} diff --git a/packages/js/email-editor/src/components/personalization-tags/personalization-tags-popover.tsx b/packages/js/email-editor/src/components/personalization-tags/personalization-tags-popover.tsx new file mode 100644 index 0000000000..6220708910 --- /dev/null +++ b/packages/js/email-editor/src/components/personalization-tags/personalization-tags-popover.tsx @@ -0,0 +1,97 @@ +import { useEffect, useState } from '@wordpress/element'; +import { Popover, Button, TextControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +type PersonalizationTagsPopoverProps = { + contentRef: React.RefObject< HTMLElement >; + onUpdate: ( originalValue: string, updatedValue: string ) => void; +}; + +/** + * Component to display a popover with a text control to update personalization tags. + * The popover is displayed when a user clicks on a personalization tag in the editor. + * @param root0 + * @param root0.contentRef Reference to the container where the popover should be displayed + * @param root0.onUpdate Callback to update the personalization tag + */ +const PersonalizationTagsPopover = ( { + contentRef, + onUpdate, +}: PersonalizationTagsPopoverProps ) => { + const [ isPopoverVisible, setIsPopoverVisible ] = useState( false ); + const [ popoverAnchor, setPopoverAnchor ] = useState< HTMLElement | null >( + null + ); + const [ updatedValue, setUpdatedValue ] = useState( '' ); + const [ originalValue, setOriginalValue ] = useState( '' ); + + useEffect( () => { + if ( ! contentRef || ! contentRef.current ) { + return undefined; + } + + const container = contentRef.current; + + // Handle clicks within the referenced container + const handleContainerClick = ( event: Event ) => { + const target = event.target as HTMLElement; + const commentSpan = target.closest( + 'span[data-rich-text-comment]' + ) as HTMLElement; + + if ( commentSpan ) { + // Remove brackets from the text content for better user experience + const textContent = commentSpan.innerText.replace( + /^\[|\]$/g, + '' + ); + setOriginalValue( textContent ); + setUpdatedValue( textContent ); + setPopoverAnchor( commentSpan ); + setIsPopoverVisible( true ); + } + }; + + // Add the event listener to the container + container.addEventListener( 'click', handleContainerClick ); + + // Cleanup function to remove the event listener on unmount + return () => { + container.removeEventListener( 'click', handleContainerClick ); + }; + }, [ contentRef ] ); + + return ( + <> + { isPopoverVisible && ( + setIsPopoverVisible( false ) } + anchorRef={ popoverAnchor } + className="mailpoet-personalization-tag-popover" + > +
+ setUpdatedValue( value ) } + /> +
+ +
+
+
+ ) } + + ); +}; + +export { PersonalizationTagsPopover };