@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 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
- import { jsx } from "react/jsx-runtime";
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 === "pill" && height === width ? "circular" : "linear"
35
+ className: getSkeletonVariant({ borderRadius, height, width })
7
36
  });
8
- var Skeleton = styled(Box).attrs(SkeletonAttrs)`
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
@@ -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":"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","names":["React","React","jsx","React","jsx","React"]}
package/dist/index.d.mts CHANGED
@@ -1,13 +1,14 @@
1
- import * as styled_components from 'styled-components';
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
- declare const Skeleton: styled_components.StyledComponent<react.ForwardRefExoticComponent<Omit<_sproutsocial_seeds_react_box.TypeBoxProps, "ref"> & react.RefAttributes<HTMLDivElement>>, styled_components.DefaultTheme, {
10
- className: string;
11
- }, "className">;
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 * as styled_components from 'styled-components';
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
- declare const Skeleton: styled_components.StyledComponent<react.ForwardRefExoticComponent<Omit<_sproutsocial_seeds_react_box.TypeBoxProps, "ref"> & react.RefAttributes<HTMLDivElement>>, styled_components.DefaultTheme, {
10
- className: string;
11
- }, "className">;
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
- var import_jsx_runtime = require("react/jsx-runtime");
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 === "pill" && height === width ? "circular" : "linear"
72
+ className: getSkeletonVariant({ borderRadius, height, width })
44
73
  });
45
- var Skeleton = (0, import_styled_components.default)(import_seeds_react_box.default).attrs(SkeletonAttrs)`
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.21",
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.1.1",
22
- "@sproutsocial/seeds-react-system-props": "^3.1.1",
23
- "@sproutsocial/seeds-react-box": "^1.1.22"
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
@@ -1,6 +0,0 @@
1
- # Node modules
2
- node_modules/
3
-
4
- # Build output
5
- dist/
6
- coverage/
package/.eslintrc.js DELETED
@@ -1,4 +0,0 @@
1
- module.exports = {
2
- root: true,
3
- extends: ["eslint-config-seeds/racine"],
4
- };
@@ -1,21 +0,0 @@
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.5.0
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.73 KB
12
- CJS dist/index.js.map 5.14 KB
13
- CJS ⚡️ Build success in 14ms
14
- ESM dist/esm/index.js 3.03 KB
15
- ESM dist/esm/index.js.map 5.07 KB
16
- ESM ⚡️ Build success in 14ms
17
- DTS Build start
18
- DTS ⚡️ Build success in 6423ms
19
- DTS dist/index.d.ts 604.00 B
20
- DTS dist/index.d.mts 604.00 B
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
@@ -1,9 +0,0 @@
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;
@@ -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;
@@ -1,3 +0,0 @@
1
- import type { TypeBoxProps } from "@sproutsocial/seeds-react-box";
2
-
3
- export interface SkeletonProps extends TypeBoxProps {}
@@ -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
@@ -1,5 +0,0 @@
1
- import Skeleton from "./Skeleton";
2
-
3
- export default Skeleton;
4
- export * from "./SkeletonTypes";
5
- export { Skeleton };
package/src/styled.d.ts DELETED
@@ -1,7 +0,0 @@
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 DELETED
@@ -1,9 +0,0 @@
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 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
- }));