@sproutsocial/seeds-react-breadcrumb 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/.eslintignore ADDED
@@ -0,0 +1,6 @@
1
+ # Node modules
2
+ node_modules/
3
+
4
+ # Build output
5
+ dist/
6
+ coverage/
package/.eslintrc.js ADDED
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ root: true,
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-breadcrumb/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.13 KB
12
+ CJS dist/index.js.map 4.71 KB
13
+ CJS ⚡️ Build success in 84ms
14
+ ESM dist/esm/index.js 2.28 KB
15
+ ESM dist/esm/index.js.map 4.64 KB
16
+ ESM ⚡️ Build success in 86ms
17
+ DTS Build start
18
+ DTS ⚡️ Build success in 12429ms
19
+ DTS dist/index.d.ts 1.09 KB
20
+ DTS dist/index.d.mts 1.09 KB
21
+ Done in 16.96s.
package/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ # @sproutsocial/seeds-react-breadcrumb
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - bd8d03d: - Migrate Breadcrumb from Racine to seeds-react-breadcrumb
8
+ - Remove MenuButton from Breadcrumb in preparation of new Menu component
@@ -0,0 +1,90 @@
1
+ // src/Breadcrumb.tsx
2
+ import * as React from "react";
3
+ import Link from "@sproutsocial/seeds-react-link";
4
+
5
+ // src/styles.ts
6
+ import styled from "styled-components";
7
+ var Nav = styled.nav`
8
+ ol {
9
+ ${(props) => props.theme.typography[200]};
10
+ margin: 0;
11
+ font-family: ${(props) => props.theme.fontFamily};
12
+ padding: 0;
13
+ display: flex;
14
+ }
15
+
16
+ li {
17
+ margin-right: ${(props) => props.theme.space[200]};
18
+ display: flex;
19
+ }
20
+
21
+ a,
22
+ button {
23
+ ${(props) => props.theme.typography[200]};
24
+ max-width: 200px;
25
+ overflow: hidden;
26
+ text-overflow: ellipsis;
27
+ white-space: nowrap;
28
+ }
29
+
30
+ ol > div + li::before {
31
+ content: "/";
32
+ margin-right: ${(props) => props.theme.space[200]};
33
+ }
34
+
35
+ li:last-child a,
36
+ li:last-child button {
37
+ color: ${(props) => props.theme.colors.text.body};
38
+ font-weight: bold;
39
+ }
40
+
41
+ li:not(:last-child)::after {
42
+ content: "/";
43
+ color: ${(props) => props.theme.colors.text.body};
44
+ margin-left: ${(props) => props.theme.space[200]};
45
+ }
46
+ `;
47
+ var styles_default = Nav;
48
+
49
+ // src/Breadcrumb.tsx
50
+ import { jsx, jsxs } from "react/jsx-runtime";
51
+ var BreadcrumbItem = ({
52
+ children,
53
+ href,
54
+ ...rest
55
+ }) => {
56
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(Link, { href, ...rest, children }) });
57
+ };
58
+ var Breadcrumb = ({
59
+ ariaLabel,
60
+ overflow,
61
+ children,
62
+ ...rest
63
+ }) => {
64
+ const listItems = React.Children.toArray(children);
65
+ const lastItem = listItems[listItems.length - 1];
66
+ return /* @__PURE__ */ jsx(styles_default, { "aria-label": ariaLabel, "data-qa-breadcrumb": ariaLabel, ...rest, children: /* @__PURE__ */ jsxs("ol", { children: [
67
+ overflow && /* @__PURE__ */ jsx("li", { children: overflow.menu }),
68
+ listItems.map((item, i) => {
69
+ const itemElem = typeof item === "object" && "props" in item ? item : /* @__PURE__ */ jsx("span", { children: "item" });
70
+ return React.cloneElement(itemElem, {
71
+ ...itemElem.props,
72
+ "aria-current": listItems[i] === lastItem ? "page" : void 0
73
+ });
74
+ })
75
+ ] }) });
76
+ };
77
+ BreadcrumbItem.displayName = "Breadcrumb.Item";
78
+ Breadcrumb.Item = BreadcrumbItem;
79
+ var Breadcrumb_default = Breadcrumb;
80
+
81
+ // src/BreadcrumbTypes.ts
82
+ import "react";
83
+
84
+ // src/index.ts
85
+ var src_default = Breadcrumb_default;
86
+ export {
87
+ Breadcrumb_default as Breadcrumb,
88
+ src_default as default
89
+ };
90
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Breadcrumb.tsx","../../src/styles.ts","../../src/BreadcrumbTypes.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport Link from \"@sproutsocial/seeds-react-link\";\nimport Nav from \"./styles\";\nimport type {\n TypeBreadcrumbProps,\n TypeBreadcrumbItemProps,\n} from \"./BreadcrumbTypes\";\n\nconst BreadcrumbItem = ({\n children,\n href,\n ...rest\n}: TypeBreadcrumbItemProps) => {\n return (\n <li>\n <Link href={href} {...rest}>\n {children}\n </Link>\n </li>\n );\n};\n\nconst Breadcrumb = ({\n ariaLabel,\n overflow,\n children,\n ...rest\n}: TypeBreadcrumbProps) => {\n const listItems = React.Children.toArray(children);\n const lastItem = listItems[listItems.length - 1];\n return (\n <Nav aria-label={ariaLabel} data-qa-breadcrumb={ariaLabel} {...rest}>\n <ol>\n {overflow && <li>{overflow.menu}</li>}\n {listItems.map((item, i) => {\n // @ts-notes - item is a childNode which can be a string or number but `cloneElement` requires props\n const itemElem =\n typeof item === \"object\" && \"props\" in item ? (\n item\n ) : (\n <span>item</span>\n );\n return React.cloneElement(itemElem, {\n ...itemElem.props,\n \"aria-current\": listItems[i] === lastItem ? \"page\" : undefined,\n });\n })}\n </ol>\n </Nav>\n );\n};\n\nBreadcrumbItem.displayName = \"Breadcrumb.Item\";\nBreadcrumb.Item = BreadcrumbItem;\n\nexport default Breadcrumb;\n","import styled from \"styled-components\";\n\nconst Nav = styled.nav`\n ol {\n ${(props) => props.theme.typography[200]};\n margin: 0;\n font-family: ${(props) => props.theme.fontFamily};\n padding: 0;\n display: flex;\n }\n\n li {\n margin-right: ${(props) => props.theme.space[200]};\n display: flex;\n }\n\n a,\n button {\n ${(props) => props.theme.typography[200]};\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n ol > div + li::before {\n content: \"/\";\n margin-right: ${(props) => props.theme.space[200]};\n }\n\n li:last-child a,\n li:last-child button {\n color: ${(props) => props.theme.colors.text.body};\n font-weight: bold;\n }\n\n li:not(:last-child)::after {\n content: \"/\";\n color: ${(props) => props.theme.colors.text.body};\n margin-left: ${(props) => props.theme.space[200]};\n }\n`;\n\nexport default Nav;\n","import * as React from \"react\";\nimport type {\n TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nexport type { TypeLinkProps as TypeBreadcrumbItemProps } from \"@sproutsocial/seeds-react-link\";\n\nexport interface TypeBreadcrumbProps\n extends TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n Omit<React.ComponentPropsWithoutRef<\"nav\">, \"color\"> {\n children: React.ReactNode;\n\n /** Description of the type of navigation being provided by the breadcrumb (i.e. \"Asset library breadcrumb\") */\n ariaLabel: string;\n\n /** optional */\n overflow?: {\n label: string;\n menu: React.ReactNode;\n };\n}\n","import Breadcrumb from \"./Breadcrumb\";\n\nexport default Breadcrumb;\nexport { Breadcrumb };\nexport * from \"./BreadcrumbTypes\";\n"],"mappings":";AAAA,YAAY,WAAW;AACvB,OAAO,UAAU;;;ACDjB,OAAO,YAAY;AAEnB,IAAM,MAAM,OAAO;AAAA;AAAA,MAEb,CAAC,UAAU,MAAM,MAAM,WAAW,GAAG,CAAC;AAAA;AAAA,mBAEzB,CAAC,UAAU,MAAM,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAMhC,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAM/C,CAAC,UAAU,MAAM,MAAM,WAAW,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBASxB,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,aAKxC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAMvC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,IAAI;AAAA,mBACjC,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG,CAAC;AAAA;AAAA;AAIpD,IAAO,iBAAQ;;;AD5BT,cAiBA,YAjBA;AAPN,IAAM,iBAAiB,CAAC;AAAA,EACtB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA+B;AAC7B,SACE,oBAAC,QACC,8BAAC,QAAK,MAAa,GAAG,MACnB,UACH,GACF;AAEJ;AAEA,IAAM,aAAa,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA2B;AACzB,QAAM,YAAkB,eAAS,QAAQ,QAAQ;AACjD,QAAM,WAAW,UAAU,UAAU,SAAS,CAAC;AAC/C,SACE,oBAAC,kBAAI,cAAY,WAAW,sBAAoB,WAAY,GAAG,MAC7D,+BAAC,QACE;AAAA,gBAAY,oBAAC,QAAI,mBAAS,MAAK;AAAA,IAC/B,UAAU,IAAI,CAAC,MAAM,MAAM;AAE1B,YAAM,WACJ,OAAO,SAAS,YAAY,WAAW,OACrC,OAEA,oBAAC,UAAK,kBAAI;AAEd,aAAa,mBAAa,UAAU;AAAA,QAClC,GAAG,SAAS;AAAA,QACZ,gBAAgB,UAAU,CAAC,MAAM,WAAW,SAAS;AAAA,MACvD,CAAC;AAAA,IACH,CAAC;AAAA,KACH,GACF;AAEJ;AAEA,eAAe,cAAc;AAC7B,WAAW,OAAO;AAElB,IAAO,qBAAQ;;;AEvDf,OAAuB;;;ACEvB,IAAO,cAAQ;","names":[]}
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { TypeStyledComponentsCommonProps, TypeSystemCommonProps } from '@sproutsocial/seeds-react-system-props';
4
+ import { TypeLinkProps } from '@sproutsocial/seeds-react-link';
5
+ export { TypeLinkProps as TypeBreadcrumbItemProps } from '@sproutsocial/seeds-react-link';
6
+
7
+ interface TypeBreadcrumbProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"nav">, "color"> {
8
+ children: React.ReactNode;
9
+ /** Description of the type of navigation being provided by the breadcrumb (i.e. "Asset library breadcrumb") */
10
+ ariaLabel: string;
11
+ /** optional */
12
+ overflow?: {
13
+ label: string;
14
+ menu: React.ReactNode;
15
+ };
16
+ }
17
+
18
+ declare const Breadcrumb: {
19
+ ({ ariaLabel, overflow, children, ...rest }: TypeBreadcrumbProps): react_jsx_runtime.JSX.Element;
20
+ Item: {
21
+ ({ children, href, ...rest }: TypeLinkProps): react_jsx_runtime.JSX.Element;
22
+ displayName: string;
23
+ };
24
+ };
25
+
26
+ export { Breadcrumb, type TypeBreadcrumbProps, Breadcrumb as default };
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { TypeStyledComponentsCommonProps, TypeSystemCommonProps } from '@sproutsocial/seeds-react-system-props';
4
+ import { TypeLinkProps } from '@sproutsocial/seeds-react-link';
5
+ export { TypeLinkProps as TypeBreadcrumbItemProps } from '@sproutsocial/seeds-react-link';
6
+
7
+ interface TypeBreadcrumbProps extends TypeStyledComponentsCommonProps, TypeSystemCommonProps, Omit<React.ComponentPropsWithoutRef<"nav">, "color"> {
8
+ children: React.ReactNode;
9
+ /** Description of the type of navigation being provided by the breadcrumb (i.e. "Asset library breadcrumb") */
10
+ ariaLabel: string;
11
+ /** optional */
12
+ overflow?: {
13
+ label: string;
14
+ menu: React.ReactNode;
15
+ };
16
+ }
17
+
18
+ declare const Breadcrumb: {
19
+ ({ ariaLabel, overflow, children, ...rest }: TypeBreadcrumbProps): react_jsx_runtime.JSX.Element;
20
+ Item: {
21
+ ({ children, href, ...rest }: TypeLinkProps): react_jsx_runtime.JSX.Element;
22
+ displayName: string;
23
+ };
24
+ };
25
+
26
+ export { Breadcrumb, type TypeBreadcrumbProps, Breadcrumb as default };
package/dist/index.js ADDED
@@ -0,0 +1,127 @@
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
+ Breadcrumb: () => Breadcrumb_default,
34
+ default: () => src_default
35
+ });
36
+ module.exports = __toCommonJS(src_exports);
37
+
38
+ // src/Breadcrumb.tsx
39
+ var React = __toESM(require("react"));
40
+ var import_seeds_react_link = __toESM(require("@sproutsocial/seeds-react-link"));
41
+
42
+ // src/styles.ts
43
+ var import_styled_components = __toESM(require("styled-components"));
44
+ var Nav = import_styled_components.default.nav`
45
+ ol {
46
+ ${(props) => props.theme.typography[200]};
47
+ margin: 0;
48
+ font-family: ${(props) => props.theme.fontFamily};
49
+ padding: 0;
50
+ display: flex;
51
+ }
52
+
53
+ li {
54
+ margin-right: ${(props) => props.theme.space[200]};
55
+ display: flex;
56
+ }
57
+
58
+ a,
59
+ button {
60
+ ${(props) => props.theme.typography[200]};
61
+ max-width: 200px;
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ white-space: nowrap;
65
+ }
66
+
67
+ ol > div + li::before {
68
+ content: "/";
69
+ margin-right: ${(props) => props.theme.space[200]};
70
+ }
71
+
72
+ li:last-child a,
73
+ li:last-child button {
74
+ color: ${(props) => props.theme.colors.text.body};
75
+ font-weight: bold;
76
+ }
77
+
78
+ li:not(:last-child)::after {
79
+ content: "/";
80
+ color: ${(props) => props.theme.colors.text.body};
81
+ margin-left: ${(props) => props.theme.space[200]};
82
+ }
83
+ `;
84
+ var styles_default = Nav;
85
+
86
+ // src/Breadcrumb.tsx
87
+ var import_jsx_runtime = require("react/jsx-runtime");
88
+ var BreadcrumbItem = ({
89
+ children,
90
+ href,
91
+ ...rest
92
+ }) => {
93
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_link.default, { href, ...rest, children }) });
94
+ };
95
+ var Breadcrumb = ({
96
+ ariaLabel,
97
+ overflow,
98
+ children,
99
+ ...rest
100
+ }) => {
101
+ const listItems = React.Children.toArray(children);
102
+ const lastItem = listItems[listItems.length - 1];
103
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(styles_default, { "aria-label": ariaLabel, "data-qa-breadcrumb": ariaLabel, ...rest, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("ol", { children: [
104
+ overflow && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: overflow.menu }),
105
+ listItems.map((item, i) => {
106
+ const itemElem = typeof item === "object" && "props" in item ? item : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "item" });
107
+ return React.cloneElement(itemElem, {
108
+ ...itemElem.props,
109
+ "aria-current": listItems[i] === lastItem ? "page" : void 0
110
+ });
111
+ })
112
+ ] }) });
113
+ };
114
+ BreadcrumbItem.displayName = "Breadcrumb.Item";
115
+ Breadcrumb.Item = BreadcrumbItem;
116
+ var Breadcrumb_default = Breadcrumb;
117
+
118
+ // src/BreadcrumbTypes.ts
119
+ var React2 = require("react");
120
+
121
+ // src/index.ts
122
+ var src_default = Breadcrumb_default;
123
+ // Annotate the CommonJS export names for ESM import in node:
124
+ 0 && (module.exports = {
125
+ Breadcrumb
126
+ });
127
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/Breadcrumb.tsx","../src/styles.ts","../src/BreadcrumbTypes.ts"],"sourcesContent":["import Breadcrumb from \"./Breadcrumb\";\n\nexport default Breadcrumb;\nexport { Breadcrumb };\nexport * from \"./BreadcrumbTypes\";\n","import * as React from \"react\";\nimport Link from \"@sproutsocial/seeds-react-link\";\nimport Nav from \"./styles\";\nimport type {\n TypeBreadcrumbProps,\n TypeBreadcrumbItemProps,\n} from \"./BreadcrumbTypes\";\n\nconst BreadcrumbItem = ({\n children,\n href,\n ...rest\n}: TypeBreadcrumbItemProps) => {\n return (\n <li>\n <Link href={href} {...rest}>\n {children}\n </Link>\n </li>\n );\n};\n\nconst Breadcrumb = ({\n ariaLabel,\n overflow,\n children,\n ...rest\n}: TypeBreadcrumbProps) => {\n const listItems = React.Children.toArray(children);\n const lastItem = listItems[listItems.length - 1];\n return (\n <Nav aria-label={ariaLabel} data-qa-breadcrumb={ariaLabel} {...rest}>\n <ol>\n {overflow && <li>{overflow.menu}</li>}\n {listItems.map((item, i) => {\n // @ts-notes - item is a childNode which can be a string or number but `cloneElement` requires props\n const itemElem =\n typeof item === \"object\" && \"props\" in item ? (\n item\n ) : (\n <span>item</span>\n );\n return React.cloneElement(itemElem, {\n ...itemElem.props,\n \"aria-current\": listItems[i] === lastItem ? \"page\" : undefined,\n });\n })}\n </ol>\n </Nav>\n );\n};\n\nBreadcrumbItem.displayName = \"Breadcrumb.Item\";\nBreadcrumb.Item = BreadcrumbItem;\n\nexport default Breadcrumb;\n","import styled from \"styled-components\";\n\nconst Nav = styled.nav`\n ol {\n ${(props) => props.theme.typography[200]};\n margin: 0;\n font-family: ${(props) => props.theme.fontFamily};\n padding: 0;\n display: flex;\n }\n\n li {\n margin-right: ${(props) => props.theme.space[200]};\n display: flex;\n }\n\n a,\n button {\n ${(props) => props.theme.typography[200]};\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n ol > div + li::before {\n content: \"/\";\n margin-right: ${(props) => props.theme.space[200]};\n }\n\n li:last-child a,\n li:last-child button {\n color: ${(props) => props.theme.colors.text.body};\n font-weight: bold;\n }\n\n li:not(:last-child)::after {\n content: \"/\";\n color: ${(props) => props.theme.colors.text.body};\n margin-left: ${(props) => props.theme.space[200]};\n }\n`;\n\nexport default Nav;\n","import * as React from \"react\";\nimport type {\n TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nexport type { TypeLinkProps as TypeBreadcrumbItemProps } from \"@sproutsocial/seeds-react-link\";\n\nexport interface TypeBreadcrumbProps\n extends TypeStyledComponentsCommonProps,\n TypeSystemCommonProps,\n Omit<React.ComponentPropsWithoutRef<\"nav\">, \"color\"> {\n children: React.ReactNode;\n\n /** Description of the type of navigation being provided by the breadcrumb (i.e. \"Asset library breadcrumb\") */\n ariaLabel: string;\n\n /** optional */\n overflow?: {\n label: string;\n menu: React.ReactNode;\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;AACvB,8BAAiB;;;ACDjB,+BAAmB;AAEnB,IAAM,MAAM,yBAAAA,QAAO;AAAA;AAAA,MAEb,CAAC,UAAU,MAAM,MAAM,WAAW,GAAG,CAAC;AAAA;AAAA,mBAEzB,CAAC,UAAU,MAAM,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAMhC,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAM/C,CAAC,UAAU,MAAM,MAAM,WAAW,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBASxB,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,aAKxC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAMvC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,IAAI;AAAA,mBACjC,CAAC,UAAU,MAAM,MAAM,MAAM,GAAG,CAAC;AAAA;AAAA;AAIpD,IAAO,iBAAQ;;;AD5BT;AAPN,IAAM,iBAAiB,CAAC;AAAA,EACtB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA+B;AAC7B,SACE,4CAAC,QACC,sDAAC,wBAAAC,SAAA,EAAK,MAAa,GAAG,MACnB,UACH,GACF;AAEJ;AAEA,IAAM,aAAa,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA2B;AACzB,QAAM,YAAkB,eAAS,QAAQ,QAAQ;AACjD,QAAM,WAAW,UAAU,UAAU,SAAS,CAAC;AAC/C,SACE,4CAAC,kBAAI,cAAY,WAAW,sBAAoB,WAAY,GAAG,MAC7D,uDAAC,QACE;AAAA,gBAAY,4CAAC,QAAI,mBAAS,MAAK;AAAA,IAC/B,UAAU,IAAI,CAAC,MAAM,MAAM;AAE1B,YAAM,WACJ,OAAO,SAAS,YAAY,WAAW,OACrC,OAEA,4CAAC,UAAK,kBAAI;AAEd,aAAa,mBAAa,UAAU;AAAA,QAClC,GAAG,SAAS;AAAA,QACZ,gBAAgB,UAAU,CAAC,MAAM,WAAW,SAAS;AAAA,MACvD,CAAC;AAAA,IACH,CAAC;AAAA,KACH,GACF;AAEJ;AAEA,eAAe,cAAc;AAC7B,WAAW,OAAO;AAElB,IAAO,qBAAQ;;;AEvDf,IAAAC,SAAuB;;;AHEvB,IAAO,cAAQ;","names":["styled","Link","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-breadcrumb",
7
+ };
8
+
9
+ module.exports = config;
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@sproutsocial/seeds-react-breadcrumb",
3
+ "version": "1.0.0",
4
+ "description": "Seeds React Breadcrumb",
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-icon": "*",
24
+ "@sproutsocial/seeds-react-link": "*",
25
+ "@sproutsocial/seeds-react-menu": "*"
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
+ },
39
+ "peerDependencies": {
40
+ "styled-components": "^5.2.3"
41
+ },
42
+ "engines": {
43
+ "node": ">=18"
44
+ }
45
+ }
@@ -0,0 +1,94 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-function */
2
+ import React from "react";
3
+ import { Breadcrumb } from "./";
4
+ import {
5
+ ActionMenu,
6
+ MenuContent,
7
+ MenuItem,
8
+ MenuToggleButton,
9
+ } from "@sproutsocial/seeds-react-menu";
10
+ import { Icon } from "@sproutsocial/seeds-react-icon";
11
+
12
+ export default {
13
+ title: "Components/Breadcrumb",
14
+ };
15
+
16
+ const path = [
17
+ "Asset Library",
18
+ "Coffee Shops",
19
+ "Midwest",
20
+ "Chicago",
21
+ "Humboldt Park",
22
+ "A really really really really really long coffee shop name",
23
+ "Dark Roast",
24
+ ];
25
+
26
+ const pathMiddle = Math.round((path.length - 1) / 2);
27
+
28
+ export const defaultStory = () => (
29
+ <Breadcrumb ariaLabel="breadcrumb">
30
+ {path.slice(0, 3).map((item) => (
31
+ <Breadcrumb.Item href="#">{item}</Breadcrumb.Item>
32
+ ))}
33
+ </Breadcrumb>
34
+ );
35
+
36
+ export const buttonStory = () => (
37
+ <Breadcrumb ariaLabel="breadcrumb">
38
+ {path.slice(0, 3).map((item) => (
39
+ <Breadcrumb.Item onClick={() => {}}>{item}</Breadcrumb.Item>
40
+ ))}
41
+ </Breadcrumb>
42
+ );
43
+
44
+ const BreadcrumbMenu = () => (
45
+ <ActionMenu
46
+ menuToggleElement={
47
+ <MenuToggleButton appearance="secondary" py={0} px={200}>
48
+ <Icon name="ellipsis-horizontal-solid" aria-hidden />
49
+ </MenuToggleButton>
50
+ }
51
+ >
52
+ <MenuContent>
53
+ {path.length > 4
54
+ ? path.slice(0, pathMiddle).map((item) => (
55
+ <MenuItem id={item} onClick={() => {}}>
56
+ {item}
57
+ </MenuItem>
58
+ ))
59
+ : path.map((item) => (
60
+ <MenuItem id={item} onClick={() => {}}>
61
+ {item}
62
+ </MenuItem>
63
+ ))}
64
+ </MenuContent>
65
+ </ActionMenu>
66
+ );
67
+
68
+ export const overflowMenu = () => (
69
+ <Breadcrumb
70
+ overflow={{
71
+ label: "Asset Library's Breadcrumbs Overflow Menu",
72
+ menu: <BreadcrumbMenu />,
73
+ }}
74
+ ariaLabel="breadcrumb"
75
+ >
76
+ {path.length > 4
77
+ ? path
78
+ .slice(pathMiddle, path.length)
79
+ .map((item) => <Breadcrumb.Item href="#">{item}</Breadcrumb.Item>)
80
+ : path.map((item) => <Breadcrumb.Item href="#">{item}</Breadcrumb.Item>)}
81
+ </Breadcrumb>
82
+ );
83
+
84
+ defaultStory.story = {
85
+ name: "Default",
86
+ };
87
+
88
+ buttonStory.story = {
89
+ name: "With Button",
90
+ };
91
+
92
+ overflowMenu.story = {
93
+ name: "With Overflow",
94
+ };
@@ -0,0 +1,56 @@
1
+ import * as React from "react";
2
+ import Link from "@sproutsocial/seeds-react-link";
3
+ import Nav from "./styles";
4
+ import type {
5
+ TypeBreadcrumbProps,
6
+ TypeBreadcrumbItemProps,
7
+ } from "./BreadcrumbTypes";
8
+
9
+ const BreadcrumbItem = ({
10
+ children,
11
+ href,
12
+ ...rest
13
+ }: TypeBreadcrumbItemProps) => {
14
+ return (
15
+ <li>
16
+ <Link href={href} {...rest}>
17
+ {children}
18
+ </Link>
19
+ </li>
20
+ );
21
+ };
22
+
23
+ const Breadcrumb = ({
24
+ ariaLabel,
25
+ overflow,
26
+ children,
27
+ ...rest
28
+ }: TypeBreadcrumbProps) => {
29
+ const listItems = React.Children.toArray(children);
30
+ const lastItem = listItems[listItems.length - 1];
31
+ return (
32
+ <Nav aria-label={ariaLabel} data-qa-breadcrumb={ariaLabel} {...rest}>
33
+ <ol>
34
+ {overflow && <li>{overflow.menu}</li>}
35
+ {listItems.map((item, i) => {
36
+ // @ts-notes - item is a childNode which can be a string or number but `cloneElement` requires props
37
+ const itemElem =
38
+ typeof item === "object" && "props" in item ? (
39
+ item
40
+ ) : (
41
+ <span>item</span>
42
+ );
43
+ return React.cloneElement(itemElem, {
44
+ ...itemElem.props,
45
+ "aria-current": listItems[i] === lastItem ? "page" : undefined,
46
+ });
47
+ })}
48
+ </ol>
49
+ </Nav>
50
+ );
51
+ };
52
+
53
+ BreadcrumbItem.displayName = "Breadcrumb.Item";
54
+ Breadcrumb.Item = BreadcrumbItem;
55
+
56
+ export default Breadcrumb;
@@ -0,0 +1,22 @@
1
+ import * as React from "react";
2
+ import type {
3
+ TypeStyledComponentsCommonProps,
4
+ TypeSystemCommonProps,
5
+ } from "@sproutsocial/seeds-react-system-props";
6
+ export type { TypeLinkProps as TypeBreadcrumbItemProps } from "@sproutsocial/seeds-react-link";
7
+
8
+ export interface TypeBreadcrumbProps
9
+ extends TypeStyledComponentsCommonProps,
10
+ TypeSystemCommonProps,
11
+ Omit<React.ComponentPropsWithoutRef<"nav">, "color"> {
12
+ children: React.ReactNode;
13
+
14
+ /** Description of the type of navigation being provided by the breadcrumb (i.e. "Asset library breadcrumb") */
15
+ ariaLabel: string;
16
+
17
+ /** optional */
18
+ overflow?: {
19
+ label: string;
20
+ menu: React.ReactNode;
21
+ };
22
+ }
@@ -0,0 +1,54 @@
1
+ import * as React from "react";
2
+ import Breadcrumb from "../";
3
+
4
+ const path = [
5
+ "Asset Library",
6
+ "Coffee Shops",
7
+ "Midwest",
8
+ "Chicago",
9
+ "Humboldt Park",
10
+ "A really really really really really long coffee shop name",
11
+ "Dark Roast",
12
+ ];
13
+
14
+ const pathMiddle = Math.round((path.length - 1) / 2);
15
+
16
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
+ function BreadcrumbTypes() {
18
+ return (
19
+ <>
20
+ <Breadcrumb ariaLabel="breadcrumb">
21
+ <Breadcrumb.Item href="/">Level One</Breadcrumb.Item>
22
+ <Breadcrumb.Item href="/level-two">Level Two</Breadcrumb.Item>
23
+ <Breadcrumb.Item href="/level-three">Level Three</Breadcrumb.Item>
24
+ </Breadcrumb>
25
+ <Breadcrumb ariaLabel="breadcrumb">
26
+ {path.slice(0, 3).map((item) => (
27
+ <Breadcrumb.Item href="#">{item}</Breadcrumb.Item>
28
+ ))}
29
+ </Breadcrumb>
30
+ <Breadcrumb ariaLabel="breadcrumb">
31
+ {path.slice(0, 3).map((item) => (
32
+ <Breadcrumb.Item onClick={() => {}}>{item}</Breadcrumb.Item>
33
+ ))}
34
+ </Breadcrumb>
35
+ <Breadcrumb
36
+ overflow={{
37
+ label: "Asset Library's Breadcrumbs Overflow Menu",
38
+ menu: <div />,
39
+ }}
40
+ ariaLabel="breadcrumb"
41
+ >
42
+ {path.length > 4
43
+ ? path
44
+ .slice(pathMiddle, path.length)
45
+ .map((item) => <Breadcrumb.Item href="#">{item}</Breadcrumb.Item>)
46
+ : path.map((item) => (
47
+ <Breadcrumb.Item href="#">{item}</Breadcrumb.Item>
48
+ ))}
49
+ </Breadcrumb>
50
+ {/* @ts-expect-error - test that missing children rejected */}
51
+ <Breadcrumb />
52
+ </>
53
+ );
54
+ }
@@ -0,0 +1,71 @@
1
+ import React from "react";
2
+ import { render, screen } from "@sproutsocial/seeds-react-testing-library";
3
+ import Breadcrumb from "../";
4
+
5
+ describe("Breadcrumb", () => {
6
+ it("should render breadcrumb items", async () => {
7
+ render(
8
+ <Breadcrumb ariaLabel="breadcrumb">
9
+ <Breadcrumb.Item href="/">Level One</Breadcrumb.Item>
10
+ <Breadcrumb.Item href="/level-two">Level Two</Breadcrumb.Item>
11
+ <Breadcrumb.Item href="/level-three">Level Three</Breadcrumb.Item>
12
+ </Breadcrumb>
13
+ );
14
+ expect(
15
+ screen.queryAllByText("Level", {
16
+ exact: false,
17
+ }).length
18
+ ).toEqual(3);
19
+ });
20
+
21
+ it("should render breadcrumb items with a name", async () => {
22
+ render(
23
+ <Breadcrumb ariaLabel="breadcrumb">
24
+ <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
25
+ <Breadcrumb.Item href="/level-two">Level Two</Breadcrumb.Item>
26
+ <Breadcrumb.Item href="/level-three">Level Three</Breadcrumb.Item>
27
+ </Breadcrumb>
28
+ );
29
+ expect(screen.getByText("Home")).toBeInTheDocument();
30
+ });
31
+
32
+ it("should have an aria-label prop", async () => {
33
+ render(
34
+ <Breadcrumb ariaLabel="breadcrumb">
35
+ <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
36
+ <Breadcrumb.Item href="/level-two">Level Two</Breadcrumb.Item>
37
+ <Breadcrumb.Item href="/level-three">Level Three</Breadcrumb.Item>
38
+ </Breadcrumb>
39
+ );
40
+ expect(
41
+ screen.getByDataQaLabel({
42
+ breadcrumb: "breadcrumb",
43
+ })
44
+ ).toBeTruthy();
45
+ });
46
+
47
+ it("should render breadcrumb items with an href", async () => {
48
+ render(
49
+ <Breadcrumb ariaLabel="breadcrumb">
50
+ <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
51
+ <Breadcrumb.Item href="/level-two">Level Two</Breadcrumb.Item>
52
+ <Breadcrumb.Item href="/level-three">Level Three</Breadcrumb.Item>
53
+ </Breadcrumb>
54
+ );
55
+ expect(screen.getByText("Level Two")).toHaveAttribute("href", "/level-two");
56
+ });
57
+
58
+ it("should render the last breadcrumb item with an aria-current prop", async () => {
59
+ render(
60
+ <Breadcrumb ariaLabel="breadcrumb">
61
+ <Breadcrumb.Item href="/">Home</Breadcrumb.Item>
62
+ <Breadcrumb.Item href="/level-two">Level Two</Breadcrumb.Item>
63
+ <Breadcrumb.Item href="/level-three">Level Three</Breadcrumb.Item>
64
+ </Breadcrumb>
65
+ );
66
+ expect(screen.getByText("Level Three")).toHaveAttribute(
67
+ "aria-current",
68
+ "page"
69
+ );
70
+ });
71
+ });
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ import Breadcrumb from "./Breadcrumb";
2
+
3
+ export default Breadcrumb;
4
+ export { Breadcrumb };
5
+ export * from "./BreadcrumbTypes";
@@ -0,0 +1,7 @@
1
+ import "styled-components";
2
+ import { TypeTheme } from "@sproutsocial/seeds-react-theme";
3
+
4
+ declare module "styled-components" {
5
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
6
+ export interface DefaultTheme extends TypeTheme {}
7
+ }
package/src/styles.ts ADDED
@@ -0,0 +1,44 @@
1
+ import styled from "styled-components";
2
+
3
+ const Nav = styled.nav`
4
+ ol {
5
+ ${(props) => props.theme.typography[200]};
6
+ margin: 0;
7
+ font-family: ${(props) => props.theme.fontFamily};
8
+ padding: 0;
9
+ display: flex;
10
+ }
11
+
12
+ li {
13
+ margin-right: ${(props) => props.theme.space[200]};
14
+ display: flex;
15
+ }
16
+
17
+ a,
18
+ button {
19
+ ${(props) => props.theme.typography[200]};
20
+ max-width: 200px;
21
+ overflow: hidden;
22
+ text-overflow: ellipsis;
23
+ white-space: nowrap;
24
+ }
25
+
26
+ ol > div + li::before {
27
+ content: "/";
28
+ margin-right: ${(props) => props.theme.space[200]};
29
+ }
30
+
31
+ li:last-child a,
32
+ li:last-child button {
33
+ color: ${(props) => props.theme.colors.text.body};
34
+ font-weight: bold;
35
+ }
36
+
37
+ li:not(:last-child)::after {
38
+ content: "/";
39
+ color: ${(props) => props.theme.colors.text.body};
40
+ margin-left: ${(props) => props.theme.space[200]};
41
+ }
42
+ `;
43
+
44
+ export default Nav;
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", "coverage"]
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
+ }));