@khanacademy/wonder-blocks-link 6.1.7 → 6.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/package.json +5 -5
- package/src/__tests__/__snapshots__/custom-snapshot.test.tsx.snap +0 -820
- package/src/__tests__/custom-snapshot.test.tsx +0 -79
- package/src/components/__tests__/link.test.tsx +0 -559
- package/src/components/__tests__/link.typestest.tsx +0 -40
- package/src/components/link-core.tsx +0 -289
- package/src/components/link.tsx +0 -291
- package/src/index.ts +0 -3
- package/tsconfig-build.json +0 -15
- package/tsconfig-build.tsbuildinfo +0 -1
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import {StyleSheet} from "aphrodite";
|
|
3
|
-
import {Link} from "react-router-dom";
|
|
4
|
-
import {__RouterContext} from "react-router";
|
|
5
|
-
|
|
6
|
-
import {addStyle} from "@khanacademy/wonder-blocks-core";
|
|
7
|
-
import {mix, fade, color, spacing} from "@khanacademy/wonder-blocks-tokens";
|
|
8
|
-
import {isClientSideUrl} from "@khanacademy/wonder-blocks-clickable";
|
|
9
|
-
import {PhosphorIcon} from "@khanacademy/wonder-blocks-icon";
|
|
10
|
-
import externalLinkIcon from "@phosphor-icons/core/bold/arrow-square-out-bold.svg";
|
|
11
|
-
|
|
12
|
-
import type {
|
|
13
|
-
ChildrenProps,
|
|
14
|
-
ClickableState,
|
|
15
|
-
} from "@khanacademy/wonder-blocks-clickable";
|
|
16
|
-
import type {StyleDeclaration} from "aphrodite";
|
|
17
|
-
import type {SharedProps} from "./link";
|
|
18
|
-
|
|
19
|
-
type Props = SharedProps &
|
|
20
|
-
ChildrenProps &
|
|
21
|
-
ClickableState & {
|
|
22
|
-
href: string;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const StyledAnchor = addStyle("a");
|
|
26
|
-
const StyledLink = addStyle(Link);
|
|
27
|
-
|
|
28
|
-
const LinkCore = React.forwardRef(function LinkCore(
|
|
29
|
-
props: Props,
|
|
30
|
-
ref: React.ForwardedRef<typeof Link | HTMLAnchorElement>,
|
|
31
|
-
) {
|
|
32
|
-
const renderInner = (router: any): React.ReactNode => {
|
|
33
|
-
const {
|
|
34
|
-
children,
|
|
35
|
-
skipClientNav,
|
|
36
|
-
focused,
|
|
37
|
-
hovered,
|
|
38
|
-
href,
|
|
39
|
-
inline = false,
|
|
40
|
-
kind = "primary",
|
|
41
|
-
light = false,
|
|
42
|
-
visitable = false,
|
|
43
|
-
pressed,
|
|
44
|
-
style,
|
|
45
|
-
testId,
|
|
46
|
-
waiting: _,
|
|
47
|
-
target,
|
|
48
|
-
startIcon,
|
|
49
|
-
endIcon,
|
|
50
|
-
...restProps
|
|
51
|
-
} = props;
|
|
52
|
-
|
|
53
|
-
const linkStyles = _generateStyles(inline, kind, light, visitable);
|
|
54
|
-
const restingStyles = inline
|
|
55
|
-
? linkStyles.restingInline
|
|
56
|
-
: linkStyles.resting;
|
|
57
|
-
|
|
58
|
-
const defaultStyles = [
|
|
59
|
-
sharedStyles.shared,
|
|
60
|
-
restingStyles,
|
|
61
|
-
pressed && linkStyles.active,
|
|
62
|
-
// A11y: The focus ring should always be present when the
|
|
63
|
-
// the link has focus, even the link is being hovered over.
|
|
64
|
-
// TODO(WB-1498): Udpate ClickableBehavior so that focus doesn't
|
|
65
|
-
// stop on mouseleave. We want the focus ring to remain on a
|
|
66
|
-
// focused link even after hovering and un-hovering on it.
|
|
67
|
-
!pressed && hovered && linkStyles.hover,
|
|
68
|
-
!pressed && focused && linkStyles.focus,
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
const commonProps = {
|
|
72
|
-
"data-testid": testId,
|
|
73
|
-
style: [defaultStyles, style],
|
|
74
|
-
target,
|
|
75
|
-
...restProps,
|
|
76
|
-
} as const;
|
|
77
|
-
|
|
78
|
-
const linkUrl = new URL(href, window.location.origin);
|
|
79
|
-
|
|
80
|
-
const isExternalLink = linkUrl.origin !== window.location.origin;
|
|
81
|
-
|
|
82
|
-
const externalIcon = (
|
|
83
|
-
<PhosphorIcon
|
|
84
|
-
icon={externalLinkIcon}
|
|
85
|
-
size="small"
|
|
86
|
-
style={[linkContentStyles.endIcon, linkContentStyles.centered]}
|
|
87
|
-
testId="external-icon"
|
|
88
|
-
/>
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
let startIconElement;
|
|
92
|
-
let endIconElement;
|
|
93
|
-
|
|
94
|
-
if (startIcon) {
|
|
95
|
-
startIconElement = React.cloneElement(startIcon, {
|
|
96
|
-
style: [
|
|
97
|
-
linkContentStyles.startIcon,
|
|
98
|
-
linkContentStyles.centered,
|
|
99
|
-
],
|
|
100
|
-
testId: "start-icon",
|
|
101
|
-
"aria-hidden": "true",
|
|
102
|
-
...startIcon.props,
|
|
103
|
-
} as Partial<React.ReactElement<React.ComponentProps<typeof PhosphorIcon>>>);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (endIcon) {
|
|
107
|
-
endIconElement = React.cloneElement(endIcon, {
|
|
108
|
-
style: [linkContentStyles.endIcon, linkContentStyles.centered],
|
|
109
|
-
testId: "end-icon",
|
|
110
|
-
"aria-hidden": "true",
|
|
111
|
-
...endIcon.props,
|
|
112
|
-
} as Partial<React.ReactElement<React.ComponentProps<typeof PhosphorIcon>>>);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const linkContent = (
|
|
116
|
-
<>
|
|
117
|
-
{startIcon && startIconElement}
|
|
118
|
-
{children}
|
|
119
|
-
{endIcon
|
|
120
|
-
? endIconElement
|
|
121
|
-
: isExternalLink && target === "_blank" && externalIcon}
|
|
122
|
-
</>
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
return router && !skipClientNav && isClientSideUrl(href) ? (
|
|
126
|
-
<StyledLink
|
|
127
|
-
{...commonProps}
|
|
128
|
-
to={href}
|
|
129
|
-
ref={ref as React.ForwardedRef<typeof Link>}
|
|
130
|
-
>
|
|
131
|
-
{linkContent}
|
|
132
|
-
</StyledLink>
|
|
133
|
-
) : (
|
|
134
|
-
<StyledAnchor
|
|
135
|
-
{...commonProps}
|
|
136
|
-
href={href}
|
|
137
|
-
ref={ref as React.ForwardedRef<HTMLAnchorElement>}
|
|
138
|
-
>
|
|
139
|
-
{linkContent}
|
|
140
|
-
</StyledAnchor>
|
|
141
|
-
);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
return (
|
|
145
|
-
<__RouterContext.Consumer>
|
|
146
|
-
{(router) => renderInner(router)}
|
|
147
|
-
</__RouterContext.Consumer>
|
|
148
|
-
);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const styles: Record<string, any> = {};
|
|
152
|
-
|
|
153
|
-
const linkContentStyles = StyleSheet.create({
|
|
154
|
-
startIcon: {
|
|
155
|
-
marginInlineEnd: spacing.xxxSmall_4,
|
|
156
|
-
},
|
|
157
|
-
endIcon: {
|
|
158
|
-
marginInlineStart: spacing.xxxSmall_4,
|
|
159
|
-
},
|
|
160
|
-
centered: {
|
|
161
|
-
// Manually align the bottom of start/end icons with the text baseline.
|
|
162
|
-
verticalAlign: "-10%",
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
const sharedStyles = StyleSheet.create({
|
|
167
|
-
shared: {
|
|
168
|
-
cursor: "pointer",
|
|
169
|
-
textDecoration: "none",
|
|
170
|
-
outline: "none",
|
|
171
|
-
alignItems: "center",
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
const _generateStyles = (
|
|
176
|
-
inline: boolean,
|
|
177
|
-
kind: "primary" | "secondary",
|
|
178
|
-
light: boolean,
|
|
179
|
-
visitable: boolean,
|
|
180
|
-
) => {
|
|
181
|
-
const buttonType = `${kind}-${inline.toString()}-${light.toString()}-${visitable.toString()}`;
|
|
182
|
-
if (styles[buttonType]) {
|
|
183
|
-
return styles[buttonType];
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (kind === "secondary" && light) {
|
|
187
|
-
throw new Error("Secondary Light links are not supported");
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (visitable && kind !== "primary") {
|
|
191
|
-
throw new Error("Only primary link is visitable");
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const {blue, purple, white, offBlack, offBlack32, offBlack64} = color;
|
|
195
|
-
|
|
196
|
-
// NOTE: This color is only used here.
|
|
197
|
-
const pink = "#fa50ae";
|
|
198
|
-
|
|
199
|
-
// Standard purple
|
|
200
|
-
const linkPurple = mix(fade(offBlack, 0.08), purple);
|
|
201
|
-
// Light blue
|
|
202
|
-
const fadedBlue = color.fadedBlue;
|
|
203
|
-
// Light pink
|
|
204
|
-
const activeLightVisited = mix(fade(white, 0.32), pink);
|
|
205
|
-
// Dark blue
|
|
206
|
-
const activeDefaultPrimary = color.activeBlue;
|
|
207
|
-
|
|
208
|
-
const primaryDefaultTextColor = light ? white : blue;
|
|
209
|
-
const secondaryDefaultTextColor = inline ? offBlack : offBlack64;
|
|
210
|
-
const defaultTextColor =
|
|
211
|
-
kind === "primary"
|
|
212
|
-
? primaryDefaultTextColor
|
|
213
|
-
: secondaryDefaultTextColor;
|
|
214
|
-
|
|
215
|
-
const primaryActiveColor = light ? fadedBlue : activeDefaultPrimary;
|
|
216
|
-
const secondaryActiveColor = inline ? activeDefaultPrimary : offBlack;
|
|
217
|
-
const activeColor =
|
|
218
|
-
kind === "primary" ? primaryActiveColor : secondaryActiveColor;
|
|
219
|
-
|
|
220
|
-
const defaultVisited = visitable
|
|
221
|
-
? {
|
|
222
|
-
":visited": {
|
|
223
|
-
color: light ? pink : linkPurple,
|
|
224
|
-
},
|
|
225
|
-
}
|
|
226
|
-
: Object.freeze({});
|
|
227
|
-
const activeVisited = visitable
|
|
228
|
-
? {
|
|
229
|
-
":visited": {
|
|
230
|
-
color: light
|
|
231
|
-
? activeLightVisited
|
|
232
|
-
: mix(offBlack32, linkPurple),
|
|
233
|
-
},
|
|
234
|
-
}
|
|
235
|
-
: Object.freeze({});
|
|
236
|
-
|
|
237
|
-
const newStyles: StyleDeclaration = {
|
|
238
|
-
resting: {
|
|
239
|
-
color: defaultTextColor,
|
|
240
|
-
...defaultVisited,
|
|
241
|
-
},
|
|
242
|
-
restingInline: {
|
|
243
|
-
color: defaultTextColor,
|
|
244
|
-
// TODO(WB-1521): Update text decoration to the 1px dashed
|
|
245
|
-
// underline after the Link audit.
|
|
246
|
-
// textDecoration: "underline currentcolor solid 1px",
|
|
247
|
-
textDecoration: "underline currentcolor solid",
|
|
248
|
-
// TODO(WB-1521): Update the underline offset to be 4px after
|
|
249
|
-
// the Link audit.
|
|
250
|
-
// textUnderlineOffset: 4,
|
|
251
|
-
textUnderlineOffset: 2,
|
|
252
|
-
...defaultVisited,
|
|
253
|
-
},
|
|
254
|
-
hover: {
|
|
255
|
-
// TODO(WB-1521): Update text decoration to the 1px dashed
|
|
256
|
-
// underline after the Link audit.
|
|
257
|
-
// textDecoration: "underline currentcolor dashed 2px",
|
|
258
|
-
textDecoration: "underline currentcolor solid",
|
|
259
|
-
color: defaultTextColor,
|
|
260
|
-
// TODO(WB-1521): Update the underline offset to be 4px after
|
|
261
|
-
// the Link audit.
|
|
262
|
-
// textUnderlineOffset: 4,
|
|
263
|
-
...defaultVisited,
|
|
264
|
-
},
|
|
265
|
-
focus: {
|
|
266
|
-
// Focus styles only show up with keyboard navigation.
|
|
267
|
-
// Mouse users don't see focus styles.
|
|
268
|
-
":focus-visible": {
|
|
269
|
-
color: defaultTextColor,
|
|
270
|
-
outline: `1px solid ${light ? white : blue}`,
|
|
271
|
-
borderRadius: 3,
|
|
272
|
-
...defaultVisited,
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
active: {
|
|
276
|
-
color: activeColor,
|
|
277
|
-
textDecoration: "underline currentcolor solid",
|
|
278
|
-
// TODO(WB-1521): Update the underline offset to be 4px after
|
|
279
|
-
// the Link audit.
|
|
280
|
-
// textUnderlineOffset: 4,
|
|
281
|
-
...activeVisited,
|
|
282
|
-
},
|
|
283
|
-
};
|
|
284
|
-
|
|
285
|
-
styles[buttonType] = StyleSheet.create(newStyles);
|
|
286
|
-
return styles[buttonType];
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
export default LinkCore;
|
package/src/components/link.tsx
DELETED
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import {__RouterContext} from "react-router";
|
|
3
|
-
import {Link as ReactRouterLink} from "react-router-dom";
|
|
4
|
-
import {getClickableBehavior} from "@khanacademy/wonder-blocks-clickable";
|
|
5
|
-
|
|
6
|
-
import type {AriaProps, StyleType} from "@khanacademy/wonder-blocks-core";
|
|
7
|
-
import {PhosphorIcon} from "@khanacademy/wonder-blocks-icon";
|
|
8
|
-
import type {Typography} from "@khanacademy/wonder-blocks-typography";
|
|
9
|
-
import LinkCore from "./link-core";
|
|
10
|
-
|
|
11
|
-
type CommonProps = AriaProps & {
|
|
12
|
-
/**
|
|
13
|
-
* Text to appear on the link. It can be a plain text or a Typography element.
|
|
14
|
-
*/
|
|
15
|
-
children: string | React.ReactElement<React.ComponentProps<Typography>>;
|
|
16
|
-
/**
|
|
17
|
-
* URL to navigate to.
|
|
18
|
-
*/
|
|
19
|
-
href: string;
|
|
20
|
-
/**
|
|
21
|
-
* An optional id attribute.
|
|
22
|
-
*/
|
|
23
|
-
id?: string;
|
|
24
|
-
/**
|
|
25
|
-
* Indicates that this link is used within a body of text.
|
|
26
|
-
* This styles the link with an underline to distinguish it
|
|
27
|
-
* from surrounding text.
|
|
28
|
-
*/
|
|
29
|
-
inline?: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Kind of Link. Note: Secondary light Links are not supported.
|
|
32
|
-
*/
|
|
33
|
-
kind?: "primary" | "secondary";
|
|
34
|
-
/**
|
|
35
|
-
* Whether the button is on a dark/colored background.
|
|
36
|
-
*/
|
|
37
|
-
light?: boolean;
|
|
38
|
-
/**
|
|
39
|
-
* Whether the link should change color once it's visited.
|
|
40
|
-
* secondary or primary (light) links are not allowed to be visitable.
|
|
41
|
-
*/
|
|
42
|
-
visitable?: boolean;
|
|
43
|
-
/**
|
|
44
|
-
* Specifies the type of relationship between the current document and the
|
|
45
|
-
* linked document. Should only be used when `href` is specified. This
|
|
46
|
-
* defaults to "noopener noreferrer" when `target="_blank"`, but can be
|
|
47
|
-
* overridden by setting this prop to something else.
|
|
48
|
-
*/
|
|
49
|
-
rel?: string;
|
|
50
|
-
/**
|
|
51
|
-
* Set the tabindex attribute on the rendered element.
|
|
52
|
-
*/
|
|
53
|
-
tabIndex?: number;
|
|
54
|
-
/**
|
|
55
|
-
* Test ID used for e2e testing.
|
|
56
|
-
*/
|
|
57
|
-
testId?: string;
|
|
58
|
-
/**
|
|
59
|
-
* Whether to avoid using client-side navigation.
|
|
60
|
-
*
|
|
61
|
-
* If the URL passed to href is local to the client-side, e.g.
|
|
62
|
-
* /math/algebra/eval-exprs, then it tries to use react-router-dom's Link
|
|
63
|
-
* component which handles the client-side navigation. You can set
|
|
64
|
-
* `skipClientNav` to true avoid using client-side nav entirely.
|
|
65
|
-
*
|
|
66
|
-
* NOTE: All URLs containing a protocol are considered external, e.g.
|
|
67
|
-
* https://khanacademy.org/math/algebra/eval-exprs will trigger a full
|
|
68
|
-
* page reload.
|
|
69
|
-
*/
|
|
70
|
-
skipClientNav?: boolean;
|
|
71
|
-
/**
|
|
72
|
-
* Custom styles.
|
|
73
|
-
*/
|
|
74
|
-
style?: StyleType;
|
|
75
|
-
// TODO(yejia): use this if ADR #47 has been implemented
|
|
76
|
-
/*
|
|
77
|
-
style?: Style<Exact<{
|
|
78
|
-
width?: number | string
|
|
79
|
-
position: Position,
|
|
80
|
-
...MarginStyles,
|
|
81
|
-
...FlexItemStyles,
|
|
82
|
-
}>>,
|
|
83
|
-
*/
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Adds CSS classes to the Link.
|
|
87
|
-
*/
|
|
88
|
-
className?: string;
|
|
89
|
-
// NOTE(jeresig): Currently React Docgen (used by Styleguidist) doesn't
|
|
90
|
-
// support ... inside of an exact object type. Thus we had to move the
|
|
91
|
-
// following propers into this SharedProps, even though they should be
|
|
92
|
-
// external. Once that's fixed we can split them back apart.
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Function to call when button is clicked.
|
|
96
|
-
*
|
|
97
|
-
* This callback should be used for things like marking BigBingo
|
|
98
|
-
* conversions. It should NOT be used to redirect to a different URL or to
|
|
99
|
-
* prevent navigation via e.preventDefault(). The event passed to this
|
|
100
|
-
* handler will have its preventDefault() and stopPropagation() methods
|
|
101
|
-
* stubbed out.
|
|
102
|
-
*/
|
|
103
|
-
onClick?: (e: React.SyntheticEvent) => unknown;
|
|
104
|
-
/**
|
|
105
|
-
* Run async code in the background while client-side navigating. If the
|
|
106
|
-
* browser does a full page load navigation, the callback promise must be
|
|
107
|
-
* settled before the navigation will occur. Errors are ignored so that
|
|
108
|
-
* navigation is guaranteed to succeed.
|
|
109
|
-
*/
|
|
110
|
-
safeWithNav?: () => Promise<unknown>;
|
|
111
|
-
/**
|
|
112
|
-
* Respond to raw "keydown" event.
|
|
113
|
-
*/
|
|
114
|
-
onKeyDown?: (e: React.KeyboardEvent) => unknown;
|
|
115
|
-
/**
|
|
116
|
-
* Respond to raw "keyup" event.
|
|
117
|
-
*/
|
|
118
|
-
onKeyUp?: (e: React.KeyboardEvent) => unknown;
|
|
119
|
-
/**
|
|
120
|
-
* An optional title attribute.
|
|
121
|
-
*/
|
|
122
|
-
title?: string;
|
|
123
|
-
/**
|
|
124
|
-
* An optional icon displayed before the link label.
|
|
125
|
-
*/
|
|
126
|
-
startIcon?: React.ReactElement<React.ComponentProps<typeof PhosphorIcon>>;
|
|
127
|
-
/**
|
|
128
|
-
* An optional icon displayed after the link label.
|
|
129
|
-
* If `target="_blank"` and `endIcon` is passed in, `endIcon` will override
|
|
130
|
-
* the default `externalIcon`.
|
|
131
|
-
*/
|
|
132
|
-
endIcon?: React.ReactElement<React.ComponentProps<typeof PhosphorIcon>>;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
export type SharedProps =
|
|
136
|
-
| (CommonProps & {
|
|
137
|
-
/**
|
|
138
|
-
* A target destination window for a link to open in. We only support
|
|
139
|
-
* "_blank" which opens the URL in a new tab.
|
|
140
|
-
*
|
|
141
|
-
* TODO(WB-1262): only allow this prop when `href` is also set.t
|
|
142
|
-
*/
|
|
143
|
-
target?: "_blank";
|
|
144
|
-
|
|
145
|
-
beforeNav?: never; // disallow beforeNav when target="_blank"
|
|
146
|
-
})
|
|
147
|
-
| (CommonProps & {
|
|
148
|
-
/**
|
|
149
|
-
* Run async code before navigating to the URL passed to `href`. If the
|
|
150
|
-
* promise returned rejects then navigation will not occur.
|
|
151
|
-
*
|
|
152
|
-
* If both safeWithNav and beforeNav are provided, beforeNav will be run
|
|
153
|
-
* first and safeWithNav will only be run if beforeNav does not reject.
|
|
154
|
-
*
|
|
155
|
-
* WARNING: Using this with `target="_blank"` will trigger built-in popup
|
|
156
|
-
* blockers in Firefox and Safari. This is because we do navigation
|
|
157
|
-
* programmatically and `beforeNav` causes a delay which means that the
|
|
158
|
-
* browser can't make a directly link between a user action and the
|
|
159
|
-
* navigation.
|
|
160
|
-
*/
|
|
161
|
-
beforeNav?: () => Promise<unknown>;
|
|
162
|
-
|
|
163
|
-
target?: never; // disallow target="_blank" when using beforeNav
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Reusable link component.
|
|
168
|
-
*
|
|
169
|
-
* Consisting of a [`ClickableBehavior`](#clickablebehavior) surrounding a
|
|
170
|
-
* `LinkCore`. `ClickableBehavior` handles interactions and state changes.
|
|
171
|
-
* `LinkCore` is a stateless component which displays the different states
|
|
172
|
-
* the `Link` can take.
|
|
173
|
-
*
|
|
174
|
-
* ### Usage
|
|
175
|
-
*
|
|
176
|
-
* ```jsx
|
|
177
|
-
* <Link
|
|
178
|
-
* href="https://khanacademy.org/"
|
|
179
|
-
* >
|
|
180
|
-
* Label
|
|
181
|
-
* </Link>
|
|
182
|
-
* ```
|
|
183
|
-
*/
|
|
184
|
-
const Link = React.forwardRef(function Link(
|
|
185
|
-
props: SharedProps,
|
|
186
|
-
ref: React.ForwardedRef<typeof ReactRouterLink | HTMLAnchorElement>,
|
|
187
|
-
) {
|
|
188
|
-
const {
|
|
189
|
-
onClick,
|
|
190
|
-
beforeNav = undefined,
|
|
191
|
-
safeWithNav,
|
|
192
|
-
href,
|
|
193
|
-
skipClientNav,
|
|
194
|
-
children,
|
|
195
|
-
tabIndex,
|
|
196
|
-
onKeyDown,
|
|
197
|
-
onKeyUp,
|
|
198
|
-
target = undefined,
|
|
199
|
-
inline = false,
|
|
200
|
-
kind = "primary",
|
|
201
|
-
light = false,
|
|
202
|
-
visitable = false,
|
|
203
|
-
...sharedProps
|
|
204
|
-
} = props;
|
|
205
|
-
|
|
206
|
-
const renderClickableBehavior = (router: any): React.ReactNode => {
|
|
207
|
-
const ClickableBehavior = getClickableBehavior(
|
|
208
|
-
href,
|
|
209
|
-
skipClientNav,
|
|
210
|
-
router,
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
if (beforeNav) {
|
|
214
|
-
return (
|
|
215
|
-
<ClickableBehavior
|
|
216
|
-
disabled={false}
|
|
217
|
-
href={href}
|
|
218
|
-
role="link"
|
|
219
|
-
onClick={onClick}
|
|
220
|
-
beforeNav={beforeNav}
|
|
221
|
-
safeWithNav={safeWithNav}
|
|
222
|
-
onKeyDown={onKeyDown}
|
|
223
|
-
onKeyUp={onKeyUp}
|
|
224
|
-
>
|
|
225
|
-
{(state, {...childrenProps}) => {
|
|
226
|
-
return (
|
|
227
|
-
<LinkCore
|
|
228
|
-
{...sharedProps}
|
|
229
|
-
{...state}
|
|
230
|
-
{...childrenProps}
|
|
231
|
-
skipClientNav={skipClientNav}
|
|
232
|
-
href={href}
|
|
233
|
-
target={target}
|
|
234
|
-
tabIndex={tabIndex}
|
|
235
|
-
inline={inline}
|
|
236
|
-
kind={kind}
|
|
237
|
-
light={light}
|
|
238
|
-
visitable={visitable}
|
|
239
|
-
ref={ref}
|
|
240
|
-
>
|
|
241
|
-
{children}
|
|
242
|
-
</LinkCore>
|
|
243
|
-
);
|
|
244
|
-
}}
|
|
245
|
-
</ClickableBehavior>
|
|
246
|
-
);
|
|
247
|
-
} else {
|
|
248
|
-
return (
|
|
249
|
-
<ClickableBehavior
|
|
250
|
-
disabled={false}
|
|
251
|
-
href={href}
|
|
252
|
-
role="link"
|
|
253
|
-
onClick={onClick}
|
|
254
|
-
safeWithNav={safeWithNav}
|
|
255
|
-
target={target}
|
|
256
|
-
onKeyDown={onKeyDown}
|
|
257
|
-
onKeyUp={onKeyUp}
|
|
258
|
-
>
|
|
259
|
-
{(state, {...childrenProps}) => {
|
|
260
|
-
return (
|
|
261
|
-
<LinkCore
|
|
262
|
-
{...sharedProps}
|
|
263
|
-
{...state}
|
|
264
|
-
{...childrenProps}
|
|
265
|
-
skipClientNav={skipClientNav}
|
|
266
|
-
href={href}
|
|
267
|
-
target={target}
|
|
268
|
-
tabIndex={tabIndex}
|
|
269
|
-
inline={inline}
|
|
270
|
-
kind={kind}
|
|
271
|
-
light={light}
|
|
272
|
-
visitable={visitable}
|
|
273
|
-
ref={ref}
|
|
274
|
-
>
|
|
275
|
-
{children}
|
|
276
|
-
</LinkCore>
|
|
277
|
-
);
|
|
278
|
-
}}
|
|
279
|
-
</ClickableBehavior>
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
return (
|
|
285
|
-
<__RouterContext.Consumer>
|
|
286
|
-
{(router) => renderClickableBehavior(router)}
|
|
287
|
-
</__RouterContext.Consumer>
|
|
288
|
-
);
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
export default Link;
|
package/src/index.ts
DELETED
package/tsconfig-build.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"exclude": ["dist"],
|
|
3
|
-
"extends": "../tsconfig-shared.json",
|
|
4
|
-
"compilerOptions": {
|
|
5
|
-
"outDir": "./dist",
|
|
6
|
-
"rootDir": "src",
|
|
7
|
-
},
|
|
8
|
-
"references": [
|
|
9
|
-
{"path": "../wonder-blocks-clickable/tsconfig-build.json"},
|
|
10
|
-
{"path": "../wonder-blocks-core/tsconfig-build.json"},
|
|
11
|
-
{"path": "../wonder-blocks-typography/tsconfig-build.json"},
|
|
12
|
-
{"path": "../wonder-blocks-icon/tsconfig-build.json"},
|
|
13
|
-
{"path": "../wonder-blocks-tokens/tsconfig-build.json"},
|
|
14
|
-
]
|
|
15
|
-
}
|