Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ const emailAddress = 'edx@example.com';
const emailAddresses = ['foo@example.com', 'bar@example.com', 'baz@example.com'];
const subject = 'subject';
const body = 'body';
const content = 'content';
const children = 'content';

const baseProps = { subject, body, content };
const baseProps = { subject, body, children };

function MailtoLinkWrapper(props) {
function MailtoLinkWrapper(props: React.ComponentProps<typeof MailtoLink>) {
return (
<IntlProvider locale="en">
<MailtoLink {...props} />
Expand Down Expand Up @@ -55,7 +55,7 @@ describe('correct rendering', () => {
});

it('renders empty mailtoLink', () => {
const { getByText } = render(<MailtoLinkWrapper content={content} />);
const { getByText } = render(<MailtoLinkWrapper>{children}</MailtoLinkWrapper>);
const linkElement = getByText('content');
expect(linkElement.getAttribute('href')).toEqual('mailto:');
});
Expand Down
103 changes: 43 additions & 60 deletions src/MailtoLink/index.jsx → src/MailtoLink/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import React from 'react';
import PropTypes from 'prop-types';
import emailPropType from 'email-prop-type';
import isRequiredIf from 'react-proptype-conditional-require';
import mailtoLink from 'mailto-link';
import classNames from 'classnames';

Expand All @@ -11,21 +8,50 @@ import withDeprecatedProps, { DeprTypes } from '../withDeprecatedProps';
export const MAIL_TO_LINK_EXTERNAL_LINK_ALTERNATIVE_TEXT = 'Dismiss';
export const MAIL_TO_LINK_EXTERNAL_LINK_TITLE = 'Opens in a new tab';

const MailtoLink = React.forwardRef((props, ref) => {
const {
to,
cc,
bcc,
subject,
body,
children,
target,
onClick,
externalLink,
className,
...attrs
} = props;
interface MailtoLinkProps {
/** Content of the MailtoLink */
children: React.ReactNode;
/** Custom class names for the MailtoLink */
className?: string;
/** Specifies the email's recipients */
to?: string | string[];
/** Specifies the email's carbon copy recipients */
cc?: string | string[];
/** Specifies the email's blind carbon copy recipients */
bcc?: string | string[];
/** Specifies the email's subject */
subject?: string;
/** Specifies the email's body */
body?: string;
/** Specifies where the link should open. The default behavior is `_self`,
* which means that the URL will be loaded into the same browsing context as the current one */
target?: '_self' | '_blank';
/** Specifies the callback function when the link is clicked */
onClick?: (event: React.MouseEvent<HTMLAnchorElement>) => void;
/** The object that contains the `alternativeText` and `title` fields which specify
* the text and title for links with a `_blank` target (which loads the URL in a new browsing context). */
externalLink?: {
alternativeText?: string;
title?: string;
};
}

const MailtoLink = React.forwardRef<HTMLAnchorElement, MailtoLinkProps>(({
children,
className,
to = [],
cc = [],
bcc = [],
subject = '',
body = '',
target = '_self',
onClick,
externalLink = {
alternativeText: MAIL_TO_LINK_EXTERNAL_LINK_ALTERNATIVE_TEXT,
title: MAIL_TO_LINK_EXTERNAL_LINK_TITLE,
},
...attrs
}, ref) => {
const externalLinkAlternativeText = externalLink.alternativeText;
const externalLinkTitle = externalLink.title;
const destination = mailtoLink({
Expand All @@ -52,49 +78,6 @@ const MailtoLink = React.forwardRef((props, ref) => {
);
});

MailtoLink.defaultProps = {
to: [],
cc: [],
bcc: [],
subject: '',
body: '',
target: '_self',
onClick: null,
externalLink: {
alternativeText: MAIL_TO_LINK_EXTERNAL_LINK_ALTERNATIVE_TEXT,
title: MAIL_TO_LINK_EXTERNAL_LINK_TITLE,
},
className: undefined,
};

MailtoLink.propTypes = {
/** Content of the ``MailToLink`` */
children: PropTypes.node.isRequired,
/** Custom class names for the ``MailToLink`` */
className: PropTypes.string,
/** Specifies the email's recipients */
to: PropTypes.oneOfType([PropTypes.arrayOf(emailPropType), emailPropType]),
/** Specifies the email's carbon copy recipients */
cc: PropTypes.oneOfType([PropTypes.arrayOf(emailPropType), emailPropType]),
/** Specifies the email's blind carbon copy recipients */
bcc: PropTypes.oneOfType([PropTypes.arrayOf(emailPropType), emailPropType]),
/** Specifies the email's subject */
subject: PropTypes.string,
/** Specifies the email's body */
body: PropTypes.string,
/** Specifies where the link should open. The default behavior is `_self`,
* which means that the URL will be loaded into the same browsing context as the current one */
target: PropTypes.string,
/** Specifies the callback function when the link is clicked */
onClick: PropTypes.func,
/** The object that contains the `alternativeText` and `title` fields which specify
* the text and title for links with a `_blank` target (which loads the URL in a new browsing context). */
externalLink: PropTypes.shape({
alternativeText: isRequiredIf(PropTypes.string, props => props.target === '_blank'),
title: isRequiredIf(PropTypes.string, props => props.target === '_blank'),
}),
};

export default withDeprecatedProps(MailtoLink, 'MailtoLink', {
content: {
deprType: DeprTypes.MOVED,
Expand Down
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export { default as Annotation } from './Annotation';
export { default as Avatar } from './Avatar';
export { default as AvatarButton } from './AvatarButton';
export { default as Badge } from './Badge';
export { default as MailtoLink, MAIL_TO_LINK_EXTERNAL_LINK_ALTERNATIVE_TEXT, MAIL_TO_LINK_EXTERNAL_LINK_TITLE } from './MailtoLink';
export { default as Breadcrumb } from './Breadcrumb';
export { default as Bubble } from './Bubble';
export { default as Button, ButtonGroup, ButtonToolbar } from './Button';
Expand Down Expand Up @@ -98,8 +99,7 @@ export { default as Fade } from './Fade';
export { default as IconButtonToggle } from './IconButtonToggle';
// @ts-ignore: has yet to be converted to TypeScript
export { default as Image, Figure } from './Image';
// @ts-ignore: has yet to be converted to TypeScript
export { default as MailtoLink, MAIL_TO_LINK_EXTERNAL_LINK_ALTERNATIVE_TEXT, MAIL_TO_LINK_EXTERNAL_LINK_TITLE } from './MailtoLink';

// @ts-ignore: has yet to be converted to TypeScript
export { default as Media } from './Media';
// @ts-ignore: has yet to be converted to TypeScript
Expand Down