@purpurds/link 3.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.
@@ -0,0 +1,31 @@
1
+ Name: classnames
2
+ Version: 2.5.1
3
+ License: MIT
4
+ Private: false
5
+ Description: A simple utility for conditionally joining classNames together
6
+ Repository: git+https://github.com/JedWatson/classnames.git
7
+ Author: Jed Watson
8
+ License Copyright:
9
+ ===
10
+
11
+ The MIT License (MIT)
12
+
13
+ Copyright (c) 2018 Jed Watson
14
+
15
+ Permission is hereby granted, free of charge, to any person obtaining a copy
16
+ of this software and associated documentation files (the "Software"), to deal
17
+ in the Software without restriction, including without limitation the rights
18
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19
+ copies of the Software, and to permit persons to whom the Software is
20
+ furnished to do so, subject to the following conditions:
21
+
22
+ The above copyright notice and this permission notice shall be included in all
23
+ copies or substantial portions of the Software.
24
+
25
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react/jsx-runtime");function v(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var _={exports:{}};/*!
2
+ Copyright (c) 2018 Jed Watson.
3
+ Licensed under the MIT License (MIT), see
4
+ http://jedwatson.github.io/classnames
5
+ */(function(n){(function(){var a={}.hasOwnProperty;function r(){for(var t="",e=0;e<arguments.length;e++){var i=arguments[e];i&&(t=u(t,l.call(this,i)))}return t}function l(t){if(typeof t=="string"||typeof t=="number")return this&&this[t]||t;if(typeof t!="object")return"";if(Array.isArray(t))return r.apply(this,t);if(t.toString!==Object.prototype.toString&&!t.toString.toString().includes("[native code]"))return t.toString();var e="";for(var i in t)a.call(t,i)&&t[i]&&(e=u(e,this&&this[i]||i));return e}function u(t,e){return e?t?t+" "+e:t+e:t}n.exports?(r.default=r,n.exports=r):window.classNames=r})()})(_);var f=_.exports;const k=v(f),g={"purpur-link":"_purpur-link_eselc_1","purpur-link--text":"_purpur-link--text_eselc_15","purpur-link--standalone":"_purpur-link--standalone_eselc_15","purpur-link--navigation":"_purpur-link--navigation_eselc_15","purpur-link--disable-visited":"_purpur-link--disable-visited_eselc_25","purpur-link--text-negative":"_purpur-link--text-negative_eselc_28","purpur-link--standalone-negative":"_purpur-link--standalone-negative_eselc_28","purpur-link--navigation-negative":"_purpur-link--navigation-negative_eselc_28","purpur-link--ensure-target-area":"_purpur-link--ensure-target-area_eselc_67","purpur-link--silent":"_purpur-link--silent_eselc_73"},N=k.bind(g),s="purpur-link",d={TEXT:"text",TEXT_NEGATIVE:"text-negative",STANDALONE:"standalone",STANDALONE_NEGATIVE:"standalone-negative",NAVIGATION:"navigation",NAVIGATION_NEGATIVE:"navigation-negative"},A=Object.values(d),T=({["data-testid"]:n,children:a,className:r,disableVisited:l,ensureTargetArea:u,href:t,silent:e,target:i,variant:p,...o})=>c.jsx("span",{className:N([r,s,`${s}--${p}`,{[`${s}--silent`]:e,[`${s}--negative`]:p.endsWith("negative"),[`${s}--disable-visited`]:l??e,[`${s}--ensure-target-area`]:u}]),"data-testid":n,...o,children:t?c.jsx("a",{href:t,target:i,...o,children:a}):a});exports.LINK_VARIANT=d;exports.Link=T;exports.linkVariants=A;
6
+ //# sourceMappingURL=link.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.cjs.js","sources":["../../../common/temp/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/bind.js","../src/link.tsx"],"sourcesContent":["/*!\n\tCopyright (c) 2018 Jed Watson.\n\tLicensed under the MIT License (MIT), see\n\thttp://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\n\tfunction classNames () {\n\t\tvar classes = '';\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\tvar arg = arguments[i];\n\t\t\tif (arg) {\n\t\t\t\tclasses = appendClass(classes, parseValue.call(this, arg));\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction parseValue (arg) {\n\t\tif (typeof arg === 'string' || typeof arg === 'number') {\n\t\t\treturn this && this[arg] || arg;\n\t\t}\n\n\t\tif (typeof arg !== 'object') {\n\t\t\treturn '';\n\t\t}\n\n\t\tif (Array.isArray(arg)) {\n\t\t\treturn classNames.apply(this, arg);\n\t\t}\n\n\t\tif (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {\n\t\t\treturn arg.toString();\n\t\t}\n\n\t\tvar classes = '';\n\n\t\tfor (var key in arg) {\n\t\t\tif (hasOwn.call(arg, key) && arg[key]) {\n\t\t\t\tclasses = appendClass(classes, this && this[key] || key);\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction appendClass (value, newClass) {\n\t\tif (!newClass) {\n\t\t\treturn value;\n\t\t}\n\t\n\t\tif (value) {\n\t\t\treturn value + ' ' + newClass;\n\t\t}\n\t\n\t\treturn value + newClass;\n\t}\n\n\tif (typeof module !== 'undefined' && module.exports) {\n\t\tclassNames.default = classNames;\n\t\tmodule.exports = classNames;\n\t} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\t\t// register as 'classnames', consistent with npm package name\n\t\tdefine('classnames', [], function () {\n\t\t\treturn classNames;\n\t\t});\n\t} else {\n\t\twindow.classNames = classNames;\n\t}\n}());\n","import React, { ReactNode } from \"react\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./link.module.scss\";\n\nconst cx = c.bind(styles);\nconst rootClassName = \"purpur-link\";\n\nexport const LINK_VARIANT = {\n TEXT: \"text\",\n TEXT_NEGATIVE: \"text-negative\",\n STANDALONE: \"standalone\",\n STANDALONE_NEGATIVE: \"standalone-negative\",\n NAVIGATION: \"navigation\",\n NAVIGATION_NEGATIVE: \"navigation-negative\",\n} as const;\n\nexport const linkVariants = Object.values(LINK_VARIANT);\nexport type LinkVariant = (typeof LINK_VARIANT)[keyof typeof LINK_VARIANT];\n\nexport type LinkProps = {\n children: ReactNode;\n className?: string;\n [\"data-testid\"]?: string;\n /** Disables visited styling */\n disableVisited?: boolean;\n /**\n * This sets a minimum size on the targetable area of the link. Please note\n * it also changes display value to flex, meaning its container will behave\n * like a block element. You can wrap this component in a flex container\n * for additional layout control.\n */\n ensureTargetArea?: boolean;\n /**\n * This will wrap children in a <a/> tag and set the href accordingly\n */\n href?: string;\n /**\n * A silent link is intended to wrap an element\n * to make it a link but not add any styling\n * except for the pointer cursor and focus style.\n */\n silent?: boolean;\n /**\n * if target and href is specified, target will be added to the <a/> tag\n */\n target?: React.HTMLAttributeAnchorTarget;\n /**\n * Determines if link is displayed on its own line\n * (standalone) or within the current text content\n * (text).\n */\n variant: LinkVariant;\n};\n\nexport const Link = ({\n [\"data-testid\"]: dataTestid,\n children,\n className,\n disableVisited,\n ensureTargetArea,\n href,\n silent,\n target,\n variant,\n ...props\n}: LinkProps) => (\n <span\n className={cx([\n className,\n rootClassName,\n `${rootClassName}--${variant}`,\n {\n [`${rootClassName}--silent`]: silent,\n [`${rootClassName}--negative`]: variant.endsWith(\"negative\"),\n [`${rootClassName}--disable-visited`]: disableVisited ?? silent,\n [`${rootClassName}--ensure-target-area`]: ensureTargetArea,\n },\n ])}\n data-testid={dataTestid}\n {...props}\n >\n {href ? (\n <a href={href} target={target} {...props}>\n {children}\n </a>\n ) : (\n children\n )}\n </span>\n);\n"],"names":["hasOwn","classNames","classes","i","arg","appendClass","parseValue","key","value","newClass","module","cx","c","styles","rootClassName","LINK_VARIANT","linkVariants","Link","dataTestid","children","className","disableVisited","ensureTargetArea","href","silent","target","variant","props","jsx"],"mappings":";;;;gBAOC,UAAY,CAGZ,IAAIA,EAAS,CAAE,EAAC,eAEhB,SAASC,GAAc,CAGtB,QAFIC,EAAU,GAELC,EAAI,EAAGA,EAAI,UAAU,OAAQA,IAAK,CAC1C,IAAIC,EAAM,UAAUD,CAAC,EACjBC,IACHF,EAAUG,EAAYH,EAASI,EAAW,KAAK,KAAMF,CAAG,CAAC,EAE1D,CAED,OAAOF,CACP,CAED,SAASI,EAAYF,EAAK,CACzB,GAAI,OAAOA,GAAQ,UAAY,OAAOA,GAAQ,SAC7C,OAAO,MAAQ,KAAKA,CAAG,GAAKA,EAG7B,GAAI,OAAOA,GAAQ,SAClB,MAAO,GAGR,GAAI,MAAM,QAAQA,CAAG,EACpB,OAAOH,EAAW,MAAM,KAAMG,CAAG,EAGlC,GAAIA,EAAI,WAAa,OAAO,UAAU,UAAY,CAACA,EAAI,SAAS,SAAQ,EAAG,SAAS,eAAe,EAClG,OAAOA,EAAI,WAGZ,IAAIF,EAAU,GAEd,QAASK,KAAOH,EACXJ,EAAO,KAAKI,EAAKG,CAAG,GAAKH,EAAIG,CAAG,IACnCL,EAAUG,EAAYH,EAAS,MAAQ,KAAKK,CAAG,GAAKA,CAAG,GAIzD,OAAOL,CACP,CAED,SAASG,EAAaG,EAAOC,EAAU,CACtC,OAAKA,EAIDD,EACIA,EAAQ,IAAMC,EAGfD,EAAQC,EAPPD,CAQR,CAEoCE,EAAO,SAC3CT,EAAW,QAAUA,EACrBS,EAAA,QAAiBT,GAOjB,OAAO,WAAaA,CAEtB,8qBCvEMU,EAAKC,EAAE,KAAKC,CAAM,EAClBC,EAAgB,cAETC,EAAe,CAC1B,KAAM,OACN,cAAe,gBACf,WAAY,aACZ,oBAAqB,sBACrB,WAAY,aACZ,oBAAqB,qBACvB,EAEaC,EAAe,OAAO,OAAOD,CAAY,EAsCzCE,EAAO,CAAC,CACnB,CAAC,eAAgBC,EACjB,SAAAC,EACA,UAAAC,EACA,eAAAC,EACA,iBAAAC,EACA,KAAAC,EACA,OAAAC,EACA,OAAAC,EACA,QAAAC,EACA,GAAGC,CACL,IACEC,EAAA,IAAC,OAAA,CACC,UAAWjB,EAAG,CACZS,EACAN,EACA,GAAGA,CAAa,KAAKY,CAAO,GAC5B,CACE,CAAC,GAAGZ,CAAa,UAAU,EAAGU,EAC9B,CAAC,GAAGV,CAAa,YAAY,EAAGY,EAAQ,SAAS,UAAU,EAC3D,CAAC,GAAGZ,CAAa,mBAAmB,EAAGO,GAAkBG,EACzD,CAAC,GAAGV,CAAa,sBAAsB,EAAGQ,CAC5C,CAAA,CACD,EACD,cAAaJ,EACZ,GAAGS,EAEH,SAAAJ,QACE,IAAE,CAAA,KAAAA,EAAY,OAAAE,EAAiB,GAAGE,EAChC,SAAAR,CACH,CAAA,EAEAA,CAAA,CAEJ","x_google_ignoreList":[0]}
package/dist/link.d.ts ADDED
@@ -0,0 +1,47 @@
1
+ import React, { ReactNode } from "react";
2
+ export declare const LINK_VARIANT: {
3
+ readonly TEXT: "text";
4
+ readonly TEXT_NEGATIVE: "text-negative";
5
+ readonly STANDALONE: "standalone";
6
+ readonly STANDALONE_NEGATIVE: "standalone-negative";
7
+ readonly NAVIGATION: "navigation";
8
+ readonly NAVIGATION_NEGATIVE: "navigation-negative";
9
+ };
10
+ export declare const linkVariants: ("text" | "text-negative" | "standalone" | "standalone-negative" | "navigation" | "navigation-negative")[];
11
+ export type LinkVariant = (typeof LINK_VARIANT)[keyof typeof LINK_VARIANT];
12
+ export type LinkProps = {
13
+ children: ReactNode;
14
+ className?: string;
15
+ ["data-testid"]?: string;
16
+ /** Disables visited styling */
17
+ disableVisited?: boolean;
18
+ /**
19
+ * This sets a minimum size on the targetable area of the link. Please note
20
+ * it also changes display value to flex, meaning its container will behave
21
+ * like a block element. You can wrap this component in a flex container
22
+ * for additional layout control.
23
+ */
24
+ ensureTargetArea?: boolean;
25
+ /**
26
+ * This will wrap children in a <a/> tag and set the href accordingly
27
+ */
28
+ href?: string;
29
+ /**
30
+ * A silent link is intended to wrap an element
31
+ * to make it a link but not add any styling
32
+ * except for the pointer cursor and focus style.
33
+ */
34
+ silent?: boolean;
35
+ /**
36
+ * if target and href is specified, target will be added to the <a/> tag
37
+ */
38
+ target?: React.HTMLAttributeAnchorTarget;
39
+ /**
40
+ * Determines if link is displayed on its own line
41
+ * (standalone) or within the current text content
42
+ * (text).
43
+ */
44
+ variant: LinkVariant;
45
+ };
46
+ export declare const Link: ({ ["data-testid"]: dataTestid, children, className, disableVisited, ensureTargetArea, href, silent, target, variant, ...props }: LinkProps) => React.JSX.Element;
47
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../src/link.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQzC,eAAO,MAAM,YAAY;;;;;;;CAOf,CAAC;AAEX,eAAO,MAAM,YAAY,4GAA8B,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE3E,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC;IACzB,+BAA+B;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,yBAAyB,CAAC;IACzC;;;;OAIG;IACH,OAAO,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,IAAI,oIAWd,SAAS,sBAwBX,CAAC"}
@@ -0,0 +1,95 @@
1
+ import { jsx as c } from "react/jsx-runtime";
2
+ function d(n) {
3
+ return n && n.__esModule && Object.prototype.hasOwnProperty.call(n, "default") ? n.default : n;
4
+ }
5
+ var _ = { exports: {} };
6
+ /*!
7
+ Copyright (c) 2018 Jed Watson.
8
+ Licensed under the MIT License (MIT), see
9
+ http://jedwatson.github.io/classnames
10
+ */
11
+ (function(n) {
12
+ (function() {
13
+ var a = {}.hasOwnProperty;
14
+ function i() {
15
+ for (var t = "", e = 0; e < arguments.length; e++) {
16
+ var r = arguments[e];
17
+ r && (t = u(t, p.call(this, r)));
18
+ }
19
+ return t;
20
+ }
21
+ function p(t) {
22
+ if (typeof t == "string" || typeof t == "number")
23
+ return this && this[t] || t;
24
+ if (typeof t != "object")
25
+ return "";
26
+ if (Array.isArray(t))
27
+ return i.apply(this, t);
28
+ if (t.toString !== Object.prototype.toString && !t.toString.toString().includes("[native code]"))
29
+ return t.toString();
30
+ var e = "";
31
+ for (var r in t)
32
+ a.call(t, r) && t[r] && (e = u(e, this && this[r] || r));
33
+ return e;
34
+ }
35
+ function u(t, e) {
36
+ return e ? t ? t + " " + e : t + e : t;
37
+ }
38
+ n.exports ? (i.default = i, n.exports = i) : window.classNames = i;
39
+ })();
40
+ })(_);
41
+ var v = _.exports;
42
+ const f = /* @__PURE__ */ d(v), k = {
43
+ "purpur-link": "_purpur-link_eselc_1",
44
+ "purpur-link--text": "_purpur-link--text_eselc_15",
45
+ "purpur-link--standalone": "_purpur-link--standalone_eselc_15",
46
+ "purpur-link--navigation": "_purpur-link--navigation_eselc_15",
47
+ "purpur-link--disable-visited": "_purpur-link--disable-visited_eselc_25",
48
+ "purpur-link--text-negative": "_purpur-link--text-negative_eselc_28",
49
+ "purpur-link--standalone-negative": "_purpur-link--standalone-negative_eselc_28",
50
+ "purpur-link--navigation-negative": "_purpur-link--navigation-negative_eselc_28",
51
+ "purpur-link--ensure-target-area": "_purpur-link--ensure-target-area_eselc_67",
52
+ "purpur-link--silent": "_purpur-link--silent_eselc_73"
53
+ }, g = f.bind(k), s = "purpur-link", N = {
54
+ TEXT: "text",
55
+ TEXT_NEGATIVE: "text-negative",
56
+ STANDALONE: "standalone",
57
+ STANDALONE_NEGATIVE: "standalone-negative",
58
+ NAVIGATION: "navigation",
59
+ NAVIGATION_NEGATIVE: "navigation-negative"
60
+ }, E = Object.values(N), T = ({
61
+ ["data-testid"]: n,
62
+ children: a,
63
+ className: i,
64
+ disableVisited: p,
65
+ ensureTargetArea: u,
66
+ href: t,
67
+ silent: e,
68
+ target: r,
69
+ variant: l,
70
+ ...o
71
+ }) => /* @__PURE__ */ c(
72
+ "span",
73
+ {
74
+ className: g([
75
+ i,
76
+ s,
77
+ `${s}--${l}`,
78
+ {
79
+ [`${s}--silent`]: e,
80
+ [`${s}--negative`]: l.endsWith("negative"),
81
+ [`${s}--disable-visited`]: p ?? e,
82
+ [`${s}--ensure-target-area`]: u
83
+ }
84
+ ]),
85
+ "data-testid": n,
86
+ ...o,
87
+ children: t ? /* @__PURE__ */ c("a", { href: t, target: r, ...o, children: a }) : a
88
+ }
89
+ );
90
+ export {
91
+ N as LINK_VARIANT,
92
+ T as Link,
93
+ E as linkVariants
94
+ };
95
+ //# sourceMappingURL=link.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.es.js","sources":["../../../common/temp/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/bind.js","../src/link.tsx"],"sourcesContent":["/*!\n\tCopyright (c) 2018 Jed Watson.\n\tLicensed under the MIT License (MIT), see\n\thttp://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\n\tfunction classNames () {\n\t\tvar classes = '';\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\tvar arg = arguments[i];\n\t\t\tif (arg) {\n\t\t\t\tclasses = appendClass(classes, parseValue.call(this, arg));\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction parseValue (arg) {\n\t\tif (typeof arg === 'string' || typeof arg === 'number') {\n\t\t\treturn this && this[arg] || arg;\n\t\t}\n\n\t\tif (typeof arg !== 'object') {\n\t\t\treturn '';\n\t\t}\n\n\t\tif (Array.isArray(arg)) {\n\t\t\treturn classNames.apply(this, arg);\n\t\t}\n\n\t\tif (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {\n\t\t\treturn arg.toString();\n\t\t}\n\n\t\tvar classes = '';\n\n\t\tfor (var key in arg) {\n\t\t\tif (hasOwn.call(arg, key) && arg[key]) {\n\t\t\t\tclasses = appendClass(classes, this && this[key] || key);\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction appendClass (value, newClass) {\n\t\tif (!newClass) {\n\t\t\treturn value;\n\t\t}\n\t\n\t\tif (value) {\n\t\t\treturn value + ' ' + newClass;\n\t\t}\n\t\n\t\treturn value + newClass;\n\t}\n\n\tif (typeof module !== 'undefined' && module.exports) {\n\t\tclassNames.default = classNames;\n\t\tmodule.exports = classNames;\n\t} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\t\t// register as 'classnames', consistent with npm package name\n\t\tdefine('classnames', [], function () {\n\t\t\treturn classNames;\n\t\t});\n\t} else {\n\t\twindow.classNames = classNames;\n\t}\n}());\n","import React, { ReactNode } from \"react\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./link.module.scss\";\n\nconst cx = c.bind(styles);\nconst rootClassName = \"purpur-link\";\n\nexport const LINK_VARIANT = {\n TEXT: \"text\",\n TEXT_NEGATIVE: \"text-negative\",\n STANDALONE: \"standalone\",\n STANDALONE_NEGATIVE: \"standalone-negative\",\n NAVIGATION: \"navigation\",\n NAVIGATION_NEGATIVE: \"navigation-negative\",\n} as const;\n\nexport const linkVariants = Object.values(LINK_VARIANT);\nexport type LinkVariant = (typeof LINK_VARIANT)[keyof typeof LINK_VARIANT];\n\nexport type LinkProps = {\n children: ReactNode;\n className?: string;\n [\"data-testid\"]?: string;\n /** Disables visited styling */\n disableVisited?: boolean;\n /**\n * This sets a minimum size on the targetable area of the link. Please note\n * it also changes display value to flex, meaning its container will behave\n * like a block element. You can wrap this component in a flex container\n * for additional layout control.\n */\n ensureTargetArea?: boolean;\n /**\n * This will wrap children in a <a/> tag and set the href accordingly\n */\n href?: string;\n /**\n * A silent link is intended to wrap an element\n * to make it a link but not add any styling\n * except for the pointer cursor and focus style.\n */\n silent?: boolean;\n /**\n * if target and href is specified, target will be added to the <a/> tag\n */\n target?: React.HTMLAttributeAnchorTarget;\n /**\n * Determines if link is displayed on its own line\n * (standalone) or within the current text content\n * (text).\n */\n variant: LinkVariant;\n};\n\nexport const Link = ({\n [\"data-testid\"]: dataTestid,\n children,\n className,\n disableVisited,\n ensureTargetArea,\n href,\n silent,\n target,\n variant,\n ...props\n}: LinkProps) => (\n <span\n className={cx([\n className,\n rootClassName,\n `${rootClassName}--${variant}`,\n {\n [`${rootClassName}--silent`]: silent,\n [`${rootClassName}--negative`]: variant.endsWith(\"negative\"),\n [`${rootClassName}--disable-visited`]: disableVisited ?? silent,\n [`${rootClassName}--ensure-target-area`]: ensureTargetArea,\n },\n ])}\n data-testid={dataTestid}\n {...props}\n >\n {href ? (\n <a href={href} target={target} {...props}>\n {children}\n </a>\n ) : (\n children\n )}\n </span>\n);\n"],"names":["hasOwn","classNames","classes","i","arg","appendClass","parseValue","key","value","newClass","module","cx","c","styles","rootClassName","LINK_VARIANT","linkVariants","Link","dataTestid","children","className","disableVisited","ensureTargetArea","href","silent","target","variant","props","jsx"],"mappings":";;;;;;;;;;;AAOA,GAAC,WAAY;AAGZ,QAAIA,IAAS,CAAE,EAAC;AAEhB,aAASC,IAAc;AAGtB,eAFIC,IAAU,IAELC,IAAI,GAAGA,IAAI,UAAU,QAAQA,KAAK;AAC1C,YAAIC,IAAM,UAAUD,CAAC;AACrB,QAAIC,MACHF,IAAUG,EAAYH,GAASI,EAAW,KAAK,MAAMF,CAAG,CAAC;AAAA,MAE1D;AAED,aAAOF;AAAA,IACP;AAED,aAASI,EAAYF,GAAK;AACzB,UAAI,OAAOA,KAAQ,YAAY,OAAOA,KAAQ;AAC7C,eAAO,QAAQ,KAAKA,CAAG,KAAKA;AAG7B,UAAI,OAAOA,KAAQ;AAClB,eAAO;AAGR,UAAI,MAAM,QAAQA,CAAG;AACpB,eAAOH,EAAW,MAAM,MAAMG,CAAG;AAGlC,UAAIA,EAAI,aAAa,OAAO,UAAU,YAAY,CAACA,EAAI,SAAS,SAAQ,EAAG,SAAS,eAAe;AAClG,eAAOA,EAAI;AAGZ,UAAIF,IAAU;AAEd,eAASK,KAAOH;AACf,QAAIJ,EAAO,KAAKI,GAAKG,CAAG,KAAKH,EAAIG,CAAG,MACnCL,IAAUG,EAAYH,GAAS,QAAQ,KAAKK,CAAG,KAAKA,CAAG;AAIzD,aAAOL;AAAA,IACP;AAED,aAASG,EAAaG,GAAOC,GAAU;AACtC,aAAKA,IAIDD,IACIA,IAAQ,MAAMC,IAGfD,IAAQC,IAPPD;AAAA,IAQR;AAED,IAAqCE,EAAO,WAC3CT,EAAW,UAAUA,GACrBS,EAAA,UAAiBT,KAOjB,OAAO,aAAaA;AAAA,EAEtB;;;;;;;;;;;;;;GCvEMU,IAAKC,EAAE,KAAKC,CAAM,GAClBC,IAAgB,eAETC,IAAe;AAAA,EAC1B,MAAM;AAAA,EACN,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,qBAAqB;AAAA,EACrB,YAAY;AAAA,EACZ,qBAAqB;AACvB,GAEaC,IAAe,OAAO,OAAOD,CAAY,GAsCzCE,IAAO,CAAC;AAAA,EACnB,CAAC,gBAAgBC;AAAA,EACjB,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,MAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,GAAGC;AACL,MACE,gBAAAC;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,WAAWjB,EAAG;AAAA,MACZS;AAAA,MACAN;AAAA,MACA,GAAGA,CAAa,KAAKY,CAAO;AAAA,MAC5B;AAAA,QACE,CAAC,GAAGZ,CAAa,UAAU,GAAGU;AAAA,QAC9B,CAAC,GAAGV,CAAa,YAAY,GAAGY,EAAQ,SAAS,UAAU;AAAA,QAC3D,CAAC,GAAGZ,CAAa,mBAAmB,GAAGO,KAAkBG;AAAA,QACzD,CAAC,GAAGV,CAAa,sBAAsB,GAAGQ;AAAA,MAC5C;AAAA,IAAA,CACD;AAAA,IACD,eAAaJ;AAAA,IACZ,GAAGS;AAAA,IAEH,UAAAJ,sBACE,KAAE,EAAA,MAAAA,GAAY,QAAAE,GAAiB,GAAGE,GAChC,UAAAR,EACH,CAAA,IAEAA;AAAA,EAAA;AAEJ;","x_google_ignoreList":[0]}
@@ -0,0 +1,6 @@
1
+ System.register(["react"],function(l,E){"use strict";var p;return{setters:[o=>{p=o.default}],execute:function(){function o(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}var _={exports:{}};/*!
2
+ Copyright (c) 2018 Jed Watson.
3
+ Licensed under the MIT License (MIT), see
4
+ http://jedwatson.github.io/classnames
5
+ */(function(n){(function(){var a={}.hasOwnProperty;function i(){for(var t="",e=0;e<arguments.length;e++){var r=arguments[e];r&&(t=u(t,c.call(this,r)))}return t}function c(t){if(typeof t=="string"||typeof t=="number")return this&&this[t]||t;if(typeof t!="object")return"";if(Array.isArray(t))return i.apply(this,t);if(t.toString!==Object.prototype.toString&&!t.toString.toString().includes("[native code]"))return t.toString();var e="";for(var r in t)a.call(t,r)&&t[r]&&(e=u(e,this&&this[r]||r));return e}function u(t,e){return e?t?t+" "+e:t+e:t}n.exports?(i.default=i,n.exports=i):window.classNames=i})()})(_);var f=_.exports;const k=o(f),N={"purpur-link":"_purpur-link_eselc_1","purpur-link--text":"_purpur-link--text_eselc_15","purpur-link--standalone":"_purpur-link--standalone_eselc_15","purpur-link--navigation":"_purpur-link--navigation_eselc_15","purpur-link--disable-visited":"_purpur-link--disable-visited_eselc_25","purpur-link--text-negative":"_purpur-link--text-negative_eselc_28","purpur-link--standalone-negative":"_purpur-link--standalone-negative_eselc_28","purpur-link--navigation-negative":"_purpur-link--navigation-negative_eselc_28","purpur-link--ensure-target-area":"_purpur-link--ensure-target-area_eselc_67","purpur-link--silent":"_purpur-link--silent_eselc_73"},g=k.bind(N),s="purpur-link",A=l("LINK_VARIANT",{TEXT:"text",TEXT_NEGATIVE:"text-negative",STANDALONE:"standalone",STANDALONE_NEGATIVE:"standalone-negative",NAVIGATION:"navigation",NAVIGATION_NEGATIVE:"navigation-negative"}),T=l("linkVariants",Object.values(A)),b=l("Link",({["data-testid"]:n,children:a,className:i,disableVisited:c,ensureTargetArea:u,href:t,silent:e,target:r,variant:d,...v})=>p.createElement("span",{className:g([i,s,`${s}--${d}`,{[`${s}--silent`]:e,[`${s}--negative`]:d.endsWith("negative"),[`${s}--disable-visited`]:c??e,[`${s}--ensure-target-area`]:u}]),"data-testid":n,...v},t?p.createElement("a",{href:t,target:r,...v},a):a))}}});
6
+ //# sourceMappingURL=link.system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.system.js","sources":["../../../common/temp/node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/bind.js","../src/link.tsx"],"sourcesContent":["/*!\n\tCopyright (c) 2018 Jed Watson.\n\tLicensed under the MIT License (MIT), see\n\thttp://jedwatson.github.io/classnames\n*/\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tvar hasOwn = {}.hasOwnProperty;\n\n\tfunction classNames () {\n\t\tvar classes = '';\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\tvar arg = arguments[i];\n\t\t\tif (arg) {\n\t\t\t\tclasses = appendClass(classes, parseValue.call(this, arg));\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction parseValue (arg) {\n\t\tif (typeof arg === 'string' || typeof arg === 'number') {\n\t\t\treturn this && this[arg] || arg;\n\t\t}\n\n\t\tif (typeof arg !== 'object') {\n\t\t\treturn '';\n\t\t}\n\n\t\tif (Array.isArray(arg)) {\n\t\t\treturn classNames.apply(this, arg);\n\t\t}\n\n\t\tif (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {\n\t\t\treturn arg.toString();\n\t\t}\n\n\t\tvar classes = '';\n\n\t\tfor (var key in arg) {\n\t\t\tif (hasOwn.call(arg, key) && arg[key]) {\n\t\t\t\tclasses = appendClass(classes, this && this[key] || key);\n\t\t\t}\n\t\t}\n\n\t\treturn classes;\n\t}\n\n\tfunction appendClass (value, newClass) {\n\t\tif (!newClass) {\n\t\t\treturn value;\n\t\t}\n\t\n\t\tif (value) {\n\t\t\treturn value + ' ' + newClass;\n\t\t}\n\t\n\t\treturn value + newClass;\n\t}\n\n\tif (typeof module !== 'undefined' && module.exports) {\n\t\tclassNames.default = classNames;\n\t\tmodule.exports = classNames;\n\t} else if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {\n\t\t// register as 'classnames', consistent with npm package name\n\t\tdefine('classnames', [], function () {\n\t\t\treturn classNames;\n\t\t});\n\t} else {\n\t\twindow.classNames = classNames;\n\t}\n}());\n","import React, { ReactNode } from \"react\";\nimport c from \"classnames/bind\";\n\nimport styles from \"./link.module.scss\";\n\nconst cx = c.bind(styles);\nconst rootClassName = \"purpur-link\";\n\nexport const LINK_VARIANT = {\n TEXT: \"text\",\n TEXT_NEGATIVE: \"text-negative\",\n STANDALONE: \"standalone\",\n STANDALONE_NEGATIVE: \"standalone-negative\",\n NAVIGATION: \"navigation\",\n NAVIGATION_NEGATIVE: \"navigation-negative\",\n} as const;\n\nexport const linkVariants = Object.values(LINK_VARIANT);\nexport type LinkVariant = (typeof LINK_VARIANT)[keyof typeof LINK_VARIANT];\n\nexport type LinkProps = {\n children: ReactNode;\n className?: string;\n [\"data-testid\"]?: string;\n /** Disables visited styling */\n disableVisited?: boolean;\n /**\n * This sets a minimum size on the targetable area of the link. Please note\n * it also changes display value to flex, meaning its container will behave\n * like a block element. You can wrap this component in a flex container\n * for additional layout control.\n */\n ensureTargetArea?: boolean;\n /**\n * This will wrap children in a <a/> tag and set the href accordingly\n */\n href?: string;\n /**\n * A silent link is intended to wrap an element\n * to make it a link but not add any styling\n * except for the pointer cursor and focus style.\n */\n silent?: boolean;\n /**\n * if target and href is specified, target will be added to the <a/> tag\n */\n target?: React.HTMLAttributeAnchorTarget;\n /**\n * Determines if link is displayed on its own line\n * (standalone) or within the current text content\n * (text).\n */\n variant: LinkVariant;\n};\n\nexport const Link = ({\n [\"data-testid\"]: dataTestid,\n children,\n className,\n disableVisited,\n ensureTargetArea,\n href,\n silent,\n target,\n variant,\n ...props\n}: LinkProps) => (\n <span\n className={cx([\n className,\n rootClassName,\n `${rootClassName}--${variant}`,\n {\n [`${rootClassName}--silent`]: silent,\n [`${rootClassName}--negative`]: variant.endsWith(\"negative\"),\n [`${rootClassName}--disable-visited`]: disableVisited ?? silent,\n [`${rootClassName}--ensure-target-area`]: ensureTargetArea,\n },\n ])}\n data-testid={dataTestid}\n {...props}\n >\n {href ? (\n <a href={href} target={target} {...props}>\n {children}\n </a>\n ) : (\n children\n )}\n </span>\n);\n"],"names":["hasOwn","classNames","classes","i","arg","appendClass","parseValue","key","value","newClass","module","cx","c","styles","rootClassName","LINK_VARIANT","exports","linkVariants","Link","dataTestid","children","className","disableVisited","ensureTargetArea","href","silent","target","variant","props","React"],"mappings":";;;;gBAOC,UAAY,CAGZ,IAAIA,EAAS,CAAE,EAAC,eAEhB,SAASC,GAAc,CAGtB,QAFIC,EAAU,GAELC,EAAI,EAAGA,EAAI,UAAU,OAAQA,IAAK,CAC1C,IAAIC,EAAM,UAAUD,CAAC,EACjBC,IACHF,EAAUG,EAAYH,EAASI,EAAW,KAAK,KAAMF,CAAG,CAAC,EAE1D,CAED,OAAOF,CACP,CAED,SAASI,EAAYF,EAAK,CACzB,GAAI,OAAOA,GAAQ,UAAY,OAAOA,GAAQ,SAC7C,OAAO,MAAQ,KAAKA,CAAG,GAAKA,EAG7B,GAAI,OAAOA,GAAQ,SAClB,MAAO,GAGR,GAAI,MAAM,QAAQA,CAAG,EACpB,OAAOH,EAAW,MAAM,KAAMG,CAAG,EAGlC,GAAIA,EAAI,WAAa,OAAO,UAAU,UAAY,CAACA,EAAI,SAAS,SAAQ,EAAG,SAAS,eAAe,EAClG,OAAOA,EAAI,WAGZ,IAAIF,EAAU,GAEd,QAASK,KAAOH,EACXJ,EAAO,KAAKI,EAAKG,CAAG,GAAKH,EAAIG,CAAG,IACnCL,EAAUG,EAAYH,EAAS,MAAQ,KAAKK,CAAG,GAAKA,CAAG,GAIzD,OAAOL,CACP,CAED,SAASG,EAAaG,EAAOC,EAAU,CACtC,OAAKA,EAIDD,EACIA,EAAQ,IAAMC,EAGfD,EAAQC,EAPPD,CAQR,CAEoCE,EAAO,SAC3CT,EAAW,QAAUA,EACrBS,EAAA,QAAiBT,GAOjB,OAAO,WAAaA,CAEtB,8qBCvEMU,EAAKC,EAAE,KAAKC,CAAM,EAClBC,EAAgB,cAETC,EAAeC,EAAA,eAAA,CAC1B,KAAM,OACN,cAAe,gBACf,WAAY,aACZ,oBAAqB,sBACrB,WAAY,aACZ,oBAAqB,qBACvB,CAAA,EAEaC,EAAeD,EAAA,eAAA,OAAO,OAAOD,CAAY,CAAA,EAsCzCG,WAAO,CAAC,CACnB,CAAC,eAAgBC,EACjB,SAAAC,EACA,UAAAC,EACA,eAAAC,EACA,iBAAAC,EACA,KAAAC,EACA,OAAAC,EACA,OAAAC,EACA,QAAAC,EACA,GAAGC,CACL,IACEC,EAAA,cAAC,OAAA,CACC,UAAWlB,EAAG,CACZU,EACAP,EACA,GAAGA,CAAa,KAAKa,CAAO,GAC5B,CACE,CAAC,GAAGb,CAAa,UAAU,EAAGW,EAC9B,CAAC,GAAGX,CAAa,YAAY,EAAGa,EAAQ,SAAS,UAAU,EAC3D,CAAC,GAAGb,CAAa,mBAAmB,EAAGQ,GAAkBG,EACzD,CAAC,GAAGX,CAAa,sBAAsB,EAAGS,CAC5C,CAAA,CACD,EACD,cAAaJ,EACZ,GAAGS,CAAA,EAEHJ,kBACE,IAAE,CAAA,KAAAA,EAAY,OAAAE,EAAiB,GAAGE,CAAA,EAChCR,CACH,EAEAA,CAEJ,CAAA","x_google_ignoreList":[0]}
@@ -0,0 +1 @@
1
+ ._purpur-link_eselc_1 a{align-items:center;cursor:pointer;display:inline-flex;gap:var(--purpur-spacing-50);text-decoration:underline}._purpur-link_eselc_1 a:focus,._purpur-link_eselc_1 a:active{outline:solid var(--purpur-border-width-sm) var(--purpur-color-border-interactive-focus);outline-offset:var(--purpur-spacing-25)}._purpur-link_eselc_1 a:focus:not(:focus-visible){outline:0}._purpur-link--text_eselc_15 a,._purpur-link--standalone_eselc_15 a,._purpur-link--navigation_eselc_15 a{color:var(--purpur-color-text-interactive-primary)}._purpur-link--text_eselc_15 a:hover,._purpur-link--standalone_eselc_15 a:hover,._purpur-link--navigation_eselc_15 a:hover{color:var(--purpur-color-text-interactive-primary-active);background-color:var(--purpur-color-background-interactive-transparent-hover)}._purpur-link--text_eselc_15 a:active,._purpur-link--standalone_eselc_15 a:active,._purpur-link--navigation_eselc_15 a:active{background-color:var(--purpur-color-background-interactive-transparent-active)}._purpur-link--text_eselc_15 a:visited:not(._purpur-link--disable-visited_eselc_25),._purpur-link--standalone_eselc_15 a:visited:not(._purpur-link--disable-visited_eselc_25),._purpur-link--navigation_eselc_15 a:visited:not(._purpur-link--disable-visited_eselc_25){color:var(--purpur-color-text-interactive-primary-active)}._purpur-link--text-negative_eselc_28 a,._purpur-link--standalone-negative_eselc_28 a,._purpur-link--navigation-negative_eselc_28 a{color:var(--purpur-color-text-interactive-primary-negative)}._purpur-link--text-negative_eselc_28 a:hover,._purpur-link--standalone-negative_eselc_28 a:hover,._purpur-link--navigation-negative_eselc_28 a:hover{background-color:var(--purpur-color-background-interactive-transparent-negative-hover);color:var(--purpur-color-text-interactive-primary-negative)}._purpur-link--text-negative_eselc_28 a:active,._purpur-link--standalone-negative_eselc_28 a:active,._purpur-link--navigation-negative_eselc_28 a:active{background-color:var(--purpur-color-background-interactive-transparent-negative-active);color:var(--purpur-color-text-interactive-primary-negative-active)}._purpur-link--text-negative_eselc_28 a:visited:not(._purpur-link--disable-visited_eselc_25),._purpur-link--standalone-negative_eselc_28 a:visited:not(._purpur-link--disable-visited_eselc_25),._purpur-link--navigation-negative_eselc_28 a:visited:not(._purpur-link--disable-visited_eselc_25){color:var(--purpur-color-text-interactive-primary-negative-active)}._purpur-link--standalone_eselc_15,._purpur-link--standalone-negative_eselc_28{display:inline-block}._purpur-link--standalone_eselc_15 a,._purpur-link--standalone-negative_eselc_28 a{font-family:var(--purpur-typography-family-default),Helvetica,Arial,"Lucida Grande",sans-serif;font-weight:var(--purpur-typography-weight-normal);font-size:var(--purpur-typography-scale-100);line-height:var(--purpur-typography-line-height-loose);padding:var(--purpur-spacing-100) 0}._purpur-link--navigation_eselc_15 a,._purpur-link--navigation-negative_eselc_28 a{font-family:var(--purpur-typography-family-default),Helvetica,Arial,"Lucida Grande",sans-serif;font-weight:var(--purpur-typography-weight-normal);font-size:var(--purpur-typography-scale-100);line-height:var(--purpur-typography-line-height-loose);align-items:center;background-color:var(--purpur-color-functional-transparent);display:flex;font-weight:var(--purpur-typography-weight-medium);text-decoration:none}._purpur-link--navigation_eselc_15 a:active,._purpur-link--navigation_eselc_15 a:hover,._purpur-link--navigation-negative_eselc_28 a:active,._purpur-link--navigation-negative_eselc_28 a:hover{background-color:var(--purpur-color-functional-transparent);text-decoration:underline}._purpur-link--ensure-target-area_eselc_67,._purpur-link--ensure-target-area_eselc_67 a{align-items:center;display:flex;min-height:var(--purpur-spacing-600);min-width:var(--purpur-spacing-600)}._purpur-link--silent_eselc_73 a{background-color:inherit;color:inherit;height:100%;text-decoration:none}._purpur-link--silent_eselc_73 a:hover,._purpur-link--silent_eselc_73 a:focus,._purpur-link--silent_eselc_73 a:active{background-color:inherit;color:inherit}._purpur-link--silent_eselc_73 a:focus{outline:0}._purpur-link--silent_eselc_73:is(._purpur-link--disable-visited_eselc_25) a:visited{color:inherit}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@purpurds/link",
3
+ "version": "3.0.0",
4
+ "license": "AGPL-3.0-only",
5
+ "main": "./dist/link.cjs.js",
6
+ "types": "./dist/link.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./dist/link.cjs.js",
10
+ "systemjs": "./dist/link.system.js",
11
+ "types": "./dist/link.d.ts",
12
+ "default": "./dist/link.es.js"
13
+ },
14
+ "./styles": "./dist/styles.css"
15
+ },
16
+ "source": "src/link.tsx",
17
+ "dependencies": {
18
+ "classnames": "~2.5.0",
19
+ "@purpurds/paragraph": "3.0.0",
20
+ "@purpurds/tokens": "3.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@rushstack/eslint-patch": "~1.7.0",
24
+ "@storybook/blocks": "~7.6.0",
25
+ "@storybook/react": "~7.6.0",
26
+ "@telia/base-rig": "~8.2.0",
27
+ "@telia/react-rig": "~3.2.0",
28
+ "@testing-library/dom": "~9.3.3",
29
+ "@testing-library/jest-dom": "~6.3.0",
30
+ "@testing-library/react": "~14.1.2",
31
+ "@types/node": "18",
32
+ "@types/react-dom": "~18.2.17",
33
+ "@types/react": "~18.2.42",
34
+ "eslint-plugin-testing-library": "~6.2.0",
35
+ "eslint": "~8.56.0",
36
+ "jsdom": "~22.1.0",
37
+ "lint-staged": "~10.5.3",
38
+ "prettier": "~2.8.8",
39
+ "react-dom": "~18.2.0",
40
+ "react": "~18.2.0",
41
+ "typescript": "~5.2.2",
42
+ "vite": "~5.0.6",
43
+ "vitest": "~1.2.0",
44
+ "@purpurds/icon": "3.0.0",
45
+ "@purpurds/component-rig": "1.0.0"
46
+ },
47
+ "scripts": {
48
+ "build:dev": "vite",
49
+ "build:watch": "vite build --watch",
50
+ "build": "rm -rf dist && vite build && vite build --mode systemjs",
51
+ "ci:build": "rushx build",
52
+ "coverage": "vitest run --coverage",
53
+ "lint:fix": "eslint . --fix",
54
+ "lint": "lint-staged --no-stash 2>&1",
55
+ "sbdev": "rush sbdev",
56
+ "test:unit": "vitest run --passWithNoTests",
57
+ "test:watch": "vitest --watch",
58
+ "test": "rushx test:unit",
59
+ "typecheck": "tsc -p ./tsconfig.json"
60
+ }
61
+ }
package/readme.mdx ADDED
@@ -0,0 +1,72 @@
1
+ import { Meta, Stories, ArgTypes, Primary, Subtitle } from "@storybook/blocks";
2
+
3
+ import * as LinkStories from "./src/link.stories";
4
+ import packageInfo from "./package.json";
5
+
6
+ <Meta name="Docs" title="Components/Link" of={LinkStories} />
7
+
8
+ # Link
9
+
10
+ <Subtitle>Version {packageInfo.version}</Subtitle>
11
+
12
+ ### Showcase
13
+
14
+ <Primary />
15
+
16
+ ### Properties
17
+
18
+ <ArgTypes />
19
+
20
+ ### Installation
21
+
22
+ #### Via NPM
23
+
24
+ Add the dependency to your consumer app like `"@purpurds/link": "x.y.z"`
25
+
26
+ #### From outside the monorepo (build-time)
27
+
28
+ To install this package, you need to setup access to the artifactory. [Click here to go to the guide on how to do that](https://github.com/telia-company/jfrog-documentation/blob/main/doc/JFrog/JFrog_Onboarding.md#getting-access-to-artifactory-and-other-jfrog-applications).
29
+
30
+ ---
31
+
32
+ In MyApp.tsx
33
+
34
+ ```tsx
35
+ import "@purpurds/tokens/index.css";
36
+ ```
37
+
38
+ and
39
+
40
+ ```tsx
41
+ import "@purpurds/link/styles";
42
+ ```
43
+
44
+ In MyComponent.tsx
45
+
46
+ ##### With a custom anchor (e.g. NextJS) as children
47
+
48
+ ```tsx
49
+ import { Link } from "@purpurds/link";
50
+
51
+ export const MyComponent = () => {
52
+ return (
53
+ <Link>
54
+ <CustomAnchor>Some content</CustomAnchor>
55
+ </Link>
56
+ );
57
+ };
58
+ ```
59
+
60
+ ##### Without an anchor as children
61
+
62
+ ```tsx
63
+ import { Link } from "@purpurds/link";
64
+
65
+ export const MyComponent = () => {
66
+ return (
67
+ <Link href="http://telia.se" target="_blank">
68
+ Some content
69
+ </Link>
70
+ );
71
+ };
72
+ ```
@@ -0,0 +1,4 @@
1
+ declare module "*.scss" {
2
+ const styles: { [className: string]: string };
3
+ export default styles;
4
+ }
@@ -0,0 +1,130 @@
1
+ @import "@purpurds/paragraph/src/paragraph.mixins.scss";
2
+
3
+ .purpur-link {
4
+ $block: &;
5
+
6
+ a {
7
+ align-items: center;
8
+ cursor: pointer;
9
+ display: inline-flex;
10
+ gap: var(--purpur-spacing-50);
11
+ text-decoration: underline;
12
+
13
+ &:focus,
14
+ &:active {
15
+ outline: solid var(--purpur-border-width-sm) var(--purpur-color-border-interactive-focus);
16
+ outline-offset: var(--purpur-spacing-25);
17
+ }
18
+
19
+ &:focus:not(:focus-visible) {
20
+ outline: 0;
21
+ }
22
+ }
23
+
24
+ &--text,
25
+ &--standalone,
26
+ &--navigation {
27
+ a {
28
+ color: var(--purpur-color-text-interactive-primary);
29
+
30
+ &:hover {
31
+ color: var(--purpur-color-text-interactive-primary-active);
32
+ background-color: var(--purpur-color-background-interactive-transparent-hover);
33
+ }
34
+
35
+ &:active {
36
+ background-color: var(--purpur-color-background-interactive-transparent-active);
37
+ }
38
+
39
+ &:visited:not(#{$block}--disable-visited) {
40
+ color: var(--purpur-color-text-interactive-primary-active);
41
+ }
42
+ }
43
+ }
44
+
45
+ &--text-negative,
46
+ &--standalone-negative,
47
+ &--navigation-negative {
48
+ a {
49
+ color: var(--purpur-color-text-interactive-primary-negative);
50
+
51
+ &:hover {
52
+ background-color: var(--purpur-color-background-interactive-transparent-negative-hover);
53
+ color: var(--purpur-color-text-interactive-primary-negative);
54
+ }
55
+
56
+ &:active {
57
+ background-color: var(--purpur-color-background-interactive-transparent-negative-active);
58
+ color: var(--purpur-color-text-interactive-primary-negative-active);
59
+ }
60
+
61
+ &:visited:not(#{$block}--disable-visited) {
62
+ color: var(--purpur-color-text-interactive-primary-negative-active);
63
+ }
64
+ }
65
+ }
66
+
67
+ &--standalone,
68
+ &--standalone-negative {
69
+ display: inline-block;
70
+
71
+ a {
72
+ @include purpur-paragraph-100();
73
+ padding: var(--purpur-spacing-100) 0;
74
+ }
75
+ }
76
+
77
+ &--navigation,
78
+ &--navigation-negative {
79
+ a {
80
+ @include purpur-paragraph-100();
81
+ align-items: center;
82
+ background-color: var(--purpur-color-functional-transparent);
83
+ display: flex;
84
+ font-weight: var(--purpur-typography-weight-medium);
85
+ text-decoration: none;
86
+
87
+ &:active,
88
+ &:hover {
89
+ background-color: var(--purpur-color-functional-transparent);
90
+ text-decoration: underline;
91
+ }
92
+ }
93
+ }
94
+
95
+ &--ensure-target-area,
96
+ &--ensure-target-area a {
97
+ align-items: center;
98
+ display: flex;
99
+ min-height: var(--purpur-spacing-600);
100
+ min-width: var(--purpur-spacing-600);
101
+ }
102
+
103
+ &--silent {
104
+ a {
105
+ background-color: inherit;
106
+ color: inherit;
107
+ height: 100%;
108
+ text-decoration: none;
109
+
110
+ &:hover,
111
+ &:focus,
112
+ &:active {
113
+ background-color: inherit;
114
+ color: inherit;
115
+ }
116
+ }
117
+
118
+ a:focus {
119
+ outline: 0;
120
+ }
121
+
122
+ &:is(#{$block}--disable-visited) {
123
+ a {
124
+ &:visited {
125
+ color: inherit;
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
@@ -0,0 +1,129 @@
1
+ /* eslint-disable react/prop-types */
2
+ import React from "react";
3
+ import { bloodPressure, endUser, Icon } from "@purpurds/icon";
4
+ import type { Meta, StoryObj } from "@storybook/react";
5
+
6
+ import { Link, linkVariants } from "./link";
7
+
8
+ const meta: Meta<typeof Link> = {
9
+ title: "Components/Link",
10
+ component: Link,
11
+ parameters: {
12
+ design: [
13
+ {
14
+ name: "Link",
15
+ type: "figma",
16
+ url: "https://www.figma.com/file/XEaIIFskrrxIBHMZDkIuIg/Purpur-DS---Component-Library?type=design&node-id=3319%3A712&mode=design&t=k1a8dn8C4Mhqq7i4-1",
17
+ },
18
+ ],
19
+ },
20
+ argTypes: {
21
+ variant: {
22
+ options: linkVariants,
23
+ control: { type: "select" },
24
+ },
25
+ target: { control: { type: "text" } },
26
+ },
27
+ decorators: [
28
+ (Story, context) => {
29
+ const {
30
+ args: { variant },
31
+ } = context;
32
+
33
+ return (
34
+ <div
35
+ style={{
36
+ backgroundColor:
37
+ variant && variant.endsWith("negative")
38
+ ? "var(--purpur-color-background-tone-on-tone-primary)"
39
+ : undefined,
40
+ padding: "var(--purpur-spacing-200)",
41
+ }}
42
+ >
43
+ <Story {...context} />
44
+ </div>
45
+ );
46
+ },
47
+ ],
48
+ };
49
+ export default meta;
50
+
51
+ type Story = StoryObj<typeof Link>;
52
+
53
+ export const Showcase: Story = {
54
+ args: {
55
+ variant: linkVariants[0],
56
+ children: "Hello Link!",
57
+ },
58
+ render: ({ children, variant, ...args }) => (
59
+ <div
60
+ style={{
61
+ backgroundColor:
62
+ variant && variant.endsWith("negative")
63
+ ? "var(--purpur-color-background-tone-on-tone-primary)"
64
+ : undefined,
65
+ padding: "var(--purpur-spacing-200)",
66
+ }}
67
+ >
68
+ <Link variant={variant} {...args}>
69
+ <a href="https://www.telia.se" target="_blank">
70
+ {children}
71
+ </a>
72
+ </Link>
73
+ </div>
74
+ ),
75
+ };
76
+
77
+ export const WithLeftIcon: Story = {
78
+ name: "Link with left icon",
79
+ args: {
80
+ variant: linkVariants[0],
81
+ children: "Hello Link!",
82
+ },
83
+ render: ({ children, variant, ...args }) => (
84
+ <Link variant={variant} {...args}>
85
+ <a href="https://www.telia.se" target="_blank">
86
+ <Icon svg={bloodPressure} size="xs" />
87
+ {children}
88
+ </a>
89
+ </Link>
90
+ ),
91
+ };
92
+
93
+ export const WithRightIcon: Story = {
94
+ name: "Link with right icon",
95
+ args: {
96
+ variant: linkVariants[0],
97
+ children: "Hello Link!",
98
+ },
99
+ render: ({ children, variant, ...args }) => (
100
+ <div
101
+ style={{
102
+ backgroundColor:
103
+ variant && variant.endsWith("negative")
104
+ ? "var(--purpur-color-background-tone-on-tone-primary)"
105
+ : undefined,
106
+ }}
107
+ >
108
+ <Link variant={variant} {...args}>
109
+ <a href="https://www.telia.se" target="_blank">
110
+ {children}
111
+ <Icon svg={endUser} size="xs" />
112
+ </a>
113
+ </Link>
114
+ </div>
115
+ ),
116
+ };
117
+
118
+ export const WithoutAnchorAsChild: Story = {
119
+ name: "Link without anchor tag as child",
120
+ args: {
121
+ variant: linkVariants[0],
122
+ children: "Hello Link!",
123
+ },
124
+ render: ({ children, variant, ...args }) => (
125
+ <Link variant={variant} href="https://www.telia.se" target="_blank" {...args}>
126
+ {children}
127
+ </Link>
128
+ ),
129
+ };
@@ -0,0 +1,46 @@
1
+ /* eslint-disable jsx-a11y/anchor-is-valid */
2
+ import React from "react";
3
+ import * as matchers from "@testing-library/jest-dom/matchers";
4
+ import { cleanup, render, screen } from "@testing-library/react";
5
+ import { afterEach, describe, expect, it } from "vitest";
6
+
7
+ import { Link } from "./link";
8
+
9
+ expect.extend(matchers);
10
+
11
+ describe("Link", () => {
12
+ afterEach(() => {
13
+ cleanup();
14
+ });
15
+
16
+ it("should render", () => {
17
+ render(
18
+ <Link variant="text" data-testid="link">
19
+ Some text content
20
+ </Link>
21
+ );
22
+
23
+ expect(screen.getByTestId("link")).toHaveTextContent("Some text content");
24
+ expect(screen.getByTestId("link")).toHaveClass("purpur-link--text");
25
+ });
26
+
27
+ it("should add a class for disabling visited styling", () => {
28
+ render(
29
+ <Link variant="text" data-testid="link" disableVisited>
30
+ Some text content
31
+ </Link>
32
+ );
33
+
34
+ expect(screen.getByTestId("link")).toHaveClass("purpur-link--disable-visited");
35
+ });
36
+
37
+ it("should add a class for silent styling", () => {
38
+ render(
39
+ <Link variant="text" data-testid="link" silent>
40
+ Some text content
41
+ </Link>
42
+ );
43
+
44
+ expect(screen.getByTestId("link")).toHaveClass("purpur-link--silent");
45
+ });
46
+ });
package/src/link.tsx ADDED
@@ -0,0 +1,91 @@
1
+ import React, { ReactNode } from "react";
2
+ import c from "classnames/bind";
3
+
4
+ import styles from "./link.module.scss";
5
+
6
+ const cx = c.bind(styles);
7
+ const rootClassName = "purpur-link";
8
+
9
+ export const LINK_VARIANT = {
10
+ TEXT: "text",
11
+ TEXT_NEGATIVE: "text-negative",
12
+ STANDALONE: "standalone",
13
+ STANDALONE_NEGATIVE: "standalone-negative",
14
+ NAVIGATION: "navigation",
15
+ NAVIGATION_NEGATIVE: "navigation-negative",
16
+ } as const;
17
+
18
+ export const linkVariants = Object.values(LINK_VARIANT);
19
+ export type LinkVariant = (typeof LINK_VARIANT)[keyof typeof LINK_VARIANT];
20
+
21
+ export type LinkProps = {
22
+ children: ReactNode;
23
+ className?: string;
24
+ ["data-testid"]?: string;
25
+ /** Disables visited styling */
26
+ disableVisited?: boolean;
27
+ /**
28
+ * This sets a minimum size on the targetable area of the link. Please note
29
+ * it also changes display value to flex, meaning its container will behave
30
+ * like a block element. You can wrap this component in a flex container
31
+ * for additional layout control.
32
+ */
33
+ ensureTargetArea?: boolean;
34
+ /**
35
+ * This will wrap children in a <a/> tag and set the href accordingly
36
+ */
37
+ href?: string;
38
+ /**
39
+ * A silent link is intended to wrap an element
40
+ * to make it a link but not add any styling
41
+ * except for the pointer cursor and focus style.
42
+ */
43
+ silent?: boolean;
44
+ /**
45
+ * if target and href is specified, target will be added to the <a/> tag
46
+ */
47
+ target?: React.HTMLAttributeAnchorTarget;
48
+ /**
49
+ * Determines if link is displayed on its own line
50
+ * (standalone) or within the current text content
51
+ * (text).
52
+ */
53
+ variant: LinkVariant;
54
+ };
55
+
56
+ export const Link = ({
57
+ ["data-testid"]: dataTestid,
58
+ children,
59
+ className,
60
+ disableVisited,
61
+ ensureTargetArea,
62
+ href,
63
+ silent,
64
+ target,
65
+ variant,
66
+ ...props
67
+ }: LinkProps) => (
68
+ <span
69
+ className={cx([
70
+ className,
71
+ rootClassName,
72
+ `${rootClassName}--${variant}`,
73
+ {
74
+ [`${rootClassName}--silent`]: silent,
75
+ [`${rootClassName}--negative`]: variant.endsWith("negative"),
76
+ [`${rootClassName}--disable-visited`]: disableVisited ?? silent,
77
+ [`${rootClassName}--ensure-target-area`]: ensureTargetArea,
78
+ },
79
+ ])}
80
+ data-testid={dataTestid}
81
+ {...props}
82
+ >
83
+ {href ? (
84
+ <a href={href} target={target} {...props}>
85
+ {children}
86
+ </a>
87
+ ) : (
88
+ children
89
+ )}
90
+ </span>
91
+ );