├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ └── publish.yml ├── .gitignore ├── .husky ├── commit-msg ├── pre-commit └── pre-push ├── .npmignore ├── .prettierrc.js ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets ├── banner-of-dynamic-shimmer.gif ├── preview1.gif └── preview2.gif ├── babel.config.js ├── example ├── .bundle │ └── config ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── Gemfile ├── Gemfile.lock ├── __tests__ │ └── App.test.tsx ├── android │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── dynamicshimmer │ │ │ │ └── ReactNativeFlipper.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── dynamicshimmer │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── release │ │ │ └── java │ │ │ └── com │ │ │ └── dynamicshimmer │ │ │ └── ReactNativeFlipper.java │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── .xcode.env │ ├── DynamicShimmer.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── DynamicShimmer.xcscheme │ ├── DynamicShimmer.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── DynamicShimmer │ │ ├── AppDelegate.h │ │ ├── AppDelegate.mm │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── main.m │ ├── DynamicShimmerTests │ │ ├── DynamicShimmerTests.m │ │ └── Info.plist │ ├── Podfile │ └── Podfile.lock ├── jest.config.js ├── metro.config.js ├── package.json ├── src │ ├── App.tsx │ ├── components │ │ ├── List │ │ │ ├── List.tsx │ │ │ ├── ListStyles.ts │ │ │ ├── ListTypes.ts │ │ │ └── index.ts │ │ ├── Profile │ │ │ ├── Profile.tsx │ │ │ ├── ProfileStyles.ts │ │ │ └── index.ts │ │ ├── ScrollViewExample │ │ │ ├── ScrollViewExample.tsx │ │ │ ├── ScrollViewExampleStyles.ts │ │ │ └── index.ts │ │ ├── ShimmerElement │ │ │ ├── ShimmerElement.tsx │ │ │ └── index.ts │ │ └── index.ts │ ├── constants │ │ ├── AppConst.ts │ │ ├── NavigationStrings.ts │ │ ├── StaticData.ts │ │ ├── Strings.ts │ │ └── index.ts │ ├── hooks │ │ ├── index.ts │ │ └── useLoading.ts │ ├── modules │ │ ├── Home │ │ │ ├── HomeScreen.tsx │ │ │ ├── HomeScreenStyles.ts │ │ │ └── index.ts │ │ ├── List │ │ │ ├── ListScreen.tsx │ │ │ └── index.ts │ │ ├── Profile │ │ │ ├── ProfileScreen.tsx │ │ │ └── index.ts │ │ ├── ScrollViewExample │ │ │ ├── ScrollViewExampleScreen.tsx │ │ │ └── index.ts │ │ └── index.ts │ ├── navigation │ │ ├── Routes.tsx │ │ └── types.ts │ └── theme │ │ ├── ApplicationStyle.ts │ │ ├── Colors.ts │ │ └── index.ts └── tsconfig.json ├── package.json ├── src ├── components │ ├── Shimmer │ │ ├── Shimmer.tsx │ │ ├── ShimmerStyles.ts │ │ ├── ShimmerTypes.ts │ │ ├── components │ │ │ ├── RenderShimmerView │ │ │ │ ├── RenderShimmerView.tsx │ │ │ │ ├── RenderShimmerViewTypes.ts │ │ │ │ └── index.ts │ │ │ ├── ShimmerEffect │ │ │ │ ├── ShimmerEffect.tsx │ │ │ │ ├── ShimmerEffectStyles.ts │ │ │ │ ├── ShimmerEffectTypes.ts │ │ │ │ └── index.ts │ │ │ ├── ShimmerFlatList │ │ │ │ ├── ShimmerFlatList.tsx │ │ │ │ ├── ShimmerFlatListTypes.ts │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ └── index.ts │ └── index.ts ├── constants │ ├── AppConst.ts │ ├── StaticData.ts │ └── index.ts ├── index.ts ├── theme │ ├── Colors.ts │ ├── Metrics.ts │ └── index.ts └── utils │ ├── CommonUtils.ts │ └── index.ts └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | example/ 3 | lib/ 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const OFF = 0; 2 | const WARN = 1; 3 | const ERROR = 2; 4 | 5 | module.exports = { 6 | extends: ['@react-native-community', 'prettier'], 7 | plugins: ['prettier'], 8 | root: true, 9 | ignorePatterns: ['.eslintrc.js'], 10 | rules: { 11 | 'prettier/prettier': [ 12 | 'error', 13 | {}, 14 | { 15 | usePrettierrc: true, 16 | }, 17 | ], 18 | 'prefer-const': 'warn', 19 | 'no-console': ['error', { allow: ['warn', 'error'] }], 20 | // General 21 | indent: [ 22 | OFF, 23 | 2, 24 | { 25 | SwitchCase: 1, 26 | VariableDeclarator: 1, 27 | outerIIFEBody: 1, 28 | FunctionDeclaration: { 29 | parameters: 1, 30 | body: 1, 31 | }, 32 | FunctionExpression: { 33 | parameters: 1, 34 | body: 1, 35 | }, 36 | flatTernaryExpressions: true, 37 | offsetTernaryExpressions: true, 38 | }, 39 | ], 40 | 'global-require': OFF, 41 | 'no-plusplus': OFF, 42 | 'no-cond-assign': OFF, 43 | 'max-classes-per-file': [ERROR, 10], 44 | 'no-shadow': OFF, 45 | 'no-undef': OFF, 46 | 'no-bitwise': OFF, 47 | 'no-param-reassign': OFF, 48 | 'no-use-before-define': OFF, 49 | 'linebreak-style': [ERROR, 'unix'], 50 | semi: [ERROR, 'always'], 51 | 'object-curly-spacing': [ERROR, 'always'], 52 | 'eol-last': [ERROR, 'always'], 53 | 'no-console': OFF, 54 | 'no-restricted-syntax': [ 55 | WARN, 56 | { 57 | selector: 58 | "CallExpression[callee.object.name='console'][callee.property.name!=/^(warn|error|info|trace|disableYellowBox|tron)$/]", 59 | message: 'Unexpected property on console object was called', 60 | }, 61 | ], 62 | eqeqeq: [WARN, 'always'], 63 | quotes: [ 64 | ERROR, 65 | 'single', 66 | { avoidEscape: true, allowTemplateLiterals: false }, 67 | ], 68 | // typescript 69 | '@typescript-eslint/no-shadow': [ERROR], 70 | '@typescript-eslint/no-use-before-define': [ERROR], 71 | '@typescript-eslint/no-unused-vars': ERROR, 72 | '@typescript-eslint/consistent-type-definitions': [ERROR, 'interface'], 73 | '@typescript-eslint/indent': [ 74 | OFF, 75 | 2, 76 | { 77 | SwitchCase: 1, 78 | VariableDeclarator: 1, 79 | outerIIFEBody: 1, 80 | FunctionDeclaration: { 81 | parameters: 1, 82 | body: 1, 83 | }, 84 | FunctionExpression: { 85 | parameters: 1, 86 | body: 1, 87 | }, 88 | flatTernaryExpressions: true, 89 | offsetTernaryExpressions: true, 90 | }, 91 | ], 92 | // react 93 | 'react/jsx-props-no-spreading': OFF, 94 | 'react/jsx-filename-extension': [ 95 | ERROR, 96 | { extensions: ['.js', '.jsx', '.ts', '.tsx'] }, 97 | ], 98 | 'react/no-unescaped-entities': [ERROR, { forbid: ['>', '"', '}'] }], 99 | 'react/prop-types': [ 100 | ERROR, 101 | { ignore: ['action', 'dispatch', 'nav', 'navigation'] }, 102 | ], 103 | 'react/display-name': OFF, 104 | 'react/jsx-boolean-value': ERROR, 105 | 'react/jsx-no-undef': ERROR, 106 | 'react/jsx-uses-react': ERROR, 107 | 'react/jsx-sort-props': [ 108 | ERROR, 109 | { 110 | callbacksLast: true, 111 | shorthandFirst: true, 112 | ignoreCase: true, 113 | noSortAlphabetically: true, 114 | }, 115 | ], 116 | 'react/jsx-pascal-case': ERROR, 117 | 'react/no-children-prop': OFF, 118 | // react-native specific rules 119 | 'react-native/no-unused-styles': ERROR, 120 | 'react-native/no-inline-styles': ERROR, 121 | 'react-native/no-color-literals': ERROR, 122 | 'react-native/no-raw-text': ERROR, 123 | }, 124 | globals: { 125 | JSX: 'readonly', 126 | }, 127 | env: { 128 | jest: true, 129 | }, 130 | }; 131 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: "🚀 Publish" 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | release: 10 | name: 🚀 Publish 11 | runs-on: macos-13 12 | steps: 13 | - name: 📚 checkout 14 | uses: actions/checkout@v2.4.2 15 | - name: 🟢 node 16 | uses: actions/setup-node@v3.3.0 17 | with: 18 | node-version: 18 19 | registry-url: https://registry.npmjs.org 20 | - name: 🚀 Build & Publish 21 | run: yarn install && yarn build && yarn publish --access public 22 | env: 23 | NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log* 37 | yarn.lock 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | !debug.keystore 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://docs.fastlane.tools/best-practices/source-control/ 51 | 52 | */fastlane/report.xml 53 | */fastlane/Preview.html 54 | */fastlane/screenshots 55 | 56 | # Bundle artifact 57 | *.jsbundle 58 | 59 | # Ruby / CocoaPods 60 | /ios/Pods/ 61 | /vendor/bundle/ 62 | 63 | # generated 64 | lib 65 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | # npx build 5 | # npx test -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .github/ 2 | example/ 3 | assets/ 4 | .eslintignore 5 | .eslintrc 6 | CONTRIBUTING.md 7 | babel.config.js 8 | .buckconfig 9 | jest-setup.js 10 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: true, 5 | singleQuote: true, 6 | trailingComma: 'es5' 7 | }; 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We welcome code changes that improve this library or fix a problem, and please make sure to follow all best practices and test all the changes/fixes before committing and creating a pull request. 🚀 🚀 4 | 5 | ### Committing and Pushing Changes 6 | 7 | Commit messages should be formatted as: 8 | 9 | ``` 10 | [optional scope]: 11 | 12 | [optional body] 13 | 14 | [optional footer] 15 | ``` 16 | 17 | Where type can be one of the following: 18 | 19 | - feat 20 | - fix 21 | - docs 22 | - chore 23 | - style 24 | - refactor 25 | - test 26 | 27 | and an optional scope can be a component 28 | 29 | ``` 30 | docs: update contributing guide 31 | ``` 32 | 33 | ``` 34 | fix(TicketId/Component): layout flicker issue 35 | ``` 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Simform Solutions 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Dynamic Shimmer - Simform](./assets/banner-of-dynamic-shimmer.gif) 2 | 3 | # react-native-dynamic-shimmer 4 | 5 | [![react-native-dynamic-shimmer on npm](https://img.shields.io/npm/v/react-native-dynamic-shimmer.svg?style=flat)](https://www.npmjs.com/package/react-native-dynamic-shimmer) [![react-native-dynamic-shimmer downloads](https://img.shields.io/npm/dm/react-native-dynamic-shimmer)](https://www.npmtrends.com/react-native-dynamic-shimmer) [![react-native-dynamic-shimmer install size](https://packagephobia.com/badge?p=react-native-dynamic-shimmer)](https://packagephobia.com/result?p=react-native-dynamic-shimmer) [![Android](https://img.shields.io/badge/Platform-Android-green?logo=android)](https://www.android.com) [![iOS](https://img.shields.io/badge/Platform-iOS-green?logo=apple)](https://developer.apple.com/ios) [![MIT](https://img.shields.io/badge/License-MIT-green)](https://opensource.org/licenses/MIT) 6 | 7 | --- 8 | 9 | This package offers an efficient Shimmer component wrapper for React Native apps, enabling you to effortlessly show loading placeholders (shimmer effects) while data is being retrieved. 10 | 11 | The Shimmer component can be used with any view, including text, images, and custom components, ensuring a smooth loading experience. 12 | 13 | --- 14 | 15 | ## 🎬 Preview 16 | 17 | --- 18 | 19 | 20 | 21 | 22 | 23 | 24 |
SimformSolutionsSimformSolutions
25 | 26 | --- 27 | 28 | ## Quick Access 29 | 30 | - [Installation](#installation) 31 | - [Usage and Examples](#usage) 32 | - [Properties](#properties) 33 | - [Example Code](#example) 34 | - [License](#license) 35 | 36 | ## Getting Started 🔧 37 | 38 | Here's how to get started with react-native-dynamic-shimmer in your React Native project: 39 | 40 | ### Installation 41 | 42 | ##### 1. Install the package 43 | 44 | ```bash 45 | $ npm install react-native-dynamic-shimmer 46 | # --- or --- 47 | $ yarn add react-native-dynamic-shimmer 48 | ``` 49 | 50 | ##### 2. Install peer dependencies 51 | 52 | ```bash 53 | $ npm install lodash 54 | # --- or --- 55 | $ yarn add lodash 56 | ``` 57 | 58 | ##### 3. Install cocoapods in the ios project 59 | 60 | ```bash 61 | cd ios && pod install 62 | ``` 63 | 64 | ##### Know more about [lodash](https://www.npmjs.com/package/lodash) 65 | 66 | --- 67 | 68 | ### Usage 69 | 70 | #### Basic Example 71 | 72 | Here we’ve created a simple component and wrapped that in Shimmer to show shimmer effect. 73 | 74 | ```tsx 75 | import React, { useEffect, useState } from 'react'; 76 | import { Image, Text, View, StyleSheet } from 'react-native'; 77 | import { Shimmer } from 'react-native-dynamic-shimmer'; 78 | import LinearGradient from 'react-native-linear-gradient'; 79 | 80 | const App = (): React.JSX.Element => { 81 | const [isLoading, setIsLoading] = useState(true); 82 | 83 | useEffect(() => { 84 | const timer = setTimeout(() => { 85 | setIsLoading(false); 86 | }, 3000); 87 | 88 | return () => clearTimeout(timer); 89 | }, []); 90 | 91 | const ShimmerElement = () => { 92 | return ( 93 | 100 | ); 101 | }; 102 | 103 | const ProfileCard = (): React.JSX.Element => { 104 | return ( 105 | 106 | 112 | 113 | 114 | Michael Williams 115 | 116 | Software Engineer 117 | 118 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla 119 | ultricies urna eget sapien ultrices, eu maximus justo rutrum. 120 | 121 | 122 | 123 | ); 124 | }; 125 | 126 | return ( 127 | }> 128 | 129 | 130 | ); 131 | }; 132 | 133 | const styles = StyleSheet.create({ 134 | profileContainer: { 135 | flexDirection: 'row', 136 | alignItems: 'center', 137 | padding: 20, 138 | borderBottomWidth: 1, 139 | borderBottomColor: '#9b9b9b', 140 | }, 141 | profileImage: { 142 | width: 100, 143 | height: 100, 144 | borderRadius: 50, 145 | marginRight: 20, 146 | }, 147 | textWrapper: { 148 | flex: 1, 149 | }, 150 | name: { 151 | fontSize: 24, 152 | fontWeight: 'bold', 153 | marginBottom: 5, 154 | }, 155 | jobTitle: { 156 | fontSize: 18, 157 | marginBottom: 10, 158 | color: '#9b9b9b', 159 | }, 160 | profileBio: { 161 | fontSize: 16, 162 | lineHeight: 22, 163 | }, 164 | }); 165 | 166 | export default App; 167 | ``` 168 | 169 | > **Note: If you're using React Native CLI, you can use LinearGradient from the 'react-native-linear-gradient' package for the shimmer element, as shown in the above example. For Expo projects, you should use 'expo-linear-gradient' instead of 'react-native-linear-gradient' for gradient support for shimmer element**. 170 | 171 | #### 🎬 Preview 172 | 173 | --- 174 | 175 | 176 | 177 | 178 | 179 |
SimformSolutions
180 | 181 | ### Properties 182 | 183 | | **Props** | **Default** | **Type** | **Description** | 184 | | ------------ | :---------: | :----------------: | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 185 | | **loading** | true | boolean | This prop controls whether the Shimmer component displays the loading shimmer effect. If loading is true, the shimmer effect will be visible; otherwise, the actual content (wrapped by the Shimmer component) will be displayed. | 186 | | shimmerElement | - | React.ReactElement | A custom gradient element used to create the shimmer effect. This allows flexibility to provide different gradient designs for the shimmer animation. | 187 | | duration | 1000 | number | Specifies the duration of the shimmer animation in milliseconds. This value determines how long the shimmer effect will run, allowing you to control the speed and smoothness of the shimmer transition. | 188 | 189 | --- 190 | 191 | ### Additional Prop 192 | 193 | This prop is used in a **Text** element when you need a customized length for a particular text. 194 | 195 | | **Props** | **Default** | **Type** | **Description** | 196 | | -------------- | :---------: | :------: | -------------------------------------------------------------------------------------------------------------------------------------------------------- | 197 | | **aria-label** | - | string | If provided, the shimmer width for a Text element is calculated based on the aria-label string length, offering more precise control over shimmer width. | 198 | 199 | --- 200 | 201 | ## Example 202 | 203 | You can check out the example app for react-native-dynamic-shimmer in [Example](./example/src/App.tsx) 204 | 205 | ```sh 206 | yarn 207 | yarn example ios // For ios 208 | yarn example android // For Android 209 | ``` 210 | 211 | # TODO 212 | 213 | - [ ] Enhance FlatList Shimmer Effect with a Custom Hook in the renderItem Function 214 | - [ ] Add Support for Memoized Components 215 | - [ ] Implement Compatibility for SVG Components 216 | - [ ] Handle Complex UI Scenarios 217 | - [ ] Extend Support for Various UI Libraries 218 | - [ ] Performance Improvement 219 | 220 | ## Find this library useful? ❤️ 221 | 222 | Support it by joining [stargazers](https://github.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/stargazers) for this repository.⭐ 223 | 224 | ## Bugs / Feature requests / Feedbacks 225 | 226 | For bugs, feature requests, and discussion please use [GitHub Issues](https://github.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/issues/new?labels=bug&late=BUG_REPORT.md&title=%5BBUG%5D%3A), [GitHub New Feature](https://github.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/issues/new?labels=enhancement&late=FEATURE_REQUEST.md&title=%5BFEATURE%5D%3A), [GitHub Feedback](https://github.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/issues/new?labels=enhancement&late=FEATURE_REQUEST.md&title=%5BFEEDBACK%5D%3A) 227 | 228 | ## 🤝 How to Contribute 229 | 230 | We'd love to have you improve this library or fix a problem 💪 231 | Check out our [Contributing Guide](CONTRIBUTING.md) for ideas on contributing. 232 | 233 | ## Awesome Mobile Libraries 234 | 235 | - Check out our other [available awesome mobile libraries](https://github.com/SimformSolutionsPvtLtd/Awesome-Mobile-Libraries) 236 | 237 | ## License 238 | 239 | - [MIT License](./LICENSE) 240 | -------------------------------------------------------------------------------- /assets/banner-of-dynamic-shimmer.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/assets/banner-of-dynamic-shimmer.gif -------------------------------------------------------------------------------- /assets/preview1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/assets/preview1.gif -------------------------------------------------------------------------------- /assets/preview2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/assets/preview2.gif -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | 35 | # node.js 36 | # 37 | node_modules/ 38 | npm-debug.log 39 | yarn-error.log 40 | yarn.lock 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | !debug.keystore 47 | 48 | # fastlane 49 | # 50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 51 | # screenshots whenever they are needed. 52 | # For more information about the recommended setup visit: 53 | # https://docs.fastlane.tools/best-practices/source-control/ 54 | 55 | **/fastlane/report.xml 56 | **/fastlane/Preview.html 57 | **/fastlane/screenshots 58 | **/fastlane/test_output 59 | 60 | # Bundle artifact 61 | *.jsbundle 62 | 63 | # Ruby / CocoaPods 64 | /ios/Pods/ 65 | /vendor/bundle/ 66 | -------------------------------------------------------------------------------- /example/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: true, 5 | singleQuote: true, 6 | trailingComma: 'es5', 7 | }; 8 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /example/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | gem 'cocoapods', '~> 1.13' 7 | gem 'activesupport', '>= 6.1.7.3', '< 7.1.0' 8 | -------------------------------------------------------------------------------- /example/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.7) 5 | base64 6 | nkf 7 | rexml 8 | activesupport (7.0.8.4) 9 | concurrent-ruby (~> 1.0, >= 1.0.2) 10 | i18n (>= 1.6, < 2) 11 | minitest (>= 5.1) 12 | tzinfo (~> 2.0) 13 | addressable (2.8.7) 14 | public_suffix (>= 2.0.2, < 7.0) 15 | algoliasearch (1.27.5) 16 | httpclient (~> 2.8, >= 2.8.3) 17 | json (>= 1.5.1) 18 | atomos (0.1.3) 19 | base64 (0.2.0) 20 | claide (1.1.0) 21 | cocoapods (1.15.2) 22 | addressable (~> 2.8) 23 | claide (>= 1.0.2, < 2.0) 24 | cocoapods-core (= 1.15.2) 25 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 26 | cocoapods-downloader (>= 2.1, < 3.0) 27 | cocoapods-plugins (>= 1.0.0, < 2.0) 28 | cocoapods-search (>= 1.0.0, < 2.0) 29 | cocoapods-trunk (>= 1.6.0, < 2.0) 30 | cocoapods-try (>= 1.1.0, < 2.0) 31 | colored2 (~> 3.1) 32 | escape (~> 0.0.4) 33 | fourflusher (>= 2.3.0, < 3.0) 34 | gh_inspector (~> 1.0) 35 | molinillo (~> 0.8.0) 36 | nap (~> 1.0) 37 | ruby-macho (>= 2.3.0, < 3.0) 38 | xcodeproj (>= 1.23.0, < 2.0) 39 | cocoapods-core (1.15.2) 40 | activesupport (>= 5.0, < 8) 41 | addressable (~> 2.8) 42 | algoliasearch (~> 1.0) 43 | concurrent-ruby (~> 1.1) 44 | fuzzy_match (~> 2.0.4) 45 | nap (~> 1.0) 46 | netrc (~> 0.11) 47 | public_suffix (~> 4.0) 48 | typhoeus (~> 1.0) 49 | cocoapods-deintegrate (1.0.5) 50 | cocoapods-downloader (2.1) 51 | cocoapods-plugins (1.0.0) 52 | nap 53 | cocoapods-search (1.0.1) 54 | cocoapods-trunk (1.6.0) 55 | nap (>= 0.8, < 2.0) 56 | netrc (~> 0.11) 57 | cocoapods-try (1.2.0) 58 | colored2 (3.1.2) 59 | concurrent-ruby (1.3.3) 60 | escape (0.0.4) 61 | ethon (0.16.0) 62 | ffi (>= 1.15.0) 63 | ffi (1.17.0) 64 | fourflusher (2.3.1) 65 | fuzzy_match (2.0.4) 66 | gh_inspector (1.1.3) 67 | httpclient (2.8.3) 68 | i18n (1.14.5) 69 | concurrent-ruby (~> 1.0) 70 | json (2.7.2) 71 | minitest (5.24.1) 72 | molinillo (0.8.0) 73 | nanaimo (0.3.0) 74 | nap (1.1.0) 75 | netrc (0.11.0) 76 | nkf (0.2.0) 77 | public_suffix (4.0.7) 78 | rexml (3.2.9) 79 | strscan 80 | ruby-macho (2.5.1) 81 | strscan (3.1.0) 82 | typhoeus (1.4.1) 83 | ethon (>= 0.9.0) 84 | tzinfo (2.0.6) 85 | concurrent-ruby (~> 1.0) 86 | xcodeproj (1.24.0) 87 | CFPropertyList (>= 2.3.3, < 4.0) 88 | atomos (~> 0.1.3) 89 | claide (>= 1.0.2, < 2.0) 90 | colored2 (~> 3.1) 91 | nanaimo (~> 0.3.0) 92 | rexml (~> 3.2.4) 93 | 94 | PLATFORMS 95 | ruby 96 | 97 | DEPENDENCIES 98 | activesupport (>= 6.1.7.3, < 7.1.0) 99 | cocoapods (~> 1.13) 100 | 101 | RUBY VERSION 102 | ruby 2.7.6p219 103 | 104 | BUNDLED WITH 105 | 2.1.4 106 | -------------------------------------------------------------------------------- /example/__tests__/App.test.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: import explicitly to use the types shipped with jest. 10 | import { it } from '@jest/globals'; 11 | 12 | // Note: test renderer must be required after react-native. 13 | import renderer from 'react-test-renderer'; 14 | 15 | it('renders correctly', () => { 16 | renderer.create(); 17 | }); 18 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "com.facebook.react" 3 | 4 | /** 5 | * This is the configuration block to customize your React Native Android app. 6 | * By default you don't need to apply any configuration, just uncomment the lines you need. 7 | */ 8 | react { 9 | /* Folders */ 10 | // The root of your project, i.e. where "package.json" lives. Default is '..' 11 | // root = file("../") 12 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native 13 | // reactNativeDir = file("../node_modules/react-native") 14 | // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen 15 | // codegenDir = file("../node_modules/@react-native/codegen") 16 | // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js 17 | // cliFile = file("../node_modules/react-native/cli.js") 18 | 19 | /* Variants */ 20 | // The list of variants to that are debuggable. For those we're going to 21 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'. 22 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. 23 | // debuggableVariants = ["liteDebug", "prodDebug"] 24 | 25 | /* Bundling */ 26 | // A list containing the node command and its flags. Default is just 'node'. 27 | // nodeExecutableAndArgs = ["node"] 28 | // 29 | // The command to run when bundling. By default is 'bundle' 30 | // bundleCommand = "ram-bundle" 31 | // 32 | // The path to the CLI configuration file. Default is empty. 33 | // bundleConfig = file(../rn-cli.config.js) 34 | // 35 | // The name of the generated asset file containing your JS bundle 36 | // bundleAssetName = "MyApplication.android.bundle" 37 | // 38 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' 39 | // entryFile = file("../js/MyApplication.android.js") 40 | // 41 | // A list of extra flags to pass to the 'bundle' commands. 42 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle 43 | // extraPackagerArgs = [] 44 | 45 | /* Hermes Commands */ 46 | // The hermes compiler command to run. By default it is 'hermesc' 47 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" 48 | // 49 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" 50 | // hermesFlags = ["-O", "-output-source-map"] 51 | } 52 | 53 | /** 54 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. 55 | */ 56 | def enableProguardInReleaseBuilds = false 57 | 58 | /** 59 | * The preferred build flavor of JavaScriptCore (JSC) 60 | * 61 | * For example, to use the international variant, you can use: 62 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 63 | * 64 | * The international variant includes ICU i18n library and necessary data 65 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 66 | * give correct results when using with locales other than en-US. Note that 67 | * this variant is about 6MiB larger per architecture than default. 68 | */ 69 | def jscFlavor = 'org.webkit:android-jsc:+' 70 | 71 | android { 72 | ndkVersion rootProject.ext.ndkVersion 73 | 74 | compileSdkVersion rootProject.ext.compileSdkVersion 75 | 76 | namespace "com.dynamicshimmer" 77 | defaultConfig { 78 | applicationId "com.dynamicshimmer" 79 | minSdkVersion rootProject.ext.minSdkVersion 80 | targetSdkVersion rootProject.ext.targetSdkVersion 81 | versionCode 1 82 | versionName "1.0" 83 | } 84 | signingConfigs { 85 | debug { 86 | storeFile file('debug.keystore') 87 | storePassword 'android' 88 | keyAlias 'androiddebugkey' 89 | keyPassword 'android' 90 | } 91 | } 92 | buildTypes { 93 | debug { 94 | signingConfig signingConfigs.debug 95 | } 96 | release { 97 | // Caution! In production, you need to generate your own keystore file. 98 | // see https://reactnative.dev/docs/signed-apk-android. 99 | signingConfig signingConfigs.debug 100 | minifyEnabled enableProguardInReleaseBuilds 101 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 102 | } 103 | } 104 | } 105 | 106 | dependencies { 107 | // The version of react-native is set by the React Native Gradle Plugin 108 | implementation("com.facebook.react:react-android") 109 | 110 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") 111 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 112 | exclude group:'com.squareup.okhttp3', module:'okhttp' 113 | } 114 | 115 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") 116 | if (hermesEnabled.toBoolean()) { 117 | implementation("com.facebook.react:hermes-android") 118 | } else { 119 | implementation jscFlavor 120 | } 121 | } 122 | 123 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 124 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/android/app/src/debug/java/com/dynamicshimmer/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.dynamicshimmer; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 21 | import com.facebook.react.ReactInstanceEventListener; 22 | import com.facebook.react.ReactInstanceManager; 23 | import com.facebook.react.bridge.ReactContext; 24 | import com.facebook.react.modules.network.NetworkingModule; 25 | import okhttp3.OkHttpClient; 26 | 27 | /** 28 | * Class responsible of loading Flipper inside your React Native application. This is the debug 29 | * flavor of it. Here you can add your own plugins and customize the Flipper setup. 30 | */ 31 | public class ReactNativeFlipper { 32 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 33 | if (FlipperUtils.shouldEnableFlipper(context)) { 34 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 35 | 36 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 37 | client.addPlugin(new DatabasesFlipperPlugin(context)); 38 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 39 | client.addPlugin(CrashReporterPlugin.getInstance()); 40 | 41 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 42 | NetworkingModule.setCustomClientBuilder( 43 | new NetworkingModule.CustomClientBuilder() { 44 | @Override 45 | public void apply(OkHttpClient.Builder builder) { 46 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 47 | } 48 | }); 49 | client.addPlugin(networkFlipperPlugin); 50 | client.start(); 51 | 52 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 53 | // Hence we run if after all native modules have been initialized 54 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 55 | if (reactContext == null) { 56 | reactInstanceManager.addReactInstanceEventListener( 57 | new ReactInstanceEventListener() { 58 | @Override 59 | public void onReactContextInitialized(ReactContext reactContext) { 60 | reactInstanceManager.removeReactInstanceEventListener(this); 61 | reactContext.runOnNativeModulesQueueThread( 62 | new Runnable() { 63 | @Override 64 | public void run() { 65 | client.addPlugin(new FrescoFlipperPlugin()); 66 | } 67 | }); 68 | } 69 | }); 70 | } else { 71 | client.addPlugin(new FrescoFlipperPlugin()); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/dynamicshimmer/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.dynamicshimmer; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | @Override 15 | protected String getMainComponentName() { 16 | return "DynamicShimmer"; 17 | } 18 | 19 | /** 20 | * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link 21 | * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React 22 | * (aka React 18) with two boolean flags. 23 | */ 24 | @Override 25 | protected ReactActivityDelegate createReactActivityDelegate() { 26 | return new DefaultReactActivityDelegate( 27 | this, 28 | getMainComponentName(), 29 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 30 | DefaultNewArchitectureEntryPoint.getFabricEnabled()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/dynamicshimmer/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.dynamicshimmer; 2 | 3 | import android.app.Application; 4 | import com.facebook.react.PackageList; 5 | import com.facebook.react.ReactApplication; 6 | import com.facebook.react.ReactNativeHost; 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 9 | import com.facebook.react.defaults.DefaultReactNativeHost; 10 | import com.facebook.soloader.SoLoader; 11 | import java.util.List; 12 | 13 | public class MainApplication extends Application implements ReactApplication { 14 | 15 | private final ReactNativeHost mReactNativeHost = 16 | new DefaultReactNativeHost(this) { 17 | @Override 18 | public boolean getUseDeveloperSupport() { 19 | return BuildConfig.DEBUG; 20 | } 21 | 22 | @Override 23 | protected List getPackages() { 24 | @SuppressWarnings("UnnecessaryLocalVariable") 25 | List packages = new PackageList(this).getPackages(); 26 | // Packages that cannot be autolinked yet can be added manually here, for example: 27 | // packages.add(new MyReactNativePackage()); 28 | return packages; 29 | } 30 | 31 | @Override 32 | protected String getJSMainModuleName() { 33 | return "index"; 34 | } 35 | 36 | @Override 37 | protected boolean isNewArchEnabled() { 38 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 39 | } 40 | 41 | @Override 42 | protected Boolean isHermesEnabled() { 43 | return BuildConfig.IS_HERMES_ENABLED; 44 | } 45 | }; 46 | 47 | @Override 48 | public ReactNativeHost getReactNativeHost() { 49 | return mReactNativeHost; 50 | } 51 | 52 | @Override 53 | public void onCreate() { 54 | super.onCreate(); 55 | SoLoader.init(this, /* native exopackage */ false); 56 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 57 | // If you opted-in for the New Architecture, we load the native entry point for this app. 58 | DefaultNewArchitectureEntryPoint.load(); 59 | } 60 | ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | DynamicShimmer 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/android/app/src/release/java/com/dynamicshimmer/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.dynamicshimmer; 8 | 9 | import android.content.Context; 10 | import com.facebook.react.ReactInstanceManager; 11 | 12 | /** 13 | * Class responsible of loading Flipper inside your React Native application. This is the release 14 | * flavor of it so it's empty as we don't want to load Flipper. 15 | */ 16 | public class ReactNativeFlipper { 17 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 18 | // Do nothing as we don't want to initialize Flipper on Release. 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "33.0.0" 6 | minSdkVersion = 30 7 | compileSdkVersion = 33 8 | targetSdkVersion = 33 9 | 10 | // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. 11 | ndkVersion = "23.1.7779620" 12 | } 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | dependencies { 18 | classpath("com.android.tools.build:gradle") 19 | classpath("com.facebook.react:react-native-gradle-plugin") 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.182.0 29 | 30 | # Use this property to specify which architecture you want to build. 31 | # You can also override it from the CLI using 32 | # ./gradlew -PreactNativeArchitectures=x86_64 33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 34 | 35 | # Use this property to enable support to the new architecture. 36 | # This will allow you to use TurboModules and the Fabric render in 37 | # your application. You should enable this flag either if you want 38 | # to write custom TurboModules/Fabric components OR use libraries that 39 | # are providing them. 40 | newArchEnabled=false 41 | 42 | # Use this property to enable or disable the Hermes JS engine. 43 | # If set to false, you will be using JSC instead. 44 | hermesEnabled=true 45 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer/982d760705cca54c15256062cfb3d55180cc8b50/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 147 | # shellcheck disable=SC3045 148 | MAX_FD=$( ulimit -H -n ) || 149 | warn "Could not query maximum file descriptor limit" 150 | esac 151 | case $MAX_FD in #( 152 | '' | soft) :;; #( 153 | *) 154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 155 | # shellcheck disable=SC3045 156 | ulimit -n "$MAX_FD" || 157 | warn "Could not set maximum file descriptor limit to $MAX_FD" 158 | esac 159 | fi 160 | 161 | # Collect all arguments for the java command, stacking in reverse order: 162 | # * args from the command line 163 | # * the main class name 164 | # * -classpath 165 | # * -D...appname settings 166 | # * --module-path (only if needed) 167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 168 | 169 | # For Cygwin or MSYS, switch paths to Windows format before running java 170 | if "$cygwin" || "$msys" ; then 171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 173 | 174 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 175 | 176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 177 | for arg do 178 | if 179 | case $arg in #( 180 | -*) false ;; # don't mess with options #( 181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 182 | [ -e "$t" ] ;; #( 183 | *) false ;; 184 | esac 185 | then 186 | arg=$( cygpath --path --ignore --mixed "$arg" ) 187 | fi 188 | # Roll the args list around exactly as many times as the number of 189 | # args, so each arg winds up back in the position where it started, but 190 | # possibly modified. 191 | # 192 | # NB: a `for` loop captures its iteration list before it begins, so 193 | # changing the positional parameters here affects neither the number of 194 | # iterations, nor the values presented in `arg`. 195 | shift # remove old arg 196 | set -- "$@" "$arg" # push replacement arg 197 | done 198 | fi 199 | 200 | # Collect all arguments for the java command; 201 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 202 | # shell script including quotes and variable substitutions, so put them in 203 | # double quotes to make sure that they get re-expanded; and 204 | # * put everything else in single quotes, so that it's not re-expanded. 205 | 206 | set -- \ 207 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 208 | -classpath "$CLASSPATH" \ 209 | org.gradle.wrapper.GradleWrapperMain \ 210 | "$@" 211 | 212 | # Stop when "xargs" is not available. 213 | if ! command -v xargs >/dev/null 2>&1 214 | then 215 | die "xargs is not available" 216 | fi 217 | 218 | # Use "xargs" to parse quoted args. 219 | # 220 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 221 | # 222 | # In Bash we could simply go: 223 | # 224 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 225 | # set -- "${ARGS[@]}" "$@" 226 | # 227 | # but POSIX shell has neither arrays nor command substitution, so instead we 228 | # post-process each arg (as a line of input to sed) to backslash-escape any 229 | # character that might be a shell metacharacter, then use eval to reverse 230 | # that process (while maintaining the separation between arguments), and wrap 231 | # the whole thing up as a single "set" statement. 232 | # 233 | # This will of course break if any of these variables contains a newline or 234 | # an unmatched quote. 235 | # 236 | 237 | eval "set -- $( 238 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 239 | xargs -n1 | 240 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 241 | tr '\n' ' ' 242 | )" '"$@"' 243 | 244 | exec "$JAVACMD" "$@" 245 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'DynamicShimmer' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/@react-native/gradle-plugin') 5 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DynamicShimmer", 3 | "displayName": "DynamicShimmer" 4 | } 5 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import { name as appName } from './app.json'; 3 | import App from './src/App'; 4 | 5 | AppRegistry.registerComponent(appName, () => App); 6 | -------------------------------------------------------------------------------- /example/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer.xcodeproj/xcshareddata/xcschemes/DynamicShimmer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | @implementation AppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 8 | { 9 | self.moduleName = @"DynamicShimmer"; 10 | // You can add your custom initial props in the dictionary below. 11 | // They will be passed down to the ViewController used by React Native. 12 | self.initialProps = @{}; 13 | 14 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 15 | } 16 | 17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 18 | { 19 | #if DEBUG 20 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 21 | #else 22 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 23 | #endif 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | DynamicShimmer 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSLocationWhenInUseUsageDescription 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UIViewControllerBasedStatusBarAppearance 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmer/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmerTests/DynamicShimmerTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface DynamicShimmerTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation DynamicShimmerTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /example/ios/DynamicShimmerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Resolve react_native_pods.rb with node to allow for hoisting 2 | require Pod::Executable.execute_command('node', ['-p', 3 | 'require.resolve( 4 | "react-native/scripts/react_native_pods.rb", 5 | {paths: [process.argv[1]]}, 6 | )', __dir__]).strip 7 | 8 | platform :ios, min_ios_version_supported 9 | prepare_react_native_project! 10 | 11 | # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. 12 | # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded 13 | # 14 | # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` 15 | # ```js 16 | # module.exports = { 17 | # dependencies: { 18 | # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), 19 | # ``` 20 | flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled 21 | 22 | linkage = ENV['USE_FRAMEWORKS'] 23 | if linkage != nil 24 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 25 | use_frameworks! :linkage => linkage.to_sym 26 | end 27 | 28 | target 'DynamicShimmer' do 29 | config = use_native_modules! 30 | 31 | # Flags change depending on the env values. 32 | flags = get_default_flags() 33 | 34 | use_react_native!( 35 | :path => config[:reactNativePath], 36 | # Hermes is now enabled by default. Disable by setting this flag to false. 37 | :hermes_enabled => flags[:hermes_enabled], 38 | :fabric_enabled => flags[:fabric_enabled], 39 | # Enables Flipper. 40 | # 41 | # Note that if you have use_frameworks! enabled, Flipper will not work and 42 | # you should disable the next line. 43 | :flipper_configuration => flipper_config, 44 | # An absolute path to your application root. 45 | :app_path => "#{Pod::Config.instance.installation_root}/.." 46 | ) 47 | 48 | target 'DynamicShimmerTests' do 49 | inherit! :complete 50 | # Pods for testing 51 | end 52 | 53 | post_install do |installer| 54 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 55 | react_native_post_install( 56 | installer, 57 | config[:reactNativePath], 58 | :mac_catalyst_enabled => false 59 | ) 60 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /example/ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - boost (1.76.0) 3 | - BVLinearGradient (2.8.3): 4 | - React-Core 5 | - CocoaAsyncSocket (7.6.5) 6 | - DoubleConversion (1.1.6) 7 | - FBLazyVector (0.72.7) 8 | - FBReactNativeSpec (0.72.7): 9 | - RCT-Folly (= 2021.07.22.00) 10 | - RCTRequired (= 0.72.7) 11 | - RCTTypeSafety (= 0.72.7) 12 | - React-Core (= 0.72.7) 13 | - React-jsi (= 0.72.7) 14 | - ReactCommon/turbomodule/core (= 0.72.7) 15 | - Flipper (0.182.0): 16 | - Flipper-Folly (~> 2.6) 17 | - Flipper-Boost-iOSX (1.76.0.1.11) 18 | - Flipper-DoubleConversion (3.2.0.1) 19 | - Flipper-Fmt (7.1.7) 20 | - Flipper-Folly (2.6.10): 21 | - Flipper-Boost-iOSX 22 | - Flipper-DoubleConversion 23 | - Flipper-Fmt (= 7.1.7) 24 | - Flipper-Glog 25 | - libevent (~> 2.1.12) 26 | - OpenSSL-Universal (= 1.1.1100) 27 | - Flipper-Glog (0.5.0.5) 28 | - Flipper-PeerTalk (0.0.4) 29 | - FlipperKit (0.182.0): 30 | - FlipperKit/Core (= 0.182.0) 31 | - FlipperKit/Core (0.182.0): 32 | - Flipper (~> 0.182.0) 33 | - FlipperKit/CppBridge 34 | - FlipperKit/FBCxxFollyDynamicConvert 35 | - FlipperKit/FBDefines 36 | - FlipperKit/FKPortForwarding 37 | - SocketRocket (~> 0.6.0) 38 | - FlipperKit/CppBridge (0.182.0): 39 | - Flipper (~> 0.182.0) 40 | - FlipperKit/FBCxxFollyDynamicConvert (0.182.0): 41 | - Flipper-Folly (~> 2.6) 42 | - FlipperKit/FBDefines (0.182.0) 43 | - FlipperKit/FKPortForwarding (0.182.0): 44 | - CocoaAsyncSocket (~> 7.6) 45 | - Flipper-PeerTalk (~> 0.0.4) 46 | - FlipperKit/FlipperKitHighlightOverlay (0.182.0) 47 | - FlipperKit/FlipperKitLayoutHelpers (0.182.0): 48 | - FlipperKit/Core 49 | - FlipperKit/FlipperKitHighlightOverlay 50 | - FlipperKit/FlipperKitLayoutTextSearchable 51 | - FlipperKit/FlipperKitLayoutIOSDescriptors (0.182.0): 52 | - FlipperKit/Core 53 | - FlipperKit/FlipperKitHighlightOverlay 54 | - FlipperKit/FlipperKitLayoutHelpers 55 | - YogaKit (~> 1.18) 56 | - FlipperKit/FlipperKitLayoutPlugin (0.182.0): 57 | - FlipperKit/Core 58 | - FlipperKit/FlipperKitHighlightOverlay 59 | - FlipperKit/FlipperKitLayoutHelpers 60 | - FlipperKit/FlipperKitLayoutIOSDescriptors 61 | - FlipperKit/FlipperKitLayoutTextSearchable 62 | - YogaKit (~> 1.18) 63 | - FlipperKit/FlipperKitLayoutTextSearchable (0.182.0) 64 | - FlipperKit/FlipperKitNetworkPlugin (0.182.0): 65 | - FlipperKit/Core 66 | - FlipperKit/FlipperKitReactPlugin (0.182.0): 67 | - FlipperKit/Core 68 | - FlipperKit/FlipperKitUserDefaultsPlugin (0.182.0): 69 | - FlipperKit/Core 70 | - FlipperKit/SKIOSNetworkPlugin (0.182.0): 71 | - FlipperKit/Core 72 | - FlipperKit/FlipperKitNetworkPlugin 73 | - fmt (6.2.1) 74 | - glog (0.3.5) 75 | - hermes-engine (0.72.7): 76 | - hermes-engine/Pre-built (= 0.72.7) 77 | - hermes-engine/Pre-built (0.72.7) 78 | - libevent (2.1.12) 79 | - OpenSSL-Universal (1.1.1100) 80 | - RCT-Folly (2021.07.22.00): 81 | - boost 82 | - DoubleConversion 83 | - fmt (~> 6.2.1) 84 | - glog 85 | - RCT-Folly/Default (= 2021.07.22.00) 86 | - RCT-Folly/Default (2021.07.22.00): 87 | - boost 88 | - DoubleConversion 89 | - fmt (~> 6.2.1) 90 | - glog 91 | - RCT-Folly/Futures (2021.07.22.00): 92 | - boost 93 | - DoubleConversion 94 | - fmt (~> 6.2.1) 95 | - glog 96 | - libevent 97 | - RCTRequired (0.72.7) 98 | - RCTTypeSafety (0.72.7): 99 | - FBLazyVector (= 0.72.7) 100 | - RCTRequired (= 0.72.7) 101 | - React-Core (= 0.72.7) 102 | - React (0.72.7): 103 | - React-Core (= 0.72.7) 104 | - React-Core/DevSupport (= 0.72.7) 105 | - React-Core/RCTWebSocket (= 0.72.7) 106 | - React-RCTActionSheet (= 0.72.7) 107 | - React-RCTAnimation (= 0.72.7) 108 | - React-RCTBlob (= 0.72.7) 109 | - React-RCTImage (= 0.72.7) 110 | - React-RCTLinking (= 0.72.7) 111 | - React-RCTNetwork (= 0.72.7) 112 | - React-RCTSettings (= 0.72.7) 113 | - React-RCTText (= 0.72.7) 114 | - React-RCTVibration (= 0.72.7) 115 | - React-callinvoker (0.72.7) 116 | - React-Codegen (0.72.7): 117 | - DoubleConversion 118 | - FBReactNativeSpec 119 | - glog 120 | - hermes-engine 121 | - RCT-Folly 122 | - RCTRequired 123 | - RCTTypeSafety 124 | - React-Core 125 | - React-jsi 126 | - React-jsiexecutor 127 | - React-NativeModulesApple 128 | - React-rncore 129 | - ReactCommon/turbomodule/bridging 130 | - ReactCommon/turbomodule/core 131 | - React-Core (0.72.7): 132 | - glog 133 | - hermes-engine 134 | - RCT-Folly (= 2021.07.22.00) 135 | - React-Core/Default (= 0.72.7) 136 | - React-cxxreact 137 | - React-hermes 138 | - React-jsi 139 | - React-jsiexecutor 140 | - React-perflogger 141 | - React-runtimeexecutor 142 | - React-utils 143 | - SocketRocket (= 0.6.1) 144 | - Yoga 145 | - React-Core/CoreModulesHeaders (0.72.7): 146 | - glog 147 | - hermes-engine 148 | - RCT-Folly (= 2021.07.22.00) 149 | - React-Core/Default 150 | - React-cxxreact 151 | - React-hermes 152 | - React-jsi 153 | - React-jsiexecutor 154 | - React-perflogger 155 | - React-runtimeexecutor 156 | - React-utils 157 | - SocketRocket (= 0.6.1) 158 | - Yoga 159 | - React-Core/Default (0.72.7): 160 | - glog 161 | - hermes-engine 162 | - RCT-Folly (= 2021.07.22.00) 163 | - React-cxxreact 164 | - React-hermes 165 | - React-jsi 166 | - React-jsiexecutor 167 | - React-perflogger 168 | - React-runtimeexecutor 169 | - React-utils 170 | - SocketRocket (= 0.6.1) 171 | - Yoga 172 | - React-Core/DevSupport (0.72.7): 173 | - glog 174 | - hermes-engine 175 | - RCT-Folly (= 2021.07.22.00) 176 | - React-Core/Default (= 0.72.7) 177 | - React-Core/RCTWebSocket (= 0.72.7) 178 | - React-cxxreact 179 | - React-hermes 180 | - React-jsi 181 | - React-jsiexecutor 182 | - React-jsinspector (= 0.72.7) 183 | - React-perflogger 184 | - React-runtimeexecutor 185 | - React-utils 186 | - SocketRocket (= 0.6.1) 187 | - Yoga 188 | - React-Core/RCTActionSheetHeaders (0.72.7): 189 | - glog 190 | - hermes-engine 191 | - RCT-Folly (= 2021.07.22.00) 192 | - React-Core/Default 193 | - React-cxxreact 194 | - React-hermes 195 | - React-jsi 196 | - React-jsiexecutor 197 | - React-perflogger 198 | - React-runtimeexecutor 199 | - React-utils 200 | - SocketRocket (= 0.6.1) 201 | - Yoga 202 | - React-Core/RCTAnimationHeaders (0.72.7): 203 | - glog 204 | - hermes-engine 205 | - RCT-Folly (= 2021.07.22.00) 206 | - React-Core/Default 207 | - React-cxxreact 208 | - React-hermes 209 | - React-jsi 210 | - React-jsiexecutor 211 | - React-perflogger 212 | - React-runtimeexecutor 213 | - React-utils 214 | - SocketRocket (= 0.6.1) 215 | - Yoga 216 | - React-Core/RCTBlobHeaders (0.72.7): 217 | - glog 218 | - hermes-engine 219 | - RCT-Folly (= 2021.07.22.00) 220 | - React-Core/Default 221 | - React-cxxreact 222 | - React-hermes 223 | - React-jsi 224 | - React-jsiexecutor 225 | - React-perflogger 226 | - React-runtimeexecutor 227 | - React-utils 228 | - SocketRocket (= 0.6.1) 229 | - Yoga 230 | - React-Core/RCTImageHeaders (0.72.7): 231 | - glog 232 | - hermes-engine 233 | - RCT-Folly (= 2021.07.22.00) 234 | - React-Core/Default 235 | - React-cxxreact 236 | - React-hermes 237 | - React-jsi 238 | - React-jsiexecutor 239 | - React-perflogger 240 | - React-runtimeexecutor 241 | - React-utils 242 | - SocketRocket (= 0.6.1) 243 | - Yoga 244 | - React-Core/RCTLinkingHeaders (0.72.7): 245 | - glog 246 | - hermes-engine 247 | - RCT-Folly (= 2021.07.22.00) 248 | - React-Core/Default 249 | - React-cxxreact 250 | - React-hermes 251 | - React-jsi 252 | - React-jsiexecutor 253 | - React-perflogger 254 | - React-runtimeexecutor 255 | - React-utils 256 | - SocketRocket (= 0.6.1) 257 | - Yoga 258 | - React-Core/RCTNetworkHeaders (0.72.7): 259 | - glog 260 | - hermes-engine 261 | - RCT-Folly (= 2021.07.22.00) 262 | - React-Core/Default 263 | - React-cxxreact 264 | - React-hermes 265 | - React-jsi 266 | - React-jsiexecutor 267 | - React-perflogger 268 | - React-runtimeexecutor 269 | - React-utils 270 | - SocketRocket (= 0.6.1) 271 | - Yoga 272 | - React-Core/RCTSettingsHeaders (0.72.7): 273 | - glog 274 | - hermes-engine 275 | - RCT-Folly (= 2021.07.22.00) 276 | - React-Core/Default 277 | - React-cxxreact 278 | - React-hermes 279 | - React-jsi 280 | - React-jsiexecutor 281 | - React-perflogger 282 | - React-runtimeexecutor 283 | - React-utils 284 | - SocketRocket (= 0.6.1) 285 | - Yoga 286 | - React-Core/RCTTextHeaders (0.72.7): 287 | - glog 288 | - hermes-engine 289 | - RCT-Folly (= 2021.07.22.00) 290 | - React-Core/Default 291 | - React-cxxreact 292 | - React-hermes 293 | - React-jsi 294 | - React-jsiexecutor 295 | - React-perflogger 296 | - React-runtimeexecutor 297 | - React-utils 298 | - SocketRocket (= 0.6.1) 299 | - Yoga 300 | - React-Core/RCTVibrationHeaders (0.72.7): 301 | - glog 302 | - hermes-engine 303 | - RCT-Folly (= 2021.07.22.00) 304 | - React-Core/Default 305 | - React-cxxreact 306 | - React-hermes 307 | - React-jsi 308 | - React-jsiexecutor 309 | - React-perflogger 310 | - React-runtimeexecutor 311 | - React-utils 312 | - SocketRocket (= 0.6.1) 313 | - Yoga 314 | - React-Core/RCTWebSocket (0.72.7): 315 | - glog 316 | - hermes-engine 317 | - RCT-Folly (= 2021.07.22.00) 318 | - React-Core/Default (= 0.72.7) 319 | - React-cxxreact 320 | - React-hermes 321 | - React-jsi 322 | - React-jsiexecutor 323 | - React-perflogger 324 | - React-runtimeexecutor 325 | - React-utils 326 | - SocketRocket (= 0.6.1) 327 | - Yoga 328 | - React-CoreModules (0.72.7): 329 | - RCT-Folly (= 2021.07.22.00) 330 | - RCTTypeSafety (= 0.72.7) 331 | - React-Codegen (= 0.72.7) 332 | - React-Core/CoreModulesHeaders (= 0.72.7) 333 | - React-jsi (= 0.72.7) 334 | - React-RCTBlob 335 | - React-RCTImage (= 0.72.7) 336 | - ReactCommon/turbomodule/core (= 0.72.7) 337 | - SocketRocket (= 0.6.1) 338 | - React-cxxreact (0.72.7): 339 | - boost (= 1.76.0) 340 | - DoubleConversion 341 | - glog 342 | - hermes-engine 343 | - RCT-Folly (= 2021.07.22.00) 344 | - React-callinvoker (= 0.72.7) 345 | - React-debug (= 0.72.7) 346 | - React-jsi (= 0.72.7) 347 | - React-jsinspector (= 0.72.7) 348 | - React-logger (= 0.72.7) 349 | - React-perflogger (= 0.72.7) 350 | - React-runtimeexecutor (= 0.72.7) 351 | - React-debug (0.72.7) 352 | - React-hermes (0.72.7): 353 | - DoubleConversion 354 | - glog 355 | - hermes-engine 356 | - RCT-Folly (= 2021.07.22.00) 357 | - RCT-Folly/Futures (= 2021.07.22.00) 358 | - React-cxxreact (= 0.72.7) 359 | - React-jsi 360 | - React-jsiexecutor (= 0.72.7) 361 | - React-jsinspector (= 0.72.7) 362 | - React-perflogger (= 0.72.7) 363 | - React-jsi (0.72.7): 364 | - boost (= 1.76.0) 365 | - DoubleConversion 366 | - glog 367 | - hermes-engine 368 | - RCT-Folly (= 2021.07.22.00) 369 | - React-jsiexecutor (0.72.7): 370 | - DoubleConversion 371 | - glog 372 | - hermes-engine 373 | - RCT-Folly (= 2021.07.22.00) 374 | - React-cxxreact (= 0.72.7) 375 | - React-jsi (= 0.72.7) 376 | - React-perflogger (= 0.72.7) 377 | - React-jsinspector (0.72.7) 378 | - React-logger (0.72.7): 379 | - glog 380 | - react-native-safe-area-context (4.14.0): 381 | - React-Core 382 | - React-NativeModulesApple (0.72.7): 383 | - hermes-engine 384 | - React-callinvoker 385 | - React-Core 386 | - React-cxxreact 387 | - React-jsi 388 | - React-runtimeexecutor 389 | - ReactCommon/turbomodule/bridging 390 | - ReactCommon/turbomodule/core 391 | - React-perflogger (0.72.7) 392 | - React-RCTActionSheet (0.72.7): 393 | - React-Core/RCTActionSheetHeaders (= 0.72.7) 394 | - React-RCTAnimation (0.72.7): 395 | - RCT-Folly (= 2021.07.22.00) 396 | - RCTTypeSafety (= 0.72.7) 397 | - React-Codegen (= 0.72.7) 398 | - React-Core/RCTAnimationHeaders (= 0.72.7) 399 | - React-jsi (= 0.72.7) 400 | - ReactCommon/turbomodule/core (= 0.72.7) 401 | - React-RCTAppDelegate (0.72.7): 402 | - RCT-Folly 403 | - RCTRequired 404 | - RCTTypeSafety 405 | - React-Core 406 | - React-CoreModules 407 | - React-hermes 408 | - React-NativeModulesApple 409 | - React-RCTImage 410 | - React-RCTNetwork 411 | - React-runtimescheduler 412 | - ReactCommon/turbomodule/core 413 | - React-RCTBlob (0.72.7): 414 | - hermes-engine 415 | - RCT-Folly (= 2021.07.22.00) 416 | - React-Codegen (= 0.72.7) 417 | - React-Core/RCTBlobHeaders (= 0.72.7) 418 | - React-Core/RCTWebSocket (= 0.72.7) 419 | - React-jsi (= 0.72.7) 420 | - React-RCTNetwork (= 0.72.7) 421 | - ReactCommon/turbomodule/core (= 0.72.7) 422 | - React-RCTImage (0.72.7): 423 | - RCT-Folly (= 2021.07.22.00) 424 | - RCTTypeSafety (= 0.72.7) 425 | - React-Codegen (= 0.72.7) 426 | - React-Core/RCTImageHeaders (= 0.72.7) 427 | - React-jsi (= 0.72.7) 428 | - React-RCTNetwork (= 0.72.7) 429 | - ReactCommon/turbomodule/core (= 0.72.7) 430 | - React-RCTLinking (0.72.7): 431 | - React-Codegen (= 0.72.7) 432 | - React-Core/RCTLinkingHeaders (= 0.72.7) 433 | - React-jsi (= 0.72.7) 434 | - ReactCommon/turbomodule/core (= 0.72.7) 435 | - React-RCTNetwork (0.72.7): 436 | - RCT-Folly (= 2021.07.22.00) 437 | - RCTTypeSafety (= 0.72.7) 438 | - React-Codegen (= 0.72.7) 439 | - React-Core/RCTNetworkHeaders (= 0.72.7) 440 | - React-jsi (= 0.72.7) 441 | - ReactCommon/turbomodule/core (= 0.72.7) 442 | - React-RCTSettings (0.72.7): 443 | - RCT-Folly (= 2021.07.22.00) 444 | - RCTTypeSafety (= 0.72.7) 445 | - React-Codegen (= 0.72.7) 446 | - React-Core/RCTSettingsHeaders (= 0.72.7) 447 | - React-jsi (= 0.72.7) 448 | - ReactCommon/turbomodule/core (= 0.72.7) 449 | - React-RCTText (0.72.7): 450 | - React-Core/RCTTextHeaders (= 0.72.7) 451 | - React-RCTVibration (0.72.7): 452 | - RCT-Folly (= 2021.07.22.00) 453 | - React-Codegen (= 0.72.7) 454 | - React-Core/RCTVibrationHeaders (= 0.72.7) 455 | - React-jsi (= 0.72.7) 456 | - ReactCommon/turbomodule/core (= 0.72.7) 457 | - React-rncore (0.72.7) 458 | - React-runtimeexecutor (0.72.7): 459 | - React-jsi (= 0.72.7) 460 | - React-runtimescheduler (0.72.7): 461 | - glog 462 | - hermes-engine 463 | - RCT-Folly (= 2021.07.22.00) 464 | - React-callinvoker 465 | - React-debug 466 | - React-jsi 467 | - React-runtimeexecutor 468 | - React-utils (0.72.7): 469 | - glog 470 | - RCT-Folly (= 2021.07.22.00) 471 | - React-debug 472 | - ReactCommon/turbomodule/bridging (0.72.7): 473 | - DoubleConversion 474 | - glog 475 | - hermes-engine 476 | - RCT-Folly (= 2021.07.22.00) 477 | - React-callinvoker (= 0.72.7) 478 | - React-cxxreact (= 0.72.7) 479 | - React-jsi (= 0.72.7) 480 | - React-logger (= 0.72.7) 481 | - React-perflogger (= 0.72.7) 482 | - ReactCommon/turbomodule/core (0.72.7): 483 | - DoubleConversion 484 | - glog 485 | - hermes-engine 486 | - RCT-Folly (= 2021.07.22.00) 487 | - React-callinvoker (= 0.72.7) 488 | - React-cxxreact (= 0.72.7) 489 | - React-jsi (= 0.72.7) 490 | - React-logger (= 0.72.7) 491 | - React-perflogger (= 0.72.7) 492 | - RNScreens (3.34.0): 493 | - RCT-Folly (= 2021.07.22.00) 494 | - React-Core 495 | - React-RCTImage 496 | - SocketRocket (0.6.1) 497 | - Yoga (1.14.0) 498 | - YogaKit (1.18.1): 499 | - Yoga (~> 1.14) 500 | 501 | DEPENDENCIES: 502 | - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) 503 | - BVLinearGradient (from `../node_modules/react-native-linear-gradient`) 504 | - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) 505 | - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) 506 | - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) 507 | - Flipper (= 0.182.0) 508 | - Flipper-Boost-iOSX (= 1.76.0.1.11) 509 | - Flipper-DoubleConversion (= 3.2.0.1) 510 | - Flipper-Fmt (= 7.1.7) 511 | - Flipper-Folly (= 2.6.10) 512 | - Flipper-Glog (= 0.5.0.5) 513 | - Flipper-PeerTalk (= 0.0.4) 514 | - FlipperKit (= 0.182.0) 515 | - FlipperKit/Core (= 0.182.0) 516 | - FlipperKit/CppBridge (= 0.182.0) 517 | - FlipperKit/FBCxxFollyDynamicConvert (= 0.182.0) 518 | - FlipperKit/FBDefines (= 0.182.0) 519 | - FlipperKit/FKPortForwarding (= 0.182.0) 520 | - FlipperKit/FlipperKitHighlightOverlay (= 0.182.0) 521 | - FlipperKit/FlipperKitLayoutPlugin (= 0.182.0) 522 | - FlipperKit/FlipperKitLayoutTextSearchable (= 0.182.0) 523 | - FlipperKit/FlipperKitNetworkPlugin (= 0.182.0) 524 | - FlipperKit/FlipperKitReactPlugin (= 0.182.0) 525 | - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.182.0) 526 | - FlipperKit/SKIOSNetworkPlugin (= 0.182.0) 527 | - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) 528 | - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) 529 | - libevent (~> 2.1.12) 530 | - OpenSSL-Universal (= 1.1.1100) 531 | - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) 532 | - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) 533 | - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) 534 | - React (from `../node_modules/react-native/`) 535 | - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) 536 | - React-Codegen (from `build/generated/ios`) 537 | - React-Core (from `../node_modules/react-native/`) 538 | - React-Core/DevSupport (from `../node_modules/react-native/`) 539 | - React-Core/RCTWebSocket (from `../node_modules/react-native/`) 540 | - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) 541 | - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) 542 | - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) 543 | - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) 544 | - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) 545 | - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) 546 | - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) 547 | - React-logger (from `../node_modules/react-native/ReactCommon/logger`) 548 | - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) 549 | - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) 550 | - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) 551 | - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) 552 | - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) 553 | - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) 554 | - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) 555 | - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) 556 | - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) 557 | - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) 558 | - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) 559 | - React-RCTText (from `../node_modules/react-native/Libraries/Text`) 560 | - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) 561 | - React-rncore (from `../node_modules/react-native/ReactCommon`) 562 | - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) 563 | - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) 564 | - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) 565 | - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) 566 | - RNScreens (from `../node_modules/react-native-screens`) 567 | - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) 568 | 569 | SPEC REPOS: 570 | trunk: 571 | - CocoaAsyncSocket 572 | - Flipper 573 | - Flipper-Boost-iOSX 574 | - Flipper-DoubleConversion 575 | - Flipper-Fmt 576 | - Flipper-Folly 577 | - Flipper-Glog 578 | - Flipper-PeerTalk 579 | - FlipperKit 580 | - fmt 581 | - libevent 582 | - OpenSSL-Universal 583 | - SocketRocket 584 | - YogaKit 585 | 586 | EXTERNAL SOURCES: 587 | boost: 588 | :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" 589 | BVLinearGradient: 590 | :path: "../node_modules/react-native-linear-gradient" 591 | DoubleConversion: 592 | :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" 593 | FBLazyVector: 594 | :path: "../node_modules/react-native/Libraries/FBLazyVector" 595 | FBReactNativeSpec: 596 | :path: "../node_modules/react-native/React/FBReactNativeSpec" 597 | glog: 598 | :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" 599 | hermes-engine: 600 | :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" 601 | :tag: hermes-2023-08-07-RNv0.72.4-813b2def12bc9df02654b3e3653ae4a68d0572e0 602 | RCT-Folly: 603 | :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" 604 | RCTRequired: 605 | :path: "../node_modules/react-native/Libraries/RCTRequired" 606 | RCTTypeSafety: 607 | :path: "../node_modules/react-native/Libraries/TypeSafety" 608 | React: 609 | :path: "../node_modules/react-native/" 610 | React-callinvoker: 611 | :path: "../node_modules/react-native/ReactCommon/callinvoker" 612 | React-Codegen: 613 | :path: build/generated/ios 614 | React-Core: 615 | :path: "../node_modules/react-native/" 616 | React-CoreModules: 617 | :path: "../node_modules/react-native/React/CoreModules" 618 | React-cxxreact: 619 | :path: "../node_modules/react-native/ReactCommon/cxxreact" 620 | React-debug: 621 | :path: "../node_modules/react-native/ReactCommon/react/debug" 622 | React-hermes: 623 | :path: "../node_modules/react-native/ReactCommon/hermes" 624 | React-jsi: 625 | :path: "../node_modules/react-native/ReactCommon/jsi" 626 | React-jsiexecutor: 627 | :path: "../node_modules/react-native/ReactCommon/jsiexecutor" 628 | React-jsinspector: 629 | :path: "../node_modules/react-native/ReactCommon/jsinspector" 630 | React-logger: 631 | :path: "../node_modules/react-native/ReactCommon/logger" 632 | react-native-safe-area-context: 633 | :path: "../node_modules/react-native-safe-area-context" 634 | React-NativeModulesApple: 635 | :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" 636 | React-perflogger: 637 | :path: "../node_modules/react-native/ReactCommon/reactperflogger" 638 | React-RCTActionSheet: 639 | :path: "../node_modules/react-native/Libraries/ActionSheetIOS" 640 | React-RCTAnimation: 641 | :path: "../node_modules/react-native/Libraries/NativeAnimation" 642 | React-RCTAppDelegate: 643 | :path: "../node_modules/react-native/Libraries/AppDelegate" 644 | React-RCTBlob: 645 | :path: "../node_modules/react-native/Libraries/Blob" 646 | React-RCTImage: 647 | :path: "../node_modules/react-native/Libraries/Image" 648 | React-RCTLinking: 649 | :path: "../node_modules/react-native/Libraries/LinkingIOS" 650 | React-RCTNetwork: 651 | :path: "../node_modules/react-native/Libraries/Network" 652 | React-RCTSettings: 653 | :path: "../node_modules/react-native/Libraries/Settings" 654 | React-RCTText: 655 | :path: "../node_modules/react-native/Libraries/Text" 656 | React-RCTVibration: 657 | :path: "../node_modules/react-native/Libraries/Vibration" 658 | React-rncore: 659 | :path: "../node_modules/react-native/ReactCommon" 660 | React-runtimeexecutor: 661 | :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" 662 | React-runtimescheduler: 663 | :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" 664 | React-utils: 665 | :path: "../node_modules/react-native/ReactCommon/react/utils" 666 | ReactCommon: 667 | :path: "../node_modules/react-native/ReactCommon" 668 | RNScreens: 669 | :path: "../node_modules/react-native-screens" 670 | Yoga: 671 | :path: "../node_modules/react-native/ReactCommon/yoga" 672 | 673 | SPEC CHECKSUMS: 674 | boost: 57d2868c099736d80fcd648bf211b4431e51a558 675 | BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3 676 | CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 677 | DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 678 | FBLazyVector: 5fbbff1d7734827299274638deb8ba3024f6c597 679 | FBReactNativeSpec: 638095fe8a01506634d77b260ef8a322019ac671 680 | Flipper: 6edb735e6c3e332975d1b17956bcc584eccf5818 681 | Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c 682 | Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 683 | Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b 684 | Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 685 | Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 686 | Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 687 | FlipperKit: 2efad7007d6745a3f95e4034d547be637f89d3f6 688 | fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 689 | glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b 690 | hermes-engine: 9180d43df05c1ed658a87cc733dc3044cf90c00a 691 | libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 692 | OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c 693 | RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 694 | RCTRequired: 83bca1c184feb4d2e51c72c8369b83d641443f95 695 | RCTTypeSafety: 13c4a87a16d7db6cd66006ce9759f073402ef85b 696 | React: e67aa9f99957c7611c392b5e49355d877d6525e2 697 | React-callinvoker: 2790c09d964c2e5404b5410cde91b152e3746b7b 698 | React-Codegen: e6e05e105ca7cdb990f4d609985a2a689d8d0653 699 | React-Core: 9283f1e7d0d5e3d33ad298547547b1b43912534c 700 | React-CoreModules: 6312c9b2fec4329d9ae6a2b8c350032d1664c51b 701 | React-cxxreact: 7da72565656c8ac7f97c9a031d0b199bbdec0640 702 | React-debug: 4accb2b9dc09b575206d2c42f4082990a52ae436 703 | React-hermes: 1299a94f255f59a72d5baa54a2ca2e1eee104947 704 | React-jsi: 2208de64c3a41714ac04e86975386fc49116ea13 705 | React-jsiexecutor: c49502e5d02112247ee4526bc3ccfc891ae3eb9b 706 | React-jsinspector: 8baadae51f01d867c3921213a25ab78ab4fbcd91 707 | React-logger: 8edc785c47c8686c7962199a307015e2ce9a0e4f 708 | react-native-safe-area-context: 4532f1a0c5d34a46b9324ccaaedcb5582a302b7d 709 | React-NativeModulesApple: b6868ee904013a7923128892ee4a032498a1024a 710 | React-perflogger: 31ea61077185eb1428baf60c0db6e2886f141a5a 711 | React-RCTActionSheet: 392090a3abc8992eb269ef0eaa561750588fc39d 712 | React-RCTAnimation: 4b3cc6a29474bc0d78c4f04b52ab59bf760e8a9b 713 | React-RCTAppDelegate: 89b015b29885109addcabecdf3b2e833905437c7 714 | React-RCTBlob: 3e23dcbe6638897b5605e46d0d62955d78e8d27b 715 | React-RCTImage: 8a5d339d614a90a183fc1b8b6a7eb44e2e703943 716 | React-RCTLinking: b37dfbf646d77c326f9eae094b1fcd575b1c24c7 717 | React-RCTNetwork: 8bed9b2461c7d8a7d14e63df9b16181c448beebc 718 | React-RCTSettings: 506a5f09a455123a8873801b70aa7b4010b76b01 719 | React-RCTText: 3c71ecaad8ee010b79632ea2590f86c02f5cce17 720 | React-RCTVibration: d1b78ca38f61ea4b3e9ebb2ddbd0b5662631d99b 721 | React-rncore: bfc2f6568b6fecbae6f2f774e95c60c3c9e95bf2 722 | React-runtimeexecutor: 47b0a2d5bbb416db65ef881a6f7bdcfefa0001ab 723 | React-runtimescheduler: 7649c3b46c8dee1853691ecf60146a16ae59253c 724 | React-utils: 56838edeaaf651220d1e53cd0b8934fb8ce68415 725 | ReactCommon: 5f704096ccf7733b390f59043b6fa9cc180ee4f6 726 | RNScreens: 80369e822c4f123c3f076c9ea4141991c17770f9 727 | SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 728 | Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5 729 | YogaKit: f782866e155069a2cca2517aafea43200b01fd5a 730 | 731 | PODFILE CHECKSUM: e3b5aab162ecc026c6c64754f007930f156544fc 732 | 733 | COCOAPODS: 1.14.3 734 | -------------------------------------------------------------------------------- /example/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | const path = require('path'); 8 | const rootPackage = require('../package.json'); 9 | const blacklist = require('metro-config/src/defaults/exclusionList'); 10 | const rootModules = Object.keys({ 11 | ...rootPackage.peerDependencies, 12 | }); 13 | const moduleRoot = path.resolve(__dirname, '..'); 14 | /** 15 | * Only load one version for peerDependencies and alias them to the versions in example's node_modules" 16 | */ 17 | module.exports = { 18 | watchFolders: [moduleRoot], 19 | resolver: { 20 | blacklistRE: blacklist([ 21 | ...rootModules.map( 22 | m => 23 | new RegExp( 24 | `^${escape(path.join(moduleRoot, 'node_modules', m))}\\/.*$` 25 | ) 26 | ), 27 | /^((?!example).)+[\\/\\]node_modules[\\/\\]react[\\/\\].*/, 28 | /^((?!example).)+[\\/\\]node_modules[\\/\\]react-native[\\/\\].*/, 29 | ]), 30 | extraNodeModules: { 31 | ...rootModules.reduce((acc, name) => { 32 | acc[name] = path.join(__dirname, 'node_modules', name); 33 | return acc; 34 | }, {}), 35 | }, 36 | }, 37 | transformer: { 38 | getTransformOptions: async () => ({ 39 | transform: { 40 | experimentalImportSupport: false, 41 | inlineRequires: true, 42 | }, 43 | }), 44 | }, 45 | }; 46 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DynamicShimmer", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "lint": "eslint .", 9 | "start": "react-native start", 10 | "test": "jest" 11 | }, 12 | "dependencies": { 13 | "@react-navigation/native": "^6.1.17", 14 | "@react-navigation/native-stack": "^6.10.0", 15 | "lodash": "^4.17.21", 16 | "react": "18.2.0", 17 | "react-native": "0.72.7", 18 | "react-native-linear-gradient": "^2.8.3", 19 | "react-native-safe-area-context": "^4.10.8", 20 | "react-native-screens": "^3.32.0" 21 | }, 22 | "devDependencies": { 23 | "@babel/core": "^7.20.0", 24 | "@babel/preset-env": "^7.20.0", 25 | "@babel/runtime": "^7.20.0", 26 | "@react-native/eslint-config": "^0.72.2", 27 | "@react-native/metro-config": "^0.72.11", 28 | "@tsconfig/react-native": "^3.0.0", 29 | "@types/lodash": "^4.17.7", 30 | "@types/react": "^18.0.24", 31 | "@types/react-test-renderer": "^18.0.0", 32 | "babel-jest": "^29.2.1", 33 | "eslint": "^8.19.0", 34 | "jest": "^29.2.1", 35 | "metro-react-native-babel-preset": "0.76.8", 36 | "prettier": "^2.4.1", 37 | "react-test-renderer": "18.2.0", 38 | "typescript": "4.8.4" 39 | }, 40 | "engines": { 41 | "node": ">=16" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SafeAreaView } from 'react-native'; 3 | import Routes from './navigation/Routes'; 4 | import { applicationStyle } from './theme'; 5 | 6 | /** 7 | * App Component 8 | * 9 | * The main application component that serves as the entry point of the React Native app. 10 | * It wraps the application's routes in a `SafeAreaView` to ensure that content is rendered 11 | * within the safe area boundaries of the device. 12 | * 13 | * @returns {React.JSX.Element} A JSX element representing the main application layout. 14 | */ 15 | const App = () => { 16 | return ( 17 | 18 | 19 | 20 | ); 21 | }; 22 | 23 | export default App; 24 | -------------------------------------------------------------------------------- /example/src/components/List/List.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FlatList, Image, Text, View } from 'react-native'; 3 | import { Shimmer } from 'react-native-dynamic-shimmer'; 4 | import { sampleDataForList } from '../../constants'; 5 | import { useLoading } from '../../hooks'; 6 | import { ShimmerElement } from '../ShimmerElement'; 7 | import styles from './ListStyles'; 8 | import type { ListItem } from './ListTypes'; 9 | 10 | /** 11 | * List 12 | * 13 | * It renders a list of items with a shimmer loading effect in a React Native 14 | * app. 15 | * @returns A functional component named List is being returned. This component renders a 16 | * FlatList with items from sampleDataForList. Each item in the list is rendered using the renderItem 17 | * function which displays an image, name, and job title. The component also includes a Shimmer 18 | * component that shows a loading indicator based on the isLoading state. 19 | */ 20 | const List = (): React.JSX.Element => { 21 | const isLoading = useLoading(); 22 | 23 | const renderItem = ({ item }: { item: ListItem }) => { 24 | return ( 25 | 26 | 27 | 28 | 29 | 30 | {item?.name} 31 | {item?.jobTitle} 32 | 33 | 34 | ); 35 | }; 36 | 37 | return ( 38 | } 41 | duration={2450}> 42 | item?.id} 46 | /> 47 | 48 | ); 49 | }; 50 | 51 | export default List; 52 | -------------------------------------------------------------------------------- /example/src/components/List/ListStyles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { Colors } from '../../../../src/theme'; 3 | 4 | const styles = StyleSheet.create({ 5 | container: { 6 | backgroundColor: Colors.white, 7 | flexDirection: 'row', 8 | padding: 10, 9 | borderBottomColor: Colors.gray, 10 | borderBottomWidth: 1, 11 | alignItems: 'center', 12 | }, 13 | subContainer: { 14 | height: 50, 15 | width: 50, 16 | borderRadius: 30, 17 | justifyContent: 'center', 18 | alignItems: 'center', 19 | }, 20 | text: { 21 | fontSize: 17, 22 | fontWeight: '600', 23 | }, 24 | imageStyle: { 25 | height: 50, 26 | width: 50, 27 | borderRadius: 50, 28 | }, 29 | secondContainer: { padding: 10 }, 30 | }); 31 | 32 | export default styles; 33 | -------------------------------------------------------------------------------- /example/src/components/List/ListTypes.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a list item. 3 | * 4 | * @property {string} id - The unique identifier for the item. 5 | * @property {string} imageUri - The URI of the item's image. 6 | * @property {string} name - The name associated with the item. 7 | * @property {string} jobTitle - The job title associated with the item. 8 | */ 9 | export interface ListItem { 10 | id: string; 11 | imageUri: string; 12 | name: string; 13 | jobTitle: string; 14 | } 15 | -------------------------------------------------------------------------------- /example/src/components/List/index.ts: -------------------------------------------------------------------------------- 1 | export { default as List } from './List'; 2 | -------------------------------------------------------------------------------- /example/src/components/Profile/Profile.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Image, Text, View } from 'react-native'; 3 | import { Shimmer } from 'react-native-dynamic-shimmer'; 4 | import { AppConst, Strings } from '../../constants'; 5 | import { useLoading } from '../../hooks'; 6 | import { ShimmerElement } from '../ShimmerElement'; 7 | import styles from './ProfileStyles'; 8 | 9 | /** 10 | * ProfileCard 11 | * 12 | * This component displays the user's profile image, name, job title, and a short bio. 13 | * It uses the `Strings` and `AppConst` constants to dynamically load the user's information. 14 | * 15 | * @returns {React.JSX.Element} A profile card containing the user's image, name, job title, and bio. 16 | */ 17 | const ProfileCard = (): React.JSX.Element => { 18 | return ( 19 | 20 | 26 | 27 | {/* The shimmer width for this Text element is calculated based on the aria-label string length, offering more precise control over shimmer width. */} 28 | 29 | {Strings.michaelWilliams} 30 | 31 | {Strings.softwareEngineer} 32 | {Strings.loremString} 33 | 34 | 35 | ); 36 | }; 37 | 38 | /** 39 | * Profile 40 | * 41 | * It integrates the ProfileCard with a loading shimmer effect. 42 | * It uses the `useLoading` hook to determine if the content should display the shimmer or the profile. 43 | * 44 | * @returns {React.JSX.Element} A component that conditionally renders the ProfileCard wrapped in a Shimmer 45 | * loading animation based on the loading state. 46 | */ 47 | const Profile = (): React.JSX.Element => { 48 | const isLoading = useLoading(); 49 | 50 | return ( 51 | } 54 | duration={2450}> 55 | 56 | 57 | ); 58 | }; 59 | 60 | export default Profile; 61 | -------------------------------------------------------------------------------- /example/src/components/Profile/ProfileStyles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { Colors } from '../../../../src/theme'; 3 | 4 | const styles = StyleSheet.create({ 5 | container: { 6 | flexDirection: 'row', 7 | alignItems: 'center', 8 | padding: 20, 9 | borderBottomWidth: 1, 10 | borderBottomColor: Colors.gray, 11 | }, 12 | image: { 13 | width: 100, 14 | height: 100, 15 | borderRadius: 50, 16 | marginRight: 20, 17 | }, 18 | textContainer: { 19 | flex: 1, 20 | }, 21 | name: { 22 | fontSize: 24, 23 | fontWeight: 'bold', 24 | marginBottom: 5, 25 | }, 26 | jobTitle: { 27 | fontSize: 18, 28 | marginBottom: 10, 29 | color: Colors.gray, 30 | }, 31 | bio: { 32 | fontSize: 16, 33 | lineHeight: 22, 34 | }, 35 | }); 36 | 37 | export default styles; 38 | -------------------------------------------------------------------------------- /example/src/components/Profile/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Profile } from './Profile'; 2 | -------------------------------------------------------------------------------- /example/src/components/ScrollViewExample/ScrollViewExample.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Image, ScrollView, Text, View } from 'react-native'; 3 | import { Shimmer } from 'react-native-dynamic-shimmer'; 4 | import { Strings, contentForScrollView } from '../../constants'; 5 | import { useLoading } from '../../hooks'; 6 | import { ShimmerElement } from '../ShimmerElement'; 7 | import styles from './ScrollViewExampleStyles'; 8 | 9 | /** 10 | * ScrollViewSample 11 | * 12 | * This component renders a scrollable view containing a heading and a list of items. 13 | * Each item consists of an image and a description. he data for these items comes 14 | * from the static `contentForScrollView` which contains the image URL and description for each item. 15 | * @returns {React.JSX.Element} A JSX element representing a ScrollView with content. 16 | */ 17 | const ScrollViewSample = (): React.JSX.Element => { 18 | return ( 19 | 20 | {Strings.welcomeText} 21 | {contentForScrollView.map((item, index) => ( 22 | 23 | 24 | {item?.description} 25 | 26 | ))} 27 | 28 | ); 29 | }; 30 | 31 | /** 32 | * ScrollViewExample 33 | * 34 | * This component checks if the data is loading, and based on the loading state, 35 | * either renders the `ScrollViewSample` component wrapped inside a Shimmer effect, 36 | * or the loaded content itself. The `useLoading` hook manages the loading state. 37 | * 38 | * @returns {React.JSX.Element} A JSX element that conditionally renders the content with a shimmer effect. 39 | */ 40 | const ScrollViewExample = (): React.JSX.Element => { 41 | const isLoading = useLoading(); 42 | 43 | return ( 44 | 45 | } 48 | duration={2450}> 49 | 50 | 51 | 52 | ); 53 | }; 54 | 55 | export default ScrollViewExample; 56 | -------------------------------------------------------------------------------- /example/src/components/ScrollViewExample/ScrollViewExampleStyles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | const styles = StyleSheet.create({ 4 | mainContainer: { 5 | padding: 20, 6 | }, 7 | container: { 8 | alignItems: 'center', 9 | }, 10 | heading: { 11 | fontSize: 24, 12 | fontWeight: 'bold', 13 | marginBottom: 20, 14 | textAlign: 'center', 15 | }, 16 | paragraph: { 17 | fontSize: 16, 18 | lineHeight: 24, 19 | marginBottom: 20, 20 | textAlign: 'justify', 21 | }, 22 | image: { 23 | width: 300, 24 | height: 200, 25 | marginBottom: 20, 26 | borderRadius: 8, 27 | }, 28 | }); 29 | 30 | export default styles; 31 | -------------------------------------------------------------------------------- /example/src/components/ScrollViewExample/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ScrollViewExample } from './ScrollViewExample'; 2 | -------------------------------------------------------------------------------- /example/src/components/ShimmerElement/ShimmerElement.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import LinearGradient from 'react-native-linear-gradient'; 4 | import { Colors } from '../../theme'; 5 | 6 | /** 7 | * Renders a horizontal gradient with gray-to-white-to-gray colors. 8 | * 9 | * @returns {JSX.Element} Gradient background covering the parent. 10 | */ 11 | const ShimmerElement = () => { 12 | return ( 13 | 20 | ); 21 | }; 22 | 23 | export default ShimmerElement; 24 | -------------------------------------------------------------------------------- /example/src/components/ShimmerElement/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ShimmerElement } from './ShimmerElement'; 2 | -------------------------------------------------------------------------------- /example/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './List'; 2 | export * from './Profile'; 3 | export * from './ScrollViewExample'; 4 | -------------------------------------------------------------------------------- /example/src/constants/AppConst.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A constant freezing object that contains the app value. 3 | * @type {Object} 4 | */ 5 | 6 | export default Object.freeze({ 7 | profileImageUrl: 'https://randomuser.me/api/portraits/men/1.jpg', 8 | }); 9 | -------------------------------------------------------------------------------- /example/src/constants/NavigationStrings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Navigation Screen Names 3 | * 4 | * This module exports an object containing constants that represent the names of various 5 | * screens in the application. These constants are used throughout the app to navigate 6 | * between different screens. 7 | * 8 | */ 9 | export default { 10 | HOME: 'Home', 11 | LIST: 'List', 12 | PROFILE: 'Profile', 13 | SCROLL_VIEW_EXAMPLE: 'ScrollViewExample', 14 | }; 15 | -------------------------------------------------------------------------------- /example/src/constants/StaticData.ts: -------------------------------------------------------------------------------- 1 | import Strings from './Strings'; 2 | 3 | /** 4 | * sampleDataForList 5 | * 6 | * This is a static array that holds a list of user data, including each user's id, image URI, 7 | * name, and job title. This data can be used to populate components like lists or user profiles 8 | * within the application. 9 | * 10 | * @type {Array} 11 | * @property {string} id - A unique identifier for each user. 12 | * @property {string} imageUri - The URI link to the user's profile picture. 13 | * @property {string} name - The user's name. 14 | * @property {string} jobTitle - The user's job title. 15 | */ 16 | const sampleDataForList = [ 17 | { 18 | id: '1', 19 | imageUri: 'https://randomuser.me/api/portraits/men/1.jpg', 20 | name: 'Olivia Martinez', 21 | jobTitle: 'Marketing Manager', 22 | }, 23 | { 24 | id: '2', 25 | imageUri: 'https://randomuser.me/api/portraits/women/2.jpg', 26 | name: 'Jane Smith', 27 | jobTitle: 'Backend Developer', 28 | }, 29 | { 30 | id: '3', 31 | imageUri: 'https://randomuser.me/api/portraits/men/3.jpg', 32 | name: 'Michael Johnson', 33 | jobTitle: 'Backend Developer', 34 | }, 35 | { 36 | id: '4', 37 | imageUri: 'https://randomuser.me/api/portraits/women/4.jpg', 38 | name: 'Merry Martinez', 39 | jobTitle: 'Marketing Manager', 40 | }, 41 | { 42 | id: '5', 43 | imageUri: 'https://randomuser.me/api/portraits/men/7.jpg', 44 | name: 'Andrew Johnson', 45 | jobTitle: 'Marketing Manager', 46 | }, 47 | ]; 48 | 49 | /** 50 | * contentForScrollView 51 | * 52 | * This is a static array containing data for images and descriptions. Each object in the array 53 | * includes an image URL and a description, which is stored in `Strings.description`. 54 | * This data can be used in scrollable views for displaying images with accompanying text. 55 | * 56 | * @type {Array} 57 | * @property {string} imageUrl - The URL of the image to be displayed. 58 | * @property {string} description - A description text for the image, fetched from the `Strings` module. 59 | */ 60 | const contentForScrollView = [ 61 | { 62 | imageUrl: 63 | 'https://img.freepik.com/free-photo/young-woman-walking-wooden-path-with-green-rice-field-vang-vieng-laos_335224-1258.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 64 | description: Strings.description, 65 | }, 66 | { 67 | imageUrl: 68 | 'https://img.freepik.com/premium-photo/garden-near-sigiriya_219717-5813.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 69 | description: Strings.description, 70 | }, 71 | { 72 | imageUrl: 73 | 'https://img.freepik.com/free-photo/beautiful-rainbow-nature_23-2151498359.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 74 | description: Strings.description, 75 | }, 76 | { 77 | imageUrl: 78 | 'https://img.freepik.com/free-photo/cascade-boat-clean-china-natural-rural_1417-1356.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 79 | description: Strings.description, 80 | }, 81 | { 82 | imageUrl: 83 | 'https://img.freepik.com/free-photo/young-woman-walking-wooden-path-with-green-rice-field-vang-vieng-laos_335224-1258.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 84 | description: Strings.description, 85 | }, 86 | { 87 | imageUrl: 88 | 'https://img.freepik.com/free-photo/beautiful-rainbow-nature_23-2151498359.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 89 | description: Strings.description, 90 | }, 91 | { 92 | imageUrl: 93 | 'https://img.freepik.com/premium-photo/garden-near-sigiriya_219717-5813.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 94 | description: Strings.description, 95 | }, 96 | { 97 | imageUrl: 98 | 'https://img.freepik.com/free-photo/cascade-boat-clean-china-natural-rural_1417-1356.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 99 | description: Strings.description, 100 | }, 101 | { 102 | imageUrl: 103 | 'https://img.freepik.com/free-photo/young-woman-walking-wooden-path-with-green-rice-field-vang-vieng-laos_335224-1258.jpg?size=626&ext=jpg&ga=GA1.1.719202892.1708413389&semt=ais_hybrid', 104 | description: Strings.description, 105 | }, 106 | ]; 107 | 108 | export { contentForScrollView, sampleDataForList }; 109 | -------------------------------------------------------------------------------- /example/src/constants/Strings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Strings Module 3 | * 4 | * This module exports an object containing various static strings used throughout the 5 | * application. These strings are typically used for UI labels, headings, descriptions, 6 | * and other text content within the app. 7 | * 8 | */ 9 | export default { 10 | loremString: 11 | 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ultricies urna eget sapien ultrices, eu maximus justo rutrum.', 12 | michaelWilliams: 'Michael Williams', 13 | softwareEngineer: 'Software Engineer', 14 | description: 15 | 'Mauris vel mi ut orci venenatis tristique. Nullam sed suscipit velit. Nullam in elit vitae libero mattis ultricies.', 16 | welcomeText: 'Welcome to ScrollView Example', 17 | list: 'List', 18 | profile: 'Profile', 19 | scrollViewExample: 'ScrollViewExample', 20 | }; 21 | -------------------------------------------------------------------------------- /example/src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AppConst } from './AppConst'; 2 | export { default as NavigationStrings } from './NavigationStrings'; 3 | export * from './StaticData'; 4 | export { default as Strings } from './Strings'; 5 | -------------------------------------------------------------------------------- /example/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | import useLoading from './useLoading'; 2 | 3 | export { useLoading }; 4 | -------------------------------------------------------------------------------- /example/src/hooks/useLoading.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | /** 4 | * Custom hook `useLoading` that simulates a loading state for a given duration. 5 | * 6 | * @param {number} [duration=3000] - Duration in milliseconds for which the loading state remains `true`. 7 | * Defaults to 3000 milliseconds (3 seconds) if not provided. 8 | * 9 | * @returns {boolean} - A boolean indicating whether the component is in a loading state (`true` initially, 10 | * changes to `false` after the specified duration). 11 | */ 12 | const useLoading = (duration: number = 3000): boolean => { 13 | const [isLoading, setIsLoading] = useState(true); 14 | 15 | useEffect(() => { 16 | const timer = setTimeout(() => { 17 | setIsLoading(false); 18 | }, duration); 19 | 20 | return () => clearTimeout(timer); 21 | }, [duration]); 22 | 23 | return isLoading; 24 | }; 25 | 26 | export default useLoading; 27 | -------------------------------------------------------------------------------- /example/src/modules/Home/HomeScreen.tsx: -------------------------------------------------------------------------------- 1 | import { useNavigation } from '@react-navigation/native'; 2 | import React from 'react'; 3 | import { Text, TouchableOpacity, View } from 'react-native'; 4 | import { NavigationStrings, Strings } from '../../constants'; 5 | import type { NavProps } from '../../navigation/types'; 6 | import styles from './HomeScreenStyles'; 7 | 8 | /** 9 | * HomeScreen Component 10 | * 11 | * This component serves as the main screen of the application. It displays a set of buttons 12 | * that navigate to different sections of the app. Each button corresponds to a specific 13 | * screen defined in the navigation structure. 14 | * 15 | * @returns {React.JSX.Element} A JSX element representing the Home screen with navigation buttons. 16 | */ 17 | const HomeScreen = () => { 18 | const navigation = useNavigation(); 19 | 20 | return ( 21 | 22 | { 24 | navigation.navigate(NavigationStrings.LIST); 25 | }}> 26 | {Strings.list} 27 | 28 | { 30 | navigation.navigate(NavigationStrings.PROFILE); 31 | }}> 32 | {Strings.profile} 33 | 34 | { 36 | navigation.navigate(NavigationStrings.SCROLL_VIEW_EXAMPLE); 37 | }}> 38 | {Strings.scrollViewExample} 39 | 40 | 41 | ); 42 | }; 43 | 44 | export default HomeScreen; 45 | -------------------------------------------------------------------------------- /example/src/modules/Home/HomeScreenStyles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | const styles = StyleSheet.create({ 4 | container: { 5 | flex: 1, 6 | alignItems: 'center', 7 | justifyContent: 'center', 8 | }, 9 | title: { 10 | fontSize: 16, 11 | fontWeight: '500', 12 | paddingVertical: 10, 13 | }, 14 | }); 15 | 16 | export default styles; 17 | -------------------------------------------------------------------------------- /example/src/modules/Home/index.ts: -------------------------------------------------------------------------------- 1 | export { default as HomeScreen } from './HomeScreen'; 2 | -------------------------------------------------------------------------------- /example/src/modules/List/ListScreen.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { List } from '../../components'; 3 | 4 | /** 5 | * ListScreen Component 6 | * 7 | * This component serves as a wrapper for the `List` component, which displays a list 8 | * of items. It acts as a dedicated screen in the navigation flow of the application. 9 | * 10 | * @returns {React.JSX.Element} A JSX element that renders the List component. 11 | */ 12 | const ListScreen = () => { 13 | return ; 14 | }; 15 | 16 | export default ListScreen; 17 | -------------------------------------------------------------------------------- /example/src/modules/List/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ListScreen } from './ListScreen'; 2 | -------------------------------------------------------------------------------- /example/src/modules/Profile/ProfileScreen.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Profile } from '../../components'; 3 | 4 | /** 5 | * ProfileScreen Component 6 | * 7 | * This component serves as a wrapper for the `Profile` component, which displays 8 | * user profile information. It acts as a dedicated screen in the application's navigation flow. 9 | * 10 | * @returns {React.JSX.Element} A JSX element that renders the Profile component. 11 | */ 12 | const ProfileScreen = () => { 13 | return ; 14 | }; 15 | 16 | export default ProfileScreen; 17 | -------------------------------------------------------------------------------- /example/src/modules/Profile/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ProfileScreen } from './ProfileScreen'; 2 | -------------------------------------------------------------------------------- /example/src/modules/ScrollViewExample/ScrollViewExampleScreen.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ScrollViewExample } from '../../components'; 3 | 4 | /** 5 | * ScrollViewExampleScreen Component 6 | * 7 | * This component serves as a wrapper for the `ScrollViewExample` component, which displays 8 | * a scrollable view of content. It acts as a dedicated screen in the application's navigation flow. 9 | * 10 | * @returns {React.JSX.Element} A JSX element that renders the ScrollViewExample component. 11 | */ 12 | const ScrollViewExampleScreen = () => { 13 | return ; 14 | }; 15 | 16 | export default ScrollViewExampleScreen; 17 | -------------------------------------------------------------------------------- /example/src/modules/ScrollViewExample/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ScrollViewExampleScreen } from './ScrollViewExampleScreen'; 2 | -------------------------------------------------------------------------------- /example/src/modules/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Home'; 2 | export * from './List'; 3 | export * from './Profile'; 4 | export * from './ScrollViewExample'; 5 | -------------------------------------------------------------------------------- /example/src/navigation/Routes.tsx: -------------------------------------------------------------------------------- 1 | import { NavigationContainer } from '@react-navigation/native'; 2 | import { createNativeStackNavigator } from '@react-navigation/native-stack'; 3 | import React from 'react'; 4 | import { NavigationStrings } from '../constants'; 5 | import { 6 | HomeScreen, 7 | ListScreen, 8 | ProfileScreen, 9 | ScrollViewExampleScreen, 10 | } from '../modules'; 11 | 12 | const Stack = createNativeStackNavigator(); 13 | 14 | /** 15 | * Routes Component 16 | * 17 | * This component sets up the navigation structure of the application using a stack navigator. 18 | * It defines the various screens available in the app, including the Home screen, List 19 | * screen, Profile screen, and Scroll View Example screen. The initial route is set to 20 | * the Home screen. 21 | * 22 | * @returns {React.JSX.Element} A JSX element representing the navigation container with stack routes. 23 | */ 24 | const Routes = () => { 25 | return ( 26 | 27 | 28 | 29 | 30 | 34 | 38 | 39 | 40 | ); 41 | }; 42 | 43 | export default Routes; 44 | -------------------------------------------------------------------------------- /example/src/navigation/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * NavProps Interface 3 | * 4 | * This interface defines the properties for navigation in the application. It includes methods 5 | * for navigating to a different screen, going back to the previous screen, and popping the 6 | * current screen from the navigation stack. 7 | * 8 | * @interface NavProps 9 | * @property {Function} navigate - A function that takes a string argument representing the 10 | * name of the screen to navigate to. 11 | * @property {Function} goBack - A function that navigates back to the previous screen in the stack. 12 | * @property {Function} pop - A function that removes the current screen from the navigation stack. 13 | */ 14 | interface NavProps { 15 | navigate: (args: string) => void; 16 | goBack: () => void; 17 | pop: () => void; 18 | } 19 | 20 | export type { NavProps }; 21 | -------------------------------------------------------------------------------- /example/src/theme/ApplicationStyle.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | 3 | /** 4 | * Application Styles 5 | * 6 | * This module contains the styles used throughout the application. 7 | * The styles are defined using React Native's `StyleSheet` API to ensure 8 | * consistent styling and performance. 9 | * 10 | */ 11 | const applicationStyle = StyleSheet.create({ 12 | screen: { 13 | flex: 1, 14 | }, 15 | }); 16 | 17 | export default applicationStyle; 18 | -------------------------------------------------------------------------------- /example/src/theme/Colors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A collection of color constants used throughout the application. 3 | * 4 | */ 5 | const colors = { 6 | white: '#ffffff', 7 | black: '#000000', 8 | blue: '#05259b', 9 | gray: '#9b9b9b', 10 | green: '#008000', 11 | }; 12 | 13 | export default colors; 14 | -------------------------------------------------------------------------------- /example/src/theme/index.ts: -------------------------------------------------------------------------------- 1 | import applicationStyle from './ApplicationStyle'; 2 | import { default as Colors } from './Colors'; 3 | 4 | export { Colors, applicationStyle }; 5 | -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "esModuleInterop": true, 5 | "jsx": "react-native", 6 | "lib": ["ESNext"], 7 | "module": "CommonJS", 8 | "noEmit": true, 9 | "paths": { 10 | "react-native-dynamic-shimmer": ["../src"] 11 | }, 12 | "declaration": true, 13 | "allowUnreachableCode": false, 14 | "allowUnusedLabels": false, 15 | "forceConsistentCasingInFileNames": true, 16 | "moduleResolution": "Node", 17 | "noFallthroughCasesInSwitch": true, 18 | "noImplicitReturns": true, 19 | "noImplicitUseStrict": false, 20 | "noStrictGenericChecks": false, 21 | "noUnusedLocals": true, 22 | "noUnusedParameters": true, 23 | "resolveJsonModule": true, 24 | "noEmitOnError": true, 25 | "skipLibCheck": true, 26 | "sourceMap": true, 27 | "strict": true, 28 | "target": "ESNext", 29 | "noUncheckedIndexedAccess": true, 30 | "verbatimModuleSyntax": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-dynamic-shimmer", 3 | "version": "1.0.2", 4 | "description": "Shimmer component wrapper for React Native apps", 5 | "main": "lib/index", 6 | "types": "lib/index.d.ts", 7 | "homepage": "https://github.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer#readme", 8 | "author": "Simform Solutions", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/SimformSolutionsPvtLtd/react-native-dynamic-shimmer" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "react-native", 16 | "typescript", 17 | "rn", 18 | "dynamic-shimmer", 19 | "react-native-dynamic-shimmer", 20 | "shimmer", 21 | "skeleton", 22 | "loading-placeholder", 23 | "skeleton-loader", 24 | "skeleton-animation" 25 | ], 26 | "license": "MIT", 27 | "files": [ 28 | "/lib" 29 | ], 30 | "scripts": { 31 | "prepare": "husky install && yarn build", 32 | "clean": "rm -rf node_modules", 33 | "build": "rm -rf lib && tsc -p .", 34 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx", 35 | "lint:fix": "eslint 'src/**/*.{js,jsx,ts,tsx}' -c .eslintrc --fix ", 36 | "build:local": "yarn build && yarn pack", 37 | "test": "jest", 38 | "example": "yarn --cwd example" 39 | }, 40 | "peerDependencies": { 41 | "react": "*", 42 | "react-native": "*" 43 | }, 44 | "devDependencies": { 45 | "@babel/core": "^7.12.9", 46 | "@babel/runtime": "^7.12.5", 47 | "@commitlint/cli": "^16.1.0", 48 | "@commitlint/config-conventional": "^16.0.0", 49 | "@react-native-community/eslint-config": "^3.0.1", 50 | "@testing-library/react-native": "^9.0.0", 51 | "@tsconfig/react-native": "^2.0.2", 52 | "@types/jest": "^27.4.0", 53 | "@types/lodash": "^4.17.7", 54 | "@types/react": "^18.0.24", 55 | "@types/react-native": "^0.69.5", 56 | "@types/react-test-renderer": "^18.0.0", 57 | "@typescript-eslint/eslint-plugin": "^5.29.0", 58 | "@typescript-eslint/parser": "^5.29.0", 59 | "babel-jest": "^27.4.6", 60 | "eslint": "^7.32.0", 61 | "eslint-plugin-simple-import-sort": "^7.0.0", 62 | "husky": "^8.0.1", 63 | "jest": "^27.4.7", 64 | "lint-staged": "^11.1.2", 65 | "metro-react-native-babel-preset": "^0.70.3", 66 | "prettier": "^2.7.1", 67 | "react": "18.2.0", 68 | "react-native": "0.74.3", 69 | "react-test-renderer": "18.0.0", 70 | "typescript": "^5.1.6" 71 | }, 72 | "husky": { 73 | "hooks": { 74 | "pre-commit": "lint-staged", 75 | "pre-push": "yarn build && yarn test" 76 | } 77 | }, 78 | "lint-staged": { 79 | "src/**/*.{js,ts,tsx}": [ 80 | "eslint" 81 | ] 82 | }, 83 | "resolutions": { 84 | "@types/react": "*" 85 | }, 86 | "jest": { 87 | "preset": "react-native", 88 | "moduleFileExtensions": [ 89 | "ts", 90 | "tsx", 91 | "js", 92 | "jsx", 93 | "json", 94 | "node" 95 | ], 96 | "setupFilesAfterEnv": [], 97 | "modulePathIgnorePatterns": [] 98 | }, 99 | "eslintIgnore": [ 100 | "node_modules/", 101 | "lib/" 102 | ], 103 | "commitlint": { 104 | "extends": [ 105 | "@commitlint/config-conventional" 106 | ] 107 | }, 108 | "dependencies": { 109 | "lodash": "^4.17.21" 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/components/Shimmer/Shimmer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | FlatList, 4 | View, 5 | type DimensionValue, 6 | type ViewStyle, 7 | } from 'react-native'; 8 | import { marginProperties } from '../../constants'; 9 | import { width as screenWidth } from '../../theme'; 10 | import { 11 | calculateAdjustedChildWidth, 12 | calculateAspectRatioDimensions, 13 | calculateGlobalScreenWidth, 14 | calculateParentWidth, 15 | calculateWidthFromAspectRatio, 16 | calculatedEachChildWidth, 17 | checkRootComponent, 18 | computeTotalWidths, 19 | distributeWidths, 20 | flattenStyle, 21 | getAdjustedWidth, 22 | getAriaLabelWidth, 23 | getHorizontalMargin, 24 | getWidthFromAspectRatio, 25 | isAspectRatio, 26 | } from '../../utils'; 27 | import shimmerStyles from './ShimmerStyles'; 28 | import type { 29 | ComputeTotalWidthReturnType, 30 | FetchLeafNodesPropsType, 31 | ShimmerProps, 32 | } from './ShimmerTypes'; 33 | import { RenderShimmerView, ShimmerFlatList } from './components'; 34 | 35 | /** 36 | * Shimmer component that wraps child components and displays a loading state. 37 | * 38 | * @param {Object} props - The props for the Shimmer component. 39 | * @param {React.ReactNode} props.children - The child components to render. 40 | * @param {boolean} props.loading - Indicates if the shimmer is in loading state. 41 | * @param {React.ReactElement} props.shimmerElement - The gradient element used for the shimmer effect. 42 | * @param {number} props.duration - The duration of the shimmer effect animation 43 | * @returns {React.ReactNode} - The rendered children or shimmer view. 44 | */ 45 | const Shimmer = ({ 46 | children, 47 | loading, 48 | shimmerElement, 49 | duration, 50 | }: ShimmerProps) => { 51 | if (!loading) return children; 52 | 53 | /** 54 | * Recursively fetches and renders leaf nodes from a given set of children, 55 | * applying appropriate width and margin calculations to ensure proper layout 56 | * within the parent component's dimensions. This function supports handling 57 | * of aspect ratios, margin adjustments, and shimmer effects for loading states. 58 | * 59 | * @param {Object} params - Parameters for fetching leaf nodes. 60 | * @param {React.ReactNode} params.subChildren - The child components or elements 61 | * that are to be processed and rendered. Can be an array of elements or a single element. 62 | * @param {Object} params.parentInfo - Information about the parent component, 63 | * including a reference to the parent element. 64 | * @param {number} params.calculatedWidth - The width that should be assigned to 65 | * the child components based on the parent's dimensions and other factors. 66 | * @param {boolean} params.isPreviousRow - Indicates if the current node is 67 | * part of a previous row, affecting how width is calculated. 68 | * @param {boolean} params.isRoot - Indicates if the current component is 69 | * the root of the rendering tree. 70 | * @param {number} params.prevMargin - The margin that was applied to the 71 | * previous child, which may affect the layout of the current child. 72 | * 73 | * @returns {React.ReactNode} - The rendered child components with appropriate 74 | * width and margin adjustments applied. This can include shimmer effects 75 | * for loading states, as well as nested child components processed recursively. 76 | * 77 | */ 78 | const fetchLeafNodes = ({ 79 | subChildren, 80 | parentInfo, 81 | calculatedWidth, 82 | isPreviousRow, 83 | isRoot, 84 | prevMargin, 85 | }: FetchLeafNodesPropsType): React.ReactNode => { 86 | // Initialize total margin for child components. 87 | let finalMargin: number = 0; 88 | 89 | // Store child components with calculated widths. 90 | let widthData: (JSX.Element & { width: number })[] = []; 91 | 92 | // Calculate global screen width. 93 | const { globalScreenWidth } = calculateGlobalScreenWidth(parentInfo); 94 | 95 | // Extract parent component from parentInfo. 96 | const parent: JSX.Element = parentInfo?.parent; 97 | 98 | // Check if the parent is the root component. 99 | const parentIsRoot: boolean = checkRootComponent(parent); 100 | 101 | // Count number of child components. 102 | const childrenCount: number = parent?.props?.children?.length || 0; 103 | 104 | // Flatten parent's styles. 105 | const flattenedParentStyle: ViewStyle = flattenStyle(parent?.props?.style); 106 | 107 | // Check if parent layout is 'row'. 108 | const isRow: boolean = flattenedParentStyle?.flexDirection === 'row'; 109 | 110 | // Determine if current context is a root row. 111 | const isRootRow = isRoot && !isRow; 112 | 113 | // Flatten content container styles. 114 | const flattenContentContainerStyle: ViewStyle = flattenStyle( 115 | parent?.props?.contentContainerStyle 116 | ); 117 | 118 | const { widthAccordingToAspectRatio } = 119 | calculateWidthFromAspectRatio(flattenedParentStyle); 120 | 121 | const { aspectRatioWidth } = calculateAspectRatioDimensions( 122 | flattenContentContainerStyle, 123 | calculatedWidth 124 | ); 125 | 126 | const primaryWidth: DimensionValue | undefined = getWidthFromAspectRatio({ 127 | isAspectRatioBased: isAspectRatio(flattenedParentStyle, 'width'), 128 | aspectRatioValue: widthAccordingToAspectRatio, 129 | flattenedStyleValue: flattenedParentStyle?.width, 130 | }); 131 | 132 | const contentContainerWidth: DimensionValue | undefined = 133 | getWidthFromAspectRatio({ 134 | isAspectRatioBased: isAspectRatio( 135 | flattenContentContainerStyle, 136 | 'width' 137 | ), 138 | aspectRatioValue: aspectRatioWidth, 139 | flattenedStyleValue: flattenContentContainerStyle?.width, 140 | }); 141 | 142 | const baseWidth: DimensionValue | undefined = 143 | primaryWidth || contentContainerWidth || calculatedWidth || screenWidth; 144 | 145 | const parentWidth: number = calculateParentWidth({ 146 | baseWidth: baseWidth, 147 | containerWidth: screenWidth, 148 | parentIsRoot: parentIsRoot, 149 | calculatedChildWidth: calculatedWidth, 150 | }); 151 | 152 | const { 153 | totalWidthWithFixedChildren, 154 | totalChildrenWithoutWidth, 155 | }: ComputeTotalWidthReturnType = computeTotalWidths( 156 | subChildren, 157 | parentWidth 158 | ); 159 | 160 | const remainingWidth: number = 161 | parentWidth - globalScreenWidth - totalWidthWithFixedChildren; 162 | 163 | if (childrenCount > 0) { 164 | widthData = distributeWidths( 165 | parent?.props?.children, 166 | parentWidth, 167 | flattenedParentStyle 168 | ); 169 | } 170 | 171 | const childrenWithoutWidth: number = 172 | childrenCount - totalChildrenWithoutWidth; 173 | 174 | const divisor: number = isRootRow 175 | ? 1 176 | : childrenCount > 0 177 | ? childrenCount - childrenWithoutWidth 178 | : 1; 179 | 180 | const availableWidth: number = isRootRow 181 | ? parentWidth - globalScreenWidth 182 | : remainingWidth; 183 | 184 | const adjustedChildWidth: number | undefined = calculateAdjustedChildWidth( 185 | subChildren, 186 | parentInfo, 187 | parentWidth 188 | ); 189 | 190 | const computedWidth: number = 191 | calculatedWidth && !isRow 192 | ? calculatedWidth - globalScreenWidth 193 | : availableWidth; 194 | 195 | const derivedWidth: number | undefined = calculatedWidth 196 | ? calculatedWidth - globalScreenWidth 197 | : undefined; 198 | 199 | const calculatedChildWidth: number | undefined = isPreviousRow 200 | ? derivedWidth 201 | : adjustedChildWidth 202 | ? adjustedChildWidth - globalScreenWidth 203 | : computedWidth / divisor; 204 | 205 | /** 206 | * Calculates the total margin from a given style object. 207 | * 208 | * This function iterates through a predefined set of margin properties and 209 | * accumulates their values from the provided style. It handles the case where 210 | * margin values might be undefined, ensuring that only valid numeric margins 211 | * are included in the total. 212 | * 213 | * @param style - The style object from which to extract margin values. It 214 | * should conform to the ViewStyle type. 215 | * @returns The total margin as a number. If no valid margin properties 216 | * are found, it returns 0. 217 | */ 218 | const calculateTotalMargin = (style: ViewStyle): number => { 219 | marginProperties.forEach(marginProp => { 220 | if (style?.[marginProp] !== undefined) { 221 | finalMargin += Number(style?.[marginProp]) ?? 0; 222 | } 223 | }); 224 | 225 | return finalMargin; 226 | }; 227 | 228 | return React.Children.map(subChildren, (child: JSX.Element, index) => { 229 | const childStyle = flattenStyle(child?.props?.style); 230 | const totalMargin = getHorizontalMargin(childStyle); 231 | 232 | const { heightAccordingToAspectRatio } = calculateWidthFromAspectRatio( 233 | flattenedParentStyle, 234 | calculatedChildWidth 235 | ); 236 | 237 | const { aspectRatioHeight } = calculateAspectRatioDimensions( 238 | flattenContentContainerStyle, 239 | calculatedChildWidth 240 | ); 241 | 242 | const parentHeightFromAspectRatio = getWidthFromAspectRatio({ 243 | isAspectRatioBased: isAspectRatio(flattenedParentStyle, 'height'), 244 | aspectRatioValue: heightAccordingToAspectRatio, 245 | flattenedStyleValue: flattenedParentStyle?.height, 246 | }); 247 | 248 | const contentContainerHeightFromAspectRatio = getWidthFromAspectRatio({ 249 | isAspectRatioBased: isAspectRatio( 250 | flattenContentContainerStyle, 251 | 'height' 252 | ), 253 | aspectRatioValue: aspectRatioHeight, 254 | flattenedStyleValue: flattenContentContainerStyle?.height, 255 | }); 256 | 257 | const { shimmerStylesForEachChild } = shimmerStyles({ 258 | child, 259 | numericWidth: getAdjustedWidth( 260 | calculatedChildWidth, 261 | totalMargin, 262 | prevMargin 263 | ), 264 | parentHeight: 265 | parentHeightFromAspectRatio || contentContainerHeightFromAspectRatio, 266 | parentWidth: parentWidth, 267 | }); 268 | 269 | /** 270 | * Processes a React component to apply a shimmer effect. 271 | * 272 | * This function checks the type of the provided React element and applies 273 | * the shimmer effect conditionally based on whether the element is a 274 | * FlatList, a custom React component, or a nested child. It calculates 275 | * necessary widths and margins for rendering and handles various component 276 | * types accordingly. 277 | * 278 | * @param element - The React element (JSX.Element) to process. This can be 279 | * a FlatList, a custom component, or any nested child element. 280 | * @returns The processed React element with a shimmer effect applied. 281 | * If the element is a FlatList, it renders using the `renderFlatList` 282 | * function; otherwise, it clones and modifies the element as needed. 283 | */ 284 | const processComponentWithShimmer = ( 285 | element: JSX.Element 286 | ): JSX.Element => { 287 | const renderFlatList = (nestedChild: JSX.Element) => 288 | ShimmerFlatList({ 289 | child: nestedChild, 290 | widthData, 291 | calculatedChildWidth, 292 | globalScreenWidth, 293 | fetchLeafNodes, 294 | isRow, 295 | parentInfo, 296 | finalMargin, 297 | }); 298 | 299 | if (element?.type === FlatList) { 300 | return renderFlatList(element); 301 | } else if (element?.type?.prototype?.isReactComponent) { 302 | const widthForEachChild = calculatedEachChildWidth({ 303 | child: element, 304 | ...{ widthData, calculatedChildWidth, globalScreenWidth }, 305 | }); 306 | 307 | return React.cloneElement(element, { 308 | children: fetchLeafNodes({ 309 | subChildren: element?.props?.children, 310 | parentInfo: { 311 | parent: element, 312 | }, 313 | calculatedWidth: widthForEachChild, 314 | isPreviousRow: isRow, 315 | isRoot: parentInfo?.parent, 316 | prevMargin: finalMargin, 317 | }), 318 | }); 319 | } else { 320 | const nestedChildren: JSX.Element = element?.type?.(element?.props); 321 | 322 | if (nestedChildren?.type?.name) { 323 | return processComponentWithShimmer(nestedChildren); 324 | } 325 | 326 | if (nestedChildren?.type === FlatList) { 327 | return renderFlatList(nestedChildren); 328 | } 329 | 330 | if ( 331 | typeof nestedChildren?.props?.children === 'string' || 332 | (!nestedChildren?.type?.name && !nestedChildren?.props?.children) 333 | ) { 334 | const nestedChildStyle = flattenStyle(nestedChildren?.props?.style); 335 | calculateTotalMargin(nestedChildStyle); 336 | 337 | const ariaLabelWidth: number | undefined = getAriaLabelWidth( 338 | nestedChildren, 339 | nestedChildStyle 340 | ); 341 | 342 | return RenderShimmerView({ 343 | index, 344 | childStyle: nestedChildStyle, 345 | shimmerStyle: shimmerStylesForEachChild, 346 | shimmerWidth: getAdjustedWidth( 347 | ariaLabelWidth ? ariaLabelWidth : calculatedChildWidth, 348 | totalMargin, 349 | prevMargin 350 | ), 351 | parentWidth, 352 | loading, 353 | shimmerElement, 354 | duration, 355 | }); 356 | } else { 357 | const widthForEachChild = calculatedEachChildWidth({ 358 | child: nestedChildren, 359 | ...{ widthData, calculatedChildWidth, globalScreenWidth }, 360 | }); 361 | 362 | return React.cloneElement(nestedChildren, { 363 | children: fetchLeafNodes({ 364 | subChildren: nestedChildren?.props?.children, 365 | parentInfo: { 366 | parent: nestedChildren, 367 | }, 368 | calculatedWidth: widthForEachChild, 369 | isPreviousRow: isRow, 370 | isRoot: parentInfo?.parent, 371 | prevMargin: finalMargin, 372 | }), 373 | }); 374 | } 375 | } 376 | }; 377 | 378 | if (child?.type?.name) { 379 | return processComponentWithShimmer(child); 380 | } else { 381 | if (typeof child?.props?.children === 'string') { 382 | calculateTotalMargin(childStyle); 383 | 384 | const ariaLabelWidth: number | undefined = getAriaLabelWidth( 385 | child, 386 | childStyle 387 | ); 388 | 389 | return RenderShimmerView({ 390 | index, 391 | childStyle, 392 | shimmerStyle: shimmerStylesForEachChild, 393 | shimmerWidth: getAdjustedWidth( 394 | ariaLabelWidth ? ariaLabelWidth : calculatedChildWidth, 395 | totalMargin, 396 | prevMargin 397 | ), 398 | parentWidth, 399 | loading, 400 | shimmerElement, 401 | duration, 402 | }); 403 | } 404 | if (!child?.props?.children) { 405 | calculateTotalMargin(childStyle || {}); 406 | 407 | const ariaLabelWidth: number | undefined = getAriaLabelWidth( 408 | child, 409 | childStyle 410 | ); 411 | 412 | return RenderShimmerView({ 413 | index, 414 | childStyle, 415 | shimmerStyle: shimmerStylesForEachChild, 416 | shimmerWidth: getAdjustedWidth( 417 | ariaLabelWidth ? ariaLabelWidth : calculatedChildWidth, 418 | totalMargin, 419 | prevMargin 420 | ), 421 | parentWidth, 422 | loading, 423 | shimmerElement, 424 | duration, 425 | }); 426 | } else { 427 | const widthForEachChild = calculatedEachChildWidth({ 428 | ...{ child, widthData, calculatedChildWidth, globalScreenWidth }, 429 | }); 430 | 431 | return React.cloneElement(child, { 432 | children: fetchLeafNodes({ 433 | subChildren: child?.props?.children, 434 | parentInfo: { 435 | parent: child, 436 | }, 437 | calculatedWidth: widthForEachChild, 438 | isPreviousRow: isRow, 439 | isRoot: parentInfo?.parent, 440 | prevMargin: finalMargin, 441 | }), 442 | }); 443 | } 444 | } 445 | }); 446 | }; 447 | 448 | const shimmerChildren = fetchLeafNodes({ 449 | subChildren: children, 450 | parentInfo: { parent: <> }, 451 | }); 452 | 453 | return ( 454 | {shimmerChildren} 455 | ); 456 | }; 457 | 458 | export default Shimmer; 459 | -------------------------------------------------------------------------------- /src/components/Shimmer/ShimmerStyles.ts: -------------------------------------------------------------------------------- 1 | import { 2 | StyleSheet, 3 | type DimensionValue, 4 | type TextStyle, 5 | type ViewStyle, 6 | } from 'react-native'; 7 | import { AppConst } from '../../constants'; 8 | import { 9 | Colors, 10 | height as screenHeight, 11 | width as screenWidth, 12 | } from '../../theme'; 13 | import { 14 | calculateWidthFromAspectRatio, 15 | flattenStyle, 16 | getAriaLabelWidth, 17 | getCalculatedDimension, 18 | isAspectRatio, 19 | } from '../../utils'; 20 | 21 | /** 22 | * Generates styles for shimmer components based on child element properties and dimensions. 23 | * 24 | * This function computes the appropriate styles for a shimmer component, 25 | * considering the aspect ratio of the child element and the dimensions 26 | * of its parent. It flattens the child style, calculates the required width 27 | * and height, and returns the styles necessary for rendering the shimmer. 28 | * 29 | * @param child - The child JSX element for which to generate shimmer styles. 30 | * @param numericWidth - An optional numeric width to use if the child style does not specify one. 31 | * @param parentHeight - The height of the parent container (default is the screen height). 32 | * @param parentWidth - The width of the parent container (default is the screen width). 33 | * @returns An object containing the shimmer styles for the child element. 34 | */ 35 | const shimmerStyles = ({ 36 | child, 37 | numericWidth, 38 | parentHeight = screenHeight, 39 | parentWidth = screenWidth, 40 | }: { 41 | child?: JSX.Element; 42 | numericWidth?: number; 43 | parentHeight?: DimensionValue | undefined; 44 | parentWidth?: number; 45 | }) => { 46 | const childStyle: ViewStyle | TextStyle = flattenStyle( 47 | child?.props?.style || {} 48 | ); 49 | const margin = childStyle?.margin ?? AppConst.defaultMargin; 50 | const { widthAccordingToAspectRatio, heightAccordingToAspectRatio } = 51 | calculateWidthFromAspectRatio(childStyle, parentWidth); 52 | 53 | const isAspectRatioWidth = isAspectRatio(childStyle, 'width'); 54 | const isAspectRatioHeight = isAspectRatio(childStyle, 'height'); 55 | 56 | const widthStyle = isAspectRatioWidth 57 | ? widthAccordingToAspectRatio 58 | : childStyle?.width ?? numericWidth ?? screenWidth; 59 | 60 | const hasAspectRatioHeight = isAspectRatioHeight 61 | ? heightAccordingToAspectRatio 62 | : childStyle?.height; 63 | 64 | const heightStyle = 65 | hasAspectRatioHeight ?? 66 | ('fontSize' in childStyle 67 | ? childStyle?.fontSize 68 | : AppConst.defaultFontSize); 69 | 70 | const calculatedWidth = 71 | getCalculatedDimension({ 72 | styleValue: widthStyle, 73 | parentDimension: parentWidth, 74 | isWidthStyle: true, 75 | numericWidth: numericWidth, 76 | }) - AppConst.offSetForWidth; 77 | 78 | const ariaLabelWidth: number | undefined = getAriaLabelWidth( 79 | child, 80 | childStyle 81 | ); 82 | 83 | const calculateHeight = 84 | getCalculatedDimension({ 85 | styleValue: heightStyle, 86 | parentDimension: parentHeight, 87 | }) - AppConst.offSetForWidth; 88 | 89 | return StyleSheet.create({ 90 | shimmerStylesForEachChild: { 91 | backgroundColor: Colors.gray, 92 | overflow: 'hidden', 93 | margin, 94 | width: ariaLabelWidth 95 | ? ariaLabelWidth - AppConst.offSetForWidth 96 | : calculatedWidth, 97 | height: calculateHeight, 98 | }, 99 | }); 100 | }; 101 | 102 | export default shimmerStyles; 103 | -------------------------------------------------------------------------------- /src/components/Shimmer/ShimmerTypes.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { DimensionValue, ViewStyle } from 'react-native'; 3 | 4 | /** 5 | * Represents the information of a parent component. 6 | */ 7 | export interface ParentInfo { 8 | parent: JSX.Element; 9 | } 10 | 11 | /** 12 | * Props for fetching leaf nodes from a parent component. 13 | * 14 | * @property {JSX.Element} subChildren - The sub-children elements to fetch. 15 | * @property {ParentInfo} parentInfo - Information about the parent. 16 | * @property {number} [calculatedWidth] - Optional calculated width for the sub-children. 17 | * @property {boolean} [isPreviousRow] - Indicates if this is a previous row. 18 | * @property {React.ReactNode} [isRoot] - The root element, if applicable. 19 | * @property {number} [prevMargin] - Optional margin from the previous element. 20 | */ 21 | export interface FetchLeafNodesPropsType { 22 | subChildren: JSX.Element; 23 | parentInfo: ParentInfo; 24 | calculatedWidth?: number; 25 | isPreviousRow?: boolean; 26 | isRoot?: React.ReactNode; 27 | prevMargin?: number; 28 | } 29 | 30 | /** 31 | * Represents the styles applied to a child component. 32 | */ 33 | export interface ChildStyleType { 34 | style: ViewStyle; // The style object for the child. 35 | } 36 | 37 | /** 38 | * Props for calculating the width of a parent component. 39 | * 40 | * @property {DimensionValue | undefined} baseWidth - The base width of the parent, which may be undefined. 41 | * @property {number} containerWidth - The total width of the container in which the parent resides. 42 | * @property {boolean} parentIsRoot - Indicates whether the parent component is the root component. 43 | * @property {number | undefined} calculatedChildWidth - The calculated width of the child component, which may be undefined. 44 | */ 45 | export interface CalculatedParentWidthPropType { 46 | baseWidth: DimensionValue | undefined; 47 | containerWidth: number; 48 | parentIsRoot: boolean; 49 | calculatedChildWidth: number | undefined; 50 | } 51 | 52 | /** 53 | * Props for calculating the width of each child component. 54 | * 55 | * @property {JSX.Element} child - The child element whose width is being calculated. 56 | * @property {(JSX.Element & { width?: number })[]} widthData - An array of JSX elements with optional width properties. 57 | * @property {number | undefined} calculatedChildWidth - The calculated width of the child, which may be undefined. 58 | * @property {number} globalScreenWidth - The width of the global screen. 59 | */ 60 | export interface CalculatedEachChildWidthPropType { 61 | child: JSX.Element; 62 | widthData: (JSX.Element & { width?: number })[]; 63 | calculatedChildWidth: number | undefined; 64 | globalScreenWidth: number; 65 | } 66 | 67 | /** 68 | * Props for calculating the dimensions based on style and parent dimensions. 69 | * 70 | * @property {DimensionValue | undefined} styleValue - The style value for the dimension, which may be undefined. 71 | * @property {DimensionValue | undefined} parentDimension - The parent dimension value, which may also be undefined. 72 | * @property {boolean} [isWidthStyle] - Indicates if the style value is related to width. Optional. 73 | * @property {number | undefined} [numericWidth] - A numeric width value, which may be undefined. Optional. 74 | */ 75 | export interface GetCalculatedDimensionPropType { 76 | styleValue: DimensionValue | undefined; 77 | parentDimension: DimensionValue | undefined; 78 | isWidthStyle?: boolean; 79 | numericWidth?: number | undefined; 80 | } 81 | 82 | /** 83 | * Return type for computing the total width of children components. 84 | * 85 | * @property {number} totalWidthWithFixedChildren - The total width calculated with fixed width children included. 86 | * @property {number} totalChildrenWithoutWidth - The total width of children that do not have an explicit width defined. 87 | */ 88 | export interface ComputeTotalWidthReturnType { 89 | totalWidthWithFixedChildren: number; 90 | totalChildrenWithoutWidth: number; 91 | } 92 | 93 | /** 94 | * Props for handling the rendering of FlatList items. 95 | * 96 | * @property {JSX.Element} child - The child element to be rendered. 97 | * @property {(JSX.Element & { width: number })[]} widthData - Array of elements with their corresponding widths. 98 | * @property {number | undefined} calculatedChildWidth - The calculated width for the child element, if available. 99 | * @property {number} globalScreenWidth - The total width of the screen. 100 | * @property {(args: FetchLeafNodesPropsType) => React.ReactNode} fetchLeafNodes - Function to fetch leaf nodes based on provided arguments. 101 | * @property {boolean} isRow - Indicates whether the layout is in a row format. 102 | * @property {ParentInfo} parentInfo - Information about the parent component. 103 | * @property {number} finalMargin - The final margin to be applied to the child element. 104 | */ 105 | export interface ShimmerFlatListPropType { 106 | child: JSX.Element; 107 | widthData: (JSX.Element & { width: number })[]; 108 | calculatedChildWidth: number | undefined; 109 | globalScreenWidth: number; 110 | fetchLeafNodes: (args: FetchLeafNodesPropsType) => React.ReactNode; 111 | isRow: boolean; 112 | parentInfo: ParentInfo; 113 | finalMargin: number; 114 | } 115 | 116 | /** 117 | * Represents a copy of an item with its width. 118 | * 119 | * @property {object} itemCopy - The object containing item details. 120 | * @property {JSX.Element} itemCopy.item - The JSX element representing the item. 121 | * @property {number | string} itemCopy.width - The width of the item, which can be a number or a string. 122 | */ 123 | export interface ItemCopyType { 124 | itemCopy: { 125 | item: JSX.Element; 126 | width: number | string; 127 | }; 128 | } 129 | 130 | /** 131 | * Parameters for getting width from aspect ratio. 132 | * 133 | * @property {boolean | '' | 0 | undefined} isAspectRatioBased - Indicates if the width calculation is based on aspect ratio. 134 | * @property {DimensionValue | undefined} aspectRatioValue - The aspect ratio value to use for width calculation. 135 | * @property {DimensionValue | undefined} flattenedStyleValue - The flattened style value for width calculation. 136 | */ 137 | export interface GetWidthFromAspectRatioParams { 138 | isAspectRatioBased: boolean | '' | 0 | undefined; 139 | aspectRatioValue: DimensionValue | undefined; 140 | flattenedStyleValue: DimensionValue | undefined; 141 | } 142 | 143 | /** 144 | * Represents the return type for aspect ratio calculations. 145 | * 146 | * This type can indicate whether the aspect ratio is defined, 147 | * not defined (represented by an empty string), or invalid (represented by 0). 148 | * 149 | * @type {boolean | '' | 0 | undefined} 150 | */ 151 | export type AspectRatioReturnType = boolean | '' | 0 | undefined; 152 | 153 | /** 154 | * Props for parsing dimension values. 155 | * 156 | * @property {DimensionValue | undefined} dimension - The dimension value to be parsed, which can be a number, string, or undefined. 157 | * @property {number | undefined} screenSize - The size of the screen to be used for calculations, if applicable. 158 | */ 159 | export interface ParseDimensionPropType { 160 | dimension: DimensionValue | undefined; 161 | screenSize: number | undefined; 162 | } 163 | 164 | /** 165 | * Represents the calculated width and height based on aspect ratio. 166 | * 167 | * @property {number | undefined} widthAccordingToAspectRatio - The calculated width according to the aspect ratio, or undefined if not applicable. 168 | * @property {number | undefined} heightAccordingToAspectRatio - The calculated height according to the aspect ratio, or undefined if not applicable. 169 | */ 170 | export interface CalculateWidthFromAspectRatioReturnType { 171 | widthAccordingToAspectRatio: number | undefined; 172 | heightAccordingToAspectRatio: number | undefined; 173 | } 174 | 175 | /** 176 | * Props for the Shimmer component. 177 | * 178 | * @property {JSX.Element} children - The child elements to render within the shimmer. 179 | * @property {boolean} loading - Indicates whether the shimmer is in a loading state. 180 | * @property {React.ReactElement} shimmerElement - The gradient element used for the shimmer effect. 181 | * @property {number} duration - The duration of the shimmer effect animation 182 | */ 183 | export interface ShimmerProps { 184 | children: JSX.Element; 185 | loading: boolean; 186 | shimmerElement?: React.ReactElement; 187 | duration?: number; 188 | } 189 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/RenderShimmerView/RenderShimmerView.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View } from 'react-native'; 3 | import { ShimmerEffect } from '../ShimmerEffect'; 4 | import type { RenderShimmerPropTypes } from './RenderShimmerViewTypes'; 5 | 6 | /** 7 | * Renders the shimmer view for each child component. 8 | * 9 | * @param {Object} props - The props for the shimmer view. 10 | * @param {number} props.index - The index of the child. 11 | * @param {ViewStyle} props.childStyle - The style for the child component. 12 | * @param {ViewStyle} props.shimmerStyle - The style for the shimmer component. 13 | * @param {number} props.shimmerWidth - The calculated width for the shimmer effect. 14 | * @param {number} props.parentWidth - The width of the parent component. 15 | * @param {boolean} props.loading - Indicates if the data is still loading. 16 | * @param {React.ReactElement} props.shimmerElement - The gradient element used for the shimmer effect. 17 | * @param {number} props.duration - The duration of the shimmer effect animation 18 | * 19 | * @returns {JSX.Element} - The rendered shimmer view. 20 | */ 21 | const RenderShimmerView = ({ 22 | index, 23 | childStyle, 24 | shimmerStyle, 25 | shimmerWidth, 26 | parentWidth, 27 | loading, 28 | shimmerElement, 29 | duration, 30 | }: RenderShimmerPropTypes) => { 31 | return ( 32 | 36 | 43 | 44 | ); 45 | }; 46 | 47 | export default RenderShimmerView; 48 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/RenderShimmerView/RenderShimmerViewTypes.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { ViewStyle } from 'react-native'; 3 | 4 | /** 5 | * Props for rendering a shimmer effect. 6 | * 7 | * @property {number} index - The index of the item being rendered. 8 | * @property {ViewStyle} childStyle - The style applied to the child component. 9 | * @property {ViewStyle} shimmerStyle - The style applied to the shimmer effect. 10 | * @property {number} shimmerWidth - The width of the shimmer effect. 11 | * @property {number} parentWidth - The width of the parent component. 12 | * @property {boolean} loading - Indicates whether the loading state is active. 13 | * @property {React.ReactElement} shimmerElement - The gradient element used for the shimmer effect. 14 | * @property {number} duration - The duration of the shimmer effect animation 15 | */ 16 | export interface RenderShimmerPropTypes { 17 | index: number; 18 | childStyle: ViewStyle; 19 | shimmerStyle: ViewStyle; 20 | shimmerWidth: number; 21 | parentWidth: number; 22 | loading: boolean; 23 | shimmerElement?: React.ReactElement; 24 | duration?: number; 25 | } 26 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/RenderShimmerView/index.ts: -------------------------------------------------------------------------------- 1 | export { default as RenderShimmerView } from './RenderShimmerView'; 2 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/ShimmerEffect/ShimmerEffect.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useRef } from 'react'; 2 | import { Animated, StyleSheet, View, type DimensionValue } from 'react-native'; 3 | import { AppConst } from '../../../../constants'; 4 | import { width as screenWidth } from '../../../../theme'; 5 | import { 6 | calculateWidthFromAspectRatio, 7 | isAspectRatio, 8 | } from '../../../../utils'; 9 | import shimmerEffectStyles from './ShimmerEffectStyles'; 10 | import type { ShimmerEffectPropType } from './ShimmerEffectTypes'; 11 | 12 | /** 13 | * ShimmerEffect Component 14 | * 15 | * A functional component that renders a shimmering effect using an animated gradient. 16 | * The shimmer effect can be applied to any child component, providing a loading indicator 17 | * for users. The component takes in properties to customize the shimmer's width and duration. 18 | * 19 | * @param {Object} props - The component props. 20 | * @param {DimensionValue} props.shimmerWidth - The width of the shimmer effect. 21 | * @param {number} [props.duration=1000] - The duration of the shimmer animation in milliseconds. Default is 1000. 22 | * @param {Object} [props.childStyle] - The style object to apply to the child component. 23 | * @param {number} [props.parentWidth] - The width of the parent component, used for calculating percentage-based widths. 24 | * @param {React.ReactElement} props.shimmerElement - The gradient element used for the shimmer effect. 25 | * 26 | * @returns {JSX.Element} The rendered shimmer component. 27 | */ 28 | const ShimmerEffect: React.FC = ({ 29 | shimmerWidth, 30 | duration = 1000, 31 | childStyle, 32 | parentWidth, 33 | shimmerElement, 34 | }) => { 35 | // Create a reference to an animated value initialized to 0 36 | const animatedValue: Animated.Value = useRef(new Animated.Value(0)).current; 37 | 38 | /** 39 | * Effect hook to manage the shimmer animation lifecycle. 40 | * 41 | * This effect sets up a looping animation that changes the `animatedValue` 42 | * from 0 to 0.8 over the specified duration. The animation uses the native driver 43 | * for improved performance. The animation starts immediately upon component mount 44 | * and stops when the component unmounts. 45 | */ 46 | useEffect(() => { 47 | const shimmerAnimation = Animated.loop( 48 | Animated.timing(animatedValue, { 49 | toValue: 1, 50 | duration: duration, 51 | useNativeDriver: true, 52 | }) 53 | ); 54 | // Start the shimmer animation 55 | shimmerAnimation.start(); 56 | 57 | // Cleanup function to stop the animation when the component unmounts 58 | return () => { 59 | shimmerAnimation.stop(); // Stop the animation to prevent memory leaks 60 | }; 61 | }, [animatedValue, duration]); 62 | 63 | const { widthAccordingToAspectRatio } = 64 | calculateWidthFromAspectRatio(childStyle); 65 | 66 | const isAspectRatioWidth = isAspectRatio(childStyle, 'width'); 67 | 68 | let childWidth: DimensionValue | undefined = isAspectRatioWidth 69 | ? widthAccordingToAspectRatio 70 | : childStyle?.width; 71 | 72 | if (typeof childWidth === 'string' && childWidth?.includes('%')) { 73 | const percentage: number = 74 | parseFloat(childWidth) / AppConst.percentageDenominator; 75 | childWidth = percentage * parentWidth; 76 | } else { 77 | childWidth = childWidth; 78 | } 79 | 80 | const interpolatedChildWidth = 81 | typeof childWidth === 'number' ? childWidth : shimmerWidth ?? screenWidth; 82 | 83 | const { shimmerEffectStylesForGradient, shimmerOverlay } = 84 | shimmerEffectStyles({ 85 | interpolatedChildWidth, 86 | }); 87 | 88 | return ( 89 | 110 | {shimmerElement ? shimmerElement : } 111 | 112 | ); 113 | }; 114 | 115 | export default ShimmerEffect; 116 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/ShimmerEffect/ShimmerEffectStyles.ts: -------------------------------------------------------------------------------- 1 | import { StyleSheet } from 'react-native'; 2 | import { Colors } from '../../../../theme'; 3 | 4 | /** 5 | * The function `shimmerEffectStyles` creates styles for a gradient shimmer effect with a specified width. 6 | * @param - The `shimmerEffectStyles` function takes in an object as a parameter with an optional property 7 | * `interpolatedChildWidth`, which is a number representing the width of the child element being 8 | * interpolated. The function then returns a StyleSheet object with styles for a gradient shimmer 9 | * effect, setting the width of the shimmer 10 | * @returns A StyleSheet object with a single style definition named "shimmerEffectStylesForGradient" that 11 | * includes a width property set to the value of interpolatedChildWidth and a zIndex property set to 1. 12 | */ 13 | const shimmerEffectStyles = ({ 14 | interpolatedChildWidth, 15 | }: { 16 | interpolatedChildWidth?: number; 17 | }) => { 18 | return StyleSheet.create({ 19 | shimmerEffectStylesForGradient: { 20 | width: interpolatedChildWidth, 21 | zIndex: 1, 22 | }, 23 | shimmerOverlay: { 24 | width: 15, 25 | height: '100%', 26 | backgroundColor: Colors.gray, 27 | elevation: 30, 28 | shadowOffset: { 29 | width: 30, 30 | height: 10, 31 | }, 32 | shadowRadius: 10, 33 | shadowColor: Colors.white, 34 | shadowOpacity: 1, 35 | }, 36 | }); 37 | }; 38 | 39 | export default shimmerEffectStyles; 40 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/ShimmerEffect/ShimmerEffectTypes.ts: -------------------------------------------------------------------------------- 1 | import type React from 'react'; 2 | import type { ViewStyle } from 'react-native'; 3 | 4 | /** 5 | * Props for configuring a shimmer effect. 6 | * 7 | * @property {number} shimmerWidth - The width of the shimmer effect. 8 | * @property {number} [duration] - Optional duration for the shimmer animation. 9 | * @property {ViewStyle} childStyle - The style to apply to the child elements. 10 | * @property {number} parentWidth - The width of the parent container. 11 | * @property {React.ReactElement} shimmerElement - The gradient element used for the shimmer effect. 12 | * 13 | */ 14 | export interface ShimmerEffectPropType { 15 | shimmerWidth: number; 16 | duration?: number; 17 | childStyle: ViewStyle; 18 | parentWidth: number; 19 | shimmerElement?: React.ReactElement; 20 | } 21 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/ShimmerEffect/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ShimmerEffect } from './ShimmerEffect'; 2 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/ShimmerFlatList/ShimmerFlatList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { staticFlatListData } from '../../../../constants'; 3 | import { calculatedEachChildWidth } from '../../../../utils'; 4 | import type { 5 | RenderItemProps, 6 | ShimmerFlatListPropType, 7 | } from './ShimmerFlatListTypes'; 8 | 9 | /** 10 | * Renders components within a FlatList with a shimmer loading effect. 11 | * 12 | * @param {Object} props - The properties for rendering the FlatList. 13 | * @param {JSX.Element} props.child - The child component to render within the FlatList. 14 | * @param {Array} props.widthData - An array containing data about the widths of child components. 15 | * @param {number} props.calculatedChildWidth - The calculated width for the child component. 16 | * @param {number} props.globalScreenWidth - The total width of the screen. 17 | * @param {Function} props.fetchLeafNodes - A function that retrieves leaf nodes from a component. 18 | * @param {boolean} props.isRow - A flag indicating whether the layout is organized in a row. 19 | * @param {Object} props.parentInfo - Information pertaining to the parent component. 20 | * @param {number} props.finalMargin - The margin to apply to the layout. 21 | * @returns {JSX.Element} - A new child component with the shimmer effect applied. 22 | */ 23 | const ShimmerFlatList = ({ 24 | child, 25 | widthData, 26 | calculatedChildWidth, 27 | globalScreenWidth, 28 | fetchLeafNodes, 29 | isRow, 30 | parentInfo, 31 | finalMargin, 32 | }: ShimmerFlatListPropType) => { 33 | const renderItem = 34 | child?.props?.renderItem ?? child.type?.(child?.props)?.props?.renderItem; 35 | 36 | /** 37 | * Renders a shimmer effect for a given child element by fetching its leaf nodes. 38 | * 39 | * @param {JSX.Element} element - The child component to render with a shimmer effect. 40 | * @param {number | undefined} calculatedWidth - The calculated width for the shimmer effect. 41 | * @returns {JSX.Element} - The element with shimmer effect applied to its children. 42 | */ 43 | const shimmerElement = ( 44 | element: JSX.Element, 45 | calculatedWidth: number | undefined 46 | ) => { 47 | const shimmeredItem: React.ReactNode = fetchLeafNodes({ 48 | subChildren: element?.props?.children, 49 | parentInfo: { 50 | parent: element, 51 | }, 52 | calculatedWidth: calculatedWidth, 53 | isPreviousRow: isRow, 54 | isRoot: parentInfo?.parent, 55 | prevMargin: finalMargin, 56 | }); 57 | 58 | return React.cloneElement(element, { 59 | children: shimmeredItem, 60 | }); 61 | }; 62 | 63 | /** 64 | * Applies a shimmer effect to a given React component or its nested children. 65 | * 66 | * @param {JSX.Element} element - The React component to apply the shimmer effect to. 67 | * @param {number | undefined} calculatedWidth - The calculated width for the shimmer effect. 68 | * @returns {JSX.Element} - The element with shimmer effect applied, either directly or to its nested children. 69 | */ 70 | const handleShimmeringComponent = ( 71 | element: JSX.Element, 72 | calculatedWidth: number | undefined 73 | ): JSX.Element => { 74 | if (element?.type?.prototype?.isReactComponent) { 75 | return shimmerElement(element, calculatedWidth); 76 | } else { 77 | const nestedChildren: JSX.Element = element?.type?.(element?.props); 78 | if ( 79 | nestedChildren?.type?.name && 80 | !nestedChildren?.type?.prototype?.isReactComponent 81 | ) { 82 | return handleShimmeringComponent(nestedChildren, calculatedWidth); 83 | } else { 84 | return shimmerElement(nestedChildren, calculatedWidth); 85 | } 86 | } 87 | }; 88 | 89 | /** 90 | * Renders an item with a shimmer effect for a FlatList. 91 | * 92 | * This function takes the props of a FlatList item, calculates its width, 93 | * and applies a shimmer effect to it using the `handleShimmeringComponent` 94 | * or `shimmerElement` function based on the item type. 95 | * 96 | * @param {RenderItemProps} renderItemProps - The props provided to the renderItem function of the FlatList. 97 | * @returns {React.ReactElement} - The rendered item with shimmer effect applied. 98 | */ 99 | const renderItemWithShimmer = ( 100 | renderItemProps: RenderItemProps 101 | ): React.ReactElement => { 102 | const originalItem: JSX.Element = renderItem(renderItemProps); 103 | 104 | const calculatedWidth = calculatedEachChildWidth({ 105 | child: originalItem, 106 | ...{ widthData, calculatedChildWidth, globalScreenWidth }, 107 | }); 108 | 109 | return originalItem?.type?.name 110 | ? handleShimmeringComponent(originalItem, calculatedWidth) 111 | : shimmerElement(originalItem, calculatedWidth); 112 | }; 113 | 114 | return React.cloneElement(child, { 115 | data: staticFlatListData, 116 | renderItem: renderItemWithShimmer, 117 | }); 118 | }; 119 | 120 | export default ShimmerFlatList; 121 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/ShimmerFlatList/ShimmerFlatListTypes.ts: -------------------------------------------------------------------------------- 1 | import type { FetchLeafNodesPropsType, ParentInfo } from '../../ShimmerTypes'; 2 | 3 | /** 4 | * Props for handling the rendering of FlatList items. 5 | * 6 | * @property {JSX.Element} child - The child element to be rendered. 7 | * @property {(JSX.Element & { width: number })[]} widthData - Array of elements with their corresponding widths. 8 | * @property {number | undefined} calculatedChildWidth - The calculated width for the child element, if available. 9 | * @property {number} globalScreenWidth - The total width of the screen. 10 | * @property {(args: FetchLeafNodesPropsType) => React.ReactNode} fetchLeafNodes - Function to fetch leaf nodes based on provided arguments. 11 | * @property {boolean} isRow - Indicates whether the layout is in a row format. 12 | * @property {ParentInfo} parentInfo - Information about the parent component. 13 | * @property {number} finalMargin - The final margin to be applied to the child element. 14 | */ 15 | export interface ShimmerFlatListPropType { 16 | child: JSX.Element; 17 | widthData: (JSX.Element & { width: number })[]; 18 | calculatedChildWidth: number | undefined; 19 | globalScreenWidth: number; 20 | fetchLeafNodes: (args: FetchLeafNodesPropsType) => React.ReactNode; 21 | isRow: boolean; 22 | parentInfo: ParentInfo; 23 | finalMargin: number; 24 | } 25 | 26 | /** 27 | * Represents an item of data. 28 | * 29 | * @property {string} id - The unique identifier for the item. 30 | * @property {string} title - The title of the item. 31 | */ 32 | interface ItemData { 33 | id: string; 34 | title: string; 35 | } 36 | 37 | /** 38 | * Props for rendering an item in a list. 39 | * 40 | * @property {ItemData} item - The item data to render. 41 | * @property {number} index - The index of the item in the list. 42 | */ 43 | export interface RenderItemProps { 44 | item: ItemData; 45 | index: number; 46 | } 47 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/ShimmerFlatList/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ShimmerFlatList } from './ShimmerFlatList'; 2 | -------------------------------------------------------------------------------- /src/components/Shimmer/components/index.ts: -------------------------------------------------------------------------------- 1 | import { RenderShimmerView } from './RenderShimmerView'; 2 | import { ShimmerEffect } from './ShimmerEffect'; 3 | import { ShimmerFlatList } from './ShimmerFlatList'; 4 | 5 | export { RenderShimmerView, ShimmerEffect, ShimmerFlatList }; 6 | -------------------------------------------------------------------------------- /src/components/Shimmer/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Shimmer } from './Shimmer'; 2 | export { default as shimmerStyles } from './ShimmerStyles'; 3 | export * from './ShimmerTypes'; 4 | export * from './components'; 5 | -------------------------------------------------------------------------------- /src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Shimmer'; 2 | -------------------------------------------------------------------------------- /src/constants/AppConst.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A constant freezing object that contains the app value. 3 | * @type {Object} 4 | */ 5 | 6 | export default Object.freeze({ 7 | offSetForWidth: 4, 8 | defaultMargin: 3, 9 | defaultFontSize: 16, 10 | lengthMultiplier: 10, 11 | profileImageUrl: 'https://randomuser.me/api/portraits/men/1.jpg', 12 | percentageDenominator: 100, 13 | paddingMarginMultiplier: 2, 14 | }); 15 | -------------------------------------------------------------------------------- /src/constants/StaticData.ts: -------------------------------------------------------------------------------- 1 | import type { ViewStyle } from 'react-native'; 2 | 3 | /** 4 | * An array of dummy data for use in a FlatList component. 5 | * Each item contains an `id` and a `title`. 6 | * @type {Array<{ id: string; title: string }>} 7 | */ 8 | export const staticFlatListData = [ 9 | { id: '1', title: 'Item 1' }, 10 | { id: '2', title: 'Item 2' }, 11 | { id: '3', title: 'Item 3' }, 12 | { id: '4', title: 'Item 4' }, 13 | ]; 14 | 15 | /** 16 | * An array of margin property keys that can be used in React Native styles. 17 | * These properties define the margin spacing around a component. 18 | * @type {Array} 19 | */ 20 | export const marginProperties: Array = [ 21 | 'margin', 22 | 'marginLeft', 23 | 'marginRight', 24 | ]; 25 | -------------------------------------------------------------------------------- /src/constants/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AppConst } from './AppConst'; 2 | export { marginProperties, staticFlatListData } from './StaticData'; 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './components'; 2 | -------------------------------------------------------------------------------- /src/theme/Colors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A collection of color constants used throughout the application. 3 | * 4 | */ 5 | const colors = { 6 | white: '#ffffff', 7 | black: '#000000', 8 | blue: '#05259b', 9 | gray: '#9b9b9b', 10 | green: '#008000', 11 | }; 12 | 13 | export default colors; 14 | -------------------------------------------------------------------------------- /src/theme/Metrics.ts: -------------------------------------------------------------------------------- 1 | import { Dimensions, type ScaledSize } from 'react-native'; 2 | 3 | /** 4 | * Get the width and height of the device screen. 5 | * @returns {ScaledSize} - the width and height of the device screen. 6 | */ 7 | const { width, height }: ScaledSize = Dimensions.get('window'); 8 | 9 | export { height, width }; 10 | -------------------------------------------------------------------------------- /src/theme/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Colors } from './Colors'; 2 | export * from './Metrics'; 3 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CommonUtils'; 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "declaration": true, 5 | "esModuleInterop": true, 6 | "allowUnreachableCode": false, 7 | "allowUnusedLabels": false, 8 | "jsx": "react", 9 | "lib": ["ESNext"], 10 | "module": "ESNext", 11 | "forceConsistentCasingInFileNames": true, 12 | "moduleResolution": "Node", 13 | "noFallthroughCasesInSwitch": true, 14 | "noImplicitReturns": true, 15 | "noImplicitUseStrict": false, 16 | "noStrictGenericChecks": false, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "resolveJsonModule": true, 20 | "noEmitOnError": true, 21 | "outDir": "./lib", 22 | "skipLibCheck": true, 23 | "sourceMap": true, 24 | "strict": true, 25 | "target": "ESNext", 26 | "noUncheckedIndexedAccess": true, 27 | "verbatimModuleSyntax": true 28 | }, 29 | "exclude": ["example/node_modules/**", "node_modules/**", "**/__tests__/*"], 30 | "include": ["src"] 31 | } 32 | --------------------------------------------------------------------------------