@veracity/vui
Version:
Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.
110 lines (106 loc) • 3.5 kB
JavaScript
import { isReactText, isString } from "../utils/assertion.js";
import { filterUndefined } from "../utils/object.js";
import { cs } from "../utils/styles.js";
import { useStyleConfig } from "../core/theme.js";
import styled from "../core/styled.js";
import vui from "../core/vui.js";
import { T } from "../t/t.js";
import { LinkProvider } from "./context.js";
import { LinkIcon } from "./linkIcon.js";
import { LinkText } from "./linkText.js";
import { useEffect, useMemo } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
//#region src/link/link.tsx
const linkSwipeAnimation = `
@keyframes linkSwipe {
from {
background-size: 0 1px;
}
to {
background-size: 100% 1px;
}
}
`;
const LinkBase = styled.aBox.attrs((props) => ({ isUnderlined: props.isUnderlined || false }))`
${linkSwipeAnimation}
display: inline;
cursor: pointer;
position: relative;
line-height: 1.5;
outline: none;
width: fit-content;
text-decoration: none;
&:not(.vui-linkNoUnderline) > .vui-t {
position: relative;
background: linear-gradient(to right, currentcolor, currentcolor);
background-size: ${({ isUnderlined }) => isUnderlined ? "100% 1px" : "0 1px"};
background-position: 0 100%;
background-repeat: no-repeat;
text-decoration: none;
padding-bottom: 2px;
line-height: 1.2;
}
&:hover > .vui-t {
animation: ${({ isUnderlined }) => isUnderlined ? "linkSwipe 0.5s ease forwards" : "linkSwipe 0.3s ease forwards"};
background-size: 100% 1px;
}
`;
const Link = vui((props, ref) => {
const { children, className, fontWeight, startIcon, endIcon, iconLeft, iconRight, isExternal, isUnderlined, size, text, variant, weight, ...rest } = props;
const resolvedStartIcon = startIcon ?? iconLeft;
const resolvedEndIcon = endIcon ?? iconRight;
const styles = useStyleConfig("Link", props);
const context = useMemo(() => filterUndefined({
size,
variant
}), [size, variant]);
const iconPadding = size === "xs" ? "1.2rem" : "1.5rem";
const aliasedProps = filterUndefined({
fontWeight: weight || fontWeight,
rel: isExternal ? "noopener" : void 0,
target: isExternal ? "_blank" : void 0,
pl: resolvedStartIcon ? iconPadding : void 0,
pr: resolvedEndIcon ? iconPadding : void 0
});
useEffect(() => {
if (iconLeft !== void 0) console.warn("[Link] `iconLeft` is deprecated. Use `startIcon` instead.");
if (iconRight !== void 0) console.warn("[Link] `iconRight` is deprecated. Use `endIcon` instead.");
}, [iconLeft, iconRight]);
return /* @__PURE__ */ jsx(LinkProvider, {
value: context,
"data-size": context.size,
"data-variant": context.variant,
children: /* @__PURE__ */ jsxs(LinkBase, {
className: cs("vui-link", className),
focusRing: 2,
isUnderlined,
ref,
...styles.container,
...aliasedProps,
...rest,
children: [
isString(resolvedStartIcon) ? /* @__PURE__ */ jsx(LinkIcon, {
mr: 1,
left: 0,
name: resolvedStartIcon
}) : resolvedStartIcon,
children ? /* @__PURE__ */ jsx(T, {
fontSize: "inherit",
children
}) : isReactText(text) && /* @__PURE__ */ jsx(LinkText, { text }),
isString(resolvedEndIcon) ? /* @__PURE__ */ jsx(LinkIcon, {
ml: 1,
right: 0,
name: resolvedEndIcon
}) : resolvedEndIcon
]
})
});
});
Link.Icon = LinkIcon;
Link.Text = LinkText;
Link.displayName = "Link";
//#endregion
export { Link, Link as default, LinkBase };
globalThis.__vuiVersion__ = "5.3.1"
//# sourceMappingURL=link.js.map