skeleton-ghost-loader 2.6.8 → 2.6.9

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.
@@ -2,20 +2,19 @@ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
2
  import React from "react";
3
3
  const skeletonBgColors = {
4
4
  text: "#ccc",
5
- // lighter for text
6
5
  box: "#e0e0e0"
7
- // darker for boxes/buttons
8
6
  };
9
7
  const styleCache = {};
10
8
  function getComputedStyleFromNode(node) {
9
+ var _a, _b, _c, _d, _e;
11
10
  if (typeof document === "undefined") return {};
12
11
  const type = typeof node.type === "string" ? node.type : "div";
13
- const key = `${type}-${node.props.id || ""}-${node.props.className || ""}`;
12
+ const key = `${type}-${((_a = node.props) == null ? void 0 : _a.id) || ""}-${((_b = node.props) == null ? void 0 : _b.className) || ""}`;
14
13
  if (styleCache[key]) return styleCache[key];
15
14
  const el = document.createElement(type);
16
- if (node.props.id) el.id = node.props.id;
17
- if (node.props.className) el.className = node.props.className;
18
- if (node.props.style) {
15
+ if ((_c = node.props) == null ? void 0 : _c.id) el.id = node.props.id;
16
+ if ((_d = node.props) == null ? void 0 : _d.className) el.className = node.props.className;
17
+ if ((_e = node.props) == null ? void 0 : _e.style) {
19
18
  Object.entries(node.props.style).forEach(([k, v]) => {
20
19
  el.style[k] = v;
21
20
  });
@@ -24,46 +23,74 @@ function getComputedStyleFromNode(node) {
24
23
  document.body.appendChild(el);
25
24
  const cs = window.getComputedStyle(el);
26
25
  const computed = {
27
- height: cs.height || void 0,
28
- width: cs.width || "100%",
29
- fontSize: cs.fontSize || void 0,
30
- margin: cs.margin || "0",
31
- padding: cs.padding || "0",
32
- borderRadius: cs.borderRadius || "4px"
26
+ height: cs.height,
27
+ width: cs.width,
28
+ fontSize: cs.fontSize,
29
+ margin: cs.margin,
30
+ padding: cs.padding,
31
+ borderRadius: cs.borderRadius
33
32
  };
34
33
  document.body.removeChild(el);
35
34
  styleCache[key] = computed;
36
35
  return computed;
37
36
  }
37
+ const TEXT_TAGS = ["p", "span", "h1", "h2", "h3", "h4", "h5", "h6"];
38
+ const TEXT_HEIGHT_MAP = {
39
+ h1: "2.4em",
40
+ h2: "2em",
41
+ h3: "1.75em",
42
+ h4: "1.5em",
43
+ h5: "1.3em",
44
+ h6: "1.15em",
45
+ p: "1em",
46
+ span: "0.9em"
47
+ };
38
48
  const SkeletonBlock = ({ children }) => {
39
49
  function traverse(node) {
40
50
  if (!React.isValidElement(node)) return node;
41
51
  let newProps = { ...node.props };
42
52
  let style = { ...newProps.style };
43
- if (newProps.skeletonrequired === "y" && typeof node.type === "string") {
53
+ const type = typeof node.type === "string" ? node.type : null;
54
+ const isText = type && TEXT_TAGS.includes(type);
55
+ if (newProps.skeletonrequired === "y" && type) {
44
56
  const defaults = getComputedStyleFromNode(node);
45
- style.height = style.height || newProps.height || defaults.height || "20px";
46
- style.width = style.width || newProps.width || defaults.width || "100%";
47
- style.fontSize = style.fontSize || newProps.fontSize || defaults.fontSize || "16px";
48
- style.margin = style.margin || newProps.margin || defaults.margin || "0";
49
- style.padding = style.padding || newProps.padding || defaults.padding || "0";
57
+ style.width = style.width || defaults.width || "100%";
58
+ style.fontSize = style.fontSize || defaults.fontSize || "16px";
59
+ style.margin = style.margin || defaults.margin || "0";
60
+ style.padding = style.padding || defaults.padding || "0";
50
61
  style.borderRadius = style.borderRadius || defaults.borderRadius || "4px";
51
- const isText = ["p", "span", "h1", "h2", "h3", "h4", "h5", "h6"].includes(node.type);
52
- style.backgroundColor = isText ? skeletonBgColors.text : skeletonBgColors.box;
62
+ if (isText) {
63
+ const computedHeight = parseFloat(defaults.height || "0");
64
+ style.height = computedHeight > 0 ? defaults.height : TEXT_HEIGHT_MAP[type] || "1em";
65
+ style.minHeight = TEXT_HEIGHT_MAP[type] || "1em";
66
+ } else {
67
+ style.height = style.height || defaults.height || "20px";
68
+ }
69
+ const base = isText ? skeletonBgColors.text : skeletonBgColors.box;
70
+ style.backgroundColor = base;
53
71
  style.color = "transparent";
54
72
  style.position = "relative";
55
73
  style.overflow = "hidden";
56
- const shimmerBase = isText ? skeletonBgColors.text : skeletonBgColors.box;
57
- style.backgroundImage = `linear-gradient(90deg, ${shimmerBase} 0%, #f5f5f5 50%, ${shimmerBase} 100%)`;
74
+ style.backgroundImage = `linear-gradient(
75
+ 90deg,
76
+ ${base} 0%,
77
+ #f5f5f5 50%,
78
+ ${base} 100%
79
+ )`;
58
80
  style.backgroundSize = "200% 100%";
59
- style.animation = "shimmer 1.5s infinite";
81
+ style.animation = "shimmer 1.5s infinite linear";
60
82
  delete newProps.skeletonrequired;
61
83
  newProps.style = style;
62
84
  }
63
- const childrenNodes = React.Children.map(node.props.children, traverse);
85
+ if (typeof node.type === "function") {
86
+ return traverse(node.type(newProps));
87
+ }
88
+ const childrenNodes = React.Children.map(
89
+ node.props.children,
90
+ traverse
91
+ );
64
92
  return React.cloneElement(node, newProps, childrenNodes);
65
93
  }
66
- const result = React.Children.map(children, traverse);
67
94
  return /* @__PURE__ */ jsxs(Fragment, { children: [
68
95
  /* @__PURE__ */ jsx("style", { children: `
69
96
  @keyframes shimmer {
@@ -71,7 +98,7 @@ const SkeletonBlock = ({ children }) => {
71
98
  100% { background-position: 200% 0; }
72
99
  }
73
100
  ` }),
74
- result
101
+ React.Children.map(children, traverse)
75
102
  ] });
76
103
  };
77
104
  export {
@@ -4,20 +4,19 @@
4
4
  "use strict";
5
5
  const skeletonBgColors = {
6
6
  text: "#ccc",
7
- // lighter for text
8
7
  box: "#e0e0e0"
9
- // darker for boxes/buttons
10
8
  };
11
9
  const styleCache = {};
12
10
  function getComputedStyleFromNode(node) {
11
+ var _a, _b, _c, _d, _e;
13
12
  if (typeof document === "undefined") return {};
14
13
  const type = typeof node.type === "string" ? node.type : "div";
15
- const key = `${type}-${node.props.id || ""}-${node.props.className || ""}`;
14
+ const key = `${type}-${((_a = node.props) == null ? void 0 : _a.id) || ""}-${((_b = node.props) == null ? void 0 : _b.className) || ""}`;
16
15
  if (styleCache[key]) return styleCache[key];
17
16
  const el = document.createElement(type);
18
- if (node.props.id) el.id = node.props.id;
19
- if (node.props.className) el.className = node.props.className;
20
- if (node.props.style) {
17
+ if ((_c = node.props) == null ? void 0 : _c.id) el.id = node.props.id;
18
+ if ((_d = node.props) == null ? void 0 : _d.className) el.className = node.props.className;
19
+ if ((_e = node.props) == null ? void 0 : _e.style) {
21
20
  Object.entries(node.props.style).forEach(([k, v]) => {
22
21
  el.style[k] = v;
23
22
  });
@@ -26,46 +25,74 @@
26
25
  document.body.appendChild(el);
27
26
  const cs = window.getComputedStyle(el);
28
27
  const computed = {
29
- height: cs.height || void 0,
30
- width: cs.width || "100%",
31
- fontSize: cs.fontSize || void 0,
32
- margin: cs.margin || "0",
33
- padding: cs.padding || "0",
34
- borderRadius: cs.borderRadius || "4px"
28
+ height: cs.height,
29
+ width: cs.width,
30
+ fontSize: cs.fontSize,
31
+ margin: cs.margin,
32
+ padding: cs.padding,
33
+ borderRadius: cs.borderRadius
35
34
  };
36
35
  document.body.removeChild(el);
37
36
  styleCache[key] = computed;
38
37
  return computed;
39
38
  }
39
+ const TEXT_TAGS = ["p", "span", "h1", "h2", "h3", "h4", "h5", "h6"];
40
+ const TEXT_HEIGHT_MAP = {
41
+ h1: "2.4em",
42
+ h2: "2em",
43
+ h3: "1.75em",
44
+ h4: "1.5em",
45
+ h5: "1.3em",
46
+ h6: "1.15em",
47
+ p: "1em",
48
+ span: "0.9em"
49
+ };
40
50
  const SkeletonBlock = ({ children }) => {
41
51
  function traverse(node) {
42
52
  if (!React.isValidElement(node)) return node;
43
53
  let newProps = { ...node.props };
44
54
  let style = { ...newProps.style };
45
- if (newProps.skeletonrequired === "y" && typeof node.type === "string") {
55
+ const type = typeof node.type === "string" ? node.type : null;
56
+ const isText = type && TEXT_TAGS.includes(type);
57
+ if (newProps.skeletonrequired === "y" && type) {
46
58
  const defaults = getComputedStyleFromNode(node);
47
- style.height = style.height || newProps.height || defaults.height || "20px";
48
- style.width = style.width || newProps.width || defaults.width || "100%";
49
- style.fontSize = style.fontSize || newProps.fontSize || defaults.fontSize || "16px";
50
- style.margin = style.margin || newProps.margin || defaults.margin || "0";
51
- style.padding = style.padding || newProps.padding || defaults.padding || "0";
59
+ style.width = style.width || defaults.width || "100%";
60
+ style.fontSize = style.fontSize || defaults.fontSize || "16px";
61
+ style.margin = style.margin || defaults.margin || "0";
62
+ style.padding = style.padding || defaults.padding || "0";
52
63
  style.borderRadius = style.borderRadius || defaults.borderRadius || "4px";
53
- const isText = ["p", "span", "h1", "h2", "h3", "h4", "h5", "h6"].includes(node.type);
54
- style.backgroundColor = isText ? skeletonBgColors.text : skeletonBgColors.box;
64
+ if (isText) {
65
+ const computedHeight = parseFloat(defaults.height || "0");
66
+ style.height = computedHeight > 0 ? defaults.height : TEXT_HEIGHT_MAP[type] || "1em";
67
+ style.minHeight = TEXT_HEIGHT_MAP[type] || "1em";
68
+ } else {
69
+ style.height = style.height || defaults.height || "20px";
70
+ }
71
+ const base = isText ? skeletonBgColors.text : skeletonBgColors.box;
72
+ style.backgroundColor = base;
55
73
  style.color = "transparent";
56
74
  style.position = "relative";
57
75
  style.overflow = "hidden";
58
- const shimmerBase = isText ? skeletonBgColors.text : skeletonBgColors.box;
59
- style.backgroundImage = `linear-gradient(90deg, ${shimmerBase} 0%, #f5f5f5 50%, ${shimmerBase} 100%)`;
76
+ style.backgroundImage = `linear-gradient(
77
+ 90deg,
78
+ ${base} 0%,
79
+ #f5f5f5 50%,
80
+ ${base} 100%
81
+ )`;
60
82
  style.backgroundSize = "200% 100%";
61
- style.animation = "shimmer 1.5s infinite";
83
+ style.animation = "shimmer 1.5s infinite linear";
62
84
  delete newProps.skeletonrequired;
63
85
  newProps.style = style;
64
86
  }
65
- const childrenNodes = React.Children.map(node.props.children, traverse);
87
+ if (typeof node.type === "function") {
88
+ return traverse(node.type(newProps));
89
+ }
90
+ const childrenNodes = React.Children.map(
91
+ node.props.children,
92
+ traverse
93
+ );
66
94
  return React.cloneElement(node, newProps, childrenNodes);
67
95
  }
68
- const result = React.Children.map(children, traverse);
69
96
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
70
97
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
71
98
  @keyframes shimmer {
@@ -73,7 +100,7 @@
73
100
  100% { background-position: 200% 0; }
74
101
  }
75
102
  ` }),
76
- result
103
+ React.Children.map(children, traverse)
77
104
  ] });
78
105
  };
79
106
  exports2.SkeletonBlock = SkeletonBlock;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skeleton-ghost-loader",
3
- "version": "2.6.8",
3
+ "version": "2.6.9",
4
4
  "description": "Smart skeleton loader that auto-detects styles (inline, class, Tailwind, browser defaults)",
5
5
  "author": "Shubh Patil",
6
6
  "license": "MIT",