UNPKG

@atlaskit/editor-plugin-mentions

Version:

Mentions plugin for @atlaskit/editor-core

228 lines (223 loc) 8.56 kB
/* InviteItemWithEmailDomain.tsx generated by @compiled/babel-plugin v0.39.1 */ import _extends from "@babel/runtime/helpers/extends"; import "./InviteItemWithEmailDomain.compiled.css"; import { ax, ix } from "@compiled/react/runtime"; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { FormattedMessage, injectIntl } from 'react-intl'; import { mentionMessages as messages } from '@atlaskit/editor-common/messages'; import EmailIcon from '@atlaskit/icon/core/email'; import StatusErrorIcon from '@atlaskit/icon/core/status-error'; import Pressable from '@atlaskit/primitives/pressable'; import { isValidEmail } from '@atlaskit/user-picker'; const mentionItemStyle = null; const mentionItemSelectedStyle = null; const displayNameStyles = { localPart: "_1i4q1hna", domainPart: "_1e0c1o8l _p12f1osq _1i4q1hna" }; const DisplayName = ({ name }) => { const atIndex = name.indexOf('@'); if (atIndex === -1) { return /*#__PURE__*/React.createElement("span", { className: ax([displayNameStyles.localPart]) }, name); } const localPart = name.slice(0, atIndex); const domainPart = name.slice(atIndex); // includes the @ return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("span", { className: ax([displayNameStyles.localPart]) }, localPart), /*#__PURE__*/React.createElement("span", { className: ax([displayNameStyles.domainPart]) }, domainPart)); }; const style = { byline: "_19pkv77o", rowStyle: "_1reo15vq _18m915vq _4cvr1h6o _1e0c1txw _2lx2vrvc _1n261g80 _ca0q12x7 _n3td12x7 _19bvutpp _u5f3utpp _1bto1l2s _s7n4nkob", avatar: "_16jlidpf _1o9zkb7n _i0dl1wug _1e0c1txw _4cvr1h6o _1bah1h6o _kqswh2mm _1bsb14no _4t3i14no", nameSection: "_16jlkb7n _1o9zkb7n _i0dlf1ug _1ul9idpf _18u0utpp _2hwxu2gc _syazazsu", capitalize: "_1p1d1dk0", inviteButton: "_2rko12b0 _11c8fhey _1h6d1l7x _1dqonqa1 _189ee4h9 _1e0c116y _4cvr1h6o _1bah1h6o _ca0q12x7 _u5f3utpp _n3td12x7 _19bvutpp _syazazsu _k48p1wq8 _4t3iviql _bfhksm61 _cun9187o _irr31dpa" }; const VALID_OPTION = 'VALID'; const POTENTIAL_OPTION = 'POTENTIAL'; // eslint-disable-next-line require-unicode-regexp const COMPLETE_EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/i; const ERROR_DELAY_MS = 750; /** * Truncates an email-like string to fit within a max length by inserting an * ellipsis into the middle of the local part (before the @). * * Preserves the full `@domain` suffix so users can always see * which domain the invite targets. */ export const truncateInviteOption = (value, maxLength = 34) => { if (value.length <= maxLength) { return value; } const atIndex = value.lastIndexOf('@'); if (atIndex === -1) { // No @ — truncate to maxLength and append ellipsis const ellipsis = '\u2026'; return `${value.slice(0, maxLength - 1)}${ellipsis}`; } const domain = value.slice(atIndex); // includes @ const local = value.slice(0, atIndex); const ellipsis = '\u2026'; const available = maxLength - domain.length - ellipsis.length; if (available <= 0) { // Domain alone exceeds budget — show as much as we can return `${ellipsis}${domain.slice(-(maxLength - ellipsis.length))}`; } const leading = Math.ceil(available / 2); const trailing = Math.floor(available / 2); const truncatedLocal = trailing > 0 ? `${local.slice(0, leading)}${ellipsis}${local.slice(local.length - trailing)}` : `${local.slice(0, leading)}${ellipsis}`; return `${truncatedLocal}${domain}`; }; const getInviteOption = (inputValue, suggestedEmailDomain) => { if (inputValue.includes(' ') && inputValue.includes('@')) { return truncateInviteOption(inputValue); } const isEmail = inputValue && [VALID_OPTION, POTENTIAL_OPTION].includes(isValidEmail(inputValue)); if (isEmail || !suggestedEmailDomain) { return truncateInviteOption(inputValue); } return truncateInviteOption(`${inputValue.toLocaleLowerCase()}@${suggestedEmailDomain}`); }; const getIsEmailValid = inputValue => { if (!inputValue || inputValue.length === 0) { return false; } if (inputValue.includes(' ')) { return false; } if (inputValue.includes('@') && !COMPLETE_EMAIL_REGEX.test(inputValue)) { return false; } return true; }; export const INVITE_ITEM_DESCRIPTION = { id: 'invite-teammate' }; const InviteItemWithEmailDomain = ({ productName, onMount, onMouseEnter, onSelection, selected, userRole, query = '', emailDomain, intl }) => { const [showErrorIcon, setShowErrorIcon] = useState(query.length !== 0 && !getIsEmailValid(query)); const timeoutRef = useRef(); const possibleEmail = getInviteOption(query, emailDomain); const isEmailValid = getIsEmailValid(query); const getByline = () => { if (showErrorIcon) { return intl.formatMessage(messages.inviteTeammateInvalidEmail); } if (userRole === 'admin') { return /*#__PURE__*/React.createElement(FormattedMessage // Ignored via go/ees005 // eslint-disable-next-line react/jsx-props-no-spreading , _extends({}, messages.inviteItemTitle, { // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) values: { userRole: userRole || 'basic', productName: /*#__PURE__*/React.createElement("span", { "data-testid": "capitalized-message", className: ax([style.capitalize]) }, productName) } })); } return intl.formatMessage(messages.sendInvite); }; const onInviteButtonClick = useCallback( // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any event => { if (onSelection) { event.preventDefault(); onSelection(INVITE_ITEM_DESCRIPTION, event); } }, [onSelection]); const onItemMouseEnter = useCallback( // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any event => { if (onMouseEnter) { onMouseEnter(INVITE_ITEM_DESCRIPTION, event); } }, [onMouseEnter]); const onItemFocus = useCallback( // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any event => { if (onMouseEnter) { onMouseEnter(INVITE_ITEM_DESCRIPTION, event); } }, [onMouseEnter]); useEffect(() => { if (onMount) { onMount(); } }, [onMount]); // Debounce error icon display: only show error after user stops typing invalid input useEffect(() => { // Clear existing timeout if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = undefined; } // Reset error icon immediately if input becomes valid or empty if (isEmailValid || query.length === 0) { setShowErrorIcon(false); } else { // Debounce: only show error icon after delay if input remains invalid timeoutRef.current = setTimeout(() => { setShowErrorIcon(true); }, ERROR_DELAY_MS); } // Cleanup timeout on unmount or when query changes return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } }; }, [query, isEmailValid]); const displayName = query && emailDomain ? possibleEmail : undefined; return displayName && /*#__PURE__*/React.createElement("div", { onMouseEnter: onItemMouseEnter, onFocus: onItemFocus, "data-id": INVITE_ITEM_DESCRIPTION.id, className: ax(["_1reo15vq _18m915vq _bfhk1j28 _1e0c1ule _2mzuglyw", selected && "_bfhk1dpa"]) }, /*#__PURE__*/React.createElement("div", { className: ax([style.rowStyle]) }, /*#__PURE__*/React.createElement("span", { className: ax([style.avatar]) }, showErrorIcon ? /*#__PURE__*/React.createElement(StatusErrorIcon, { label: "Error", color: "var(--ds-icon-danger, #C9372C)" }) : /*#__PURE__*/React.createElement(EmailIcon, { label: "Email", color: "var(--ds-icon-subtle, #505258)" })), /*#__PURE__*/React.createElement("div", { "data-testid": "name-section", className: ax([style.nameSection]) }, /*#__PURE__*/React.createElement(DisplayName, { name: displayName }), /*#__PURE__*/React.createElement("div", { className: ax([style.byline]) }, getByline())), /*#__PURE__*/React.createElement(Pressable, { onClick: onInviteButtonClick, xcss: style.inviteButton, isDisabled: showErrorIcon }, intl.formatMessage(messages.inviteButton)))); }; // eslint-disable-next-line @typescript-eslint/ban-types const _default_1 = injectIntl(InviteItemWithEmailDomain); export default _default_1;