@sproutsocial/seeds-react-skeleton 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-skeleton/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.96 KB
12
+ CJS dist/index.js.map 5.24 KB
13
+ CJS ⚡️ Build success in 119ms
14
+ ESM dist/esm/index.js 3.23 KB
15
+ ESM dist/esm/index.js.map 5.17 KB
16
+ ESM ⚡️ Build success in 125ms
17
+ DTS Build start
18
+ DTS ⚡️ Build success in 33302ms
19
+ DTS dist/index.d.ts 317.00 B
20
+ DTS dist/index.d.mts 317.00 B
21
+ Done in 41.01s.
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @sproutsocial/seeds-react-skeleton
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - bd8d03d: Migrate Skeleton to its own seeds-react-skeleton component
@@ -0,0 +1,136 @@
1
+ // src/Skeleton.tsx
2
+ import styled from "styled-components";
3
+ import Box from "@sproutsocial/seeds-react-box";
4
+ import { jsx } from "react/jsx-runtime";
5
+ var SkeletonAttrs = ({ borderRadius, height, width }) => ({
6
+ className: borderRadius === "pill" && height === width ? "circular" : "linear"
7
+ });
8
+ var Skeleton = styled(Box).attrs(SkeletonAttrs)`
9
+ position: relative;
10
+ background: ${(props) => props.theme.colors.container.background.decorative.neutral};
11
+ overflow: hidden;
12
+ &.circular {
13
+ &:before {
14
+ position: absolute;
15
+ top: -25%;
16
+ left: -25%;
17
+ content: '';
18
+ background-image: ${(props) => `conic-gradient(
19
+ ${props.theme.colors.container.background.decorative.neutral} 270deg,
20
+ ${props.theme.colors.container.border.decorative.neutral} 300deg
21
+ );`};
22
+ height: 150%;
23
+ width: 150%;
24
+ animation: SkeletonRotate 2s infinite linear;
25
+ }
26
+ &:after {
27
+ position: absolute;
28
+ top: 50%;
29
+ left: 50%;
30
+ transform: translate(-50%, -50%);
31
+ content: '';
32
+ height: calc(100% - 8px);
33
+ width: calc(100% - 8px);
34
+ background: ${(p) => p.theme.colors.app.background.base};
35
+ border-radius: 50%;
36
+ }
37
+ }
38
+ &.linear {
39
+ position: relative;
40
+ background-image: ${(props) => `linear-gradient(
41
+ 288deg,
42
+ ${props.theme.colors.container.background.decorative.neutral} 32%,
43
+ ${props.theme.colors.container.border.decorative.neutral},
44
+ ${props.theme.colors.container.background.decorative.neutral} 68%
45
+ );`}
46
+ background-size: 400%;
47
+ background-repeat: no-repeat;
48
+ animation: SkeletonShimmer 2s linear infinite reverse;
49
+ overflow: hidden;
50
+ &:after {
51
+ position: absolute;
52
+ bottom: 0;
53
+ content: "";
54
+ height: calc(100% - 4px);
55
+ width: 100%;
56
+ background: ${(props) => props.theme.colors.container.background.decorative.neutral};
57
+
58
+ }
59
+ }
60
+
61
+ @media (prefers-reduced-motion) {
62
+ &.linear,
63
+ &.circular::before {
64
+ animation: none;
65
+ }
66
+ &:before,
67
+ &:after {
68
+ display: none;
69
+ }
70
+ &.linear,
71
+ &.circular {
72
+ border: 1px solid ${(props) => props.theme.colors.container.border.decorative.neutral};
73
+ animation: SkeletonPulse 2s linear infinite alternate;
74
+ }
75
+ }
76
+
77
+ @keyframes SkeletonRotate {
78
+ 100% {
79
+ transform: rotate(360deg);
80
+ }
81
+ }
82
+ @keyframes SkeletonRotateFade {
83
+ 50% {
84
+ transform: rotate(360deg);
85
+ }
86
+ 90% {
87
+ opacity: 1;
88
+ }
89
+ 100% {
90
+ transform: rotate(720deg);
91
+ opacity: 0;
92
+ }
93
+ }
94
+
95
+ @keyframes SkeletonShimmer {
96
+ 0% {
97
+ background-position: 0% 0;
98
+ }
99
+ 100% {
100
+ background-position: 100% 0;
101
+ }
102
+ }
103
+ @keyframes SkeletonPulse {
104
+ 0% {
105
+ border-color: ${(props) => props.theme.colors.container.border.decorative.neutral}FF;
106
+ }
107
+ 100% {
108
+ border-color: ${(props) => props.theme.colors.container.border.decorative.neutral}1A;
109
+ }
110
+ }
111
+ `;
112
+ var SkeletonComponent = ({
113
+ borderRadius,
114
+ height,
115
+ width,
116
+ ...props
117
+ }) => {
118
+ return /* @__PURE__ */ jsx(
119
+ Skeleton,
120
+ {
121
+ borderRadius,
122
+ height,
123
+ width,
124
+ ...props
125
+ }
126
+ );
127
+ };
128
+ var Skeleton_default = SkeletonComponent;
129
+
130
+ // src/index.ts
131
+ var src_default = Skeleton_default;
132
+ export {
133
+ Skeleton_default as Skeleton,
134
+ src_default as default
135
+ };
136
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Skeleton.tsx","../../src/index.ts"],"sourcesContent":["import styled from \"styled-components\";\nimport Box, { type TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\n\n/**\n *\n * @param borderRadius\n * @returns classname string for handling appropriate loader style depending on passed in properties\n */\n// @ts-ignore TODO: fix noImplicitAny error here. IDK why there are no types for this component\nconst SkeletonAttrs = ({ borderRadius, height, width }) => ({\n className:\n borderRadius === \"pill\" && height === width ? \"circular\" : \"linear\",\n});\n\nconst Skeleton = styled(Box).attrs(SkeletonAttrs)`\n position: relative;\n background: ${(props) =>\n props.theme.colors.container.background.decorative.neutral};\n overflow: hidden;\n &.circular {\n &:before {\n position: absolute;\n top: -25%;\n left: -25%;\n content: '';\n background-image: ${(props) => `conic-gradient(\n ${props.theme.colors.container.background.decorative.neutral} 270deg,\n ${props.theme.colors.container.border.decorative.neutral} 300deg\n );`};\n height: 150%;\n width: 150%;\n animation: SkeletonRotate 2s infinite linear;\n }\n &:after {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n content: '';\n height: calc(100% - 8px);\n width: calc(100% - 8px);\n background: ${(p) => p.theme.colors.app.background.base};\n border-radius: 50%;\n }\n }\n &.linear {\n position: relative;\n background-image: ${(props) => `linear-gradient(\n 288deg,\n ${props.theme.colors.container.background.decorative.neutral} 32%,\n ${props.theme.colors.container.border.decorative.neutral},\n ${props.theme.colors.container.background.decorative.neutral} 68%\n );`}\n background-size: 400%;\n background-repeat: no-repeat;\n animation: SkeletonShimmer 2s linear infinite reverse;\n overflow: hidden;\n &:after {\n position: absolute;\n bottom: 0;\n content: \"\";\n height: calc(100% - 4px);\n width: 100%;\n background: ${(props) =>\n props.theme.colors.container.background.decorative.neutral};\n \n }\n }\n\n @media (prefers-reduced-motion) {\n &.linear,\n &.circular::before {\n animation: none;\n }\n &:before,\n &:after {\n display: none;\n }\n &.linear,\n &.circular {\n border: 1px solid ${(props) =>\n props.theme.colors.container.border.decorative.neutral};\n animation: SkeletonPulse 2s linear infinite alternate; \n }\n }\n\n @keyframes SkeletonRotate {\n 100% {\n transform: rotate(360deg);\n }\n }\n @keyframes SkeletonRotateFade {\n 50% {\n transform: rotate(360deg);\n }\n 90% {\n opacity: 1;\n }\n 100% {\n transform: rotate(720deg);\n opacity: 0;\n }\n }\n\n @keyframes SkeletonShimmer {\n 0% {\n background-position: 0% 0;\n }\n 100% {\n background-position: 100% 0;\n }\n }\n @keyframes SkeletonPulse {\n 0% {\n border-color: ${(props) =>\n props.theme.colors.container.border.decorative.neutral}FF;\n }\n 100% {\n border-color: ${(props) =>\n props.theme.colors.container.border.decorative.neutral}1A;\n }\n }\n`;\n\n// @TODO: Refine types that are passed to SkeletonComponent\nconst SkeletonComponent = ({\n borderRadius,\n height,\n width,\n ...props\n}: TypeBoxProps) => {\n return (\n <Skeleton\n borderRadius={borderRadius}\n height={height}\n width={width}\n {...props}\n />\n );\n};\n\nexport default SkeletonComponent;\n","import Skeleton from \"./Skeleton\";\n\nexport default Skeleton;\nexport { Skeleton };\n"],"mappings":";AAAA,OAAO,YAAY;AACnB,OAAO,SAAgC;AAmInC;AA3HJ,IAAM,gBAAgB,CAAC,EAAE,cAAc,QAAQ,MAAM,OAAO;AAAA,EAC1D,WACE,iBAAiB,UAAU,WAAW,QAAQ,aAAa;AAC/D;AAEA,IAAM,WAAW,OAAO,GAAG,EAAE,MAAM,aAAa;AAAA;AAAA,gBAEhC,CAAC,UACb,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAQpC,CAAC,UAAU;AAAA,QAC7B,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA,QAC1D,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA,OACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAaa,CAAC,MAAM,EAAE,MAAM,OAAO,IAAI,WAAW,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMrC,CAAC,UAAU;AAAA;AAAA,QAE3B,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA,QAC1D,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA,QACtD,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA,OAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAWa,CAAC,UACb,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAgBxC,CAAC,UACnB,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAiCxC,CAAC,UACf,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA;AAAA;AAAA,sBAGxC,CAAC,UACf,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA;AAAA;AAAA;AAM9D,IAAM,oBAAoB,CAAC;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAoB;AAClB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,mBAAQ;;;AC3If,IAAO,cAAQ;","names":[]}
@@ -0,0 +1,6 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
3
+
4
+ declare const SkeletonComponent: ({ borderRadius, height, width, ...props }: TypeBoxProps) => react_jsx_runtime.JSX.Element;
5
+
6
+ export { SkeletonComponent as Skeleton, SkeletonComponent as default };
@@ -0,0 +1,6 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
3
+
4
+ declare const SkeletonComponent: ({ borderRadius, height, width, ...props }: TypeBoxProps) => react_jsx_runtime.JSX.Element;
5
+
6
+ export { SkeletonComponent as Skeleton, SkeletonComponent as default };
package/dist/index.js ADDED
@@ -0,0 +1,173 @@
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
+ Skeleton: () => Skeleton_default,
34
+ default: () => src_default
35
+ });
36
+ module.exports = __toCommonJS(src_exports);
37
+
38
+ // src/Skeleton.tsx
39
+ var import_styled_components = __toESM(require("styled-components"));
40
+ var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
41
+ var import_jsx_runtime = require("react/jsx-runtime");
42
+ var SkeletonAttrs = ({ borderRadius, height, width }) => ({
43
+ className: borderRadius === "pill" && height === width ? "circular" : "linear"
44
+ });
45
+ var Skeleton = (0, import_styled_components.default)(import_seeds_react_box.default).attrs(SkeletonAttrs)`
46
+ position: relative;
47
+ background: ${(props) => props.theme.colors.container.background.decorative.neutral};
48
+ overflow: hidden;
49
+ &.circular {
50
+ &:before {
51
+ position: absolute;
52
+ top: -25%;
53
+ left: -25%;
54
+ content: '';
55
+ background-image: ${(props) => `conic-gradient(
56
+ ${props.theme.colors.container.background.decorative.neutral} 270deg,
57
+ ${props.theme.colors.container.border.decorative.neutral} 300deg
58
+ );`};
59
+ height: 150%;
60
+ width: 150%;
61
+ animation: SkeletonRotate 2s infinite linear;
62
+ }
63
+ &:after {
64
+ position: absolute;
65
+ top: 50%;
66
+ left: 50%;
67
+ transform: translate(-50%, -50%);
68
+ content: '';
69
+ height: calc(100% - 8px);
70
+ width: calc(100% - 8px);
71
+ background: ${(p) => p.theme.colors.app.background.base};
72
+ border-radius: 50%;
73
+ }
74
+ }
75
+ &.linear {
76
+ position: relative;
77
+ background-image: ${(props) => `linear-gradient(
78
+ 288deg,
79
+ ${props.theme.colors.container.background.decorative.neutral} 32%,
80
+ ${props.theme.colors.container.border.decorative.neutral},
81
+ ${props.theme.colors.container.background.decorative.neutral} 68%
82
+ );`}
83
+ background-size: 400%;
84
+ background-repeat: no-repeat;
85
+ animation: SkeletonShimmer 2s linear infinite reverse;
86
+ overflow: hidden;
87
+ &:after {
88
+ position: absolute;
89
+ bottom: 0;
90
+ content: "";
91
+ height: calc(100% - 4px);
92
+ width: 100%;
93
+ background: ${(props) => props.theme.colors.container.background.decorative.neutral};
94
+
95
+ }
96
+ }
97
+
98
+ @media (prefers-reduced-motion) {
99
+ &.linear,
100
+ &.circular::before {
101
+ animation: none;
102
+ }
103
+ &:before,
104
+ &:after {
105
+ display: none;
106
+ }
107
+ &.linear,
108
+ &.circular {
109
+ border: 1px solid ${(props) => props.theme.colors.container.border.decorative.neutral};
110
+ animation: SkeletonPulse 2s linear infinite alternate;
111
+ }
112
+ }
113
+
114
+ @keyframes SkeletonRotate {
115
+ 100% {
116
+ transform: rotate(360deg);
117
+ }
118
+ }
119
+ @keyframes SkeletonRotateFade {
120
+ 50% {
121
+ transform: rotate(360deg);
122
+ }
123
+ 90% {
124
+ opacity: 1;
125
+ }
126
+ 100% {
127
+ transform: rotate(720deg);
128
+ opacity: 0;
129
+ }
130
+ }
131
+
132
+ @keyframes SkeletonShimmer {
133
+ 0% {
134
+ background-position: 0% 0;
135
+ }
136
+ 100% {
137
+ background-position: 100% 0;
138
+ }
139
+ }
140
+ @keyframes SkeletonPulse {
141
+ 0% {
142
+ border-color: ${(props) => props.theme.colors.container.border.decorative.neutral}FF;
143
+ }
144
+ 100% {
145
+ border-color: ${(props) => props.theme.colors.container.border.decorative.neutral}1A;
146
+ }
147
+ }
148
+ `;
149
+ var SkeletonComponent = ({
150
+ borderRadius,
151
+ height,
152
+ width,
153
+ ...props
154
+ }) => {
155
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
156
+ Skeleton,
157
+ {
158
+ borderRadius,
159
+ height,
160
+ width,
161
+ ...props
162
+ }
163
+ );
164
+ };
165
+ var Skeleton_default = SkeletonComponent;
166
+
167
+ // src/index.ts
168
+ var src_default = Skeleton_default;
169
+ // Annotate the CommonJS export names for ESM import in node:
170
+ 0 && (module.exports = {
171
+ Skeleton
172
+ });
173
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/Skeleton.tsx"],"sourcesContent":["import Skeleton from \"./Skeleton\";\n\nexport default Skeleton;\nexport { Skeleton };\n","import styled from \"styled-components\";\nimport Box, { type TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\n\n/**\n *\n * @param borderRadius\n * @returns classname string for handling appropriate loader style depending on passed in properties\n */\n// @ts-ignore TODO: fix noImplicitAny error here. IDK why there are no types for this component\nconst SkeletonAttrs = ({ borderRadius, height, width }) => ({\n className:\n borderRadius === \"pill\" && height === width ? \"circular\" : \"linear\",\n});\n\nconst Skeleton = styled(Box).attrs(SkeletonAttrs)`\n position: relative;\n background: ${(props) =>\n props.theme.colors.container.background.decorative.neutral};\n overflow: hidden;\n &.circular {\n &:before {\n position: absolute;\n top: -25%;\n left: -25%;\n content: '';\n background-image: ${(props) => `conic-gradient(\n ${props.theme.colors.container.background.decorative.neutral} 270deg,\n ${props.theme.colors.container.border.decorative.neutral} 300deg\n );`};\n height: 150%;\n width: 150%;\n animation: SkeletonRotate 2s infinite linear;\n }\n &:after {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n content: '';\n height: calc(100% - 8px);\n width: calc(100% - 8px);\n background: ${(p) => p.theme.colors.app.background.base};\n border-radius: 50%;\n }\n }\n &.linear {\n position: relative;\n background-image: ${(props) => `linear-gradient(\n 288deg,\n ${props.theme.colors.container.background.decorative.neutral} 32%,\n ${props.theme.colors.container.border.decorative.neutral},\n ${props.theme.colors.container.background.decorative.neutral} 68%\n );`}\n background-size: 400%;\n background-repeat: no-repeat;\n animation: SkeletonShimmer 2s linear infinite reverse;\n overflow: hidden;\n &:after {\n position: absolute;\n bottom: 0;\n content: \"\";\n height: calc(100% - 4px);\n width: 100%;\n background: ${(props) =>\n props.theme.colors.container.background.decorative.neutral};\n \n }\n }\n\n @media (prefers-reduced-motion) {\n &.linear,\n &.circular::before {\n animation: none;\n }\n &:before,\n &:after {\n display: none;\n }\n &.linear,\n &.circular {\n border: 1px solid ${(props) =>\n props.theme.colors.container.border.decorative.neutral};\n animation: SkeletonPulse 2s linear infinite alternate; \n }\n }\n\n @keyframes SkeletonRotate {\n 100% {\n transform: rotate(360deg);\n }\n }\n @keyframes SkeletonRotateFade {\n 50% {\n transform: rotate(360deg);\n }\n 90% {\n opacity: 1;\n }\n 100% {\n transform: rotate(720deg);\n opacity: 0;\n }\n }\n\n @keyframes SkeletonShimmer {\n 0% {\n background-position: 0% 0;\n }\n 100% {\n background-position: 100% 0;\n }\n }\n @keyframes SkeletonPulse {\n 0% {\n border-color: ${(props) =>\n props.theme.colors.container.border.decorative.neutral}FF;\n }\n 100% {\n border-color: ${(props) =>\n props.theme.colors.container.border.decorative.neutral}1A;\n }\n }\n`;\n\n// @TODO: Refine types that are passed to SkeletonComponent\nconst SkeletonComponent = ({\n borderRadius,\n height,\n width,\n ...props\n}: TypeBoxProps) => {\n return (\n <Skeleton\n borderRadius={borderRadius}\n height={height}\n width={width}\n {...props}\n />\n );\n};\n\nexport default SkeletonComponent;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,+BAAmB;AACnB,6BAAuC;AAmInC;AA3HJ,IAAM,gBAAgB,CAAC,EAAE,cAAc,QAAQ,MAAM,OAAO;AAAA,EAC1D,WACE,iBAAiB,UAAU,WAAW,QAAQ,aAAa;AAC/D;AAEA,IAAM,eAAW,yBAAAA,SAAO,uBAAAC,OAAG,EAAE,MAAM,aAAa;AAAA;AAAA,gBAEhC,CAAC,UACb,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAQpC,CAAC,UAAU;AAAA,QAC7B,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA,QAC1D,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA,OACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAaa,CAAC,MAAM,EAAE,MAAM,OAAO,IAAI,WAAW,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMrC,CAAC,UAAU;AAAA;AAAA,QAE3B,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA,QAC1D,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA,QACtD,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA,OAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAWa,CAAC,UACb,MAAM,MAAM,OAAO,UAAU,WAAW,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAgBxC,CAAC,UACnB,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAiCxC,CAAC,UACf,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA;AAAA;AAAA,sBAGxC,CAAC,UACf,MAAM,MAAM,OAAO,UAAU,OAAO,WAAW,OAAO;AAAA;AAAA;AAAA;AAM9D,IAAM,oBAAoB,CAAC;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAoB;AAClB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,mBAAQ;;;AD3If,IAAO,cAAQ;","names":["styled","Box"]}
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-skeleton",
7
+ };
8
+
9
+ module.exports = config;
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@sproutsocial/seeds-react-skeleton",
3
+ "version": "1.0.0",
4
+ "description": "Seeds React Skeleton",
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
+ },
25
+ "devDependencies": {
26
+ "@types/react": "^18.0.0",
27
+ "@types/styled-components": "^5.1.26",
28
+ "@sproutsocial/eslint-config-seeds": "*",
29
+ "react": "^18.0.0",
30
+ "styled-components": "^5.2.3",
31
+ "tsup": "^8.0.2",
32
+ "typescript": "^5.6.2",
33
+ "@sproutsocial/seeds-tsconfig": "*",
34
+ "@sproutsocial/seeds-testing": "*",
35
+ "@sproutsocial/seeds-react-testing-library": "*"
36
+ },
37
+ "peerDependencies": {
38
+ "styled-components": "^5.2.3"
39
+ },
40
+ "engines": {
41
+ "node": ">=18"
42
+ }
43
+ }
@@ -0,0 +1,41 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import Box from "@sproutsocial/seeds-react-box";
4
+ import Banner from "@sproutsocial/seeds-react-banner";
5
+ import Skeleton from "./Skeleton";
6
+
7
+ const meta: Meta<typeof Skeleton> = {
8
+ title: "Components/Skeleton",
9
+ component: Skeleton,
10
+ };
11
+ export default meta;
12
+
13
+ type Story = StoryObj<typeof Skeleton>;
14
+
15
+ export const Default: Story = {
16
+ name: "Usage Example",
17
+ render: () => (
18
+ <>
19
+ <Banner
20
+ type="info"
21
+ text="When using a skeleton component, it's important to wrap it in a container with a role attribute set to status and an appropriate aria-label attribute. This helps ensure that screen readers and other assistive technologies can properly convey the purpose of the skeleton to users with screen readers."
22
+ mb={400}
23
+ />
24
+ <Box
25
+ maxWidth={200}
26
+ p={400}
27
+ borderRadius="outer"
28
+ border={500}
29
+ borderColor="container.border.base"
30
+ tabIndex={0}
31
+ role="status"
32
+ aria-label="Content is loading"
33
+ >
34
+ <Skeleton borderRadius="pill" height={48} width={48} mb={400} />
35
+ <Skeleton borderRadius="inner" height={16} width="100%" mb={400} />
36
+ <Skeleton borderRadius="inner" height={16} width="100%" mb={400} />
37
+ <Skeleton borderRadius="inner" height={128} width="100%" />
38
+ </Box>
39
+ </>
40
+ ),
41
+ };
@@ -0,0 +1,142 @@
1
+ import styled from "styled-components";
2
+ import Box, { type TypeBoxProps } from "@sproutsocial/seeds-react-box";
3
+
4
+ /**
5
+ *
6
+ * @param borderRadius
7
+ * @returns classname string for handling appropriate loader style depending on passed in properties
8
+ */
9
+ // @ts-ignore TODO: fix noImplicitAny error here. IDK why there are no types for this component
10
+ const SkeletonAttrs = ({ borderRadius, height, width }) => ({
11
+ className:
12
+ borderRadius === "pill" && height === width ? "circular" : "linear",
13
+ });
14
+
15
+ const Skeleton = styled(Box).attrs(SkeletonAttrs)`
16
+ position: relative;
17
+ background: ${(props) =>
18
+ props.theme.colors.container.background.decorative.neutral};
19
+ overflow: hidden;
20
+ &.circular {
21
+ &:before {
22
+ position: absolute;
23
+ top: -25%;
24
+ left: -25%;
25
+ content: '';
26
+ background-image: ${(props) => `conic-gradient(
27
+ ${props.theme.colors.container.background.decorative.neutral} 270deg,
28
+ ${props.theme.colors.container.border.decorative.neutral} 300deg
29
+ );`};
30
+ height: 150%;
31
+ width: 150%;
32
+ animation: SkeletonRotate 2s infinite linear;
33
+ }
34
+ &:after {
35
+ position: absolute;
36
+ top: 50%;
37
+ left: 50%;
38
+ transform: translate(-50%, -50%);
39
+ content: '';
40
+ height: calc(100% - 8px);
41
+ width: calc(100% - 8px);
42
+ background: ${(p) => p.theme.colors.app.background.base};
43
+ border-radius: 50%;
44
+ }
45
+ }
46
+ &.linear {
47
+ position: relative;
48
+ background-image: ${(props) => `linear-gradient(
49
+ 288deg,
50
+ ${props.theme.colors.container.background.decorative.neutral} 32%,
51
+ ${props.theme.colors.container.border.decorative.neutral},
52
+ ${props.theme.colors.container.background.decorative.neutral} 68%
53
+ );`}
54
+ background-size: 400%;
55
+ background-repeat: no-repeat;
56
+ animation: SkeletonShimmer 2s linear infinite reverse;
57
+ overflow: hidden;
58
+ &:after {
59
+ position: absolute;
60
+ bottom: 0;
61
+ content: "";
62
+ height: calc(100% - 4px);
63
+ width: 100%;
64
+ background: ${(props) =>
65
+ props.theme.colors.container.background.decorative.neutral};
66
+
67
+ }
68
+ }
69
+
70
+ @media (prefers-reduced-motion) {
71
+ &.linear,
72
+ &.circular::before {
73
+ animation: none;
74
+ }
75
+ &:before,
76
+ &:after {
77
+ display: none;
78
+ }
79
+ &.linear,
80
+ &.circular {
81
+ border: 1px solid ${(props) =>
82
+ props.theme.colors.container.border.decorative.neutral};
83
+ animation: SkeletonPulse 2s linear infinite alternate;
84
+ }
85
+ }
86
+
87
+ @keyframes SkeletonRotate {
88
+ 100% {
89
+ transform: rotate(360deg);
90
+ }
91
+ }
92
+ @keyframes SkeletonRotateFade {
93
+ 50% {
94
+ transform: rotate(360deg);
95
+ }
96
+ 90% {
97
+ opacity: 1;
98
+ }
99
+ 100% {
100
+ transform: rotate(720deg);
101
+ opacity: 0;
102
+ }
103
+ }
104
+
105
+ @keyframes SkeletonShimmer {
106
+ 0% {
107
+ background-position: 0% 0;
108
+ }
109
+ 100% {
110
+ background-position: 100% 0;
111
+ }
112
+ }
113
+ @keyframes SkeletonPulse {
114
+ 0% {
115
+ border-color: ${(props) =>
116
+ props.theme.colors.container.border.decorative.neutral}FF;
117
+ }
118
+ 100% {
119
+ border-color: ${(props) =>
120
+ props.theme.colors.container.border.decorative.neutral}1A;
121
+ }
122
+ }
123
+ `;
124
+
125
+ // @TODO: Refine types that are passed to SkeletonComponent
126
+ const SkeletonComponent = ({
127
+ borderRadius,
128
+ height,
129
+ width,
130
+ ...props
131
+ }: TypeBoxProps) => {
132
+ return (
133
+ <Skeleton
134
+ borderRadius={borderRadius}
135
+ height={height}
136
+ width={width}
137
+ {...props}
138
+ />
139
+ );
140
+ };
141
+
142
+ export default SkeletonComponent;
@@ -0,0 +1,31 @@
1
+ import React from "react";
2
+ import { render, screen } from "@sproutsocial/seeds-react-testing-library";
3
+ import Skeleton from "../Skeleton";
4
+
5
+ describe("Skeleton Component", () => {
6
+ it("renders with circular class when borderRadius is 'pill' and height equals width", () => {
7
+ render(
8
+ <Skeleton
9
+ borderRadius="pill"
10
+ height="50px"
11
+ width="50px"
12
+ data-testid="skeleton"
13
+ />
14
+ );
15
+ const skeletonElement = screen.getByTestId("skeleton");
16
+ expect(skeletonElement).toHaveClass("circular");
17
+ });
18
+
19
+ it("renders with linear class when borderRadius is not 'pill' or height does not equal width", () => {
20
+ render(
21
+ <Skeleton
22
+ borderRadius="square"
23
+ height="50px"
24
+ width="100px"
25
+ data-testid="skeleton"
26
+ />
27
+ );
28
+ const skeletonElement = screen.getByTestId("skeleton");
29
+ expect(skeletonElement).toHaveClass("linear");
30
+ });
31
+ });
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ import Skeleton from "../Skeleton";
3
+
4
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
5
+ function SkeletonTypes() {
6
+ return (
7
+ <>
8
+ <Skeleton />
9
+ {/* @ts-expect-error - test that invalid prop is rejected */}
10
+ <Skeleton flexDirection="invalid" />
11
+ </>
12
+ );
13
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ import Skeleton from "./Skeleton";
2
+
3
+ export default Skeleton;
4
+ export { Skeleton };
@@ -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/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", "**/*.stories.tsx"]
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
+ }));