UNPKG

3.4 kBJavaScriptView Raw
1import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
2import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties';
3import { css } from '@emotion/css';
4import { Box } from '@spark-web/box';
5import { useLinkComponent } from '@spark-web/link';
6import { forwardRefWithAs } from '@spark-web/utils/ts';
7import { useTextContext, useForegroundTone } from '@spark-web/text';
8import { useTheme } from '@spark-web/theme';
9import { resetElementStyles, buildDataAttributes } from '@spark-web/utils/internal';
10import { jsx } from 'react/jsx-runtime';
11import { useComposedRefs } from '@spark-web/utils';
12import { forwardRef, useRef, useCallback } from 'react';
13
14var TEXT_LINK_ERROR_MESSAGE = 'TextLink components must be inside `Text`.';
15function useTextLink(tag) {
16 var textContext = useTextContext();
17
18 // Limit API surface area; expect style inheritance
19 if (!textContext) {
20 throw new Error(TEXT_LINK_ERROR_MESSAGE);
21 }
22 var theme = useTheme();
23 var textColor = useForegroundTone(textContext.tone);
24 var resetStyles = resetElementStyles(tag);
25 var linkStyles = {
26 color: textColor,
27 cursor: 'pointer',
28 textDecoration: 'underline',
29 fontWeight: theme.typography.fontWeight.semibold
30 };
31 var styles = [resetStyles, linkStyles];
32 return styles;
33}
34
35var _excluded$1 = ["as", "data"];
36/**
37 * Text links are used as navigational elements. They may appear on their own,
38 * within a sentence or paragraph, or directly following content.
39 *
40 * @note If you are **only** providing "onClick" use `TextLinkButton` instead.
41 */
42var TextLink = forwardRefWithAs(
43// NOTE: we need `forwardRefWithAs` for TS, but we don't want consumers changing the underlying element
44// eslint-disable-next-line @typescript-eslint/no-unused-vars
45function (_ref, ref) {
46 _ref.as;
47 var data = _ref.data,
48 consumerProps = _objectWithoutProperties(_ref, _excluded$1);
49 var LinkComponent = useLinkComponent(ref);
50 var styles = useTextLink('a');
51 return /*#__PURE__*/jsx(Box, _objectSpread({
52 as: LinkComponent,
53 asElement: "a",
54 ref: ref,
55 className: css(styles),
56 data: data
57 }, consumerProps));
58});
59
60var _excluded = ["data"];
61// NOTE: Rather than a native `button` element, we render a `span` with the ARIA
62// role of "button" to avoid issues with text behaviour. Resolves:
63// - alignment
64// - truncating
65// - wrapping
66
67/** The appearance of `TextLink`, with the semantics of a `<button/>`. */
68var TextLinkButton = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
69 var data = _ref.data,
70 consumerProps = _objectWithoutProperties(_ref, _excluded);
71 var styles = useTextLink('span');
72 var internalRef = useRef(null);
73 var ref = useComposedRefs(internalRef, forwardedRef);
74 var handleKeyDown = useCallback(function (event) {
75 if (event.key === 'Enter' || event.key === ' ') {
76 var _internalRef$current;
77 event.preventDefault();
78 (_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.click();
79 }
80 }, [internalRef]);
81 return /*#__PURE__*/jsx("span", _objectSpread(_objectSpread({
82 role: "button",
83 ref: ref,
84 className: css(styles),
85 tabIndex: 0,
86 onKeyDown: handleKeyDown
87 }, data ? buildDataAttributes(data) : undefined), consumerProps));
88});
89TextLinkButton.displayName = 'TextLinkButton';
90
91export { TextLink, TextLinkButton };