@sproutsocial/seeds-react-empty-state 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-empty-state/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 3.66 KB
12
+ CJS dist/index.js.map 3.41 KB
13
+ CJS ⚡️ Build success in 192ms
14
+ ESM dist/esm/index.js 1.65 KB
15
+ ESM dist/esm/index.js.map 3.27 KB
16
+ ESM ⚡️ Build success in 197ms
17
+ DTS Build start
18
+ DTS ⚡️ Build success in 24267ms
19
+ DTS dist/index.d.ts 858.00 B
20
+ DTS dist/index.d.mts 858.00 B
21
+ Done in 29.62s.
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @sproutsocial/seeds-react-empty-state
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 69ed5b1: Migrated EmptyState from Racine to seeds-react-empty-state
@@ -0,0 +1,60 @@
1
+ // src/EmptyState.tsx
2
+ import * as React from "react";
3
+ import Box from "@sproutsocial/seeds-react-box";
4
+ import Text from "@sproutsocial/seeds-react-text";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ var EmptyState = ({
7
+ media,
8
+ headline,
9
+ subtext,
10
+ primaryAction,
11
+ secondaryAction,
12
+ ...rest
13
+ }) => {
14
+ return /* @__PURE__ */ jsxs(Box, { maxWidth: "400px", mx: "auto", "data-qa-emptystate": headline, ...rest, children: [
15
+ media && /* @__PURE__ */ jsx(
16
+ Box,
17
+ {
18
+ display: "flex",
19
+ flexDirection: "column",
20
+ justifyContent: "center",
21
+ mb: 450,
22
+ children: media
23
+ }
24
+ ),
25
+ /* @__PURE__ */ jsxs(Text, { as: "div", textAlign: "center", children: [
26
+ /* @__PURE__ */ jsx(
27
+ Text,
28
+ {
29
+ as: "p",
30
+ m: 0,
31
+ color: "text.headline",
32
+ fontWeight: "semibold",
33
+ fontSize: 400,
34
+ children: headline
35
+ }
36
+ ),
37
+ subtext && /* @__PURE__ */ jsx(Text, { as: "p", color: "text.subtext", fontSize: 200, mb: 0, mt: 400, children: subtext }),
38
+ /* @__PURE__ */ jsxs(Box, { mt: primaryAction || secondaryAction ? 450 : 0, children: [
39
+ primaryAction && React.cloneElement(primaryAction, {
40
+ appearance: "primary"
41
+ }),
42
+ secondaryAction && /* @__PURE__ */ jsx(Box, { mt: 400, children: React.cloneElement(secondaryAction, {
43
+ appearance: "unstyled"
44
+ }) })
45
+ ] })
46
+ ] })
47
+ ] });
48
+ };
49
+ var EmptyState_default = EmptyState;
50
+
51
+ // src/EmptyStateTypes.ts
52
+ import "react";
53
+
54
+ // src/index.ts
55
+ var src_default = EmptyState_default;
56
+ export {
57
+ EmptyState_default as EmptyState,
58
+ src_default as default
59
+ };
60
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/EmptyState.tsx","../../src/EmptyStateTypes.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\n// eslint-disable-next-line import/no-deprecated\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport type { TypeEmptyStateProps } from \"./EmptyStateTypes\";\n\nconst EmptyState = ({\n media,\n headline,\n subtext,\n primaryAction,\n secondaryAction,\n ...rest\n}: TypeEmptyStateProps) => {\n return (\n <Box maxWidth=\"400px\" mx=\"auto\" data-qa-emptystate={headline} {...rest}>\n {media && (\n <Box\n display=\"flex\"\n flexDirection=\"column\"\n justifyContent=\"center\"\n mb={450}\n >\n {media}\n </Box>\n )}\n\n <Text as=\"div\" textAlign=\"center\">\n <Text\n as=\"p\"\n m={0}\n color=\"text.headline\"\n fontWeight=\"semibold\"\n fontSize={400}\n >\n {headline}\n </Text>\n\n {subtext && (\n <Text as=\"p\" color=\"text.subtext\" fontSize={200} mb={0} mt={400}>\n {subtext}\n </Text>\n )}\n\n <Box mt={primaryAction || secondaryAction ? 450 : 0}>\n {primaryAction &&\n React.cloneElement(primaryAction, {\n appearance: \"primary\",\n })}\n\n {secondaryAction && (\n <Box mt={400}>\n {React.cloneElement(secondaryAction, {\n appearance: \"unstyled\",\n })}\n </Box>\n )}\n </Box>\n </Text>\n </Box>\n );\n};\n\nexport default EmptyState;\n","import * as React from \"react\";\nimport type { TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\n\nexport interface TypeEmptyStateProps extends TypeBoxProps {\n /** An image in (preferably in SVG format) */\n media?: React.ReactNode;\n\n /** A headline describing the empty state */\n headline: React.ReactNode;\n\n /** Optional description of the empty state */\n subtext?: React.ReactNode;\n\n /** Element for the primary call-to-action */\n primaryAction?: React.ReactElement;\n\n /** Element for any secondary call-to-action */\n secondaryAction?: React.ReactElement;\n}\n","import EmptyState from \"./EmptyState\";\n\nexport default EmptyState;\nexport { EmptyState };\nexport * from \"./EmptyStateTypes\";\n"],"mappings":";AAAA,YAAY,WAAW;AACvB,OAAO,SAAS;AAEhB,OAAO,UAAU;AAcT,cA2BA,YA3BA;AAXR,IAAM,aAAa,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA2B;AACzB,SACE,qBAAC,OAAI,UAAS,SAAQ,IAAG,QAAO,sBAAoB,UAAW,GAAG,MAC/D;AAAA,aACC;AAAA,MAAC;AAAA;AAAA,QACC,SAAQ;AAAA,QACR,eAAc;AAAA,QACd,gBAAe;AAAA,QACf,IAAI;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,IAGF,qBAAC,QAAK,IAAG,OAAM,WAAU,UACvB;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAG;AAAA,UACH,GAAG;AAAA,UACH,OAAM;AAAA,UACN,YAAW;AAAA,UACX,UAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MAEC,WACC,oBAAC,QAAK,IAAG,KAAI,OAAM,gBAAe,UAAU,KAAK,IAAI,GAAG,IAAI,KACzD,mBACH;AAAA,MAGF,qBAAC,OAAI,IAAI,iBAAiB,kBAAkB,MAAM,GAC/C;AAAA,yBACO,mBAAa,eAAe;AAAA,UAChC,YAAY;AAAA,QACd,CAAC;AAAA,QAEF,mBACC,oBAAC,OAAI,IAAI,KACN,UAAM,mBAAa,iBAAiB;AAAA,UACnC,YAAY;AAAA,QACd,CAAC,GACH;AAAA,SAEJ;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,IAAO,qBAAQ;;;AC/Df,OAAuB;;;ACEvB,IAAO,cAAQ;","names":[]}
@@ -0,0 +1,20 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
4
+
5
+ interface TypeEmptyStateProps extends TypeBoxProps {
6
+ /** An image in (preferably in SVG format) */
7
+ media?: React.ReactNode;
8
+ /** A headline describing the empty state */
9
+ headline: React.ReactNode;
10
+ /** Optional description of the empty state */
11
+ subtext?: React.ReactNode;
12
+ /** Element for the primary call-to-action */
13
+ primaryAction?: React.ReactElement;
14
+ /** Element for any secondary call-to-action */
15
+ secondaryAction?: React.ReactElement;
16
+ }
17
+
18
+ declare const EmptyState: ({ media, headline, subtext, primaryAction, secondaryAction, ...rest }: TypeEmptyStateProps) => react_jsx_runtime.JSX.Element;
19
+
20
+ export { EmptyState, type TypeEmptyStateProps, EmptyState as default };
@@ -0,0 +1,20 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
4
+
5
+ interface TypeEmptyStateProps extends TypeBoxProps {
6
+ /** An image in (preferably in SVG format) */
7
+ media?: React.ReactNode;
8
+ /** A headline describing the empty state */
9
+ headline: React.ReactNode;
10
+ /** Optional description of the empty state */
11
+ subtext?: React.ReactNode;
12
+ /** Element for the primary call-to-action */
13
+ primaryAction?: React.ReactElement;
14
+ /** Element for any secondary call-to-action */
15
+ secondaryAction?: React.ReactElement;
16
+ }
17
+
18
+ declare const EmptyState: ({ media, headline, subtext, primaryAction, secondaryAction, ...rest }: TypeEmptyStateProps) => react_jsx_runtime.JSX.Element;
19
+
20
+ export { EmptyState, type TypeEmptyStateProps, EmptyState as default };
package/dist/index.js ADDED
@@ -0,0 +1,97 @@
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
+ EmptyState: () => EmptyState_default,
34
+ default: () => src_default
35
+ });
36
+ module.exports = __toCommonJS(src_exports);
37
+
38
+ // src/EmptyState.tsx
39
+ var React = __toESM(require("react"));
40
+ var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
41
+ var import_seeds_react_text = __toESM(require("@sproutsocial/seeds-react-text"));
42
+ var import_jsx_runtime = require("react/jsx-runtime");
43
+ var EmptyState = ({
44
+ media,
45
+ headline,
46
+ subtext,
47
+ primaryAction,
48
+ secondaryAction,
49
+ ...rest
50
+ }) => {
51
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_seeds_react_box.default, { maxWidth: "400px", mx: "auto", "data-qa-emptystate": headline, ...rest, children: [
52
+ media && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
53
+ import_seeds_react_box.default,
54
+ {
55
+ display: "flex",
56
+ flexDirection: "column",
57
+ justifyContent: "center",
58
+ mb: 450,
59
+ children: media
60
+ }
61
+ ),
62
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_seeds_react_text.default, { as: "div", textAlign: "center", children: [
63
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
64
+ import_seeds_react_text.default,
65
+ {
66
+ as: "p",
67
+ m: 0,
68
+ color: "text.headline",
69
+ fontWeight: "semibold",
70
+ fontSize: 400,
71
+ children: headline
72
+ }
73
+ ),
74
+ subtext && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_text.default, { as: "p", color: "text.subtext", fontSize: 200, mb: 0, mt: 400, children: subtext }),
75
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_seeds_react_box.default, { mt: primaryAction || secondaryAction ? 450 : 0, children: [
76
+ primaryAction && React.cloneElement(primaryAction, {
77
+ appearance: "primary"
78
+ }),
79
+ secondaryAction && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { mt: 400, children: React.cloneElement(secondaryAction, {
80
+ appearance: "unstyled"
81
+ }) })
82
+ ] })
83
+ ] })
84
+ ] });
85
+ };
86
+ var EmptyState_default = EmptyState;
87
+
88
+ // src/EmptyStateTypes.ts
89
+ var React2 = require("react");
90
+
91
+ // src/index.ts
92
+ var src_default = EmptyState_default;
93
+ // Annotate the CommonJS export names for ESM import in node:
94
+ 0 && (module.exports = {
95
+ EmptyState
96
+ });
97
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/EmptyState.tsx","../src/EmptyStateTypes.ts"],"sourcesContent":["import EmptyState from \"./EmptyState\";\n\nexport default EmptyState;\nexport { EmptyState };\nexport * from \"./EmptyStateTypes\";\n","import * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\n// eslint-disable-next-line import/no-deprecated\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport type { TypeEmptyStateProps } from \"./EmptyStateTypes\";\n\nconst EmptyState = ({\n media,\n headline,\n subtext,\n primaryAction,\n secondaryAction,\n ...rest\n}: TypeEmptyStateProps) => {\n return (\n <Box maxWidth=\"400px\" mx=\"auto\" data-qa-emptystate={headline} {...rest}>\n {media && (\n <Box\n display=\"flex\"\n flexDirection=\"column\"\n justifyContent=\"center\"\n mb={450}\n >\n {media}\n </Box>\n )}\n\n <Text as=\"div\" textAlign=\"center\">\n <Text\n as=\"p\"\n m={0}\n color=\"text.headline\"\n fontWeight=\"semibold\"\n fontSize={400}\n >\n {headline}\n </Text>\n\n {subtext && (\n <Text as=\"p\" color=\"text.subtext\" fontSize={200} mb={0} mt={400}>\n {subtext}\n </Text>\n )}\n\n <Box mt={primaryAction || secondaryAction ? 450 : 0}>\n {primaryAction &&\n React.cloneElement(primaryAction, {\n appearance: \"primary\",\n })}\n\n {secondaryAction && (\n <Box mt={400}>\n {React.cloneElement(secondaryAction, {\n appearance: \"unstyled\",\n })}\n </Box>\n )}\n </Box>\n </Text>\n </Box>\n );\n};\n\nexport default EmptyState;\n","import * as React from \"react\";\nimport type { TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\n\nexport interface TypeEmptyStateProps extends TypeBoxProps {\n /** An image in (preferably in SVG format) */\n media?: React.ReactNode;\n\n /** A headline describing the empty state */\n headline: React.ReactNode;\n\n /** Optional description of the empty state */\n subtext?: React.ReactNode;\n\n /** Element for the primary call-to-action */\n primaryAction?: React.ReactElement;\n\n /** Element for any secondary call-to-action */\n secondaryAction?: React.ReactElement;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;AACvB,6BAAgB;AAEhB,8BAAiB;AAcT;AAXR,IAAM,aAAa,CAAC;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA2B;AACzB,SACE,6CAAC,uBAAAA,SAAA,EAAI,UAAS,SAAQ,IAAG,QAAO,sBAAoB,UAAW,GAAG,MAC/D;AAAA,aACC;AAAA,MAAC,uBAAAA;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,eAAc;AAAA,QACd,gBAAe;AAAA,QACf,IAAI;AAAA,QAEH;AAAA;AAAA,IACH;AAAA,IAGF,6CAAC,wBAAAC,SAAA,EAAK,IAAG,OAAM,WAAU,UACvB;AAAA;AAAA,QAAC,wBAAAA;AAAA,QAAA;AAAA,UACC,IAAG;AAAA,UACH,GAAG;AAAA,UACH,OAAM;AAAA,UACN,YAAW;AAAA,UACX,UAAU;AAAA,UAET;AAAA;AAAA,MACH;AAAA,MAEC,WACC,4CAAC,wBAAAA,SAAA,EAAK,IAAG,KAAI,OAAM,gBAAe,UAAU,KAAK,IAAI,GAAG,IAAI,KACzD,mBACH;AAAA,MAGF,6CAAC,uBAAAD,SAAA,EAAI,IAAI,iBAAiB,kBAAkB,MAAM,GAC/C;AAAA,yBACO,mBAAa,eAAe;AAAA,UAChC,YAAY;AAAA,QACd,CAAC;AAAA,QAEF,mBACC,4CAAC,uBAAAA,SAAA,EAAI,IAAI,KACN,UAAM,mBAAa,iBAAiB;AAAA,UACnC,YAAY;AAAA,QACd,CAAC,GACH;AAAA,SAEJ;AAAA,OACF;AAAA,KACF;AAEJ;AAEA,IAAO,qBAAQ;;;AC/Df,IAAAE,SAAuB;;;AFEvB,IAAO,cAAQ;","names":["Box","Text","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-empty-state",
7
+ };
8
+
9
+ module.exports = config;
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@sproutsocial/seeds-react-empty-state",
3
+ "version": "1.0.0",
4
+ "description": "Seeds React EmptyState",
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-box": "*",
24
+ "@sproutsocial/seeds-react-text": "*"
25
+ },
26
+ "devDependencies": {
27
+ "@types/react": "^18.0.0",
28
+ "@types/styled-components": "^5.1.26",
29
+ "@sproutsocial/eslint-config-seeds": "*",
30
+ "react": "^18.0.0",
31
+ "styled-components": "^5.2.3",
32
+ "tsup": "^8.0.2",
33
+ "typescript": "^5.6.2",
34
+ "@sproutsocial/seeds-tsconfig": "*",
35
+ "@sproutsocial/seeds-testing": "*",
36
+ "@sproutsocial/seeds-react-testing-library": "*",
37
+ "@sproutsocial/seeds-react-button": "*",
38
+ "@sproutsocial/seeds-react-image": "*"
39
+ },
40
+ "peerDependencies": {
41
+ "styled-components": "^5.2.3"
42
+ },
43
+ "engines": {
44
+ "node": ">=18"
45
+ }
46
+ }
@@ -0,0 +1,87 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import { Button } from "@sproutsocial/seeds-react-button";
4
+ import { Image } from "@sproutsocial/seeds-react-image";
5
+ import EmptyState from "./EmptyState";
6
+
7
+ const meta: Meta<typeof EmptyState> = {
8
+ title: "Components/EmptyState",
9
+ component: EmptyState,
10
+ };
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof EmptyState>;
14
+
15
+ export const Default: Story = {
16
+ args: {
17
+ media: (
18
+ <Image
19
+ alt="No assets matching your search or filters"
20
+ src="https://cl.ly/c878e80ca537/telescope.svg"
21
+ m={0}
22
+ />
23
+ ),
24
+ headline: "No assets matching your search or filters",
25
+ },
26
+ };
27
+
28
+ export const WithSubtext: Story = {
29
+ args: {
30
+ media: (
31
+ <Image
32
+ alt="No assets matching your search or filters"
33
+ src="https://cl.ly/20065a490d48/not-found.svg"
34
+ m={0}
35
+ />
36
+ ),
37
+ headline: "Select a category to get started",
38
+ subtext:
39
+ "Select one or more categories from the right sidebar to see content.",
40
+ },
41
+ };
42
+
43
+ export const WithPrimaryAction: Story = {
44
+ args: {
45
+ media: (
46
+ <Image
47
+ alt="No assets matching your search or filters"
48
+ src="https://cl.ly/57b28cb6caef/abacus.svg"
49
+ m={0}
50
+ />
51
+ ),
52
+ headline: "Uh oh! Something went wrong, please try again.",
53
+ primaryAction: <Button>Reload Page</Button>,
54
+ },
55
+ };
56
+
57
+ export const WithSubtextAndPrimaryAction: Story = {
58
+ args: {
59
+ media: (
60
+ <Image
61
+ alt="No assets matching your search or filters"
62
+ src="https://cl.ly/b04c6087458f/notes.svg"
63
+ m={0}
64
+ />
65
+ ),
66
+ headline: "No content found",
67
+ subtext: "There is no content for the date range you’ve selected.",
68
+ primaryAction: <Button>Compose a Post</Button>,
69
+ },
70
+ };
71
+
72
+ export const WithSubtextPrimaryActionAndSecondaryAction: Story = {
73
+ args: {
74
+ media: (
75
+ <Image
76
+ alt="No assets matching your search or filters"
77
+ src="https://cl.ly/db498c7682df/download/analytics.svg"
78
+ m={0}
79
+ />
80
+ ),
81
+ headline: "Ready to create your first topic?",
82
+ subtext:
83
+ "Now that you have the basics down, it’s time to create a topic. Remember to look for the icon at any time you are feeling lost.",
84
+ primaryAction: <Button>Create a Topic</Button>,
85
+ secondaryAction: <Button>I'll do this later</Button>,
86
+ },
87
+ };
@@ -0,0 +1,64 @@
1
+ import * as React from "react";
2
+ import Box from "@sproutsocial/seeds-react-box";
3
+ // eslint-disable-next-line import/no-deprecated
4
+ import Text from "@sproutsocial/seeds-react-text";
5
+ import type { TypeEmptyStateProps } from "./EmptyStateTypes";
6
+
7
+ const EmptyState = ({
8
+ media,
9
+ headline,
10
+ subtext,
11
+ primaryAction,
12
+ secondaryAction,
13
+ ...rest
14
+ }: TypeEmptyStateProps) => {
15
+ return (
16
+ <Box maxWidth="400px" mx="auto" data-qa-emptystate={headline} {...rest}>
17
+ {media && (
18
+ <Box
19
+ display="flex"
20
+ flexDirection="column"
21
+ justifyContent="center"
22
+ mb={450}
23
+ >
24
+ {media}
25
+ </Box>
26
+ )}
27
+
28
+ <Text as="div" textAlign="center">
29
+ <Text
30
+ as="p"
31
+ m={0}
32
+ color="text.headline"
33
+ fontWeight="semibold"
34
+ fontSize={400}
35
+ >
36
+ {headline}
37
+ </Text>
38
+
39
+ {subtext && (
40
+ <Text as="p" color="text.subtext" fontSize={200} mb={0} mt={400}>
41
+ {subtext}
42
+ </Text>
43
+ )}
44
+
45
+ <Box mt={primaryAction || secondaryAction ? 450 : 0}>
46
+ {primaryAction &&
47
+ React.cloneElement(primaryAction, {
48
+ appearance: "primary",
49
+ })}
50
+
51
+ {secondaryAction && (
52
+ <Box mt={400}>
53
+ {React.cloneElement(secondaryAction, {
54
+ appearance: "unstyled",
55
+ })}
56
+ </Box>
57
+ )}
58
+ </Box>
59
+ </Text>
60
+ </Box>
61
+ );
62
+ };
63
+
64
+ export default EmptyState;
@@ -0,0 +1,19 @@
1
+ import * as React from "react";
2
+ import type { TypeBoxProps } from "@sproutsocial/seeds-react-box";
3
+
4
+ export interface TypeEmptyStateProps extends TypeBoxProps {
5
+ /** An image in (preferably in SVG format) */
6
+ media?: React.ReactNode;
7
+
8
+ /** A headline describing the empty state */
9
+ headline: React.ReactNode;
10
+
11
+ /** Optional description of the empty state */
12
+ subtext?: React.ReactNode;
13
+
14
+ /** Element for the primary call-to-action */
15
+ primaryAction?: React.ReactElement;
16
+
17
+ /** Element for any secondary call-to-action */
18
+ secondaryAction?: React.ReactElement;
19
+ }
@@ -0,0 +1,127 @@
1
+ import React from "react";
2
+ import { render, screen } from "@sproutsocial/seeds-react-testing-library";
3
+ import { Button } from "@sproutsocial/seeds-react-button";
4
+ import EmptyState from "../EmptyState";
5
+ import Image from "@sproutsocial/seeds-react-image";
6
+
7
+ describe("EmptyState", () => {
8
+ it("should render", () => {
9
+ render(
10
+ <EmptyState
11
+ media={
12
+ <Image
13
+ alt="No assets matching your search or filters"
14
+ src="https://cl.ly/c878e80ca537/telescope.svg"
15
+ m={0}
16
+ />
17
+ }
18
+ headline="No content found"
19
+ />
20
+ );
21
+ expect(
22
+ screen.getByDataQaLabel({
23
+ emptystate: "No content found",
24
+ })
25
+ ).toBeTruthy();
26
+ });
27
+ it("should render a media", async () => {
28
+ render(
29
+ <EmptyState
30
+ media={
31
+ <Image
32
+ alt="No assets matching your search or filters"
33
+ src="https://cl.ly/c878e80ca537/telescope.svg"
34
+ m={0}
35
+ />
36
+ }
37
+ headline="No assets matching your search or filters"
38
+ />
39
+ );
40
+ expect(
41
+ screen.getByDataQaLabel({
42
+ image: "No assets matching your search or filters",
43
+ })
44
+ ).toBeTruthy();
45
+ expect(
46
+ screen.getByDataQaLabel({
47
+ "image-src": "https://cl.ly/c878e80ca537/telescope.svg",
48
+ })
49
+ ).toBeTruthy();
50
+ });
51
+ it("should render a headline", async () => {
52
+ render(
53
+ <EmptyState
54
+ media={
55
+ <Image
56
+ alt="No assets matching your search or filters"
57
+ src="https://cl.ly/c878e80ca537/telescope.svg"
58
+ m={0}
59
+ />
60
+ }
61
+ headline="No assets matching your search or filters"
62
+ />
63
+ );
64
+ expect(
65
+ screen.getByText("No assets matching your search or filters")
66
+ ).toBeInTheDocument();
67
+ });
68
+ it("should render a subtext", async () => {
69
+ render(
70
+ <EmptyState
71
+ media={
72
+ <Image
73
+ alt="No assets matching your search or filters"
74
+ src="https://cl.ly/b04c6087458f/notes.svg"
75
+ m={0}
76
+ />
77
+ }
78
+ headline="No content found"
79
+ subtext="There is no content for the date range you’ve selected."
80
+ primaryAction={<Button>Compose a Post</Button>}
81
+ />
82
+ );
83
+ expect(
84
+ screen.getByText(
85
+ "There is no content for the date range you’ve selected."
86
+ )
87
+ ).toBeInTheDocument();
88
+ });
89
+ it("should render a primary button", async () => {
90
+ render(
91
+ <EmptyState
92
+ media={
93
+ <Image
94
+ alt="No assets matching your search or filters"
95
+ src="https://cl.ly/57b28cb6caef/abacus.svg"
96
+ m={0}
97
+ />
98
+ }
99
+ headline="Uh oh! Something went wrong, please try again."
100
+ primaryAction={<Button>Reload Page</Button>}
101
+ />
102
+ );
103
+ const element = screen.getByText("Reload Page");
104
+ expect(element).toBeInTheDocument();
105
+ expect(element).toHaveStyleRule("color", "#FFFFFF");
106
+ });
107
+ it("should render a secondary button", async () => {
108
+ render(
109
+ <EmptyState
110
+ media={
111
+ <Image
112
+ alt="No assets matching your search or filters"
113
+ src="https://cl.ly/db498c7682df/download/analytics.svg"
114
+ m={0}
115
+ />
116
+ }
117
+ headline="Ready to create your first topic?"
118
+ subtext="Now that you have the basics down, it’s time to create a topic. Remember to look for the icon at any time you are feeling lost."
119
+ primaryAction={<Button>Create a Topic</Button>}
120
+ secondaryAction={<Button>I&apos;ll do this later</Button>}
121
+ />
122
+ );
123
+ const element = screen.getByText("I'll do this later");
124
+ expect(element).toBeInTheDocument();
125
+ expect(element).toHaveStyleRule("color", "#515e5f");
126
+ });
127
+ });
@@ -0,0 +1,44 @@
1
+ import * as React from "react";
2
+ import { Button } from "@sproutsocial/seeds-react-button";
3
+ import EmptyState from "../EmptyState";
4
+ import Image from "@sproutsocial/seeds-react-image";
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
7
+ function EmptyStateTypes() {
8
+ const url = "https://cl.ly/20065a490d48/not-found.svg";
9
+ return (
10
+ <>
11
+ <EmptyState
12
+ media={
13
+ <Image alt="No assets matching your search or filters" src={url} />
14
+ }
15
+ headline="No assets matching your search or filters"
16
+ />
17
+ <EmptyState
18
+ media={
19
+ <Image alt="No assets matching your search or filters" src={url} />
20
+ }
21
+ headline="Select a category to get started"
22
+ subtext="Select one or more categories from the right sidebar to see content."
23
+ />
24
+ <EmptyState
25
+ media={
26
+ <Image alt="No assets matching your search or filters" src={url} />
27
+ }
28
+ headline="Uh oh! Something went wrong, please try again."
29
+ primaryAction={<Button>Reload Page</Button>}
30
+ />
31
+ <EmptyState
32
+ media={
33
+ <Image alt="No assets matching your search or filters" src={url} />
34
+ }
35
+ headline="Ready to create your first topic?"
36
+ subtext="Now that you have the basics down, it’s time to create a topic. Remember to look for the icon at any time you are feeling lost."
37
+ primaryAction={<Button>Create a Topic</Button>}
38
+ secondaryAction={<Button>Ill do this later</Button>}
39
+ />
40
+ {/* @ts-expect-error - test that invalid type is rejected */}
41
+ <EmptyState />
42
+ </>
43
+ );
44
+ }
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ import EmptyState from "./EmptyState";
2
+
3
+ export default EmptyState;
4
+ export { EmptyState };
5
+ export * from "./EmptyStateTypes";
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
+ }));