instaskeleton 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -23,7 +23,6 @@
23
23
  - [HOC Pattern](#hoc-pattern)
24
24
  - [API Reference](#api-reference)
25
25
  - [Performance](#performance)
26
- - [Examples](#example-app)
27
26
  - [Browser Support](#browser-support)
28
27
  - [License](#license)
29
28
 
@@ -270,38 +269,12 @@ Animations are disabled automatically when `prefers-reduced-motion: reduce` is s
270
269
  | Lists with repeated items | `infer` + `cacheKey` | Cached after first render |
271
270
  | Complex nested structures | `infer` + `inferOptions` | Tune depth/node limits |
272
271
 
273
- ## Example App
274
-
275
- The local example app is a comprehensive visual reference covering:
276
-
277
- - Profile cards, product grids, social feeds
278
- - Tables, file lists, pricing cards
279
- - Settings forms with mixed controls
280
- - Chat threads, deeply nested comment threads
281
- - Dashboard layouts with nested cards
282
- - E-commerce product detail pages
283
- - Multi-level navigation structures
284
- - Mixed media galleries
285
- - Complex forms with validation states
286
- - Manual schema mirrors showing exact structure
287
- - HOC usage patterns
288
- - All primitive node types
289
- - Animation comparison (shimmer, pulse, none)
290
-
291
- Run it from the repo root:
292
-
293
- ```bash
294
- npm run example:install
295
- npm run example:dev
296
- ```
297
-
298
272
  ## Development
299
273
 
300
274
  ```bash
301
275
  npm run build # Build the library
302
276
  npm run typecheck # Run TypeScript checks
303
277
  npm run dev # Watch mode
304
- npm run example:dev # Run example app
305
278
  ```
306
279
 
307
280
  ## Browser Support
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var g=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var v=(e,t)=>{for(var n in t)g(e,n,{get:t[n],enumerable:!0})},P=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of b(t))!w.call(e,r)&&r!==n&&g(e,r,{get:()=>t[r],enumerable:!(o=x(t,r))||o.enumerable});return e};var C=e=>P(g({},"__esModule",{value:!0}),e);var D={};v(D,{InstaSkeleton:()=>y,clearInstaSkeletonCache:()=>I,withInstaSkeleton:()=>N});module.exports=C(D);var l=require("react"),a=require("react/jsx-runtime"),R={maxDepth:6,maxNodes:120,textLineHeight:"0.95rem"},A=100,m=new Map;function E(e,t){if(m.size>=A){let n=m.keys().next().value;n&&m.delete(n)}m.set(e,t)}function L(e){return e?Array.isArray(e)?e:[e]:[]}function h(e,t){return e??t}function W(e,t){let n={...R,...t},o=0,r=(i,d)=>{if(o>=n.maxNodes||d>n.maxDepth)return[];if(i==null||typeof i=="boolean")return[];if(typeof i=="string"||typeof i=="number")return o+=1,[{type:"line",height:n.textLineHeight}];if(Array.isArray(i))return i.flatMap(p=>r(p,d+1));if(!(0,l.isValidElement)(i))return[];o+=1;let s=typeof i.type=="string"?i.type:"component";if(s==="img"||s==="video"||s==="svg"||s==="canvas")return[{type:"rect",height:"8rem"}];if(s==="button"||s==="input"||s==="textarea"||s==="select")return[{type:"rect",height:"2.5rem",radius:"0.5rem"}];let u=r(i.props.children,d+1);return u.length===0?[{type:"line",width:"70%",height:n.textLineHeight}]:u.length===1?u:[{type:"group",children:u}]};return r(l.Children.toArray(e),0)}function k(e){let t={};return e.width!==void 0&&(t.width=h(e.width,"")),e.height!==void 0&&(t.height=h(e.height,"")),e.radius!==void 0&&(t.borderRadius=h(e.radius,"")),e.gap!==void 0&&(t.gap=h(e.gap,"")),t}var S=(0,l.memo)(function e({node:t,animation:n}){if(t.type==="group")return(0,a.jsx)("div",{className:"is-group",style:k(t),children:(t.children??[]).map((r,i)=>(0,a.jsx)(e,{node:r,animation:n},i))});let o=n==="none"?"":` is-anim-${n}`;return(0,a.jsx)("div",{className:`is-node is-${t.type}${o}`,style:k(t),"aria-hidden":"true"})}),y=(0,l.memo)(function({loading:t,children:n,schema:o,infer:r=!0,cacheKey:i,className:d,animation:s="shimmer",inferOptions:u}){if(!t)return(0,a.jsx)(a.Fragment,{children:n});let p=(0,l.useMemo)(()=>{let f=L(o);if(f.length>0)return f;if(!r)return[];if(i&&m.has(i))return m.get(i)??[];let c=W(n,u);return i&&E(i,c),c},[o,r,n,i,u]);return(0,a.jsx)("div",{className:["is-root",d].filter(Boolean).join(" "),role:"status","aria-live":"polite","aria-busy":"true",children:p.length>0?p.map((f,c)=>(0,a.jsx)(S,{node:f,animation:s},c)):(0,a.jsx)(S,{node:{type:"line"},animation:s})})});function N(e,t){let n=o=>{let{loading:r,...i}=o;return(0,a.jsx)(y,{loading:r,schema:t?.skeleton,infer:t?.infer,cacheKey:t?.cacheKey,className:t?.className,animation:t?.animation,children:(0,a.jsx)(e,{...i})})};return n.displayName=`withInstaSkeleton(${e.displayName||e.name||"Component"})`,(0,l.memo)(n)}function I(e){if(e){m.delete(e);return}m.clear()}0&&(module.exports={InstaSkeleton,clearInstaSkeletonCache,withInstaSkeleton});
1
+ "use strict";var h=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var b=(e,t)=>{for(var i in t)h(e,i,{get:t[i],enumerable:!0})},v=(e,t,i,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of x(t))!w.call(e,r)&&r!==i&&h(e,r,{get:()=>t[r],enumerable:!(o=I(t,r))||o.enumerable});return e};var P=e=>v(h({},"__esModule",{value:!0}),e);var W={};b(W,{InstaSkeleton:()=>k,clearInstaSkeletonCache:()=>N,withInstaSkeleton:()=>S});module.exports=P(W);var l=require("react"),a=require("react/jsx-runtime"),C={maxDepth:6,maxNodes:120,textLineHeight:"0.95rem"},R=100,m=new Map;function A(e,t){if(m.size>=R){let i=m.keys().next().value;i&&m.delete(i)}m.set(e,t)}function E(e){return e?Array.isArray(e)?e:[e]:[]}function L(e,t){let i={...C,...t},o=0,r=(n,d)=>{if(o>=i.maxNodes||d>i.maxDepth)return[];if(n==null||typeof n=="boolean")return[];if(typeof n=="string"||typeof n=="number")return o+=1,[{type:"line",height:i.textLineHeight}];if(Array.isArray(n))return n.flatMap(p=>r(p,d+1));if(!(0,l.isValidElement)(n))return[];o+=1;let s=typeof n.type=="string"?n.type:"component";if(s==="img"||s==="video"||s==="svg"||s==="canvas")return[{type:"rect",height:"8rem"}];if(s==="button"||s==="input"||s==="textarea"||s==="select")return[{type:"rect",height:"2.5rem",radius:"0.5rem"}];let u=r(n.props.children,d+1);return u.length===0?[{type:"line",width:"70%",height:i.textLineHeight}]:u.length===1?u:[{type:"group",children:u}]};return r(l.Children.toArray(e),0)}function g(e){let t={};return e.width!==void 0&&(t.width=e.width),e.height!==void 0&&(t.height=e.height),e.radius!==void 0&&(t.borderRadius=e.radius),e.gap!==void 0&&(t.gap=e.gap),e.direction!==void 0&&(t.flexDirection=e.direction),e.align!==void 0&&(t.alignItems=e.align),t}var y=(0,l.memo)(function e({node:t,animation:i}){if(t.type==="group")return(0,a.jsx)("div",{className:"isk-group",style:g(t),children:(t.children??[]).map((r,n)=>(0,a.jsx)(e,{node:r,animation:i},n))});let o=i==="none"?"":` isk-anim-${i}`;return(0,a.jsx)("div",{className:`isk-node isk-${t.type}${o}`,style:g(t),"aria-hidden":"true"})}),k=(0,l.memo)(function({loading:t,children:i,schema:o,infer:r=!0,cacheKey:n,className:d,animation:s="shimmer",inferOptions:u}){let p=(0,l.useMemo)(()=>{if(!t)return[];let f=E(o);if(f.length>0)return f;if(!r)return[];if(n&&m.has(n))return m.get(n)??[];let c=L(i,u);return n&&A(n,c),c},[t,o,r,i,n,u]);return t?(0,a.jsx)("div",{className:["isk-root",d].filter(Boolean).join(" "),role:"status","aria-live":"polite","aria-busy":"true",children:p.length>0?p.map((f,c)=>(0,a.jsx)(y,{node:f,animation:s},c)):(0,a.jsx)(y,{node:{type:"line"},animation:s})}):(0,a.jsx)(a.Fragment,{children:i})});function S(e,t){let i=o=>{let{loading:r,...n}=o;return(0,a.jsx)(k,{loading:r,schema:t?.skeleton,infer:t?.infer,cacheKey:t?.cacheKey,className:t?.className,animation:t?.animation,children:(0,a.jsx)(e,{...n})})};return i.displayName=`withInstaSkeleton(${e.displayName||e.name||"Component"})`,(0,l.memo)(i)}function N(e){if(e){m.delete(e);return}m.clear()}0&&(module.exports={InstaSkeleton,clearInstaSkeletonCache,withInstaSkeleton});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core.tsx"],"sourcesContent":["import './styles.css';\n\nexport { InstaSkeleton, clearInstaSkeletonCache, withInstaSkeleton } from './core';\nexport type { InferOptions, InstaSkeletonProps, SkeletonNode, SkeletonNodeType, WithInstaSkeletonProps } from './types';\n","import React, { Children, isValidElement, memo, useMemo } from 'react';\nimport type {\n InferOptions,\n InstaSkeletonProps,\n SkeletonNode,\n WithInstaSkeletonProps\n} from './types';\n\nconst DEFAULT_INFER: Required<InferOptions> = {\n maxDepth: 6,\n maxNodes: 120,\n textLineHeight: '0.95rem'\n};\n\nconst CACHE_MAX_SIZE = 100;\nconst schemaCache = new Map<string, SkeletonNode[]>();\n\nfunction setCacheWithLimit(key: string, value: SkeletonNode[]): void {\n if (schemaCache.size >= CACHE_MAX_SIZE) {\n const firstKey = schemaCache.keys().next().value;\n if (firstKey) schemaCache.delete(firstKey);\n }\n schemaCache.set(key, value);\n}\n\nfunction normalizeSchema(schema?: SkeletonNode | SkeletonNode[]): SkeletonNode[] {\n if (!schema) return [];\n return Array.isArray(schema) ? schema : [schema];\n}\n\nfunction resolveDimension(value: string | number | undefined, fallback: string | number): string | number {\n return value ?? fallback;\n}\n\nfunction inferFromChildren(children: React.ReactNode, options?: InferOptions): SkeletonNode[] {\n const merged = { ...DEFAULT_INFER, ...options };\n let nodeCount = 0;\n\n const walk = (node: React.ReactNode, depth: number): SkeletonNode[] => {\n if (nodeCount >= merged.maxNodes || depth > merged.maxDepth) return [];\n if (node == null || typeof node === 'boolean') return [];\n\n if (typeof node === 'string' || typeof node === 'number') {\n nodeCount += 1;\n return [{ type: 'line', height: merged.textLineHeight }];\n }\n\n if (Array.isArray(node)) {\n return node.flatMap((item) => walk(item, depth + 1));\n }\n\n if (!isValidElement(node)) {\n return [];\n }\n\n nodeCount += 1;\n\n const elType = typeof node.type === 'string' ? node.type : 'component';\n\n if (elType === 'img' || elType === 'video' || elType === 'svg' || elType === 'canvas') {\n return [{ type: 'rect', height: '8rem' }];\n }\n\n if (elType === 'button' || elType === 'input' || elType === 'textarea' || elType === 'select') {\n return [{ type: 'rect', height: '2.5rem', radius: '0.5rem' }];\n }\n\n const childNodes = walk(node.props.children, depth + 1);\n\n if (childNodes.length === 0) {\n return [{ type: 'line', width: '70%', height: merged.textLineHeight }];\n }\n\n if (childNodes.length === 1) {\n return childNodes;\n }\n\n return [{ type: 'group', children: childNodes }];\n };\n\n return walk(Children.toArray(children), 0);\n}\n\nfunction nodeStyle(node: SkeletonNode): React.CSSProperties {\n const style: React.CSSProperties = {};\n\n if (node.width !== undefined) style.width = resolveDimension(node.width, '');\n if (node.height !== undefined) style.height = resolveDimension(node.height, '');\n if (node.radius !== undefined) style.borderRadius = resolveDimension(node.radius, '');\n if (node.gap !== undefined) style.gap = resolveDimension(node.gap, '');\n\n return style;\n}\n\nconst NodeView = memo(function NodeView({ node, animation }: { node: SkeletonNode; animation: InstaSkeletonProps['animation'] }) {\n if (node.type === 'group') {\n return (\n <div className=\"is-group\" style={nodeStyle(node)}>\n {(node.children ?? []).map((child, index) => (\n <NodeView key={index} node={child} animation={animation} />\n ))}\n </div>\n );\n }\n\n const animClass = animation === 'none' ? '' : ` is-anim-${animation}`;\n return <div className={`is-node is-${node.type}${animClass}`} style={nodeStyle(node)} aria-hidden=\"true\" />;\n});\n\nexport const InstaSkeleton = memo(function InstaSkeleton({\n loading,\n children,\n schema,\n infer = true,\n cacheKey,\n className,\n animation = 'shimmer',\n inferOptions\n}: InstaSkeletonProps) {\n // Early exit: skip all inference work when not loading\n if (!loading) return <>{children}</>;\n\n const skeletonSchema = useMemo(() => {\n const normalized = normalizeSchema(schema);\n if (normalized.length > 0) return normalized;\n if (!infer) return [];\n\n if (cacheKey && schemaCache.has(cacheKey)) {\n return schemaCache.get(cacheKey) ?? [];\n }\n\n const inferred = inferFromChildren(children, inferOptions);\n if (cacheKey) setCacheWithLimit(cacheKey, inferred);\n return inferred;\n }, [schema, infer, children, cacheKey, inferOptions]);\n\n return (\n <div className={['is-root', className].filter(Boolean).join(' ')} role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n {skeletonSchema.length > 0 ? (\n skeletonSchema.map((node, index) => <NodeView key={index} node={node} animation={animation} />)\n ) : (\n <NodeView node={{ type: 'line' }} animation={animation} />\n )}\n </div>\n );\n});\n\nexport function withInstaSkeleton<P extends object>(\n Component: React.ComponentType<P>,\n options?: Omit<WithInstaSkeletonProps, 'loading'>\n) {\n const Wrapped = (props: P & { loading: boolean }) => {\n const { loading, ...rest } = props;\n\n return (\n <InstaSkeleton\n loading={loading}\n schema={options?.skeleton}\n infer={options?.infer}\n cacheKey={options?.cacheKey}\n className={options?.className}\n animation={options?.animation}\n >\n <Component {...(rest as P)} />\n </InstaSkeleton>\n );\n };\n\n Wrapped.displayName = `withInstaSkeleton(${Component.displayName || Component.name || 'Component'})`;\n\n return memo(Wrapped);\n}\n\nexport function clearInstaSkeletonCache(key?: string): void {\n if (key) {\n schemaCache.delete(key);\n return;\n }\n\n schemaCache.clear();\n}\n"],"mappings":"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","names":["index_exports","__export","InstaSkeleton","clearInstaSkeletonCache","withInstaSkeleton","__toCommonJS","import_react","import_jsx_runtime","DEFAULT_INFER","CACHE_MAX_SIZE","schemaCache","setCacheWithLimit","key","value","firstKey","normalizeSchema","schema","resolveDimension","fallback","inferFromChildren","children","options","merged","nodeCount","walk","node","depth","item","elType","childNodes","nodeStyle","style","NodeView","animation","child","index","animClass","InstaSkeleton","loading","infer","cacheKey","className","inferOptions","skeletonSchema","normalized","inferred","withInstaSkeleton","Component","Wrapped","props","rest","clearInstaSkeletonCache"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core.tsx"],"sourcesContent":["import './styles.css';\n\nexport { InstaSkeleton, clearInstaSkeletonCache, withInstaSkeleton } from './core';\nexport type { InferOptions, InstaSkeletonProps, SkeletonNode, SkeletonNodeType, WithInstaSkeletonProps } from './types';\n","import React, { Children, isValidElement, memo, useMemo } from 'react';\nimport type {\n InferOptions,\n InstaSkeletonProps,\n SkeletonNode,\n WithInstaSkeletonProps\n} from './types';\n\nconst DEFAULT_INFER: Required<InferOptions> = {\n maxDepth: 6,\n maxNodes: 120,\n textLineHeight: '0.95rem'\n};\n\nconst CACHE_MAX_SIZE = 100;\nconst schemaCache = new Map<string, SkeletonNode[]>();\n\nfunction setCacheWithLimit(key: string, value: SkeletonNode[]): void {\n if (schemaCache.size >= CACHE_MAX_SIZE) {\n const firstKey = schemaCache.keys().next().value;\n if (firstKey) schemaCache.delete(firstKey);\n }\n schemaCache.set(key, value);\n}\n\nfunction normalizeSchema(schema?: SkeletonNode | SkeletonNode[]): SkeletonNode[] {\n if (!schema) return [];\n return Array.isArray(schema) ? schema : [schema];\n}\n\nfunction inferFromChildren(children: React.ReactNode, options?: InferOptions): SkeletonNode[] {\n const merged = { ...DEFAULT_INFER, ...options };\n let nodeCount = 0;\n\n const walk = (node: React.ReactNode, depth: number): SkeletonNode[] => {\n if (nodeCount >= merged.maxNodes || depth > merged.maxDepth) return [];\n if (node == null || typeof node === 'boolean') return [];\n\n if (typeof node === 'string' || typeof node === 'number') {\n nodeCount += 1;\n return [{ type: 'line', height: merged.textLineHeight }];\n }\n\n if (Array.isArray(node)) {\n return node.flatMap((item) => walk(item, depth + 1));\n }\n\n if (!isValidElement(node)) {\n return [];\n }\n\n nodeCount += 1;\n\n const elType = typeof node.type === 'string' ? node.type : 'component';\n\n if (elType === 'img' || elType === 'video' || elType === 'svg' || elType === 'canvas') {\n return [{ type: 'rect', height: '8rem' }];\n }\n\n if (elType === 'button' || elType === 'input' || elType === 'textarea' || elType === 'select') {\n return [{ type: 'rect', height: '2.5rem', radius: '0.5rem' }];\n }\n\n const childNodes = walk(node.props.children, depth + 1);\n\n if (childNodes.length === 0) {\n return [{ type: 'line', width: '70%', height: merged.textLineHeight }];\n }\n\n if (childNodes.length === 1) {\n return childNodes;\n }\n\n return [{ type: 'group', children: childNodes }];\n };\n\n return walk(Children.toArray(children), 0);\n}\n\nfunction nodeStyle(node: SkeletonNode): React.CSSProperties {\n const style: React.CSSProperties = {};\n\n if (node.width !== undefined) style.width = node.width;\n if (node.height !== undefined) style.height = node.height;\n if (node.radius !== undefined) style.borderRadius = node.radius;\n if (node.gap !== undefined) style.gap = node.gap;\n if (node.direction !== undefined) style.flexDirection = node.direction;\n if (node.align !== undefined) style.alignItems = node.align;\n\n return style;\n}\n\nconst NodeView = memo(function NodeView({ node, animation }: { node: SkeletonNode; animation: InstaSkeletonProps['animation'] }) {\n if (node.type === 'group') {\n return (\n <div className=\"isk-group\" style={nodeStyle(node)}>\n {(node.children ?? []).map((child, index) => (\n <NodeView key={index} node={child} animation={animation} />\n ))}\n </div>\n );\n }\n\n const animClass = animation === 'none' ? '' : ` isk-anim-${animation}`;\n return <div className={`isk-node isk-${node.type}${animClass}`} style={nodeStyle(node)} aria-hidden=\"true\" />;\n});\n\nexport const InstaSkeleton = memo(function InstaSkeleton({\n loading,\n children,\n schema,\n infer = true,\n cacheKey,\n className,\n animation = 'shimmer',\n inferOptions\n}: InstaSkeletonProps) {\n const skeletonSchema = useMemo(() => {\n if (!loading) return [];\n\n const normalized = normalizeSchema(schema);\n if (normalized.length > 0) return normalized;\n if (!infer) return [];\n\n if (cacheKey && schemaCache.has(cacheKey)) {\n return schemaCache.get(cacheKey) ?? [];\n }\n\n const inferred = inferFromChildren(children, inferOptions);\n if (cacheKey) setCacheWithLimit(cacheKey, inferred);\n return inferred;\n }, [loading, schema, infer, children, cacheKey, inferOptions]);\n\n if (!loading) return <>{children}</>;\n\n return (\n <div className={['isk-root', className].filter(Boolean).join(' ')} role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n {skeletonSchema.length > 0 ? (\n skeletonSchema.map((node, index) => <NodeView key={index} node={node} animation={animation} />)\n ) : (\n <NodeView node={{ type: 'line' }} animation={animation} />\n )}\n </div>\n );\n});\n\nexport function withInstaSkeleton<P extends object>(\n Component: React.ComponentType<P>,\n options?: Omit<WithInstaSkeletonProps, 'loading'>\n) {\n const Wrapped = (props: P & { loading: boolean }) => {\n const { loading, ...rest } = props;\n\n return (\n <InstaSkeleton\n loading={loading}\n schema={options?.skeleton}\n infer={options?.infer}\n cacheKey={options?.cacheKey}\n className={options?.className}\n animation={options?.animation}\n >\n <Component {...(rest as P)} />\n </InstaSkeleton>\n );\n };\n\n Wrapped.displayName = `withInstaSkeleton(${Component.displayName || Component.name || 'Component'})`;\n\n return memo(Wrapped);\n}\n\nexport function clearInstaSkeletonCache(key?: string): void {\n if (key) {\n schemaCache.delete(key);\n return;\n }\n\n schemaCache.clear();\n}\n"],"mappings":"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","names":["index_exports","__export","InstaSkeleton","clearInstaSkeletonCache","withInstaSkeleton","__toCommonJS","import_react","import_jsx_runtime","DEFAULT_INFER","CACHE_MAX_SIZE","schemaCache","setCacheWithLimit","key","value","firstKey","normalizeSchema","schema","inferFromChildren","children","options","merged","nodeCount","walk","node","depth","item","elType","childNodes","nodeStyle","style","NodeView","animation","child","index","animClass","InstaSkeleton","loading","infer","cacheKey","className","inferOptions","skeletonSchema","normalized","inferred","withInstaSkeleton","Component","Wrapped","props","rest","clearInstaSkeletonCache"]}
package/dist/index.css CHANGED
@@ -1,2 +1,2 @@
1
- .is-root{display:flex;flex-direction:column;gap:.75rem;width:100%}.is-node{position:relative;overflow:hidden;background:#e6e6e6;border-radius:.5rem}.is-line{height:.95rem;width:100%;border-radius:999px}.is-rect{width:100%;height:5rem}.is-circle{width:2.5rem;height:2.5rem;border-radius:999px}.is-group{display:flex;flex-direction:column;gap:.5rem}.is-anim-shimmer:after{content:"";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.6),transparent);animation:is-shimmer 1.2s linear infinite;will-change:transform}.is-anim-pulse{animation:is-pulse 1.1s ease-in-out infinite}@keyframes is-shimmer{to{transform:translate(100%)}}@keyframes is-pulse{0%{opacity:1}50%{opacity:.6}to{opacity:1}}@media(prefers-reduced-motion:reduce){.is-anim-shimmer:after,.is-anim-pulse{animation:none}}
1
+ .isk-root{display:flex;flex-direction:column;gap:.75rem;width:100%}.isk-node{position:relative;overflow:hidden;background:#e6e6e6;border-radius:.5rem}.isk-line{height:.95rem;width:100%;border-radius:999px}.isk-rect{width:100%;height:5rem}.isk-circle{width:2.5rem;height:2.5rem;border-radius:999px}.isk-group{display:flex;flex-direction:column;gap:.5rem}.isk-anim-shimmer:after{content:"";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,rgba(255,255,255,.6),transparent);animation:isk-shimmer 1.2s linear infinite;will-change:transform}.isk-anim-pulse{animation:isk-pulse 1.1s ease-in-out infinite}@keyframes isk-shimmer{to{transform:translate(100%)}}@keyframes isk-pulse{0%{opacity:1}50%{opacity:.6}to{opacity:1}}@media(prefers-reduced-motion:reduce){.isk-anim-shimmer:after,.isk-anim-pulse{animation:none}}
2
2
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/styles.css"],"sourcesContent":[".is-root {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n width: 100%;\n}\n\n.is-node {\n position: relative;\n overflow: hidden;\n background: #e6e6e6;\n border-radius: 0.5rem;\n}\n\n.is-line {\n height: 0.95rem;\n width: 100%;\n border-radius: 999px;\n}\n\n.is-rect {\n width: 100%;\n height: 5rem;\n}\n\n.is-circle {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: 999px;\n}\n\n.is-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.is-anim-shimmer::after {\n content: '';\n position: absolute;\n inset: 0;\n transform: translateX(-100%);\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);\n animation: is-shimmer 1.2s linear infinite;\n will-change: transform;\n}\n\n.is-anim-pulse {\n animation: is-pulse 1.1s ease-in-out infinite;\n}\n\n@keyframes is-shimmer {\n 100% {\n transform: translateX(100%);\n }\n}\n\n@keyframes is-pulse {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: 0.6;\n }\n 100% {\n opacity: 1;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .is-anim-shimmer::after,\n .is-anim-pulse {\n animation: none;\n }\n}\n"],"mappings":"AAAA,CAAC,QACC,QAAS,KACT,eAAgB,OAChB,IAAK,OACL,MAAO,IACT,CAEA,CAAC,QACC,SAAU,SACV,SAAU,OACV,WAAY,QAVd,cAWiB,KACjB,CAEA,CAAC,QACC,OAAQ,OACR,MAAO,KAhBT,cAiBiB,KACjB,CAEA,CAAC,QACC,MAAO,KACP,OAAQ,IACV,CAEA,CAAC,UACC,MAAO,OACP,OAAQ,OA3BV,cA4BiB,KACjB,CAEA,CAAC,SACC,QAAS,KACT,eAAgB,OAChB,IAAK,KACP,CAEA,CAAC,eAAe,OACd,QAAS,GACT,SAAU,SAvCZ,MAwCS,EACP,UAAW,UAAW,OACtB,WAAY,gBAAgB,KAAK,CAAE,WAAW,CAAE,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,GAAI,CAAE,aAC1E,UAAW,WAAW,KAAK,OAAO,SAClC,YAAa,SACf,CAEA,CAAC,cACC,UAAW,SAAS,KAAK,YAAY,QACvC,CAEA,WARa,WASX,GACE,UAAW,UAAW,KACxB,CACF,CAEA,WATa,SAUX,GACE,QAAS,CACX,CACA,IACE,QAAS,EACX,CACA,GACE,QAAS,CACX,CACF,CAEA,OAAO,uBAAyB,QAC9B,CAjCD,eAiCiB,OAChB,CAxBD,cAyBG,UAAW,IACb,CACF","names":[]}
1
+ {"version":3,"sources":["../src/styles.css"],"sourcesContent":[".isk-root {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n width: 100%;\n}\n\n.isk-node {\n position: relative;\n overflow: hidden;\n background: #e6e6e6;\n border-radius: 0.5rem;\n}\n\n.isk-line {\n height: 0.95rem;\n width: 100%;\n border-radius: 999px;\n}\n\n.isk-rect {\n width: 100%;\n height: 5rem;\n}\n\n.isk-circle {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: 999px;\n}\n\n.isk-group {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.isk-anim-shimmer::after {\n content: '';\n position: absolute;\n inset: 0;\n transform: translateX(-100%);\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.6), transparent);\n animation: isk-shimmer 1.2s linear infinite;\n will-change: transform;\n}\n\n.isk-anim-pulse {\n animation: isk-pulse 1.1s ease-in-out infinite;\n}\n\n@keyframes isk-shimmer {\n 100% {\n transform: translateX(100%);\n }\n}\n\n@keyframes isk-pulse {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: 0.6;\n }\n 100% {\n opacity: 1;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .isk-anim-shimmer::after,\n .isk-anim-pulse {\n animation: none;\n }\n}\n"],"mappings":"AAAA,CAAC,SACC,QAAS,KACT,eAAgB,OAChB,IAAK,OACL,MAAO,IACT,CAEA,CAAC,SACC,SAAU,SACV,SAAU,OACV,WAAY,QAVd,cAWiB,KACjB,CAEA,CAAC,SACC,OAAQ,OACR,MAAO,KAhBT,cAiBiB,KACjB,CAEA,CAAC,SACC,MAAO,KACP,OAAQ,IACV,CAEA,CAAC,WACC,MAAO,OACP,OAAQ,OA3BV,cA4BiB,KACjB,CAEA,CAAC,UACC,QAAS,KACT,eAAgB,OAChB,IAAK,KACP,CAEA,CAAC,gBAAgB,OACf,QAAS,GACT,SAAU,SAvCZ,MAwCS,EACP,UAAW,UAAW,OACtB,WAAY,gBAAgB,KAAK,CAAE,WAAW,CAAE,KAAK,GAAG,CAAE,GAAG,CAAE,GAAG,CAAE,GAAI,CAAE,aAC1E,UAAW,YAAY,KAAK,OAAO,SACnC,YAAa,SACf,CAEA,CAAC,eACC,UAAW,UAAU,KAAK,YAAY,QACxC,CAEA,WARa,YASX,GACE,UAAW,UAAW,KACxB,CACF,CAEA,WATa,UAUX,GACE,QAAS,CACX,CACA,IACE,QAAS,EACX,CACA,GACE,QAAS,CACX,CACF,CAEA,OAAO,uBAAyB,QAC9B,CAjCD,gBAiCkB,OACjB,CAxBD,eAyBG,UAAW,IACb,CACF","names":[]}
package/dist/index.d.cts CHANGED
@@ -8,6 +8,8 @@ interface SkeletonNode {
8
8
  height?: string | number;
9
9
  radius?: string | number;
10
10
  gap?: string | number;
11
+ direction?: 'row' | 'column';
12
+ align?: 'start' | 'center' | 'end' | 'stretch';
11
13
  children?: SkeletonNode[];
12
14
  }
13
15
  interface InferOptions {
package/dist/index.d.ts CHANGED
@@ -8,6 +8,8 @@ interface SkeletonNode {
8
8
  height?: string | number;
9
9
  radius?: string | number;
10
10
  gap?: string | number;
11
+ direction?: 'row' | 'column';
12
+ align?: 'start' | 'center' | 'end' | 'stretch';
11
13
  children?: SkeletonNode[];
12
14
  }
13
15
  interface InferOptions {
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{Children as S,isValidElement as N,memo as h,useMemo as I}from"react";import{Fragment as A,jsx as s}from"react/jsx-runtime";var x={maxDepth:6,maxNodes:120,textLineHeight:"0.95rem"},b=100,l=new Map;function w(e,t){if(l.size>=b){let i=l.keys().next().value;i&&l.delete(i)}l.set(e,t)}function v(e){return e?Array.isArray(e)?e:[e]:[]}function c(e,t){return e??t}function P(e,t){let i={...x,...t},o=0,a=(n,u)=>{if(o>=i.maxNodes||u>i.maxDepth)return[];if(n==null||typeof n=="boolean")return[];if(typeof n=="string"||typeof n=="number")return o+=1,[{type:"line",height:i.textLineHeight}];if(Array.isArray(n))return n.flatMap(d=>a(d,u+1));if(!N(n))return[];o+=1;let r=typeof n.type=="string"?n.type:"component";if(r==="img"||r==="video"||r==="svg"||r==="canvas")return[{type:"rect",height:"8rem"}];if(r==="button"||r==="input"||r==="textarea"||r==="select")return[{type:"rect",height:"2.5rem",radius:"0.5rem"}];let m=a(n.props.children,u+1);return m.length===0?[{type:"line",width:"70%",height:i.textLineHeight}]:m.length===1?m:[{type:"group",children:m}]};return a(S.toArray(e),0)}function g(e){let t={};return e.width!==void 0&&(t.width=c(e.width,"")),e.height!==void 0&&(t.height=c(e.height,"")),e.radius!==void 0&&(t.borderRadius=c(e.radius,"")),e.gap!==void 0&&(t.gap=c(e.gap,"")),t}var y=h(function e({node:t,animation:i}){if(t.type==="group")return s("div",{className:"is-group",style:g(t),children:(t.children??[]).map((a,n)=>s(e,{node:a,animation:i},n))});let o=i==="none"?"":` is-anim-${i}`;return s("div",{className:`is-node is-${t.type}${o}`,style:g(t),"aria-hidden":"true"})}),k=h(function({loading:t,children:i,schema:o,infer:a=!0,cacheKey:n,className:u,animation:r="shimmer",inferOptions:m}){if(!t)return s(A,{children:i});let d=I(()=>{let p=v(o);if(p.length>0)return p;if(!a)return[];if(n&&l.has(n))return l.get(n)??[];let f=P(i,m);return n&&w(n,f),f},[o,a,i,n,m]);return s("div",{className:["is-root",u].filter(Boolean).join(" "),role:"status","aria-live":"polite","aria-busy":"true",children:d.length>0?d.map((p,f)=>s(y,{node:p,animation:r},f)):s(y,{node:{type:"line"},animation:r})})});function C(e,t){let i=o=>{let{loading:a,...n}=o;return s(k,{loading:a,schema:t?.skeleton,infer:t?.infer,cacheKey:t?.cacheKey,className:t?.className,animation:t?.animation,children:s(e,{...n})})};return i.displayName=`withInstaSkeleton(${e.displayName||e.name||"Component"})`,h(i)}function R(e){if(e){l.delete(e);return}l.clear()}export{k as InstaSkeleton,R as clearInstaSkeletonCache,C as withInstaSkeleton};
1
+ import{Children as y,isValidElement as S,memo as c,useMemo as N}from"react";import{Fragment as R,jsx as s}from"react/jsx-runtime";var I={maxDepth:6,maxNodes:120,textLineHeight:"0.95rem"},x=100,l=new Map;function w(e,t){if(l.size>=x){let n=l.keys().next().value;n&&l.delete(n)}l.set(e,t)}function b(e){return e?Array.isArray(e)?e:[e]:[]}function v(e,t){let n={...I,...t},o=0,a=(i,u)=>{if(o>=n.maxNodes||u>n.maxDepth)return[];if(i==null||typeof i=="boolean")return[];if(typeof i=="string"||typeof i=="number")return o+=1,[{type:"line",height:n.textLineHeight}];if(Array.isArray(i))return i.flatMap(d=>a(d,u+1));if(!S(i))return[];o+=1;let r=typeof i.type=="string"?i.type:"component";if(r==="img"||r==="video"||r==="svg"||r==="canvas")return[{type:"rect",height:"8rem"}];if(r==="button"||r==="input"||r==="textarea"||r==="select")return[{type:"rect",height:"2.5rem",radius:"0.5rem"}];let m=a(i.props.children,u+1);return m.length===0?[{type:"line",width:"70%",height:n.textLineHeight}]:m.length===1?m:[{type:"group",children:m}]};return a(y.toArray(e),0)}function h(e){let t={};return e.width!==void 0&&(t.width=e.width),e.height!==void 0&&(t.height=e.height),e.radius!==void 0&&(t.borderRadius=e.radius),e.gap!==void 0&&(t.gap=e.gap),e.direction!==void 0&&(t.flexDirection=e.direction),e.align!==void 0&&(t.alignItems=e.align),t}var k=c(function e({node:t,animation:n}){if(t.type==="group")return s("div",{className:"isk-group",style:h(t),children:(t.children??[]).map((a,i)=>s(e,{node:a,animation:n},i))});let o=n==="none"?"":` isk-anim-${n}`;return s("div",{className:`isk-node isk-${t.type}${o}`,style:h(t),"aria-hidden":"true"})}),g=c(function({loading:t,children:n,schema:o,infer:a=!0,cacheKey:i,className:u,animation:r="shimmer",inferOptions:m}){let d=N(()=>{if(!t)return[];let p=b(o);if(p.length>0)return p;if(!a)return[];if(i&&l.has(i))return l.get(i)??[];let f=v(n,m);return i&&w(i,f),f},[t,o,a,n,i,m]);return t?s("div",{className:["isk-root",u].filter(Boolean).join(" "),role:"status","aria-live":"polite","aria-busy":"true",children:d.length>0?d.map((p,f)=>s(k,{node:p,animation:r},f)):s(k,{node:{type:"line"},animation:r})}):s(R,{children:n})});function P(e,t){let n=o=>{let{loading:a,...i}=o;return s(g,{loading:a,schema:t?.skeleton,infer:t?.infer,cacheKey:t?.cacheKey,className:t?.className,animation:t?.animation,children:s(e,{...i})})};return n.displayName=`withInstaSkeleton(${e.displayName||e.name||"Component"})`,c(n)}function C(e){if(e){l.delete(e);return}l.clear()}export{g as InstaSkeleton,C as clearInstaSkeletonCache,P as withInstaSkeleton};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core.tsx"],"sourcesContent":["import React, { Children, isValidElement, memo, useMemo } from 'react';\nimport type {\n InferOptions,\n InstaSkeletonProps,\n SkeletonNode,\n WithInstaSkeletonProps\n} from './types';\n\nconst DEFAULT_INFER: Required<InferOptions> = {\n maxDepth: 6,\n maxNodes: 120,\n textLineHeight: '0.95rem'\n};\n\nconst CACHE_MAX_SIZE = 100;\nconst schemaCache = new Map<string, SkeletonNode[]>();\n\nfunction setCacheWithLimit(key: string, value: SkeletonNode[]): void {\n if (schemaCache.size >= CACHE_MAX_SIZE) {\n const firstKey = schemaCache.keys().next().value;\n if (firstKey) schemaCache.delete(firstKey);\n }\n schemaCache.set(key, value);\n}\n\nfunction normalizeSchema(schema?: SkeletonNode | SkeletonNode[]): SkeletonNode[] {\n if (!schema) return [];\n return Array.isArray(schema) ? schema : [schema];\n}\n\nfunction resolveDimension(value: string | number | undefined, fallback: string | number): string | number {\n return value ?? fallback;\n}\n\nfunction inferFromChildren(children: React.ReactNode, options?: InferOptions): SkeletonNode[] {\n const merged = { ...DEFAULT_INFER, ...options };\n let nodeCount = 0;\n\n const walk = (node: React.ReactNode, depth: number): SkeletonNode[] => {\n if (nodeCount >= merged.maxNodes || depth > merged.maxDepth) return [];\n if (node == null || typeof node === 'boolean') return [];\n\n if (typeof node === 'string' || typeof node === 'number') {\n nodeCount += 1;\n return [{ type: 'line', height: merged.textLineHeight }];\n }\n\n if (Array.isArray(node)) {\n return node.flatMap((item) => walk(item, depth + 1));\n }\n\n if (!isValidElement(node)) {\n return [];\n }\n\n nodeCount += 1;\n\n const elType = typeof node.type === 'string' ? node.type : 'component';\n\n if (elType === 'img' || elType === 'video' || elType === 'svg' || elType === 'canvas') {\n return [{ type: 'rect', height: '8rem' }];\n }\n\n if (elType === 'button' || elType === 'input' || elType === 'textarea' || elType === 'select') {\n return [{ type: 'rect', height: '2.5rem', radius: '0.5rem' }];\n }\n\n const childNodes = walk(node.props.children, depth + 1);\n\n if (childNodes.length === 0) {\n return [{ type: 'line', width: '70%', height: merged.textLineHeight }];\n }\n\n if (childNodes.length === 1) {\n return childNodes;\n }\n\n return [{ type: 'group', children: childNodes }];\n };\n\n return walk(Children.toArray(children), 0);\n}\n\nfunction nodeStyle(node: SkeletonNode): React.CSSProperties {\n const style: React.CSSProperties = {};\n\n if (node.width !== undefined) style.width = resolveDimension(node.width, '');\n if (node.height !== undefined) style.height = resolveDimension(node.height, '');\n if (node.radius !== undefined) style.borderRadius = resolveDimension(node.radius, '');\n if (node.gap !== undefined) style.gap = resolveDimension(node.gap, '');\n\n return style;\n}\n\nconst NodeView = memo(function NodeView({ node, animation }: { node: SkeletonNode; animation: InstaSkeletonProps['animation'] }) {\n if (node.type === 'group') {\n return (\n <div className=\"is-group\" style={nodeStyle(node)}>\n {(node.children ?? []).map((child, index) => (\n <NodeView key={index} node={child} animation={animation} />\n ))}\n </div>\n );\n }\n\n const animClass = animation === 'none' ? '' : ` is-anim-${animation}`;\n return <div className={`is-node is-${node.type}${animClass}`} style={nodeStyle(node)} aria-hidden=\"true\" />;\n});\n\nexport const InstaSkeleton = memo(function InstaSkeleton({\n loading,\n children,\n schema,\n infer = true,\n cacheKey,\n className,\n animation = 'shimmer',\n inferOptions\n}: InstaSkeletonProps) {\n // Early exit: skip all inference work when not loading\n if (!loading) return <>{children}</>;\n\n const skeletonSchema = useMemo(() => {\n const normalized = normalizeSchema(schema);\n if (normalized.length > 0) return normalized;\n if (!infer) return [];\n\n if (cacheKey && schemaCache.has(cacheKey)) {\n return schemaCache.get(cacheKey) ?? [];\n }\n\n const inferred = inferFromChildren(children, inferOptions);\n if (cacheKey) setCacheWithLimit(cacheKey, inferred);\n return inferred;\n }, [schema, infer, children, cacheKey, inferOptions]);\n\n return (\n <div className={['is-root', className].filter(Boolean).join(' ')} role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n {skeletonSchema.length > 0 ? (\n skeletonSchema.map((node, index) => <NodeView key={index} node={node} animation={animation} />)\n ) : (\n <NodeView node={{ type: 'line' }} animation={animation} />\n )}\n </div>\n );\n});\n\nexport function withInstaSkeleton<P extends object>(\n Component: React.ComponentType<P>,\n options?: Omit<WithInstaSkeletonProps, 'loading'>\n) {\n const Wrapped = (props: P & { loading: boolean }) => {\n const { loading, ...rest } = props;\n\n return (\n <InstaSkeleton\n loading={loading}\n schema={options?.skeleton}\n infer={options?.infer}\n cacheKey={options?.cacheKey}\n className={options?.className}\n animation={options?.animation}\n >\n <Component {...(rest as P)} />\n </InstaSkeleton>\n );\n };\n\n Wrapped.displayName = `withInstaSkeleton(${Component.displayName || Component.name || 'Component'})`;\n\n return memo(Wrapped);\n}\n\nexport function clearInstaSkeletonCache(key?: string): void {\n if (key) {\n schemaCache.delete(key);\n return;\n }\n\n schemaCache.clear();\n}\n"],"mappings":"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","names":["Children","isValidElement","memo","useMemo","Fragment","jsx","DEFAULT_INFER","CACHE_MAX_SIZE","schemaCache","setCacheWithLimit","key","value","firstKey","normalizeSchema","schema","resolveDimension","fallback","inferFromChildren","children","options","merged","nodeCount","walk","node","depth","item","elType","childNodes","nodeStyle","style","NodeView","animation","child","index","animClass","InstaSkeleton","loading","infer","cacheKey","className","inferOptions","skeletonSchema","normalized","inferred","withInstaSkeleton","Component","Wrapped","props","rest","clearInstaSkeletonCache"]}
1
+ {"version":3,"sources":["../src/core.tsx"],"sourcesContent":["import React, { Children, isValidElement, memo, useMemo } from 'react';\nimport type {\n InferOptions,\n InstaSkeletonProps,\n SkeletonNode,\n WithInstaSkeletonProps\n} from './types';\n\nconst DEFAULT_INFER: Required<InferOptions> = {\n maxDepth: 6,\n maxNodes: 120,\n textLineHeight: '0.95rem'\n};\n\nconst CACHE_MAX_SIZE = 100;\nconst schemaCache = new Map<string, SkeletonNode[]>();\n\nfunction setCacheWithLimit(key: string, value: SkeletonNode[]): void {\n if (schemaCache.size >= CACHE_MAX_SIZE) {\n const firstKey = schemaCache.keys().next().value;\n if (firstKey) schemaCache.delete(firstKey);\n }\n schemaCache.set(key, value);\n}\n\nfunction normalizeSchema(schema?: SkeletonNode | SkeletonNode[]): SkeletonNode[] {\n if (!schema) return [];\n return Array.isArray(schema) ? schema : [schema];\n}\n\nfunction inferFromChildren(children: React.ReactNode, options?: InferOptions): SkeletonNode[] {\n const merged = { ...DEFAULT_INFER, ...options };\n let nodeCount = 0;\n\n const walk = (node: React.ReactNode, depth: number): SkeletonNode[] => {\n if (nodeCount >= merged.maxNodes || depth > merged.maxDepth) return [];\n if (node == null || typeof node === 'boolean') return [];\n\n if (typeof node === 'string' || typeof node === 'number') {\n nodeCount += 1;\n return [{ type: 'line', height: merged.textLineHeight }];\n }\n\n if (Array.isArray(node)) {\n return node.flatMap((item) => walk(item, depth + 1));\n }\n\n if (!isValidElement(node)) {\n return [];\n }\n\n nodeCount += 1;\n\n const elType = typeof node.type === 'string' ? node.type : 'component';\n\n if (elType === 'img' || elType === 'video' || elType === 'svg' || elType === 'canvas') {\n return [{ type: 'rect', height: '8rem' }];\n }\n\n if (elType === 'button' || elType === 'input' || elType === 'textarea' || elType === 'select') {\n return [{ type: 'rect', height: '2.5rem', radius: '0.5rem' }];\n }\n\n const childNodes = walk(node.props.children, depth + 1);\n\n if (childNodes.length === 0) {\n return [{ type: 'line', width: '70%', height: merged.textLineHeight }];\n }\n\n if (childNodes.length === 1) {\n return childNodes;\n }\n\n return [{ type: 'group', children: childNodes }];\n };\n\n return walk(Children.toArray(children), 0);\n}\n\nfunction nodeStyle(node: SkeletonNode): React.CSSProperties {\n const style: React.CSSProperties = {};\n\n if (node.width !== undefined) style.width = node.width;\n if (node.height !== undefined) style.height = node.height;\n if (node.radius !== undefined) style.borderRadius = node.radius;\n if (node.gap !== undefined) style.gap = node.gap;\n if (node.direction !== undefined) style.flexDirection = node.direction;\n if (node.align !== undefined) style.alignItems = node.align;\n\n return style;\n}\n\nconst NodeView = memo(function NodeView({ node, animation }: { node: SkeletonNode; animation: InstaSkeletonProps['animation'] }) {\n if (node.type === 'group') {\n return (\n <div className=\"isk-group\" style={nodeStyle(node)}>\n {(node.children ?? []).map((child, index) => (\n <NodeView key={index} node={child} animation={animation} />\n ))}\n </div>\n );\n }\n\n const animClass = animation === 'none' ? '' : ` isk-anim-${animation}`;\n return <div className={`isk-node isk-${node.type}${animClass}`} style={nodeStyle(node)} aria-hidden=\"true\" />;\n});\n\nexport const InstaSkeleton = memo(function InstaSkeleton({\n loading,\n children,\n schema,\n infer = true,\n cacheKey,\n className,\n animation = 'shimmer',\n inferOptions\n}: InstaSkeletonProps) {\n const skeletonSchema = useMemo(() => {\n if (!loading) return [];\n\n const normalized = normalizeSchema(schema);\n if (normalized.length > 0) return normalized;\n if (!infer) return [];\n\n if (cacheKey && schemaCache.has(cacheKey)) {\n return schemaCache.get(cacheKey) ?? [];\n }\n\n const inferred = inferFromChildren(children, inferOptions);\n if (cacheKey) setCacheWithLimit(cacheKey, inferred);\n return inferred;\n }, [loading, schema, infer, children, cacheKey, inferOptions]);\n\n if (!loading) return <>{children}</>;\n\n return (\n <div className={['isk-root', className].filter(Boolean).join(' ')} role=\"status\" aria-live=\"polite\" aria-busy=\"true\">\n {skeletonSchema.length > 0 ? (\n skeletonSchema.map((node, index) => <NodeView key={index} node={node} animation={animation} />)\n ) : (\n <NodeView node={{ type: 'line' }} animation={animation} />\n )}\n </div>\n );\n});\n\nexport function withInstaSkeleton<P extends object>(\n Component: React.ComponentType<P>,\n options?: Omit<WithInstaSkeletonProps, 'loading'>\n) {\n const Wrapped = (props: P & { loading: boolean }) => {\n const { loading, ...rest } = props;\n\n return (\n <InstaSkeleton\n loading={loading}\n schema={options?.skeleton}\n infer={options?.infer}\n cacheKey={options?.cacheKey}\n className={options?.className}\n animation={options?.animation}\n >\n <Component {...(rest as P)} />\n </InstaSkeleton>\n );\n };\n\n Wrapped.displayName = `withInstaSkeleton(${Component.displayName || Component.name || 'Component'})`;\n\n return memo(Wrapped);\n}\n\nexport function clearInstaSkeletonCache(key?: string): void {\n if (key) {\n schemaCache.delete(key);\n return;\n }\n\n schemaCache.clear();\n}\n"],"mappings":"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","names":["Children","isValidElement","memo","useMemo","Fragment","jsx","DEFAULT_INFER","CACHE_MAX_SIZE","schemaCache","setCacheWithLimit","key","value","firstKey","normalizeSchema","schema","inferFromChildren","children","options","merged","nodeCount","walk","node","depth","item","elType","childNodes","nodeStyle","style","NodeView","animation","child","index","animClass","InstaSkeleton","loading","infer","cacheKey","className","inferOptions","skeletonSchema","normalized","inferred","withInstaSkeleton","Component","Wrapped","props","rest","clearInstaSkeletonCache"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "instaskeleton",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Ultra-light React skeleton loader with zero DOM scanning. Automatic JSX inference, manual schema support, shimmer & pulse animations. Only ~1.65KB gzipped.",
5
5
  "license": "MIT",
6
6
  "author": {