react-loaded 0.1.1 → 0.1.2

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/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var react=require('react'),jsxRuntime=require('react/jsx-runtime');var C=react.createContext(false);function de(){return react.useContext(C)}function x(){let e=globalThis,t=e.__REACT_LOADED_DEV__;if(typeof t=="boolean")return t;let n=e.__DEV__;if(typeof n=="boolean")return n;let o=globalThis.process,l=typeof o=="object"&&o!==null?o.env?.NODE_ENV:void 0;return typeof l=="string"?l!=="production":false}var fe=typeof globalThis<"u"&&typeof globalThis.document<"u",y=fe?react.useLayoutEffect:react.useEffect;var be=6,ge=40;function X(e){if(!e||typeof e!="object")return false;let t=e;return !(t.nodeType!==1||typeof t.tagName!="string"||typeof t.querySelectorAll!="function"||typeof Element<"u"&&!(e instanceof Element))}var H=new Set;function F(e){if(!X(e))return false;try{return e.querySelectorAll("*"),!0}catch{return false}}function L(e){if(F(e))return e;if(e&&typeof e=="object"&&"nativeElement"in e){let t=e.nativeElement;if(F(t))return t}return null}function Ee(e){let t=e.type;if(typeof t=="string")return `<${t}>`;if(typeof t=="function"){let n=t;return `<${n.displayName||n.name||"Unknown"}>`}if(typeof t=="object"&&t!==null){let n=t;return `<${n.displayName||n.name||"Unknown"}>`}return "<Unknown>"}var J=Number.parseInt(react.version,10),Se=Number.isFinite(J)&&J>=19;function ye(e){let n=e.props?.ref;if(n!==void 0)return n;if(Se)return;let o=e.ref;if(o!==void 0)return o}function he(e,t){e&&(typeof e=="function"?e(t):e.current=t);}var _=new Set(["IMG","VIDEO","CANVAS"]),I=new Set(["SVG"]),we=new Set(["BUTTON","INPUT","TEXTAREA","SELECT","A"]),Re="button,input,textarea,select,a,[role='button']",Te=new Set(["SCRIPT","STYLE","LINK","META","NOSCRIPT","TEMPLATE"]);function O(e){return e.tagName.toUpperCase()}function P(e,t=O(e)){return we.has(t)?true:e.getAttribute("role")==="button"}function Ce(e,t){return !!(e.closest(Re)&&!P(e,t))}function xe(e,t=O(e)){return !!(_.has(t)||I.has(t)||P(e,t)||e.childElementCount===0&&e.textContent?.trim())}function ve(e,t){let n=e.length,o=Math.max(4,.8*n),l=Ne(t)*o,r=n+2+l;return Math.max(be,Math.min(ge,r))}function Ne(e){if(!e)return 0;let t=2166136261;for(let o=0;o<e.length;o+=1)t^=e.charCodeAt(o),t=Math.imul(t,16777619);return (t>>>0)/4294967295*2-1}function Le(e){let t=globalThis.getComputedStyle(e).textAlign;return t==="center"?"center":t==="right"||t==="end"?"right":"left"}function A(e,t={}){let{animate:n=true,seed:o}=t,l=o==null?"loaded":String(o);if(!X(e))return;let r=e;r.classList.add("loaded-skeleton-mode"),n&&r.classList.add("loaded-animate"),r.classList.contains("loaded-skeleton-wrapper")||r.classList.add("loaded-skeleton-bg");let c=e.getElementsByTagName("*"),p=0,d=s=>{let i=O(s);if(Te.has(i)||!xe(s,i)||Ce(s,i))return;let a=s,f=s.textContent?.trim();if(s.childElementCount===0&&f&&!_.has(i)&&!I.has(i)&&!P(s,i)){a.classList.add("loaded-text-skeleton"),a.dataset.skeletonAlign=Le(a);let b=`${l}|${p}|${f??""}`;p+=1;let h=ve(f??"",b);a.style.setProperty("--skeleton-text-width",`${h}ch`);}else _.has(i)?a.classList.add("loaded-skeleton-media"):I.has(i)?(a.classList.add("loaded-skeleton-content"),a.classList.add("loaded-skeleton-svg")):(a.classList.add("loaded-skeleton-content"),a.setAttribute("tabindex","-1"));};d(e);for(let s of c)d(s);}function M({element:e,children:t,loading:n=false,animate:o=true,className:l="",seed:r,suppressRefWarning:E=false}){let c=react.useRef(false),p=react.useRef(false),d=react.useRef(null),s=react.useRef(null),i=react.useRef(false),[a,f]=react.useState(false),u=e.type,b=e.key??null,h=react.useRef(n),V=react.useRef(u),j=react.useRef(b),S=react.useCallback(()=>{s.current!==null&&(clearTimeout(s.current),s.current=null);},[]);react.useEffect(()=>{i.current=a;},[a]),y(()=>{let k=h.current,m=V.current,R=j.current;(k&&!n||(m!==u||R!==b))&&(c.current=false,p.current=false,d.current=null,S(),i.current&&f(false)),h.current=n,V.current=u,j.current=b;},[n,u,b,S]),react.useEffect(()=>()=>{S();},[S]);let U=ye(e),w=react.useCallback(k=>{if(!i.current&&(f(true),!E&&x())){let m=Ee(e);H.has(m)||(console.warn(k==="non-dom-ref"?`[SmartSkeleton] ${m} does not forward its ref to a DOM element. A wrapper <div> has been added automatically. Use forwardRef to avoid this.`:`[SmartSkeleton] ${m} does not accept a ref. A wrapper <div> has been added automatically. Use forwardRef to avoid this.`),H.add(m));}},[e,E]),B=react.useCallback(k=>{p.current=true,d.current=k;let m=L(k);m&&n&&!c.current&&(A(m,{animate:o,seed:r}),c.current=true),he(U,k);},[n,U,o,r]);if(y(()=>{if(!n||a)return;S();let k=d.current,m=L(k);if(m&&!c.current&&(A(m,{animate:o,seed:r}),c.current=true),p.current){k!==null&&!m&&w("non-dom-ref");return}return s.current=setTimeout(()=>{if(s.current=null,!n||i.current)return;let R=d.current,T=L(R);if(T&&!c.current&&(A(T,{animate:o,seed:r}),c.current=true),p.current){R!==null&&!T&&w("non-dom-ref");return}w("no-ref-call");},0),()=>{S();}},[n,a,o,r,w,S]),!n)return t??null;let re=e.props.className??"",$=["loaded-skeleton-mode",o&&"loaded-animate"].filter(Boolean).join(" "),se=[$,"loaded-skeleton-wrapper",l].filter(Boolean).join(" "),ae=[re,$,"loaded-skeleton-bg",l].filter(Boolean).join(" ");return jsxRuntime.jsx(C.Provider,{value:true,children:a?jsxRuntime.jsx("div",{ref:B,className:se,"aria-hidden":"true",children:e}):react.cloneElement(e,{ref:B,className:ae,"aria-hidden":true})})}var z="react-loaded",Ie="loaded",Q=1;function Z(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}function q(e){if(!Z(e))return {};let t={};for(let[n,o]of Object.entries(e))typeof o=="number"&&(t[n]=o);return t}function ee(e){return Z(e)&&e.v===Q?q(e.counts):q(e)}function Oe(e){if(typeof localStorage>"u")return {};try{let t=localStorage.getItem(e);return t===null?{}:ee(JSON.parse(t))}catch{return {}}}function te(e){if(typeof localStorage>"u")return;let t={v:Q,counts:e};try{localStorage.setItem(z,JSON.stringify(t));}catch{}}function ne(){if(typeof localStorage>"u")return {};try{let e=localStorage.getItem(z);if(e!==null)return ee(JSON.parse(e));let t=Oe(Ie);return Object.keys(t).length>0&&te(t),t}catch{return {}}}function Pe(e){let n=ne()[e];return typeof n=="number"?n:null}function Me(e,t){if(!(typeof localStorage>"u"))try{let n=ne();n[e]=t,te(n);}catch{}}function D({storageKey:e,defaultCount:t=3,currentCount:n,loading:o,minCount:l=1,maxCount:r}){let[E,c]=react.useState(()=>W(t,l,r)),p=react.useRef(false);return y(()=>{if(!e)return;let d=Pe(e);if(d===null)return;let s=W(d,l,r);c(i=>Object.is(i,s)?i:s);},[e,l,r]),react.useEffect(()=>{if(!o&&n!==void 0){let d=W(n,l,r);c(d),e&&Me(e,d);}},[o,n,e,l,r]),react.useEffect(()=>{x()&&!e&&!p.current&&(console.warn("[Loaded] SmartSkeletonList used without storageKey. The count will reset on remount. Add a storageKey to persist across sessions."),p.current=true);},[e]),E}function W(e,t,n){let o=Math.max(e,t);return n!==void 0&&(o=Math.min(o,n)),o}function De({loading:e=false,items:t,renderItem:n,renderSkeleton:o,storageKey:l,defaultCount:r=3,minCount:E=1,maxCount:c,animate:p=true,seed:d,suppressRefWarning:s=false,keyExtractor:i=(a,f)=>f}){let a=D({storageKey:l,defaultCount:r,currentCount:t?.length,loading:e,minCount:E,maxCount:c});if(e){let f=new Array(a);for(let u=0;u<a;u+=1){let b=d===void 0?`${u}`:`${d}:${u}`;f[u]=jsxRuntime.jsx(M,{loading:true,element:o(u),animate:p,seed:b,suppressRefWarning:s},`skeleton-${u}`);}return jsxRuntime.jsx(jsxRuntime.Fragment,{children:f})}return !t||t.length===0?null:jsxRuntime.jsx(jsxRuntime.Fragment,{children:t.map((f,u)=>jsxRuntime.jsx(react.Fragment,{children:n(f,u)},i(f,u)))})}exports.SkeletonContext=C;exports.SmartSkeleton=M;exports.SmartSkeletonList=De;exports.useIsSkeletonMode=de;exports.usePersistedCount=D;//# sourceMappingURL=index.cjs.map
1
+ 'use strict';var react=require('react'),jsxRuntime=require('react/jsx-runtime');var w=react.createContext(false);function me(){return react.useContext(w)}function R(){let e=globalThis,t=e.__REACT_LOADED_DEV__;if(typeof t=="boolean")return t;let n=e.__DEV__;if(typeof n=="boolean")return n;let o=globalThis.process,l=typeof o=="object"&&o!==null?o.env?.NODE_ENV:void 0;return typeof l=="string"?l!=="production":false}var be=typeof globalThis<"u"&&typeof globalThis.document<"u",T=be?react.useLayoutEffect:react.useEffect;function X(e){if(!e||typeof e!="object")return false;let t=e;return !(t.nodeType!==1||typeof t.tagName!="string"||typeof t.querySelectorAll!="function"||typeof Element<"u"&&!(e instanceof Element))}function A(e){if(!X(e))return false;try{return e.querySelectorAll("*"),!0}catch{return false}}var N=new Set(["IMG","VIDEO","CANVAS"]),_=new Set(["SVG"]),ge=new Set(["BUTTON","INPUT","TEXTAREA","SELECT","A"]),Ee="button,input,textarea,select,a,[role='button']",Se=new Set(["SCRIPT","STYLE","LINK","META","NOSCRIPT","TEMPLATE"]);function I(e){return e.tagName.toUpperCase()}function O(e,t=I(e)){return ge.has(t)?true:e.getAttribute("role")==="button"}function ye(e,t){return !!(e.closest(Ee)&&!O(e,t))}function he(e,t=I(e)){return !!(N.has(t)||_.has(t)||O(e,t)||e.childElementCount===0&&e.textContent?.trim())}function we(e,t){let n=e.length,o=Math.max(4,.8*n),l=Re(t)*o,s=n+2+l;return Math.max(6,Math.min(40,s))}function Re(e){if(!e)return 0;let t=2166136261;for(let o=0;o<e.length;o+=1)t^=e.charCodeAt(o),t=Math.imul(t,16777619);return (t>>>0)/4294967295*2-1}function Te(e){let t=globalThis.getComputedStyle(e).textAlign;return t==="center"?"center":t==="right"||t==="end"?"right":"left"}function M(e,t={}){let{animate:n=true,seed:o}=t,l=o==null?"loaded":String(o);if(!X(e))return;let s=e;s.classList.add("loaded-skeleton-mode"),n&&s.classList.add("loaded-animate"),s.classList.contains("loaded-skeleton-wrapper")||s.classList.add("loaded-skeleton-bg");let m=e.getElementsByTagName("*"),c=0,d=r=>{let a=I(r);if(Se.has(a)||!he(r,a))return;let i=r;if(ye(r,a)){i.classList.add("loaded-skeleton-force-hide");return}let u=r.textContent?.trim();if(r.childElementCount===0&&u&&!N.has(a)&&!_.has(a)&&!O(r,a)){i.classList.add("loaded-text-skeleton"),i.dataset.skeletonAlign=Te(i);let S=`${l}|${c}|${u??""}`;c+=1;let y=we(u??"",S);i.style.setProperty("--skeleton-text-width",`${y}ch`);}else N.has(a)?i.classList.add("loaded-skeleton-media"):_.has(a)?(i.classList.add("loaded-skeleton-content"),i.classList.add("loaded-skeleton-svg")):(i.classList.add("loaded-skeleton-content"),i.setAttribute("tabindex","-1"));};d(e);for(let r of m)d(r);}var F=Number.parseInt(react.version,10),Ce=Number.isFinite(F)&&F>=19;function P(e){if(A(e))return e;if(e&&typeof e=="object"&&"nativeElement"in e){let t=e.nativeElement;if(A(t))return t}return null}function J(e){let t=e.type;if(typeof t=="string")return `<${t}>`;if(typeof t=="function"){let n=t;return `<${n.displayName||n.name||"Unknown"}>`}if(typeof t=="object"&&t!==null){let n=t;return `<${n.displayName||n.name||"Unknown"}>`}return "<Unknown>"}function K(e){let n=e.props?.ref;if(n!==void 0)return n;if(Ce)return;let o=e.ref;if(o!==void 0)return o}function Y(e,t){e&&(typeof e=="function"?e(t):e.current=t);}var q=new Set;function W({element:e,children:t,loading:n=false,animate:o=true,className:l="",seed:s,suppressRefWarning:b=false}){let m=e.type,c=e.key??null,d=react.useRef(false),r=react.useRef(false),a=react.useRef(null),i=react.useRef(false),[f,u]=react.useState(false),E=react.useRef(n),S=react.useRef(m),y=react.useRef(c),h=react.useCallback(p=>{i.current=p,u(p);},[]),U=K(e),C=react.useCallback(p=>{if(i.current||h(true),!b&&R()){let k=J(e);q.has(k)||(console.warn(p==="non-dom-ref"?`[SmartSkeleton] ${k} does not forward its ref to a DOM element. A wrapper <div> has been added automatically. Use forwardRef to avoid this.`:`[SmartSkeleton] ${k} does not accept a ref. A wrapper <div> has been added automatically. Use forwardRef to avoid this.`),q.add(k));}},[e,b,h]),j=react.useCallback(p=>{r.current=true,a.current=p;let k=P(p);k&&n&&!d.current&&(M(k,{animate:o,seed:s}),d.current=true),Y(U,p);},[n,U,o,s]);if(T(()=>{let p=E.current,k=S.current,ue=y.current,$=p&&!n,G=k!==m||ue!==c;if(E.current=n,S.current=m,y.current=c,($||G)&&(d.current=false,$?(r.current=false,a.current=null):G&&a.current===null&&(r.current=false),i.current)){h(false);return}if(!n||f)return;let v=a.current,L=P(v);if(L&&!d.current&&(M(L,{animate:o,seed:s}),d.current=true),r.current){if(v!==null&&!L){C("non-dom-ref");return}if(v!==null)return;r.current=false;}C("no-ref-call");},[n,f,m,c,o,s,C,h]),!n)return t??null;let ie=e.props.className??"",H=["loaded-skeleton-mode",o&&"loaded-animate"].filter(Boolean).join(" "),le=[H,"loaded-skeleton-wrapper",l].filter(Boolean).join(" "),de=[ie,H,"loaded-skeleton-bg",l].filter(Boolean).join(" ");return jsxRuntime.jsx(w.Provider,{value:true,children:f?jsxRuntime.jsx("div",{ref:j,className:le,"aria-hidden":"true",children:e}):react.cloneElement(e,{ref:j,className:de,"aria-hidden":true})})}var ee="react-loaded",Ae="loaded",te=1;function ne(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}function Z(e){if(!ne(e))return {};let t={};for(let[n,o]of Object.entries(e))typeof o=="number"&&(t[n]=o);return t}function oe(e){return ne(e)&&e.v===te?Z(e.counts):Z(e)}function Ie(e){if(typeof localStorage>"u")return {};try{let t=localStorage.getItem(e);return t===null?{}:oe(JSON.parse(t))}catch{return {}}}function re(e){if(typeof localStorage>"u")return;let t={v:te,counts:e};try{localStorage.setItem(ee,JSON.stringify(t));}catch{}}function se(){if(typeof localStorage>"u")return {};try{let e=localStorage.getItem(ee);if(e!==null)return oe(JSON.parse(e));let t=Ie(Ae);return Object.keys(t).length>0&&re(t),t}catch{return {}}}function Oe(e){let n=se()[e];return typeof n=="number"?n:null}function Me(e,t){if(!(typeof localStorage>"u"))try{let n=se();n[e]=t,re(n);}catch{}}function B({storageKey:e,defaultCount:t=3,currentCount:n,loading:o,minCount:l=1,maxCount:s}){let[b,m]=react.useState(()=>V(t,l,s)),c=react.useRef(false);return T(()=>{if(!e)return;let d=Oe(e);if(d===null)return;let r=V(d,l,s);m(a=>Object.is(a,r)?a:r);},[e,l,s]),react.useEffect(()=>{if(!o&&n!==void 0){let d=V(n,l,s);m(d),e&&Me(e,d);}},[o,n,e,l,s]),react.useEffect(()=>{R()&&!e&&!c.current&&(console.warn("[Loaded] SmartSkeletonList used without storageKey. The count will reset on remount. Add a storageKey to persist across sessions."),c.current=true);},[e]),b}function V(e,t,n){let o=Math.max(e,t);return n!==void 0&&(o=Math.min(o,n)),o}function De({loading:e=false,items:t,renderItem:n,renderSkeleton:o,storageKey:l,defaultCount:s=3,minCount:b=1,maxCount:m,animate:c=true,seed:d,suppressRefWarning:r=false,keyExtractor:a=(i,f)=>f}){let i=B({storageKey:l,defaultCount:s,currentCount:t?.length,loading:e,minCount:b,maxCount:m});if(e){let f=new Array(i);for(let u=0;u<i;u+=1){let E=d===void 0?`${u}`:`${d}:${u}`;f[u]=jsxRuntime.jsx(W,{loading:true,element:o(u),animate:c,seed:E,suppressRefWarning:r},`skeleton-${u}`);}return jsxRuntime.jsx(jsxRuntime.Fragment,{children:f})}return !t||t.length===0?null:jsxRuntime.jsx(jsxRuntime.Fragment,{children:t.map((f,u)=>jsxRuntime.jsx(react.Fragment,{children:n(f,u)},a(f,u)))})}exports.SkeletonContext=w;exports.SmartSkeleton=W;exports.SmartSkeletonList=De;exports.useIsSkeletonMode=me;exports.usePersistedCount=B;//# sourceMappingURL=index.cjs.map
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/SkeletonContext/SkeletonContext.tsx","../src/utils/isDevEnv.ts","../src/utils/useIsomorphicLayoutEffect.ts","../src/components/SmartSkeleton/SmartSkeleton.tsx","../src/hooks/usePersistedCount/usePersistedCount.ts","../src/components/SmartSkeletonList/SmartSkeletonList.tsx"],"names":["SkeletonContext","createContext","useIsSkeletonMode","useContext","isDevEnv","maybeGlobal","override","devFlag","maybeProcess","nodeEnv","canUseDOM","useIsomorphicLayoutEffect","useLayoutEffect","useEffect","TEXT_WIDTH_MIN_CH","TEXT_WIDTH_MAX_CH","isElement","value","maybeElement","warnedComponents","isUsableElement","resolveRefTarget","node","nativeElement","getElementDisplayName","element","type","fn","obj","REACT_MAJOR_VERSION","reactVersion","IS_REACT_19_OR_NEWER","getOriginalRef","propsRef","legacyRef","forwardRef","originalRef","MEDIA_ELEMENTS","SVG_ELEMENTS","INTERACTIVE_ELEMENTS","BUTTON_LIKE_SELECTOR","SKIPPED_TAGS","getTagName","el","isButtonLikeElement","tagName","isButtonLikeDescendant","isContentElement","calculateTextWidthCh","text","seedKey","textLength","jitterRange","jitter","deterministicJitter","width","hash","index","resolveTextAlign","align","applySkeletonClasses","rootElement","options","animate","seed","baseSeed","htmlRoot","descendants","textIndex","processElement","htmlEl","textContent","widthCh","SmartSkeleton","children","loading","className","suppressRefWarning","hasAppliedRef","useRef","refWasCalledRef","lastRefNodeRef","deferredWrapperCheckTimeoutRef","needsWrapperRef","needsWrapper","setNeedsWrapper","useState","currentElementType","currentElementKey","previousLoadingRef","previousElementTypeRef","previousElementKeyRef","cancelDeferredWrapperCheck","useCallback","previousLoading","previousElementType","previousElementKey","enableWrapperWithWarning","reason","displayName","refCallback","target","delayedNode","delayedTarget","existingClassName","baseClasses","wrapperClassName","mergedClassName","jsx","cloneElement","STORAGE_KEY","LEGACY_STORAGE_KEY","STORAGE_VERSION","isRecord","toNumberRecord","result","key","maybeNumber","parseStoredCounts","readStoredCountsFromKey","raw","writeStoredCounts","counts","payload","getStoredCounts","rawNew","legacyCounts","getStoredCount","setStoredCount","count","usePersistedCount","storageKey","defaultCount","currentCount","minCount","maxCount","setCount","clampCount","hasWarnedRef","stored","next","prev","newCount","min","max","SmartSkeletonList","items","renderItem","renderSkeleton","keyExtractor","_","skeletonCount","skeletons","itemSeed","Fragment","item"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createContext, useContext } from \"react\";\n\nexport const SkeletonContext = createContext(false);\n\nexport function useIsSkeletonMode(): boolean {\n return useContext(SkeletonContext);\n}\n","export function isDevEnv(): boolean {\n const maybeGlobal = globalThis as unknown as Record<string, unknown>;\n\n // Manual override for environments where NODE_ENV isn't injected.\n // Example: `globalThis.__REACT_LOADED_DEV__ = true`.\n const override = maybeGlobal.__REACT_LOADED_DEV__;\n if (typeof override === \"boolean\") return override;\n\n // Common global used by some toolchains/runtimes.\n const devFlag = maybeGlobal.__DEV__;\n if (typeof devFlag === \"boolean\") return devFlag;\n\n const maybeProcess = (globalThis as unknown as { process?: unknown }).process;\n const nodeEnv =\n typeof maybeProcess === \"object\" && maybeProcess !== null\n ? (maybeProcess as { env?: { NODE_ENV?: unknown } }).env?.NODE_ENV\n : undefined;\n\n if (typeof nodeEnv === \"string\") {\n return nodeEnv !== \"production\";\n }\n\n // No environment detected — assume production (convention: opt-in to dev mode).\n return false;\n}\n","import { useEffect, useLayoutEffect } from \"react\";\n\nconst canUseDOM =\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as { document?: unknown }).document !== \"undefined\";\n\nexport const useIsomorphicLayoutEffect = canUseDOM\n ? useLayoutEffect\n : useEffect;\n","import {\n cloneElement,\n type ReactElement,\n type Ref,\n version as reactVersion,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { isDevEnv } from \"../../utils/isDevEnv\";\nimport { useIsomorphicLayoutEffect } from \"../../utils/useIsomorphicLayoutEffect\";\nimport { SkeletonContext } from \"../SkeletonContext/SkeletonContext\";\nimport \"./SmartSkeleton.css\";\n\n// Text width configuration (in ch units)\nconst TEXT_WIDTH_MIN_CH = 6;\nconst TEXT_WIDTH_MAX_CH = 40;\n\nfunction isElement(value: unknown): value is Element {\n if (!value || typeof value !== \"object\") return false;\n const maybeElement = value as Element;\n // Must have nodeType 1 (Element) and a working querySelectorAll\n if (maybeElement.nodeType !== 1) return false;\n if (typeof maybeElement.tagName !== \"string\") return false;\n if (typeof maybeElement.querySelectorAll !== \"function\") return false;\n // Additional check: instanceof Element if available\n if (typeof Element !== \"undefined\" && !(value instanceof Element)) {\n return false;\n }\n return true;\n}\n\nconst warnedComponents = new Set<string>();\n\nfunction isUsableElement(value: unknown): value is Element {\n if (!isElement(value)) return false;\n // Test that querySelectorAll actually works\n try {\n (value as Element).querySelectorAll(\"*\");\n return true;\n } catch {\n return false;\n }\n}\n\nfunction resolveRefTarget(node: unknown): Element | null {\n if (isUsableElement(node)) return node;\n if (node && typeof node === \"object\" && \"nativeElement\" in node) {\n const nativeElement = (node as { nativeElement?: unknown }).nativeElement;\n if (isUsableElement(nativeElement)) return nativeElement;\n }\n return null;\n}\n\nfunction getElementDisplayName(element: ReactElement): string {\n const type = element.type;\n if (typeof type === \"string\") {\n return `<${type}>`;\n }\n if (typeof type === \"function\") {\n const fn = type as { displayName?: string; name?: string };\n return `<${fn.displayName || fn.name || \"Unknown\"}>`;\n }\n if (typeof type === \"object\" && type !== null) {\n const obj = type as { displayName?: string; name?: string };\n return `<${obj.displayName || obj.name || \"Unknown\"}>`;\n }\n return \"<Unknown>\";\n}\n\nconst REACT_MAJOR_VERSION = Number.parseInt(reactVersion, 10);\nconst IS_REACT_19_OR_NEWER =\n Number.isFinite(REACT_MAJOR_VERSION) && REACT_MAJOR_VERSION >= 19;\n\n/**\n * Get the original ref from the element, supporting both React 18 and React 19.\n * React 19: ref is a regular prop on element.props.ref\n * React 18: ref is on element.ref\n */\nfunction getOriginalRef(element: ReactElement): Ref<unknown> | undefined {\n // React 19 style (ref as prop)\n const elementProps = element.props as { ref?: Ref<unknown> } | undefined;\n const propsRef = elementProps?.ref;\n if (propsRef !== undefined) return propsRef;\n\n // React 19+ warns on element.ref access; skip legacy fallback entirely.\n if (IS_REACT_19_OR_NEWER) return undefined;\n\n // React 18 style\n const legacyRef = (element as ReactElement & { ref?: Ref<unknown> }).ref;\n if (legacyRef !== undefined) return legacyRef;\n\n return undefined;\n}\n\n/**\n * Forward a ref value to the original ref (callback or object style).\n */\nfunction forwardRef(originalRef: Ref<unknown> | undefined, node: unknown) {\n if (!originalRef) return;\n if (typeof originalRef === \"function\") {\n originalRef(node);\n } else {\n (originalRef as React.MutableRefObject<unknown>).current = node;\n }\n}\n\nconst MEDIA_ELEMENTS = new Set([\"IMG\", \"VIDEO\", \"CANVAS\"]);\nconst SVG_ELEMENTS = new Set([\"SVG\"]);\n\nconst INTERACTIVE_ELEMENTS = new Set([\n \"BUTTON\",\n \"INPUT\",\n \"TEXTAREA\",\n \"SELECT\",\n \"A\",\n]);\n\nconst BUTTON_LIKE_SELECTOR = \"button,input,textarea,select,a,[role='button']\";\nconst SKIPPED_TAGS = new Set([\n \"SCRIPT\",\n \"STYLE\",\n \"LINK\",\n \"META\",\n \"NOSCRIPT\",\n \"TEMPLATE\",\n]);\n\nfunction getTagName(el: Element): string {\n return el.tagName.toUpperCase();\n}\n\nfunction isButtonLikeElement(el: Element, tagName = getTagName(el)): boolean {\n if (INTERACTIVE_ELEMENTS.has(tagName)) return true;\n const role = el.getAttribute(\"role\");\n return role === \"button\";\n}\n\nfunction isButtonLikeDescendant(el: Element, tagName: string): boolean {\n const closestButton = el.closest(BUTTON_LIKE_SELECTOR);\n return Boolean(closestButton && !isButtonLikeElement(el, tagName));\n}\n\nfunction isContentElement(el: Element, tagName = getTagName(el)): boolean {\n if (MEDIA_ELEMENTS.has(tagName)) return true;\n if (SVG_ELEMENTS.has(tagName)) return true;\n if (isButtonLikeElement(el, tagName)) return true;\n\n const isLeafNode = el.childElementCount === 0;\n\n // Text elements that are leaf nodes (no child elements, only text)\n if (isLeafNode && el.textContent?.trim()) return true;\n\n return false;\n}\n\n/**\n * Calculate text skeleton width in ch units based on text content.\n * Uses a deterministic jitter: widthCh = clamp(6, 40, len + 2 + jitter)\n */\nfunction calculateTextWidthCh(text: string, seedKey: string): number {\n const textLength = text.length;\n const jitterRange = Math.max(4, 0.8 * textLength);\n const jitter = deterministicJitter(seedKey) * jitterRange;\n const width = textLength + 2 + jitter;\n return Math.max(TEXT_WIDTH_MIN_CH, Math.min(TEXT_WIDTH_MAX_CH, width));\n}\n\nfunction deterministicJitter(seedKey: string): number {\n if (!seedKey) return 0;\n let hash = 2166136261;\n for (let index = 0; index < seedKey.length; index += 1) {\n hash ^= seedKey.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n const normalized = (hash >>> 0) / 0xffffffff;\n return normalized * 2 - 1;\n}\n\nfunction resolveTextAlign(el: HTMLElement): \"left\" | \"center\" | \"right\" {\n const align = globalThis.getComputedStyle(el).textAlign;\n if (align === \"center\") return \"center\";\n if (align === \"right\" || align === \"end\") return \"right\";\n return \"left\";\n}\n\nexport function applySkeletonClasses(\n rootElement: Element,\n options: { animate?: boolean; seed?: string | number } = {},\n): void {\n const { animate = true, seed } = options;\n const baseSeed =\n seed === undefined || seed === null ? \"loaded\" : String(seed);\n\n if (!isElement(rootElement)) {\n return;\n }\n\n const htmlRoot = rootElement as HTMLElement;\n\n // Apply skeleton mode to the root element\n htmlRoot.classList.add(\"loaded-skeleton-mode\");\n\n if (animate) {\n htmlRoot.classList.add(\"loaded-animate\");\n }\n\n // Apply background class for standalone usage (when not used via SmartSkeleton JSX)\n // If element has loaded-skeleton-wrapper, CSS handles bg via > :first-child rule\n // If element already has loaded-skeleton-bg (from JSX), this is a no-op\n const isWrapper = htmlRoot.classList.contains(\"loaded-skeleton-wrapper\");\n if (!isWrapper) {\n htmlRoot.classList.add(\"loaded-skeleton-bg\");\n }\n\n // Only add specific classes where needed (text, media, content)\n const descendants = rootElement.getElementsByTagName(\"*\");\n\n let textIndex = 0;\n\n const processElement = (el: Element) => {\n const tagName = getTagName(el);\n if (SKIPPED_TAGS.has(tagName)) return;\n if (!isContentElement(el, tagName)) return;\n if (isButtonLikeDescendant(el, tagName)) return;\n\n const htmlEl = el as HTMLElement;\n const textContent = el.textContent?.trim();\n const isLeafWithText = el.childElementCount === 0 && textContent;\n\n if (\n isLeafWithText &&\n !MEDIA_ELEMENTS.has(tagName) &&\n !SVG_ELEMENTS.has(tagName) &&\n !isButtonLikeElement(el, tagName)\n ) {\n // Text elements: overlay bar with ch-based width\n htmlEl.classList.add(\"loaded-text-skeleton\");\n htmlEl.dataset.skeletonAlign = resolveTextAlign(htmlEl);\n const seedKey = `${baseSeed}|${textIndex}|${textContent ?? \"\"}`;\n textIndex += 1;\n const widthCh = calculateTextWidthCh(textContent ?? \"\", seedKey);\n htmlEl.style.setProperty(\"--skeleton-text-width\", `${widthCh}ch`);\n } else if (MEDIA_ELEMENTS.has(tagName)) {\n // Media elements\n htmlEl.classList.add(\"loaded-skeleton-media\");\n } else if (SVG_ELEMENTS.has(tagName)) {\n // SVG elements rendered as rounded content blocks\n htmlEl.classList.add(\"loaded-skeleton-content\");\n htmlEl.classList.add(\"loaded-skeleton-svg\");\n } else {\n // Interactive elements (buttons, inputs, etc.)\n htmlEl.classList.add(\"loaded-skeleton-content\");\n // Prevent keyboard focus / interaction while in skeleton mode.\n // aria-hidden does not remove elements from the tab order.\n htmlEl.setAttribute(\"tabindex\", \"-1\");\n }\n };\n\n processElement(rootElement);\n for (const el of descendants) {\n processElement(el);\n }\n}\n\nexport interface SmartSkeletonProps {\n /** The skeleton element with mock data, rendered when loading */\n element: ReactElement;\n /** The real content to render when not loading. If omitted, returns null when loading=false. */\n children?: ReactElement;\n /** Whether the skeleton is currently loading. Default: false */\n loading?: boolean;\n /** Enable shimmer animation. Default: true */\n animate?: boolean;\n /** Additional CSS class name */\n className?: string;\n /** Optional seed to stabilize skeleton text widths */\n seed?: string | number;\n /** Suppress warning when auto-wrapper is applied. Default: false */\n suppressRefWarning?: boolean;\n}\n\nexport function SmartSkeleton({\n element,\n children,\n loading = false,\n animate = true,\n className = \"\",\n seed,\n suppressRefWarning = false,\n}: SmartSkeletonProps): ReactElement | null {\n const hasAppliedRef = useRef(false);\n const refWasCalledRef = useRef(false);\n const lastRefNodeRef = useRef<unknown>(null);\n const deferredWrapperCheckTimeoutRef = useRef<ReturnType<\n typeof setTimeout\n > | null>(null);\n const needsWrapperRef = useRef(false);\n const [needsWrapper, setNeedsWrapper] = useState(false);\n const currentElementType = element.type;\n const currentElementKey = element.key ?? null;\n const previousLoadingRef = useRef(loading);\n const previousElementTypeRef =\n useRef<ReactElement[\"type\"]>(currentElementType);\n const previousElementKeyRef = useRef<ReactElement[\"key\"] | null>(\n currentElementKey,\n );\n\n const cancelDeferredWrapperCheck = useCallback(() => {\n if (deferredWrapperCheckTimeoutRef.current !== null) {\n clearTimeout(deferredWrapperCheckTimeoutRef.current);\n deferredWrapperCheckTimeoutRef.current = null;\n }\n }, []);\n\n useEffect(() => {\n needsWrapperRef.current = needsWrapper;\n }, [needsWrapper]);\n\n // Keep render pure: reset mutable tracking only after commit.\n useIsomorphicLayoutEffect(() => {\n const previousLoading = previousLoadingRef.current;\n const previousElementType = previousElementTypeRef.current;\n const previousElementKey = previousElementKeyRef.current;\n\n const didExitLoading = previousLoading && !loading;\n const hasElementIdentityChanged =\n previousElementType !== currentElementType ||\n previousElementKey !== currentElementKey;\n\n if (didExitLoading || hasElementIdentityChanged) {\n hasAppliedRef.current = false;\n refWasCalledRef.current = false;\n lastRefNodeRef.current = null;\n cancelDeferredWrapperCheck();\n\n if (needsWrapperRef.current) {\n setNeedsWrapper(false);\n }\n }\n\n previousLoadingRef.current = loading;\n previousElementTypeRef.current = currentElementType;\n previousElementKeyRef.current = currentElementKey;\n }, [\n loading,\n currentElementType,\n currentElementKey,\n cancelDeferredWrapperCheck,\n ]);\n\n useEffect(() => {\n return () => {\n cancelDeferredWrapperCheck();\n };\n }, [cancelDeferredWrapperCheck]);\n\n const originalRef = getOriginalRef(element);\n\n const enableWrapperWithWarning = useCallback(\n (reason: \"non-dom-ref\" | \"no-ref-call\") => {\n if (needsWrapperRef.current) return;\n setNeedsWrapper(true);\n\n if (!suppressRefWarning && isDevEnv()) {\n const displayName = getElementDisplayName(element);\n if (!warnedComponents.has(displayName)) {\n if (reason === \"non-dom-ref\") {\n console.warn(\n `[SmartSkeleton] ${displayName} does not forward its ref to a DOM element. ` +\n `A wrapper <div> has been added automatically. Use forwardRef to avoid this.`,\n );\n } else {\n console.warn(\n `[SmartSkeleton] ${displayName} does not accept a ref. ` +\n `A wrapper <div> has been added automatically. Use forwardRef to avoid this.`,\n );\n }\n warnedComponents.add(displayName);\n }\n }\n },\n [element, suppressRefWarning],\n );\n\n const refCallback = useCallback(\n (node: unknown) => {\n refWasCalledRef.current = true;\n lastRefNodeRef.current = node;\n\n const target = resolveRefTarget(node);\n\n if (target && loading && !hasAppliedRef.current) {\n applySkeletonClasses(target, { animate, seed });\n hasAppliedRef.current = true;\n }\n\n // Forward ref to original element\n forwardRef(originalRef, node);\n },\n [loading, originalRef, animate, seed],\n );\n\n // Decide wrapper fallback after commit to avoid eager false positives:\n // some environments attach refs slightly later in the same tick.\n useIsomorphicLayoutEffect(() => {\n if (!loading || needsWrapper) return;\n\n cancelDeferredWrapperCheck();\n\n const node = lastRefNodeRef.current;\n const target = resolveRefTarget(node);\n\n if (target && !hasAppliedRef.current) {\n applySkeletonClasses(target, { animate, seed });\n hasAppliedRef.current = true;\n }\n\n if (refWasCalledRef.current) {\n if (node !== null && !target) {\n enableWrapperWithWarning(\"non-dom-ref\");\n }\n return;\n }\n\n deferredWrapperCheckTimeoutRef.current = setTimeout(() => {\n deferredWrapperCheckTimeoutRef.current = null;\n\n if (!loading || needsWrapperRef.current) return;\n\n const delayedNode = lastRefNodeRef.current;\n const delayedTarget = resolveRefTarget(delayedNode);\n\n if (delayedTarget && !hasAppliedRef.current) {\n applySkeletonClasses(delayedTarget, { animate, seed });\n hasAppliedRef.current = true;\n }\n\n if (refWasCalledRef.current) {\n if (delayedNode !== null && !delayedTarget) {\n enableWrapperWithWarning(\"non-dom-ref\");\n }\n return;\n }\n\n enableWrapperWithWarning(\"no-ref-call\");\n }, 0);\n\n return () => {\n cancelDeferredWrapperCheck();\n };\n }, [\n loading,\n needsWrapper,\n animate,\n seed,\n enableWrapperWithWarning,\n cancelDeferredWrapperCheck,\n ]);\n\n // Not loading: return children or null\n if (!loading) {\n return children ?? null;\n }\n\n // Build merged className for skeleton mode\n const elementProps = element.props as { className?: string };\n const existingClassName = elementProps.className ?? \"\";\n\n // Base classes for skeleton mode\n const baseClasses = [\"loaded-skeleton-mode\", animate && \"loaded-animate\"]\n .filter(Boolean)\n .join(\" \");\n\n // When wrapping: wrapper gets mode + wrapper marker (no bg - it goes on child via ref)\n const wrapperClassName = [baseClasses, \"loaded-skeleton-wrapper\", className]\n .filter(Boolean)\n .join(\" \");\n\n // When not wrapping: element gets mode + bg directly (for SSR)\n const mergedClassName = [\n existingClassName,\n baseClasses,\n \"loaded-skeleton-bg\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <SkeletonContext.Provider value={true}>\n {needsWrapper ? (\n <div ref={refCallback} className={wrapperClassName} aria-hidden=\"true\">\n {element}\n </div>\n ) : (\n cloneElement(element as ReactElement<Record<string, unknown>>, {\n ref: refCallback,\n className: mergedClassName,\n \"aria-hidden\": true,\n })\n )}\n </SkeletonContext.Provider>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { isDevEnv } from \"../../utils/isDevEnv\";\nimport { useIsomorphicLayoutEffect } from \"../../utils/useIsomorphicLayoutEffect\";\n\nconst STORAGE_KEY = \"react-loaded\";\nconst LEGACY_STORAGE_KEY = \"loaded\";\nconst STORAGE_VERSION = 1 as const;\n\ntype StoredCounts = Record<string, number>;\ntype StoredPayloadV1 = { v: typeof STORAGE_VERSION; counts: StoredCounts };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction toNumberRecord(value: unknown): StoredCounts {\n if (!isRecord(value)) return {};\n const result: StoredCounts = {};\n for (const [key, maybeNumber] of Object.entries(value)) {\n if (typeof maybeNumber === \"number\") {\n result[key] = maybeNumber;\n }\n }\n return result;\n}\n\nfunction parseStoredCounts(value: unknown): StoredCounts {\n // Current schema: { v: 1, counts: Record<string, number> }\n if (isRecord(value) && value.v === STORAGE_VERSION) {\n return toNumberRecord(value.counts);\n }\n\n // Legacy schema: Record<string, number>\n return toNumberRecord(value);\n}\n\nfunction readStoredCountsFromKey(key: string): StoredCounts {\n if (typeof localStorage === \"undefined\") return {};\n try {\n const raw = localStorage.getItem(key);\n if (raw === null) return {};\n return parseStoredCounts(JSON.parse(raw));\n } catch {\n return {};\n }\n}\n\nfunction writeStoredCounts(counts: StoredCounts): void {\n if (typeof localStorage === \"undefined\") return;\n const payload: StoredPayloadV1 = { v: STORAGE_VERSION, counts };\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));\n } catch {\n // Silently fail if localStorage is full or unavailable\n }\n}\n\nfunction getStoredCounts(): Record<string, number> {\n if (typeof localStorage === \"undefined\") return {};\n\n try {\n const rawNew = localStorage.getItem(STORAGE_KEY);\n if (rawNew !== null) {\n return parseStoredCounts(JSON.parse(rawNew));\n }\n\n // Backward compatibility: migrate legacy key once if present.\n const legacyCounts = readStoredCountsFromKey(LEGACY_STORAGE_KEY);\n if (Object.keys(legacyCounts).length > 0) {\n writeStoredCounts(legacyCounts);\n }\n return legacyCounts;\n } catch {\n return {};\n }\n}\n\nfunction getStoredCount(key: string): number | null {\n const counts = getStoredCounts();\n const value = counts[key];\n return typeof value === \"number\" ? value : null;\n}\n\nfunction setStoredCount(key: string, count: number): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n const counts = getStoredCounts();\n counts[key] = count;\n writeStoredCounts(counts);\n } catch {\n // Silently fail if localStorage is full or unavailable\n }\n}\n\nexport interface UsePersistedCountOptions {\n storageKey?: string;\n defaultCount?: number;\n currentCount?: number;\n loading: boolean;\n minCount?: number;\n maxCount?: number;\n}\n\nexport function usePersistedCount({\n storageKey,\n defaultCount = 3,\n currentCount,\n loading,\n minCount = 1,\n maxCount,\n}: UsePersistedCountOptions): number {\n // Always start from the default to match SSR output, then (on the client)\n // sync to the persisted value in a layout effect before first paint.\n const [count, setCount] = useState<number>(() =>\n clampCount(defaultCount, minCount, maxCount),\n );\n\n const hasWarnedRef = useRef(false);\n\n useIsomorphicLayoutEffect(() => {\n if (!storageKey) return;\n const stored = getStoredCount(storageKey);\n if (stored === null) return;\n const next = clampCount(stored, minCount, maxCount);\n setCount((prev) => (Object.is(prev, next) ? prev : next));\n }, [storageKey, minCount, maxCount]);\n\n useEffect(() => {\n if (!loading && currentCount !== undefined) {\n const newCount = clampCount(currentCount, minCount, maxCount);\n setCount(newCount);\n\n if (storageKey) {\n setStoredCount(storageKey, newCount);\n }\n }\n }, [loading, currentCount, storageKey, minCount, maxCount]);\n\n useEffect(() => {\n if (isDevEnv() && !storageKey && !hasWarnedRef.current) {\n console.warn(\n \"[Loaded] SmartSkeletonList used without storageKey. \" +\n \"The count will reset on remount. Add a storageKey to persist across sessions.\",\n );\n hasWarnedRef.current = true;\n }\n }, [storageKey]);\n\n return count;\n}\n\nfunction clampCount(\n value: number,\n min: number,\n max: number | undefined,\n): number {\n let result = Math.max(value, min);\n if (max !== undefined) {\n result = Math.min(result, max);\n }\n return result;\n}\n","import { Fragment, type ReactElement } from \"react\";\nimport { usePersistedCount } from \"../../hooks/usePersistedCount/usePersistedCount\";\nimport { SmartSkeleton } from \"../SmartSkeleton/SmartSkeleton\";\n\nexport interface SmartSkeletonListProps<T> {\n /** Whether the list is currently loading. Default: false */\n loading?: boolean;\n /** The items to render. Pass undefined while loading. */\n items: T[] | undefined;\n /** Render function for each item when loaded */\n renderItem: (item: T, index: number) => ReactElement;\n /** Render function for skeleton placeholders */\n renderSkeleton: (index: number) => ReactElement;\n /** Key for localStorage persistence. Without it, count resets on remount. */\n storageKey?: string;\n /** Initial skeleton count before any data is known. Default: 3 */\n defaultCount?: number;\n /** Minimum skeletons to show. Default: 1 */\n minCount?: number;\n /** Maximum skeletons to show */\n maxCount?: number;\n /** Enable shimmer animation. Default: true */\n animate?: boolean;\n /** Optional seed to stabilize skeleton text widths */\n seed?: string | number;\n /** Suppress warning when auto-wrapper is applied. Default: false */\n suppressRefWarning?: boolean;\n /** Extract unique key for each item. Default: index */\n keyExtractor?: (item: T, index: number) => string | number;\n}\n\nexport function SmartSkeletonList<T>({\n loading = false,\n items,\n renderItem,\n renderSkeleton,\n storageKey,\n defaultCount = 3,\n minCount = 1,\n maxCount,\n animate = true,\n seed,\n suppressRefWarning = false,\n keyExtractor = (_, index) => index,\n}: SmartSkeletonListProps<T>): ReactElement | null {\n const skeletonCount = usePersistedCount({\n storageKey,\n defaultCount,\n currentCount: items?.length,\n loading,\n minCount,\n maxCount,\n });\n\n if (loading) {\n const skeletons = new Array(skeletonCount);\n for (let index = 0; index < skeletonCount; index += 1) {\n const itemSeed = seed === undefined ? `${index}` : `${seed}:${index}`;\n skeletons[index] = (\n <SmartSkeleton\n key={`skeleton-${index}`}\n loading={true}\n element={renderSkeleton(index)}\n animate={animate}\n seed={itemSeed}\n suppressRefWarning={suppressRefWarning}\n />\n );\n }\n return <>{skeletons}</>;\n }\n\n if (!items || items.length === 0) {\n return null;\n }\n\n return (\n <>\n {items.map((item, index) => (\n <Fragment key={keyExtractor(item, index)}>\n {renderItem(item, index)}\n </Fragment>\n ))}\n </>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/SkeletonContext/SkeletonContext.tsx","../src/utils/isDevEnv.ts","../src/utils/useIsomorphicLayoutEffect.ts","../src/components/SmartSkeleton/applySkeletonClasses.ts","../src/components/SmartSkeleton/refUtils.ts","../src/components/SmartSkeleton/SmartSkeleton.tsx","../src/hooks/usePersistedCount/usePersistedCount.ts","../src/components/SmartSkeletonList/SmartSkeletonList.tsx"],"names":["SkeletonContext","createContext","useIsSkeletonMode","useContext","isDevEnv","maybeGlobal","override","devFlag","maybeProcess","nodeEnv","canUseDOM","useIsomorphicLayoutEffect","useLayoutEffect","useEffect","isElement","value","maybeElement","isUsableElement","MEDIA_ELEMENTS","SVG_ELEMENTS","INTERACTIVE_ELEMENTS","BUTTON_LIKE_SELECTOR","SKIPPED_TAGS","getTagName","el","isButtonLikeElement","tagName","isButtonLikeDescendant","isContentElement","calculateTextWidthCh","text","seedKey","textLength","jitterRange","jitter","deterministicJitter","width","hash","index","resolveTextAlign","align","applySkeletonClasses","rootElement","options","animate","seed","baseSeed","htmlRoot","descendants","textIndex","processElement","htmlEl","textContent","widthCh","REACT_MAJOR_VERSION","reactVersion","IS_REACT_19_OR_NEWER","resolveRefTarget","node","nativeElement","getElementDisplayName","element","type","fn","obj","getOriginalRef","propsRef","legacyRef","forwardRef","originalRef","warnedComponents","SmartSkeleton","children","loading","className","suppressRefWarning","currentElementType","currentElementKey","hasAppliedRef","useRef","refWasCalledRef","lastRefNodeRef","needsWrapperRef","needsWrapper","setNeedsWrapper","useState","previousLoadingRef","previousElementTypeRef","previousElementKeyRef","setWrapperState","useCallback","next","enableWrapperWithWarning","reason","displayName","refCallback","target","previousLoading","previousElementType","previousElementKey","didExitLoading","hasElementIdentityChanged","existingClassName","baseClasses","wrapperClassName","mergedClassName","jsx","cloneElement","STORAGE_KEY","LEGACY_STORAGE_KEY","STORAGE_VERSION","isRecord","toNumberRecord","result","key","maybeNumber","parseStoredCounts","readStoredCountsFromKey","raw","writeStoredCounts","counts","payload","getStoredCounts","rawNew","legacyCounts","getStoredCount","setStoredCount","count","usePersistedCount","storageKey","defaultCount","currentCount","minCount","maxCount","setCount","clampCount","hasWarnedRef","stored","prev","newCount","min","max","SmartSkeletonList","items","renderItem","renderSkeleton","keyExtractor","_","skeletonCount","skeletons","itemSeed","Fragment","item"],"mappings":"gFAEO,IAAMA,CAAAA,CAAkBC,mBAAAA,CAAc,KAAK,EAE3C,SAASC,IAA6B,CAC5C,OAAOC,iBAAWH,CAAe,CAClC,CCNO,SAASI,CAAAA,EAAoB,CACnC,IAAMC,CAAAA,CAAc,UAAA,CAIdC,CAAAA,CAAWD,CAAAA,CAAY,oBAAA,CAC7B,GAAI,OAAOC,CAAAA,EAAa,UAAW,OAAOA,CAAAA,CAG1C,IAAMC,CAAAA,CAAUF,CAAAA,CAAY,OAAA,CAC5B,GAAI,OAAOE,CAAAA,EAAY,UAAW,OAAOA,CAAAA,CAEzC,IAAMC,CAAAA,CAAgB,UAAA,CAAgD,QAChEC,CAAAA,CACL,OAAOD,CAAAA,EAAiB,QAAA,EAAYA,CAAAA,GAAiB,IAAA,CACjDA,EAAkD,GAAA,EAAK,QAAA,CACxD,OAEJ,OAAI,OAAOC,GAAY,QAAA,CACfA,CAAAA,GAAY,YAAA,CAIb,KACR,CCtBA,IAAMC,GACL,OAAO,UAAA,CAAe,GAAA,EACtB,OAAQ,UAAA,CAAsC,QAAA,CAAa,IAE/CC,CAAAA,CAA4BD,EAAAA,CACtCE,qBAAAA,CACAC,eAAAA,CCJH,SAASC,CAAAA,CAAUC,EAAkC,CACpD,GAAI,CAACA,CAAAA,EAAS,OAAOA,CAAAA,EAAU,SAAU,OAAO,MAAA,CAChD,IAAMC,CAAAA,CAAeD,CAAAA,CAMrB,OAJI,EAAAC,CAAAA,CAAa,QAAA,GAAa,CAAA,EAC1B,OAAOA,CAAAA,CAAa,SAAY,QAAA,EAChC,OAAOA,EAAa,gBAAA,EAAqB,UAAA,EAEzC,OAAO,OAAA,CAAY,GAAA,EAAe,EAAED,CAAAA,YAAiB,OAAA,CAAA,CAI1D,CAEO,SAASE,CAAAA,CAAgBF,CAAAA,CAAkC,CACjE,GAAI,CAACD,EAAUC,CAAK,CAAA,CAAG,OAAO,MAAA,CAE9B,GAAI,CACH,OAACA,CAAAA,CAAkB,gBAAA,CAAiB,GAAG,CAAA,CAChC,CAAA,CACR,MAAQ,CACP,OAAO,MACR,CACD,CAEA,IAAMG,EAAiB,IAAI,GAAA,CAAI,CAAC,KAAA,CAAO,OAAA,CAAS,QAAQ,CAAC,CAAA,CACnDC,CAAAA,CAAe,IAAI,GAAA,CAAI,CAAC,KAAK,CAAC,CAAA,CAE9BC,GAAuB,IAAI,GAAA,CAAI,CACpC,QAAA,CACA,OAAA,CACA,UAAA,CACA,QAAA,CACA,GACD,CAAC,EAEKC,EAAAA,CAAuB,gDAAA,CACvBC,GAAe,IAAI,GAAA,CAAI,CAC5B,QAAA,CACA,OAAA,CACA,MAAA,CACA,MAAA,CACA,UAAA,CACA,UACD,CAAC,CAAA,CAED,SAASC,CAAAA,CAAWC,CAAAA,CAAqB,CACxC,OAAOA,EAAG,OAAA,CAAQ,WAAA,EACnB,CAEA,SAASC,CAAAA,CAAoBD,EAAaE,CAAAA,CAAUH,CAAAA,CAAWC,CAAE,CAAA,CAAY,CAC5E,OAAIJ,EAAAA,CAAqB,GAAA,CAAIM,CAAO,CAAA,CAAU,IAAA,CACjCF,CAAAA,CAAG,aAAa,MAAM,CAAA,GACnB,QACjB,CAEA,SAASG,GAAuBH,CAAAA,CAAaE,CAAAA,CAA0B,CAEtE,OAAO,CAAA,EADeF,CAAAA,CAAG,QAAQH,EAAoB,CAAA,EACrB,CAACI,CAAAA,CAAoBD,CAAAA,CAAIE,CAAO,CAAA,CACjE,CAEA,SAASE,EAAAA,CAAiBJ,CAAAA,CAAaE,CAAAA,CAAUH,EAAWC,CAAE,CAAA,CAAY,CAQzE,OAPI,CAAA,EAAAN,EAAe,GAAA,CAAIQ,CAAO,CAAA,EAC1BP,CAAAA,CAAa,GAAA,CAAIO,CAAO,GACxBD,CAAAA,CAAoBD,CAAAA,CAAIE,CAAO,CAAA,EAEhBF,CAAAA,CAAG,oBAAsB,CAAA,EAG1BA,CAAAA,CAAG,WAAA,EAAa,IAAA,EAAK,CAGxC,CAMA,SAASK,EAAAA,CAAqBC,CAAAA,CAAcC,EAAyB,CACpE,IAAMC,EAAaF,CAAAA,CAAK,MAAA,CAClBG,CAAAA,CAAc,IAAA,CAAK,GAAA,CAAI,CAAA,CAAG,GAAMD,CAAU,CAAA,CAC1CE,EAASC,EAAAA,CAAoBJ,CAAO,EAAIE,CAAAA,CACxCG,CAAAA,CAAQJ,CAAAA,CAAa,CAAA,CAAIE,CAAAA,CAC/B,OAAO,KAAK,GAAA,CAAI,CAAA,CAAmB,IAAA,CAAK,GAAA,CAAI,EAAA,CAAmBE,CAAK,CAAC,CACtE,CAEA,SAASD,EAAAA,CAAoBJ,CAAAA,CAAyB,CACrD,GAAI,CAACA,CAAAA,CAAS,OAAO,CAAA,CACrB,IAAIM,EAAO,UAAA,CACX,IAAA,IAASC,CAAAA,CAAQ,CAAA,CAAGA,CAAAA,CAAQP,CAAAA,CAAQ,OAAQO,CAAAA,EAAS,CAAA,CACpDD,GAAQN,CAAAA,CAAQ,UAAA,CAAWO,CAAK,CAAA,CAChCD,CAAAA,CAAO,IAAA,CAAK,IAAA,CAAKA,CAAAA,CAAM,QAAQ,EAGhC,OAAA,CADoBA,CAAAA,GAAS,GAAK,UAAA,CACd,CAAA,CAAI,CACzB,CAEA,SAASE,EAAAA,CAAiBf,CAAAA,CAA8C,CACvE,IAAMgB,EAAQ,UAAA,CAAW,gBAAA,CAAiBhB,CAAE,CAAA,CAAE,SAAA,CAC9C,OAAIgB,CAAAA,GAAU,QAAA,CAAiB,QAAA,CAC3BA,CAAAA,GAAU,OAAA,EAAWA,CAAAA,GAAU,MAAc,OAAA,CAC1C,MACR,CAEO,SAASC,CAAAA,CACfC,EACAC,CAAAA,CAAyD,EAAC,CACnD,CACP,GAAM,CAAE,QAAAC,CAAAA,CAAU,IAAA,CAAM,KAAAC,CAAK,CAAA,CAAIF,EAC3BG,CAAAA,CACiBD,CAAAA,EAAS,IAAA,CAAO,QAAA,CAAW,MAAA,CAAOA,CAAI,EAE7D,GAAI,CAAC/B,EAAU4B,CAAW,CAAA,CACzB,OAGD,IAAMK,CAAAA,CAAWL,CAAAA,CAGjBK,CAAAA,CAAS,SAAA,CAAU,GAAA,CAAI,sBAAsB,CAAA,CAEzCH,CAAAA,EACHG,CAAAA,CAAS,SAAA,CAAU,GAAA,CAAI,gBAAgB,EAMtBA,CAAAA,CAAS,SAAA,CAAU,QAAA,CAAS,yBAAyB,CAAA,EAEtEA,CAAAA,CAAS,UAAU,GAAA,CAAI,oBAAoB,EAI5C,IAAMC,CAAAA,CAAcN,EAAY,oBAAA,CAAqB,GAAG,CAAA,CAEpDO,CAAAA,CAAY,CAAA,CAEVC,CAAAA,CAAkB1B,GAAgB,CACvC,IAAME,EAAUH,CAAAA,CAAWC,CAAE,EAE7B,GADIF,EAAAA,CAAa,GAAA,CAAII,CAAO,CAAA,EACxB,CAACE,GAAiBJ,CAAAA,CAAIE,CAAO,EAAG,OAEpC,IAAMyB,EAAS3B,CAAAA,CAEf,GAD2BG,EAAAA,CAAuBH,CAAAA,CAAIE,CAAO,CAAA,CACrC,CACvByB,CAAAA,CAAO,SAAA,CAAU,IAAI,4BAA4B,CAAA,CACjD,MACD,CAEA,IAAMC,CAAAA,CAAc5B,CAAAA,CAAG,WAAA,EAAa,IAAA,GAGpC,GAFuBA,CAAAA,CAAG,oBAAsB,CAAA,EAAK4B,CAAAA,EAIpD,CAAClC,CAAAA,CAAe,GAAA,CAAIQ,CAAO,CAAA,EAC3B,CAACP,CAAAA,CAAa,IAAIO,CAAO,CAAA,EACzB,CAACD,CAAAA,CAAoBD,CAAAA,CAAIE,CAAO,CAAA,CAC/B,CAEDyB,CAAAA,CAAO,SAAA,CAAU,GAAA,CAAI,sBAAsB,EAC3CA,CAAAA,CAAO,OAAA,CAAQ,cAAgBZ,EAAAA,CAAiBY,CAAM,EACtD,IAAMpB,CAAAA,CAAU,CAAA,EAAGe,CAAQ,CAAA,CAAA,EAAIG,CAAS,IAAIG,CAAAA,EAAe,EAAE,CAAA,CAAA,CAC7DH,CAAAA,EAAa,CAAA,CACb,IAAMI,EAAUxB,EAAAA,CAAqBuB,CAAAA,EAAe,EAAA,CAAIrB,CAAO,CAAA,CAC/DoB,CAAAA,CAAO,MAAM,WAAA,CAAY,uBAAA,CAAyB,GAAGE,CAAO,CAAA,EAAA,CAAI,EACjE,CAAA,KAAWnC,CAAAA,CAAe,GAAA,CAAIQ,CAAO,CAAA,CAEpCyB,CAAAA,CAAO,UAAU,GAAA,CAAI,uBAAuB,EAClChC,CAAAA,CAAa,GAAA,CAAIO,CAAO,CAAA,EAElCyB,CAAAA,CAAO,SAAA,CAAU,GAAA,CAAI,yBAAyB,CAAA,CAC9CA,EAAO,SAAA,CAAU,GAAA,CAAI,qBAAqB,CAAA,GAG1CA,CAAAA,CAAO,UAAU,GAAA,CAAI,yBAAyB,CAAA,CAG9CA,CAAAA,CAAO,YAAA,CAAa,UAAA,CAAY,IAAI,CAAA,EAEtC,CAAA,CAEAD,EAAeR,CAAW,CAAA,CAC1B,QAAWlB,CAAAA,IAAMwB,CAAAA,CAChBE,CAAAA,CAAe1B,CAAE,EAEnB,CC3LO,IAAM8B,CAAAA,CAAsB,OAAO,QAAA,CAASC,aAAAA,CAAc,EAAE,CAAA,CAC7DC,EAAAA,CACL,MAAA,CAAO,SAASF,CAAmB,CAAA,EAAKA,GAAuB,EAAA,CAEzD,SAASG,EAAiBC,CAAAA,CAA+B,CAC/D,GAAIzC,CAAAA,CAAgByC,CAAI,CAAA,CAAG,OAAOA,CAAAA,CAClC,GAAIA,GAAQ,OAAOA,CAAAA,EAAS,UAAY,eAAA,GAAmBA,CAAAA,CAAM,CAChE,IAAMC,CAAAA,CAAiBD,CAAAA,CAAqC,cAC5D,GAAIzC,CAAAA,CAAgB0C,CAAa,CAAA,CAAG,OAAOA,CAC5C,CACA,OAAO,IACR,CAEO,SAASC,CAAAA,CAAsBC,CAAAA,CAA+B,CACpE,IAAMC,CAAAA,CAAOD,EAAQ,IAAA,CACrB,GAAI,OAAOC,CAAAA,EAAS,QAAA,CACnB,OAAO,CAAA,CAAA,EAAIA,CAAI,CAAA,CAAA,CAAA,CAEhB,GAAI,OAAOA,CAAAA,EAAS,WAAY,CAC/B,IAAMC,EAAKD,CAAAA,CACX,OAAO,CAAA,CAAA,EAAIC,CAAAA,CAAG,WAAA,EAAeA,CAAAA,CAAG,MAAQ,SAAS,CAAA,CAAA,CAClD,CACA,GAAI,OAAOD,GAAS,QAAA,EAAYA,CAAAA,GAAS,IAAA,CAAM,CAC9C,IAAME,CAAAA,CAAMF,EACZ,OAAO,CAAA,CAAA,EAAIE,EAAI,WAAA,EAAeA,CAAAA,CAAI,MAAQ,SAAS,CAAA,CAAA,CACpD,CACA,OAAO,WACR,CAOO,SAASC,CAAAA,CACfJ,CAAAA,CAC2B,CAG3B,IAAMK,CAAAA,CADeL,EAAQ,KAAA,EACE,GAAA,CAC/B,GAAIK,CAAAA,GAAa,MAAA,CAAW,OAAOA,EAGnC,GAAIV,EAAAA,CAAsB,OAG1B,IAAMW,CAAAA,CAAaN,EAAkD,GAAA,CACrE,GAAIM,CAAAA,GAAc,MAAA,CAAW,OAAOA,CAGrC,CAKO,SAASC,CAAAA,CACfC,EACAX,CAAAA,CACC,CACIW,IACD,OAAOA,CAAAA,EAAgB,UAAA,CAC1BA,CAAAA,CAAYX,CAAI,CAAA,CAEfW,EAAgD,OAAA,CAAUX,CAAAA,EAE7D,CC/CA,IAAMY,CAAAA,CAAmB,IAAI,GAAA,CAmBtB,SAASC,CAAAA,CAAc,CAC7B,QAAAV,CAAAA,CACA,QAAA,CAAAW,EACA,OAAA,CAAAC,CAAAA,CAAU,MACV,OAAA,CAAA7B,CAAAA,CAAU,IAAA,CACV,SAAA,CAAA8B,CAAAA,CAAY,EAAA,CACZ,KAAA7B,CAAAA,CACA,kBAAA,CAAA8B,EAAqB,KACtB,CAAA,CAA4C,CAC3C,IAAMC,CAAAA,CAAqBf,CAAAA,CAAQ,IAAA,CAC7BgB,CAAAA,CAAoBhB,CAAAA,CAAQ,KAAO,IAAA,CACnCiB,CAAAA,CAAgBC,aAAO,KAAK,CAAA,CAC5BC,EAAkBD,YAAAA,CAAO,KAAK,CAAA,CAC9BE,CAAAA,CAAiBF,YAAAA,CAAgB,IAAI,EACrCG,CAAAA,CAAkBH,YAAAA,CAAO,KAAK,CAAA,CAC9B,CAACI,EAAcC,CAAe,CAAA,CAAIC,cAAAA,CAAS,KAAK,CAAA,CAChDC,CAAAA,CAAqBP,aAAON,CAAO,CAAA,CACnCc,EACLR,YAAAA,CAA6BH,CAAkB,EAC1CY,CAAAA,CAAwBT,YAAAA,CAC7BF,CACD,CAAA,CAEMY,CAAAA,CAAkBC,iBAAAA,CAAaC,GAAkB,CACtDT,CAAAA,CAAgB,QAAUS,CAAAA,CAC1BP,CAAAA,CAAgBO,CAAI,EACrB,CAAA,CAAG,EAAE,CAAA,CAECtB,CAAAA,CAAcJ,EAAeJ,CAAO,CAAA,CAEpC+B,EAA2BF,iBAAAA,CAC/BG,CAAAA,EAA0C,CAK1C,GAJKX,CAAAA,CAAgB,OAAA,EACpBO,CAAAA,CAAgB,IAAI,CAAA,CAGjB,CAACd,CAAAA,EAAsBvE,CAAAA,EAAS,CAAG,CACtC,IAAM0F,CAAAA,CAAclC,EAAsBC,CAAO,CAAA,CAC5CS,CAAAA,CAAiB,GAAA,CAAIwB,CAAW,CAAA,GAEnC,QAAQ,IAAA,CADLD,CAAAA,GAAW,cAEb,CAAA,gBAAA,EAAmBC,CAAW,0HAK9B,CAAA,gBAAA,EAAmBA,CAAW,CAAA,mGAAA,CAH/B,CAAA,CAODxB,CAAAA,CAAiB,GAAA,CAAIwB,CAAW,CAAA,EAElC,CACD,EACA,CAACjC,CAAAA,CAASc,EAAoBc,CAAe,CAC9C,CAAA,CAEMM,CAAAA,CAAcL,iBAAAA,CAClBhC,CAAAA,EAAkB,CAClBsB,CAAAA,CAAgB,OAAA,CAAU,KAC1BC,CAAAA,CAAe,OAAA,CAAUvB,EAEzB,IAAMsC,CAAAA,CAASvC,CAAAA,CAAiBC,CAAI,CAAA,CAEhCsC,CAAAA,EAAUvB,GAAW,CAACK,CAAAA,CAAc,UACvCrC,CAAAA,CAAqBuD,CAAAA,CAAQ,CAAE,OAAA,CAAApD,CAAAA,CAAS,IAAA,CAAAC,CAAK,CAAC,CAAA,CAC9CiC,EAAc,OAAA,CAAU,IAAA,CAAA,CAIzBV,EAAWC,CAAAA,CAAaX,CAAI,EAC7B,CAAA,CACA,CAACe,CAAAA,CAASJ,CAAAA,CAAazB,CAAAA,CAASC,CAAI,CACrC,CAAA,CA4EA,GAtEAlC,EAA0B,IAAM,CAC/B,IAAMsF,CAAAA,CAAkBX,CAAAA,CAAmB,OAAA,CACrCY,CAAAA,CAAsBX,CAAAA,CAAuB,OAAA,CAC7CY,GAAqBX,CAAAA,CAAsB,OAAA,CAE3CY,EAAiBH,CAAAA,EAAmB,CAACxB,EACrC4B,CAAAA,CACLH,CAAAA,GAAwBtB,CAAAA,EACxBuB,EAAAA,GAAuBtB,CAAAA,CAMxB,GAJAS,EAAmB,OAAA,CAAUb,CAAAA,CAC7Bc,CAAAA,CAAuB,OAAA,CAAUX,CAAAA,CACjCY,CAAAA,CAAsB,QAAUX,CAAAA,CAAAA,CAE5BuB,CAAAA,EAAkBC,CAAAA,IACrBvB,CAAAA,CAAc,OAAA,CAAU,KAAA,CACpBsB,GACHpB,CAAAA,CAAgB,OAAA,CAAU,MAC1BC,CAAAA,CAAe,OAAA,CAAU,MACfoB,CAAAA,EAA6BpB,CAAAA,CAAe,OAAA,GAAY,IAAA,GAElED,CAAAA,CAAgB,OAAA,CAAU,OAGvBE,CAAAA,CAAgB,OAAA,CAAA,CAAS,CAC5BO,CAAAA,CAAgB,KAAK,EAErB,MACD,CAID,GADI,CAAChB,CAAAA,EACDU,CAAAA,CAAc,OAElB,IAAMzB,CAAAA,CAAOuB,EAAe,OAAA,CACtBe,CAAAA,CAASvC,EAAiBC,CAAI,CAAA,CAOpC,GALIsC,CAAAA,EAAU,CAAClB,CAAAA,CAAc,UAC5BrC,CAAAA,CAAqBuD,CAAAA,CAAQ,CAAE,OAAA,CAAApD,CAAAA,CAAS,KAAAC,CAAK,CAAC,CAAA,CAC9CiC,CAAAA,CAAc,OAAA,CAAU,IAAA,CAAA,CAGrBE,EAAgB,OAAA,CAAS,CAC5B,GAAItB,CAAAA,GAAS,IAAA,EAAQ,CAACsC,CAAAA,CAAQ,CAC7BJ,CAAAA,CAAyB,aAAa,CAAA,CACtC,MACD,CACA,GAAIlC,CAAAA,GAAS,KACZ,OAIDsB,CAAAA,CAAgB,QAAU,MAC3B,CAIAY,CAAAA,CAAyB,aAAa,EACvC,CAAA,CAAG,CACFnB,CAAAA,CACAU,CAAAA,CACAP,EACAC,CAAAA,CACAjC,CAAAA,CACAC,EACA+C,CAAAA,CACAH,CACD,CAAC,CAAA,CAGG,CAAChB,CAAAA,CACJ,OAAOD,CAAAA,EAAY,IAAA,CAKpB,IAAM8B,EAAAA,CADezC,CAAAA,CAAQ,KAAA,CACU,WAAa,EAAA,CAG9C0C,CAAAA,CAAc,CAAC,sBAAA,CAAwB3D,CAAAA,EAAW,gBAAgB,EACtE,MAAA,CAAO,OAAO,EACd,IAAA,CAAK,GAAG,EAGJ4D,EAAAA,CAAmB,CAACD,CAAAA,CAAa,yBAAA,CAA2B7B,CAAS,CAAA,CACzE,OAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA,CAGJ+B,GAAkB,CACvBH,EAAAA,CACAC,CAAAA,CACA,oBAAA,CACA7B,CACD,CAAA,CACE,OAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA,CAEV,OACCgC,cAAAA,CAAC1G,CAAAA,CAAgB,QAAA,CAAhB,CAAyB,KAAA,CAAO,IAAA,CAC/B,SAAAmF,CAAAA,CACAuB,cAAAA,CAAC,OAAI,GAAA,CAAKX,CAAAA,CAAa,UAAWS,EAAAA,CAAkB,aAAA,CAAY,MAAA,CAC9D,QAAA,CAAA3C,CAAAA,CACF,CAAA,CAEA8C,mBAAa9C,CAAAA,CAAkD,CAC9D,IAAKkC,CAAAA,CACL,SAAA,CAAWU,GACX,aAAA,CAAe,IAChB,CAAC,CAAA,CAEH,CAEF,CCpOA,IAAMG,GAAc,cAAA,CACdC,EAAAA,CAAqB,SACrBC,EAAAA,CAAkB,CAAA,CAKxB,SAASC,EAAAA,CAAShG,CAAAA,CAAkD,CACnE,OAAO,CAAA,CAAQA,CAAAA,EAAU,OAAOA,CAAAA,EAAU,QAAA,EAAY,CAAC,KAAA,CAAM,OAAA,CAAQA,CAAK,CAC3E,CAEA,SAASiG,CAAAA,CAAejG,CAAAA,CAA8B,CACrD,GAAI,CAACgG,EAAAA,CAAShG,CAAK,EAAG,OAAO,GAC7B,IAAMkG,CAAAA,CAAuB,EAAC,CAC9B,IAAA,GAAW,CAACC,EAAKC,CAAW,CAAA,GAAK,OAAO,OAAA,CAAQpG,CAAK,EAChD,OAAOoG,CAAAA,EAAgB,QAAA,GAC1BF,CAAAA,CAAOC,CAAG,CAAA,CAAIC,GAGhB,OAAOF,CACR,CAEA,SAASG,EAAAA,CAAkBrG,EAA8B,CAExD,OAAIgG,EAAAA,CAAShG,CAAK,CAAA,EAAKA,CAAAA,CAAM,IAAM+F,EAAAA,CAC3BE,CAAAA,CAAejG,EAAM,MAAM,CAAA,CAI5BiG,EAAejG,CAAK,CAC5B,CAEA,SAASsG,EAAAA,CAAwBH,CAAAA,CAA2B,CAC3D,GAAI,OAAO,aAAiB,GAAA,CAAa,OAAO,EAAC,CACjD,GAAI,CACH,IAAMI,CAAAA,CAAM,YAAA,CAAa,QAAQJ,CAAG,CAAA,CACpC,OAAII,CAAAA,GAAQ,IAAA,CAAa,EAAC,CACnBF,EAAAA,CAAkB,IAAA,CAAK,KAAA,CAAME,CAAG,CAAC,CACzC,CAAA,KAAQ,CACP,OAAO,EACR,CACD,CAEA,SAASC,EAAAA,CAAkBC,CAAAA,CAA4B,CACtD,GAAI,OAAO,YAAA,CAAiB,GAAA,CAAa,OACzC,IAAMC,CAAAA,CAA2B,CAAE,EAAGX,EAAAA,CAAiB,MAAA,CAAAU,CAAO,CAAA,CAC9D,GAAI,CACH,aAAa,OAAA,CAAQZ,EAAAA,CAAa,KAAK,SAAA,CAAUa,CAAO,CAAC,EAC1D,CAAA,KAAQ,CAER,CACD,CAEA,SAASC,IAA0C,CAClD,GAAI,OAAO,YAAA,CAAiB,GAAA,CAAa,OAAO,EAAC,CAEjD,GAAI,CACH,IAAMC,CAAAA,CAAS,aAAa,OAAA,CAAQf,EAAW,EAC/C,GAAIe,CAAAA,GAAW,KACd,OAAOP,EAAAA,CAAkB,IAAA,CAAK,KAAA,CAAMO,CAAM,CAAC,EAI5C,IAAMC,CAAAA,CAAeP,GAAwBR,EAAkB,CAAA,CAC/D,OAAI,MAAA,CAAO,IAAA,CAAKe,CAAY,CAAA,CAAE,MAAA,CAAS,CAAA,EACtCL,GAAkBK,CAAY,CAAA,CAExBA,CACR,CAAA,KAAQ,CACP,OAAO,EACR,CACD,CAEA,SAASC,EAAAA,CAAeX,EAA4B,CAEnD,IAAMnG,EADS2G,EAAAA,EAAgB,CACVR,CAAG,CAAA,CACxB,OAAO,OAAOnG,CAAAA,EAAU,QAAA,CAAWA,CAAAA,CAAQ,IAC5C,CAEA,SAAS+G,GAAeZ,CAAAA,CAAaa,CAAAA,CAAqB,CACzD,GAAI,EAAA,OAAO,YAAA,CAAiB,GAAA,CAAA,CAE5B,GAAI,CACH,IAAMP,CAAAA,CAASE,EAAAA,EAAgB,CAC/BF,CAAAA,CAAON,CAAG,CAAA,CAAIa,EACdR,EAAAA,CAAkBC,CAAM,EACzB,CAAA,KAAQ,CAER,CACD,CAWO,SAASQ,CAAAA,CAAkB,CACjC,UAAA,CAAAC,CAAAA,CACA,aAAAC,CAAAA,CAAe,CAAA,CACf,YAAA,CAAAC,CAAAA,CACA,OAAA,CAAA1D,CAAAA,CACA,SAAA2D,CAAAA,CAAW,CAAA,CACX,SAAAC,CACD,CAAA,CAAqC,CAGpC,GAAM,CAACN,CAAAA,CAAOO,CAAQ,CAAA,CAAIjD,cAAAA,CAAiB,IAC1CkD,CAAAA,CAAWL,CAAAA,CAAcE,EAAUC,CAAQ,CAC5C,EAEMG,CAAAA,CAAezD,YAAAA,CAAO,KAAK,CAAA,CAEjC,OAAApE,CAAAA,CAA0B,IAAM,CAC/B,GAAI,CAACsH,CAAAA,CAAY,OACjB,IAAMQ,CAAAA,CAASZ,EAAAA,CAAeI,CAAU,CAAA,CACxC,GAAIQ,CAAAA,GAAW,KAAM,OACrB,IAAM9C,EAAO4C,CAAAA,CAAWE,CAAAA,CAAQL,EAAUC,CAAQ,CAAA,CAClDC,CAAAA,CAAUI,CAAAA,EAAU,MAAA,CAAO,EAAA,CAAGA,EAAM/C,CAAI,CAAA,CAAI+C,EAAO/C,CAAK,EACzD,EAAG,CAACsC,CAAAA,CAAYG,CAAAA,CAAUC,CAAQ,CAAC,CAAA,CAEnCxH,gBAAU,IAAM,CACf,GAAI,CAAC4D,CAAAA,EAAW0D,IAAiB,MAAA,CAAW,CAC3C,IAAMQ,CAAAA,CAAWJ,CAAAA,CAAWJ,CAAAA,CAAcC,EAAUC,CAAQ,CAAA,CAC5DC,CAAAA,CAASK,CAAQ,CAAA,CAEbV,CAAAA,EACHH,GAAeG,CAAAA,CAAYU,CAAQ,EAErC,CACD,CAAA,CAAG,CAAClE,EAAS0D,CAAAA,CAAcF,CAAAA,CAAYG,EAAUC,CAAQ,CAAC,EAE1DxH,eAAAA,CAAU,IAAM,CACXT,CAAAA,EAAS,EAAK,CAAC6H,GAAc,CAACO,CAAAA,CAAa,UAC9C,OAAA,CAAQ,IAAA,CACP,mIAED,CAAA,CACAA,CAAAA,CAAa,OAAA,CAAU,IAAA,EAEzB,CAAA,CAAG,CAACP,CAAU,CAAC,CAAA,CAERF,CACR,CAEA,SAASQ,EACRxH,CAAAA,CACA6H,CAAAA,CACAC,CAAAA,CACS,CACT,IAAI5B,CAAAA,CAAS,KAAK,GAAA,CAAIlG,CAAAA,CAAO6H,CAAG,CAAA,CAChC,OAAIC,IAAQ,MAAA,GACX5B,CAAAA,CAAS,IAAA,CAAK,GAAA,CAAIA,CAAAA,CAAQ4B,CAAG,GAEvB5B,CACR,CCnIO,SAAS6B,EAAAA,CAAqB,CACpC,OAAA,CAAArE,EAAU,KAAA,CACV,KAAA,CAAAsE,EACA,UAAA,CAAAC,CAAAA,CACA,eAAAC,CAAAA,CACA,UAAA,CAAAhB,CAAAA,CACA,YAAA,CAAAC,CAAAA,CAAe,CAAA,CACf,SAAAE,CAAAA,CAAW,CAAA,CACX,SAAAC,CAAAA,CACA,OAAA,CAAAzF,EAAU,IAAA,CACV,IAAA,CAAAC,CAAAA,CACA,kBAAA,CAAA8B,CAAAA,CAAqB,KAAA,CACrB,aAAAuE,CAAAA,CAAe,CAACC,CAAAA,CAAG7G,CAAAA,GAAUA,CAC9B,CAAA,CAAmD,CAClD,IAAM8G,CAAAA,CAAgBpB,CAAAA,CAAkB,CACvC,UAAA,CAAAC,CAAAA,CACA,aAAAC,CAAAA,CACA,YAAA,CAAca,GAAO,MAAA,CACrB,OAAA,CAAAtE,EACA,QAAA,CAAA2D,CAAAA,CACA,QAAA,CAAAC,CACD,CAAC,CAAA,CAED,GAAI5D,CAAAA,CAAS,CACZ,IAAM4E,CAAAA,CAAY,IAAI,MAAMD,CAAa,CAAA,CACzC,IAAA,IAAS9G,CAAAA,CAAQ,CAAA,CAAGA,CAAAA,CAAQ8G,EAAe9G,CAAAA,EAAS,CAAA,CAAG,CACtD,IAAMgH,CAAAA,CAAWzG,IAAS,MAAA,CAAY,CAAA,EAAGP,CAAK,CAAA,CAAA,CAAK,CAAA,EAAGO,CAAI,IAAIP,CAAK,CAAA,CAAA,CACnE+G,EAAU/G,CAAK,CAAA,CACdoE,eAACnC,CAAAA,CAAA,CAEA,OAAA,CAAS,IAAA,CACT,OAAA,CAAS0E,CAAAA,CAAe3G,CAAK,CAAA,CAC7B,OAAA,CAASM,EACT,IAAA,CAAM0G,CAAAA,CACN,mBAAoB3E,CAAAA,CAAAA,CALf,CAAA,SAAA,EAAYrC,CAAK,CAAA,CAMvB,EAEF,CACA,OAAOoE,cAAAA,CAAA6C,mBAAAA,CAAA,CAAG,QAAA,CAAAF,CAAAA,CAAU,CACrB,CAEA,OAAI,CAACN,CAAAA,EAASA,CAAAA,CAAM,MAAA,GAAW,EACvB,IAAA,CAIPrC,cAAAA,CAAA6C,oBAAA,CACE,QAAA,CAAAR,EAAM,GAAA,CAAI,CAACS,CAAAA,CAAMlH,CAAAA,GACjBoE,cAAAA,CAAC6C,cAAAA,CAAA,CACC,QAAA,CAAAP,CAAAA,CAAWQ,CAAAA,CAAMlH,CAAK,CAAA,CAAA,CADT4G,CAAAA,CAAaM,EAAMlH,CAAK,CAEvC,CACA,CAAA,CACF,CAEF","file":"index.cjs","sourcesContent":["import { createContext, useContext } from \"react\";\n\nexport const SkeletonContext = createContext(false);\n\nexport function useIsSkeletonMode(): boolean {\n\treturn useContext(SkeletonContext);\n}\n","export function isDevEnv(): boolean {\n\tconst maybeGlobal = globalThis as unknown as Record<string, unknown>;\n\n\t// Manual override for environments where NODE_ENV isn't injected.\n\t// Example: `globalThis.__REACT_LOADED_DEV__ = true`.\n\tconst override = maybeGlobal.__REACT_LOADED_DEV__;\n\tif (typeof override === \"boolean\") return override;\n\n\t// Common global used by some toolchains/runtimes.\n\tconst devFlag = maybeGlobal.__DEV__;\n\tif (typeof devFlag === \"boolean\") return devFlag;\n\n\tconst maybeProcess = (globalThis as unknown as { process?: unknown }).process;\n\tconst nodeEnv =\n\t\ttypeof maybeProcess === \"object\" && maybeProcess !== null\n\t\t\t? (maybeProcess as { env?: { NODE_ENV?: unknown } }).env?.NODE_ENV\n\t\t\t: undefined;\n\n\tif (typeof nodeEnv === \"string\") {\n\t\treturn nodeEnv !== \"production\";\n\t}\n\n\t// No environment detected — assume production (convention: opt-in to dev mode).\n\treturn false;\n}\n","import { useEffect, useLayoutEffect } from \"react\";\n\nconst canUseDOM =\n\ttypeof globalThis !== \"undefined\" &&\n\ttypeof (globalThis as { document?: unknown }).document !== \"undefined\";\n\nexport const useIsomorphicLayoutEffect = canUseDOM\n\t? useLayoutEffect\n\t: useEffect;\n","// Text width configuration (in ch units)\nconst TEXT_WIDTH_MIN_CH = 6;\nconst TEXT_WIDTH_MAX_CH = 40;\n\nfunction isElement(value: unknown): value is Element {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst maybeElement = value as Element;\n\t// Must have nodeType 1 (Element) and a working querySelectorAll\n\tif (maybeElement.nodeType !== 1) return false;\n\tif (typeof maybeElement.tagName !== \"string\") return false;\n\tif (typeof maybeElement.querySelectorAll !== \"function\") return false;\n\t// Additional check: instanceof Element if available\n\tif (typeof Element !== \"undefined\" && !(value instanceof Element)) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function isUsableElement(value: unknown): value is Element {\n\tif (!isElement(value)) return false;\n\t// Test that querySelectorAll actually works\n\ttry {\n\t\t(value as Element).querySelectorAll(\"*\");\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nconst MEDIA_ELEMENTS = new Set([\"IMG\", \"VIDEO\", \"CANVAS\"]);\nconst SVG_ELEMENTS = new Set([\"SVG\"]);\n\nconst INTERACTIVE_ELEMENTS = new Set([\n\t\"BUTTON\",\n\t\"INPUT\",\n\t\"TEXTAREA\",\n\t\"SELECT\",\n\t\"A\",\n]);\n\nconst BUTTON_LIKE_SELECTOR = \"button,input,textarea,select,a,[role='button']\";\nconst SKIPPED_TAGS = new Set([\n\t\"SCRIPT\",\n\t\"STYLE\",\n\t\"LINK\",\n\t\"META\",\n\t\"NOSCRIPT\",\n\t\"TEMPLATE\",\n]);\n\nfunction getTagName(el: Element): string {\n\treturn el.tagName.toUpperCase();\n}\n\nfunction isButtonLikeElement(el: Element, tagName = getTagName(el)): boolean {\n\tif (INTERACTIVE_ELEMENTS.has(tagName)) return true;\n\tconst role = el.getAttribute(\"role\");\n\treturn role === \"button\";\n}\n\nfunction isButtonLikeDescendant(el: Element, tagName: string): boolean {\n\tconst closestButton = el.closest(BUTTON_LIKE_SELECTOR);\n\treturn Boolean(closestButton && !isButtonLikeElement(el, tagName));\n}\n\nfunction isContentElement(el: Element, tagName = getTagName(el)): boolean {\n\tif (MEDIA_ELEMENTS.has(tagName)) return true;\n\tif (SVG_ELEMENTS.has(tagName)) return true;\n\tif (isButtonLikeElement(el, tagName)) return true;\n\n\tconst isLeafNode = el.childElementCount === 0;\n\n\t// Text elements that are leaf nodes (no child elements, only text)\n\tif (isLeafNode && el.textContent?.trim()) return true;\n\n\treturn false;\n}\n\n/**\n * Calculate text skeleton width in ch units based on text content.\n * Uses a deterministic jitter: widthCh = clamp(6, 40, len + 2 + jitter)\n */\nfunction calculateTextWidthCh(text: string, seedKey: string): number {\n\tconst textLength = text.length;\n\tconst jitterRange = Math.max(4, 0.8 * textLength);\n\tconst jitter = deterministicJitter(seedKey) * jitterRange;\n\tconst width = textLength + 2 + jitter;\n\treturn Math.max(TEXT_WIDTH_MIN_CH, Math.min(TEXT_WIDTH_MAX_CH, width));\n}\n\nfunction deterministicJitter(seedKey: string): number {\n\tif (!seedKey) return 0;\n\tlet hash = 2166136261;\n\tfor (let index = 0; index < seedKey.length; index += 1) {\n\t\thash ^= seedKey.charCodeAt(index);\n\t\thash = Math.imul(hash, 16777619);\n\t}\n\tconst normalized = (hash >>> 0) / 0xffffffff;\n\treturn normalized * 2 - 1;\n}\n\nfunction resolveTextAlign(el: HTMLElement): \"left\" | \"center\" | \"right\" {\n\tconst align = globalThis.getComputedStyle(el).textAlign;\n\tif (align === \"center\") return \"center\";\n\tif (align === \"right\" || align === \"end\") return \"right\";\n\treturn \"left\";\n}\n\nexport function applySkeletonClasses(\n\trootElement: Element,\n\toptions: { animate?: boolean; seed?: string | number } = {},\n): void {\n\tconst { animate = true, seed } = options;\n\tconst baseSeed =\n\t\tseed === undefined || seed === null ? \"loaded\" : String(seed);\n\n\tif (!isElement(rootElement)) {\n\t\treturn;\n\t}\n\n\tconst htmlRoot = rootElement as HTMLElement;\n\n\t// Apply skeleton mode to the root element\n\thtmlRoot.classList.add(\"loaded-skeleton-mode\");\n\n\tif (animate) {\n\t\thtmlRoot.classList.add(\"loaded-animate\");\n\t}\n\n\t// Apply background class for standalone usage (when not used via SmartSkeleton JSX)\n\t// If element has loaded-skeleton-wrapper, CSS handles bg via > :first-child rule\n\t// If element already has loaded-skeleton-bg (from JSX), this is a no-op\n\tconst isWrapper = htmlRoot.classList.contains(\"loaded-skeleton-wrapper\");\n\tif (!isWrapper) {\n\t\thtmlRoot.classList.add(\"loaded-skeleton-bg\");\n\t}\n\n\t// Only add specific classes where needed (text, media, content)\n\tconst descendants = rootElement.getElementsByTagName(\"*\");\n\n\tlet textIndex = 0;\n\n\tconst processElement = (el: Element) => {\n\t\tconst tagName = getTagName(el);\n\t\tif (SKIPPED_TAGS.has(tagName)) return;\n\t\tif (!isContentElement(el, tagName)) return;\n\n\t\tconst htmlEl = el as HTMLElement;\n\t\tconst isInsideButtonLike = isButtonLikeDescendant(el, tagName);\n\t\tif (isInsideButtonLike) {\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-force-hide\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst textContent = el.textContent?.trim();\n\t\tconst isLeafWithText = el.childElementCount === 0 && textContent;\n\n\t\tif (\n\t\t\tisLeafWithText &&\n\t\t\t!MEDIA_ELEMENTS.has(tagName) &&\n\t\t\t!SVG_ELEMENTS.has(tagName) &&\n\t\t\t!isButtonLikeElement(el, tagName)\n\t\t) {\n\t\t\t// Text elements: overlay bar with ch-based width\n\t\t\thtmlEl.classList.add(\"loaded-text-skeleton\");\n\t\t\thtmlEl.dataset.skeletonAlign = resolveTextAlign(htmlEl);\n\t\t\tconst seedKey = `${baseSeed}|${textIndex}|${textContent ?? \"\"}`;\n\t\t\ttextIndex += 1;\n\t\t\tconst widthCh = calculateTextWidthCh(textContent ?? \"\", seedKey);\n\t\t\thtmlEl.style.setProperty(\"--skeleton-text-width\", `${widthCh}ch`);\n\t\t} else if (MEDIA_ELEMENTS.has(tagName)) {\n\t\t\t// Media elements\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-media\");\n\t\t} else if (SVG_ELEMENTS.has(tagName)) {\n\t\t\t// SVG elements rendered as rounded content blocks\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-content\");\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-svg\");\n\t\t} else {\n\t\t\t// Interactive elements (buttons, inputs, etc.)\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-content\");\n\t\t\t// Prevent keyboard focus / interaction while in skeleton mode.\n\t\t\t// aria-hidden does not remove elements from the tab order.\n\t\t\thtmlEl.setAttribute(\"tabindex\", \"-1\");\n\t\t}\n\t};\n\n\tprocessElement(rootElement);\n\tfor (const el of descendants) {\n\t\tprocessElement(el);\n\t}\n}\n","import { type ReactElement, type Ref, version as reactVersion } from \"react\";\nimport { isUsableElement } from \"./applySkeletonClasses\";\n\nexport const REACT_MAJOR_VERSION = Number.parseInt(reactVersion, 10);\nconst IS_REACT_19_OR_NEWER =\n\tNumber.isFinite(REACT_MAJOR_VERSION) && REACT_MAJOR_VERSION >= 19;\n\nexport function resolveRefTarget(node: unknown): Element | null {\n\tif (isUsableElement(node)) return node;\n\tif (node && typeof node === \"object\" && \"nativeElement\" in node) {\n\t\tconst nativeElement = (node as { nativeElement?: unknown }).nativeElement;\n\t\tif (isUsableElement(nativeElement)) return nativeElement;\n\t}\n\treturn null;\n}\n\nexport function getElementDisplayName(element: ReactElement): string {\n\tconst type = element.type;\n\tif (typeof type === \"string\") {\n\t\treturn `<${type}>`;\n\t}\n\tif (typeof type === \"function\") {\n\t\tconst fn = type as { displayName?: string; name?: string };\n\t\treturn `<${fn.displayName || fn.name || \"Unknown\"}>`;\n\t}\n\tif (typeof type === \"object\" && type !== null) {\n\t\tconst obj = type as { displayName?: string; name?: string };\n\t\treturn `<${obj.displayName || obj.name || \"Unknown\"}>`;\n\t}\n\treturn \"<Unknown>\";\n}\n\n/**\n * Get the original ref from the element, supporting both React 18 and React 19.\n * React 19: ref is a regular prop on element.props.ref\n * React 18: ref is on element.ref\n */\nexport function getOriginalRef(\n\telement: ReactElement,\n): Ref<unknown> | undefined {\n\t// React 19 style (ref as prop)\n\tconst elementProps = element.props as { ref?: Ref<unknown> } | undefined;\n\tconst propsRef = elementProps?.ref;\n\tif (propsRef !== undefined) return propsRef;\n\n\t// React 19+ warns on element.ref access; skip legacy fallback entirely.\n\tif (IS_REACT_19_OR_NEWER) return undefined;\n\n\t// React 18 style\n\tconst legacyRef = (element as ReactElement & { ref?: Ref<unknown> }).ref;\n\tif (legacyRef !== undefined) return legacyRef;\n\n\treturn undefined;\n}\n\n/**\n * Forward a ref value to the original ref (callback or object style).\n */\nexport function forwardRef(\n\toriginalRef: Ref<unknown> | undefined,\n\tnode: unknown,\n) {\n\tif (!originalRef) return;\n\tif (typeof originalRef === \"function\") {\n\t\toriginalRef(node);\n\t} else {\n\t\t(originalRef as React.MutableRefObject<unknown>).current = node;\n\t}\n}\n","import {\n\tcloneElement,\n\ttype ReactElement,\n\tuseCallback,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { isDevEnv } from \"../../utils/isDevEnv\";\nimport { useIsomorphicLayoutEffect } from \"../../utils/useIsomorphicLayoutEffect\";\nimport { SkeletonContext } from \"../SkeletonContext/SkeletonContext\";\nimport { applySkeletonClasses } from \"./applySkeletonClasses\";\nimport {\n\tforwardRef,\n\tgetElementDisplayName,\n\tgetOriginalRef,\n\tresolveRefTarget,\n} from \"./refUtils\";\nimport \"./SmartSkeleton.css\";\n\nexport { applySkeletonClasses } from \"./applySkeletonClasses\";\n\nconst warnedComponents = new Set<string>();\n\nexport interface SmartSkeletonProps {\n\t/** The skeleton element with mock data, rendered when loading */\n\telement: ReactElement;\n\t/** The real content to render when not loading. If omitted, returns null when loading=false. */\n\tchildren?: ReactElement;\n\t/** Whether the skeleton is currently loading. Default: false */\n\tloading?: boolean;\n\t/** Enable shimmer animation. Default: true */\n\tanimate?: boolean;\n\t/** Additional CSS class name */\n\tclassName?: string;\n\t/** Optional seed to stabilize skeleton text widths */\n\tseed?: string | number;\n\t/** Suppress warning when auto-wrapper is applied. Default: false */\n\tsuppressRefWarning?: boolean;\n}\n\nexport function SmartSkeleton({\n\telement,\n\tchildren,\n\tloading = false,\n\tanimate = true,\n\tclassName = \"\",\n\tseed,\n\tsuppressRefWarning = false,\n}: SmartSkeletonProps): ReactElement | null {\n\tconst currentElementType = element.type;\n\tconst currentElementKey = element.key ?? null;\n\tconst hasAppliedRef = useRef(false);\n\tconst refWasCalledRef = useRef(false);\n\tconst lastRefNodeRef = useRef<unknown>(null);\n\tconst needsWrapperRef = useRef(false);\n\tconst [needsWrapper, setNeedsWrapper] = useState(false);\n\tconst previousLoadingRef = useRef(loading);\n\tconst previousElementTypeRef =\n\t\tuseRef<ReactElement[\"type\"]>(currentElementType);\n\tconst previousElementKeyRef = useRef<ReactElement[\"key\"] | null>(\n\t\tcurrentElementKey,\n\t);\n\n\tconst setWrapperState = useCallback((next: boolean) => {\n\t\tneedsWrapperRef.current = next;\n\t\tsetNeedsWrapper(next);\n\t}, []);\n\n\tconst originalRef = getOriginalRef(element);\n\n\tconst enableWrapperWithWarning = useCallback(\n\t\t(reason: \"non-dom-ref\" | \"no-ref-call\") => {\n\t\t\tif (!needsWrapperRef.current) {\n\t\t\t\tsetWrapperState(true);\n\t\t\t}\n\n\t\t\tif (!suppressRefWarning && isDevEnv()) {\n\t\t\t\tconst displayName = getElementDisplayName(element);\n\t\t\t\tif (!warnedComponents.has(displayName)) {\n\t\t\t\t\tif (reason === \"non-dom-ref\") {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[SmartSkeleton] ${displayName} does not forward its ref to a DOM element. ` +\n\t\t\t\t\t\t\t\t`A wrapper <div> has been added automatically. Use forwardRef to avoid this.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[SmartSkeleton] ${displayName} does not accept a ref. ` +\n\t\t\t\t\t\t\t\t`A wrapper <div> has been added automatically. Use forwardRef to avoid this.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\twarnedComponents.add(displayName);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[element, suppressRefWarning, setWrapperState],\n\t);\n\n\tconst refCallback = useCallback(\n\t\t(node: unknown) => {\n\t\t\trefWasCalledRef.current = true;\n\t\t\tlastRefNodeRef.current = node;\n\n\t\t\tconst target = resolveRefTarget(node);\n\n\t\t\tif (target && loading && !hasAppliedRef.current) {\n\t\t\t\tapplySkeletonClasses(target, { animate, seed });\n\t\t\t\thasAppliedRef.current = true;\n\t\t\t}\n\n\t\t\t// Forward ref to original element\n\t\t\tforwardRef(originalRef, node);\n\t\t},\n\t\t[loading, originalRef, animate, seed],\n\t);\n\n\t// Single layout effect: handles identity reset AND wrapper fallback decision.\n\t// Merged into one effect because React fires ref callbacks (during commit)\n\t// BEFORE layout effects. Having a separate reset effect would clear the ref\n\t// data that was just written by the current commit's ref callbacks.\n\tuseIsomorphicLayoutEffect(() => {\n\t\tconst previousLoading = previousLoadingRef.current;\n\t\tconst previousElementType = previousElementTypeRef.current;\n\t\tconst previousElementKey = previousElementKeyRef.current;\n\n\t\tconst didExitLoading = previousLoading && !loading;\n\t\tconst hasElementIdentityChanged =\n\t\t\tpreviousElementType !== currentElementType ||\n\t\t\tpreviousElementKey !== currentElementKey;\n\n\t\tpreviousLoadingRef.current = loading;\n\t\tpreviousElementTypeRef.current = currentElementType;\n\t\tpreviousElementKeyRef.current = currentElementKey;\n\n\t\tif (didExitLoading || hasElementIdentityChanged) {\n\t\t\thasAppliedRef.current = false;\n\t\t\tif (didExitLoading) {\n\t\t\t\trefWasCalledRef.current = false;\n\t\t\t\tlastRefNodeRef.current = null;\n\t\t\t} else if (hasElementIdentityChanged && lastRefNodeRef.current === null) {\n\t\t\t\t// Ignore cleanup-only ref callbacks from previous element identity.\n\t\t\t\trefWasCalledRef.current = false;\n\t\t\t}\n\n\t\t\tif (needsWrapperRef.current) {\n\t\t\t\tsetWrapperState(false);\n\t\t\t\t// Re-render will re-run this effect with the direct path.\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (!loading) return;\n\t\tif (needsWrapper) return;\n\n\t\tconst node = lastRefNodeRef.current;\n\t\tconst target = resolveRefTarget(node);\n\n\t\tif (target && !hasAppliedRef.current) {\n\t\t\tapplySkeletonClasses(target, { animate, seed });\n\t\t\thasAppliedRef.current = true;\n\t\t}\n\n\t\tif (refWasCalledRef.current) {\n\t\t\tif (node !== null && !target) {\n\t\t\t\tenableWrapperWithWarning(\"non-dom-ref\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (node !== null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Ref callback was only invoked with null during cleanup.\n\t\t\t// Treat as a missing ref call for the current element.\n\t\t\trefWasCalledRef.current = false;\n\t\t}\n\n\t\t// Ref was not called: the component doesn't accept refs.\n\t\t// Switch to wrapper mode synchronously (before browser paint).\n\t\tenableWrapperWithWarning(\"no-ref-call\");\n\t}, [\n\t\tloading,\n\t\tneedsWrapper,\n\t\tcurrentElementType,\n\t\tcurrentElementKey,\n\t\tanimate,\n\t\tseed,\n\t\tenableWrapperWithWarning,\n\t\tsetWrapperState,\n\t]);\n\n\t// Not loading: return children or null\n\tif (!loading) {\n\t\treturn children ?? null;\n\t}\n\n\t// Build merged className for skeleton mode\n\tconst elementProps = element.props as { className?: string };\n\tconst existingClassName = elementProps.className ?? \"\";\n\n\t// Base classes for skeleton mode\n\tconst baseClasses = [\"loaded-skeleton-mode\", animate && \"loaded-animate\"]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\t// When wrapping: wrapper gets mode + wrapper marker (no bg - it goes on child via ref)\n\tconst wrapperClassName = [baseClasses, \"loaded-skeleton-wrapper\", className]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\t// When not wrapping: element gets mode + bg directly (for SSR)\n\tconst mergedClassName = [\n\t\texistingClassName,\n\t\tbaseClasses,\n\t\t\"loaded-skeleton-bg\",\n\t\tclassName,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\treturn (\n\t\t<SkeletonContext.Provider value={true}>\n\t\t\t{needsWrapper ? (\n\t\t\t\t<div ref={refCallback} className={wrapperClassName} aria-hidden=\"true\">\n\t\t\t\t\t{element}\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\tcloneElement(element as ReactElement<Record<string, unknown>>, {\n\t\t\t\t\tref: refCallback,\n\t\t\t\t\tclassName: mergedClassName,\n\t\t\t\t\t\"aria-hidden\": true,\n\t\t\t\t})\n\t\t\t)}\n\t\t</SkeletonContext.Provider>\n\t);\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { isDevEnv } from \"../../utils/isDevEnv\";\nimport { useIsomorphicLayoutEffect } from \"../../utils/useIsomorphicLayoutEffect\";\n\nconst STORAGE_KEY = \"react-loaded\";\nconst LEGACY_STORAGE_KEY = \"loaded\";\nconst STORAGE_VERSION = 1 as const;\n\ntype StoredCounts = Record<string, number>;\ntype StoredPayloadV1 = { v: typeof STORAGE_VERSION; counts: StoredCounts };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction toNumberRecord(value: unknown): StoredCounts {\n\tif (!isRecord(value)) return {};\n\tconst result: StoredCounts = {};\n\tfor (const [key, maybeNumber] of Object.entries(value)) {\n\t\tif (typeof maybeNumber === \"number\") {\n\t\t\tresult[key] = maybeNumber;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction parseStoredCounts(value: unknown): StoredCounts {\n\t// Current schema: { v: 1, counts: Record<string, number> }\n\tif (isRecord(value) && value.v === STORAGE_VERSION) {\n\t\treturn toNumberRecord(value.counts);\n\t}\n\n\t// Legacy schema: Record<string, number>\n\treturn toNumberRecord(value);\n}\n\nfunction readStoredCountsFromKey(key: string): StoredCounts {\n\tif (typeof localStorage === \"undefined\") return {};\n\ttry {\n\t\tconst raw = localStorage.getItem(key);\n\t\tif (raw === null) return {};\n\t\treturn parseStoredCounts(JSON.parse(raw));\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction writeStoredCounts(counts: StoredCounts): void {\n\tif (typeof localStorage === \"undefined\") return;\n\tconst payload: StoredPayloadV1 = { v: STORAGE_VERSION, counts };\n\ttry {\n\t\tlocalStorage.setItem(STORAGE_KEY, JSON.stringify(payload));\n\t} catch {\n\t\t// Silently fail if localStorage is full or unavailable\n\t}\n}\n\nfunction getStoredCounts(): Record<string, number> {\n\tif (typeof localStorage === \"undefined\") return {};\n\n\ttry {\n\t\tconst rawNew = localStorage.getItem(STORAGE_KEY);\n\t\tif (rawNew !== null) {\n\t\t\treturn parseStoredCounts(JSON.parse(rawNew));\n\t\t}\n\n\t\t// Backward compatibility: migrate legacy key once if present.\n\t\tconst legacyCounts = readStoredCountsFromKey(LEGACY_STORAGE_KEY);\n\t\tif (Object.keys(legacyCounts).length > 0) {\n\t\t\twriteStoredCounts(legacyCounts);\n\t\t}\n\t\treturn legacyCounts;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction getStoredCount(key: string): number | null {\n\tconst counts = getStoredCounts();\n\tconst value = counts[key];\n\treturn typeof value === \"number\" ? value : null;\n}\n\nfunction setStoredCount(key: string, count: number): void {\n\tif (typeof localStorage === \"undefined\") return;\n\n\ttry {\n\t\tconst counts = getStoredCounts();\n\t\tcounts[key] = count;\n\t\twriteStoredCounts(counts);\n\t} catch {\n\t\t// Silently fail if localStorage is full or unavailable\n\t}\n}\n\nexport interface UsePersistedCountOptions {\n\tstorageKey?: string;\n\tdefaultCount?: number;\n\tcurrentCount?: number;\n\tloading: boolean;\n\tminCount?: number;\n\tmaxCount?: number;\n}\n\nexport function usePersistedCount({\n\tstorageKey,\n\tdefaultCount = 3,\n\tcurrentCount,\n\tloading,\n\tminCount = 1,\n\tmaxCount,\n}: UsePersistedCountOptions): number {\n\t// Always start from the default to match SSR output, then (on the client)\n\t// sync to the persisted value in a layout effect before first paint.\n\tconst [count, setCount] = useState<number>(() =>\n\t\tclampCount(defaultCount, minCount, maxCount),\n\t);\n\n\tconst hasWarnedRef = useRef(false);\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tif (!storageKey) return;\n\t\tconst stored = getStoredCount(storageKey);\n\t\tif (stored === null) return;\n\t\tconst next = clampCount(stored, minCount, maxCount);\n\t\tsetCount((prev) => (Object.is(prev, next) ? prev : next));\n\t}, [storageKey, minCount, maxCount]);\n\n\tuseEffect(() => {\n\t\tif (!loading && currentCount !== undefined) {\n\t\t\tconst newCount = clampCount(currentCount, minCount, maxCount);\n\t\t\tsetCount(newCount);\n\n\t\t\tif (storageKey) {\n\t\t\t\tsetStoredCount(storageKey, newCount);\n\t\t\t}\n\t\t}\n\t}, [loading, currentCount, storageKey, minCount, maxCount]);\n\n\tuseEffect(() => {\n\t\tif (isDevEnv() && !storageKey && !hasWarnedRef.current) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[Loaded] SmartSkeletonList used without storageKey. \" +\n\t\t\t\t\t\"The count will reset on remount. Add a storageKey to persist across sessions.\",\n\t\t\t);\n\t\t\thasWarnedRef.current = true;\n\t\t}\n\t}, [storageKey]);\n\n\treturn count;\n}\n\nfunction clampCount(\n\tvalue: number,\n\tmin: number,\n\tmax: number | undefined,\n): number {\n\tlet result = Math.max(value, min);\n\tif (max !== undefined) {\n\t\tresult = Math.min(result, max);\n\t}\n\treturn result;\n}\n","import { Fragment, type ReactElement } from \"react\";\nimport { usePersistedCount } from \"../../hooks/usePersistedCount/usePersistedCount\";\nimport { SmartSkeleton } from \"../SmartSkeleton/SmartSkeleton\";\n\nexport interface SmartSkeletonListProps<T> {\n\t/** Whether the list is currently loading. Default: false */\n\tloading?: boolean;\n\t/** The items to render. Pass undefined while loading. */\n\titems: T[] | undefined;\n\t/** Render function for each item when loaded */\n\trenderItem: (item: T, index: number) => ReactElement;\n\t/** Render function for skeleton placeholders */\n\trenderSkeleton: (index: number) => ReactElement;\n\t/** Key for localStorage persistence. Without it, count resets on remount. */\n\tstorageKey?: string;\n\t/** Initial skeleton count before any data is known. Default: 3 */\n\tdefaultCount?: number;\n\t/** Minimum skeletons to show. Default: 1 */\n\tminCount?: number;\n\t/** Maximum skeletons to show */\n\tmaxCount?: number;\n\t/** Enable shimmer animation. Default: true */\n\tanimate?: boolean;\n\t/** Optional seed to stabilize skeleton text widths */\n\tseed?: string | number;\n\t/** Suppress warning when auto-wrapper is applied. Default: false */\n\tsuppressRefWarning?: boolean;\n\t/** Extract unique key for each item. Default: index */\n\tkeyExtractor?: (item: T, index: number) => string | number;\n}\n\nexport function SmartSkeletonList<T>({\n\tloading = false,\n\titems,\n\trenderItem,\n\trenderSkeleton,\n\tstorageKey,\n\tdefaultCount = 3,\n\tminCount = 1,\n\tmaxCount,\n\tanimate = true,\n\tseed,\n\tsuppressRefWarning = false,\n\tkeyExtractor = (_, index) => index,\n}: SmartSkeletonListProps<T>): ReactElement | null {\n\tconst skeletonCount = usePersistedCount({\n\t\tstorageKey,\n\t\tdefaultCount,\n\t\tcurrentCount: items?.length,\n\t\tloading,\n\t\tminCount,\n\t\tmaxCount,\n\t});\n\n\tif (loading) {\n\t\tconst skeletons = new Array(skeletonCount);\n\t\tfor (let index = 0; index < skeletonCount; index += 1) {\n\t\t\tconst itemSeed = seed === undefined ? `${index}` : `${seed}:${index}`;\n\t\t\tskeletons[index] = (\n\t\t\t\t<SmartSkeleton\n\t\t\t\t\tkey={`skeleton-${index}`}\n\t\t\t\t\tloading={true}\n\t\t\t\t\telement={renderSkeleton(index)}\n\t\t\t\t\tanimate={animate}\n\t\t\t\t\tseed={itemSeed}\n\t\t\t\t\tsuppressRefWarning={suppressRefWarning}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\t\treturn <>{skeletons}</>;\n\t}\n\n\tif (!items || items.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{items.map((item, index) => (\n\t\t\t\t<Fragment key={keyExtractor(item, index)}>\n\t\t\t\t\t{renderItem(item, index)}\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</>\n\t);\n}\n"]}
package/dist/index.css CHANGED
@@ -1,2 +1,2 @@
1
- :root{--loaded-bg-wrapper: rgba(229, 231, 235, 1);--loaded-bg-content: rgba(156, 163, 175, .6);--loaded-border-radius: 4px;--loaded-text-inset: .3em}.loaded-skeleton-mode{user-select:none;pointer-events:none}.loaded-skeleton-mode,.loaded-skeleton-mode *{color:transparent!important;background-color:transparent!important;border-color:transparent!important;background-image:none!important;box-shadow:none!important;text-shadow:none!important}.loaded-skeleton-mode *:before,.loaded-skeleton-mode *:after{background:transparent!important;background-image:none!important;color:transparent!important;border-color:transparent!important;box-shadow:none!important;text-shadow:none!important}.loaded-skeleton-mode ::placeholder{color:transparent!important;opacity:0!important}.loaded-skeleton-mode.loaded-skeleton-bg,.loaded-skeleton-mode .loaded-skeleton-bg{background-color:var(--loaded-bg-wrapper)!important}.loaded-skeleton-mode.loaded-skeleton-wrapper>:first-child{background-color:var(--loaded-bg-wrapper)!important}.loaded-skeleton-mode .loaded-skeleton-content{background-color:var(--loaded-bg-content)!important}.loaded-skeleton-mode .loaded-text-skeleton{position:relative;background-color:transparent!important}.loaded-skeleton-mode .loaded-text-skeleton:before{content:""!important;position:absolute!important;left:0!important;width:var(--skeleton-text-width, 100%)!important;max-width:90%!important;top:var(--loaded-text-inset)!important;bottom:var(--loaded-text-inset)!important;background:var(--loaded-bg-content)!important;background-image:none!important;border-radius:var(--loaded-border-radius)!important;pointer-events:none!important;transform:none!important}.loaded-skeleton-mode .loaded-text-skeleton[data-skeleton-align=center]:before{left:50%!important;transform:translate(-50%)!important}.loaded-skeleton-mode .loaded-text-skeleton[data-skeleton-align=right]:before{left:auto!important;right:0!important}.loaded-skeleton-mode .loaded-skeleton-media{background-color:var(--loaded-bg-content)!important;opacity:1!important}.loaded-skeleton-mode .loaded-skeleton-svg{background-color:var(--loaded-bg-content)!important;border-radius:50%!important}.loaded-skeleton-mode .loaded-skeleton-svg *{visibility:hidden!important}.loaded-skeleton-mode img.loaded-skeleton-media{object-position:-9999px -9999px!important}@keyframes loaded-shimmer{0%{opacity:1}50%{opacity:.6}to{opacity:1}}.loaded-skeleton-mode.loaded-animate{animation:loaded-shimmer 1.5s ease-in-out infinite}
1
+ :root{--loaded-bg-wrapper: rgba(229, 231, 235, 1);--loaded-bg-content: rgba(156, 163, 175, .6);--loaded-border-radius: 4px;--loaded-text-inset: .3em}.loaded-skeleton-mode{user-select:none;pointer-events:none}.loaded-skeleton-mode,.loaded-skeleton-mode *{color:transparent!important;background-color:transparent!important;border-color:transparent!important;background-image:none!important;box-shadow:none!important;text-shadow:none!important}.loaded-skeleton-mode img{object-position:-9999px -9999px!important}.loaded-skeleton-mode *:before,.loaded-skeleton-mode *:after{background:transparent!important;background-image:none!important;color:transparent!important;border-color:transparent!important;box-shadow:none!important;text-shadow:none!important}.loaded-skeleton-mode ::placeholder{color:transparent!important;opacity:0!important}.loaded-skeleton-mode.loaded-skeleton-bg,.loaded-skeleton-mode .loaded-skeleton-bg{background-color:var(--loaded-bg-wrapper)!important}.loaded-skeleton-mode.loaded-skeleton-wrapper>:first-child{background-color:var(--loaded-bg-wrapper)!important}.loaded-skeleton-mode .loaded-skeleton-content{background-color:var(--loaded-bg-content)!important}.loaded-skeleton-mode .loaded-text-skeleton{position:relative;background-color:transparent!important}.loaded-skeleton-mode .loaded-text-skeleton:before{content:""!important;position:absolute!important;left:0!important;width:var(--skeleton-text-width, 100%)!important;max-width:90%!important;top:var(--loaded-text-inset)!important;bottom:var(--loaded-text-inset)!important;background:var(--loaded-bg-content)!important;background-image:none!important;border-radius:var(--loaded-border-radius)!important;pointer-events:none!important;transform:none!important}.loaded-skeleton-mode .loaded-text-skeleton[data-skeleton-align=center]:before{left:50%!important;transform:translate(-50%)!important}.loaded-skeleton-mode .loaded-text-skeleton[data-skeleton-align=right]:before{left:auto!important;right:0!important}.loaded-skeleton-mode .loaded-skeleton-media{background-color:var(--loaded-bg-content)!important;opacity:1!important}.loaded-skeleton-mode .loaded-skeleton-svg{background-color:var(--loaded-bg-content)!important;border-radius:50%!important}.loaded-skeleton-mode .loaded-skeleton-svg *{visibility:hidden!important}.loaded-skeleton-mode .loaded-skeleton-force-hide{opacity:0!important;visibility:hidden!important}@keyframes loaded-shimmer{0%{opacity:1}50%{opacity:.6}to{opacity:1}}.loaded-skeleton-mode.loaded-animate{animation:loaded-shimmer 1.5s ease-in-out infinite}
2
2
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/SmartSkeleton/SmartSkeleton.css"],"sourcesContent":[":root {\n --loaded-bg-wrapper: rgba(229, 231, 235, 1);\n --loaded-bg-content: rgba(156, 163, 175, 0.6);\n --loaded-border-radius: 4px;\n --loaded-text-inset: 0.3em;\n}\n\n.loaded-skeleton-mode {\n user-select: none;\n pointer-events: none;\n}\n\n/* Base styles applied to ALL elements inside skeleton via CSS selector */\n.loaded-skeleton-mode,\n.loaded-skeleton-mode * {\n color: transparent !important;\n background-color: transparent !important;\n border-color: transparent !important;\n background-image: none !important;\n box-shadow: none !important;\n text-shadow: none !important;\n}\n\n/* Reset pseudo-elements */\n.loaded-skeleton-mode *::before,\n.loaded-skeleton-mode *::after {\n background: transparent !important;\n background-image: none !important;\n color: transparent !important;\n border-color: transparent !important;\n box-shadow: none !important;\n text-shadow: none !important;\n}\n\n/* Hide input placeholders during skeleton */\n.loaded-skeleton-mode ::placeholder {\n color: transparent !important;\n opacity: 0 !important;\n}\n\n/* Main background for non-wrapper case (element has loaded-skeleton-bg directly) */\n.loaded-skeleton-mode.loaded-skeleton-bg,\n.loaded-skeleton-mode .loaded-skeleton-bg {\n background-color: var(--loaded-bg-wrapper) !important;\n}\n\n/* Main background for wrapper case (applies to first child to preserve border-radius) */\n.loaded-skeleton-mode.loaded-skeleton-wrapper > :first-child {\n background-color: var(--loaded-bg-wrapper) !important;\n}\n\n/* Content elements (buttons, inputs, etc.) */\n.loaded-skeleton-mode .loaded-skeleton-content {\n background-color: var(--loaded-bg-content) !important;\n}\n\n/* Text skeleton with pseudo-element */\n.loaded-skeleton-mode .loaded-text-skeleton {\n position: relative;\n background-color: transparent !important;\n}\n\n/* Text skeleton bar drawn via pseudo-element */\n.loaded-skeleton-mode .loaded-text-skeleton::before {\n content: \"\" !important;\n position: absolute !important;\n left: 0 !important;\n width: var(--skeleton-text-width, 100%) !important;\n max-width: 90% !important;\n top: var(--loaded-text-inset) !important;\n bottom: var(--loaded-text-inset) !important;\n background: var(--loaded-bg-content) !important;\n background-image: none !important;\n border-radius: var(--loaded-border-radius) !important;\n pointer-events: none !important;\n transform: none !important;\n}\n\n.loaded-skeleton-mode\n .loaded-text-skeleton[data-skeleton-align=\"center\"]::before {\n left: 50% !important;\n transform: translateX(-50%) !important;\n}\n\n.loaded-skeleton-mode\n .loaded-text-skeleton[data-skeleton-align=\"right\"]::before {\n left: auto !important;\n right: 0 !important;\n}\n\n/* Media elements (images, videos, etc.) */\n.loaded-skeleton-mode .loaded-skeleton-media {\n background-color: var(--loaded-bg-content) !important;\n opacity: 1 !important;\n}\n\n/* SVG elements rendered as rounded blocks */\n.loaded-skeleton-mode .loaded-skeleton-svg {\n background-color: var(--loaded-bg-content) !important;\n border-radius: 50% !important;\n}\n\n/* Hide SVG internal content (paths, circles, etc.) */\n.loaded-skeleton-mode .loaded-skeleton-svg * {\n visibility: hidden !important;\n}\n\n.loaded-skeleton-mode img.loaded-skeleton-media {\n object-position: -9999px -9999px !important;\n}\n\n/* Animation */\n@keyframes loaded-shimmer {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: 0.6;\n }\n 100% {\n opacity: 1;\n }\n}\n\n.loaded-skeleton-mode.loaded-animate {\n animation: loaded-shimmer 1.5s ease-in-out infinite;\n}\n"],"mappings":"AAAA,MACE,qBAAqB,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GACzC,qBAAqB,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IACzC,wBAAwB,IACxB,qBAAqB,IACvB,CAEA,CAAC,qBACC,YAAa,KACb,eAAgB,IAClB,CAGA,CANC,qBAOD,CAPC,qBAOqB,EACpB,MAAO,sBACP,iBAAkB,sBAClB,aAAc,sBACd,iBAAkB,eAClB,WAAY,eACZ,YAAa,cACf,CAGA,CAjBC,qBAiBqB,CAAC,QACvB,CAlBC,qBAkBqB,CAAC,OACrB,WAAY,sBACZ,iBAAkB,eAClB,MAAO,sBACP,aAAc,sBACd,WAAY,eACZ,YAAa,cACf,CAGA,CA5BC,qBA4BqB,cACpB,MAAO,sBACP,QAAS,WACX,CAGA,CAlCC,oBAkCoB,CAAC,mBACtB,CAnCC,qBAmCqB,CADA,mBAEpB,iBAAkB,IAAI,8BACxB,CAGA,CAxCC,oBAwCoB,CAAC,uBAAwB,CAAE,aAC9C,iBAAkB,IAAI,8BACxB,CAGA,CA7CC,qBA6CqB,CAAC,wBACrB,iBAAkB,IAAI,8BACxB,CAGA,CAlDC,qBAkDqB,CAAC,qBACrB,SAAU,SACV,iBAAkB,qBACpB,CAGA,CAxDC,qBAwDqB,CANC,oBAMoB,QACzC,QAAS,aACT,SAAU,mBACV,KAAM,YACN,MAAO,IAAI,qBAAqB,EAAE,gBAClC,UAAW,cACX,IAAK,IAAI,+BACT,OAAQ,IAAI,+BACZ,WAAY,IAAI,+BAChB,iBAAkB,eAClB,cAAe,IAAI,kCACnB,eAAgB,eAChB,UAAW,cACb,CAEA,CAvEC,qBAwEC,CAtBqB,oBAsBA,CAAC,2BAA6B,QACnD,KAAM,cACN,UAAW,UAAW,eACxB,CAEA,CA7EC,qBA8EC,CA5BqB,oBA4BA,CAAC,0BAA4B,QAClD,KAAM,eACN,MAAO,WACT,CAGA,CApFC,qBAoFqB,CAAC,sBACrB,iBAAkB,IAAI,+BACtB,QAAS,WACX,CAGA,CA1FC,qBA0FqB,CAAC,oBACrB,iBAAkB,IAAI,+BAlGxB,cAmGiB,aACjB,CAGA,CAhGC,qBAgGqB,CANC,oBAMoB,EACzC,WAAY,gBACd,CAEA,CApGC,qBAoGqB,GAAG,CAhBF,sBAiBrB,gBAAiB,QAAQ,iBAC3B,CAGA,WAAW,eACT,GACE,QAAS,CACX,CACA,IACE,QAAS,EACX,CACA,GACE,QAAS,CACX,CACF,CAEA,CArHC,oBAqHoB,CAAC,eACpB,UAAW,eAAe,KAAK,YAAY,QAC7C","names":[]}
1
+ {"version":3,"sources":["../src/components/SmartSkeleton/SmartSkeleton.css"],"sourcesContent":[":root {\n\t--loaded-bg-wrapper: rgba(229, 231, 235, 1);\n\t--loaded-bg-content: rgba(156, 163, 175, 0.6);\n\t--loaded-border-radius: 4px;\n\t--loaded-text-inset: 0.3em;\n}\n\n.loaded-skeleton-mode {\n\tuser-select: none;\n\tpointer-events: none;\n}\n\n/* Base styles applied to ALL elements inside skeleton via CSS selector */\n.loaded-skeleton-mode,\n.loaded-skeleton-mode * {\n\tcolor: transparent !important;\n\tbackground-color: transparent !important;\n\tborder-color: transparent !important;\n\tbackground-image: none !important;\n\tbox-shadow: none !important;\n\ttext-shadow: none !important;\n}\n\n.loaded-skeleton-mode img {\n\tobject-position: -9999px -9999px !important;\n}\n\n/* Reset pseudo-elements */\n.loaded-skeleton-mode *::before,\n.loaded-skeleton-mode *::after {\n\tbackground: transparent !important;\n\tbackground-image: none !important;\n\tcolor: transparent !important;\n\tborder-color: transparent !important;\n\tbox-shadow: none !important;\n\ttext-shadow: none !important;\n}\n\n/* Hide input placeholders during skeleton */\n.loaded-skeleton-mode ::placeholder {\n\tcolor: transparent !important;\n\topacity: 0 !important;\n}\n\n/* Main background for non-wrapper case (element has loaded-skeleton-bg directly) */\n.loaded-skeleton-mode.loaded-skeleton-bg,\n.loaded-skeleton-mode .loaded-skeleton-bg {\n\tbackground-color: var(--loaded-bg-wrapper) !important;\n}\n\n/* Main background for wrapper case (applies to first child to preserve border-radius) */\n.loaded-skeleton-mode.loaded-skeleton-wrapper > :first-child {\n\tbackground-color: var(--loaded-bg-wrapper) !important;\n}\n\n/* Content elements (buttons, inputs, etc.) */\n.loaded-skeleton-mode .loaded-skeleton-content {\n\tbackground-color: var(--loaded-bg-content) !important;\n}\n\n/* Text skeleton with pseudo-element */\n.loaded-skeleton-mode .loaded-text-skeleton {\n\tposition: relative;\n\tbackground-color: transparent !important;\n}\n\n/* Text skeleton bar drawn via pseudo-element */\n.loaded-skeleton-mode .loaded-text-skeleton::before {\n\tcontent: \"\" !important;\n\tposition: absolute !important;\n\tleft: 0 !important;\n\twidth: var(--skeleton-text-width, 100%) !important;\n\tmax-width: 90% !important;\n\ttop: var(--loaded-text-inset) !important;\n\tbottom: var(--loaded-text-inset) !important;\n\tbackground: var(--loaded-bg-content) !important;\n\tbackground-image: none !important;\n\tborder-radius: var(--loaded-border-radius) !important;\n\tpointer-events: none !important;\n\ttransform: none !important;\n}\n\n.loaded-skeleton-mode\n\t.loaded-text-skeleton[data-skeleton-align=\"center\"]::before {\n\tleft: 50% !important;\n\ttransform: translateX(-50%) !important;\n}\n\n.loaded-skeleton-mode\n\t.loaded-text-skeleton[data-skeleton-align=\"right\"]::before {\n\tleft: auto !important;\n\tright: 0 !important;\n}\n\n/* Media elements (images, videos, etc.) */\n.loaded-skeleton-mode .loaded-skeleton-media {\n\tbackground-color: var(--loaded-bg-content) !important;\n\topacity: 1 !important;\n}\n\n/* SVG elements rendered as rounded blocks */\n.loaded-skeleton-mode .loaded-skeleton-svg {\n\tbackground-color: var(--loaded-bg-content) !important;\n\tborder-radius: 50% !important;\n}\n\n/* Hide SVG internal content (paths, circles, etc.) */\n.loaded-skeleton-mode .loaded-skeleton-svg * {\n\tvisibility: hidden !important;\n}\n\n.loaded-skeleton-mode .loaded-skeleton-force-hide {\n\topacity: 0 !important;\n\tvisibility: hidden !important;\n}\n\n/* Animation */\n@keyframes loaded-shimmer {\n\t0% {\n\t\topacity: 1;\n\t}\n\t50% {\n\t\topacity: 0.6;\n\t}\n\t100% {\n\t\topacity: 1;\n\t}\n}\n\n.loaded-skeleton-mode.loaded-animate {\n\tanimation: loaded-shimmer 1.5s ease-in-out infinite;\n}\n"],"mappings":"AAAA,MACC,qBAAqB,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GACzC,qBAAqB,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IACzC,wBAAwB,IACxB,qBAAqB,IACtB,CAEA,CAAC,qBACA,YAAa,KACb,eAAgB,IACjB,CAGA,CANC,qBAOD,CAPC,qBAOqB,EACrB,MAAO,sBACP,iBAAkB,sBAClB,aAAc,sBACd,iBAAkB,eAClB,WAAY,eACZ,YAAa,cACd,CAEA,CAhBC,qBAgBqB,IACrB,gBAAiB,QAAQ,iBAC1B,CAGA,CArBC,qBAqBqB,CAAC,QACvB,CAtBC,qBAsBqB,CAAC,OACtB,WAAY,sBACZ,iBAAkB,eAClB,MAAO,sBACP,aAAc,sBACd,WAAY,eACZ,YAAa,cACd,CAGA,CAhCC,qBAgCqB,cACrB,MAAO,sBACP,QAAS,WACV,CAGA,CAtCC,oBAsCoB,CAAC,mBACtB,CAvCC,qBAuCqB,CADA,mBAErB,iBAAkB,IAAI,8BACvB,CAGA,CA5CC,oBA4CoB,CAAC,uBAAwB,CAAE,aAC/C,iBAAkB,IAAI,8BACvB,CAGA,CAjDC,qBAiDqB,CAAC,wBACtB,iBAAkB,IAAI,8BACvB,CAGA,CAtDC,qBAsDqB,CAAC,qBACtB,SAAU,SACV,iBAAkB,qBACnB,CAGA,CA5DC,qBA4DqB,CANC,oBAMoB,QAC1C,QAAS,aACT,SAAU,mBACV,KAAM,YACN,MAAO,IAAI,qBAAqB,EAAE,gBAClC,UAAW,cACX,IAAK,IAAI,+BACT,OAAQ,IAAI,+BACZ,WAAY,IAAI,+BAChB,iBAAkB,eAClB,cAAe,IAAI,kCACnB,eAAgB,eAChB,UAAW,cACZ,CAEA,CA3EC,qBA4EA,CAtBsB,oBAsBD,CAAC,2BAA6B,QACnD,KAAM,cACN,UAAW,UAAW,eACvB,CAEA,CAjFC,qBAkFA,CA5BsB,oBA4BD,CAAC,0BAA4B,QAClD,KAAM,eACN,MAAO,WACR,CAGA,CAxFC,qBAwFqB,CAAC,sBACtB,iBAAkB,IAAI,+BACtB,QAAS,WACV,CAGA,CA9FC,qBA8FqB,CAAC,oBACtB,iBAAkB,IAAI,+BAtGvB,cAuGgB,aAChB,CAGA,CApGC,qBAoGqB,CANC,oBAMoB,EAC1C,WAAY,gBACb,CAEA,CAxGC,qBAwGqB,CAAC,2BACtB,QAAS,YACT,WAAY,gBACb,CAGA,WAAW,eACV,GACC,QAAS,CACV,CACA,IACC,QAAS,EACV,CACA,GACC,QAAS,CACV,CACD,CAEA,CA1HC,oBA0HoB,CAAC,eACrB,UAAW,eAAe,KAAK,YAAY,QAC5C","names":[]}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import {createContext,useContext,useRef,useState,useCallback,useEffect,cloneElement,Fragment as Fragment$1,useLayoutEffect,version}from'react';import {jsx,Fragment}from'react/jsx-runtime';var C=createContext(false);function de(){return useContext(C)}function x(){let e=globalThis,t=e.__REACT_LOADED_DEV__;if(typeof t=="boolean")return t;let n=e.__DEV__;if(typeof n=="boolean")return n;let o=globalThis.process,l=typeof o=="object"&&o!==null?o.env?.NODE_ENV:void 0;return typeof l=="string"?l!=="production":false}var fe=typeof globalThis<"u"&&typeof globalThis.document<"u",y=fe?useLayoutEffect:useEffect;var be=6,ge=40;function X(e){if(!e||typeof e!="object")return false;let t=e;return !(t.nodeType!==1||typeof t.tagName!="string"||typeof t.querySelectorAll!="function"||typeof Element<"u"&&!(e instanceof Element))}var H=new Set;function F(e){if(!X(e))return false;try{return e.querySelectorAll("*"),!0}catch{return false}}function L(e){if(F(e))return e;if(e&&typeof e=="object"&&"nativeElement"in e){let t=e.nativeElement;if(F(t))return t}return null}function Ee(e){let t=e.type;if(typeof t=="string")return `<${t}>`;if(typeof t=="function"){let n=t;return `<${n.displayName||n.name||"Unknown"}>`}if(typeof t=="object"&&t!==null){let n=t;return `<${n.displayName||n.name||"Unknown"}>`}return "<Unknown>"}var J=Number.parseInt(version,10),Se=Number.isFinite(J)&&J>=19;function ye(e){let n=e.props?.ref;if(n!==void 0)return n;if(Se)return;let o=e.ref;if(o!==void 0)return o}function he(e,t){e&&(typeof e=="function"?e(t):e.current=t);}var _=new Set(["IMG","VIDEO","CANVAS"]),I=new Set(["SVG"]),we=new Set(["BUTTON","INPUT","TEXTAREA","SELECT","A"]),Re="button,input,textarea,select,a,[role='button']",Te=new Set(["SCRIPT","STYLE","LINK","META","NOSCRIPT","TEMPLATE"]);function O(e){return e.tagName.toUpperCase()}function P(e,t=O(e)){return we.has(t)?true:e.getAttribute("role")==="button"}function Ce(e,t){return !!(e.closest(Re)&&!P(e,t))}function xe(e,t=O(e)){return !!(_.has(t)||I.has(t)||P(e,t)||e.childElementCount===0&&e.textContent?.trim())}function ve(e,t){let n=e.length,o=Math.max(4,.8*n),l=Ne(t)*o,r=n+2+l;return Math.max(be,Math.min(ge,r))}function Ne(e){if(!e)return 0;let t=2166136261;for(let o=0;o<e.length;o+=1)t^=e.charCodeAt(o),t=Math.imul(t,16777619);return (t>>>0)/4294967295*2-1}function Le(e){let t=globalThis.getComputedStyle(e).textAlign;return t==="center"?"center":t==="right"||t==="end"?"right":"left"}function A(e,t={}){let{animate:n=true,seed:o}=t,l=o==null?"loaded":String(o);if(!X(e))return;let r=e;r.classList.add("loaded-skeleton-mode"),n&&r.classList.add("loaded-animate"),r.classList.contains("loaded-skeleton-wrapper")||r.classList.add("loaded-skeleton-bg");let c=e.getElementsByTagName("*"),p=0,d=s=>{let i=O(s);if(Te.has(i)||!xe(s,i)||Ce(s,i))return;let a=s,f=s.textContent?.trim();if(s.childElementCount===0&&f&&!_.has(i)&&!I.has(i)&&!P(s,i)){a.classList.add("loaded-text-skeleton"),a.dataset.skeletonAlign=Le(a);let b=`${l}|${p}|${f??""}`;p+=1;let h=ve(f??"",b);a.style.setProperty("--skeleton-text-width",`${h}ch`);}else _.has(i)?a.classList.add("loaded-skeleton-media"):I.has(i)?(a.classList.add("loaded-skeleton-content"),a.classList.add("loaded-skeleton-svg")):(a.classList.add("loaded-skeleton-content"),a.setAttribute("tabindex","-1"));};d(e);for(let s of c)d(s);}function M({element:e,children:t,loading:n=false,animate:o=true,className:l="",seed:r,suppressRefWarning:E=false}){let c=useRef(false),p=useRef(false),d=useRef(null),s=useRef(null),i=useRef(false),[a,f]=useState(false),u=e.type,b=e.key??null,h=useRef(n),V=useRef(u),j=useRef(b),S=useCallback(()=>{s.current!==null&&(clearTimeout(s.current),s.current=null);},[]);useEffect(()=>{i.current=a;},[a]),y(()=>{let k=h.current,m=V.current,R=j.current;(k&&!n||(m!==u||R!==b))&&(c.current=false,p.current=false,d.current=null,S(),i.current&&f(false)),h.current=n,V.current=u,j.current=b;},[n,u,b,S]),useEffect(()=>()=>{S();},[S]);let U=ye(e),w=useCallback(k=>{if(!i.current&&(f(true),!E&&x())){let m=Ee(e);H.has(m)||(console.warn(k==="non-dom-ref"?`[SmartSkeleton] ${m} does not forward its ref to a DOM element. A wrapper <div> has been added automatically. Use forwardRef to avoid this.`:`[SmartSkeleton] ${m} does not accept a ref. A wrapper <div> has been added automatically. Use forwardRef to avoid this.`),H.add(m));}},[e,E]),B=useCallback(k=>{p.current=true,d.current=k;let m=L(k);m&&n&&!c.current&&(A(m,{animate:o,seed:r}),c.current=true),he(U,k);},[n,U,o,r]);if(y(()=>{if(!n||a)return;S();let k=d.current,m=L(k);if(m&&!c.current&&(A(m,{animate:o,seed:r}),c.current=true),p.current){k!==null&&!m&&w("non-dom-ref");return}return s.current=setTimeout(()=>{if(s.current=null,!n||i.current)return;let R=d.current,T=L(R);if(T&&!c.current&&(A(T,{animate:o,seed:r}),c.current=true),p.current){R!==null&&!T&&w("non-dom-ref");return}w("no-ref-call");},0),()=>{S();}},[n,a,o,r,w,S]),!n)return t??null;let re=e.props.className??"",$=["loaded-skeleton-mode",o&&"loaded-animate"].filter(Boolean).join(" "),se=[$,"loaded-skeleton-wrapper",l].filter(Boolean).join(" "),ae=[re,$,"loaded-skeleton-bg",l].filter(Boolean).join(" ");return jsx(C.Provider,{value:true,children:a?jsx("div",{ref:B,className:se,"aria-hidden":"true",children:e}):cloneElement(e,{ref:B,className:ae,"aria-hidden":true})})}var z="react-loaded",Ie="loaded",Q=1;function Z(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}function q(e){if(!Z(e))return {};let t={};for(let[n,o]of Object.entries(e))typeof o=="number"&&(t[n]=o);return t}function ee(e){return Z(e)&&e.v===Q?q(e.counts):q(e)}function Oe(e){if(typeof localStorage>"u")return {};try{let t=localStorage.getItem(e);return t===null?{}:ee(JSON.parse(t))}catch{return {}}}function te(e){if(typeof localStorage>"u")return;let t={v:Q,counts:e};try{localStorage.setItem(z,JSON.stringify(t));}catch{}}function ne(){if(typeof localStorage>"u")return {};try{let e=localStorage.getItem(z);if(e!==null)return ee(JSON.parse(e));let t=Oe(Ie);return Object.keys(t).length>0&&te(t),t}catch{return {}}}function Pe(e){let n=ne()[e];return typeof n=="number"?n:null}function Me(e,t){if(!(typeof localStorage>"u"))try{let n=ne();n[e]=t,te(n);}catch{}}function D({storageKey:e,defaultCount:t=3,currentCount:n,loading:o,minCount:l=1,maxCount:r}){let[E,c]=useState(()=>W(t,l,r)),p=useRef(false);return y(()=>{if(!e)return;let d=Pe(e);if(d===null)return;let s=W(d,l,r);c(i=>Object.is(i,s)?i:s);},[e,l,r]),useEffect(()=>{if(!o&&n!==void 0){let d=W(n,l,r);c(d),e&&Me(e,d);}},[o,n,e,l,r]),useEffect(()=>{x()&&!e&&!p.current&&(console.warn("[Loaded] SmartSkeletonList used without storageKey. The count will reset on remount. Add a storageKey to persist across sessions."),p.current=true);},[e]),E}function W(e,t,n){let o=Math.max(e,t);return n!==void 0&&(o=Math.min(o,n)),o}function De({loading:e=false,items:t,renderItem:n,renderSkeleton:o,storageKey:l,defaultCount:r=3,minCount:E=1,maxCount:c,animate:p=true,seed:d,suppressRefWarning:s=false,keyExtractor:i=(a,f)=>f}){let a=D({storageKey:l,defaultCount:r,currentCount:t?.length,loading:e,minCount:E,maxCount:c});if(e){let f=new Array(a);for(let u=0;u<a;u+=1){let b=d===void 0?`${u}`:`${d}:${u}`;f[u]=jsx(M,{loading:true,element:o(u),animate:p,seed:b,suppressRefWarning:s},`skeleton-${u}`);}return jsx(Fragment,{children:f})}return !t||t.length===0?null:jsx(Fragment,{children:t.map((f,u)=>jsx(Fragment$1,{children:n(f,u)},i(f,u)))})}export{C as SkeletonContext,M as SmartSkeleton,De as SmartSkeletonList,de as useIsSkeletonMode,D as usePersistedCount};//# sourceMappingURL=index.js.map
1
+ import {createContext,useContext,useRef,useState,useCallback,cloneElement,useEffect,Fragment as Fragment$1,useLayoutEffect,version}from'react';import {jsx,Fragment}from'react/jsx-runtime';var w=createContext(false);function me(){return useContext(w)}function R(){let e=globalThis,t=e.__REACT_LOADED_DEV__;if(typeof t=="boolean")return t;let n=e.__DEV__;if(typeof n=="boolean")return n;let o=globalThis.process,l=typeof o=="object"&&o!==null?o.env?.NODE_ENV:void 0;return typeof l=="string"?l!=="production":false}var be=typeof globalThis<"u"&&typeof globalThis.document<"u",T=be?useLayoutEffect:useEffect;function X(e){if(!e||typeof e!="object")return false;let t=e;return !(t.nodeType!==1||typeof t.tagName!="string"||typeof t.querySelectorAll!="function"||typeof Element<"u"&&!(e instanceof Element))}function A(e){if(!X(e))return false;try{return e.querySelectorAll("*"),!0}catch{return false}}var N=new Set(["IMG","VIDEO","CANVAS"]),_=new Set(["SVG"]),ge=new Set(["BUTTON","INPUT","TEXTAREA","SELECT","A"]),Ee="button,input,textarea,select,a,[role='button']",Se=new Set(["SCRIPT","STYLE","LINK","META","NOSCRIPT","TEMPLATE"]);function I(e){return e.tagName.toUpperCase()}function O(e,t=I(e)){return ge.has(t)?true:e.getAttribute("role")==="button"}function ye(e,t){return !!(e.closest(Ee)&&!O(e,t))}function he(e,t=I(e)){return !!(N.has(t)||_.has(t)||O(e,t)||e.childElementCount===0&&e.textContent?.trim())}function we(e,t){let n=e.length,o=Math.max(4,.8*n),l=Re(t)*o,s=n+2+l;return Math.max(6,Math.min(40,s))}function Re(e){if(!e)return 0;let t=2166136261;for(let o=0;o<e.length;o+=1)t^=e.charCodeAt(o),t=Math.imul(t,16777619);return (t>>>0)/4294967295*2-1}function Te(e){let t=globalThis.getComputedStyle(e).textAlign;return t==="center"?"center":t==="right"||t==="end"?"right":"left"}function M(e,t={}){let{animate:n=true,seed:o}=t,l=o==null?"loaded":String(o);if(!X(e))return;let s=e;s.classList.add("loaded-skeleton-mode"),n&&s.classList.add("loaded-animate"),s.classList.contains("loaded-skeleton-wrapper")||s.classList.add("loaded-skeleton-bg");let m=e.getElementsByTagName("*"),c=0,d=r=>{let a=I(r);if(Se.has(a)||!he(r,a))return;let i=r;if(ye(r,a)){i.classList.add("loaded-skeleton-force-hide");return}let u=r.textContent?.trim();if(r.childElementCount===0&&u&&!N.has(a)&&!_.has(a)&&!O(r,a)){i.classList.add("loaded-text-skeleton"),i.dataset.skeletonAlign=Te(i);let S=`${l}|${c}|${u??""}`;c+=1;let y=we(u??"",S);i.style.setProperty("--skeleton-text-width",`${y}ch`);}else N.has(a)?i.classList.add("loaded-skeleton-media"):_.has(a)?(i.classList.add("loaded-skeleton-content"),i.classList.add("loaded-skeleton-svg")):(i.classList.add("loaded-skeleton-content"),i.setAttribute("tabindex","-1"));};d(e);for(let r of m)d(r);}var F=Number.parseInt(version,10),Ce=Number.isFinite(F)&&F>=19;function P(e){if(A(e))return e;if(e&&typeof e=="object"&&"nativeElement"in e){let t=e.nativeElement;if(A(t))return t}return null}function J(e){let t=e.type;if(typeof t=="string")return `<${t}>`;if(typeof t=="function"){let n=t;return `<${n.displayName||n.name||"Unknown"}>`}if(typeof t=="object"&&t!==null){let n=t;return `<${n.displayName||n.name||"Unknown"}>`}return "<Unknown>"}function K(e){let n=e.props?.ref;if(n!==void 0)return n;if(Ce)return;let o=e.ref;if(o!==void 0)return o}function Y(e,t){e&&(typeof e=="function"?e(t):e.current=t);}var q=new Set;function W({element:e,children:t,loading:n=false,animate:o=true,className:l="",seed:s,suppressRefWarning:b=false}){let m=e.type,c=e.key??null,d=useRef(false),r=useRef(false),a=useRef(null),i=useRef(false),[f,u]=useState(false),E=useRef(n),S=useRef(m),y=useRef(c),h=useCallback(p=>{i.current=p,u(p);},[]),U=K(e),C=useCallback(p=>{if(i.current||h(true),!b&&R()){let k=J(e);q.has(k)||(console.warn(p==="non-dom-ref"?`[SmartSkeleton] ${k} does not forward its ref to a DOM element. A wrapper <div> has been added automatically. Use forwardRef to avoid this.`:`[SmartSkeleton] ${k} does not accept a ref. A wrapper <div> has been added automatically. Use forwardRef to avoid this.`),q.add(k));}},[e,b,h]),j=useCallback(p=>{r.current=true,a.current=p;let k=P(p);k&&n&&!d.current&&(M(k,{animate:o,seed:s}),d.current=true),Y(U,p);},[n,U,o,s]);if(T(()=>{let p=E.current,k=S.current,ue=y.current,$=p&&!n,G=k!==m||ue!==c;if(E.current=n,S.current=m,y.current=c,($||G)&&(d.current=false,$?(r.current=false,a.current=null):G&&a.current===null&&(r.current=false),i.current)){h(false);return}if(!n||f)return;let v=a.current,L=P(v);if(L&&!d.current&&(M(L,{animate:o,seed:s}),d.current=true),r.current){if(v!==null&&!L){C("non-dom-ref");return}if(v!==null)return;r.current=false;}C("no-ref-call");},[n,f,m,c,o,s,C,h]),!n)return t??null;let ie=e.props.className??"",H=["loaded-skeleton-mode",o&&"loaded-animate"].filter(Boolean).join(" "),le=[H,"loaded-skeleton-wrapper",l].filter(Boolean).join(" "),de=[ie,H,"loaded-skeleton-bg",l].filter(Boolean).join(" ");return jsx(w.Provider,{value:true,children:f?jsx("div",{ref:j,className:le,"aria-hidden":"true",children:e}):cloneElement(e,{ref:j,className:de,"aria-hidden":true})})}var ee="react-loaded",Ae="loaded",te=1;function ne(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}function Z(e){if(!ne(e))return {};let t={};for(let[n,o]of Object.entries(e))typeof o=="number"&&(t[n]=o);return t}function oe(e){return ne(e)&&e.v===te?Z(e.counts):Z(e)}function Ie(e){if(typeof localStorage>"u")return {};try{let t=localStorage.getItem(e);return t===null?{}:oe(JSON.parse(t))}catch{return {}}}function re(e){if(typeof localStorage>"u")return;let t={v:te,counts:e};try{localStorage.setItem(ee,JSON.stringify(t));}catch{}}function se(){if(typeof localStorage>"u")return {};try{let e=localStorage.getItem(ee);if(e!==null)return oe(JSON.parse(e));let t=Ie(Ae);return Object.keys(t).length>0&&re(t),t}catch{return {}}}function Oe(e){let n=se()[e];return typeof n=="number"?n:null}function Me(e,t){if(!(typeof localStorage>"u"))try{let n=se();n[e]=t,re(n);}catch{}}function B({storageKey:e,defaultCount:t=3,currentCount:n,loading:o,minCount:l=1,maxCount:s}){let[b,m]=useState(()=>V(t,l,s)),c=useRef(false);return T(()=>{if(!e)return;let d=Oe(e);if(d===null)return;let r=V(d,l,s);m(a=>Object.is(a,r)?a:r);},[e,l,s]),useEffect(()=>{if(!o&&n!==void 0){let d=V(n,l,s);m(d),e&&Me(e,d);}},[o,n,e,l,s]),useEffect(()=>{R()&&!e&&!c.current&&(console.warn("[Loaded] SmartSkeletonList used without storageKey. The count will reset on remount. Add a storageKey to persist across sessions."),c.current=true);},[e]),b}function V(e,t,n){let o=Math.max(e,t);return n!==void 0&&(o=Math.min(o,n)),o}function De({loading:e=false,items:t,renderItem:n,renderSkeleton:o,storageKey:l,defaultCount:s=3,minCount:b=1,maxCount:m,animate:c=true,seed:d,suppressRefWarning:r=false,keyExtractor:a=(i,f)=>f}){let i=B({storageKey:l,defaultCount:s,currentCount:t?.length,loading:e,minCount:b,maxCount:m});if(e){let f=new Array(i);for(let u=0;u<i;u+=1){let E=d===void 0?`${u}`:`${d}:${u}`;f[u]=jsx(W,{loading:true,element:o(u),animate:c,seed:E,suppressRefWarning:r},`skeleton-${u}`);}return jsx(Fragment,{children:f})}return !t||t.length===0?null:jsx(Fragment,{children:t.map((f,u)=>jsx(Fragment$1,{children:n(f,u)},a(f,u)))})}export{w as SkeletonContext,W as SmartSkeleton,De as SmartSkeletonList,me as useIsSkeletonMode,B as usePersistedCount};//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/SkeletonContext/SkeletonContext.tsx","../src/utils/isDevEnv.ts","../src/utils/useIsomorphicLayoutEffect.ts","../src/components/SmartSkeleton/SmartSkeleton.tsx","../src/hooks/usePersistedCount/usePersistedCount.ts","../src/components/SmartSkeletonList/SmartSkeletonList.tsx"],"names":["SkeletonContext","createContext","useIsSkeletonMode","useContext","isDevEnv","maybeGlobal","override","devFlag","maybeProcess","nodeEnv","canUseDOM","useIsomorphicLayoutEffect","useLayoutEffect","useEffect","TEXT_WIDTH_MIN_CH","TEXT_WIDTH_MAX_CH","isElement","value","maybeElement","warnedComponents","isUsableElement","resolveRefTarget","node","nativeElement","getElementDisplayName","element","type","fn","obj","REACT_MAJOR_VERSION","reactVersion","IS_REACT_19_OR_NEWER","getOriginalRef","propsRef","legacyRef","forwardRef","originalRef","MEDIA_ELEMENTS","SVG_ELEMENTS","INTERACTIVE_ELEMENTS","BUTTON_LIKE_SELECTOR","SKIPPED_TAGS","getTagName","el","isButtonLikeElement","tagName","isButtonLikeDescendant","isContentElement","calculateTextWidthCh","text","seedKey","textLength","jitterRange","jitter","deterministicJitter","width","hash","index","resolveTextAlign","align","applySkeletonClasses","rootElement","options","animate","seed","baseSeed","htmlRoot","descendants","textIndex","processElement","htmlEl","textContent","widthCh","SmartSkeleton","children","loading","className","suppressRefWarning","hasAppliedRef","useRef","refWasCalledRef","lastRefNodeRef","deferredWrapperCheckTimeoutRef","needsWrapperRef","needsWrapper","setNeedsWrapper","useState","currentElementType","currentElementKey","previousLoadingRef","previousElementTypeRef","previousElementKeyRef","cancelDeferredWrapperCheck","useCallback","previousLoading","previousElementType","previousElementKey","enableWrapperWithWarning","reason","displayName","refCallback","target","delayedNode","delayedTarget","existingClassName","baseClasses","wrapperClassName","mergedClassName","jsx","cloneElement","STORAGE_KEY","LEGACY_STORAGE_KEY","STORAGE_VERSION","isRecord","toNumberRecord","result","key","maybeNumber","parseStoredCounts","readStoredCountsFromKey","raw","writeStoredCounts","counts","payload","getStoredCounts","rawNew","legacyCounts","getStoredCount","setStoredCount","count","usePersistedCount","storageKey","defaultCount","currentCount","minCount","maxCount","setCount","clampCount","hasWarnedRef","stored","next","prev","newCount","min","max","SmartSkeletonList","items","renderItem","renderSkeleton","keyExtractor","_","skeletonCount","skeletons","itemSeed","Fragment","item"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, useContext } from \"react\";\n\nexport const SkeletonContext = createContext(false);\n\nexport function useIsSkeletonMode(): boolean {\n return useContext(SkeletonContext);\n}\n","export function isDevEnv(): boolean {\n const maybeGlobal = globalThis as unknown as Record<string, unknown>;\n\n // Manual override for environments where NODE_ENV isn't injected.\n // Example: `globalThis.__REACT_LOADED_DEV__ = true`.\n const override = maybeGlobal.__REACT_LOADED_DEV__;\n if (typeof override === \"boolean\") return override;\n\n // Common global used by some toolchains/runtimes.\n const devFlag = maybeGlobal.__DEV__;\n if (typeof devFlag === \"boolean\") return devFlag;\n\n const maybeProcess = (globalThis as unknown as { process?: unknown }).process;\n const nodeEnv =\n typeof maybeProcess === \"object\" && maybeProcess !== null\n ? (maybeProcess as { env?: { NODE_ENV?: unknown } }).env?.NODE_ENV\n : undefined;\n\n if (typeof nodeEnv === \"string\") {\n return nodeEnv !== \"production\";\n }\n\n // No environment detected — assume production (convention: opt-in to dev mode).\n return false;\n}\n","import { useEffect, useLayoutEffect } from \"react\";\n\nconst canUseDOM =\n typeof globalThis !== \"undefined\" &&\n typeof (globalThis as { document?: unknown }).document !== \"undefined\";\n\nexport const useIsomorphicLayoutEffect = canUseDOM\n ? useLayoutEffect\n : useEffect;\n","import {\n cloneElement,\n type ReactElement,\n type Ref,\n version as reactVersion,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { isDevEnv } from \"../../utils/isDevEnv\";\nimport { useIsomorphicLayoutEffect } from \"../../utils/useIsomorphicLayoutEffect\";\nimport { SkeletonContext } from \"../SkeletonContext/SkeletonContext\";\nimport \"./SmartSkeleton.css\";\n\n// Text width configuration (in ch units)\nconst TEXT_WIDTH_MIN_CH = 6;\nconst TEXT_WIDTH_MAX_CH = 40;\n\nfunction isElement(value: unknown): value is Element {\n if (!value || typeof value !== \"object\") return false;\n const maybeElement = value as Element;\n // Must have nodeType 1 (Element) and a working querySelectorAll\n if (maybeElement.nodeType !== 1) return false;\n if (typeof maybeElement.tagName !== \"string\") return false;\n if (typeof maybeElement.querySelectorAll !== \"function\") return false;\n // Additional check: instanceof Element if available\n if (typeof Element !== \"undefined\" && !(value instanceof Element)) {\n return false;\n }\n return true;\n}\n\nconst warnedComponents = new Set<string>();\n\nfunction isUsableElement(value: unknown): value is Element {\n if (!isElement(value)) return false;\n // Test that querySelectorAll actually works\n try {\n (value as Element).querySelectorAll(\"*\");\n return true;\n } catch {\n return false;\n }\n}\n\nfunction resolveRefTarget(node: unknown): Element | null {\n if (isUsableElement(node)) return node;\n if (node && typeof node === \"object\" && \"nativeElement\" in node) {\n const nativeElement = (node as { nativeElement?: unknown }).nativeElement;\n if (isUsableElement(nativeElement)) return nativeElement;\n }\n return null;\n}\n\nfunction getElementDisplayName(element: ReactElement): string {\n const type = element.type;\n if (typeof type === \"string\") {\n return `<${type}>`;\n }\n if (typeof type === \"function\") {\n const fn = type as { displayName?: string; name?: string };\n return `<${fn.displayName || fn.name || \"Unknown\"}>`;\n }\n if (typeof type === \"object\" && type !== null) {\n const obj = type as { displayName?: string; name?: string };\n return `<${obj.displayName || obj.name || \"Unknown\"}>`;\n }\n return \"<Unknown>\";\n}\n\nconst REACT_MAJOR_VERSION = Number.parseInt(reactVersion, 10);\nconst IS_REACT_19_OR_NEWER =\n Number.isFinite(REACT_MAJOR_VERSION) && REACT_MAJOR_VERSION >= 19;\n\n/**\n * Get the original ref from the element, supporting both React 18 and React 19.\n * React 19: ref is a regular prop on element.props.ref\n * React 18: ref is on element.ref\n */\nfunction getOriginalRef(element: ReactElement): Ref<unknown> | undefined {\n // React 19 style (ref as prop)\n const elementProps = element.props as { ref?: Ref<unknown> } | undefined;\n const propsRef = elementProps?.ref;\n if (propsRef !== undefined) return propsRef;\n\n // React 19+ warns on element.ref access; skip legacy fallback entirely.\n if (IS_REACT_19_OR_NEWER) return undefined;\n\n // React 18 style\n const legacyRef = (element as ReactElement & { ref?: Ref<unknown> }).ref;\n if (legacyRef !== undefined) return legacyRef;\n\n return undefined;\n}\n\n/**\n * Forward a ref value to the original ref (callback or object style).\n */\nfunction forwardRef(originalRef: Ref<unknown> | undefined, node: unknown) {\n if (!originalRef) return;\n if (typeof originalRef === \"function\") {\n originalRef(node);\n } else {\n (originalRef as React.MutableRefObject<unknown>).current = node;\n }\n}\n\nconst MEDIA_ELEMENTS = new Set([\"IMG\", \"VIDEO\", \"CANVAS\"]);\nconst SVG_ELEMENTS = new Set([\"SVG\"]);\n\nconst INTERACTIVE_ELEMENTS = new Set([\n \"BUTTON\",\n \"INPUT\",\n \"TEXTAREA\",\n \"SELECT\",\n \"A\",\n]);\n\nconst BUTTON_LIKE_SELECTOR = \"button,input,textarea,select,a,[role='button']\";\nconst SKIPPED_TAGS = new Set([\n \"SCRIPT\",\n \"STYLE\",\n \"LINK\",\n \"META\",\n \"NOSCRIPT\",\n \"TEMPLATE\",\n]);\n\nfunction getTagName(el: Element): string {\n return el.tagName.toUpperCase();\n}\n\nfunction isButtonLikeElement(el: Element, tagName = getTagName(el)): boolean {\n if (INTERACTIVE_ELEMENTS.has(tagName)) return true;\n const role = el.getAttribute(\"role\");\n return role === \"button\";\n}\n\nfunction isButtonLikeDescendant(el: Element, tagName: string): boolean {\n const closestButton = el.closest(BUTTON_LIKE_SELECTOR);\n return Boolean(closestButton && !isButtonLikeElement(el, tagName));\n}\n\nfunction isContentElement(el: Element, tagName = getTagName(el)): boolean {\n if (MEDIA_ELEMENTS.has(tagName)) return true;\n if (SVG_ELEMENTS.has(tagName)) return true;\n if (isButtonLikeElement(el, tagName)) return true;\n\n const isLeafNode = el.childElementCount === 0;\n\n // Text elements that are leaf nodes (no child elements, only text)\n if (isLeafNode && el.textContent?.trim()) return true;\n\n return false;\n}\n\n/**\n * Calculate text skeleton width in ch units based on text content.\n * Uses a deterministic jitter: widthCh = clamp(6, 40, len + 2 + jitter)\n */\nfunction calculateTextWidthCh(text: string, seedKey: string): number {\n const textLength = text.length;\n const jitterRange = Math.max(4, 0.8 * textLength);\n const jitter = deterministicJitter(seedKey) * jitterRange;\n const width = textLength + 2 + jitter;\n return Math.max(TEXT_WIDTH_MIN_CH, Math.min(TEXT_WIDTH_MAX_CH, width));\n}\n\nfunction deterministicJitter(seedKey: string): number {\n if (!seedKey) return 0;\n let hash = 2166136261;\n for (let index = 0; index < seedKey.length; index += 1) {\n hash ^= seedKey.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n const normalized = (hash >>> 0) / 0xffffffff;\n return normalized * 2 - 1;\n}\n\nfunction resolveTextAlign(el: HTMLElement): \"left\" | \"center\" | \"right\" {\n const align = globalThis.getComputedStyle(el).textAlign;\n if (align === \"center\") return \"center\";\n if (align === \"right\" || align === \"end\") return \"right\";\n return \"left\";\n}\n\nexport function applySkeletonClasses(\n rootElement: Element,\n options: { animate?: boolean; seed?: string | number } = {},\n): void {\n const { animate = true, seed } = options;\n const baseSeed =\n seed === undefined || seed === null ? \"loaded\" : String(seed);\n\n if (!isElement(rootElement)) {\n return;\n }\n\n const htmlRoot = rootElement as HTMLElement;\n\n // Apply skeleton mode to the root element\n htmlRoot.classList.add(\"loaded-skeleton-mode\");\n\n if (animate) {\n htmlRoot.classList.add(\"loaded-animate\");\n }\n\n // Apply background class for standalone usage (when not used via SmartSkeleton JSX)\n // If element has loaded-skeleton-wrapper, CSS handles bg via > :first-child rule\n // If element already has loaded-skeleton-bg (from JSX), this is a no-op\n const isWrapper = htmlRoot.classList.contains(\"loaded-skeleton-wrapper\");\n if (!isWrapper) {\n htmlRoot.classList.add(\"loaded-skeleton-bg\");\n }\n\n // Only add specific classes where needed (text, media, content)\n const descendants = rootElement.getElementsByTagName(\"*\");\n\n let textIndex = 0;\n\n const processElement = (el: Element) => {\n const tagName = getTagName(el);\n if (SKIPPED_TAGS.has(tagName)) return;\n if (!isContentElement(el, tagName)) return;\n if (isButtonLikeDescendant(el, tagName)) return;\n\n const htmlEl = el as HTMLElement;\n const textContent = el.textContent?.trim();\n const isLeafWithText = el.childElementCount === 0 && textContent;\n\n if (\n isLeafWithText &&\n !MEDIA_ELEMENTS.has(tagName) &&\n !SVG_ELEMENTS.has(tagName) &&\n !isButtonLikeElement(el, tagName)\n ) {\n // Text elements: overlay bar with ch-based width\n htmlEl.classList.add(\"loaded-text-skeleton\");\n htmlEl.dataset.skeletonAlign = resolveTextAlign(htmlEl);\n const seedKey = `${baseSeed}|${textIndex}|${textContent ?? \"\"}`;\n textIndex += 1;\n const widthCh = calculateTextWidthCh(textContent ?? \"\", seedKey);\n htmlEl.style.setProperty(\"--skeleton-text-width\", `${widthCh}ch`);\n } else if (MEDIA_ELEMENTS.has(tagName)) {\n // Media elements\n htmlEl.classList.add(\"loaded-skeleton-media\");\n } else if (SVG_ELEMENTS.has(tagName)) {\n // SVG elements rendered as rounded content blocks\n htmlEl.classList.add(\"loaded-skeleton-content\");\n htmlEl.classList.add(\"loaded-skeleton-svg\");\n } else {\n // Interactive elements (buttons, inputs, etc.)\n htmlEl.classList.add(\"loaded-skeleton-content\");\n // Prevent keyboard focus / interaction while in skeleton mode.\n // aria-hidden does not remove elements from the tab order.\n htmlEl.setAttribute(\"tabindex\", \"-1\");\n }\n };\n\n processElement(rootElement);\n for (const el of descendants) {\n processElement(el);\n }\n}\n\nexport interface SmartSkeletonProps {\n /** The skeleton element with mock data, rendered when loading */\n element: ReactElement;\n /** The real content to render when not loading. If omitted, returns null when loading=false. */\n children?: ReactElement;\n /** Whether the skeleton is currently loading. Default: false */\n loading?: boolean;\n /** Enable shimmer animation. Default: true */\n animate?: boolean;\n /** Additional CSS class name */\n className?: string;\n /** Optional seed to stabilize skeleton text widths */\n seed?: string | number;\n /** Suppress warning when auto-wrapper is applied. Default: false */\n suppressRefWarning?: boolean;\n}\n\nexport function SmartSkeleton({\n element,\n children,\n loading = false,\n animate = true,\n className = \"\",\n seed,\n suppressRefWarning = false,\n}: SmartSkeletonProps): ReactElement | null {\n const hasAppliedRef = useRef(false);\n const refWasCalledRef = useRef(false);\n const lastRefNodeRef = useRef<unknown>(null);\n const deferredWrapperCheckTimeoutRef = useRef<ReturnType<\n typeof setTimeout\n > | null>(null);\n const needsWrapperRef = useRef(false);\n const [needsWrapper, setNeedsWrapper] = useState(false);\n const currentElementType = element.type;\n const currentElementKey = element.key ?? null;\n const previousLoadingRef = useRef(loading);\n const previousElementTypeRef =\n useRef<ReactElement[\"type\"]>(currentElementType);\n const previousElementKeyRef = useRef<ReactElement[\"key\"] | null>(\n currentElementKey,\n );\n\n const cancelDeferredWrapperCheck = useCallback(() => {\n if (deferredWrapperCheckTimeoutRef.current !== null) {\n clearTimeout(deferredWrapperCheckTimeoutRef.current);\n deferredWrapperCheckTimeoutRef.current = null;\n }\n }, []);\n\n useEffect(() => {\n needsWrapperRef.current = needsWrapper;\n }, [needsWrapper]);\n\n // Keep render pure: reset mutable tracking only after commit.\n useIsomorphicLayoutEffect(() => {\n const previousLoading = previousLoadingRef.current;\n const previousElementType = previousElementTypeRef.current;\n const previousElementKey = previousElementKeyRef.current;\n\n const didExitLoading = previousLoading && !loading;\n const hasElementIdentityChanged =\n previousElementType !== currentElementType ||\n previousElementKey !== currentElementKey;\n\n if (didExitLoading || hasElementIdentityChanged) {\n hasAppliedRef.current = false;\n refWasCalledRef.current = false;\n lastRefNodeRef.current = null;\n cancelDeferredWrapperCheck();\n\n if (needsWrapperRef.current) {\n setNeedsWrapper(false);\n }\n }\n\n previousLoadingRef.current = loading;\n previousElementTypeRef.current = currentElementType;\n previousElementKeyRef.current = currentElementKey;\n }, [\n loading,\n currentElementType,\n currentElementKey,\n cancelDeferredWrapperCheck,\n ]);\n\n useEffect(() => {\n return () => {\n cancelDeferredWrapperCheck();\n };\n }, [cancelDeferredWrapperCheck]);\n\n const originalRef = getOriginalRef(element);\n\n const enableWrapperWithWarning = useCallback(\n (reason: \"non-dom-ref\" | \"no-ref-call\") => {\n if (needsWrapperRef.current) return;\n setNeedsWrapper(true);\n\n if (!suppressRefWarning && isDevEnv()) {\n const displayName = getElementDisplayName(element);\n if (!warnedComponents.has(displayName)) {\n if (reason === \"non-dom-ref\") {\n console.warn(\n `[SmartSkeleton] ${displayName} does not forward its ref to a DOM element. ` +\n `A wrapper <div> has been added automatically. Use forwardRef to avoid this.`,\n );\n } else {\n console.warn(\n `[SmartSkeleton] ${displayName} does not accept a ref. ` +\n `A wrapper <div> has been added automatically. Use forwardRef to avoid this.`,\n );\n }\n warnedComponents.add(displayName);\n }\n }\n },\n [element, suppressRefWarning],\n );\n\n const refCallback = useCallback(\n (node: unknown) => {\n refWasCalledRef.current = true;\n lastRefNodeRef.current = node;\n\n const target = resolveRefTarget(node);\n\n if (target && loading && !hasAppliedRef.current) {\n applySkeletonClasses(target, { animate, seed });\n hasAppliedRef.current = true;\n }\n\n // Forward ref to original element\n forwardRef(originalRef, node);\n },\n [loading, originalRef, animate, seed],\n );\n\n // Decide wrapper fallback after commit to avoid eager false positives:\n // some environments attach refs slightly later in the same tick.\n useIsomorphicLayoutEffect(() => {\n if (!loading || needsWrapper) return;\n\n cancelDeferredWrapperCheck();\n\n const node = lastRefNodeRef.current;\n const target = resolveRefTarget(node);\n\n if (target && !hasAppliedRef.current) {\n applySkeletonClasses(target, { animate, seed });\n hasAppliedRef.current = true;\n }\n\n if (refWasCalledRef.current) {\n if (node !== null && !target) {\n enableWrapperWithWarning(\"non-dom-ref\");\n }\n return;\n }\n\n deferredWrapperCheckTimeoutRef.current = setTimeout(() => {\n deferredWrapperCheckTimeoutRef.current = null;\n\n if (!loading || needsWrapperRef.current) return;\n\n const delayedNode = lastRefNodeRef.current;\n const delayedTarget = resolveRefTarget(delayedNode);\n\n if (delayedTarget && !hasAppliedRef.current) {\n applySkeletonClasses(delayedTarget, { animate, seed });\n hasAppliedRef.current = true;\n }\n\n if (refWasCalledRef.current) {\n if (delayedNode !== null && !delayedTarget) {\n enableWrapperWithWarning(\"non-dom-ref\");\n }\n return;\n }\n\n enableWrapperWithWarning(\"no-ref-call\");\n }, 0);\n\n return () => {\n cancelDeferredWrapperCheck();\n };\n }, [\n loading,\n needsWrapper,\n animate,\n seed,\n enableWrapperWithWarning,\n cancelDeferredWrapperCheck,\n ]);\n\n // Not loading: return children or null\n if (!loading) {\n return children ?? null;\n }\n\n // Build merged className for skeleton mode\n const elementProps = element.props as { className?: string };\n const existingClassName = elementProps.className ?? \"\";\n\n // Base classes for skeleton mode\n const baseClasses = [\"loaded-skeleton-mode\", animate && \"loaded-animate\"]\n .filter(Boolean)\n .join(\" \");\n\n // When wrapping: wrapper gets mode + wrapper marker (no bg - it goes on child via ref)\n const wrapperClassName = [baseClasses, \"loaded-skeleton-wrapper\", className]\n .filter(Boolean)\n .join(\" \");\n\n // When not wrapping: element gets mode + bg directly (for SSR)\n const mergedClassName = [\n existingClassName,\n baseClasses,\n \"loaded-skeleton-bg\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n return (\n <SkeletonContext.Provider value={true}>\n {needsWrapper ? (\n <div ref={refCallback} className={wrapperClassName} aria-hidden=\"true\">\n {element}\n </div>\n ) : (\n cloneElement(element as ReactElement<Record<string, unknown>>, {\n ref: refCallback,\n className: mergedClassName,\n \"aria-hidden\": true,\n })\n )}\n </SkeletonContext.Provider>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { isDevEnv } from \"../../utils/isDevEnv\";\nimport { useIsomorphicLayoutEffect } from \"../../utils/useIsomorphicLayoutEffect\";\n\nconst STORAGE_KEY = \"react-loaded\";\nconst LEGACY_STORAGE_KEY = \"loaded\";\nconst STORAGE_VERSION = 1 as const;\n\ntype StoredCounts = Record<string, number>;\ntype StoredPayloadV1 = { v: typeof STORAGE_VERSION; counts: StoredCounts };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction toNumberRecord(value: unknown): StoredCounts {\n if (!isRecord(value)) return {};\n const result: StoredCounts = {};\n for (const [key, maybeNumber] of Object.entries(value)) {\n if (typeof maybeNumber === \"number\") {\n result[key] = maybeNumber;\n }\n }\n return result;\n}\n\nfunction parseStoredCounts(value: unknown): StoredCounts {\n // Current schema: { v: 1, counts: Record<string, number> }\n if (isRecord(value) && value.v === STORAGE_VERSION) {\n return toNumberRecord(value.counts);\n }\n\n // Legacy schema: Record<string, number>\n return toNumberRecord(value);\n}\n\nfunction readStoredCountsFromKey(key: string): StoredCounts {\n if (typeof localStorage === \"undefined\") return {};\n try {\n const raw = localStorage.getItem(key);\n if (raw === null) return {};\n return parseStoredCounts(JSON.parse(raw));\n } catch {\n return {};\n }\n}\n\nfunction writeStoredCounts(counts: StoredCounts): void {\n if (typeof localStorage === \"undefined\") return;\n const payload: StoredPayloadV1 = { v: STORAGE_VERSION, counts };\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));\n } catch {\n // Silently fail if localStorage is full or unavailable\n }\n}\n\nfunction getStoredCounts(): Record<string, number> {\n if (typeof localStorage === \"undefined\") return {};\n\n try {\n const rawNew = localStorage.getItem(STORAGE_KEY);\n if (rawNew !== null) {\n return parseStoredCounts(JSON.parse(rawNew));\n }\n\n // Backward compatibility: migrate legacy key once if present.\n const legacyCounts = readStoredCountsFromKey(LEGACY_STORAGE_KEY);\n if (Object.keys(legacyCounts).length > 0) {\n writeStoredCounts(legacyCounts);\n }\n return legacyCounts;\n } catch {\n return {};\n }\n}\n\nfunction getStoredCount(key: string): number | null {\n const counts = getStoredCounts();\n const value = counts[key];\n return typeof value === \"number\" ? value : null;\n}\n\nfunction setStoredCount(key: string, count: number): void {\n if (typeof localStorage === \"undefined\") return;\n\n try {\n const counts = getStoredCounts();\n counts[key] = count;\n writeStoredCounts(counts);\n } catch {\n // Silently fail if localStorage is full or unavailable\n }\n}\n\nexport interface UsePersistedCountOptions {\n storageKey?: string;\n defaultCount?: number;\n currentCount?: number;\n loading: boolean;\n minCount?: number;\n maxCount?: number;\n}\n\nexport function usePersistedCount({\n storageKey,\n defaultCount = 3,\n currentCount,\n loading,\n minCount = 1,\n maxCount,\n}: UsePersistedCountOptions): number {\n // Always start from the default to match SSR output, then (on the client)\n // sync to the persisted value in a layout effect before first paint.\n const [count, setCount] = useState<number>(() =>\n clampCount(defaultCount, minCount, maxCount),\n );\n\n const hasWarnedRef = useRef(false);\n\n useIsomorphicLayoutEffect(() => {\n if (!storageKey) return;\n const stored = getStoredCount(storageKey);\n if (stored === null) return;\n const next = clampCount(stored, minCount, maxCount);\n setCount((prev) => (Object.is(prev, next) ? prev : next));\n }, [storageKey, minCount, maxCount]);\n\n useEffect(() => {\n if (!loading && currentCount !== undefined) {\n const newCount = clampCount(currentCount, minCount, maxCount);\n setCount(newCount);\n\n if (storageKey) {\n setStoredCount(storageKey, newCount);\n }\n }\n }, [loading, currentCount, storageKey, minCount, maxCount]);\n\n useEffect(() => {\n if (isDevEnv() && !storageKey && !hasWarnedRef.current) {\n console.warn(\n \"[Loaded] SmartSkeletonList used without storageKey. \" +\n \"The count will reset on remount. Add a storageKey to persist across sessions.\",\n );\n hasWarnedRef.current = true;\n }\n }, [storageKey]);\n\n return count;\n}\n\nfunction clampCount(\n value: number,\n min: number,\n max: number | undefined,\n): number {\n let result = Math.max(value, min);\n if (max !== undefined) {\n result = Math.min(result, max);\n }\n return result;\n}\n","import { Fragment, type ReactElement } from \"react\";\nimport { usePersistedCount } from \"../../hooks/usePersistedCount/usePersistedCount\";\nimport { SmartSkeleton } from \"../SmartSkeleton/SmartSkeleton\";\n\nexport interface SmartSkeletonListProps<T> {\n /** Whether the list is currently loading. Default: false */\n loading?: boolean;\n /** The items to render. Pass undefined while loading. */\n items: T[] | undefined;\n /** Render function for each item when loaded */\n renderItem: (item: T, index: number) => ReactElement;\n /** Render function for skeleton placeholders */\n renderSkeleton: (index: number) => ReactElement;\n /** Key for localStorage persistence. Without it, count resets on remount. */\n storageKey?: string;\n /** Initial skeleton count before any data is known. Default: 3 */\n defaultCount?: number;\n /** Minimum skeletons to show. Default: 1 */\n minCount?: number;\n /** Maximum skeletons to show */\n maxCount?: number;\n /** Enable shimmer animation. Default: true */\n animate?: boolean;\n /** Optional seed to stabilize skeleton text widths */\n seed?: string | number;\n /** Suppress warning when auto-wrapper is applied. Default: false */\n suppressRefWarning?: boolean;\n /** Extract unique key for each item. Default: index */\n keyExtractor?: (item: T, index: number) => string | number;\n}\n\nexport function SmartSkeletonList<T>({\n loading = false,\n items,\n renderItem,\n renderSkeleton,\n storageKey,\n defaultCount = 3,\n minCount = 1,\n maxCount,\n animate = true,\n seed,\n suppressRefWarning = false,\n keyExtractor = (_, index) => index,\n}: SmartSkeletonListProps<T>): ReactElement | null {\n const skeletonCount = usePersistedCount({\n storageKey,\n defaultCount,\n currentCount: items?.length,\n loading,\n minCount,\n maxCount,\n });\n\n if (loading) {\n const skeletons = new Array(skeletonCount);\n for (let index = 0; index < skeletonCount; index += 1) {\n const itemSeed = seed === undefined ? `${index}` : `${seed}:${index}`;\n skeletons[index] = (\n <SmartSkeleton\n key={`skeleton-${index}`}\n loading={true}\n element={renderSkeleton(index)}\n animate={animate}\n seed={itemSeed}\n suppressRefWarning={suppressRefWarning}\n />\n );\n }\n return <>{skeletons}</>;\n }\n\n if (!items || items.length === 0) {\n return null;\n }\n\n return (\n <>\n {items.map((item, index) => (\n <Fragment key={keyExtractor(item, index)}>\n {renderItem(item, index)}\n </Fragment>\n ))}\n </>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/SkeletonContext/SkeletonContext.tsx","../src/utils/isDevEnv.ts","../src/utils/useIsomorphicLayoutEffect.ts","../src/components/SmartSkeleton/applySkeletonClasses.ts","../src/components/SmartSkeleton/refUtils.ts","../src/components/SmartSkeleton/SmartSkeleton.tsx","../src/hooks/usePersistedCount/usePersistedCount.ts","../src/components/SmartSkeletonList/SmartSkeletonList.tsx"],"names":["SkeletonContext","createContext","useIsSkeletonMode","useContext","isDevEnv","maybeGlobal","override","devFlag","maybeProcess","nodeEnv","canUseDOM","useIsomorphicLayoutEffect","useLayoutEffect","useEffect","isElement","value","maybeElement","isUsableElement","MEDIA_ELEMENTS","SVG_ELEMENTS","INTERACTIVE_ELEMENTS","BUTTON_LIKE_SELECTOR","SKIPPED_TAGS","getTagName","el","isButtonLikeElement","tagName","isButtonLikeDescendant","isContentElement","calculateTextWidthCh","text","seedKey","textLength","jitterRange","jitter","deterministicJitter","width","hash","index","resolveTextAlign","align","applySkeletonClasses","rootElement","options","animate","seed","baseSeed","htmlRoot","descendants","textIndex","processElement","htmlEl","textContent","widthCh","REACT_MAJOR_VERSION","reactVersion","IS_REACT_19_OR_NEWER","resolveRefTarget","node","nativeElement","getElementDisplayName","element","type","fn","obj","getOriginalRef","propsRef","legacyRef","forwardRef","originalRef","warnedComponents","SmartSkeleton","children","loading","className","suppressRefWarning","currentElementType","currentElementKey","hasAppliedRef","useRef","refWasCalledRef","lastRefNodeRef","needsWrapperRef","needsWrapper","setNeedsWrapper","useState","previousLoadingRef","previousElementTypeRef","previousElementKeyRef","setWrapperState","useCallback","next","enableWrapperWithWarning","reason","displayName","refCallback","target","previousLoading","previousElementType","previousElementKey","didExitLoading","hasElementIdentityChanged","existingClassName","baseClasses","wrapperClassName","mergedClassName","jsx","cloneElement","STORAGE_KEY","LEGACY_STORAGE_KEY","STORAGE_VERSION","isRecord","toNumberRecord","result","key","maybeNumber","parseStoredCounts","readStoredCountsFromKey","raw","writeStoredCounts","counts","payload","getStoredCounts","rawNew","legacyCounts","getStoredCount","setStoredCount","count","usePersistedCount","storageKey","defaultCount","currentCount","minCount","maxCount","setCount","clampCount","hasWarnedRef","stored","prev","newCount","min","max","SmartSkeletonList","items","renderItem","renderSkeleton","keyExtractor","_","skeletonCount","skeletons","itemSeed","Fragment","item"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, useContext } from \"react\";\n\nexport const SkeletonContext = createContext(false);\n\nexport function useIsSkeletonMode(): boolean {\n\treturn useContext(SkeletonContext);\n}\n","export function isDevEnv(): boolean {\n\tconst maybeGlobal = globalThis as unknown as Record<string, unknown>;\n\n\t// Manual override for environments where NODE_ENV isn't injected.\n\t// Example: `globalThis.__REACT_LOADED_DEV__ = true`.\n\tconst override = maybeGlobal.__REACT_LOADED_DEV__;\n\tif (typeof override === \"boolean\") return override;\n\n\t// Common global used by some toolchains/runtimes.\n\tconst devFlag = maybeGlobal.__DEV__;\n\tif (typeof devFlag === \"boolean\") return devFlag;\n\n\tconst maybeProcess = (globalThis as unknown as { process?: unknown }).process;\n\tconst nodeEnv =\n\t\ttypeof maybeProcess === \"object\" && maybeProcess !== null\n\t\t\t? (maybeProcess as { env?: { NODE_ENV?: unknown } }).env?.NODE_ENV\n\t\t\t: undefined;\n\n\tif (typeof nodeEnv === \"string\") {\n\t\treturn nodeEnv !== \"production\";\n\t}\n\n\t// No environment detected — assume production (convention: opt-in to dev mode).\n\treturn false;\n}\n","import { useEffect, useLayoutEffect } from \"react\";\n\nconst canUseDOM =\n\ttypeof globalThis !== \"undefined\" &&\n\ttypeof (globalThis as { document?: unknown }).document !== \"undefined\";\n\nexport const useIsomorphicLayoutEffect = canUseDOM\n\t? useLayoutEffect\n\t: useEffect;\n","// Text width configuration (in ch units)\nconst TEXT_WIDTH_MIN_CH = 6;\nconst TEXT_WIDTH_MAX_CH = 40;\n\nfunction isElement(value: unknown): value is Element {\n\tif (!value || typeof value !== \"object\") return false;\n\tconst maybeElement = value as Element;\n\t// Must have nodeType 1 (Element) and a working querySelectorAll\n\tif (maybeElement.nodeType !== 1) return false;\n\tif (typeof maybeElement.tagName !== \"string\") return false;\n\tif (typeof maybeElement.querySelectorAll !== \"function\") return false;\n\t// Additional check: instanceof Element if available\n\tif (typeof Element !== \"undefined\" && !(value instanceof Element)) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function isUsableElement(value: unknown): value is Element {\n\tif (!isElement(value)) return false;\n\t// Test that querySelectorAll actually works\n\ttry {\n\t\t(value as Element).querySelectorAll(\"*\");\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nconst MEDIA_ELEMENTS = new Set([\"IMG\", \"VIDEO\", \"CANVAS\"]);\nconst SVG_ELEMENTS = new Set([\"SVG\"]);\n\nconst INTERACTIVE_ELEMENTS = new Set([\n\t\"BUTTON\",\n\t\"INPUT\",\n\t\"TEXTAREA\",\n\t\"SELECT\",\n\t\"A\",\n]);\n\nconst BUTTON_LIKE_SELECTOR = \"button,input,textarea,select,a,[role='button']\";\nconst SKIPPED_TAGS = new Set([\n\t\"SCRIPT\",\n\t\"STYLE\",\n\t\"LINK\",\n\t\"META\",\n\t\"NOSCRIPT\",\n\t\"TEMPLATE\",\n]);\n\nfunction getTagName(el: Element): string {\n\treturn el.tagName.toUpperCase();\n}\n\nfunction isButtonLikeElement(el: Element, tagName = getTagName(el)): boolean {\n\tif (INTERACTIVE_ELEMENTS.has(tagName)) return true;\n\tconst role = el.getAttribute(\"role\");\n\treturn role === \"button\";\n}\n\nfunction isButtonLikeDescendant(el: Element, tagName: string): boolean {\n\tconst closestButton = el.closest(BUTTON_LIKE_SELECTOR);\n\treturn Boolean(closestButton && !isButtonLikeElement(el, tagName));\n}\n\nfunction isContentElement(el: Element, tagName = getTagName(el)): boolean {\n\tif (MEDIA_ELEMENTS.has(tagName)) return true;\n\tif (SVG_ELEMENTS.has(tagName)) return true;\n\tif (isButtonLikeElement(el, tagName)) return true;\n\n\tconst isLeafNode = el.childElementCount === 0;\n\n\t// Text elements that are leaf nodes (no child elements, only text)\n\tif (isLeafNode && el.textContent?.trim()) return true;\n\n\treturn false;\n}\n\n/**\n * Calculate text skeleton width in ch units based on text content.\n * Uses a deterministic jitter: widthCh = clamp(6, 40, len + 2 + jitter)\n */\nfunction calculateTextWidthCh(text: string, seedKey: string): number {\n\tconst textLength = text.length;\n\tconst jitterRange = Math.max(4, 0.8 * textLength);\n\tconst jitter = deterministicJitter(seedKey) * jitterRange;\n\tconst width = textLength + 2 + jitter;\n\treturn Math.max(TEXT_WIDTH_MIN_CH, Math.min(TEXT_WIDTH_MAX_CH, width));\n}\n\nfunction deterministicJitter(seedKey: string): number {\n\tif (!seedKey) return 0;\n\tlet hash = 2166136261;\n\tfor (let index = 0; index < seedKey.length; index += 1) {\n\t\thash ^= seedKey.charCodeAt(index);\n\t\thash = Math.imul(hash, 16777619);\n\t}\n\tconst normalized = (hash >>> 0) / 0xffffffff;\n\treturn normalized * 2 - 1;\n}\n\nfunction resolveTextAlign(el: HTMLElement): \"left\" | \"center\" | \"right\" {\n\tconst align = globalThis.getComputedStyle(el).textAlign;\n\tif (align === \"center\") return \"center\";\n\tif (align === \"right\" || align === \"end\") return \"right\";\n\treturn \"left\";\n}\n\nexport function applySkeletonClasses(\n\trootElement: Element,\n\toptions: { animate?: boolean; seed?: string | number } = {},\n): void {\n\tconst { animate = true, seed } = options;\n\tconst baseSeed =\n\t\tseed === undefined || seed === null ? \"loaded\" : String(seed);\n\n\tif (!isElement(rootElement)) {\n\t\treturn;\n\t}\n\n\tconst htmlRoot = rootElement as HTMLElement;\n\n\t// Apply skeleton mode to the root element\n\thtmlRoot.classList.add(\"loaded-skeleton-mode\");\n\n\tif (animate) {\n\t\thtmlRoot.classList.add(\"loaded-animate\");\n\t}\n\n\t// Apply background class for standalone usage (when not used via SmartSkeleton JSX)\n\t// If element has loaded-skeleton-wrapper, CSS handles bg via > :first-child rule\n\t// If element already has loaded-skeleton-bg (from JSX), this is a no-op\n\tconst isWrapper = htmlRoot.classList.contains(\"loaded-skeleton-wrapper\");\n\tif (!isWrapper) {\n\t\thtmlRoot.classList.add(\"loaded-skeleton-bg\");\n\t}\n\n\t// Only add specific classes where needed (text, media, content)\n\tconst descendants = rootElement.getElementsByTagName(\"*\");\n\n\tlet textIndex = 0;\n\n\tconst processElement = (el: Element) => {\n\t\tconst tagName = getTagName(el);\n\t\tif (SKIPPED_TAGS.has(tagName)) return;\n\t\tif (!isContentElement(el, tagName)) return;\n\n\t\tconst htmlEl = el as HTMLElement;\n\t\tconst isInsideButtonLike = isButtonLikeDescendant(el, tagName);\n\t\tif (isInsideButtonLike) {\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-force-hide\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst textContent = el.textContent?.trim();\n\t\tconst isLeafWithText = el.childElementCount === 0 && textContent;\n\n\t\tif (\n\t\t\tisLeafWithText &&\n\t\t\t!MEDIA_ELEMENTS.has(tagName) &&\n\t\t\t!SVG_ELEMENTS.has(tagName) &&\n\t\t\t!isButtonLikeElement(el, tagName)\n\t\t) {\n\t\t\t// Text elements: overlay bar with ch-based width\n\t\t\thtmlEl.classList.add(\"loaded-text-skeleton\");\n\t\t\thtmlEl.dataset.skeletonAlign = resolveTextAlign(htmlEl);\n\t\t\tconst seedKey = `${baseSeed}|${textIndex}|${textContent ?? \"\"}`;\n\t\t\ttextIndex += 1;\n\t\t\tconst widthCh = calculateTextWidthCh(textContent ?? \"\", seedKey);\n\t\t\thtmlEl.style.setProperty(\"--skeleton-text-width\", `${widthCh}ch`);\n\t\t} else if (MEDIA_ELEMENTS.has(tagName)) {\n\t\t\t// Media elements\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-media\");\n\t\t} else if (SVG_ELEMENTS.has(tagName)) {\n\t\t\t// SVG elements rendered as rounded content blocks\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-content\");\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-svg\");\n\t\t} else {\n\t\t\t// Interactive elements (buttons, inputs, etc.)\n\t\t\thtmlEl.classList.add(\"loaded-skeleton-content\");\n\t\t\t// Prevent keyboard focus / interaction while in skeleton mode.\n\t\t\t// aria-hidden does not remove elements from the tab order.\n\t\t\thtmlEl.setAttribute(\"tabindex\", \"-1\");\n\t\t}\n\t};\n\n\tprocessElement(rootElement);\n\tfor (const el of descendants) {\n\t\tprocessElement(el);\n\t}\n}\n","import { type ReactElement, type Ref, version as reactVersion } from \"react\";\nimport { isUsableElement } from \"./applySkeletonClasses\";\n\nexport const REACT_MAJOR_VERSION = Number.parseInt(reactVersion, 10);\nconst IS_REACT_19_OR_NEWER =\n\tNumber.isFinite(REACT_MAJOR_VERSION) && REACT_MAJOR_VERSION >= 19;\n\nexport function resolveRefTarget(node: unknown): Element | null {\n\tif (isUsableElement(node)) return node;\n\tif (node && typeof node === \"object\" && \"nativeElement\" in node) {\n\t\tconst nativeElement = (node as { nativeElement?: unknown }).nativeElement;\n\t\tif (isUsableElement(nativeElement)) return nativeElement;\n\t}\n\treturn null;\n}\n\nexport function getElementDisplayName(element: ReactElement): string {\n\tconst type = element.type;\n\tif (typeof type === \"string\") {\n\t\treturn `<${type}>`;\n\t}\n\tif (typeof type === \"function\") {\n\t\tconst fn = type as { displayName?: string; name?: string };\n\t\treturn `<${fn.displayName || fn.name || \"Unknown\"}>`;\n\t}\n\tif (typeof type === \"object\" && type !== null) {\n\t\tconst obj = type as { displayName?: string; name?: string };\n\t\treturn `<${obj.displayName || obj.name || \"Unknown\"}>`;\n\t}\n\treturn \"<Unknown>\";\n}\n\n/**\n * Get the original ref from the element, supporting both React 18 and React 19.\n * React 19: ref is a regular prop on element.props.ref\n * React 18: ref is on element.ref\n */\nexport function getOriginalRef(\n\telement: ReactElement,\n): Ref<unknown> | undefined {\n\t// React 19 style (ref as prop)\n\tconst elementProps = element.props as { ref?: Ref<unknown> } | undefined;\n\tconst propsRef = elementProps?.ref;\n\tif (propsRef !== undefined) return propsRef;\n\n\t// React 19+ warns on element.ref access; skip legacy fallback entirely.\n\tif (IS_REACT_19_OR_NEWER) return undefined;\n\n\t// React 18 style\n\tconst legacyRef = (element as ReactElement & { ref?: Ref<unknown> }).ref;\n\tif (legacyRef !== undefined) return legacyRef;\n\n\treturn undefined;\n}\n\n/**\n * Forward a ref value to the original ref (callback or object style).\n */\nexport function forwardRef(\n\toriginalRef: Ref<unknown> | undefined,\n\tnode: unknown,\n) {\n\tif (!originalRef) return;\n\tif (typeof originalRef === \"function\") {\n\t\toriginalRef(node);\n\t} else {\n\t\t(originalRef as React.MutableRefObject<unknown>).current = node;\n\t}\n}\n","import {\n\tcloneElement,\n\ttype ReactElement,\n\tuseCallback,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { isDevEnv } from \"../../utils/isDevEnv\";\nimport { useIsomorphicLayoutEffect } from \"../../utils/useIsomorphicLayoutEffect\";\nimport { SkeletonContext } from \"../SkeletonContext/SkeletonContext\";\nimport { applySkeletonClasses } from \"./applySkeletonClasses\";\nimport {\n\tforwardRef,\n\tgetElementDisplayName,\n\tgetOriginalRef,\n\tresolveRefTarget,\n} from \"./refUtils\";\nimport \"./SmartSkeleton.css\";\n\nexport { applySkeletonClasses } from \"./applySkeletonClasses\";\n\nconst warnedComponents = new Set<string>();\n\nexport interface SmartSkeletonProps {\n\t/** The skeleton element with mock data, rendered when loading */\n\telement: ReactElement;\n\t/** The real content to render when not loading. If omitted, returns null when loading=false. */\n\tchildren?: ReactElement;\n\t/** Whether the skeleton is currently loading. Default: false */\n\tloading?: boolean;\n\t/** Enable shimmer animation. Default: true */\n\tanimate?: boolean;\n\t/** Additional CSS class name */\n\tclassName?: string;\n\t/** Optional seed to stabilize skeleton text widths */\n\tseed?: string | number;\n\t/** Suppress warning when auto-wrapper is applied. Default: false */\n\tsuppressRefWarning?: boolean;\n}\n\nexport function SmartSkeleton({\n\telement,\n\tchildren,\n\tloading = false,\n\tanimate = true,\n\tclassName = \"\",\n\tseed,\n\tsuppressRefWarning = false,\n}: SmartSkeletonProps): ReactElement | null {\n\tconst currentElementType = element.type;\n\tconst currentElementKey = element.key ?? null;\n\tconst hasAppliedRef = useRef(false);\n\tconst refWasCalledRef = useRef(false);\n\tconst lastRefNodeRef = useRef<unknown>(null);\n\tconst needsWrapperRef = useRef(false);\n\tconst [needsWrapper, setNeedsWrapper] = useState(false);\n\tconst previousLoadingRef = useRef(loading);\n\tconst previousElementTypeRef =\n\t\tuseRef<ReactElement[\"type\"]>(currentElementType);\n\tconst previousElementKeyRef = useRef<ReactElement[\"key\"] | null>(\n\t\tcurrentElementKey,\n\t);\n\n\tconst setWrapperState = useCallback((next: boolean) => {\n\t\tneedsWrapperRef.current = next;\n\t\tsetNeedsWrapper(next);\n\t}, []);\n\n\tconst originalRef = getOriginalRef(element);\n\n\tconst enableWrapperWithWarning = useCallback(\n\t\t(reason: \"non-dom-ref\" | \"no-ref-call\") => {\n\t\t\tif (!needsWrapperRef.current) {\n\t\t\t\tsetWrapperState(true);\n\t\t\t}\n\n\t\t\tif (!suppressRefWarning && isDevEnv()) {\n\t\t\t\tconst displayName = getElementDisplayName(element);\n\t\t\t\tif (!warnedComponents.has(displayName)) {\n\t\t\t\t\tif (reason === \"non-dom-ref\") {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[SmartSkeleton] ${displayName} does not forward its ref to a DOM element. ` +\n\t\t\t\t\t\t\t\t`A wrapper <div> has been added automatically. Use forwardRef to avoid this.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`[SmartSkeleton] ${displayName} does not accept a ref. ` +\n\t\t\t\t\t\t\t\t`A wrapper <div> has been added automatically. Use forwardRef to avoid this.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\twarnedComponents.add(displayName);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[element, suppressRefWarning, setWrapperState],\n\t);\n\n\tconst refCallback = useCallback(\n\t\t(node: unknown) => {\n\t\t\trefWasCalledRef.current = true;\n\t\t\tlastRefNodeRef.current = node;\n\n\t\t\tconst target = resolveRefTarget(node);\n\n\t\t\tif (target && loading && !hasAppliedRef.current) {\n\t\t\t\tapplySkeletonClasses(target, { animate, seed });\n\t\t\t\thasAppliedRef.current = true;\n\t\t\t}\n\n\t\t\t// Forward ref to original element\n\t\t\tforwardRef(originalRef, node);\n\t\t},\n\t\t[loading, originalRef, animate, seed],\n\t);\n\n\t// Single layout effect: handles identity reset AND wrapper fallback decision.\n\t// Merged into one effect because React fires ref callbacks (during commit)\n\t// BEFORE layout effects. Having a separate reset effect would clear the ref\n\t// data that was just written by the current commit's ref callbacks.\n\tuseIsomorphicLayoutEffect(() => {\n\t\tconst previousLoading = previousLoadingRef.current;\n\t\tconst previousElementType = previousElementTypeRef.current;\n\t\tconst previousElementKey = previousElementKeyRef.current;\n\n\t\tconst didExitLoading = previousLoading && !loading;\n\t\tconst hasElementIdentityChanged =\n\t\t\tpreviousElementType !== currentElementType ||\n\t\t\tpreviousElementKey !== currentElementKey;\n\n\t\tpreviousLoadingRef.current = loading;\n\t\tpreviousElementTypeRef.current = currentElementType;\n\t\tpreviousElementKeyRef.current = currentElementKey;\n\n\t\tif (didExitLoading || hasElementIdentityChanged) {\n\t\t\thasAppliedRef.current = false;\n\t\t\tif (didExitLoading) {\n\t\t\t\trefWasCalledRef.current = false;\n\t\t\t\tlastRefNodeRef.current = null;\n\t\t\t} else if (hasElementIdentityChanged && lastRefNodeRef.current === null) {\n\t\t\t\t// Ignore cleanup-only ref callbacks from previous element identity.\n\t\t\t\trefWasCalledRef.current = false;\n\t\t\t}\n\n\t\t\tif (needsWrapperRef.current) {\n\t\t\t\tsetWrapperState(false);\n\t\t\t\t// Re-render will re-run this effect with the direct path.\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (!loading) return;\n\t\tif (needsWrapper) return;\n\n\t\tconst node = lastRefNodeRef.current;\n\t\tconst target = resolveRefTarget(node);\n\n\t\tif (target && !hasAppliedRef.current) {\n\t\t\tapplySkeletonClasses(target, { animate, seed });\n\t\t\thasAppliedRef.current = true;\n\t\t}\n\n\t\tif (refWasCalledRef.current) {\n\t\t\tif (node !== null && !target) {\n\t\t\t\tenableWrapperWithWarning(\"non-dom-ref\");\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (node !== null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Ref callback was only invoked with null during cleanup.\n\t\t\t// Treat as a missing ref call for the current element.\n\t\t\trefWasCalledRef.current = false;\n\t\t}\n\n\t\t// Ref was not called: the component doesn't accept refs.\n\t\t// Switch to wrapper mode synchronously (before browser paint).\n\t\tenableWrapperWithWarning(\"no-ref-call\");\n\t}, [\n\t\tloading,\n\t\tneedsWrapper,\n\t\tcurrentElementType,\n\t\tcurrentElementKey,\n\t\tanimate,\n\t\tseed,\n\t\tenableWrapperWithWarning,\n\t\tsetWrapperState,\n\t]);\n\n\t// Not loading: return children or null\n\tif (!loading) {\n\t\treturn children ?? null;\n\t}\n\n\t// Build merged className for skeleton mode\n\tconst elementProps = element.props as { className?: string };\n\tconst existingClassName = elementProps.className ?? \"\";\n\n\t// Base classes for skeleton mode\n\tconst baseClasses = [\"loaded-skeleton-mode\", animate && \"loaded-animate\"]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\t// When wrapping: wrapper gets mode + wrapper marker (no bg - it goes on child via ref)\n\tconst wrapperClassName = [baseClasses, \"loaded-skeleton-wrapper\", className]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\t// When not wrapping: element gets mode + bg directly (for SSR)\n\tconst mergedClassName = [\n\t\texistingClassName,\n\t\tbaseClasses,\n\t\t\"loaded-skeleton-bg\",\n\t\tclassName,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" \");\n\n\treturn (\n\t\t<SkeletonContext.Provider value={true}>\n\t\t\t{needsWrapper ? (\n\t\t\t\t<div ref={refCallback} className={wrapperClassName} aria-hidden=\"true\">\n\t\t\t\t\t{element}\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\tcloneElement(element as ReactElement<Record<string, unknown>>, {\n\t\t\t\t\tref: refCallback,\n\t\t\t\t\tclassName: mergedClassName,\n\t\t\t\t\t\"aria-hidden\": true,\n\t\t\t\t})\n\t\t\t)}\n\t\t</SkeletonContext.Provider>\n\t);\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { isDevEnv } from \"../../utils/isDevEnv\";\nimport { useIsomorphicLayoutEffect } from \"../../utils/useIsomorphicLayoutEffect\";\n\nconst STORAGE_KEY = \"react-loaded\";\nconst LEGACY_STORAGE_KEY = \"loaded\";\nconst STORAGE_VERSION = 1 as const;\n\ntype StoredCounts = Record<string, number>;\ntype StoredPayloadV1 = { v: typeof STORAGE_VERSION; counts: StoredCounts };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction toNumberRecord(value: unknown): StoredCounts {\n\tif (!isRecord(value)) return {};\n\tconst result: StoredCounts = {};\n\tfor (const [key, maybeNumber] of Object.entries(value)) {\n\t\tif (typeof maybeNumber === \"number\") {\n\t\t\tresult[key] = maybeNumber;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction parseStoredCounts(value: unknown): StoredCounts {\n\t// Current schema: { v: 1, counts: Record<string, number> }\n\tif (isRecord(value) && value.v === STORAGE_VERSION) {\n\t\treturn toNumberRecord(value.counts);\n\t}\n\n\t// Legacy schema: Record<string, number>\n\treturn toNumberRecord(value);\n}\n\nfunction readStoredCountsFromKey(key: string): StoredCounts {\n\tif (typeof localStorage === \"undefined\") return {};\n\ttry {\n\t\tconst raw = localStorage.getItem(key);\n\t\tif (raw === null) return {};\n\t\treturn parseStoredCounts(JSON.parse(raw));\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction writeStoredCounts(counts: StoredCounts): void {\n\tif (typeof localStorage === \"undefined\") return;\n\tconst payload: StoredPayloadV1 = { v: STORAGE_VERSION, counts };\n\ttry {\n\t\tlocalStorage.setItem(STORAGE_KEY, JSON.stringify(payload));\n\t} catch {\n\t\t// Silently fail if localStorage is full or unavailable\n\t}\n}\n\nfunction getStoredCounts(): Record<string, number> {\n\tif (typeof localStorage === \"undefined\") return {};\n\n\ttry {\n\t\tconst rawNew = localStorage.getItem(STORAGE_KEY);\n\t\tif (rawNew !== null) {\n\t\t\treturn parseStoredCounts(JSON.parse(rawNew));\n\t\t}\n\n\t\t// Backward compatibility: migrate legacy key once if present.\n\t\tconst legacyCounts = readStoredCountsFromKey(LEGACY_STORAGE_KEY);\n\t\tif (Object.keys(legacyCounts).length > 0) {\n\t\t\twriteStoredCounts(legacyCounts);\n\t\t}\n\t\treturn legacyCounts;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction getStoredCount(key: string): number | null {\n\tconst counts = getStoredCounts();\n\tconst value = counts[key];\n\treturn typeof value === \"number\" ? value : null;\n}\n\nfunction setStoredCount(key: string, count: number): void {\n\tif (typeof localStorage === \"undefined\") return;\n\n\ttry {\n\t\tconst counts = getStoredCounts();\n\t\tcounts[key] = count;\n\t\twriteStoredCounts(counts);\n\t} catch {\n\t\t// Silently fail if localStorage is full or unavailable\n\t}\n}\n\nexport interface UsePersistedCountOptions {\n\tstorageKey?: string;\n\tdefaultCount?: number;\n\tcurrentCount?: number;\n\tloading: boolean;\n\tminCount?: number;\n\tmaxCount?: number;\n}\n\nexport function usePersistedCount({\n\tstorageKey,\n\tdefaultCount = 3,\n\tcurrentCount,\n\tloading,\n\tminCount = 1,\n\tmaxCount,\n}: UsePersistedCountOptions): number {\n\t// Always start from the default to match SSR output, then (on the client)\n\t// sync to the persisted value in a layout effect before first paint.\n\tconst [count, setCount] = useState<number>(() =>\n\t\tclampCount(defaultCount, minCount, maxCount),\n\t);\n\n\tconst hasWarnedRef = useRef(false);\n\n\tuseIsomorphicLayoutEffect(() => {\n\t\tif (!storageKey) return;\n\t\tconst stored = getStoredCount(storageKey);\n\t\tif (stored === null) return;\n\t\tconst next = clampCount(stored, minCount, maxCount);\n\t\tsetCount((prev) => (Object.is(prev, next) ? prev : next));\n\t}, [storageKey, minCount, maxCount]);\n\n\tuseEffect(() => {\n\t\tif (!loading && currentCount !== undefined) {\n\t\t\tconst newCount = clampCount(currentCount, minCount, maxCount);\n\t\t\tsetCount(newCount);\n\n\t\t\tif (storageKey) {\n\t\t\t\tsetStoredCount(storageKey, newCount);\n\t\t\t}\n\t\t}\n\t}, [loading, currentCount, storageKey, minCount, maxCount]);\n\n\tuseEffect(() => {\n\t\tif (isDevEnv() && !storageKey && !hasWarnedRef.current) {\n\t\t\tconsole.warn(\n\t\t\t\t\"[Loaded] SmartSkeletonList used without storageKey. \" +\n\t\t\t\t\t\"The count will reset on remount. Add a storageKey to persist across sessions.\",\n\t\t\t);\n\t\t\thasWarnedRef.current = true;\n\t\t}\n\t}, [storageKey]);\n\n\treturn count;\n}\n\nfunction clampCount(\n\tvalue: number,\n\tmin: number,\n\tmax: number | undefined,\n): number {\n\tlet result = Math.max(value, min);\n\tif (max !== undefined) {\n\t\tresult = Math.min(result, max);\n\t}\n\treturn result;\n}\n","import { Fragment, type ReactElement } from \"react\";\nimport { usePersistedCount } from \"../../hooks/usePersistedCount/usePersistedCount\";\nimport { SmartSkeleton } from \"../SmartSkeleton/SmartSkeleton\";\n\nexport interface SmartSkeletonListProps<T> {\n\t/** Whether the list is currently loading. Default: false */\n\tloading?: boolean;\n\t/** The items to render. Pass undefined while loading. */\n\titems: T[] | undefined;\n\t/** Render function for each item when loaded */\n\trenderItem: (item: T, index: number) => ReactElement;\n\t/** Render function for skeleton placeholders */\n\trenderSkeleton: (index: number) => ReactElement;\n\t/** Key for localStorage persistence. Without it, count resets on remount. */\n\tstorageKey?: string;\n\t/** Initial skeleton count before any data is known. Default: 3 */\n\tdefaultCount?: number;\n\t/** Minimum skeletons to show. Default: 1 */\n\tminCount?: number;\n\t/** Maximum skeletons to show */\n\tmaxCount?: number;\n\t/** Enable shimmer animation. Default: true */\n\tanimate?: boolean;\n\t/** Optional seed to stabilize skeleton text widths */\n\tseed?: string | number;\n\t/** Suppress warning when auto-wrapper is applied. Default: false */\n\tsuppressRefWarning?: boolean;\n\t/** Extract unique key for each item. Default: index */\n\tkeyExtractor?: (item: T, index: number) => string | number;\n}\n\nexport function SmartSkeletonList<T>({\n\tloading = false,\n\titems,\n\trenderItem,\n\trenderSkeleton,\n\tstorageKey,\n\tdefaultCount = 3,\n\tminCount = 1,\n\tmaxCount,\n\tanimate = true,\n\tseed,\n\tsuppressRefWarning = false,\n\tkeyExtractor = (_, index) => index,\n}: SmartSkeletonListProps<T>): ReactElement | null {\n\tconst skeletonCount = usePersistedCount({\n\t\tstorageKey,\n\t\tdefaultCount,\n\t\tcurrentCount: items?.length,\n\t\tloading,\n\t\tminCount,\n\t\tmaxCount,\n\t});\n\n\tif (loading) {\n\t\tconst skeletons = new Array(skeletonCount);\n\t\tfor (let index = 0; index < skeletonCount; index += 1) {\n\t\t\tconst itemSeed = seed === undefined ? `${index}` : `${seed}:${index}`;\n\t\t\tskeletons[index] = (\n\t\t\t\t<SmartSkeleton\n\t\t\t\t\tkey={`skeleton-${index}`}\n\t\t\t\t\tloading={true}\n\t\t\t\t\telement={renderSkeleton(index)}\n\t\t\t\t\tanimate={animate}\n\t\t\t\t\tseed={itemSeed}\n\t\t\t\t\tsuppressRefWarning={suppressRefWarning}\n\t\t\t\t/>\n\t\t\t);\n\t\t}\n\t\treturn <>{skeletons}</>;\n\t}\n\n\tif (!items || items.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{items.map((item, index) => (\n\t\t\t\t<Fragment key={keyExtractor(item, index)}>\n\t\t\t\t\t{renderItem(item, index)}\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</>\n\t);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-loaded",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Zero-layout-shift skeleton screens for React",
5
5
  "homepage": "https://github.com/Pierre-LHOSTE/react-loaded#readme",
6
6
  "repository": {