@purpurds/cta-link 5.4.3 → 5.6.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purpurds/cta-link",
3
- "version": "5.4.3",
3
+ "version": "5.6.0",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "./dist/cta-link.cjs.js",
6
6
  "types": "./dist/cta-link.d.ts",
@@ -15,9 +15,9 @@
15
15
  "source": "src/cta-link.tsx",
16
16
  "dependencies": {
17
17
  "classnames": "~2.5.0",
18
- "@purpurds/icon": "5.4.3",
19
- "@purpurds/action": "5.4.3",
20
- "@purpurds/tokens": "5.4.3"
18
+ "@purpurds/action": "5.6.0",
19
+ "@purpurds/icon": "5.6.0",
20
+ "@purpurds/tokens": "5.6.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@rushstack/eslint-patch": "~1.10.0",
package/readme.mdx CHANGED
@@ -36,9 +36,9 @@ import { CtaLink } from "@purpurds/purpur";
36
36
 
37
37
  export const MyComponent = () => {
38
38
  return (
39
- <div>
40
- <CtaLink {...someProps}>Some content</CtaLink>
41
- </div>
39
+ <CtaLink href="http://telia.se" variant="primary" negative fullWidth size="sm">
40
+ Some content
41
+ </CtaLink>
42
42
  );
43
43
  };
44
44
  ```
@@ -1,7 +1,7 @@
1
1
  import React from "react";
2
2
  import * as matchers from "@testing-library/jest-dom/matchers";
3
3
  import { cleanup, render, screen } from "@testing-library/react";
4
- import { afterEach, describe, expect, it, vi } from "vitest";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
5
 
6
6
  import { CtaLink } from "./cta-link";
7
7
 
package/src/cta-link.tsx CHANGED
@@ -1,10 +1,11 @@
1
- import React, { AnchorHTMLAttributes } from "react";
1
+ import React, { AnchorHTMLAttributes, ForwardedRef, forwardRef, HTMLAttributes } from "react";
2
2
  import { ActionProps, SIZE } from "@purpurds/action";
3
3
  import { arrowLeft, arrowRight, external, Icon, phone } from "@purpurds/icon";
4
- import c from "classnames";
4
+ import c from "classnames/bind";
5
5
 
6
6
  import styles from "./cta-link.module.scss";
7
7
 
8
+ const cx = c.bind(styles);
8
9
  const rootClassName = "purpur-cta-link";
9
10
  export const ctaLinkIcons = ["forward", "external", "back", "phone"] as const;
10
11
  export type CtaLinkIcon = (typeof ctaLinkIcons)[number];
@@ -16,44 +17,77 @@ const iconMapping = {
16
17
  phone: phone,
17
18
  };
18
19
 
19
- export const CtaLink = ({
20
- children,
21
- className,
22
- ["data-testid"]: dataTestid,
23
- fullWidth = false,
24
- iconOnly,
25
- negative = false,
26
- size = SIZE.MD,
27
- variant,
28
- icon = "forward",
29
- ...props
30
- }: ActionProps & AnchorHTMLAttributes<HTMLAnchorElement> & { icon?: CtaLinkIcon }) => {
31
- const classes = c(
32
- [
33
- className,
34
- styles[rootClassName],
35
- styles[`${rootClassName}--${negative ? `${variant}-negative` : variant}`],
36
- styles[`${rootClassName}--${size}`],
37
- ],
20
+ type DefaultProps = ActionProps & { icon?: CtaLinkIcon };
21
+
22
+ type AnchorProps = DefaultProps & {
23
+ href: string;
24
+ ref?: ForwardedRef<HTMLAnchorElement>;
25
+ } & AnchorHTMLAttributes<HTMLAnchorElement>;
26
+
27
+ type SpanProps = DefaultProps & {
28
+ ref?: ForwardedRef<HTMLSpanElement>;
29
+ } & HTMLAttributes<HTMLSpanElement>;
30
+
31
+ export type CtaLinkProps = AnchorProps | SpanProps;
32
+
33
+ export const CtaLink = forwardRef<HTMLAnchorElement | HTMLSpanElement, CtaLinkProps>(
34
+ (
38
35
  {
39
- [styles[`${rootClassName}--icon-only`]]: iconOnly,
40
- [styles[`${rootClassName}--negative`]]: negative,
41
- [styles[`${rootClassName}--full-width`]]: fullWidth,
42
- }
43
- );
44
-
45
- const Tag = props.href ? "a" : "span";
46
- const IconComponent = iconMapping[icon];
47
-
48
- return (
49
- <Tag className={classes} data-testid={dataTestid} {...props}>
50
- {(icon === "back" || icon === "phone") && (
51
- <Icon svg={IconComponent} size={size === SIZE.LG ? "sm" : "xs"} />
52
- )}
53
- {!iconOnly && children}
54
- {(icon === "forward" || icon === "external") && (
55
- <Icon svg={IconComponent} size={size === SIZE.LG ? "sm" : "xs"} />
56
- )}
57
- </Tag>
58
- );
59
- };
36
+ children,
37
+ className,
38
+ ["data-testid"]: dataTestid,
39
+ fullWidth = false,
40
+ iconOnly,
41
+ negative = false,
42
+ size = SIZE.MD,
43
+ variant,
44
+ icon = "forward",
45
+ ...props
46
+ },
47
+ ref
48
+ ) => {
49
+ const classes = cx(
50
+ [
51
+ className,
52
+ rootClassName,
53
+ `${rootClassName}--${negative ? `${variant}-negative` : variant}`,
54
+ `${rootClassName}--${size}`,
55
+ ],
56
+ {
57
+ [`${rootClassName}--icon-only`]: iconOnly,
58
+ [`${rootClassName}--negative`]: negative,
59
+ [`${rootClassName}--full-width`]: fullWidth,
60
+ }
61
+ );
62
+
63
+ const IconComponent = iconMapping[icon];
64
+
65
+ const childrenWithIcons = (
66
+ <>
67
+ {(icon === "back" || icon === "phone") && (
68
+ <Icon svg={IconComponent} size={size === SIZE.LG ? "sm" : "xs"} />
69
+ )}
70
+ {!iconOnly && children}
71
+ {(icon === "forward" || icon === "external") && (
72
+ <Icon svg={IconComponent} size={size === SIZE.LG ? "sm" : "xs"} />
73
+ )}
74
+ </>
75
+ );
76
+
77
+ const sharedProps = {
78
+ ...props,
79
+ className: classes,
80
+ ["data-testid"]: dataTestid,
81
+ };
82
+
83
+ return "href" in props && props.href ? (
84
+ <a {...sharedProps} ref={ref as ForwardedRef<HTMLAnchorElement>}>
85
+ {childrenWithIcons}
86
+ </a>
87
+ ) : (
88
+ <span {...sharedProps} ref={ref as ForwardedRef<HTMLSpanElement>}>
89
+ {childrenWithIcons}
90
+ </span>
91
+ );
92
+ }
93
+ );