@sproutsocial/seeds-react-skeleton 1.1.21 → 1.1.24
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/dist/esm/index.js +100 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +7 -6
- package/dist/index.d.ts +7 -6
- package/dist/index.js +100 -5
- package/dist/index.js.map +1 -1
- package/dist/skeleton.css +122 -0
- package/package.json +17 -6
- package/.eslintignore +0 -6
- package/.eslintrc.js +0 -4
- package/.turbo/turbo-build.log +0 -21
- package/CHANGELOG.md +0 -184
- package/jest.config.js +0 -9
- package/src/Skeleton.stories.tsx +0 -41
- package/src/Skeleton.tsx +0 -143
- package/src/SkeletonTypes.ts +0 -3
- package/src/__tests__/Skeleton.test.tsx +0 -31
- package/src/__tests__/Skeleton.typetest.tsx +0 -13
- package/src/index.ts +0 -5
- package/src/styled.d.ts +0 -7
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -12
package/dist/esm/index.js
CHANGED
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
// src/Skeleton.tsx
|
|
2
|
+
import React3 from "react";
|
|
3
|
+
|
|
4
|
+
// src/SkeletonHybrid.tsx
|
|
5
|
+
import React2 from "react";
|
|
6
|
+
|
|
7
|
+
// src/styles.ts
|
|
2
8
|
import styled from "styled-components";
|
|
3
9
|
import Box from "@sproutsocial/seeds-react-box";
|
|
4
|
-
|
|
10
|
+
|
|
11
|
+
// src/variant.ts
|
|
12
|
+
var getSkeletonVariant = ({
|
|
13
|
+
borderRadius,
|
|
14
|
+
height,
|
|
15
|
+
width
|
|
16
|
+
}) => borderRadius === "pill" && height === width ? "circular" : "linear";
|
|
17
|
+
var RADIUS_VARS = {
|
|
18
|
+
pill: "var(--radius-pill)",
|
|
19
|
+
inner: "var(--radius-inner)",
|
|
20
|
+
outer: "var(--radius-outer)",
|
|
21
|
+
400: "var(--radius-400)",
|
|
22
|
+
500: "var(--radius-500)",
|
|
23
|
+
600: "var(--radius-600)",
|
|
24
|
+
800: "var(--radius-800)",
|
|
25
|
+
900: "var(--radius-900)",
|
|
26
|
+
1e3: "var(--radius-1000)"
|
|
27
|
+
};
|
|
28
|
+
var radiusVar = (borderRadius) => {
|
|
29
|
+
if (borderRadius == null) return "0";
|
|
30
|
+
return RADIUS_VARS[String(borderRadius)] ?? "0";
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/styles.ts
|
|
5
34
|
var SkeletonAttrs = ({ borderRadius, height, width }) => ({
|
|
6
|
-
className: borderRadius
|
|
35
|
+
className: getSkeletonVariant({ borderRadius, height, width })
|
|
7
36
|
});
|
|
8
|
-
var
|
|
37
|
+
var SkeletonStyled = styled(Box).attrs(SkeletonAttrs)`
|
|
9
38
|
position: relative;
|
|
10
39
|
background: ${(props) => props.theme.colors.container.background.decorative.neutral};
|
|
11
40
|
overflow: hidden;
|
|
@@ -54,7 +83,7 @@ var Skeleton = styled(Box).attrs(SkeletonAttrs)`
|
|
|
54
83
|
height: calc(100% - 4px);
|
|
55
84
|
width: 100%;
|
|
56
85
|
background: ${(props) => props.theme.colors.container.background.decorative.neutral};
|
|
57
|
-
|
|
86
|
+
|
|
58
87
|
}
|
|
59
88
|
}
|
|
60
89
|
|
|
@@ -70,7 +99,7 @@ var Skeleton = styled(Box).attrs(SkeletonAttrs)`
|
|
|
70
99
|
&.linear,
|
|
71
100
|
&.circular {
|
|
72
101
|
border: 1px solid ${(props) => props.theme.colors.container.border.decorative.neutral};
|
|
73
|
-
animation: SkeletonPulse 2s linear infinite alternate;
|
|
102
|
+
animation: SkeletonPulse 2s linear infinite alternate;
|
|
74
103
|
}
|
|
75
104
|
}
|
|
76
105
|
|
|
@@ -109,6 +138,72 @@ var Skeleton = styled(Box).attrs(SkeletonAttrs)`
|
|
|
109
138
|
}
|
|
110
139
|
}
|
|
111
140
|
`;
|
|
141
|
+
var styles_default = SkeletonStyled;
|
|
142
|
+
|
|
143
|
+
// src/SkeletonTailwind.tsx
|
|
144
|
+
import React from "react";
|
|
145
|
+
import { jsx } from "react/jsx-runtime";
|
|
146
|
+
function cn(...inputs) {
|
|
147
|
+
const classes = [];
|
|
148
|
+
for (const input of inputs) {
|
|
149
|
+
if (!input) continue;
|
|
150
|
+
if (typeof input === "string") {
|
|
151
|
+
classes.push(input);
|
|
152
|
+
} else if (typeof input === "object") {
|
|
153
|
+
for (const [key, value] of Object.entries(input)) {
|
|
154
|
+
if (value) {
|
|
155
|
+
classes.push(key);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return classes.join(" ");
|
|
161
|
+
}
|
|
162
|
+
var toDimension = (value) => typeof value === "number" ? `${value}px` : value;
|
|
163
|
+
var SkeletonTailwind = React.forwardRef(
|
|
164
|
+
({ borderRadius, height, width, className, style, ...rest }, ref) => {
|
|
165
|
+
const variant = getSkeletonVariant({ borderRadius, height, width });
|
|
166
|
+
const skeletonStyle = {
|
|
167
|
+
width: toDimension(width),
|
|
168
|
+
height: toDimension(height),
|
|
169
|
+
...style,
|
|
170
|
+
// The shimmer/ring surface reads this for corner rounding; circular masks
|
|
171
|
+
// its own shape via border-radius: 50% in skeleton.css.
|
|
172
|
+
["--skeleton-radius"]: radiusVar(borderRadius)
|
|
173
|
+
};
|
|
174
|
+
return /* @__PURE__ */ jsx(
|
|
175
|
+
"div",
|
|
176
|
+
{
|
|
177
|
+
ref,
|
|
178
|
+
className: cn("seeds-skeleton", variant, className),
|
|
179
|
+
style: skeletonStyle,
|
|
180
|
+
...rest
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
);
|
|
185
|
+
SkeletonTailwind.displayName = "SkeletonTailwind";
|
|
186
|
+
|
|
187
|
+
// src/SkeletonHybrid.tsx
|
|
188
|
+
import { needsStyledComponents } from "@sproutsocial/seeds-react-system-props";
|
|
189
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
190
|
+
var SkeletonHybrid = React2.forwardRef(
|
|
191
|
+
(props, ref) => {
|
|
192
|
+
if (needsStyledComponents(props)) {
|
|
193
|
+
return /* @__PURE__ */ jsx2(styles_default, { ...props, ref });
|
|
194
|
+
}
|
|
195
|
+
return /* @__PURE__ */ jsx2(SkeletonTailwind, { ...props, ref });
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
SkeletonHybrid.displayName = "Skeleton";
|
|
199
|
+
var SkeletonHybrid_default = SkeletonHybrid;
|
|
200
|
+
|
|
201
|
+
// src/Skeleton.tsx
|
|
202
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
203
|
+
var Skeleton = React3.forwardRef(
|
|
204
|
+
(props, ref) => /* @__PURE__ */ jsx3(SkeletonHybrid_default, { ...props, ref })
|
|
205
|
+
);
|
|
206
|
+
Skeleton.displayName = "Skeleton";
|
|
112
207
|
var Skeleton_default = Skeleton;
|
|
113
208
|
|
|
114
209
|
// src/index.ts
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Skeleton.tsx","../../src/index.ts"],"sourcesContent":["import styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport type { SkeletonProps } from \"./SkeletonTypes\";\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\nexport const SkeletonComponent = ({\n borderRadius,\n height,\n width,\n ...props\n}: SkeletonProps) => {\n return (\n <Skeleton\n borderRadius={borderRadius}\n height={height}\n width={width}\n {...props}\n />\n );\n};\n\nexport default Skeleton;\n","import Skeleton from \"./Skeleton\";\n\nexport default Skeleton;\nexport * from \"./SkeletonTypes\";\nexport { Skeleton };\n"],"mappings":";AAAA,OAAO,YAAY;AACnB,OAAO,SAAS;AAoIZ;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;AAsB9D,IAAO,mBAAQ;;;AC5If,IAAO,gBAAQ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/Skeleton.tsx","../../src/SkeletonHybrid.tsx","../../src/styles.ts","../../src/variant.ts","../../src/SkeletonTailwind.tsx","../../src/index.ts"],"sourcesContent":["import React from \"react\";\nimport type { SkeletonProps } from \"./SkeletonTypes\";\nimport SkeletonHybrid from \"./SkeletonHybrid\";\n\n/**\n * Skeleton component. Automatically routes between the Tailwind implementation\n * (preferred) and the styled-components implementation (for consumers using\n * system props or styled() extension).\n */\nconst Skeleton = React.forwardRef<HTMLDivElement, SkeletonProps>(\n (props, ref) => <SkeletonHybrid {...props} ref={ref} />\n);\n\nSkeleton.displayName = \"Skeleton\";\nexport default Skeleton;\n","/**\n * Hybrid Skeleton Component\n * Automatically chooses between Tailwind and styled-components based on props.\n */\n\nimport React from \"react\";\nimport type { SkeletonProps } from \"./SkeletonTypes\";\nimport SkeletonStyled from \"./styles\"; // Styled-components version\nimport { SkeletonTailwind } from \"./SkeletonTailwind\"; // Tailwind version\nimport { needsStyledComponents } from \"@sproutsocial/seeds-react-system-props\";\n\nconst SkeletonHybrid = React.forwardRef<HTMLDivElement, SkeletonProps>(\n (props, ref) => {\n // Mirror the Button reference (ButtonHybrid.tsx): do NOT strip\n // width/height/borderRadius before the gate. width/height are styled-system\n // props, so a real (always-dimensioned) Skeleton — and any styled()\n // extension (injected theme/forwardedComponent) — routes to\n // styled-components, preserving styled-system dimension semantics\n // (number ≤ 1 → %, arrays → responsive) and styled() backward-compat. Only a\n // Skeleton with zero styled props uses the Tailwind path.\n if (needsStyledComponents(props)) {\n return <SkeletonStyled {...props} ref={ref} />;\n }\n\n // Use Tailwind version (preferred - better performance)\n return <SkeletonTailwind {...props} ref={ref} />;\n }\n);\n\nSkeletonHybrid.displayName = \"Skeleton\";\nexport default SkeletonHybrid;\n","import styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport { getSkeletonVariant } from \"./variant\";\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: getSkeletonVariant({ borderRadius, height, width }),\n});\n\n/**\n * Legacy styled-components implementation. Preserved verbatim as the fallback\n * rendering path for system props (margins, color, flex/grid) and `styled()`\n * extension. The Tailwind path ({@link SkeletonTailwind.tsx}) reproduces these\n * visuals as static CSS for the common case.\n */\nconst SkeletonStyled = 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\nexport default SkeletonStyled;\n","import type { SkeletonProps } from \"./SkeletonTypes\";\n\n/**\n * Computes the Skeleton variant class name. Shared by both the styled-components\n * path ({@link styles.ts}) and the Tailwind path ({@link SkeletonTailwind.tsx})\n * so the two stay in lockstep.\n *\n * A \"circular\" skeleton is a pill-rounded square (equal height/width); anything\n * else renders the \"linear\" shimmer.\n */\nexport const getSkeletonVariant = ({\n borderRadius,\n height,\n width,\n}: Pick<SkeletonProps, \"borderRadius\" | \"height\" | \"width\">): string =>\n borderRadius === \"pill\" && height === width ? \"circular\" : \"linear\";\n\n/**\n * Maps a `borderRadius` alias/token to the corresponding theme CSS variable so\n * the Tailwind path can apply corner rounding without styled-components. Unknown\n * values (e.g. \"square\") fall back to no rounding.\n */\nconst RADIUS_VARS: Record<string, string> = {\n pill: \"var(--radius-pill)\",\n inner: \"var(--radius-inner)\",\n outer: \"var(--radius-outer)\",\n 400: \"var(--radius-400)\",\n 500: \"var(--radius-500)\",\n 600: \"var(--radius-600)\",\n 800: \"var(--radius-800)\",\n 900: \"var(--radius-900)\",\n 1000: \"var(--radius-1000)\",\n};\n\nexport const radiusVar = (borderRadius: SkeletonProps[\"borderRadius\"]): string => {\n if (borderRadius == null) return \"0\";\n return RADIUS_VARS[String(borderRadius)] ?? \"0\";\n};\n","/**\n * Tailwind CSS implementation of the Skeleton component.\n * Uses Seeds skeleton CSS classes from skeleton.css.\n */\n\nimport React from \"react\";\nimport type { SkeletonProps } from \"./SkeletonTypes\";\nimport { getSkeletonVariant, radiusVar } from \"./variant\";\n\n// Utility for merging class names properly\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\n/**\n * Converts a system-prop dimension (number → px, string passthrough) into a\n * value usable in an inline style. Matches how Box/styled-system renders these.\n */\nconst toDimension = (value: SkeletonProps[\"width\"]): string | number | undefined =>\n typeof value === \"number\" ? `${value}px` : (value as string | undefined);\n\nexport const SkeletonTailwind = React.forwardRef<HTMLDivElement, SkeletonProps>(\n ({ borderRadius, height, width, className, style, ...rest }, ref) => {\n const variant = getSkeletonVariant({ borderRadius, height, width });\n\n const skeletonStyle: React.CSSProperties = {\n width: toDimension(width),\n height: toDimension(height),\n ...style,\n // The shimmer/ring surface reads this for corner rounding; circular masks\n // its own shape via border-radius: 50% in skeleton.css.\n [\"--skeleton-radius\" as any]: radiusVar(borderRadius),\n };\n\n return (\n <div\n ref={ref}\n className={cn(\"seeds-skeleton\", variant, className)}\n style={skeletonStyle}\n // `rest` is typed as the residual Box/styled-system props (SkeletonProps\n // extends TypeBoxProps); the hybrid gate (SkeletonHybrid) only routes\n // zero-styled-prop usage here, so at runtime `rest` carries plain DOM\n // attributes. Narrow the spread to keep the literal <div> type-safe —\n // ButtonTailwind sidesteps this by rendering to a Component cast as any.\n {...(rest as React.HTMLAttributes<HTMLDivElement>)}\n />\n );\n }\n);\n\nSkeletonTailwind.displayName = \"SkeletonTailwind\";\n","import Skeleton from \"./Skeleton\";\n\nexport default Skeleton;\nexport * from \"./SkeletonTypes\";\nexport { Skeleton };\n"],"mappings":";AAAA,OAAOA,YAAW;;;ACKlB,OAAOC,YAAW;;;ACLlB,OAAO,YAAY;AACnB,OAAO,SAAS;;;ACST,IAAM,qBAAqB,CAAC;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,MACE,iBAAiB,UAAU,WAAW,QAAQ,aAAa;AAO7D,IAAM,cAAsC;AAAA,EAC1C,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAM;AACR;AAEO,IAAM,YAAY,CAAC,iBAAwD;AAChF,MAAI,gBAAgB,KAAM,QAAO;AACjC,SAAO,YAAY,OAAO,YAAY,CAAC,KAAK;AAC9C;;;AD3BA,IAAM,gBAAgB,CAAC,EAAE,cAAc,QAAQ,MAAM,OAAO;AAAA,EAC1D,WAAW,mBAAmB,EAAE,cAAc,QAAQ,MAAM,CAAC;AAC/D;AAQA,IAAM,iBAAiB,OAAO,GAAG,EAAE,MAAM,aAAa;AAAA;AAAA,gBAEtC,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;AAK9D,IAAO,iBAAQ;;;AE7Hf,OAAO,WAAW;AAgDZ;AA3CN,SAAS,MACJ,QACK;AACR,QAAM,UAAoB,CAAC;AAE3B,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAO;AAEZ,QAAI,OAAO,UAAU,UAAU;AAC7B,cAAQ,KAAK,KAAK;AAAA,IACpB,WAAW,OAAO,UAAU,UAAU;AACpC,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,YAAI,OAAO;AACT,kBAAQ,KAAK,GAAG;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,QAAQ,KAAK,GAAG;AACzB;AAMA,IAAM,cAAc,CAAC,UACnB,OAAO,UAAU,WAAW,GAAG,KAAK,OAAQ;AAEvC,IAAM,mBAAmB,MAAM;AAAA,EACpC,CAAC,EAAE,cAAc,QAAQ,OAAO,WAAW,OAAO,GAAG,KAAK,GAAG,QAAQ;AACnE,UAAM,UAAU,mBAAmB,EAAE,cAAc,QAAQ,MAAM,CAAC;AAElE,UAAM,gBAAqC;AAAA,MACzC,OAAO,YAAY,KAAK;AAAA,MACxB,QAAQ,YAAY,MAAM;AAAA,MAC1B,GAAG;AAAA;AAAA;AAAA,MAGH,CAAC,mBAA0B,GAAG,UAAU,YAAY;AAAA,IACtD;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW,GAAG,kBAAkB,SAAS,SAAS;AAAA,QAClD,OAAO;AAAA,QAMN,GAAI;AAAA;AAAA,IACP;AAAA,EAEJ;AACF;AAEA,iBAAiB,cAAc;;;AH3D/B,SAAS,6BAA6B;AAYzB,gBAAAC,YAAA;AAVb,IAAM,iBAAiBC,OAAM;AAAA,EAC3B,CAAC,OAAO,QAAQ;AAQd,QAAI,sBAAsB,KAAK,GAAG;AAChC,aAAO,gBAAAD,KAAC,kBAAgB,GAAG,OAAO,KAAU;AAAA,IAC9C;AAGA,WAAO,gBAAAA,KAAC,oBAAkB,GAAG,OAAO,KAAU;AAAA,EAChD;AACF;AAEA,eAAe,cAAc;AAC7B,IAAO,yBAAQ;;;ADpBG,gBAAAE,YAAA;AADlB,IAAM,WAAWC,OAAM;AAAA,EACrB,CAAC,OAAO,QAAQ,gBAAAD,KAAC,0BAAgB,GAAG,OAAO,KAAU;AACvD;AAEA,SAAS,cAAc;AACvB,IAAO,mBAAQ;;;AKZf,IAAO,gBAAQ;","names":["React","React","jsx","React","jsx","React"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as react from 'react';
|
|
3
|
-
import * as _sproutsocial_seeds_react_box from '@sproutsocial/seeds-react-box';
|
|
1
|
+
import React from 'react';
|
|
4
2
|
import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
|
|
5
3
|
|
|
6
4
|
interface SkeletonProps extends TypeBoxProps {
|
|
7
5
|
}
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Skeleton component. Automatically routes between the Tailwind implementation
|
|
9
|
+
* (preferred) and the styled-components implementation (for consumers using
|
|
10
|
+
* system props or styled() extension).
|
|
11
|
+
*/
|
|
12
|
+
declare const Skeleton: React.ForwardRefExoticComponent<Omit<SkeletonProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
12
13
|
|
|
13
14
|
export { Skeleton, type SkeletonProps, Skeleton as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as react from 'react';
|
|
3
|
-
import * as _sproutsocial_seeds_react_box from '@sproutsocial/seeds-react-box';
|
|
1
|
+
import React from 'react';
|
|
4
2
|
import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
|
|
5
3
|
|
|
6
4
|
interface SkeletonProps extends TypeBoxProps {
|
|
7
5
|
}
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Skeleton component. Automatically routes between the Tailwind implementation
|
|
9
|
+
* (preferred) and the styled-components implementation (for consumers using
|
|
10
|
+
* system props or styled() extension).
|
|
11
|
+
*/
|
|
12
|
+
declare const Skeleton: React.ForwardRefExoticComponent<Omit<SkeletonProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
12
13
|
|
|
13
14
|
export { Skeleton, type SkeletonProps, Skeleton as default };
|
package/dist/index.js
CHANGED
|
@@ -36,13 +36,42 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/Skeleton.tsx
|
|
39
|
+
var import_react3 = __toESM(require("react"));
|
|
40
|
+
|
|
41
|
+
// src/SkeletonHybrid.tsx
|
|
42
|
+
var import_react2 = __toESM(require("react"));
|
|
43
|
+
|
|
44
|
+
// src/styles.ts
|
|
39
45
|
var import_styled_components = __toESM(require("styled-components"));
|
|
40
46
|
var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
|
|
41
|
-
|
|
47
|
+
|
|
48
|
+
// src/variant.ts
|
|
49
|
+
var getSkeletonVariant = ({
|
|
50
|
+
borderRadius,
|
|
51
|
+
height,
|
|
52
|
+
width
|
|
53
|
+
}) => borderRadius === "pill" && height === width ? "circular" : "linear";
|
|
54
|
+
var RADIUS_VARS = {
|
|
55
|
+
pill: "var(--radius-pill)",
|
|
56
|
+
inner: "var(--radius-inner)",
|
|
57
|
+
outer: "var(--radius-outer)",
|
|
58
|
+
400: "var(--radius-400)",
|
|
59
|
+
500: "var(--radius-500)",
|
|
60
|
+
600: "var(--radius-600)",
|
|
61
|
+
800: "var(--radius-800)",
|
|
62
|
+
900: "var(--radius-900)",
|
|
63
|
+
1e3: "var(--radius-1000)"
|
|
64
|
+
};
|
|
65
|
+
var radiusVar = (borderRadius) => {
|
|
66
|
+
if (borderRadius == null) return "0";
|
|
67
|
+
return RADIUS_VARS[String(borderRadius)] ?? "0";
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// src/styles.ts
|
|
42
71
|
var SkeletonAttrs = ({ borderRadius, height, width }) => ({
|
|
43
|
-
className: borderRadius
|
|
72
|
+
className: getSkeletonVariant({ borderRadius, height, width })
|
|
44
73
|
});
|
|
45
|
-
var
|
|
74
|
+
var SkeletonStyled = (0, import_styled_components.default)(import_seeds_react_box.default).attrs(SkeletonAttrs)`
|
|
46
75
|
position: relative;
|
|
47
76
|
background: ${(props) => props.theme.colors.container.background.decorative.neutral};
|
|
48
77
|
overflow: hidden;
|
|
@@ -91,7 +120,7 @@ var Skeleton = (0, import_styled_components.default)(import_seeds_react_box.defa
|
|
|
91
120
|
height: calc(100% - 4px);
|
|
92
121
|
width: 100%;
|
|
93
122
|
background: ${(props) => props.theme.colors.container.background.decorative.neutral};
|
|
94
|
-
|
|
123
|
+
|
|
95
124
|
}
|
|
96
125
|
}
|
|
97
126
|
|
|
@@ -107,7 +136,7 @@ var Skeleton = (0, import_styled_components.default)(import_seeds_react_box.defa
|
|
|
107
136
|
&.linear,
|
|
108
137
|
&.circular {
|
|
109
138
|
border: 1px solid ${(props) => props.theme.colors.container.border.decorative.neutral};
|
|
110
|
-
animation: SkeletonPulse 2s linear infinite alternate;
|
|
139
|
+
animation: SkeletonPulse 2s linear infinite alternate;
|
|
111
140
|
}
|
|
112
141
|
}
|
|
113
142
|
|
|
@@ -146,6 +175,72 @@ var Skeleton = (0, import_styled_components.default)(import_seeds_react_box.defa
|
|
|
146
175
|
}
|
|
147
176
|
}
|
|
148
177
|
`;
|
|
178
|
+
var styles_default = SkeletonStyled;
|
|
179
|
+
|
|
180
|
+
// src/SkeletonTailwind.tsx
|
|
181
|
+
var import_react = __toESM(require("react"));
|
|
182
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
183
|
+
function cn(...inputs) {
|
|
184
|
+
const classes = [];
|
|
185
|
+
for (const input of inputs) {
|
|
186
|
+
if (!input) continue;
|
|
187
|
+
if (typeof input === "string") {
|
|
188
|
+
classes.push(input);
|
|
189
|
+
} else if (typeof input === "object") {
|
|
190
|
+
for (const [key, value] of Object.entries(input)) {
|
|
191
|
+
if (value) {
|
|
192
|
+
classes.push(key);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return classes.join(" ");
|
|
198
|
+
}
|
|
199
|
+
var toDimension = (value) => typeof value === "number" ? `${value}px` : value;
|
|
200
|
+
var SkeletonTailwind = import_react.default.forwardRef(
|
|
201
|
+
({ borderRadius, height, width, className, style, ...rest }, ref) => {
|
|
202
|
+
const variant = getSkeletonVariant({ borderRadius, height, width });
|
|
203
|
+
const skeletonStyle = {
|
|
204
|
+
width: toDimension(width),
|
|
205
|
+
height: toDimension(height),
|
|
206
|
+
...style,
|
|
207
|
+
// The shimmer/ring surface reads this for corner rounding; circular masks
|
|
208
|
+
// its own shape via border-radius: 50% in skeleton.css.
|
|
209
|
+
["--skeleton-radius"]: radiusVar(borderRadius)
|
|
210
|
+
};
|
|
211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
212
|
+
"div",
|
|
213
|
+
{
|
|
214
|
+
ref,
|
|
215
|
+
className: cn("seeds-skeleton", variant, className),
|
|
216
|
+
style: skeletonStyle,
|
|
217
|
+
...rest
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
SkeletonTailwind.displayName = "SkeletonTailwind";
|
|
223
|
+
|
|
224
|
+
// src/SkeletonHybrid.tsx
|
|
225
|
+
var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
|
|
226
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
227
|
+
var SkeletonHybrid = import_react2.default.forwardRef(
|
|
228
|
+
(props, ref) => {
|
|
229
|
+
if ((0, import_seeds_react_system_props.needsStyledComponents)(props)) {
|
|
230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(styles_default, { ...props, ref });
|
|
231
|
+
}
|
|
232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SkeletonTailwind, { ...props, ref });
|
|
233
|
+
}
|
|
234
|
+
);
|
|
235
|
+
SkeletonHybrid.displayName = "Skeleton";
|
|
236
|
+
var SkeletonHybrid_default = SkeletonHybrid;
|
|
237
|
+
|
|
238
|
+
// src/Skeleton.tsx
|
|
239
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
240
|
+
var Skeleton = import_react3.default.forwardRef(
|
|
241
|
+
(props, ref) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(SkeletonHybrid_default, { ...props, ref })
|
|
242
|
+
);
|
|
243
|
+
Skeleton.displayName = "Skeleton";
|
|
149
244
|
var Skeleton_default = Skeleton;
|
|
150
245
|
|
|
151
246
|
// src/index.ts
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/Skeleton.tsx"],"sourcesContent":["import Skeleton from \"./Skeleton\";\n\nexport default Skeleton;\nexport * from \"./SkeletonTypes\";\nexport { Skeleton };\n","import styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport type { SkeletonProps } from \"./SkeletonTypes\";\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\nexport const SkeletonComponent = ({\n borderRadius,\n height,\n width,\n ...props\n}: SkeletonProps) => {\n return (\n <Skeleton\n borderRadius={borderRadius}\n height={height}\n width={width}\n {...props}\n />\n );\n};\n\nexport default Skeleton;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,+BAAmB;AACnB,6BAAgB;AAoIZ;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;AAsB9D,IAAO,mBAAQ;;;AD5If,IAAO,gBAAQ;","names":["styled","Box"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Skeleton.tsx","../src/SkeletonHybrid.tsx","../src/styles.ts","../src/variant.ts","../src/SkeletonTailwind.tsx"],"sourcesContent":["import Skeleton from \"./Skeleton\";\n\nexport default Skeleton;\nexport * from \"./SkeletonTypes\";\nexport { Skeleton };\n","import React from \"react\";\nimport type { SkeletonProps } from \"./SkeletonTypes\";\nimport SkeletonHybrid from \"./SkeletonHybrid\";\n\n/**\n * Skeleton component. Automatically routes between the Tailwind implementation\n * (preferred) and the styled-components implementation (for consumers using\n * system props or styled() extension).\n */\nconst Skeleton = React.forwardRef<HTMLDivElement, SkeletonProps>(\n (props, ref) => <SkeletonHybrid {...props} ref={ref} />\n);\n\nSkeleton.displayName = \"Skeleton\";\nexport default Skeleton;\n","/**\n * Hybrid Skeleton Component\n * Automatically chooses between Tailwind and styled-components based on props.\n */\n\nimport React from \"react\";\nimport type { SkeletonProps } from \"./SkeletonTypes\";\nimport SkeletonStyled from \"./styles\"; // Styled-components version\nimport { SkeletonTailwind } from \"./SkeletonTailwind\"; // Tailwind version\nimport { needsStyledComponents } from \"@sproutsocial/seeds-react-system-props\";\n\nconst SkeletonHybrid = React.forwardRef<HTMLDivElement, SkeletonProps>(\n (props, ref) => {\n // Mirror the Button reference (ButtonHybrid.tsx): do NOT strip\n // width/height/borderRadius before the gate. width/height are styled-system\n // props, so a real (always-dimensioned) Skeleton — and any styled()\n // extension (injected theme/forwardedComponent) — routes to\n // styled-components, preserving styled-system dimension semantics\n // (number ≤ 1 → %, arrays → responsive) and styled() backward-compat. Only a\n // Skeleton with zero styled props uses the Tailwind path.\n if (needsStyledComponents(props)) {\n return <SkeletonStyled {...props} ref={ref} />;\n }\n\n // Use Tailwind version (preferred - better performance)\n return <SkeletonTailwind {...props} ref={ref} />;\n }\n);\n\nSkeletonHybrid.displayName = \"Skeleton\";\nexport default SkeletonHybrid;\n","import styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport { getSkeletonVariant } from \"./variant\";\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: getSkeletonVariant({ borderRadius, height, width }),\n});\n\n/**\n * Legacy styled-components implementation. Preserved verbatim as the fallback\n * rendering path for system props (margins, color, flex/grid) and `styled()`\n * extension. The Tailwind path ({@link SkeletonTailwind.tsx}) reproduces these\n * visuals as static CSS for the common case.\n */\nconst SkeletonStyled = 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\nexport default SkeletonStyled;\n","import type { SkeletonProps } from \"./SkeletonTypes\";\n\n/**\n * Computes the Skeleton variant class name. Shared by both the styled-components\n * path ({@link styles.ts}) and the Tailwind path ({@link SkeletonTailwind.tsx})\n * so the two stay in lockstep.\n *\n * A \"circular\" skeleton is a pill-rounded square (equal height/width); anything\n * else renders the \"linear\" shimmer.\n */\nexport const getSkeletonVariant = ({\n borderRadius,\n height,\n width,\n}: Pick<SkeletonProps, \"borderRadius\" | \"height\" | \"width\">): string =>\n borderRadius === \"pill\" && height === width ? \"circular\" : \"linear\";\n\n/**\n * Maps a `borderRadius` alias/token to the corresponding theme CSS variable so\n * the Tailwind path can apply corner rounding without styled-components. Unknown\n * values (e.g. \"square\") fall back to no rounding.\n */\nconst RADIUS_VARS: Record<string, string> = {\n pill: \"var(--radius-pill)\",\n inner: \"var(--radius-inner)\",\n outer: \"var(--radius-outer)\",\n 400: \"var(--radius-400)\",\n 500: \"var(--radius-500)\",\n 600: \"var(--radius-600)\",\n 800: \"var(--radius-800)\",\n 900: \"var(--radius-900)\",\n 1000: \"var(--radius-1000)\",\n};\n\nexport const radiusVar = (borderRadius: SkeletonProps[\"borderRadius\"]): string => {\n if (borderRadius == null) return \"0\";\n return RADIUS_VARS[String(borderRadius)] ?? \"0\";\n};\n","/**\n * Tailwind CSS implementation of the Skeleton component.\n * Uses Seeds skeleton CSS classes from skeleton.css.\n */\n\nimport React from \"react\";\nimport type { SkeletonProps } from \"./SkeletonTypes\";\nimport { getSkeletonVariant, radiusVar } from \"./variant\";\n\n// Utility for merging class names properly\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\n/**\n * Converts a system-prop dimension (number → px, string passthrough) into a\n * value usable in an inline style. Matches how Box/styled-system renders these.\n */\nconst toDimension = (value: SkeletonProps[\"width\"]): string | number | undefined =>\n typeof value === \"number\" ? `${value}px` : (value as string | undefined);\n\nexport const SkeletonTailwind = React.forwardRef<HTMLDivElement, SkeletonProps>(\n ({ borderRadius, height, width, className, style, ...rest }, ref) => {\n const variant = getSkeletonVariant({ borderRadius, height, width });\n\n const skeletonStyle: React.CSSProperties = {\n width: toDimension(width),\n height: toDimension(height),\n ...style,\n // The shimmer/ring surface reads this for corner rounding; circular masks\n // its own shape via border-radius: 50% in skeleton.css.\n [\"--skeleton-radius\" as any]: radiusVar(borderRadius),\n };\n\n return (\n <div\n ref={ref}\n className={cn(\"seeds-skeleton\", variant, className)}\n style={skeletonStyle}\n // `rest` is typed as the residual Box/styled-system props (SkeletonProps\n // extends TypeBoxProps); the hybrid gate (SkeletonHybrid) only routes\n // zero-styled-prop usage here, so at runtime `rest` carries plain DOM\n // attributes. Narrow the spread to keep the literal <div> type-safe —\n // ButtonTailwind sidesteps this by rendering to a Component cast as any.\n {...(rest as React.HTMLAttributes<HTMLDivElement>)}\n />\n );\n }\n);\n\nSkeletonTailwind.displayName = \"SkeletonTailwind\";\n"],"mappings":"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","names":["import_react","import_react","styled","Box","React","import_jsx_runtime","React","import_jsx_runtime","React"]}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeds Skeleton component classes
|
|
3
|
+
* Static reproduction of the styled-components Skeleton visuals.
|
|
4
|
+
*
|
|
5
|
+
* Requires @sproutsocial/seeds-react-theme/dist/theme-all.css imported for
|
|
6
|
+
* CSS variable definitions and dark mode support.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* <div class="seeds-skeleton circular" style="width:48px;height:48px"></div>
|
|
10
|
+
* <div class="seeds-skeleton linear" style="width:100%;height:16px"></div>
|
|
11
|
+
*
|
|
12
|
+
* The `--skeleton-radius` custom property (set inline from the `borderRadius`
|
|
13
|
+
* prop) controls corner rounding for the linear surface; the circular variant
|
|
14
|
+
* masks its own shape.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
@layer components {
|
|
18
|
+
.seeds-skeleton {
|
|
19
|
+
position: relative;
|
|
20
|
+
background: var(--color-container-bg-decorative-neutral);
|
|
21
|
+
overflow: hidden;
|
|
22
|
+
border-radius: var(--skeleton-radius, 0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.seeds-skeleton.circular::before {
|
|
26
|
+
position: absolute;
|
|
27
|
+
top: -25%;
|
|
28
|
+
left: -25%;
|
|
29
|
+
content: "";
|
|
30
|
+
background-image: conic-gradient(
|
|
31
|
+
var(--color-container-bg-decorative-neutral) 270deg,
|
|
32
|
+
var(--color-container-border-decorative-neutral) 300deg
|
|
33
|
+
);
|
|
34
|
+
height: 150%;
|
|
35
|
+
width: 150%;
|
|
36
|
+
animation: SkeletonRotate 2s infinite linear;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.seeds-skeleton.circular::after {
|
|
40
|
+
position: absolute;
|
|
41
|
+
top: 50%;
|
|
42
|
+
left: 50%;
|
|
43
|
+
transform: translate(-50%, -50%);
|
|
44
|
+
content: "";
|
|
45
|
+
height: calc(100% - 8px);
|
|
46
|
+
width: calc(100% - 8px);
|
|
47
|
+
background: var(--color-app-bg-base);
|
|
48
|
+
border-radius: 50%;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.seeds-skeleton.linear {
|
|
52
|
+
position: relative;
|
|
53
|
+
background-image: linear-gradient(
|
|
54
|
+
288deg,
|
|
55
|
+
var(--color-container-bg-decorative-neutral) 32%,
|
|
56
|
+
var(--color-container-border-decorative-neutral),
|
|
57
|
+
var(--color-container-bg-decorative-neutral) 68%
|
|
58
|
+
);
|
|
59
|
+
background-size: 400%;
|
|
60
|
+
background-repeat: no-repeat;
|
|
61
|
+
animation: SkeletonShimmer 2s linear infinite reverse;
|
|
62
|
+
overflow: hidden;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.seeds-skeleton.linear::after {
|
|
66
|
+
position: absolute;
|
|
67
|
+
bottom: 0;
|
|
68
|
+
content: "";
|
|
69
|
+
height: calc(100% - 4px);
|
|
70
|
+
width: 100%;
|
|
71
|
+
background: var(--color-container-bg-decorative-neutral);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@media (prefers-reduced-motion) {
|
|
75
|
+
.seeds-skeleton.linear,
|
|
76
|
+
.seeds-skeleton.circular::before {
|
|
77
|
+
animation: none;
|
|
78
|
+
}
|
|
79
|
+
.seeds-skeleton::before,
|
|
80
|
+
.seeds-skeleton::after {
|
|
81
|
+
display: none;
|
|
82
|
+
}
|
|
83
|
+
.seeds-skeleton.linear,
|
|
84
|
+
.seeds-skeleton.circular {
|
|
85
|
+
border: 1px solid var(--color-container-border-decorative-neutral);
|
|
86
|
+
animation: SkeletonPulse 2s linear infinite alternate;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@keyframes SkeletonRotate {
|
|
92
|
+
100% {
|
|
93
|
+
transform: rotate(360deg);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@keyframes SkeletonShimmer {
|
|
98
|
+
0% {
|
|
99
|
+
background-position: 0% 0;
|
|
100
|
+
}
|
|
101
|
+
100% {
|
|
102
|
+
background-position: 100% 0;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* The styled-components original faded the border via hex-alpha concatenation
|
|
108
|
+
* (…neutral + "FF" → "1A"); that string trick does not translate to var(--…),
|
|
109
|
+
* so the fade is reproduced with color-mix (≈10% alpha matches 0x1A).
|
|
110
|
+
*/
|
|
111
|
+
@keyframes SkeletonPulse {
|
|
112
|
+
0% {
|
|
113
|
+
border-color: var(--color-container-border-decorative-neutral);
|
|
114
|
+
}
|
|
115
|
+
100% {
|
|
116
|
+
border-color: color-mix(
|
|
117
|
+
in srgb,
|
|
118
|
+
var(--color-container-border-decorative-neutral) 10%,
|
|
119
|
+
transparent
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sproutsocial/seeds-react-skeleton",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.24",
|
|
4
4
|
"description": "Seeds React Skeleton",
|
|
5
5
|
"author": "Sprout Social, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"module": "dist/esm/index.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/esm/index.js",
|
|
17
|
+
"require": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./dist/skeleton.css": "./dist/skeleton.css"
|
|
20
|
+
},
|
|
10
21
|
"scripts": {
|
|
11
|
-
"build": "tsup --dts",
|
|
12
|
-
"build:debug": "tsup --dts --metafile",
|
|
22
|
+
"build": "tsup --dts && cp src/skeleton.css dist/skeleton.css",
|
|
23
|
+
"build:debug": "tsup --dts --metafile && cp src/skeleton.css dist/skeleton.css",
|
|
13
24
|
"dev": "tsup --watch --dts",
|
|
14
25
|
"clean": "rm -rf .turbo dist",
|
|
15
26
|
"clean:modules": "rm -rf node_modules",
|
|
@@ -18,9 +29,9 @@
|
|
|
18
29
|
"test:watch": "jest --watch --coverage=false"
|
|
19
30
|
},
|
|
20
31
|
"dependencies": {
|
|
21
|
-
"@sproutsocial/seeds-react-theme": "^4.
|
|
22
|
-
"@sproutsocial/seeds-react-system-props": "^3.1.
|
|
23
|
-
"@sproutsocial/seeds-react-box": "^1.1.
|
|
32
|
+
"@sproutsocial/seeds-react-theme": "^4.2.0",
|
|
33
|
+
"@sproutsocial/seeds-react-system-props": "^3.1.2",
|
|
34
|
+
"@sproutsocial/seeds-react-box": "^1.1.24"
|
|
24
35
|
},
|
|
25
36
|
"devDependencies": {
|
|
26
37
|
"@types/react": "^18.0.0",
|
package/.eslintignore
DELETED
package/.eslintrc.js
DELETED
package/.turbo/turbo-build.log
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
yarn run v1.22.22
|
|
2
|
-
$ tsup --dts
|
|
3
|
-
[34mCLI[39m Building entry: src/index.ts
|
|
4
|
-
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
5
|
-
[34mCLI[39m tsup v8.5.0
|
|
6
|
-
[34mCLI[39m Using tsup config: /home/runner/_work/seeds/seeds/seeds-react/seeds-react-skeleton/tsup.config.ts
|
|
7
|
-
[34mCLI[39m Target: es2022
|
|
8
|
-
[34mCLI[39m Cleaning output folder
|
|
9
|
-
[34mCJS[39m Build start
|
|
10
|
-
[34mESM[39m Build start
|
|
11
|
-
[32mCJS[39m [1mdist/index.js [22m[32m4.73 KB[39m
|
|
12
|
-
[32mCJS[39m [1mdist/index.js.map [22m[32m5.14 KB[39m
|
|
13
|
-
[32mCJS[39m ⚡️ Build success in 14ms
|
|
14
|
-
[32mESM[39m [1mdist/esm/index.js [22m[32m3.03 KB[39m
|
|
15
|
-
[32mESM[39m [1mdist/esm/index.js.map [22m[32m5.07 KB[39m
|
|
16
|
-
[32mESM[39m ⚡️ Build success in 14ms
|
|
17
|
-
[34mDTS[39m Build start
|
|
18
|
-
[32mDTS[39m ⚡️ Build success in 6423ms
|
|
19
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m604.00 B[39m
|
|
20
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m604.00 B[39m
|
|
21
|
-
Done in 7.83s.
|
package/CHANGELOG.md
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
# @sproutsocial/seeds-react-skeleton
|
|
2
|
-
|
|
3
|
-
## 1.1.21
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- Updated dependencies [a13a571]
|
|
8
|
-
- @sproutsocial/seeds-react-theme@4.1.1
|
|
9
|
-
- @sproutsocial/seeds-react-box@1.1.22
|
|
10
|
-
|
|
11
|
-
## 1.1.20
|
|
12
|
-
|
|
13
|
-
### Patch Changes
|
|
14
|
-
|
|
15
|
-
- Updated dependencies [5892f44]
|
|
16
|
-
- @sproutsocial/seeds-react-system-props@3.1.1
|
|
17
|
-
- @sproutsocial/seeds-react-box@1.1.21
|
|
18
|
-
|
|
19
|
-
## 1.1.19
|
|
20
|
-
|
|
21
|
-
### Patch Changes
|
|
22
|
-
|
|
23
|
-
- Updated dependencies [5114a32]
|
|
24
|
-
- @sproutsocial/seeds-react-theme@4.1.0
|
|
25
|
-
- @sproutsocial/seeds-react-box@1.1.20
|
|
26
|
-
|
|
27
|
-
## 1.1.18
|
|
28
|
-
|
|
29
|
-
### Patch Changes
|
|
30
|
-
|
|
31
|
-
- Updated dependencies [132ef9d]
|
|
32
|
-
- Updated dependencies [132ef9d]
|
|
33
|
-
- @sproutsocial/seeds-react-theme@4.0.0
|
|
34
|
-
- @sproutsocial/seeds-react-system-props@3.1.0
|
|
35
|
-
- @sproutsocial/seeds-react-box@1.1.19
|
|
36
|
-
|
|
37
|
-
## 1.1.17
|
|
38
|
-
|
|
39
|
-
### Patch Changes
|
|
40
|
-
|
|
41
|
-
- Updated dependencies [47c62b3]
|
|
42
|
-
- @sproutsocial/seeds-react-theme@3.7.1
|
|
43
|
-
- @sproutsocial/seeds-react-box@1.1.18
|
|
44
|
-
|
|
45
|
-
## 1.1.16
|
|
46
|
-
|
|
47
|
-
### Patch Changes
|
|
48
|
-
|
|
49
|
-
- Updated dependencies [06da9c2]
|
|
50
|
-
- @sproutsocial/seeds-react-theme@3.7.0
|
|
51
|
-
- @sproutsocial/seeds-react-box@1.1.17
|
|
52
|
-
|
|
53
|
-
## 1.1.15
|
|
54
|
-
|
|
55
|
-
### Patch Changes
|
|
56
|
-
|
|
57
|
-
- Updated dependencies [4ba8720]
|
|
58
|
-
- @sproutsocial/seeds-react-theme@3.6.2
|
|
59
|
-
- @sproutsocial/seeds-react-box@1.1.16
|
|
60
|
-
|
|
61
|
-
## 1.1.14
|
|
62
|
-
|
|
63
|
-
### Patch Changes
|
|
64
|
-
|
|
65
|
-
- Updated dependencies [1f9a473]
|
|
66
|
-
- @sproutsocial/seeds-react-theme@3.6.1
|
|
67
|
-
- @sproutsocial/seeds-react-box@1.1.15
|
|
68
|
-
|
|
69
|
-
## 1.1.13
|
|
70
|
-
|
|
71
|
-
### Patch Changes
|
|
72
|
-
|
|
73
|
-
- Updated dependencies [17d4f12]
|
|
74
|
-
- @sproutsocial/seeds-react-theme@3.6.0
|
|
75
|
-
- @sproutsocial/seeds-react-box@1.1.14
|
|
76
|
-
|
|
77
|
-
## 1.1.12
|
|
78
|
-
|
|
79
|
-
### Patch Changes
|
|
80
|
-
|
|
81
|
-
- Updated dependencies [118e300]
|
|
82
|
-
- @sproutsocial/seeds-react-theme@3.5.1
|
|
83
|
-
- @sproutsocial/seeds-react-box@1.1.13
|
|
84
|
-
|
|
85
|
-
## 1.1.11
|
|
86
|
-
|
|
87
|
-
### Patch Changes
|
|
88
|
-
|
|
89
|
-
- Updated dependencies [db6ce39]
|
|
90
|
-
- Updated dependencies [20bb01b]
|
|
91
|
-
- @sproutsocial/seeds-react-theme@3.5.0
|
|
92
|
-
- @sproutsocial/seeds-react-box@1.1.12
|
|
93
|
-
|
|
94
|
-
## 1.1.10
|
|
95
|
-
|
|
96
|
-
### Patch Changes
|
|
97
|
-
|
|
98
|
-
- Updated dependencies [7716e16]
|
|
99
|
-
- @sproutsocial/seeds-react-theme@3.4.0
|
|
100
|
-
- @sproutsocial/seeds-react-box@1.1.11
|
|
101
|
-
|
|
102
|
-
## 1.1.9
|
|
103
|
-
|
|
104
|
-
### Patch Changes
|
|
105
|
-
|
|
106
|
-
- @sproutsocial/seeds-react-theme@3.3.2
|
|
107
|
-
- @sproutsocial/seeds-react-box@1.1.10
|
|
108
|
-
|
|
109
|
-
## 1.1.8
|
|
110
|
-
|
|
111
|
-
### Patch Changes
|
|
112
|
-
|
|
113
|
-
- @sproutsocial/seeds-react-theme@3.3.1
|
|
114
|
-
- @sproutsocial/seeds-react-box@1.1.9
|
|
115
|
-
|
|
116
|
-
## 1.1.7
|
|
117
|
-
|
|
118
|
-
### Patch Changes
|
|
119
|
-
|
|
120
|
-
- Updated dependencies [750d1ea]
|
|
121
|
-
- @sproutsocial/seeds-react-theme@3.3.0
|
|
122
|
-
- @sproutsocial/seeds-react-box@1.1.8
|
|
123
|
-
|
|
124
|
-
## 1.1.6
|
|
125
|
-
|
|
126
|
-
### Patch Changes
|
|
127
|
-
|
|
128
|
-
- Updated dependencies [fa7579a]
|
|
129
|
-
- @sproutsocial/seeds-react-theme@3.2.1
|
|
130
|
-
- @sproutsocial/seeds-react-box@1.1.7
|
|
131
|
-
|
|
132
|
-
## 1.1.5
|
|
133
|
-
|
|
134
|
-
### Patch Changes
|
|
135
|
-
|
|
136
|
-
- Updated dependencies [8f6ba8d]
|
|
137
|
-
- @sproutsocial/seeds-react-theme@3.2.0
|
|
138
|
-
- @sproutsocial/seeds-react-box@1.1.6
|
|
139
|
-
|
|
140
|
-
## 1.1.4
|
|
141
|
-
|
|
142
|
-
### Patch Changes
|
|
143
|
-
|
|
144
|
-
- Updated dependencies [b1c3b44]
|
|
145
|
-
- @sproutsocial/seeds-react-theme@3.1.1
|
|
146
|
-
- @sproutsocial/seeds-react-box@1.1.5
|
|
147
|
-
|
|
148
|
-
## 1.1.3
|
|
149
|
-
|
|
150
|
-
### Patch Changes
|
|
151
|
-
|
|
152
|
-
- Updated dependencies [47580c4]
|
|
153
|
-
- @sproutsocial/seeds-react-theme@3.1.0
|
|
154
|
-
- @sproutsocial/seeds-react-box@1.1.4
|
|
155
|
-
|
|
156
|
-
## 1.1.2
|
|
157
|
-
|
|
158
|
-
### Patch Changes
|
|
159
|
-
|
|
160
|
-
- Updated dependencies [22e1111]
|
|
161
|
-
- @sproutsocial/seeds-react-theme@3.0.1
|
|
162
|
-
- @sproutsocial/seeds-react-box@1.1.3
|
|
163
|
-
|
|
164
|
-
## 1.1.1
|
|
165
|
-
|
|
166
|
-
### Patch Changes
|
|
167
|
-
|
|
168
|
-
- 9fd8bac: Update dependencies to use semantic package version instead of wildcards
|
|
169
|
-
- Updated dependencies [9fd8bac]
|
|
170
|
-
- @sproutsocial/seeds-react-system-props@3.0.2
|
|
171
|
-
- @sproutsocial/seeds-react-theme@2.2.1
|
|
172
|
-
- @sproutsocial/seeds-react-box@1.1.2
|
|
173
|
-
|
|
174
|
-
## 1.1.0
|
|
175
|
-
|
|
176
|
-
### Minor Changes
|
|
177
|
-
|
|
178
|
-
- 55e2d47: Skeleton now exports a functional component so `react-docgen` can generate the appropriate docs
|
|
179
|
-
|
|
180
|
-
## 1.0.0
|
|
181
|
-
|
|
182
|
-
### Major Changes
|
|
183
|
-
|
|
184
|
-
- bd8d03d: Migrate Skeleton to its own seeds-react-skeleton component
|
package/jest.config.js
DELETED
package/src/Skeleton.stories.tsx
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
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
|
-
};
|
package/src/Skeleton.tsx
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import styled from "styled-components";
|
|
2
|
-
import Box from "@sproutsocial/seeds-react-box";
|
|
3
|
-
import type { SkeletonProps } from "./SkeletonTypes";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
*
|
|
7
|
-
* @param borderRadius
|
|
8
|
-
* @returns classname string for handling appropriate loader style depending on passed in properties
|
|
9
|
-
*/
|
|
10
|
-
// @ts-ignore TODO: fix noImplicitAny error here. IDK why there are no types for this component
|
|
11
|
-
const SkeletonAttrs = ({ borderRadius, height, width }) => ({
|
|
12
|
-
className:
|
|
13
|
-
borderRadius === "pill" && height === width ? "circular" : "linear",
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
const Skeleton = styled(Box).attrs(SkeletonAttrs)`
|
|
17
|
-
position: relative;
|
|
18
|
-
background: ${(props) =>
|
|
19
|
-
props.theme.colors.container.background.decorative.neutral};
|
|
20
|
-
overflow: hidden;
|
|
21
|
-
&.circular {
|
|
22
|
-
&:before {
|
|
23
|
-
position: absolute;
|
|
24
|
-
top: -25%;
|
|
25
|
-
left: -25%;
|
|
26
|
-
content: '';
|
|
27
|
-
background-image: ${(props) => `conic-gradient(
|
|
28
|
-
${props.theme.colors.container.background.decorative.neutral} 270deg,
|
|
29
|
-
${props.theme.colors.container.border.decorative.neutral} 300deg
|
|
30
|
-
);`};
|
|
31
|
-
height: 150%;
|
|
32
|
-
width: 150%;
|
|
33
|
-
animation: SkeletonRotate 2s infinite linear;
|
|
34
|
-
}
|
|
35
|
-
&:after {
|
|
36
|
-
position: absolute;
|
|
37
|
-
top: 50%;
|
|
38
|
-
left: 50%;
|
|
39
|
-
transform: translate(-50%, -50%);
|
|
40
|
-
content: '';
|
|
41
|
-
height: calc(100% - 8px);
|
|
42
|
-
width: calc(100% - 8px);
|
|
43
|
-
background: ${(p) => p.theme.colors.app.background.base};
|
|
44
|
-
border-radius: 50%;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
&.linear {
|
|
48
|
-
position: relative;
|
|
49
|
-
background-image: ${(props) => `linear-gradient(
|
|
50
|
-
288deg,
|
|
51
|
-
${props.theme.colors.container.background.decorative.neutral} 32%,
|
|
52
|
-
${props.theme.colors.container.border.decorative.neutral},
|
|
53
|
-
${props.theme.colors.container.background.decorative.neutral} 68%
|
|
54
|
-
);`}
|
|
55
|
-
background-size: 400%;
|
|
56
|
-
background-repeat: no-repeat;
|
|
57
|
-
animation: SkeletonShimmer 2s linear infinite reverse;
|
|
58
|
-
overflow: hidden;
|
|
59
|
-
&:after {
|
|
60
|
-
position: absolute;
|
|
61
|
-
bottom: 0;
|
|
62
|
-
content: "";
|
|
63
|
-
height: calc(100% - 4px);
|
|
64
|
-
width: 100%;
|
|
65
|
-
background: ${(props) =>
|
|
66
|
-
props.theme.colors.container.background.decorative.neutral};
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
@media (prefers-reduced-motion) {
|
|
72
|
-
&.linear,
|
|
73
|
-
&.circular::before {
|
|
74
|
-
animation: none;
|
|
75
|
-
}
|
|
76
|
-
&:before,
|
|
77
|
-
&:after {
|
|
78
|
-
display: none;
|
|
79
|
-
}
|
|
80
|
-
&.linear,
|
|
81
|
-
&.circular {
|
|
82
|
-
border: 1px solid ${(props) =>
|
|
83
|
-
props.theme.colors.container.border.decorative.neutral};
|
|
84
|
-
animation: SkeletonPulse 2s linear infinite alternate;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
@keyframes SkeletonRotate {
|
|
89
|
-
100% {
|
|
90
|
-
transform: rotate(360deg);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
@keyframes SkeletonRotateFade {
|
|
94
|
-
50% {
|
|
95
|
-
transform: rotate(360deg);
|
|
96
|
-
}
|
|
97
|
-
90% {
|
|
98
|
-
opacity: 1;
|
|
99
|
-
}
|
|
100
|
-
100% {
|
|
101
|
-
transform: rotate(720deg);
|
|
102
|
-
opacity: 0;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
@keyframes SkeletonShimmer {
|
|
107
|
-
0% {
|
|
108
|
-
background-position: 0% 0;
|
|
109
|
-
}
|
|
110
|
-
100% {
|
|
111
|
-
background-position: 100% 0;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
@keyframes SkeletonPulse {
|
|
115
|
-
0% {
|
|
116
|
-
border-color: ${(props) =>
|
|
117
|
-
props.theme.colors.container.border.decorative.neutral}FF;
|
|
118
|
-
}
|
|
119
|
-
100% {
|
|
120
|
-
border-color: ${(props) =>
|
|
121
|
-
props.theme.colors.container.border.decorative.neutral}1A;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
`;
|
|
125
|
-
|
|
126
|
-
// @TODO: Refine types that are passed to SkeletonComponent
|
|
127
|
-
export const SkeletonComponent = ({
|
|
128
|
-
borderRadius,
|
|
129
|
-
height,
|
|
130
|
-
width,
|
|
131
|
-
...props
|
|
132
|
-
}: SkeletonProps) => {
|
|
133
|
-
return (
|
|
134
|
-
<Skeleton
|
|
135
|
-
borderRadius={borderRadius}
|
|
136
|
-
height={height}
|
|
137
|
-
width={width}
|
|
138
|
-
{...props}
|
|
139
|
-
/>
|
|
140
|
-
);
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
export default Skeleton;
|
package/src/SkeletonTypes.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
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
|
-
});
|
|
@@ -1,13 +0,0 @@
|
|
|
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
DELETED
package/src/styled.d.ts
DELETED
package/tsconfig.json
DELETED
package/tsup.config.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
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
|
-
}));
|