react-native-skelo 0.0.2 → 0.0.5

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.
Files changed (41) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +86 -90
  3. package/lib/commonjs/animations/PulseAnimation.js +17 -42
  4. package/lib/commonjs/animations/PulseAnimation.js.map +1 -1
  5. package/lib/commonjs/animations/ShimmerAnimation.js +54 -65
  6. package/lib/commonjs/animations/ShimmerAnimation.js.map +1 -1
  7. package/lib/commonjs/components/Skeleton.js +22 -16
  8. package/lib/commonjs/components/Skeleton.js.map +1 -1
  9. package/lib/commonjs/core/parser/expandLists.js +67 -0
  10. package/lib/commonjs/core/parser/expandLists.js.map +1 -0
  11. package/lib/commonjs/index.js +1 -0
  12. package/lib/commonjs/index.js.map +1 -1
  13. package/lib/module/animations/PulseAnimation.js +18 -43
  14. package/lib/module/animations/PulseAnimation.js.map +1 -1
  15. package/lib/module/animations/ShimmerAnimation.js +55 -66
  16. package/lib/module/animations/ShimmerAnimation.js.map +1 -1
  17. package/lib/module/components/Skeleton.js +22 -16
  18. package/lib/module/components/Skeleton.js.map +1 -1
  19. package/lib/module/core/parser/expandLists.js +61 -0
  20. package/lib/module/core/parser/expandLists.js.map +1 -0
  21. package/lib/module/index.js +4 -0
  22. package/lib/module/index.js.map +1 -1
  23. package/lib/typescript/animations/PulseAnimation.d.ts +0 -44
  24. package/lib/typescript/animations/PulseAnimation.d.ts.map +1 -1
  25. package/lib/typescript/animations/ShimmerAnimation.d.ts +0 -44
  26. package/lib/typescript/animations/ShimmerAnimation.d.ts.map +1 -1
  27. package/lib/typescript/components/Skeleton.d.ts +1 -1
  28. package/lib/typescript/components/Skeleton.d.ts.map +1 -1
  29. package/lib/typescript/core/parser/expandLists.d.ts +3 -0
  30. package/lib/typescript/core/parser/expandLists.d.ts.map +1 -0
  31. package/lib/typescript/index.d.ts +1 -0
  32. package/lib/typescript/index.d.ts.map +1 -1
  33. package/lib/typescript/types/skeleton.d.ts +8 -0
  34. package/lib/typescript/types/skeleton.d.ts.map +1 -1
  35. package/package.json +5 -12
  36. package/src/animations/PulseAnimation.tsx +17 -89
  37. package/src/animations/ShimmerAnimation.tsx +39 -118
  38. package/src/components/Skeleton.tsx +24 -18
  39. package/src/core/parser/expandLists.tsx +77 -0
  40. package/src/index.ts +4 -0
  41. package/src/types/skeleton.ts +9 -0
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Shubhanshu
3
+ Copyright (c) 2026 Shubhanshu Barnwal <connect@shubhanshubb.dev> (https://shubhanshubb.dev)
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,134 +1,121 @@
1
1
  <div align="center">
2
2
 
3
- # react-native-skelo
3
+ # ðŸĶī react-native-skelo
4
4
 
5
- **Write your UI once. Skelo builds the loading state automatically.**
5
+ ### Write your UI once. Skelo builds the loading state — automatically.
6
6
 
7
- [![npm](https://img.shields.io/npm/v/react-native-skelo)](https://www.npmjs.com/package/react-native-skelo)
8
- [![license](https://img.shields.io/npm/l/react-native-skelo)](./LICENSE)
7
+ [![npm version](https://img.shields.io/npm/v/react-native-skelo?color=5FC9F8&label=npm)](https://www.npmjs.com/package/react-native-skelo)
8
+ [![downloads](https://img.shields.io/npm/dm/react-native-skelo?color=5FC9F8)](https://www.npmjs.com/package/react-native-skelo)
9
+ [![license](https://img.shields.io/npm/l/react-native-skelo?color=5FC9F8)](./LICENSE)
10
+ [![PRs welcome](https://img.shields.io/badge/PRs-welcome-5FC9F8.svg)](https://github.com/shubhanshubb/react-native-skelo)
11
+
12
+ <br />
13
+
14
+ <img src="./assets/demo.gif" alt="Skelo skeleton demo" width="270" />
15
+ &nbsp;&nbsp;
16
+ <img src="./assets/grid.gif" alt="Image-grid skeleton" width="270" />
9
17
 
10
18
  </div>
11
19
 
12
- > ⚠ïļ **Pre-release (`0.0.x`).** Early and evolving — the API may change. The first **stable** release will be **`0.1.0`**. The `deep` engine is experimental — see [caveats](#deep-mode-caveats-experimental).
20
+ <br />
13
21
 
14
- Skeleton loading screens usually mean building — and maintaining — a second copy of your UI. Skelo derives the skeleton from the UI you already wrote.
22
+ **Stop building and maintaining a second copy of your UI just for loading states.** Wrap your components in `<Skeleton>` and Skelo generates a matching skeleton — sized from the styles you already wrote.
15
23
 
16
24
  ```tsx
17
- import { Skeleton } from 'react-native-skelo';
18
-
19
25
  <Skeleton loading={isLoading}>
20
- <View style={styles.card}>
21
- <Image style={styles.avatar} />
22
- <Text style={styles.name}>{user.name}</Text>
23
- </View>
26
+ <ProfileCard user={user} />
24
27
  </Skeleton>
25
28
  ```
26
29
 
27
- While `loading`, Skelo reads the tree and its styles and renders a matching skeleton (circle avatar, text bar). When `loading` is `false`, it renders your real content.
30
+ That's the whole API. No skeleton screens to hand-draw, no keeping two layouts in sync.
28
31
 
29
- ## Installation
32
+ > ⚠ïļ **Pre-release (`0.0.x`)** — evolving fast; the API may change before the stable `0.1.0`.
30
33
 
31
- ```bash
32
- npm install react-native-skelo
33
- npm install react-native-reanimated react-native-linear-gradient
34
- ```
34
+ ---
35
35
 
36
- That's all you need for the basic (inline) and `styles` usage.
36
+ ## âœĻ Features
37
37
 
38
- ### To enable `deep` mode (optional)
38
+ - 🊄 **Zero-config** — wrap a component, get a skeleton. No setup, no separate loading screen.
39
+ - 🧠 **Sees inside your components** — introspects custom components automatically (no inlining).
40
+ - 📋 **Lists included** — `FlatList` / `SectionList` render skeleton rows while data loads.
41
+ - ðŸŽĻ **Shimmer · Pulse · None** — built-in animations on the native driver.
42
+ - ðŸŠķ **No dependencies** — no `reanimated`, no gradient library. Just `react` + `react-native`.
43
+ - 📐 **Style-aware** — every skeleton is sized from your real element styles.
39
44
 
40
- `deep` mode is opt-in so the core library never bundles a reconciler you don't
41
- use. Install `react-reconciler` (matching your React version) and import the
42
- deep entry **once** in your app's entry file:
45
+ ---
43
46
 
44
- ```bash
45
- # React 19:
46
- npm install react-reconciler@0.31.0
47
- # React 18:
48
- npm install react-reconciler@0.29.2
49
- ```
47
+ ## ðŸ“Ķ Installation
50
48
 
51
- ```js
52
- // index.js (app entry)
53
- import 'react-native-skelo/deep';
49
+ ```bash
50
+ npm install react-native-skelo
54
51
  ```
55
52
 
56
- Without this, `<Skeleton deep>` simply falls back to static parsing (no crash).
57
-
58
- ## Usage
53
+ **That's it — no other dependencies.** Everything (including custom-component introspection) works out of the box.
59
54
 
60
- ### Basic — inline host elements
61
-
62
- Skelo traverses the `View` / `Text` / `Image` tree you pass and mirrors it:
63
-
64
- ```tsx
65
- <Skeleton loading={loading} animation="shimmer">
66
- <View style={styles.row}>
67
- <Image style={styles.avatar} /> {/* → circle / box */}
68
- <Text style={styles.title}>Title</Text> {/* → text bar */}
69
- </View>
70
- </Skeleton>
71
- ```
55
+ > React 18 apps: add `"react-reconciler": "0.29.x"` to your deps (Skelo ships targeting React 19's `0.31`).
72
56
 
73
- Structure comes from the JSX; dimensions come from each element's `style`.
57
+ ---
74
58
 
75
- ### `deep` — wrap any component (experimental)
59
+ ## 🚀 Usage
76
60
 
77
- Don't want to inline? Wrap an opaque component and let Skelo introspect it:
61
+ ### Just wrap it
78
62
 
79
63
  ```tsx
80
- import { Skeleton, withSkeleton } from 'react-native-skelo';
81
-
82
- <Skeleton loading={loading} deep>
83
- <ProfileScreen />
84
- </Skeleton>
64
+ import { Skeleton } from 'react-native-skelo';
85
65
 
86
- // or as an HOC:
87
- const Home = withSkeleton(HomeScreen);
88
- <Home loading={loading} {...props} />
66
+ function Screen({ loading, user }) {
67
+ return (
68
+ <Skeleton loading={loading} animation="shimmer">
69
+ <ProfileCard user={user} />
70
+ </Skeleton>
71
+ );
72
+ }
89
73
  ```
90
74
 
91
- Requires `react-reconciler` + `import 'react-native-skelo/deep'` (see [Installation](#to-enable-deep-mode-optional)). See also [caveats](#deep-mode-caveats-experimental).
75
+ Skelo renders `ProfileCard`, reads its real `View`/`Text`/`Image` tree + styles, and draws a matching skeleton while `loading` is `true`. When it's `false`, your real UI renders.
92
76
 
93
- ### `styles` — generate from a StyleSheet
77
+ ### Lists
94
78
 
95
- Pass styles directly to get a stack of skeleton shapes (no children needed):
79
+ Wrap a `FlatList` — Skelo fills it with skeleton rows while the data loads:
96
80
 
97
81
  ```tsx
98
- <Skeleton loading={loading} styles={styles} excludeStyles={['container']} />
82
+ <Skeleton loading={loading} count={6}>
83
+ <FlatList data={items} renderItem={renderItem} />
84
+ </Skeleton>
99
85
  ```
100
86
 
101
- A StyleSheet has no hierarchy, so this produces one shape per style that has visual dimensions.
102
-
103
- ### `Skeleton.Ignore` — keep something visible
87
+ ### Keep something visible
104
88
 
105
89
  ```tsx
106
90
  <Skeleton loading={loading}>
107
91
  <Skeleton.Ignore>
108
- <Text style={styles.heading}>Profile</Text> {/* stays real */}
92
+ <Text style={styles.heading}>Profile</Text> {/* stays real */}
109
93
  </Skeleton.Ignore>
110
94
  <ProfileBody />
111
95
  </Skeleton>
112
96
  ```
113
97
 
114
- ### Custom components — register a plugin
98
+ ### Generate from a StyleSheet
99
+
100
+ ```tsx
101
+ <Skeleton loading={loading} styles={styles} excludeStyles={['container']} />
102
+ ```
103
+
104
+ ### Custom skeleton for a component
115
105
 
116
106
  ```tsx
117
107
  import { Skelo } from 'react-native-skelo';
118
- import { Avatar } from 'my-design-system';
119
108
 
120
109
  Skelo.register({
121
110
  name: 'Avatar',
122
111
  component: Avatar,
123
- strategy: (props, { primitives }) => (
124
- <primitives.Circle size={props.size ?? 40} />
125
- ),
112
+ strategy: (props, { primitives }) => <primitives.Circle size={props.size ?? 40} />,
126
113
  });
127
114
  ```
128
115
 
129
- ## API
116
+ ---
130
117
 
131
- ### `<Skeleton>` props
118
+ ## ⚙ïļ `<Skeleton>` props
132
119
 
133
120
  | Prop | Type | Default | Description |
134
121
  |---|---|---|---|
@@ -137,33 +124,42 @@ Skelo.register({
137
124
  | `duration` | `number` | `1200` | Animation duration (ms) |
138
125
  | `baseColor` / `highlightColor` | `string` | theme | Skeleton colors |
139
126
  | `borderRadius` | `number` | `4` | Default corner radius |
140
- | `deep` | `boolean` | `false` | Expand opaque components (experimental) |
127
+ | `count` | `number` | `6` | Placeholder rows for a `FlatList`/`SectionList` |
128
+ | `deep` | `boolean` | auto | Force component introspection on/off (auto when available) |
141
129
  | `styles` | `StyleSheet \| style[]` | — | Generate from styles instead of children |
142
- | `excludeStyles` | `string[]` | — | Style keys to skip in `styles` mode |
143
130
  | `accessibilityLabel` | `string` | `'Loading content'` | Screen-reader label |
144
131
 
145
- Also exported: `withSkeleton`, `SkeletonIgnore`, `StyleSkeleton`, the primitives (`SkeletonBox`, `SkeletonText`, `SkeletonImage`, `SkeletonCircle`), and `Skelo` (plugin registry + `Skelo.fromStyles`).
132
+ Also exported: `withSkeleton`, `SkeletonIgnore`, `StyleSkeleton`, the primitives (`SkeletonBox`, `SkeletonText`, `SkeletonImage`, `SkeletonCircle`), and `Skelo` (`register` / `fromStyles`).
133
+
134
+ ---
135
+
136
+ ## ðŸ§Đ How it works
137
+
138
+ - **Host elements** (`View` / `Text` / `Image`) are read directly (`React.Children` + `StyleSheet.flatten`).
139
+ - **Custom components** are expanded by a tiny JS-only `react-reconciler` renderer (bundled) that renders them off-screen to recover their real host tree + styles — then feeds the same skeleton engine.
140
+ - Anything Skelo can't introspect (native content) is measured and shown as one size-matched block.
141
+
142
+ ---
146
143
 
147
- ## How it works
144
+ ## ⚠ïļ Good to know
148
145
 
149
- - **Inline mode** — static traversal of the host-element tree (`React.Children` + `StyleSheet.flatten`).
150
- - **`deep` mode** — a JS-only `react-reconciler` renderer renders the component off-screen to recover its real host tree + styles, then feeds the same skeleton renderer.
151
- - Anything Skelo can't introspect (a custom component without `deep`, or native content) is measured and shown as a single size-matched block.
146
+ Skelo skeletonizes **what your component renders during loading**:
152
147
 
153
- ## `deep` mode caveats (experimental)
148
+ - Introspection **runs mount effects** — a screen that fetches on mount may fetch twice. Prefer it for presentational trees; register a plugin for effect-heavy screens.
149
+ - It renders **outside your providers** — components needing navigation/theme/redux context fall back to a measured block.
150
+ - **Native content** (`WebView`, `MapView`, `Video`, â€Ķ) lives outside React, so it becomes a single sized block.
151
+ - A **data-driven list/grid** that renders nothing while loading has nothing to skeletonize — keep placeholder items rendered (see the [example](./example)).
154
152
 
155
- `deep` renders your component offline to read its structure, which means:
153
+ ---
156
154
 
157
- - **Mount effects run** during introspection — a screen that fetches on mount may fetch twice. Prefer `deep` for presentational trees; register a plugin or provide a manual skeleton for effectful screens.
158
- - **Renders outside your providers** — components that require navigation/theme/redux context may fail to expand; Skelo catches this and falls back to a measured block.
159
- - Only the **React host tree** is visible. `WebView`, `MapView`, `Video`, etc. render their content natively (outside React), so they can only become a single sized block.
155
+ ## 📋 Requirements
160
156
 
161
- ## Requirements
157
+ - React Native (New Architecture recommended)
158
+ - React 19 (React 18 → override `react-reconciler` to `0.29`)
159
+ - No other dependencies
162
160
 
163
- - React Native (Fabric / New Architecture recommended)
164
- - `react-native-reanimated` â‰Ĩ 3
165
- - `react-reconciler` (optional, for `deep`) — must match your React version
161
+ ---
166
162
 
167
- ## License
163
+ ## 📄 License
168
164
 
169
165
  MIT ÂĐ [Shubhanshu Barnwal](https://shubhanshubb.dev)
@@ -6,25 +6,8 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.PulseAnimation = PulseAnimation;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
- var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
9
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
11
- /**
12
- * Pulse animation component using Reanimated 3
13
- *
14
- * Creates a subtle breathing/pulsing effect using:
15
- * - Shared values for performance
16
- * - Worklets for 60 FPS on UI thread
17
- * - Opacity animation for pulse effect
18
- *
19
- * @example
20
- * ```tsx
21
- * <PulseAnimation
22
- * width={200}
23
- * height={20}
24
- * borderRadius={4}
25
- * />
26
- * ```
27
- */
10
+ // Breathing opacity loop using React Native's built-in Animated (native driver).
28
11
  function PulseAnimation({
29
12
  width,
30
13
  height,
@@ -34,38 +17,30 @@ function PulseAnimation({
34
17
  style,
35
18
  children
36
19
  }) {
37
- // Shared value for opacity (0 to 1)
38
- const opacity = (0, _reactNativeReanimated.useSharedValue)(1);
20
+ const opacity = (0, _react.useRef)(new _reactNative.Animated.Value(1)).current;
39
21
  (0, _react.useEffect)(() => {
40
- // Start infinite pulse animation
41
- // Sequence: fade out -> fade in
42
- opacity.value = (0, _reactNativeReanimated.withRepeat)((0, _reactNativeReanimated.withSequence)((0, _reactNativeReanimated.withTiming)(0.5, {
22
+ const loop = _reactNative.Animated.loop(_reactNative.Animated.sequence([_reactNative.Animated.timing(opacity, {
23
+ toValue: 0.5,
43
24
  duration: duration / 2,
44
- easing: _reactNativeReanimated.Easing.inOut(_reactNativeReanimated.Easing.ease)
45
- }), (0, _reactNativeReanimated.withTiming)(1, {
25
+ easing: _reactNative.Easing.inOut(_reactNative.Easing.ease),
26
+ useNativeDriver: true
27
+ }), _reactNative.Animated.timing(opacity, {
28
+ toValue: 1,
46
29
  duration: duration / 2,
47
- easing: _reactNativeReanimated.Easing.inOut(_reactNativeReanimated.Easing.ease)
48
- })), -1,
49
- // Infinite repeat
50
- false // Don't reverse
51
- );
30
+ easing: _reactNative.Easing.inOut(_reactNative.Easing.ease),
31
+ useNativeDriver: true
32
+ })]));
33
+ loop.start();
34
+ return () => loop.stop();
52
35
  }, [duration, opacity]);
53
-
54
- // Animated style for pulse effect
55
- const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
56
- 'worklet';
57
-
58
- return {
59
- opacity: opacity.value
60
- };
61
- }, []);
62
- return /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
36
+ return /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, {
63
37
  style: [styles.container, {
64
38
  width,
65
39
  height,
66
40
  borderRadius,
67
- backgroundColor: baseColor
68
- }, animatedStyle, style]
41
+ backgroundColor: baseColor,
42
+ opacity
43
+ }, style]
69
44
  }, children);
70
45
  }
71
46
  const styles = _reactNative.StyleSheet.create({
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","PulseAnimation","width","height","baseColor","duration","borderRadius","style","children","opacity","useSharedValue","useEffect","value","withRepeat","withSequence","withTiming","easing","Easing","inOut","ease","animatedStyle","useAnimatedStyle","createElement","View","styles","container","backgroundColor","StyleSheet","create","overflow"],"sourceRoot":"../../../src","sources":["animations/PulseAnimation.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","PulseAnimation","width","height","baseColor","duration","borderRadius","style","children","opacity","useRef","Animated","Value","current","useEffect","loop","sequence","timing","toValue","easing","Easing","inOut","ease","useNativeDriver","start","stop","createElement","View","styles","container","backgroundColor","StyleSheet","create","overflow"],"sourceRoot":"../../../src","sources":["animations/PulseAnimation.tsx"],"mappings":"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","ignoreList":[]}
@@ -6,26 +6,10 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.ShimmerAnimation = ShimmerAnimation;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
- var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
- var _reactNativeLinearGradient = require("react-native-linear-gradient");
11
9
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
12
- /**
13
- * Shimmer animation component using Reanimated 3
14
- *
15
- * Creates a smooth left-to-right shimmer effect using:
16
- * - Shared values for performance
17
- * - Worklets for 60 FPS on UI thread
18
- * - Linear gradient for shimmer effect
19
- *
20
- * @example
21
- * ```tsx
22
- * <ShimmerAnimation
23
- * width={200}
24
- * height={20}
25
- * borderRadius={4}
26
- * />
27
- * ```
28
- */
10
+ // Zero-dependency shimmer: a highlight band (dim/bright/dim segments to fake a
11
+ // soft gradient) sweeps across the base, driven by React Native's built-in
12
+ // Animated native driver. Plain Views only — guaranteed to render and animate.
29
13
  function ShimmerAnimation({
30
14
  width,
31
15
  height,
@@ -36,68 +20,73 @@ function ShimmerAnimation({
36
20
  style,
37
21
  children
38
22
  }) {
39
- // Shared value for animation progress (0 to 1)
40
- const progress = (0, _reactNativeReanimated.useSharedValue)(0);
23
+ const progress = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current;
24
+ const [measuredWidth, setMeasuredWidth] = (0, _react.useState)(0);
41
25
  (0, _react.useEffect)(() => {
42
- // Start infinite shimmer animation
43
- progress.value = (0, _reactNativeReanimated.withRepeat)((0, _reactNativeReanimated.withTiming)(1, {
26
+ const loop = _reactNative.Animated.loop(_reactNative.Animated.timing(progress, {
27
+ toValue: 1,
44
28
  duration,
45
- easing: _reactNativeReanimated.Easing.linear
46
- }), -1,
47
- // Infinite repeat
48
- false // Don't reverse
49
- );
29
+ easing: _reactNative.Easing.linear,
30
+ useNativeDriver: true
31
+ }));
32
+ loop.start();
33
+ return () => loop.stop();
50
34
  }, [duration, progress]);
51
-
52
- // Animated style for shimmer overlay
53
- const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => {
54
- 'worklet';
55
-
56
- // Calculate shimmer position
57
- // Interpolate from -100% to 100% to create left-to-right sweep
58
- const translateX = (0, _reactNativeReanimated.interpolate)(progress.value, [0, 1], [-1, 1]);
59
- return {
60
- transform: [{
61
- translateX: translateX * (typeof width === 'number' ? width : 200)
62
- }]
63
- };
64
- }, [width]);
35
+ const onLayout = event => {
36
+ const w = event.nativeEvent.layout.width;
37
+ setMeasuredWidth(prev => prev === w ? prev : w);
38
+ };
39
+ const containerWidth = typeof width === 'number' ? width : measuredWidth || 200;
40
+ const bandWidth = Math.max(containerWidth * 0.6, 80);
41
+ const translateX = progress.interpolate({
42
+ inputRange: [0, 1],
43
+ outputRange: [-bandWidth, containerWidth]
44
+ });
65
45
  return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
46
+ onLayout: onLayout,
66
47
  style: [styles.container, {
67
48
  width,
68
49
  height,
69
50
  borderRadius,
70
51
  backgroundColor: baseColor
71
52
  }, style]
72
- }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
73
- style: [_reactNative.StyleSheet.absoluteFill, {
74
- overflow: 'hidden',
75
- borderRadius
53
+ }, /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, {
54
+ pointerEvents: "none",
55
+ style: [styles.band, {
56
+ width: bandWidth,
57
+ transform: [{
58
+ translateX
59
+ }]
60
+ }]
61
+ }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
62
+ style: [styles.segment, {
63
+ backgroundColor: highlightColor,
64
+ opacity: 0.25
65
+ }]
66
+ }), /*#__PURE__*/_react.default.createElement(_reactNative.View, {
67
+ style: [styles.segment, {
68
+ backgroundColor: highlightColor,
69
+ opacity: 0.9
76
70
  }]
77
- }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, {
78
- style: [styles.shimmer, {
79
- width: typeof width === 'number' ? width : '100%',
80
- height: '100%'
81
- }, animatedStyle]
82
- }, /*#__PURE__*/_react.default.createElement(_reactNativeLinearGradient.LinearGradient, {
83
- colors: [baseColor, highlightColor, highlightColor, baseColor],
84
- start: {
85
- x: 0,
86
- y: 0
87
- },
88
- end: {
89
- x: 1,
90
- y: 0
91
- },
92
- style: _reactNative.StyleSheet.absoluteFill
93
- }))), children);
71
+ }), /*#__PURE__*/_react.default.createElement(_reactNative.View, {
72
+ style: [styles.segment, {
73
+ backgroundColor: highlightColor,
74
+ opacity: 0.25
75
+ }]
76
+ })), children);
94
77
  }
95
78
  const styles = _reactNative.StyleSheet.create({
96
79
  container: {
97
80
  overflow: 'hidden'
98
81
  },
99
- shimmer: {
100
- position: 'absolute'
82
+ band: {
83
+ position: 'absolute',
84
+ top: 0,
85
+ bottom: 0,
86
+ flexDirection: 'row'
87
+ },
88
+ segment: {
89
+ flex: 1
101
90
  }
102
91
  });
103
92
  //# sourceMappingURL=ShimmerAnimation.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_reactNativeLinearGradient","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ShimmerAnimation","width","height","baseColor","highlightColor","duration","borderRadius","style","children","progress","useSharedValue","useEffect","value","withRepeat","withTiming","easing","Easing","linear","animatedStyle","useAnimatedStyle","translateX","interpolate","transform","createElement","View","styles","container","backgroundColor","StyleSheet","absoluteFill","overflow","shimmer","LinearGradient","colors","start","x","y","end","create","position"],"sourceRoot":"../../../src","sources":["animations/ShimmerAnimation.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ShimmerAnimation","width","height","baseColor","highlightColor","duration","borderRadius","style","children","progress","useRef","Animated","Value","current","measuredWidth","setMeasuredWidth","useState","useEffect","loop","timing","toValue","easing","Easing","linear","useNativeDriver","start","stop","onLayout","event","w","nativeEvent","layout","prev","containerWidth","bandWidth","Math","max","translateX","interpolate","inputRange","outputRange","createElement","View","styles","container","backgroundColor","pointerEvents","band","transform","segment","opacity","StyleSheet","create","overflow","position","top","bottom","flexDirection","flex"],"sourceRoot":"../../../src","sources":["animations/ShimmerAnimation.tsx"],"mappings":"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","ignoreList":[]}
@@ -10,6 +10,7 @@ var _SkeletonRenderer = require("./SkeletonRenderer");
10
10
  var _SkeletonIgnore = require("./SkeletonIgnore");
11
11
  var _StyleSkeleton = require("../core/generator/StyleSkeleton");
12
12
  var _deepRegistry = require("../core/deepRegistry");
13
+ var _expandLists = require("../core/parser/expandLists");
13
14
  var _defaults = require("../constants/defaults");
14
15
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
15
16
  /**
@@ -45,7 +46,8 @@ function Skeleton({
45
46
  children,
46
47
  styles,
47
48
  excludeStyles,
48
- deep = false,
49
+ deep,
50
+ count = 6,
49
51
  animation = _defaults.DEFAULT_CONFIG.animation,
50
52
  duration = _defaults.DEFAULT_CONFIG.duration,
51
53
  baseColor = _defaults.DEFAULT_CONFIG.baseColor,
@@ -66,24 +68,28 @@ function Skeleton({
66
68
  console.log('[Skelo] Parsing component tree...');
67
69
  }
68
70
  try {
71
+ // Turn FlatList/SectionList into placeholder rows so lists show a
72
+ // skeleton even though their data (and rows) don't exist yet.
73
+ const prepared = (0, _expandLists.expandListPlaceholders)(children, count);
74
+
69
75
  // Deep mode: expand opaque components into their real host tree via the
70
76
  // opt-in expander (registered by importing 'react-native-skelo/deep').
71
- // Falls back to static parsing if unavailable or it returns nothing.
72
- if (deep) {
73
- const expand = (0, _deepRegistry.getDeepExpander)();
74
- if (expand) {
75
- const expanded = expand(/*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, children));
76
- if (expanded && expanded.length > 0) {
77
- return expanded;
78
- }
79
- if (__DEV__) {
80
- console.warn('[Skelo] deep expansion returned nothing; falling back to static parsing.');
81
- }
82
- } else if (__DEV__) {
83
- console.warn("[Skelo] `deep` requires react-reconciler. Install it and add `import 'react-native-skelo/deep';` in your app entry.");
77
+ // When `deep` is not set explicitly, it's used automatically whenever the
78
+ // expander is available. Falls back to static parsing otherwise.
79
+ const expand = (0, _deepRegistry.getDeepExpander)();
80
+ const wantDeep = deep === undefined ? expand !== null : deep;
81
+ if (wantDeep && expand) {
82
+ const expanded = expand(/*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, prepared));
83
+ if (expanded && expanded.length > 0) {
84
+ return expanded;
85
+ }
86
+ if (__DEV__) {
87
+ console.warn('[Skelo] deep expansion returned nothing; falling back to static parsing.');
84
88
  }
89
+ } else if (deep === true && !expand && __DEV__) {
90
+ console.warn("[Skelo] `deep` requires react-reconciler. Install it and add `import 'react-native-skelo/deep';` in your app entry.");
85
91
  }
86
- const parsed = _parser.Parser.parse(children);
92
+ const parsed = _parser.Parser.parse(prepared);
87
93
  if (__DEV__ && debug) {
88
94
  // Log a lightweight summary: the raw nodes hold React elements
89
95
  // (`element`) and arbitrary props that aren't safely serializable.
@@ -101,7 +107,7 @@ function Skeleton({
101
107
  }
102
108
  return [];
103
109
  }
104
- }, [loading, styles, deep, children, debug]);
110
+ }, [loading, styles, deep, count, children, debug]);
105
111
 
106
112
  // Create skeleton config
107
113
  const config = (0, _react.useMemo)(() => ({