react-native-skelo 0.0.1 → 0.0.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/LICENSE +21 -0
- package/README.md +147 -20
- package/lib/commonjs/Skelo.js +104 -0
- package/lib/commonjs/Skelo.js.map +1 -0
- package/lib/commonjs/animations/AnimationWrapper.js +76 -0
- package/lib/commonjs/animations/AnimationWrapper.js.map +1 -0
- package/lib/commonjs/animations/PulseAnimation.js +76 -0
- package/lib/commonjs/animations/PulseAnimation.js.map +1 -0
- package/lib/commonjs/animations/ShimmerAnimation.js +103 -0
- package/lib/commonjs/animations/ShimmerAnimation.js.map +1 -0
- package/lib/commonjs/animations/index.js +27 -0
- package/lib/commonjs/animations/index.js.map +1 -0
- package/lib/commonjs/components/MeasuredBlock.js +64 -0
- package/lib/commonjs/components/MeasuredBlock.js.map +1 -0
- package/lib/commonjs/components/Skeleton.js +144 -0
- package/lib/commonjs/components/Skeleton.js.map +1 -0
- package/lib/commonjs/components/SkeletonIgnore.js +30 -0
- package/lib/commonjs/components/SkeletonIgnore.js.map +1 -0
- package/lib/commonjs/components/SkeletonRenderer.js +270 -0
- package/lib/commonjs/components/SkeletonRenderer.js.map +1 -0
- package/lib/commonjs/components/primitives/SkeletonBox.js +47 -0
- package/lib/commonjs/components/primitives/SkeletonBox.js.map +1 -0
- package/lib/commonjs/components/primitives/SkeletonCircle.js +44 -0
- package/lib/commonjs/components/primitives/SkeletonCircle.js.map +1 -0
- package/lib/commonjs/components/primitives/SkeletonImage.js +46 -0
- package/lib/commonjs/components/primitives/SkeletonImage.js.map +1 -0
- package/lib/commonjs/components/primitives/SkeletonText.js +60 -0
- package/lib/commonjs/components/primitives/SkeletonText.js.map +1 -0
- package/lib/commonjs/components/primitives/index.js +34 -0
- package/lib/commonjs/components/primitives/index.js.map +1 -0
- package/lib/commonjs/components/withSkeleton.js +45 -0
- package/lib/commonjs/components/withSkeleton.js.map +1 -0
- package/lib/commonjs/constants/defaults.js +43 -0
- package/lib/commonjs/constants/defaults.js.map +1 -0
- package/lib/commonjs/core/deepRegistry.js +18 -0
- package/lib/commonjs/core/deepRegistry.js.map +1 -0
- package/lib/commonjs/core/generator/StyleSkeleton.js +101 -0
- package/lib/commonjs/core/generator/StyleSkeleton.js.map +1 -0
- package/lib/commonjs/core/parser/Parser.js +84 -0
- package/lib/commonjs/core/parser/Parser.js.map +1 -0
- package/lib/commonjs/core/parser/expandOffline.js +83 -0
- package/lib/commonjs/core/parser/expandOffline.js.map +1 -0
- package/lib/commonjs/core/parser/hostTreeReconciler.js +228 -0
- package/lib/commonjs/core/parser/hostTreeReconciler.js.map +1 -0
- package/lib/commonjs/core/parser/index.js +13 -0
- package/lib/commonjs/core/parser/index.js.map +1 -0
- package/lib/commonjs/core/registry/SkeletonRegistry.js +113 -0
- package/lib/commonjs/core/registry/SkeletonRegistry.js.map +1 -0
- package/lib/commonjs/core/registry/index.js +19 -0
- package/lib/commonjs/core/registry/index.js.map +1 -0
- package/lib/commonjs/core/resolver/StyleResolver.js +83 -0
- package/lib/commonjs/core/resolver/StyleResolver.js.map +1 -0
- package/lib/commonjs/core/resolver/index.js +13 -0
- package/lib/commonjs/core/resolver/index.js.map +1 -0
- package/lib/commonjs/deep.js +18 -0
- package/lib/commonjs/deep.js.map +1 -0
- package/lib/commonjs/index.js +66 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/plugins/ImagePlugin.js +60 -0
- package/lib/commonjs/plugins/ImagePlugin.js.map +1 -0
- package/lib/commonjs/plugins/TextPlugin.js +70 -0
- package/lib/commonjs/plugins/TextPlugin.js.map +1 -0
- package/lib/commonjs/plugins/ViewPlugin.js +71 -0
- package/lib/commonjs/plugins/ViewPlugin.js.map +1 -0
- package/lib/commonjs/plugins/index.js +27 -0
- package/lib/commonjs/plugins/index.js.map +1 -0
- package/lib/commonjs/types/index.js +2 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/commonjs/types/plugin.js +6 -0
- package/lib/commonjs/types/plugin.js.map +1 -0
- package/lib/commonjs/types/skeleton.js +6 -0
- package/lib/commonjs/types/skeleton.js.map +1 -0
- package/lib/commonjs/utils/componentUtils.js +138 -0
- package/lib/commonjs/utils/componentUtils.js.map +1 -0
- package/lib/commonjs/utils/index.js +62 -0
- package/lib/commonjs/utils/index.js.map +1 -0
- package/lib/commonjs/utils/styleUtils.js +76 -0
- package/lib/commonjs/utils/styleUtils.js.map +1 -0
- package/lib/module/Skelo.js +98 -0
- package/lib/module/Skelo.js.map +1 -0
- package/lib/module/animations/AnimationWrapper.js +69 -0
- package/lib/module/animations/AnimationWrapper.js.map +1 -0
- package/lib/module/animations/PulseAnimation.js +69 -0
- package/lib/module/animations/PulseAnimation.js.map +1 -0
- package/lib/module/animations/ShimmerAnimation.js +96 -0
- package/lib/module/animations/ShimmerAnimation.js.map +1 -0
- package/lib/module/animations/index.js +4 -0
- package/lib/module/animations/index.js.map +1 -0
- package/lib/module/components/MeasuredBlock.js +57 -0
- package/lib/module/components/MeasuredBlock.js.map +1 -0
- package/lib/module/components/Skeleton.js +138 -0
- package/lib/module/components/Skeleton.js.map +1 -0
- package/lib/module/components/SkeletonIgnore.js +23 -0
- package/lib/module/components/SkeletonIgnore.js.map +1 -0
- package/lib/module/components/SkeletonRenderer.js +264 -0
- package/lib/module/components/SkeletonRenderer.js.map +1 -0
- package/lib/module/components/primitives/SkeletonBox.js +40 -0
- package/lib/module/components/primitives/SkeletonBox.js.map +1 -0
- package/lib/module/components/primitives/SkeletonCircle.js +37 -0
- package/lib/module/components/primitives/SkeletonCircle.js.map +1 -0
- package/lib/module/components/primitives/SkeletonImage.js +39 -0
- package/lib/module/components/primitives/SkeletonImage.js.map +1 -0
- package/lib/module/components/primitives/SkeletonText.js +53 -0
- package/lib/module/components/primitives/SkeletonText.js.map +1 -0
- package/lib/module/components/primitives/index.js +5 -0
- package/lib/module/components/primitives/index.js.map +1 -0
- package/lib/module/components/withSkeleton.js +38 -0
- package/lib/module/components/withSkeleton.js.map +1 -0
- package/lib/module/constants/defaults.js +37 -0
- package/lib/module/constants/defaults.js.map +1 -0
- package/lib/module/core/deepRegistry.js +11 -0
- package/lib/module/core/deepRegistry.js.map +1 -0
- package/lib/module/core/generator/StyleSkeleton.js +95 -0
- package/lib/module/core/generator/StyleSkeleton.js.map +1 -0
- package/lib/module/core/parser/Parser.js +77 -0
- package/lib/module/core/parser/Parser.js.map +1 -0
- package/lib/module/core/parser/expandOffline.js +77 -0
- package/lib/module/core/parser/expandOffline.js.map +1 -0
- package/lib/module/core/parser/hostTreeReconciler.js +222 -0
- package/lib/module/core/parser/hostTreeReconciler.js.map +1 -0
- package/lib/module/core/parser/index.js +2 -0
- package/lib/module/core/parser/index.js.map +1 -0
- package/lib/module/core/registry/SkeletonRegistry.js +106 -0
- package/lib/module/core/registry/SkeletonRegistry.js.map +1 -0
- package/lib/module/core/registry/index.js +2 -0
- package/lib/module/core/registry/index.js.map +1 -0
- package/lib/module/core/resolver/StyleResolver.js +77 -0
- package/lib/module/core/resolver/StyleResolver.js.map +1 -0
- package/lib/module/core/resolver/index.js +2 -0
- package/lib/module/core/resolver/index.js.map +1 -0
- package/lib/module/deep.js +11 -0
- package/lib/module/deep.js.map +1 -0
- package/lib/module/index.js +21 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/plugins/ImagePlugin.js +53 -0
- package/lib/module/plugins/ImagePlugin.js.map +1 -0
- package/lib/module/plugins/TextPlugin.js +63 -0
- package/lib/module/plugins/TextPlugin.js.map +1 -0
- package/lib/module/plugins/ViewPlugin.js +64 -0
- package/lib/module/plugins/ViewPlugin.js.map +1 -0
- package/lib/module/plugins/index.js +4 -0
- package/lib/module/plugins/index.js.map +1 -0
- package/lib/module/types/index.js +2 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/types/plugin.js +2 -0
- package/lib/module/types/plugin.js.map +1 -0
- package/lib/module/types/skeleton.js +2 -0
- package/lib/module/types/skeleton.js.map +1 -0
- package/lib/module/utils/componentUtils.js +123 -0
- package/lib/module/utils/componentUtils.js.map +1 -0
- package/lib/module/utils/index.js +3 -0
- package/lib/module/utils/index.js.map +1 -0
- package/lib/module/utils/styleUtils.js +66 -0
- package/lib/module/utils/styleUtils.js.map +1 -0
- package/lib/typescript/Skelo.d.ts +76 -0
- package/lib/typescript/Skelo.d.ts.map +1 -0
- package/lib/typescript/animations/AnimationWrapper.d.ts +66 -0
- package/lib/typescript/animations/AnimationWrapper.d.ts.map +1 -0
- package/lib/typescript/animations/PulseAnimation.d.ts +59 -0
- package/lib/typescript/animations/PulseAnimation.d.ts.map +1 -0
- package/lib/typescript/animations/ShimmerAnimation.d.ts +59 -0
- package/lib/typescript/animations/ShimmerAnimation.d.ts.map +1 -0
- package/lib/typescript/animations/index.d.ts +5 -0
- package/lib/typescript/animations/index.d.ts.map +1 -0
- package/lib/typescript/components/MeasuredBlock.d.ts +32 -0
- package/lib/typescript/components/MeasuredBlock.d.ts.map +1 -0
- package/lib/typescript/components/Skeleton.d.ts +37 -0
- package/lib/typescript/components/Skeleton.d.ts.map +1 -0
- package/lib/typescript/components/SkeletonIgnore.d.ts +26 -0
- package/lib/typescript/components/SkeletonIgnore.d.ts.map +1 -0
- package/lib/typescript/components/SkeletonRenderer.d.ts +39 -0
- package/lib/typescript/components/SkeletonRenderer.d.ts.map +1 -0
- package/lib/typescript/components/primitives/SkeletonBox.d.ts +21 -0
- package/lib/typescript/components/primitives/SkeletonBox.d.ts.map +1 -0
- package/lib/typescript/components/primitives/SkeletonCircle.d.ts +21 -0
- package/lib/typescript/components/primitives/SkeletonCircle.d.ts.map +1 -0
- package/lib/typescript/components/primitives/SkeletonImage.d.ts +21 -0
- package/lib/typescript/components/primitives/SkeletonImage.d.ts.map +1 -0
- package/lib/typescript/components/primitives/SkeletonText.d.ts +21 -0
- package/lib/typescript/components/primitives/SkeletonText.d.ts.map +1 -0
- package/lib/typescript/components/primitives/index.d.ts +5 -0
- package/lib/typescript/components/primitives/index.d.ts.map +1 -0
- package/lib/typescript/components/withSkeleton.d.ts +37 -0
- package/lib/typescript/components/withSkeleton.d.ts.map +1 -0
- package/lib/typescript/constants/defaults.d.ts +29 -0
- package/lib/typescript/constants/defaults.d.ts.map +1 -0
- package/lib/typescript/core/deepRegistry.d.ts +7 -0
- package/lib/typescript/core/deepRegistry.d.ts.map +1 -0
- package/lib/typescript/core/generator/StyleSkeleton.d.ts +36 -0
- package/lib/typescript/core/generator/StyleSkeleton.d.ts.map +1 -0
- package/lib/typescript/core/parser/Parser.d.ts +30 -0
- package/lib/typescript/core/parser/Parser.d.ts.map +1 -0
- package/lib/typescript/core/parser/expandOffline.d.ts +10 -0
- package/lib/typescript/core/parser/expandOffline.d.ts.map +1 -0
- package/lib/typescript/core/parser/hostTreeReconciler.d.ts +28 -0
- package/lib/typescript/core/parser/hostTreeReconciler.d.ts.map +1 -0
- package/lib/typescript/core/parser/index.d.ts +2 -0
- package/lib/typescript/core/parser/index.d.ts.map +1 -0
- package/lib/typescript/core/registry/SkeletonRegistry.d.ts +57 -0
- package/lib/typescript/core/registry/SkeletonRegistry.d.ts.map +1 -0
- package/lib/typescript/core/registry/index.d.ts +2 -0
- package/lib/typescript/core/registry/index.d.ts.map +1 -0
- package/lib/typescript/core/resolver/StyleResolver.d.ts +54 -0
- package/lib/typescript/core/resolver/StyleResolver.d.ts.map +1 -0
- package/lib/typescript/core/resolver/index.d.ts +2 -0
- package/lib/typescript/core/resolver/index.d.ts.map +1 -0
- package/lib/typescript/deep.d.ts +2 -0
- package/lib/typescript/deep.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +17 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/plugins/ImagePlugin.d.ts +11 -0
- package/lib/typescript/plugins/ImagePlugin.d.ts.map +1 -0
- package/lib/typescript/plugins/TextPlugin.d.ts +12 -0
- package/lib/typescript/plugins/TextPlugin.d.ts.map +1 -0
- package/lib/typescript/plugins/ViewPlugin.d.ts +11 -0
- package/lib/typescript/plugins/ViewPlugin.d.ts.map +1 -0
- package/lib/typescript/plugins/index.d.ts +4 -0
- package/lib/typescript/plugins/index.d.ts.map +1 -0
- package/lib/typescript/types/index.d.ts +3 -0
- package/lib/typescript/types/index.d.ts.map +1 -0
- package/lib/typescript/types/plugin.d.ts +144 -0
- package/lib/typescript/types/plugin.d.ts.map +1 -0
- package/lib/typescript/types/skeleton.d.ts +176 -0
- package/lib/typescript/types/skeleton.d.ts.map +1 -0
- package/lib/typescript/utils/componentUtils.d.ts +40 -0
- package/lib/typescript/utils/componentUtils.d.ts.map +1 -0
- package/lib/typescript/utils/index.d.ts +3 -0
- package/lib/typescript/utils/index.d.ts.map +1 -0
- package/lib/typescript/utils/styleUtils.d.ts +41 -0
- package/lib/typescript/utils/styleUtils.d.ts.map +1 -0
- package/package.json +171 -11
- package/src/Skelo.ts +103 -0
- package/src/animations/AnimationWrapper.tsx +139 -0
- package/src/animations/PulseAnimation.tsx +138 -0
- package/src/animations/ShimmerAnimation.tsx +169 -0
- package/src/animations/index.ts +4 -0
- package/src/components/MeasuredBlock.tsx +85 -0
- package/src/components/Skeleton.tsx +149 -0
- package/src/components/SkeletonIgnore.tsx +27 -0
- package/src/components/SkeletonRenderer.tsx +341 -0
- package/src/components/primitives/SkeletonBox.tsx +53 -0
- package/src/components/primitives/SkeletonCircle.tsx +48 -0
- package/src/components/primitives/SkeletonImage.tsx +50 -0
- package/src/components/primitives/SkeletonText.tsx +69 -0
- package/src/components/primitives/index.ts +4 -0
- package/src/components/withSkeleton.tsx +62 -0
- package/src/constants/defaults.ts +38 -0
- package/src/core/deepRegistry.ts +16 -0
- package/src/core/generator/StyleSkeleton.tsx +138 -0
- package/src/core/parser/Parser.ts +86 -0
- package/src/core/parser/expandOffline.tsx +83 -0
- package/src/core/parser/hostTreeReconciler.tsx +271 -0
- package/src/core/parser/index.ts +1 -0
- package/src/core/registry/SkeletonRegistry.ts +111 -0
- package/src/core/registry/index.ts +1 -0
- package/src/core/resolver/StyleResolver.ts +80 -0
- package/src/core/resolver/index.ts +1 -0
- package/src/deep.ts +12 -0
- package/src/index.ts +30 -0
- package/src/plugins/ImagePlugin.tsx +65 -0
- package/src/plugins/TextPlugin.tsx +71 -0
- package/src/plugins/ViewPlugin.tsx +67 -0
- package/src/plugins/index.ts +3 -0
- package/src/types/index.ts +14 -0
- package/src/types/plugin.ts +164 -0
- package/src/types/skeleton.ts +197 -0
- package/src/utils/componentUtils.ts +166 -0
- package/src/utils/index.ts +9 -0
- package/src/utils/styleUtils.ts +72 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { ShimmerAnimation } from './ShimmerAnimation';
|
|
4
|
+
import { PulseAnimation } from './PulseAnimation';
|
|
5
|
+
/**
|
|
6
|
+
* Animation wrapper that selects the appropriate animation type
|
|
7
|
+
*
|
|
8
|
+
* Provides a unified interface for all skeleton animations:
|
|
9
|
+
* - shimmer: Left-to-right shimmer effect
|
|
10
|
+
* - pulse: Breathing/pulsing opacity
|
|
11
|
+
* - none: Static skeleton (no animation)
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <AnimationWrapper
|
|
16
|
+
* animation="shimmer"
|
|
17
|
+
* width={200}
|
|
18
|
+
* height={20}
|
|
19
|
+
* />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function AnimationWrapper({
|
|
23
|
+
animation = 'shimmer',
|
|
24
|
+
width,
|
|
25
|
+
height,
|
|
26
|
+
baseColor = '#E1E9EE',
|
|
27
|
+
highlightColor = '#F2F8FC',
|
|
28
|
+
duration,
|
|
29
|
+
borderRadius = 4,
|
|
30
|
+
style,
|
|
31
|
+
children
|
|
32
|
+
}) {
|
|
33
|
+
// No animation - static skeleton
|
|
34
|
+
if (animation === 'none') {
|
|
35
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
36
|
+
style: [{
|
|
37
|
+
width,
|
|
38
|
+
height,
|
|
39
|
+
borderRadius,
|
|
40
|
+
backgroundColor: baseColor
|
|
41
|
+
}, style]
|
|
42
|
+
}, children);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Shimmer animation
|
|
46
|
+
if (animation === 'shimmer') {
|
|
47
|
+
return /*#__PURE__*/React.createElement(ShimmerAnimation, {
|
|
48
|
+
width: width,
|
|
49
|
+
height: height,
|
|
50
|
+
baseColor: baseColor,
|
|
51
|
+
highlightColor: highlightColor,
|
|
52
|
+
duration: duration ?? 1500,
|
|
53
|
+
borderRadius: borderRadius,
|
|
54
|
+
style: style
|
|
55
|
+
}, children);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Pulse animation
|
|
59
|
+
return /*#__PURE__*/React.createElement(PulseAnimation, {
|
|
60
|
+
width: width,
|
|
61
|
+
height: height,
|
|
62
|
+
baseColor: baseColor,
|
|
63
|
+
highlightColor: highlightColor,
|
|
64
|
+
duration: duration ?? 1000,
|
|
65
|
+
borderRadius: borderRadius,
|
|
66
|
+
style: style
|
|
67
|
+
}, children);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=AnimationWrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","View","ShimmerAnimation","PulseAnimation","AnimationWrapper","animation","width","height","baseColor","highlightColor","duration","borderRadius","style","children","createElement","backgroundColor"],"sourceRoot":"../../../src","sources":["animations/AnimationWrapper.tsx"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AAEzB,SAASC,IAAI,QAAQ,cAAc;AACnC,SAASC,gBAAgB,QAAQ,oBAAoB;AACrD,SAASC,cAAc,QAAQ,kBAAkB;AAwDjD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAAC;EAC/BC,SAAS,GAAG,SAAS;EACrBC,KAAK;EACLC,MAAM;EACNC,SAAS,GAAG,SAAS;EACrBC,cAAc,GAAG,SAAS;EAC1BC,QAAQ;EACRC,YAAY,GAAG,CAAC;EAChBC,KAAK;EACLC;AACqB,CAAC,EAAE;EACxB;EACA,IAAIR,SAAS,KAAK,MAAM,EAAE;IACxB,oBACEL,KAAA,CAAAc,aAAA,CAACb,IAAI;MACHW,KAAK,EAAE,CACL;QACEN,KAAK;QACLC,MAAM;QACNI,YAAY;QACZI,eAAe,EAAEP;MACnB,CAAC,EACDI,KAAK;IACL,GAEDC,QACG,CAAC;EAEX;;EAEA;EACA,IAAIR,SAAS,KAAK,SAAS,EAAE;IAC3B,oBACEL,KAAA,CAAAc,aAAA,CAACZ,gBAAgB;MACfI,KAAK,EAAEA,KAAM;MACbC,MAAM,EAAEA,MAAO;MACfC,SAAS,EAAEA,SAAU;MACrBC,cAAc,EAAEA,cAAe;MAC/BC,QAAQ,EAAEA,QAAQ,IAAI,IAAK;MAC3BC,YAAY,EAAEA,YAAa;MAC3BC,KAAK,EAAEA;IAAM,GAEZC,QACe,CAAC;EAEvB;;EAEA;EACA,oBACEb,KAAA,CAAAc,aAAA,CAACX,cAAc;IACbG,KAAK,EAAEA,KAAM;IACbC,MAAM,EAAEA,MAAO;IACfC,SAAS,EAAEA,SAAU;IACrBC,cAAc,EAAEA,cAAe;IAC/BC,QAAQ,EAAEA,QAAQ,IAAI,IAAK;IAC3BC,YAAY,EAAEA,YAAa;IAC3BC,KAAK,EAAEA;EAAM,GAEZC,QACa,CAAC;AAErB","ignoreList":[]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
|
+
import Animated, { useSharedValue, useAnimatedStyle, withRepeat, withSequence, withTiming, Easing } from 'react-native-reanimated';
|
|
4
|
+
/**
|
|
5
|
+
* Pulse animation component using Reanimated 3
|
|
6
|
+
*
|
|
7
|
+
* Creates a subtle breathing/pulsing effect using:
|
|
8
|
+
* - Shared values for performance
|
|
9
|
+
* - Worklets for 60 FPS on UI thread
|
|
10
|
+
* - Opacity animation for pulse effect
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <PulseAnimation
|
|
15
|
+
* width={200}
|
|
16
|
+
* height={20}
|
|
17
|
+
* borderRadius={4}
|
|
18
|
+
* />
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function PulseAnimation({
|
|
22
|
+
width,
|
|
23
|
+
height,
|
|
24
|
+
baseColor = '#E1E9EE',
|
|
25
|
+
duration = 1000,
|
|
26
|
+
borderRadius = 4,
|
|
27
|
+
style,
|
|
28
|
+
children
|
|
29
|
+
}) {
|
|
30
|
+
// Shared value for opacity (0 to 1)
|
|
31
|
+
const opacity = useSharedValue(1);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
// Start infinite pulse animation
|
|
34
|
+
// Sequence: fade out -> fade in
|
|
35
|
+
opacity.value = withRepeat(withSequence(withTiming(0.5, {
|
|
36
|
+
duration: duration / 2,
|
|
37
|
+
easing: Easing.inOut(Easing.ease)
|
|
38
|
+
}), withTiming(1, {
|
|
39
|
+
duration: duration / 2,
|
|
40
|
+
easing: Easing.inOut(Easing.ease)
|
|
41
|
+
})), -1,
|
|
42
|
+
// Infinite repeat
|
|
43
|
+
false // Don't reverse
|
|
44
|
+
);
|
|
45
|
+
}, [duration, opacity]);
|
|
46
|
+
|
|
47
|
+
// Animated style for pulse effect
|
|
48
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
49
|
+
'worklet';
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
opacity: opacity.value
|
|
53
|
+
};
|
|
54
|
+
}, []);
|
|
55
|
+
return /*#__PURE__*/React.createElement(Animated.View, {
|
|
56
|
+
style: [styles.container, {
|
|
57
|
+
width,
|
|
58
|
+
height,
|
|
59
|
+
borderRadius,
|
|
60
|
+
backgroundColor: baseColor
|
|
61
|
+
}, animatedStyle, style]
|
|
62
|
+
}, children);
|
|
63
|
+
}
|
|
64
|
+
const styles = StyleSheet.create({
|
|
65
|
+
container: {
|
|
66
|
+
overflow: 'hidden'
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=PulseAnimation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useEffect","StyleSheet","Animated","useSharedValue","useAnimatedStyle","withRepeat","withSequence","withTiming","Easing","PulseAnimation","width","height","baseColor","duration","borderRadius","style","children","opacity","value","easing","inOut","ease","animatedStyle","createElement","View","styles","container","backgroundColor","create","overflow"],"sourceRoot":"../../../src","sources":["animations/PulseAnimation.tsx"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,SAAS,QAAQ,OAAO;AAExC,SAASC,UAAU,QAAQ,cAAc;AACzC,OAAOC,QAAQ,IACbC,cAAc,EACdC,gBAAgB,EAChBC,UAAU,EACVC,YAAY,EACZC,UAAU,EACVC,MAAM,QACD,yBAAyB;AA+ChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAAC;EAC7BC,KAAK;EACLC,MAAM;EACNC,SAAS,GAAG,SAAS;EACrBC,QAAQ,GAAG,IAAI;EACfC,YAAY,GAAG,CAAC;EAChBC,KAAK;EACLC;AACU,CAAC,EAAE;EACb;EACA,MAAMC,OAAO,GAAGd,cAAc,CAAC,CAAC,CAAC;EAEjCH,SAAS,CAAC,MAAM;IACd;IACA;IACAiB,OAAO,CAACC,KAAK,GAAGb,UAAU,CACxBC,YAAY,CACVC,UAAU,CAAC,GAAG,EAAE;MACdM,QAAQ,EAAEA,QAAQ,GAAG,CAAC;MACtBM,MAAM,EAAEX,MAAM,CAACY,KAAK,CAACZ,MAAM,CAACa,IAAI;IAClC,CAAC,CAAC,EACFd,UAAU,CAAC,CAAC,EAAE;MACZM,QAAQ,EAAEA,QAAQ,GAAG,CAAC;MACtBM,MAAM,EAAEX,MAAM,CAACY,KAAK,CAACZ,MAAM,CAACa,IAAI;IAClC,CAAC,CACH,CAAC,EACD,CAAC,CAAC;IAAE;IACJ,KAAK,CAAC;IACR,CAAC;EACH,CAAC,EAAE,CAACR,QAAQ,EAAEI,OAAO,CAAC,CAAC;;EAEvB;EACA,MAAMK,aAAa,GAAGlB,gBAAgB,CAAC,MAAM;IAC3C,SAAS;;IAET,OAAO;MACLa,OAAO,EAAEA,OAAO,CAACC;IACnB,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,oBACEnB,KAAA,CAAAwB,aAAA,CAACrB,QAAQ,CAACsB,IAAI;IACZT,KAAK,EAAE,CACLU,MAAM,CAACC,SAAS,EAChB;MACEhB,KAAK;MACLC,MAAM;MACNG,YAAY;MACZa,eAAe,EAAEf;IACnB,CAAC,EACDU,aAAa,EACbP,KAAK;EACL,GAEDC,QACY,CAAC;AAEpB;AAEA,MAAMS,MAAM,GAAGxB,UAAU,CAAC2B,MAAM,CAAC;EAC/BF,SAAS,EAAE;IACTG,QAAQ,EAAE;EACZ;AACF,CAAC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
import Animated, { useSharedValue, useAnimatedStyle, withRepeat, withTiming, interpolate, Easing } from 'react-native-reanimated';
|
|
4
|
+
import { LinearGradient } from 'react-native-linear-gradient';
|
|
5
|
+
/**
|
|
6
|
+
* Shimmer animation component using Reanimated 3
|
|
7
|
+
*
|
|
8
|
+
* Creates a smooth left-to-right shimmer effect using:
|
|
9
|
+
* - Shared values for performance
|
|
10
|
+
* - Worklets for 60 FPS on UI thread
|
|
11
|
+
* - Linear gradient for shimmer effect
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <ShimmerAnimation
|
|
16
|
+
* width={200}
|
|
17
|
+
* height={20}
|
|
18
|
+
* borderRadius={4}
|
|
19
|
+
* />
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function ShimmerAnimation({
|
|
23
|
+
width,
|
|
24
|
+
height,
|
|
25
|
+
baseColor = '#E1E9EE',
|
|
26
|
+
highlightColor = '#F2F8FC',
|
|
27
|
+
duration = 1500,
|
|
28
|
+
borderRadius = 4,
|
|
29
|
+
style,
|
|
30
|
+
children
|
|
31
|
+
}) {
|
|
32
|
+
// Shared value for animation progress (0 to 1)
|
|
33
|
+
const progress = useSharedValue(0);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
// Start infinite shimmer animation
|
|
36
|
+
progress.value = withRepeat(withTiming(1, {
|
|
37
|
+
duration,
|
|
38
|
+
easing: Easing.linear
|
|
39
|
+
}), -1,
|
|
40
|
+
// Infinite repeat
|
|
41
|
+
false // Don't reverse
|
|
42
|
+
);
|
|
43
|
+
}, [duration, progress]);
|
|
44
|
+
|
|
45
|
+
// Animated style for shimmer overlay
|
|
46
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
47
|
+
'worklet';
|
|
48
|
+
|
|
49
|
+
// Calculate shimmer position
|
|
50
|
+
// Interpolate from -100% to 100% to create left-to-right sweep
|
|
51
|
+
const translateX = interpolate(progress.value, [0, 1], [-1, 1]);
|
|
52
|
+
return {
|
|
53
|
+
transform: [{
|
|
54
|
+
translateX: translateX * (typeof width === 'number' ? width : 200)
|
|
55
|
+
}]
|
|
56
|
+
};
|
|
57
|
+
}, [width]);
|
|
58
|
+
return /*#__PURE__*/React.createElement(View, {
|
|
59
|
+
style: [styles.container, {
|
|
60
|
+
width,
|
|
61
|
+
height,
|
|
62
|
+
borderRadius,
|
|
63
|
+
backgroundColor: baseColor
|
|
64
|
+
}, style]
|
|
65
|
+
}, /*#__PURE__*/React.createElement(Animated.View, {
|
|
66
|
+
style: [StyleSheet.absoluteFill, {
|
|
67
|
+
overflow: 'hidden',
|
|
68
|
+
borderRadius
|
|
69
|
+
}]
|
|
70
|
+
}, /*#__PURE__*/React.createElement(Animated.View, {
|
|
71
|
+
style: [styles.shimmer, {
|
|
72
|
+
width: typeof width === 'number' ? width : '100%',
|
|
73
|
+
height: '100%'
|
|
74
|
+
}, animatedStyle]
|
|
75
|
+
}, /*#__PURE__*/React.createElement(LinearGradient, {
|
|
76
|
+
colors: [baseColor, highlightColor, highlightColor, baseColor],
|
|
77
|
+
start: {
|
|
78
|
+
x: 0,
|
|
79
|
+
y: 0
|
|
80
|
+
},
|
|
81
|
+
end: {
|
|
82
|
+
x: 1,
|
|
83
|
+
y: 0
|
|
84
|
+
},
|
|
85
|
+
style: StyleSheet.absoluteFill
|
|
86
|
+
}))), children);
|
|
87
|
+
}
|
|
88
|
+
const styles = StyleSheet.create({
|
|
89
|
+
container: {
|
|
90
|
+
overflow: 'hidden'
|
|
91
|
+
},
|
|
92
|
+
shimmer: {
|
|
93
|
+
position: 'absolute'
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=ShimmerAnimation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useEffect","StyleSheet","View","Animated","useSharedValue","useAnimatedStyle","withRepeat","withTiming","interpolate","Easing","LinearGradient","ShimmerAnimation","width","height","baseColor","highlightColor","duration","borderRadius","style","children","progress","value","easing","linear","animatedStyle","translateX","transform","createElement","styles","container","backgroundColor","absoluteFill","overflow","shimmer","colors","start","x","y","end","create","position"],"sourceRoot":"../../../src","sources":["animations/ShimmerAnimation.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ShimmerAnimation","PulseAnimation","AnimationWrapper"],"sourceRoot":"../../../src","sources":["animations/index.ts"],"mappings":"AAAA,SAASA,gBAAgB,QAAQ,oBAAoB;AACrD,SAASC,cAAc,QAAQ,kBAAkB;AACjD,SAASC,gBAAgB,QAAQ,oBAAoB","ignoreList":[]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { StyleSheet, View } from 'react-native';
|
|
3
|
+
import { AnimationWrapper } from '../animations';
|
|
4
|
+
/**
|
|
5
|
+
* Renders an opaque (non-host) component hidden so it lays out at its real
|
|
6
|
+
* size, measures that size via `onLayout`, then overlays a shimmer block of
|
|
7
|
+
* exactly those dimensions.
|
|
8
|
+
*
|
|
9
|
+
* This is Skelo's runtime-measurement fallback: when the parser can't
|
|
10
|
+
* introspect a component (e.g. a user-defined function component), we can't
|
|
11
|
+
* know its internal View/Text/Image structure without native view-tree access,
|
|
12
|
+
* but we *can* render it off-screen and reproduce its footprint accurately.
|
|
13
|
+
*
|
|
14
|
+
* The result is a single, correctly-sized skeleton block rather than a
|
|
15
|
+
* misleading fixed-size placeholder.
|
|
16
|
+
*/
|
|
17
|
+
export function MeasuredBlock({
|
|
18
|
+
children,
|
|
19
|
+
config
|
|
20
|
+
}) {
|
|
21
|
+
const [size, setSize] = useState(null);
|
|
22
|
+
const handleLayout = event => {
|
|
23
|
+
const {
|
|
24
|
+
width,
|
|
25
|
+
height
|
|
26
|
+
} = event.nativeEvent.layout;
|
|
27
|
+
setSize(prev => prev && prev.width === width && prev.height === height ? prev : {
|
|
28
|
+
width,
|
|
29
|
+
height
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
return /*#__PURE__*/React.createElement(View, null, /*#__PURE__*/React.createElement(View, {
|
|
33
|
+
style: styles.hidden,
|
|
34
|
+
pointerEvents: "none",
|
|
35
|
+
importantForAccessibility: "no-hide-descendants",
|
|
36
|
+
accessibilityElementsHidden: true,
|
|
37
|
+
onLayout: handleLayout
|
|
38
|
+
}, children), size && size.width > 0 && size.height > 0 && /*#__PURE__*/React.createElement(View, {
|
|
39
|
+
style: StyleSheet.absoluteFill,
|
|
40
|
+
pointerEvents: "none"
|
|
41
|
+
}, /*#__PURE__*/React.createElement(AnimationWrapper, {
|
|
42
|
+
animation: config.animation,
|
|
43
|
+
width: size.width,
|
|
44
|
+
height: size.height,
|
|
45
|
+
baseColor: config.baseColor,
|
|
46
|
+
highlightColor: config.highlightColor,
|
|
47
|
+
duration: config.duration,
|
|
48
|
+
borderRadius: config.borderRadius
|
|
49
|
+
})));
|
|
50
|
+
}
|
|
51
|
+
const styles = StyleSheet.create({
|
|
52
|
+
hidden: {
|
|
53
|
+
opacity: 0
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
MeasuredBlock.displayName = 'Skeleton.MeasuredBlock';
|
|
57
|
+
//# sourceMappingURL=MeasuredBlock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useState","StyleSheet","View","AnimationWrapper","MeasuredBlock","children","config","size","setSize","handleLayout","event","width","height","nativeEvent","layout","prev","createElement","style","styles","hidden","pointerEvents","importantForAccessibility","accessibilityElementsHidden","onLayout","absoluteFill","animation","baseColor","highlightColor","duration","borderRadius","create","opacity","displayName"],"sourceRoot":"../../../src","sources":["components/MeasuredBlock.tsx"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,QAAQ,QAAQ,OAAO;AAEvC,SAASC,UAAU,EAAEC,IAAI,QAAQ,cAAc;AAG/C,SAASC,gBAAgB,QAAQ,eAAe;AAmBhD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,aAAaA,CAAC;EAAEC,QAAQ;EAAEC;AAA2B,CAAC,EAAE;EACtE,MAAM,CAACC,IAAI,EAAEC,OAAO,CAAC,GAAGR,QAAQ,CAAc,IAAI,CAAC;EAEnD,MAAMS,YAAY,GAAIC,KAAwB,IAAK;IACjD,MAAM;MAAEC,KAAK;MAAEC;IAAO,CAAC,GAAGF,KAAK,CAACG,WAAW,CAACC,MAAM;IAClDN,OAAO,CAACO,IAAI,IACVA,IAAI,IAAIA,IAAI,CAACJ,KAAK,KAAKA,KAAK,IAAII,IAAI,CAACH,MAAM,KAAKA,MAAM,GAAGG,IAAI,GAAG;MAAEJ,KAAK;MAAEC;IAAO,CAClF,CAAC;EACH,CAAC;EAED,oBACEb,KAAA,CAAAiB,aAAA,CAACd,IAAI,qBAEHH,KAAA,CAAAiB,aAAA,CAACd,IAAI;IACHe,KAAK,EAAEC,MAAM,CAACC,MAAO;IACrBC,aAAa,EAAC,MAAM;IACpBC,yBAAyB,EAAC,qBAAqB;IAC/CC,2BAA2B;IAC3BC,QAAQ,EAAEd;EAAa,GAEtBJ,QACG,CAAC,EAGNE,IAAI,IAAIA,IAAI,CAACI,KAAK,GAAG,CAAC,IAAIJ,IAAI,CAACK,MAAM,GAAG,CAAC,iBACxCb,KAAA,CAAAiB,aAAA,CAACd,IAAI;IAACe,KAAK,EAAEhB,UAAU,CAACuB,YAAa;IAACJ,aAAa,EAAC;EAAM,gBACxDrB,KAAA,CAAAiB,aAAA,CAACb,gBAAgB;IACfsB,SAAS,EAAEnB,MAAM,CAACmB,SAAU;IAC5Bd,KAAK,EAAEJ,IAAI,CAACI,KAAM;IAClBC,MAAM,EAAEL,IAAI,CAACK,MAAO;IACpBc,SAAS,EAAEpB,MAAM,CAACoB,SAAU;IAC5BC,cAAc,EAAErB,MAAM,CAACqB,cAAe;IACtCC,QAAQ,EAAEtB,MAAM,CAACsB,QAAS;IAC1BC,YAAY,EAAEvB,MAAM,CAACuB;EAAa,CACnC,CACG,CAEJ,CAAC;AAEX;AAEA,MAAMX,MAAM,GAAGjB,UAAU,CAAC6B,MAAM,CAAC;EAC/BX,MAAM,EAAE;IACNY,OAAO,EAAE;EACX;AACF,CAAC,CAAC;AAEF3B,aAAa,CAAC4B,WAAW,GAAG,wBAAwB","ignoreList":[]}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { Parser } from '../core/parser';
|
|
3
|
+
import { SkeletonRenderer } from './SkeletonRenderer';
|
|
4
|
+
import { SkeletonIgnore } from './SkeletonIgnore';
|
|
5
|
+
import { StyleSkeleton } from '../core/generator/StyleSkeleton';
|
|
6
|
+
import { getDeepExpander } from '../core/deepRegistry';
|
|
7
|
+
import { DEFAULT_CONFIG } from '../constants/defaults';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Main Skeleton component
|
|
11
|
+
*
|
|
12
|
+
* Automatically generates skeleton loading states for your React Native components.
|
|
13
|
+
* Wraps your UI and shows skeleton placeholders while loading.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <Skeleton loading={isLoading}>
|
|
18
|
+
* <ProfileScreen />
|
|
19
|
+
* </Skeleton>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <Skeleton
|
|
25
|
+
* loading={isLoading}
|
|
26
|
+
* animation="pulse"
|
|
27
|
+
* baseColor="#f0f0f0"
|
|
28
|
+
* highlightColor="#ffffff"
|
|
29
|
+
* >
|
|
30
|
+
* <View>
|
|
31
|
+
* <Text>Hello World</Text>
|
|
32
|
+
* <Image source={avatar} />
|
|
33
|
+
* </View>
|
|
34
|
+
* </Skeleton>
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function Skeleton({
|
|
38
|
+
loading,
|
|
39
|
+
children,
|
|
40
|
+
styles,
|
|
41
|
+
excludeStyles,
|
|
42
|
+
deep = false,
|
|
43
|
+
animation = DEFAULT_CONFIG.animation,
|
|
44
|
+
duration = DEFAULT_CONFIG.duration,
|
|
45
|
+
baseColor = DEFAULT_CONFIG.baseColor,
|
|
46
|
+
highlightColor = DEFAULT_CONFIG.highlightColor,
|
|
47
|
+
borderRadius = DEFAULT_CONFIG.borderRadius,
|
|
48
|
+
accessible = true,
|
|
49
|
+
accessibilityLabel = 'Loading content',
|
|
50
|
+
debug = false
|
|
51
|
+
}) {
|
|
52
|
+
// Parse component tree and generate skeleton.
|
|
53
|
+
// Hooks must run unconditionally (rules of hooks), but parsing stays lazy:
|
|
54
|
+
// we skip the work entirely when not loading or in styles-driven mode.
|
|
55
|
+
const skeletonTree = useMemo(() => {
|
|
56
|
+
if (!loading || styles) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
if (__DEV__ && debug) {
|
|
60
|
+
console.log('[Skelo] Parsing component tree...');
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
// Deep mode: expand opaque components into their real host tree via the
|
|
64
|
+
// opt-in expander (registered by importing 'react-native-skelo/deep').
|
|
65
|
+
// Falls back to static parsing if unavailable or it returns nothing.
|
|
66
|
+
if (deep) {
|
|
67
|
+
const expand = getDeepExpander();
|
|
68
|
+
if (expand) {
|
|
69
|
+
const expanded = expand(/*#__PURE__*/React.createElement(React.Fragment, null, children));
|
|
70
|
+
if (expanded && expanded.length > 0) {
|
|
71
|
+
return expanded;
|
|
72
|
+
}
|
|
73
|
+
if (__DEV__) {
|
|
74
|
+
console.warn('[Skelo] deep expansion returned nothing; falling back to static parsing.');
|
|
75
|
+
}
|
|
76
|
+
} else if (__DEV__) {
|
|
77
|
+
console.warn("[Skelo] `deep` requires react-reconciler. Install it and add `import 'react-native-skelo/deep';` in your app entry.");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const parsed = Parser.parse(children);
|
|
81
|
+
if (__DEV__ && debug) {
|
|
82
|
+
// Log a lightweight summary: the raw nodes hold React elements
|
|
83
|
+
// (`element`) and arbitrary props that aren't safely serializable.
|
|
84
|
+
const summarize = nodes => nodes.map(node => ({
|
|
85
|
+
type: node.type,
|
|
86
|
+
style: node.style,
|
|
87
|
+
children: summarize(node.children)
|
|
88
|
+
}));
|
|
89
|
+
console.log('[Skelo] Parsed tree:', JSON.stringify(summarize(parsed), null, 2));
|
|
90
|
+
}
|
|
91
|
+
return parsed;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (__DEV__) {
|
|
94
|
+
console.error('[Skelo] Failed to parse component tree:', error);
|
|
95
|
+
}
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
}, [loading, styles, deep, children, debug]);
|
|
99
|
+
|
|
100
|
+
// Create skeleton config
|
|
101
|
+
const config = useMemo(() => ({
|
|
102
|
+
animation,
|
|
103
|
+
duration,
|
|
104
|
+
baseColor,
|
|
105
|
+
highlightColor,
|
|
106
|
+
borderRadius
|
|
107
|
+
}), [animation, duration, baseColor, highlightColor, borderRadius]);
|
|
108
|
+
|
|
109
|
+
// If not loading, render the real children directly.
|
|
110
|
+
if (!loading) {
|
|
111
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Styles-driven mode: derive the skeleton from the provided styles instead of
|
|
115
|
+
// introspecting the child tree (useful when children are opaque components).
|
|
116
|
+
if (styles) {
|
|
117
|
+
return /*#__PURE__*/React.createElement(StyleSkeleton, {
|
|
118
|
+
styles: styles,
|
|
119
|
+
config: config,
|
|
120
|
+
exclude: excludeStyles
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return /*#__PURE__*/React.createElement(SkeletonRenderer, {
|
|
124
|
+
tree: skeletonTree,
|
|
125
|
+
config: config,
|
|
126
|
+
accessible: accessible,
|
|
127
|
+
accessibilityLabel: accessibilityLabel,
|
|
128
|
+
debug: debug
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
Skeleton.displayName = 'Skeleton';
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Escape hatch to keep children as real content inside a loading `<Skeleton>`.
|
|
135
|
+
* @see SkeletonIgnore
|
|
136
|
+
*/
|
|
137
|
+
Skeleton.Ignore = SkeletonIgnore;
|
|
138
|
+
//# sourceMappingURL=Skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useMemo","Parser","SkeletonRenderer","SkeletonIgnore","StyleSkeleton","getDeepExpander","DEFAULT_CONFIG","Skeleton","loading","children","styles","excludeStyles","deep","animation","duration","baseColor","highlightColor","borderRadius","accessible","accessibilityLabel","debug","skeletonTree","__DEV__","console","log","expand","expanded","createElement","Fragment","length","warn","parsed","parse","summarize","nodes","map","node","type","style","JSON","stringify","error","config","exclude","tree","displayName","Ignore"],"sourceRoot":"../../../src","sources":["components/Skeleton.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Escape hatch that renders its children as real content, even inside a
|
|
4
|
+
* loading `<Skeleton>`. Use it for elements that should stay visible during
|
|
5
|
+
* loading — section headings, static labels, action buttons, etc.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```tsx
|
|
9
|
+
* <Skeleton loading={loading}>
|
|
10
|
+
* <Skeleton.Ignore>
|
|
11
|
+
* <Text>Profile</Text> // stays as real text
|
|
12
|
+
* </Skeleton.Ignore>
|
|
13
|
+
* <ProfileCard /> // becomes a skeleton
|
|
14
|
+
* </Skeleton>
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function SkeletonIgnore({
|
|
18
|
+
children
|
|
19
|
+
}) {
|
|
20
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
21
|
+
}
|
|
22
|
+
SkeletonIgnore.displayName = 'Skeleton.Ignore';
|
|
23
|
+
//# sourceMappingURL=SkeletonIgnore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","SkeletonIgnore","children","createElement","Fragment","displayName"],"sourceRoot":"../../../src","sources":["components/SkeletonIgnore.tsx"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AAOzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAAC;EAAEC;AAA8B,CAAC,EAAE;EAChE,oBAAOF,KAAA,CAAAG,aAAA,CAAAH,KAAA,CAAAI,QAAA,QAAGF,QAAW,CAAC;AACxB;AAEAD,cAAc,CAACI,WAAW,GAAG,iBAAiB","ignoreList":[]}
|