UNPKG

8.12 kBJavaScriptView Raw
1'use client';
2
3import * as React from 'react';
4import clsx from 'clsx';
5import PropTypes from 'prop-types';
6import composeClasses from '@mui/utils/composeClasses';
7import { alpha, unstable_getUnit as getUnit, unstable_toUnitless as toUnitless } from "../styles/index.js";
8import { keyframes, css, styled } from "../zero-styled/index.js";
9import memoTheme from "../utils/memoTheme.js";
10import { useDefaultProps } from "../DefaultPropsProvider/index.js";
11import { getSkeletonUtilityClass } from "./skeletonClasses.js";
12import { jsx as _jsx } from "react/jsx-runtime";
13const useUtilityClasses = ownerState => {
14 const {
15 classes,
16 variant,
17 animation,
18 hasChildren,
19 width,
20 height
21 } = ownerState;
22 const slots = {
23 root: ['root', variant, animation, hasChildren && 'withChildren', hasChildren && !width && 'fitContent', hasChildren && !height && 'heightAuto']
24 };
25 return composeClasses(slots, getSkeletonUtilityClass, classes);
26};
27const pulseKeyframe = keyframes`
28 0% {
29 opacity: 1;
30 }
31
32 50% {
33 opacity: 0.4;
34 }
35
36 100% {
37 opacity: 1;
38 }
39`;
40const waveKeyframe = keyframes`
41 0% {
42 transform: translateX(-100%);
43 }
44
45 50% {
46 /* +0.5s of delay between each loop */
47 transform: translateX(100%);
48 }
49
50 100% {
51 transform: translateX(100%);
52 }
53`;
54
55// This implementation is for supporting both Styled-components v4+ and Pigment CSS.
56// A global animation has to be created here for Styled-components v4+ (https://github.com/styled-components/styled-components/blob/main/packages/styled-components/src/utils/errors.md#12).
57// which can be done by checking typeof indeterminate1Keyframe !== 'string' (at runtime, Pigment CSS transform keyframes`` to a string).
58const pulseAnimation = typeof pulseKeyframe !== 'string' ? css`
59 animation: ${pulseKeyframe} 2s ease-in-out 0.5s infinite;
60 ` : null;
61const waveAnimation = typeof waveKeyframe !== 'string' ? css`
62 &::after {
63 animation: ${waveKeyframe} 2s linear 0.5s infinite;
64 }
65 ` : null;
66const SkeletonRoot = styled('span', {
67 name: 'MuiSkeleton',
68 slot: 'Root',
69 overridesResolver: (props, styles) => {
70 const {
71 ownerState
72 } = props;
73 return [styles.root, styles[ownerState.variant], ownerState.animation !== false && styles[ownerState.animation], ownerState.hasChildren && styles.withChildren, ownerState.hasChildren && !ownerState.width && styles.fitContent, ownerState.hasChildren && !ownerState.height && styles.heightAuto];
74 }
75})(memoTheme(({
76 theme
77}) => {
78 const radiusUnit = getUnit(theme.shape.borderRadius) || 'px';
79 const radiusValue = toUnitless(theme.shape.borderRadius);
80 return {
81 display: 'block',
82 // Create a "on paper" color with sufficient contrast retaining the color
83 backgroundColor: theme.vars ? theme.vars.palette.Skeleton.bg : alpha(theme.palette.text.primary, theme.palette.mode === 'light' ? 0.11 : 0.13),
84 height: '1.2em',
85 variants: [{
86 props: {
87 variant: 'text'
88 },
89 style: {
90 marginTop: 0,
91 marginBottom: 0,
92 height: 'auto',
93 transformOrigin: '0 55%',
94 transform: 'scale(1, 0.60)',
95 borderRadius: `${radiusValue}${radiusUnit}/${Math.round(radiusValue / 0.6 * 10) / 10}${radiusUnit}`,
96 '&:empty:before': {
97 content: '"\\00a0"'
98 }
99 }
100 }, {
101 props: {
102 variant: 'circular'
103 },
104 style: {
105 borderRadius: '50%'
106 }
107 }, {
108 props: {
109 variant: 'rounded'
110 },
111 style: {
112 borderRadius: (theme.vars || theme).shape.borderRadius
113 }
114 }, {
115 props: ({
116 ownerState
117 }) => ownerState.hasChildren,
118 style: {
119 '& > *': {
120 visibility: 'hidden'
121 }
122 }
123 }, {
124 props: ({
125 ownerState
126 }) => ownerState.hasChildren && !ownerState.width,
127 style: {
128 maxWidth: 'fit-content'
129 }
130 }, {
131 props: ({
132 ownerState
133 }) => ownerState.hasChildren && !ownerState.height,
134 style: {
135 height: 'auto'
136 }
137 }, {
138 props: {
139 animation: 'pulse'
140 },
141 style: pulseAnimation || {
142 animation: `${pulseKeyframe} 2s ease-in-out 0.5s infinite`
143 }
144 }, {
145 props: {
146 animation: 'wave'
147 },
148 style: {
149 position: 'relative',
150 overflow: 'hidden',
151 /* Fix bug in Safari https://bugs.webkit.org/show_bug.cgi?id=68196 */
152 WebkitMaskImage: '-webkit-radial-gradient(white, black)',
153 '&::after': {
154 background: `linear-gradient(
155 90deg,
156 transparent,
157 ${(theme.vars || theme).palette.action.hover},
158 transparent
159 )`,
160 content: '""',
161 position: 'absolute',
162 transform: 'translateX(-100%)' /* Avoid flash during server-side hydration */,
163 bottom: 0,
164 left: 0,
165 right: 0,
166 top: 0
167 }
168 }
169 }, {
170 props: {
171 animation: 'wave'
172 },
173 style: waveAnimation || {
174 '&::after': {
175 animation: `${waveKeyframe} 2s linear 0.5s infinite`
176 }
177 }
178 }]
179 };
180}));
181const Skeleton = /*#__PURE__*/React.forwardRef(function Skeleton(inProps, ref) {
182 const props = useDefaultProps({
183 props: inProps,
184 name: 'MuiSkeleton'
185 });
186 const {
187 animation = 'pulse',
188 className,
189 component = 'span',
190 height,
191 style,
192 variant = 'text',
193 width,
194 ...other
195 } = props;
196 const ownerState = {
197 ...props,
198 animation,
199 component,
200 variant,
201 hasChildren: Boolean(other.children)
202 };
203 const classes = useUtilityClasses(ownerState);
204 return /*#__PURE__*/_jsx(SkeletonRoot, {
205 as: component,
206 ref: ref,
207 className: clsx(classes.root, className),
208 ownerState: ownerState,
209 ...other,
210 style: {
211 width,
212 height,
213 ...style
214 }
215 });
216});
217process.env.NODE_ENV !== "production" ? Skeleton.propTypes /* remove-proptypes */ = {
218 // ┌────────────────────────────── Warning ──────────────────────────────┐
219 // │ These PropTypes are generated from the TypeScript type definitions. │
220 // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
221 // └─────────────────────────────────────────────────────────────────────┘
222 /**
223 * The animation.
224 * If `false` the animation effect is disabled.
225 * @default 'pulse'
226 */
227 animation: PropTypes.oneOf(['pulse', 'wave', false]),
228 /**
229 * Optional children to infer width and height from.
230 */
231 children: PropTypes.node,
232 /**
233 * Override or extend the styles applied to the component.
234 */
235 classes: PropTypes.object,
236 /**
237 * @ignore
238 */
239 className: PropTypes.string,
240 /**
241 * The component used for the root node.
242 * Either a string to use a HTML element or a component.
243 */
244 component: PropTypes.elementType,
245 /**
246 * Height of the skeleton.
247 * Useful when you don't want to adapt the skeleton to a text element but for instance a card.
248 */
249 height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
250 /**
251 * @ignore
252 */
253 style: PropTypes.object,
254 /**
255 * The system prop that allows defining system overrides as well as additional CSS styles.
256 */
257 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
258 /**
259 * The type of content that will be rendered.
260 * @default 'text'
261 */
262 variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.oneOf(['circular', 'rectangular', 'rounded', 'text']), PropTypes.string]),
263 /**
264 * Width of the skeleton.
265 * Useful when the skeleton is inside an inline element with no width of its own.
266 */
267 width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
268} : void 0;
269export default Skeleton;
\No newline at end of file