@atlaskit/editor-plugin-mentions
Version:
Mentions plugin for @atlaskit/editor-core
185 lines (180 loc) • 6.74 kB
JavaScript
/* 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 { isValidEmail } from '@atlaskit/user-picker';
const mentionItemStyle = null;
const mentionItemSelectedStyle = null;
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 _syazazsu",
capitalize: "_1p1d1dk0"
};
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;
const getInviteOption = (inputValue, suggestedEmailDomain) => {
if (inputValue.includes(' ') && inputValue.includes('@')) {
return inputValue;
}
const isEmail = inputValue && [VALID_OPTION, POTENTIAL_OPTION].includes(isValidEmail(inputValue));
if (isEmail || !suggestedEmailDomain) {
return inputValue;
}
return `${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(false);
const timeoutRef = useRef();
const possibleEmail = getInviteOption(query, emailDomain);
const isEmailValid = getIsEmailValid(query);
// Use debounced error state for icon and byline display
const shouldShowError = !isEmailValid && showErrorIcon;
// Use debounced error state for byline: show invalid message only after delay
const isValidForByline = isEmailValid || !shouldShowError;
const getByline = () => {
if (!isValidForByline) {
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 onSelected = useCallback(
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
event => {
if (onSelection) {
// For mouse events, only handle left click
if ('button' in event && event.button !== 0) {
return;
}
// For keyboard events, only handle Enter and Space
if ('key' in event && event.key !== 'Enter' && event.key !== ' ') {
return;
}
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", {
role: "button",
tabIndex: 0,
onMouseDown: onSelected,
onKeyDown: onSelected,
onMouseEnter: onItemMouseEnter,
onFocus: onItemFocus,
"data-id": INVITE_ITEM_DESCRIPTION.id,
className: ax(["_1reo15vq _18m915vq _bfhk1j28 _1e0c1ule _2mzuglyw _80omtlke", selected && "_bfhk1dpa"])
}, /*#__PURE__*/React.createElement("div", {
className: ax([style.rowStyle])
}, /*#__PURE__*/React.createElement("span", {
className: ax([style.avatar])
}, shouldShowError ? /*#__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(React.Fragment, null, /*#__PURE__*/React.createElement("div", null, displayName), /*#__PURE__*/React.createElement("div", {
className: ax([style.byline])
}, getByline())))));
};
// eslint-disable-next-line @typescript-eslint/ban-types
const _default_1 = injectIntl(InviteItemWithEmailDomain);
export default _default_1;