-
Notifications
You must be signed in to change notification settings - Fork 279
/
Copy pathLink.tsx
88 lines (77 loc) · 2.38 KB
/
Link.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import React, { forwardRef } from 'react';
import PropTypes from 'prop-types';
import NextLink from 'next/link';
import {
Link as ReactLink,
LinkFieldValue,
LinkField,
LinkProps as ReactLinkProps,
LinkPropTypes,
withMetadata,
} from '@sitecore-jss/sitecore-jss-react';
export type LinkProps = ReactLinkProps & {
/**
* If `href` match with `internalLinkMatcher` regexp, then it's internal link and NextLink will be rendered
* @default /^\//g
*/
internalLinkMatcher?: RegExp;
};
export const Link = withMetadata(
// eslint-disable-next-line react/display-name
forwardRef<HTMLAnchorElement, LinkProps>((props: LinkProps, ref): JSX.Element | null => {
const {
field,
editable,
children,
internalLinkMatcher = /^\//g,
showLinkTextWithChildrenPresent,
...htmlLinkProps
} = props;
if (
!field ||
(!(field as LinkFieldValue).editable && !field.value && !(field as LinkFieldValue).href)
) {
return null;
}
const value = ((field as LinkFieldValue).href
? field
: (field as LinkField).value) as LinkFieldValue;
const { href, querystring, anchor } = value;
const isEditing = editable && (field as LinkFieldValue).editable;
if (href && !isEditing) {
const text = showLinkTextWithChildrenPresent || !children ? value.text || value.href : null;
// determine if a link is a route or not.
if (internalLinkMatcher.test(href)) {
return (
<NextLink
href={{ pathname: href, query: querystring, hash: anchor }}
key="link"
locale={false}
title={value.title}
target={value.target}
className={value.class}
{...htmlLinkProps}
ref={ref}
>
{text}
{children}
</NextLink>
);
}
}
// prevent passing internalLinkMatcher as it is an invalid DOM element prop
const reactLinkProps = { ...props };
delete reactLinkProps.internalLinkMatcher;
// we've already rendered the metadata wrapper - so set metadata to null to prevent duplicate wrapping
reactLinkProps.field.metadata = null;
return <ReactLink {...reactLinkProps} ref={ref} />;
})
);
Link.defaultProps = {
editable: true,
};
Link.displayName = 'NextLink';
Link.propTypes = {
internalLinkMatcher: PropTypes.instanceOf(RegExp),
...LinkPropTypes,
};