UNPKG

@atlaskit/primitives

Version:

Primitives are token-backed low-level building blocks.

174 lines (169 loc) 9.27 kB
import _extends from "@babel/runtime/helpers/extends"; import _typeof from "@babel/runtime/helpers/typeof"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; var _excluded = ["href", "children", "backgroundColor", "newWindowLabel", "padding", "paddingBlock", "paddingBlockStart", "paddingBlockEnd", "paddingInline", "paddingInlineStart", "paddingInlineEnd", "onClick", "interactionName", "componentName", "analyticsContext", "aria-label", "aria-labelledby", "style", "target", "testId", "xcss"], _excluded2 = ["className"]; /** * @jsxRuntime classic * @jsx jsx */ import { forwardRef, useCallback, useContext } from 'react'; // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766 import { css, jsx } from '@emotion/react'; import invariant from 'tiny-invariant'; import { usePlatformLeafEventHandler } from '@atlaskit/analytics-next'; import { useRouterLink } from '@atlaskit/app-provider'; import noop from '@atlaskit/ds-lib/noop'; import { useId } from '@atlaskit/ds-lib/use-id'; import InteractionContext from '@atlaskit/interaction-context'; import VisuallyHidden from '@atlaskit/visually-hidden'; import { backgroundColorStylesMap, borderColorMap, borderWidthMap, paddingStylesMap, positiveSpaceMap } from '../xcss/style-maps.partial'; import { parseXcss } from '../xcss/xcss'; // TODO: duplicates FocusRing styles from `@atlaskit/focus-ring`. var focusRingStyles = css({ '&:focus, &:focus-visible': { // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values outlineColor: borderColorMap['color.border.focused'], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values outlineOffset: positiveSpaceMap['space.025'], outlineStyle: 'solid', // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values, @atlaskit/ui-styling-standard/no-unsafe-values outlineWidth: borderWidthMap['border.width.outline'] }, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-selectors '&:focus:not(:focus-visible)': { outline: 'none' }, '@media screen and (forced-colors: active), screen and (-ms-high-contrast: active)': { '&:focus-visible': { outline: '1px solid' } } }); var baseStyles = css({ boxSizing: 'border-box', textDecoration: 'underline' }); var IS_EXTERNAL_LINK_REGEX = /^(?:(http|https):\/\/)/; var IS_NON_HTTP_BASED = /^(((mailto|tel|sms|blob):)|(#))/; // Comma is added here to add a slight pause between announcing the anchor label and "opens in new window" var OPENS_NEW_WINDOW_LABEL = '(opens new window)'; /** * __Anchor__ * * A primitive for building custom anchor links. * * - [Examples](https://atlassian.design/components/primitives/anchor/examples) * - [Code](https://atlassian.design/components/primitives/anchor/code) * - [Usage](https://atlassian.design/components/primitives/anchor/usage) */ var AnchorNoRef = function AnchorNoRef(_ref, ref) { var href = _ref.href, children = _ref.children, backgroundColor = _ref.backgroundColor, newWindowLabel = _ref.newWindowLabel, padding = _ref.padding, paddingBlock = _ref.paddingBlock, paddingBlockStart = _ref.paddingBlockStart, paddingBlockEnd = _ref.paddingBlockEnd, paddingInline = _ref.paddingInline, paddingInlineStart = _ref.paddingInlineStart, paddingInlineEnd = _ref.paddingInlineEnd, _ref$onClick = _ref.onClick, providedOnClick = _ref$onClick === void 0 ? noop : _ref$onClick, interactionName = _ref.interactionName, componentName = _ref.componentName, analyticsContext = _ref.analyticsContext, ariaLabel = _ref['aria-label'], ariaLabelledBy = _ref['aria-labelledby'], style = _ref.style, target = _ref.target, testId = _ref.testId, xcss = _ref.xcss, htmlAttributes = _objectWithoutProperties(_ref, _excluded); var interactionContext = useContext(InteractionContext); var handleClick = useCallback(function (e, analyticsEvent) { interactionContext && interactionContext.tracePress(interactionName, e.timeStamp); providedOnClick(e, analyticsEvent); }, [providedOnClick, interactionContext, interactionName]); var opensNewWindowLabelId = useId(); var onClick = usePlatformLeafEventHandler({ fn: handleClick, action: 'clicked', componentName: componentName || 'Anchor', packageName: "@atlaskit/primitives", packageVersion: "14.7.2", analyticsData: analyticsContext, actionSubject: 'link' }); // This is to remove className from safeHtmlAttributes // @ts-expect-error className doesn't exist in the prop definition but we want to ensure it cannot be applied even if types are bypassed var _spreadClass = htmlAttributes.className, safeHtmlAttributes = _objectWithoutProperties(htmlAttributes, _excluded2); var resolvedStyles = parseXcss(xcss); var RouterLink = useRouterLink(); var isExternal = typeof href === 'string' && IS_EXTERNAL_LINK_REGEX.test(href); var isNonHttpBased = typeof href === 'string' && IS_NON_HTTP_BASED.test(href); /** * Renders a router link if: * * - a link component is set in the app provider * - it's not an external link (starting with `http://` or `https://`) * - it's not a non-HTTP-based link (e.g. emails, phone numbers, hash links etc.). */ var isRouterLink = RouterLink && !isExternal && !isNonHttpBased; var hrefObjectUsedWithoutRouterLink = RouterLink === undefined && _typeof(href) === 'object'; invariant(!hrefObjectUsedWithoutRouterLink, "@atlaskit/primitives: Anchor primitive cannot pass an object to 'href' unless a router link is configured in the AppProvider"); var Component = isRouterLink ? RouterLink : 'a'; return jsx(Component // eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop -- Ignored via go/DSP-18766 , _extends({ style: style, ref: ref // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766 , className: resolvedStyles.static // eslint-disable-next-line @repo/internal/react/no-unsafe-spread-props }, safeHtmlAttributes, { // @ts-expect-error href: !isRouterLink && typeof href !== 'string' ? undefined : href, target: target, onClick: onClick, "aria-label": ariaLabel && target === '_blank' && !ariaLabelledBy ? //`${ariaLabel} ${OPENS_NEW_WINDOW_LABEL}` "".concat(ariaLabel, " , ").concat(newWindowLabel ? newWindowLabel : OPENS_NEW_WINDOW_LABEL) : ariaLabel, "aria-labelledby": ariaLabelledBy && target === '_blank' ? "".concat(ariaLabelledBy, " ").concat(opensNewWindowLabelId) : ariaLabelledBy, css: [baseStyles, focusRingStyles, // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 backgroundColor && backgroundColorStylesMap[backgroundColor], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 padding && paddingStylesMap.padding[padding], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 paddingBlock && paddingStylesMap.paddingBlock[paddingBlock], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 paddingBlockStart && paddingStylesMap.paddingBlockStart[paddingBlockStart], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 paddingBlockEnd && paddingStylesMap.paddingBlockEnd[paddingBlockEnd], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 paddingInline && paddingStylesMap.paddingInline[paddingInline], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 paddingInlineStart && paddingStylesMap.paddingInlineStart[paddingInlineStart], // eslint-disable-next-line @atlaskit/ui-styling-standard/no-imported-style-values -- Ignored via go/DSP-18766 paddingInlineEnd && paddingStylesMap.paddingInlineEnd[paddingInlineEnd], resolvedStyles.emotion], "data-testid": testId, "data-is-router-link": testId ? isRouterLink ? 'true' : 'false' : undefined }), children, target === '_blank' && (children && !ariaLabel && !ariaLabelledBy || ariaLabelledBy) && jsx(VisuallyHidden, { id: opensNewWindowLabelId }, ", ".concat(newWindowLabel ? newWindowLabel : OPENS_NEW_WINDOW_LABEL))); }; // Workarounds to support generic types with forwardRef /** * __Anchor__ * * Anchor is a primitive for building custom anchor links. It's a wrapper around the HTML `<a>` element that provides a consistent API for handling client-side routing and Atlassian Design System styling. * * - [Examples](https://atlassian.design/components/primitives/anchor/examples) * - [Code](https://atlassian.design/components/primitives/anchor/code) * - [Usage](https://atlassian.design/components/primitives/anchor/usage) */ var Anchor = /*#__PURE__*/forwardRef(AnchorNoRef); export default Anchor;