@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 +6 -0
- package/.eslintrc.js +4 -0
- package/.turbo/turbo-build.log +21 -0
- package/CHANGELOG.md +7 -0
- package/dist/esm/index.js +60 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.mts +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +97 -0
- package/dist/index.js.map +1 -0
- package/jest.config.js +9 -0
- package/package.json +46 -0
- package/src/EmptyState.stories.tsx +87 -0
- package/src/EmptyState.tsx +64 -0
- package/src/EmptyStateTypes.ts +19 -0
- package/src/__tests__/EmptyState.test.tsx +127 -0
- package/src/__tests__/EmptyState.typetest.tsx +44 -0
- package/src/index.ts +5 -0
- package/tsconfig.json +9 -0
- package/tsup.config.ts +12 -0
package/.eslintignore
ADDED
package/.eslintrc.js
ADDED
|
@@ -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,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":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -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.d.ts
ADDED
|
@@ -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
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'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
package/tsconfig.json
ADDED
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
|
+
}));
|