@sproutsocial/seeds-react-link 1.0.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/.eslintrc.js ADDED
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ root: "",
3
+ extends: ["eslint-config-seeds/racine"],
4
+ };
@@ -0,0 +1,21 @@
1
+ yarn run v1.22.22
2
+ $ tsup --dts
3
+ CLI Building entry: src/index.ts
4
+ CLI Using tsconfig: tsconfig.json
5
+ CLI tsup v8.0.2
6
+ CLI Using tsup config: /home/runner/work/seeds/seeds/seeds-react/seeds-react-link/tsup.config.ts
7
+ CLI Target: es2022
8
+ CLI Cleaning output folder
9
+ CJS Build start
10
+ ESM Build start
11
+ CJS dist/index.js 4.21 KB
12
+ CJS dist/index.js.map 5.41 KB
13
+ CJS ⚡️ Build success in 56ms
14
+ ESM dist/esm/index.js 2.27 KB
15
+ ESM dist/esm/index.js.map 5.38 KB
16
+ ESM ⚡️ Build success in 63ms
17
+ DTS Build start
18
+ DTS ⚡️ Build success in 18856ms
19
+ DTS dist/index.d.ts 1.25 KB
20
+ DTS dist/index.d.mts 1.25 KB
21
+ Done in 21.76s.
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @sproutsocial/seeds-react-link
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - ed554e3: Migrated Link and Banner to standalone packages
@@ -0,0 +1,108 @@
1
+ // src/Link.tsx
2
+ import "react";
3
+
4
+ // src/styles.ts
5
+ import styled, { css } from "styled-components";
6
+ import {
7
+ TYPOGRAPHY,
8
+ COMMON,
9
+ FLEXBOX
10
+ } from "@sproutsocial/seeds-react-system-props";
11
+ import { focusRing, disabled } from "@sproutsocial/seeds-react-mixins";
12
+ import Text from "@sproutsocial/seeds-react-text";
13
+ var Container = styled(Text)`
14
+ border: 0;
15
+ font-family: ${(props) => props.theme.fontFamily};
16
+ text-decoration: ${(props) => props.underline ? "underline" : "none"};
17
+ appearance: none;
18
+ cursor: pointer;
19
+ ${(props) => props.disabled && css`
20
+ opacity: 0.4;
21
+ cursor: not-allowed;
22
+ `}
23
+ font-weight: ${(props) => props.theme.fontWeights.semibold};
24
+ color: ${(props) => props.theme.colors.link.base};
25
+
26
+ &:hover {
27
+ color: ${(props) => props.theme.colors.link.hover};
28
+ text-decoration: underline;
29
+ }
30
+
31
+ &:active {
32
+ color: ${(props) => props.theme.colors.link.hover};
33
+ }
34
+
35
+ &:focus {
36
+ ${focusRing}
37
+ }
38
+
39
+ &:focus:active {
40
+ box-shadow: none;
41
+ }
42
+
43
+ ${(props) => !props.href && css`
44
+ background: none;
45
+ `}
46
+
47
+ ${(props) => props.disabled && disabled}
48
+
49
+ ${COMMON}
50
+ ${TYPOGRAPHY}
51
+ ${FLEXBOX}
52
+ `;
53
+ var styles_default = Container;
54
+
55
+ // src/Link.tsx
56
+ import { jsx } from "react/jsx-runtime";
57
+ var Link = ({
58
+ href,
59
+ external,
60
+ children,
61
+ disabled: disabled2,
62
+ onClick,
63
+ as,
64
+ underline = true,
65
+ qa = {},
66
+ ...rest
67
+ }) => {
68
+ if (!href && external) {
69
+ console.warn(
70
+ "Warning: external prop cannot be set without a href declaration"
71
+ );
72
+ }
73
+ const type = as || (href ? "a" : "button");
74
+ return /* @__PURE__ */ jsx(
75
+ styles_default,
76
+ {
77
+ href,
78
+ target: external ? "_blank" : void 0,
79
+ type: type === "button" ? "button" : void 0,
80
+ rel: external ? "noopener noreferrer" : void 0,
81
+ forwardedAs: type,
82
+ "aria-disabled": disabled2 ? disabled2 : void 0,
83
+ disabled: disabled2,
84
+ onClick,
85
+ underline,
86
+ "data-qa-link": "",
87
+ "data-qa-link-isdisabled": disabled2 === true,
88
+ ...qa,
89
+ ...rest,
90
+ children
91
+ }
92
+ );
93
+ };
94
+ var Link_default = Link;
95
+
96
+ // src/LinkTypes.ts
97
+ import "react";
98
+
99
+ // src/constants.ts
100
+ import { COLOR_BLUE_900 } from "@sproutsocial/seeds-color";
101
+
102
+ // src/index.ts
103
+ var src_default = Link_default;
104
+ export {
105
+ Link_default as Link,
106
+ src_default as default
107
+ };
108
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Link.tsx","../../src/styles.ts","../../src/LinkTypes.ts","../../src/constants.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport Container from \"./styles\";\nimport type { TypeLinkProps } from \"./LinkTypes\";\n\nconst Link = ({\n href,\n external,\n children,\n disabled,\n onClick,\n as,\n underline = true,\n qa = {},\n ...rest\n}: TypeLinkProps) => {\n if (!href && external) {\n // eslint-disable-next-line no-console\n console.warn(\n \"Warning: external prop cannot be set without a href declaration\"\n );\n }\n\n const type = as || (href ? \"a\" : \"button\");\n return (\n <Container\n href={href}\n target={external ? \"_blank\" : undefined}\n type={type === \"button\" ? \"button\" : undefined}\n rel={external ? \"noopener noreferrer\" : undefined}\n forwardedAs={type}\n aria-disabled={disabled ? disabled : undefined}\n disabled={disabled}\n onClick={onClick}\n underline={underline}\n data-qa-link=\"\"\n data-qa-link-isdisabled={disabled === true}\n {...qa}\n {...rest}\n >\n {children}\n </Container>\n );\n};\n\nexport default Link;\n","import styled, { css } from \"styled-components\";\nimport {\n TYPOGRAPHY,\n COMMON,\n FLEXBOX,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport { focusRing, disabled } from \"@sproutsocial/seeds-react-mixins\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport type { TypeLinkProps } from \"./LinkTypes\";\n\nconst Container = styled(Text)<TypeLinkProps>`\n border: 0;\n font-family: ${(props) => props.theme.fontFamily};\n text-decoration: ${(props) => (props.underline ? \"underline\" : \"none\")};\n appearance: none;\n cursor: pointer;\n ${(props) =>\n props.disabled &&\n css`\n opacity: 0.4;\n cursor: not-allowed;\n `}\n font-weight: ${(props) => props.theme.fontWeights.semibold};\n color: ${(props) => props.theme.colors.link.base};\n\n &:hover {\n color: ${(props) => props.theme.colors.link.hover};\n text-decoration: underline;\n }\n\n &:active {\n color: ${(props) => props.theme.colors.link.hover};\n }\n\n &:focus {\n ${focusRing}\n }\n\n &:focus:active {\n box-shadow: none;\n }\n\n ${(props) =>\n !props.href &&\n css`\n background: none;\n `}\n\n ${(props) => props.disabled && disabled}\n\n ${COMMON}\n ${TYPOGRAPHY}\n ${FLEXBOX}\n`;\n\nexport default Container;\n","import * as React from \"react\";\nimport type { TypeStyledComponentsCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeTextProps } from \"@sproutsocial/seeds-react-text\";\nimport type { TypeSystemFlexboxProps } from \"@sproutsocial/seeds-react-system-props\";\n\nexport interface TypeLinkProps\n extends Omit<\n TypeTextProps,\n keyof Omit<React.ComponentPropsWithoutRef<\"span\">, \"color\">\n >,\n Omit<React.ComponentPropsWithoutRef<\"button\">, \"color\">,\n TypeSystemFlexboxProps {\n /** Optional prop to make the URL open in a new tab */\n external?: boolean;\n children: React.ReactNode;\n\n /** Setting this prop will cause the component to be rendered as a link */\n href?: string;\n\n /** Disables user action and applies a disabled style to the component */\n disabled?: boolean;\n\n /** Can be used in addition to an href but still renders as a link. Omitting href will render as button */\n onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;\n as?: TypeStyledComponentsCommonProps[\"as\"];\n underline?: boolean;\n qa?: { [key: string]: unknown }; // should this be string|number?\n}\n","import { COLOR_BLUE_900 } from \"@sproutsocial/seeds-color\";\n\nconst defaultLink = {\n color: \"link\",\n hoverColor: \"link.hover\",\n activeColor: COLOR_BLUE_900,\n fontWeight: \"semibold\",\n};\n\nconst linkTheme = {\n default: defaultLink,\n};\n\nexport default linkTheme;\n","import Link from \"./Link\";\n\nexport default Link;\nexport { Link };\nexport * from \"./LinkTypes\";\nexport * from \"./constants\";\n"],"mappings":";AAAA,OAAuB;;;ACAvB,OAAO,UAAU,WAAW;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW,gBAAgB;AACpC,OAAO,UAAU;AAGjB,IAAM,YAAY,OAAO,IAAI;AAAA;AAAA,iBAEZ,CAAC,UAAU,MAAM,MAAM,UAAU;AAAA,qBAC7B,CAAC,UAAW,MAAM,YAAY,cAAc,MAAO;AAAA;AAAA;AAAA,IAGpE,CAAC,UACD,MAAM,YACN;AAAA;AAAA;AAAA,KAGC;AAAA,iBACY,CAAC,UAAU,MAAM,MAAM,YAAY,QAAQ;AAAA,WACjD,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,IAAI;AAAA;AAAA;AAAA,aAGrC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,aAKxC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA,MAI/C,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOX,CAAC,UACD,CAAC,MAAM,QACP;AAAA;AAAA,KAEC;AAAA;AAAA,IAED,CAAC,UAAU,MAAM,YAAY,QAAQ;AAAA;AAAA,KAEpC,MAAM;AAAA,KACN,UAAU;AAAA,KACV,OAAO;AAAA;AAGZ,IAAO,iBAAQ;;;AD/BX;AApBJ,IAAM,OAAO,CAAC;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,KAAK,CAAC;AAAA,EACN,GAAG;AACL,MAAqB;AACnB,MAAI,CAAC,QAAQ,UAAU;AAErB,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,OAAO,OAAO,MAAM;AACjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ,WAAW,WAAW;AAAA,MAC9B,MAAM,SAAS,WAAW,WAAW;AAAA,MACrC,KAAK,WAAW,wBAAwB;AAAA,MACxC,aAAa;AAAA,MACb,iBAAeA,YAAWA,YAAW;AAAA,MACrC,UAAUA;AAAA,MACV;AAAA,MACA;AAAA,MACA,gBAAa;AAAA,MACb,2BAAyBA,cAAa;AAAA,MACrC,GAAG;AAAA,MACH,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,eAAQ;;;AE5Cf,OAAuB;;;ACAvB,SAAS,sBAAsB;;;ACE/B,IAAO,cAAQ;","names":["disabled"]}
@@ -0,0 +1,25 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { TypeSystemFlexboxProps, TypeStyledComponentsCommonProps } from '@sproutsocial/seeds-react-system-props';
4
+ import { TypeTextProps } from '@sproutsocial/seeds-react-text';
5
+
6
+ interface TypeLinkProps extends Omit<TypeTextProps, keyof Omit<React.ComponentPropsWithoutRef<"span">, "color">>, Omit<React.ComponentPropsWithoutRef<"button">, "color">, TypeSystemFlexboxProps {
7
+ /** Optional prop to make the URL open in a new tab */
8
+ external?: boolean;
9
+ children: React.ReactNode;
10
+ /** Setting this prop will cause the component to be rendered as a link */
11
+ href?: string;
12
+ /** Disables user action and applies a disabled style to the component */
13
+ disabled?: boolean;
14
+ /** Can be used in addition to an href but still renders as a link. Omitting href will render as button */
15
+ onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;
16
+ as?: TypeStyledComponentsCommonProps["as"];
17
+ underline?: boolean;
18
+ qa?: {
19
+ [key: string]: unknown;
20
+ };
21
+ }
22
+
23
+ declare const Link: ({ href, external, children, disabled, onClick, as, underline, qa, ...rest }: TypeLinkProps) => react_jsx_runtime.JSX.Element;
24
+
25
+ export { Link, type TypeLinkProps, Link as default };
@@ -0,0 +1,25 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { TypeSystemFlexboxProps, TypeStyledComponentsCommonProps } from '@sproutsocial/seeds-react-system-props';
4
+ import { TypeTextProps } from '@sproutsocial/seeds-react-text';
5
+
6
+ interface TypeLinkProps extends Omit<TypeTextProps, keyof Omit<React.ComponentPropsWithoutRef<"span">, "color">>, Omit<React.ComponentPropsWithoutRef<"button">, "color">, TypeSystemFlexboxProps {
7
+ /** Optional prop to make the URL open in a new tab */
8
+ external?: boolean;
9
+ children: React.ReactNode;
10
+ /** Setting this prop will cause the component to be rendered as a link */
11
+ href?: string;
12
+ /** Disables user action and applies a disabled style to the component */
13
+ disabled?: boolean;
14
+ /** Can be used in addition to an href but still renders as a link. Omitting href will render as button */
15
+ onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;
16
+ as?: TypeStyledComponentsCommonProps["as"];
17
+ underline?: boolean;
18
+ qa?: {
19
+ [key: string]: unknown;
20
+ };
21
+ }
22
+
23
+ declare const Link: ({ href, external, children, disabled, onClick, as, underline, qa, ...rest }: TypeLinkProps) => react_jsx_runtime.JSX.Element;
24
+
25
+ export { Link, type TypeLinkProps, Link as default };
package/dist/index.js ADDED
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ Link: () => Link_default,
34
+ default: () => src_default
35
+ });
36
+ module.exports = __toCommonJS(src_exports);
37
+
38
+ // src/Link.tsx
39
+ var React = require("react");
40
+
41
+ // src/styles.ts
42
+ var import_styled_components = __toESM(require("styled-components"));
43
+ var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
44
+ var import_seeds_react_mixins = require("@sproutsocial/seeds-react-mixins");
45
+ var import_seeds_react_text = __toESM(require("@sproutsocial/seeds-react-text"));
46
+ var Container = (0, import_styled_components.default)(import_seeds_react_text.default)`
47
+ border: 0;
48
+ font-family: ${(props) => props.theme.fontFamily};
49
+ text-decoration: ${(props) => props.underline ? "underline" : "none"};
50
+ appearance: none;
51
+ cursor: pointer;
52
+ ${(props) => props.disabled && import_styled_components.css`
53
+ opacity: 0.4;
54
+ cursor: not-allowed;
55
+ `}
56
+ font-weight: ${(props) => props.theme.fontWeights.semibold};
57
+ color: ${(props) => props.theme.colors.link.base};
58
+
59
+ &:hover {
60
+ color: ${(props) => props.theme.colors.link.hover};
61
+ text-decoration: underline;
62
+ }
63
+
64
+ &:active {
65
+ color: ${(props) => props.theme.colors.link.hover};
66
+ }
67
+
68
+ &:focus {
69
+ ${import_seeds_react_mixins.focusRing}
70
+ }
71
+
72
+ &:focus:active {
73
+ box-shadow: none;
74
+ }
75
+
76
+ ${(props) => !props.href && import_styled_components.css`
77
+ background: none;
78
+ `}
79
+
80
+ ${(props) => props.disabled && import_seeds_react_mixins.disabled}
81
+
82
+ ${import_seeds_react_system_props.COMMON}
83
+ ${import_seeds_react_system_props.TYPOGRAPHY}
84
+ ${import_seeds_react_system_props.FLEXBOX}
85
+ `;
86
+ var styles_default = Container;
87
+
88
+ // src/Link.tsx
89
+ var import_jsx_runtime = require("react/jsx-runtime");
90
+ var Link = ({
91
+ href,
92
+ external,
93
+ children,
94
+ disabled: disabled2,
95
+ onClick,
96
+ as,
97
+ underline = true,
98
+ qa = {},
99
+ ...rest
100
+ }) => {
101
+ if (!href && external) {
102
+ console.warn(
103
+ "Warning: external prop cannot be set without a href declaration"
104
+ );
105
+ }
106
+ const type = as || (href ? "a" : "button");
107
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
108
+ styles_default,
109
+ {
110
+ href,
111
+ target: external ? "_blank" : void 0,
112
+ type: type === "button" ? "button" : void 0,
113
+ rel: external ? "noopener noreferrer" : void 0,
114
+ forwardedAs: type,
115
+ "aria-disabled": disabled2 ? disabled2 : void 0,
116
+ disabled: disabled2,
117
+ onClick,
118
+ underline,
119
+ "data-qa-link": "",
120
+ "data-qa-link-isdisabled": disabled2 === true,
121
+ ...qa,
122
+ ...rest,
123
+ children
124
+ }
125
+ );
126
+ };
127
+ var Link_default = Link;
128
+
129
+ // src/LinkTypes.ts
130
+ var React2 = require("react");
131
+
132
+ // src/constants.ts
133
+ var import_seeds_color = require("@sproutsocial/seeds-color");
134
+
135
+ // src/index.ts
136
+ var src_default = Link_default;
137
+ // Annotate the CommonJS export names for ESM import in node:
138
+ 0 && (module.exports = {
139
+ Link
140
+ });
141
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/Link.tsx","../src/styles.ts","../src/LinkTypes.ts","../src/constants.ts"],"sourcesContent":["import Link from \"./Link\";\n\nexport default Link;\nexport { Link };\nexport * from \"./LinkTypes\";\nexport * from \"./constants\";\n","import * as React from \"react\";\nimport Container from \"./styles\";\nimport type { TypeLinkProps } from \"./LinkTypes\";\n\nconst Link = ({\n href,\n external,\n children,\n disabled,\n onClick,\n as,\n underline = true,\n qa = {},\n ...rest\n}: TypeLinkProps) => {\n if (!href && external) {\n // eslint-disable-next-line no-console\n console.warn(\n \"Warning: external prop cannot be set without a href declaration\"\n );\n }\n\n const type = as || (href ? \"a\" : \"button\");\n return (\n <Container\n href={href}\n target={external ? \"_blank\" : undefined}\n type={type === \"button\" ? \"button\" : undefined}\n rel={external ? \"noopener noreferrer\" : undefined}\n forwardedAs={type}\n aria-disabled={disabled ? disabled : undefined}\n disabled={disabled}\n onClick={onClick}\n underline={underline}\n data-qa-link=\"\"\n data-qa-link-isdisabled={disabled === true}\n {...qa}\n {...rest}\n >\n {children}\n </Container>\n );\n};\n\nexport default Link;\n","import styled, { css } from \"styled-components\";\nimport {\n TYPOGRAPHY,\n COMMON,\n FLEXBOX,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport { focusRing, disabled } from \"@sproutsocial/seeds-react-mixins\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport type { TypeLinkProps } from \"./LinkTypes\";\n\nconst Container = styled(Text)<TypeLinkProps>`\n border: 0;\n font-family: ${(props) => props.theme.fontFamily};\n text-decoration: ${(props) => (props.underline ? \"underline\" : \"none\")};\n appearance: none;\n cursor: pointer;\n ${(props) =>\n props.disabled &&\n css`\n opacity: 0.4;\n cursor: not-allowed;\n `}\n font-weight: ${(props) => props.theme.fontWeights.semibold};\n color: ${(props) => props.theme.colors.link.base};\n\n &:hover {\n color: ${(props) => props.theme.colors.link.hover};\n text-decoration: underline;\n }\n\n &:active {\n color: ${(props) => props.theme.colors.link.hover};\n }\n\n &:focus {\n ${focusRing}\n }\n\n &:focus:active {\n box-shadow: none;\n }\n\n ${(props) =>\n !props.href &&\n css`\n background: none;\n `}\n\n ${(props) => props.disabled && disabled}\n\n ${COMMON}\n ${TYPOGRAPHY}\n ${FLEXBOX}\n`;\n\nexport default Container;\n","import * as React from \"react\";\nimport type { TypeStyledComponentsCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeTextProps } from \"@sproutsocial/seeds-react-text\";\nimport type { TypeSystemFlexboxProps } from \"@sproutsocial/seeds-react-system-props\";\n\nexport interface TypeLinkProps\n extends Omit<\n TypeTextProps,\n keyof Omit<React.ComponentPropsWithoutRef<\"span\">, \"color\">\n >,\n Omit<React.ComponentPropsWithoutRef<\"button\">, \"color\">,\n TypeSystemFlexboxProps {\n /** Optional prop to make the URL open in a new tab */\n external?: boolean;\n children: React.ReactNode;\n\n /** Setting this prop will cause the component to be rendered as a link */\n href?: string;\n\n /** Disables user action and applies a disabled style to the component */\n disabled?: boolean;\n\n /** Can be used in addition to an href but still renders as a link. Omitting href will render as button */\n onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;\n as?: TypeStyledComponentsCommonProps[\"as\"];\n underline?: boolean;\n qa?: { [key: string]: unknown }; // should this be string|number?\n}\n","import { COLOR_BLUE_900 } from \"@sproutsocial/seeds-color\";\n\nconst defaultLink = {\n color: \"link\",\n hoverColor: \"link.hover\",\n activeColor: COLOR_BLUE_900,\n fontWeight: \"semibold\",\n};\n\nconst linkTheme = {\n default: defaultLink,\n};\n\nexport default linkTheme;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;;;ACAvB,+BAA4B;AAC5B,sCAIO;AACP,gCAAoC;AACpC,8BAAiB;AAGjB,IAAM,gBAAY,yBAAAA,SAAO,wBAAAC,OAAI;AAAA;AAAA,iBAEZ,CAAC,UAAU,MAAM,MAAM,UAAU;AAAA,qBAC7B,CAAC,UAAW,MAAM,YAAY,cAAc,MAAO;AAAA;AAAA;AAAA,IAGpE,CAAC,UACD,MAAM,YACN;AAAA;AAAA;AAAA,KAGC;AAAA,iBACY,CAAC,UAAU,MAAM,MAAM,YAAY,QAAQ;AAAA,WACjD,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,IAAI;AAAA;AAAA;AAAA,aAGrC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,aAKxC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA,MAI/C,mCAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOX,CAAC,UACD,CAAC,MAAM,QACP;AAAA;AAAA,KAEC;AAAA;AAAA,IAED,CAAC,UAAU,MAAM,YAAY,kCAAQ;AAAA;AAAA,KAEpC,sCAAM;AAAA,KACN,0CAAU;AAAA,KACV,uCAAO;AAAA;AAGZ,IAAO,iBAAQ;;;AD/BX;AApBJ,IAAM,OAAO,CAAC;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,KAAK,CAAC;AAAA,EACN,GAAG;AACL,MAAqB;AACnB,MAAI,CAAC,QAAQ,UAAU;AAErB,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,OAAO,OAAO,MAAM;AACjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ,WAAW,WAAW;AAAA,MAC9B,MAAM,SAAS,WAAW,WAAW;AAAA,MACrC,KAAK,WAAW,wBAAwB;AAAA,MACxC,aAAa;AAAA,MACb,iBAAeA,YAAWA,YAAW;AAAA,MACrC,UAAUA;AAAA,MACV;AAAA,MACA;AAAA,MACA,gBAAa;AAAA,MACb,2BAAyBA,cAAa;AAAA,MACrC,GAAG;AAAA,MACH,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,eAAQ;;;AE5Cf,IAAAC,SAAuB;;;ACAvB,yBAA+B;;;AJE/B,IAAO,cAAQ;","names":["styled","Text","disabled","React"]}
package/jest.config.js ADDED
@@ -0,0 +1,9 @@
1
+ const baseConfig = require("@sproutsocial/seeds-testing");
2
+
3
+ /** * @type {import('jest').Config} */
4
+ const config = {
5
+ ...baseConfig,
6
+ displayName: "seeds-react-link",
7
+ };
8
+
9
+ module.exports = config;
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@sproutsocial/seeds-react-link",
3
+ "version": "1.0.0",
4
+ "description": "Seeds React Link",
5
+ "author": "Sprout Social, Inc.",
6
+ "license": "MIT",
7
+ "main": "dist/index.js",
8
+ "module": "dist/esm/index.js",
9
+ "types": "dist/index.d.ts",
10
+ "scripts": {
11
+ "build": "tsup --dts",
12
+ "build:debug": "tsup --dts --metafile",
13
+ "dev": "tsup --watch --dts",
14
+ "clean": "rm -rf .turbo dist",
15
+ "clean:modules": "rm -rf node_modules",
16
+ "typecheck": "tsc --noEmit",
17
+ "test": "jest",
18
+ "test:watch": "jest --watch --coverage=false"
19
+ },
20
+ "dependencies": {
21
+ "@sproutsocial/seeds-react-theme": "^*",
22
+ "@sproutsocial/seeds-react-system-props": "^*",
23
+ "@sproutsocial/seeds-react-mixins": "*",
24
+ "@sproutsocial/seeds-react-text": "*",
25
+ "@sproutsocial/seeds-color": "*"
26
+ },
27
+ "devDependencies": {
28
+ "@types/react": "^18.0.0",
29
+ "@types/styled-components": "^5.1.26",
30
+ "@sproutsocial/eslint-config-seeds": "*",
31
+ "react": "^18.0.0",
32
+ "styled-components": "^5.2.3",
33
+ "tsup": "^8.0.2",
34
+ "typescript": "^5.6.2",
35
+ "@sproutsocial/seeds-tsconfig": "*",
36
+ "@sproutsocial/seeds-testing": "*",
37
+ "@sproutsocial/seeds-react-testing-library": "*",
38
+ "@sproutsocial/seeds-react-icon": "*",
39
+ "@sproutsocial/seeds-react-box": "*"
40
+ },
41
+ "peerDependencies": {
42
+ "styled-components": "^5.2.3"
43
+ },
44
+ "engines": {
45
+ "node": ">=18"
46
+ }
47
+ }
package/src/Link.tsx ADDED
@@ -0,0 +1,45 @@
1
+ import * as React from "react";
2
+ import Container from "./styles";
3
+ import type { TypeLinkProps } from "./LinkTypes";
4
+
5
+ const Link = ({
6
+ href,
7
+ external,
8
+ children,
9
+ disabled,
10
+ onClick,
11
+ as,
12
+ underline = true,
13
+ qa = {},
14
+ ...rest
15
+ }: TypeLinkProps) => {
16
+ if (!href && external) {
17
+ // eslint-disable-next-line no-console
18
+ console.warn(
19
+ "Warning: external prop cannot be set without a href declaration"
20
+ );
21
+ }
22
+
23
+ const type = as || (href ? "a" : "button");
24
+ return (
25
+ <Container
26
+ href={href}
27
+ target={external ? "_blank" : undefined}
28
+ type={type === "button" ? "button" : undefined}
29
+ rel={external ? "noopener noreferrer" : undefined}
30
+ forwardedAs={type}
31
+ aria-disabled={disabled ? disabled : undefined}
32
+ disabled={disabled}
33
+ onClick={onClick}
34
+ underline={underline}
35
+ data-qa-link=""
36
+ data-qa-link-isdisabled={disabled === true}
37
+ {...qa}
38
+ {...rest}
39
+ >
40
+ {children}
41
+ </Container>
42
+ );
43
+ };
44
+
45
+ export default Link;
@@ -0,0 +1,28 @@
1
+ import * as React from "react";
2
+ import type { TypeStyledComponentsCommonProps } from "@sproutsocial/seeds-react-system-props";
3
+ import type { TypeTextProps } from "@sproutsocial/seeds-react-text";
4
+ import type { TypeSystemFlexboxProps } from "@sproutsocial/seeds-react-system-props";
5
+
6
+ export interface TypeLinkProps
7
+ extends Omit<
8
+ TypeTextProps,
9
+ keyof Omit<React.ComponentPropsWithoutRef<"span">, "color">
10
+ >,
11
+ Omit<React.ComponentPropsWithoutRef<"button">, "color">,
12
+ TypeSystemFlexboxProps {
13
+ /** Optional prop to make the URL open in a new tab */
14
+ external?: boolean;
15
+ children: React.ReactNode;
16
+
17
+ /** Setting this prop will cause the component to be rendered as a link */
18
+ href?: string;
19
+
20
+ /** Disables user action and applies a disabled style to the component */
21
+ disabled?: boolean;
22
+
23
+ /** Can be used in addition to an href but still renders as a link. Omitting href will render as button */
24
+ onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;
25
+ as?: TypeStyledComponentsCommonProps["as"];
26
+ underline?: boolean;
27
+ qa?: { [key: string]: unknown }; // should this be string|number?
28
+ }
@@ -0,0 +1,111 @@
1
+ import React from "react";
2
+ import { TYPOGRAPHY_SIZE_600 } from "@sproutsocial/seeds-typography";
3
+ import { render, screen } from "@sproutsocial/seeds-react-testing-library";
4
+ import Link from "../Link";
5
+
6
+ describe("Racine Link", () => {
7
+ it("should render in an anchor tag", () => {
8
+ render(
9
+ <Link href="http://sproutsocial.style" external>
10
+ Link
11
+ </Link>
12
+ );
13
+ expect(screen.getByText("Link")).toBeInTheDocument();
14
+ });
15
+
16
+ it("should render disabled", () => {
17
+ render(
18
+ <>
19
+ <Link>Regular Link</Link>
20
+ <Link disabled>Disabled Link</Link>
21
+ </>
22
+ );
23
+ expect(screen.getByText("Regular Link")).toBeEnabled();
24
+ expect(screen.getByText("Disabled Link")).toBeDisabled();
25
+ });
26
+
27
+ it("setting external to prop true should add target blank attribute to anchor", () => {
28
+ render(
29
+ <Link href="http://sproutsocial.com" external>
30
+ Link
31
+ </Link>
32
+ );
33
+ expect(screen.getByText("Link").closest("a")?.target).toEqual("_blank");
34
+ });
35
+
36
+ it("setting external to prop true should add rel='noopener' attribute", () => {
37
+ render(
38
+ <Link href="http://sproutsocial.com" external>
39
+ Link
40
+ </Link>
41
+ );
42
+ expect(screen.getByText("Link").closest("a")?.rel).toEqual(
43
+ "noopener noreferrer"
44
+ );
45
+ });
46
+
47
+ it("setting a onClick instead of href renders component as a Button", () => {
48
+ render(
49
+ <Link
50
+ onClick={() => {
51
+ // eslint-disable-next-line no-console
52
+ console.log("Button");
53
+ }}
54
+ >
55
+ Am I a button?
56
+ </Link>
57
+ );
58
+ expect(screen.getByText("Am I a button?").tagName).toEqual("BUTTON");
59
+ });
60
+
61
+ it("setting both href and onClick renders component as an Anchor", () => {
62
+ render(
63
+ <Link
64
+ href="http://sproutsocial.com"
65
+ onClick={() => {
66
+ // eslint-disable-next-line no-console
67
+ console.log("Button");
68
+ }}
69
+ >
70
+ Am I a button?
71
+ </Link>
72
+ );
73
+ expect(screen.getByText("Am I a button?").tagName).toEqual("A");
74
+ });
75
+
76
+ it("Using the 'as' prop works as expected and retains styles from Text and Link", () => {
77
+ render(
78
+ <Link
79
+ as="span"
80
+ fontSize={600}
81
+ href="//sproutsocial.com/seeds/components/link"
82
+ >
83
+ Link as span
84
+ </Link>
85
+ );
86
+ expect(screen.getByText("Link as span").tagName).toEqual("SPAN");
87
+ expect(screen.getByText("Link as span")).toHaveStyleRule(
88
+ "font-size",
89
+ TYPOGRAPHY_SIZE_600.fontSize
90
+ );
91
+ });
92
+
93
+ it("Has type attribute as button when rendered as a button element", () => {
94
+ render(<Link>Link</Link>);
95
+ expect(screen.getByDataQaLabel({ link: "" }).tagName).toEqual("BUTTON");
96
+ });
97
+
98
+ it("Does not have type attribute when rendered as an anchor element", () => {
99
+ render(<Link href="google.com">Link</Link>);
100
+ expect(screen.getByDataQaLabel({ link: "" })).not.toHaveAttribute("type");
101
+ expect(screen.getByDataQaLabel({ link: "" }).tagName).not.toEqual("BUTTON");
102
+ });
103
+
104
+ it("Can render with an underline", () => {
105
+ render(<Link underline>Link</Link>);
106
+ expect(screen.getByText("Link")).toHaveStyleRule(
107
+ "text-decoration",
108
+ "underline"
109
+ );
110
+ });
111
+ });
@@ -0,0 +1,47 @@
1
+ import React, { Fragment } from "react";
2
+ import { render } from "@sproutsocial/seeds-react-testing-library";
3
+ import Link from "../Link";
4
+
5
+ describe("Link Types", () => {
6
+ it("should render valid props", () => {
7
+ render(
8
+ <Fragment>
9
+ <Link href="http://sproutsocial.style">Link</Link>
10
+ <Link href="http://sproutsocial.style" external={false}>
11
+ Link
12
+ </Link>
13
+ <Link href="http://sproutsocial.style" external>
14
+ Link
15
+ </Link>
16
+ <Link href="#anchor">Link</Link>
17
+ <Link onClick={jest.fn()}>Link</Link>
18
+ <Link
19
+ fontSize={200}
20
+ fontWeight="bold"
21
+ color="text.subtext"
22
+ href="#anchor"
23
+ >
24
+ Link
25
+ </Link>
26
+ <Link
27
+ title="title"
28
+ fontSize={200}
29
+ fontWeight="bold"
30
+ href="#anchor"
31
+ external
32
+ truncated
33
+ ml="300"
34
+ style={{ whiteSpace: "nowrap" }}
35
+ >
36
+ Link
37
+ </Link>
38
+ {/* @ts-expect-error -test that childess is rejected */}
39
+ <Link fontSize={200} fontWeight="bold" href="#anchor" />
40
+ {/* @ts-expect-error -test that improper front size is rejected */}
41
+ <Link fontSize="12" href="link.com">
42
+ Link
43
+ </Link>
44
+ </Fragment>
45
+ );
46
+ });
47
+ });
@@ -0,0 +1,14 @@
1
+ import { COLOR_BLUE_900 } from "@sproutsocial/seeds-color";
2
+
3
+ const defaultLink = {
4
+ color: "link",
5
+ hoverColor: "link.hover",
6
+ activeColor: COLOR_BLUE_900,
7
+ fontWeight: "semibold",
8
+ };
9
+
10
+ const linkTheme = {
11
+ default: defaultLink,
12
+ };
13
+
14
+ export default linkTheme;
@@ -0,0 +1,101 @@
1
+ import React from "react";
2
+ // @ts-ignore-next-line: TS hates that this isn't part of the package.json vite magic
3
+ import { Banner } from "@sproutsocial/seeds-react-banner";
4
+ import { Box } from "@sproutsocial/seeds-react-box";
5
+ import { Icon } from "@sproutsocial/seeds-react-icon";
6
+ import { Link } from "./";
7
+ import { Text } from "@sproutsocial/seeds-react-text";
8
+ import type { Meta, StoryObj } from "@storybook/react";
9
+
10
+ const meta: Meta<typeof Link> = {
11
+ title: "Components/Link",
12
+ component: Link,
13
+ args: {
14
+ href: "?path=/story/components-button--primary",
15
+ children: "Normal link",
16
+ external: false,
17
+ },
18
+ };
19
+
20
+ export default meta;
21
+
22
+ type Story = StoryObj<typeof Link>;
23
+
24
+ export const NormalLink: Story = {
25
+ args: {
26
+ href: "?path=/story/components-button--primary",
27
+ children: "Normal link",
28
+ external: false,
29
+ },
30
+ };
31
+
32
+ export const ExternalLink: Story = {
33
+ render: (args) => (
34
+ <Link {...args}>
35
+ <Box display="flex" alignItems="center">
36
+ External link
37
+ <Icon
38
+ ml={200}
39
+ size="mini"
40
+ name="arrow-right-up-solid"
41
+ role={undefined}
42
+ svgProps={{ role: "img", "aria-label": "opens in a new tab" }}
43
+ />
44
+ </Box>
45
+ </Link>
46
+ ),
47
+ args: {
48
+ href: "#YouClickedAnExternalLink",
49
+ external: true,
50
+ children: "Opens in a new tab",
51
+ },
52
+ };
53
+
54
+ export const LinkAsAButton: Story = {
55
+ render: (args) => (
56
+ <Link
57
+ onClick={() => {
58
+ alert("You clicked a Button that looks like a Link!");
59
+ }}
60
+ >
61
+ {args.children}
62
+ </Link>
63
+ ),
64
+ args: {
65
+ children: "Primary Link",
66
+ },
67
+ };
68
+
69
+ export const UnderlinedLink: Story = {
70
+ render: (args) => <Link underline={false}>{args.children}</Link>,
71
+ args: {
72
+ children: "Link underline set to false",
73
+ },
74
+ };
75
+
76
+ export const DecorativeBackgrounds: Story = {
77
+ render: () => (
78
+ <Banner
79
+ text={
80
+ <Box
81
+ width={1}
82
+ display="flex"
83
+ alignItems="center"
84
+ justifyContent="space-between"
85
+ >
86
+ <Text>Banners use decorative backgrounds</Text>
87
+ <Link external href="https://seeds.sproutsocial.com/components/link">
88
+ Links use text.body
89
+ <Icon
90
+ ml={200}
91
+ size="mini"
92
+ name="arrow-right-up-solid"
93
+ role={undefined}
94
+ svgProps={{ role: "img", "aria-label": "opens in a new tab" }}
95
+ />
96
+ </Link>
97
+ </Box>
98
+ }
99
+ />
100
+ ),
101
+ };
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ import Link from "./Link";
2
+
3
+ export default Link;
4
+ export { Link };
5
+ export * from "./LinkTypes";
6
+ export * from "./constants";
package/src/styles.ts ADDED
@@ -0,0 +1,56 @@
1
+ import styled, { css } from "styled-components";
2
+ import {
3
+ TYPOGRAPHY,
4
+ COMMON,
5
+ FLEXBOX,
6
+ } from "@sproutsocial/seeds-react-system-props";
7
+ import { focusRing, disabled } from "@sproutsocial/seeds-react-mixins";
8
+ import Text from "@sproutsocial/seeds-react-text";
9
+ import type { TypeLinkProps } from "./LinkTypes";
10
+
11
+ const Container = styled(Text)<TypeLinkProps>`
12
+ border: 0;
13
+ font-family: ${(props) => props.theme.fontFamily};
14
+ text-decoration: ${(props) => (props.underline ? "underline" : "none")};
15
+ appearance: none;
16
+ cursor: pointer;
17
+ ${(props) =>
18
+ props.disabled &&
19
+ css`
20
+ opacity: 0.4;
21
+ cursor: not-allowed;
22
+ `}
23
+ font-weight: ${(props) => props.theme.fontWeights.semibold};
24
+ color: ${(props) => props.theme.colors.link.base};
25
+
26
+ &:hover {
27
+ color: ${(props) => props.theme.colors.link.hover};
28
+ text-decoration: underline;
29
+ }
30
+
31
+ &:active {
32
+ color: ${(props) => props.theme.colors.link.hover};
33
+ }
34
+
35
+ &:focus {
36
+ ${focusRing}
37
+ }
38
+
39
+ &:focus:active {
40
+ box-shadow: none;
41
+ }
42
+
43
+ ${(props) =>
44
+ !props.href &&
45
+ css`
46
+ background: none;
47
+ `}
48
+
49
+ ${(props) => props.disabled && disabled}
50
+
51
+ ${COMMON}
52
+ ${TYPOGRAPHY}
53
+ ${FLEXBOX}
54
+ `;
55
+
56
+ export default Container;
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@sproutsocial/seeds-tsconfig/bundler/dom/library-monorepo",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "module": "esnext"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "dist"]
9
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig((options) => ({
4
+ entry: ["src/index.ts"],
5
+ format: ["cjs", "esm"],
6
+ clean: true,
7
+ legacyOutput: true,
8
+ dts: options.dts,
9
+ external: ["react"],
10
+ sourcemap: true,
11
+ metafile: options.metafile,
12
+ }));