1 | 'use client';
|
2 | import React from 'react';
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | const SkeletonThemeContext = React.createContext({});
|
8 |
|
9 |
|
10 | const defaultEnableAnimation = true;
|
11 |
|
12 | function styleOptionsToCssProperties({ baseColor, highlightColor, width, height, borderRadius, circle, direction, duration, enableAnimation = defaultEnableAnimation, customHighlightBackground, }) {
|
13 | const style = {};
|
14 | if (direction === 'rtl')
|
15 | style['--animation-direction'] = 'reverse';
|
16 | if (typeof duration === 'number')
|
17 | style['--animation-duration'] = `${duration}s`;
|
18 | if (!enableAnimation)
|
19 | style['--pseudo-element-display'] = 'none';
|
20 | if (typeof width === 'string' || typeof width === 'number')
|
21 | style.width = width;
|
22 | if (typeof height === 'string' || typeof height === 'number')
|
23 | style.height = height;
|
24 | if (typeof borderRadius === 'string' || typeof borderRadius === 'number')
|
25 | style.borderRadius = borderRadius;
|
26 | if (circle)
|
27 | style.borderRadius = '50%';
|
28 | if (typeof baseColor !== 'undefined')
|
29 | style['--base-color'] = baseColor;
|
30 | if (typeof highlightColor !== 'undefined')
|
31 | style['--highlight-color'] = highlightColor;
|
32 | if (typeof customHighlightBackground === 'string')
|
33 | style['--custom-highlight-background'] = customHighlightBackground;
|
34 | return style;
|
35 | }
|
36 | function Skeleton({ count = 1, wrapper: Wrapper, className: customClassName, containerClassName, containerTestId, circle = false, style: styleProp, ...originalPropsStyleOptions }) {
|
37 | var _a, _b, _c;
|
38 | const contextStyleOptions = React.useContext(SkeletonThemeContext);
|
39 | const propsStyleOptions = { ...originalPropsStyleOptions };
|
40 |
|
41 |
|
42 | for (const [key, value] of Object.entries(originalPropsStyleOptions)) {
|
43 | if (typeof value === 'undefined') {
|
44 | delete propsStyleOptions[key];
|
45 | }
|
46 | }
|
47 |
|
48 | const styleOptions = {
|
49 | ...contextStyleOptions,
|
50 | ...propsStyleOptions,
|
51 | circle,
|
52 | };
|
53 |
|
54 | const style = {
|
55 | ...styleProp,
|
56 | ...styleOptionsToCssProperties(styleOptions),
|
57 | };
|
58 | let className = 'react-loading-skeleton';
|
59 | if (customClassName)
|
60 | className += ` ${customClassName}`;
|
61 | const inline = (_a = styleOptions.inline) !== null && _a !== void 0 ? _a : false;
|
62 | const elements = [];
|
63 | const countCeil = Math.ceil(count);
|
64 | for (let i = 0; i < countCeil; i++) {
|
65 | let thisStyle = style;
|
66 | if (countCeil > count && i === countCeil - 1) {
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 | const width = (_b = thisStyle.width) !== null && _b !== void 0 ? _b : '100%';
|
74 | const fractionalPart = count % 1;
|
75 | const fractionalWidth = typeof width === 'number'
|
76 | ? width * fractionalPart
|
77 | : `calc(${width} * ${fractionalPart})`;
|
78 | thisStyle = { ...thisStyle, width: fractionalWidth };
|
79 | }
|
80 | const skeletonSpan = (React.createElement("span", { className: className, style: thisStyle, key: i }, "\u200C"));
|
81 | if (inline) {
|
82 | elements.push(skeletonSpan);
|
83 | }
|
84 | else {
|
85 |
|
86 |
|
87 | elements.push(React.createElement(React.Fragment, { key: i },
|
88 | skeletonSpan,
|
89 | React.createElement("br", null)));
|
90 | }
|
91 | }
|
92 | return (React.createElement("span", { className: containerClassName, "data-testid": containerTestId, "aria-live": "polite", "aria-busy": (_c = styleOptions.enableAnimation) !== null && _c !== void 0 ? _c : defaultEnableAnimation }, Wrapper
|
93 | ? elements.map((el, i) => React.createElement(Wrapper, { key: i }, el))
|
94 | : elements));
|
95 | }
|
96 |
|
97 | function SkeletonTheme({ children, ...styleOptions }) {
|
98 | return (React.createElement(SkeletonThemeContext.Provider, { value: styleOptions }, children));
|
99 | }
|
100 |
|
101 | export { SkeletonTheme, Skeleton as default };
|