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 +0 -27
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
package/dist/index.cjs.map
CHANGED
|
@@ -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
|
-
.
|
|
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 */
|
package/dist/index.css.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/styles.css"],"sourcesContent":[".
|
|
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
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Children as
|
|
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
|
|
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.
|
|
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": {
|