@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
200 lines (199 loc) • 7.61 kB
JavaScript
;
"use client";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AnchorComponent = AnchorComponent;
exports.default = void 0;
exports.isDangerousHref = isDangerousHref;
exports.opensNewTab = void 0;
exports.pickIcon = pickIcon;
exports.scrollToHash = scrollToHash;
var _includes = _interopRequireDefault(require("core-js-pure/stable/instance/includes.js"));
var _withComponentMarkers = _interopRequireDefault(require("../../shared/helpers/withComponentMarkers.js"));
var _react = require("react");
var _clsx = require("clsx");
var _Element = _interopRequireDefault(require("../../elements/Element.js"));
var _Context = _interopRequireDefault(require("../../shared/Context.js"));
var _componentHelper = require("../../shared/component-helper.js");
var _useId = _interopRequireDefault(require("../../shared/helpers/useId.js"));
var _helpers = require("../../shared/helpers.js");
var _IconPrimary2 = _interopRequireDefault(require("../icon-primary/IconPrimary.js"));
var _Tooltip = _interopRequireDefault(require("../tooltip/Tooltip.js"));
var _index = require("../../icons/index.js");
var _jsxRuntime = require("react/jsx-runtime");
var _IconPrimary;
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
const anchorDefaultProps = {
noAnimation: false,
noStyle: false,
noHover: false,
noUnderline: false,
noIcon: false,
noLaunchIcon: false,
disabled: false
};
function AnchorComponent(localProps) {
var _context, _context2, _context3, _context4;
const context = (0, _react.useContext)(_Context.default);
const allProps = (0, _componentHelper.extendPropsWithContext)(localProps, anchorDefaultProps, {
skeleton: context?.skeleton
}, context?.getTranslation(localProps).Anchor, context?.Anchor);
const fallbackRef = (0, _react.useRef)(null);
if (!allProps.ref) {
allProps.ref = fallbackRef;
}
const tooltipRef = (0, _react.useRef)(null);
const {
id,
element,
className,
children,
tooltip,
icon,
iconPosition = 'left',
omitClass,
ref: refProp,
targetBlankTitle,
noAnimation,
noHover,
noStyle,
noUnderline,
noIcon,
noLaunchIcon,
disabled,
...rest
} = allProps;
const attributes = rest;
const internalId = (0, _useId.default)(id);
const as = element || 'a';
const isDisabled = disabled;
const hasNoHover = noHover || isDisabled;
const hasNoAnimation = noAnimation || isDisabled;
const hasNoUnderline = noUnderline || isDisabled;
if (isDangerousHref(attributes.href)) {
delete attributes.href;
}
if (isDangerousHref(attributes.to)) {
delete attributes.to;
}
const href = attributes.href || attributes.to;
const _opensNewTab = opensNewTab(allProps.target, href);
const showLaunchIcon = _opensNewTab && !isDisabled && !noIcon && !noLaunchIcon && !((_context = className) == null ? void 0 : Function.call.bind((0, _includes.default)(_context), _context))?.('dnb-anchor--no-icon') && !((_context2 = className) == null ? void 0 : Function.call.bind((0, _includes.default)(_context2), _context2))?.('dnb-anchor--no-launch-icon') && !omitClass;
const showTooltip = (tooltip || _opensNewTab) && !allProps.title;
if (_opensNewTab && !attributes.rel) {
attributes.rel = 'noopener noreferrer';
}
const iconNode = icon && getIcon(icon);
const suffix = iconPosition === 'right' && iconNode || showLaunchIcon && (_IconPrimary || (_IconPrimary = (0, _jsxRuntime.jsx)(_IconPrimary2.default, {
className: "dnb-anchor__launch-icon",
icon: _index.launch
})));
const prefix = iconPosition === 'left' && iconNode;
const anchorRef = (0, _react.useCallback)(elem => {
tooltipRef.current = elem;
if (typeof refProp === 'function') {
refProp(elem);
} else if (refProp) {
;
refProp.current = elem;
}
}, [refProp]);
if (isDisabled) {
attributes.disabled = true;
if (as === 'a') {
attributes.tabIndex = -1;
attributes['aria-disabled'] = true;
if (attributes.href) {
delete attributes.href;
}
if (attributes.to) {
delete attributes.to;
}
attributes.onClick = event => {
event.preventDefault();
event.stopPropagation();
};
}
}
return (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [(0, _jsxRuntime.jsxs)(_Element.default, {
as: as,
id: id,
internalClass: as !== 'button',
className: (0, _clsx.clsx)(omitClass !== true && (0, _clsx.clsx)('dnb-anchor', prefix && 'dnb-anchor--icon-left', suffix && 'dnb-anchor--icon-right', typeof children !== 'string' && 'dnb-anchor--was-node', hasNoAnimation && 'dnb-anchor--no-animation', hasNoHover && 'dnb-anchor--no-hover', noStyle && 'dnb-anchor--no-style', hasNoUnderline && 'dnb-anchor--no-underline', isDisabled && 'dnb-anchor--disabled', noIcon && !((_context3 = className) == null ? void 0 : Function.call.bind((0, _includes.default)(_context3), _context3))?.('dnb-anchor--no-icon') && 'dnb-anchor--no-icon', noLaunchIcon && !((_context4 = className) == null ? void 0 : Function.call.bind((0, _includes.default)(_context4), _context4))?.('dnb-anchor--no-launch-icon') && 'dnb-anchor--no-launch-icon', context?.theme?.surface === 'dark' && 'dnb-anchor--surface-dark'), className),
...attributes,
ref: anchorRef,
children: [prefix, children, suffix]
}), showTooltip && (0, _jsxRuntime.jsx)(_Tooltip.default, {
showDelay: 100,
id: internalId + '-tooltip',
targetElement: tooltipRef,
tooltip: tooltip,
children: allProps.title || targetBlankTitle
})]
});
}
function Anchor(props) {
return (0, _jsxRuntime.jsx)(AnchorComponent, {
...props
});
}
(0, _withComponentMarkers.default)(Anchor, {
_supportsSpacingProps: true
});
var _default = exports.default = Anchor;
function scrollToHash(hash) {
if (typeof document === 'undefined' || !hash || !(0, _includes.default)(hash).call(hash, '#')) {
return undefined;
}
const id = hash.split(/#/g).reverse()[0];
const anchorElem = document.getElementById(id);
if (anchorElem instanceof HTMLElement) {
try {
const scrollPadding = parseFloat(window.getComputedStyle(document.documentElement).scrollPaddingTop);
const top = (0, _helpers.getOffsetTop)(anchorElem) - scrollPadding || 0;
window.scroll({
top
});
return {
element: anchorElem
};
} catch (error) {
console.error('Anchor: Failed to scroll to element:', error);
}
}
return undefined;
}
function getIcon(icon) {
return pickIcon(icon) || (0, _jsxRuntime.jsx)(_IconPrimary2.default, {
icon: icon
});
}
function pickIcon(icon, className) {
var _context5;
if (icon?.props?.icon || ((_context5 = icon?.props?.className) == null ? void 0 : Function.call.bind((0, _includes.default)(_context5), _context5))?.('dnb-icon')) {
return (0, _react.createElement)(icon.type, {
...icon.props,
key: 'button-icon-clone',
className: (0, _clsx.clsx)(icon.props?.className, className)
});
}
return null;
}
const opensNewTab = (target, href) => target === '_blank' && !/^(mailto|tel|sms)/.test(href);
exports.opensNewTab = opensNewTab;
function isDangerousHref(href) {
if (typeof href !== 'string') {
return false;
}
let normalized = '';
for (const char of href) {
const code = char.charCodeAt(0);
if (code > 0x20 && code !== 0x7f && !(code >= 0x80 && code <= 0xa0)) {
normalized += char;
}
}
return /^(javascript|vbscript):/i.test(normalized);
}
//# sourceMappingURL=Anchor.js.map