├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── feature-request.md ├── PULL_REQUEST_TEMPLATE.md ├── codecov.yml ├── dependabot.yml └── workflows │ ├── blui-ci.yml │ ├── blui-pr-actions.yml │ └── tagging.yml ├── .gitignore ├── .gitmodules ├── .husky └── pre-commit ├── CHANGELOG.md ├── CODEOWNERS ├── LICENSE ├── MIGRATION.md ├── PUBLISHING.md ├── README.md ├── VALIDATION.md ├── components ├── .eslintrc.js ├── LICENSES.json ├── babel.config.js ├── jest.config.js ├── package.json ├── src │ ├── core │ │ ├── AutoComplete │ │ │ ├── AutoComplete.tsx │ │ │ ├── Autocomplete.test.tsx │ │ │ └── index.ts │ │ ├── ChannelValue │ │ │ ├── ChannelValue.test.tsx │ │ │ ├── ChannelValue.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── ChannelValue.test.tsx.snap │ │ │ └── index.ts │ │ ├── Chip │ │ │ ├── Chip.test.tsx │ │ │ ├── Chip.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── Chip.test.tsx.snap │ │ │ └── index.ts │ │ ├── CollapsableHeaderLayout │ │ │ ├── CollapsableHeaderLayout.test.tsx │ │ │ ├── CollapsableHeaderLayout.tsx │ │ │ └── index.ts │ │ ├── Drawer │ │ │ ├── Drawer.tsx │ │ │ ├── DrawerBody.tsx │ │ │ ├── DrawerFooter.tsx │ │ │ ├── DrawerHeader.tsx │ │ │ ├── DrawerNavGroup.tsx │ │ │ ├── DrawerNavItem.tsx │ │ │ ├── DrawerSubHeader.tsx │ │ │ ├── context │ │ │ │ ├── drawer-context.ts │ │ │ │ ├── index.ts │ │ │ │ └── nav-group-context.ts │ │ │ ├── index.ts │ │ │ ├── types.tsx │ │ │ └── utilities.tsx │ │ ├── EmptyState │ │ │ ├── EmptyState.test.tsx │ │ │ ├── EmptyState.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── EmptyState.test.tsx.snap │ │ │ └── index.ts │ │ ├── Grade │ │ │ ├── Grade.test.tsx │ │ │ ├── Grade.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── Grade.test.tsx.snap │ │ │ └── index.ts │ │ ├── Header │ │ │ ├── Header.tsx │ │ │ ├── HeaderActionItems.tsx │ │ │ ├── HeaderBackgroundImage.tsx │ │ │ ├── HeaderContent.tsx │ │ │ ├── HeaderIcon.tsx │ │ │ ├── HeaderNavigationIcon.tsx │ │ │ ├── constants.ts │ │ │ ├── contexts │ │ │ │ ├── ColorContextProvider.tsx │ │ │ │ ├── HeaderHeightContextProvider.tsx │ │ │ │ └── SearchContextProvider.tsx │ │ │ └── index.ts │ │ ├── Helpers │ │ │ ├── Utils.test.ts │ │ │ └── Utils.ts │ │ ├── Hero │ │ │ ├── Hero.test.tsx │ │ │ ├── Hero.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── Hero.test.tsx.snap │ │ │ └── index.ts │ │ ├── HeroBanner │ │ │ ├── HeroBanner.test.tsx │ │ │ ├── HeroBanner.tsx │ │ │ └── index.ts │ │ ├── Icon │ │ │ ├── Icon.test.tsx │ │ │ ├── Icon.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── Icon.test.tsx.snap │ │ │ └── index.ts │ │ ├── IconSwitch │ │ │ ├── IconSwitch.test.tsx │ │ │ ├── IconSwitch.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── IconSwitch.test.tsx.snap │ │ │ └── index.ts │ │ ├── InfoListItem │ │ │ ├── InfoListItem.test.tsx │ │ │ ├── InfoListItem.tsx │ │ │ ├── index.ts │ │ │ └── utilities.tsx │ │ ├── ListItemTag │ │ │ ├── ListItemTag.test.tsx │ │ │ ├── ListItemTag.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── ListItemTag.test.tsx.snap │ │ │ └── index.ts │ │ ├── MobileStepper │ │ │ ├── MobileStepper.test.tsx │ │ │ ├── MobileStepper.tsx │ │ │ └── index.ts │ │ ├── Overline │ │ │ ├── Overline.test.tsx │ │ │ ├── Overline.tsx │ │ │ ├── __snapshots__ │ │ │ │ └── Overline.test.tsx.snap │ │ │ └── index.tsx │ │ ├── ScoreCard │ │ │ ├── ScoreCard.test.tsx │ │ │ ├── ScoreCard.tsx │ │ │ └── index.ts │ │ ├── UserMenu │ │ │ ├── BottomSheet.tsx │ │ │ ├── UserMenu.test.tsx │ │ │ ├── UserMenu.tsx │ │ │ └── index.ts │ │ ├── Utility │ │ │ ├── Spacer.test.tsx │ │ │ ├── Spacer.tsx │ │ │ ├── index.ts │ │ │ └── shared.tsx │ │ ├── __contexts__ │ │ │ ├── font-scale-context.tsx │ │ │ └── index.ts │ │ ├── __hooks__ │ │ │ ├── useHeaderDimensions.tsx │ │ │ └── usePrevious.tsx │ │ ├── __types__ │ │ │ └── index.ts │ │ └── index.ts │ ├── images │ │ └── default-avatar.png │ ├── index.ts │ └── types │ │ └── svg.d.ts ├── tsconfig.json ├── tsconfig.lib.json └── yarn.lock ├── demos ├── api │ ├── .eslintrc.js │ ├── .storybook │ │ ├── config.js │ │ ├── main.js │ │ ├── manager-head.html │ │ ├── preview-head.html │ │ └── webpack.config.js │ ├── README.md │ ├── assets │ │ ├── brightlayer-ui-icon.svg │ │ ├── brightlayer-ui-react-native-alpha.svg │ │ ├── brightlayer-ui-react-native-beta.svg │ │ ├── brightlayer-ui-react-native.svg │ │ ├── brightlayer-ui.png │ │ └── circles-bg.svg │ ├── package.json │ ├── src │ │ └── utils.ts │ ├── stories │ │ ├── api.stories.tsx │ │ ├── utils.tsx │ │ └── welcome.stories.tsx │ ├── tsconfig.json │ └── yarn.lock └── storybook │ ├── .buckconfig │ ├── .eslintrc.js │ ├── .gitattributes │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc.js │ ├── .watchmanconfig │ ├── __tests__ │ └── App-test.tsx │ ├── android │ ├── app │ │ ├── _BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── storybook │ │ │ │ └── ReactNativeFlipper.java │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets │ │ │ └── fonts │ │ │ │ ├── AntDesign.ttf │ │ │ │ ├── Entypo.ttf │ │ │ │ ├── EvilIcons.ttf │ │ │ │ ├── Feather.ttf │ │ │ │ ├── FontAwesome.ttf │ │ │ │ ├── FontAwesome5_Brands.ttf │ │ │ │ ├── FontAwesome5_Regular.ttf │ │ │ │ ├── FontAwesome5_Solid.ttf │ │ │ │ ├── Fontisto.ttf │ │ │ │ ├── Foundation.ttf │ │ │ │ ├── Ionicons.ttf │ │ │ │ ├── MaterialCommunityIcons.ttf │ │ │ │ ├── MaterialIcons.ttf │ │ │ │ ├── Octicons.ttf │ │ │ │ ├── OpenSans-Bold.ttf │ │ │ │ ├── OpenSans-ExtraBold.ttf │ │ │ │ ├── OpenSans-Light.ttf │ │ │ │ ├── OpenSans-Regular.ttf │ │ │ │ ├── OpenSans-SemiBold.ttf │ │ │ │ ├── SimpleLineIcons.ttf │ │ │ │ └── Zocial.ttf │ │ │ ├── java │ │ │ └── com │ │ │ │ └── storybook │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── 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 │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle │ ├── app.json │ ├── assets │ └── fonts │ │ ├── OpenSans-Bold.ttf │ │ ├── OpenSans-ExtraBold.ttf │ │ ├── OpenSans-Light.ttf │ │ ├── OpenSans-Regular.ttf │ │ └── OpenSans-SemiBold.ttf │ ├── babel.config.js │ ├── index.js │ ├── ios │ ├── Podfile │ ├── Podfile.lock │ ├── storybook-tvOS │ │ └── Info.plist │ ├── storybook-tvOSTests │ │ └── Info.plist │ ├── storybook.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── storybook-tvOS.xcscheme │ │ │ └── storybook.xcscheme │ ├── storybook.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── storybook │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── storybookTests │ │ ├── Info.plist │ │ └── storybookTests.m │ ├── metro.config.js │ ├── package.json │ ├── react-native.config.js │ ├── storybook │ ├── addons.ts │ ├── assets │ │ ├── eatonLogo.png │ │ ├── farm.jpg │ │ └── test-avatar.png │ ├── decorators │ │ └── index.tsx │ ├── index.tsx │ ├── rn-addons.ts │ └── stories │ │ ├── bucket-view.tsx │ │ ├── channel-value.tsx │ │ ├── collapsible-header-layout.tsx │ │ ├── collapsible-section.tsx │ │ ├── drawer.tsx │ │ ├── empty-state.tsx │ │ ├── header.tsx │ │ ├── hero.tsx │ │ ├── index.ts │ │ ├── info-list-item │ │ ├── index.ts │ │ ├── info-list-item.tsx │ │ └── info-list.tsx │ │ ├── layout-view │ │ ├── index.ts │ │ └── layout-view.tsx │ │ ├── list-item-tag.tsx │ │ ├── mobile-stepper.tsx │ │ ├── score-card.tsx │ │ ├── search-screen.tsx │ │ ├── spacer.tsx │ │ └── user-menu.tsx │ ├── tsconfig.json │ └── yarn.lock ├── docs ├── AutoComplete.md ├── ChannelValue.md ├── Chip.md ├── CollapsibleHeaderLayout.md ├── Drawer.md ├── EmptyState.md ├── Grade.md ├── Header.md ├── Hero.md ├── IconSwitch.md ├── Icons.md ├── InfoListItem.md ├── ListItemTag.md ├── MobileStepper.md ├── Overline.md ├── ScoreCard.md ├── Spacer.md ├── UserMenu.md └── images │ ├── ListItemTagInInfoListItem.png │ ├── autocomplete.png │ ├── channelValue.png │ ├── chip.png │ ├── collapsibleHeaderLayout.gif │ ├── drawer.png │ ├── emptyState.png │ ├── grade.png │ ├── gradesSubcomponent.png │ ├── header_large.png │ ├── header_small.png │ ├── hero.png │ ├── icon.png │ ├── iconswitch.png │ ├── infoListItem.png │ ├── listItemTag.png │ ├── mobileStepper_dot.png │ ├── mobileStepper_progress.png │ ├── mobileStepper_text.png │ ├── overline.png │ ├── scorecard.png │ ├── scorecard_alt.png │ ├── spacer.png │ ├── userMenuAvatar.png │ └── userMenuOpened.png ├── package.json ├── scripts ├── buildComponents.sh ├── initializeSubmodule.sh └── linkComponents.sh └── yarn.lock /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report a bug with a Brightlayer UI resource 4 | title: '' 5 | labels: 'bug, needs-review, brightlayer-ui' 6 | assignees: '' 7 | 8 | --- 9 | 10 | #### Describe the bug / expected behavior 11 | 12 | #### What are the steps to reproduce? 13 | 1. Go to... 14 | 2. Click on... 15 | 16 | #### Screenshots / Screen recording 17 | 18 | #### Code snippet / Link to minimum reproduction example 19 | 20 | ``` 21 | CODE HERE 22 | ``` 23 | 24 | #### Your environment information 25 | 26 | 27 | #### Suggested fix 28 | 29 | 30 | #### Anything else to add? 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an idea for this resource 4 | title: '' 5 | labels: 'enhancement, needs-review, brightlayer-ui' 6 | assignees: '' 7 | 8 | --- 9 | 10 | #### Describe the desired feature/functionality 11 | 12 | #### Additional Context (where / how would this be used) 13 | 14 | #### Is this request related to a current issue? 15 | 16 | #### Suggested implementation details 17 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | Fixes # . 3 | 4 | 5 | #### Changes proposed in this Pull Request: 6 | - 7 | - 8 | - 9 | 10 | 11 | #### Screenshots / Screen Recording (if applicable) 12 | - 13 | 14 | 15 | 16 | #### To Test: 17 | - 18 | 19 | 20 | #### Any specific feedback you are looking for? 21 | - 22 | 23 | 24 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | target: 80% 6 | threshold: 5% 7 | informational: true 8 | patch: 9 | default: 10 | target: 80% 11 | threshold: 5% 12 | informational: true -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: 'npm' 4 | directory: '/' 5 | schedule: 6 | interval: 'monthly' 7 | day: 'monday' 8 | open-pull-requests-limit: 1 9 | target-branch: 'dev' 10 | labels: 11 | - 'external-dependency' 12 | 13 | - package-ecosystem: 'npm' 14 | directory: '/components' 15 | schedule: 16 | interval: 'monthly' 17 | day: 'monday' 18 | open-pull-requests-limit: 1 19 | target-branch: 'dev' 20 | labels: 21 | - 'external-dependency' 22 | 23 | - package-ecosystem: 'npm' 24 | directory: '/docs' 25 | schedule: 26 | interval: 'monthly' 27 | day: 'monday' 28 | open-pull-requests-limit: 1 29 | target-branch: 'dev' 30 | labels: 31 | - 'external-dependency' 32 | -------------------------------------------------------------------------------- /.github/workflows/blui-pr-actions.yml: -------------------------------------------------------------------------------- 1 | name: blui-pr-actions 2 | on: 3 | pull_request_target: 4 | types: 5 | - opened 6 | 7 | permissions: 8 | pull-requests: write 9 | contents: read 10 | 11 | jobs: 12 | pr-labels: 13 | uses: etn-ccis/blui-automation/.github/workflows/blui-labels.yml@dev 14 | secrets: inherit 15 | 16 | pr-comment: 17 | uses: etn-ccis/blui-automation/.github/workflows/blui-comment.yml@dev 18 | secrets: inherit -------------------------------------------------------------------------------- /.github/workflows/tagging.yml: -------------------------------------------------------------------------------- 1 | name: Tagging 2 | 3 | env: 4 | GH_TOKEN: ${{ github.token }} 5 | CURRENT_BRANCH: ${{ github.ref_name }} 6 | 7 | on: 8 | push: 9 | branches: 10 | - master 11 | 12 | jobs: 13 | tag-package: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - run: yarn install --immutable 18 | - run: bash ./scripts/buildComponents.sh 19 | - run: yarn tag:package -b ${CURRENT_BRANCH} 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # See https://help.github.com/ignore-files/ for more about ignoring files. 3 | 4 | # dependencies 5 | node_modules 6 | package-lock.json 7 | **/ios/Pods 8 | 9 | # production 10 | dist 11 | 12 | # builds 13 | **/ios/build/** 14 | **/android/app/build 15 | **/android/.gradle 16 | build.bundle 17 | storybook-static 18 | 19 | # testing 20 | /components/coverage 21 | 22 | # misc 23 | **/**/.DS_Store 24 | **/**/Thumbs.db 25 | .env.local 26 | .env.development.local 27 | .env.test.local 28 | .env.production.local 29 | .vscode/ 30 | .idea/ 31 | 32 | npm-debug.log* 33 | yarn-debug.log* 34 | yarn-error.log* 35 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "demos/showcase"] 2 | path = demos/showcase 3 | url = https://github.com/etn-ccis/blui-react-native-showcase-demo 4 | branch = dev 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | cd ./components && yarn && yarn prettier:check && yarn lint && yarn coverage & cd .. 2 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @JeffGreiner-eaton @surajeaton @joebochill @ektaghag-eaton 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021 - Present, Eaton 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /PUBLISHING.md: -------------------------------------------------------------------------------- 1 | # Publishing Instructions 2 | 3 | ## Automatic Publishing 4 | 5 | This package is published to NPM automatically by Github when code is merged into the `dev` or `master` branches. To publish a new version, simply update the version in `package.json` and merge your code into the appropriate branch. 6 | - The `dev` branch will publish versions marked as `alpha` or `beta`. 7 | - The `master` branch will publish any version (`alpha`, `beta`, or `latest`). 8 | In both cases, the code will only be published if the version number differs from the current version published under the respective dist tag. 9 | 10 | ## Manually Publishing 11 | 12 | If you need to publish a package manually, you can run the following commands from the root folder: 13 | 14 | ```sh 15 | yarn build 16 | yarn publish:package 17 | ``` 18 | 19 | The publishing script will look at the version in the `package.json` and automatically determine whether to publish an alpha, beta, or latest package. 20 | 21 | For this command to work, you must have an NPM token configured in your environment variables or you can perform a login prior to executing the publish command via: 22 | 23 | ```sh 24 | yarn build 25 | npm adduser && yarn publish:package 26 | ``` 27 | 28 | > Publishing manually should only be done for `alpha` or `beta` packages. The command will work for `latest` packages, but this should be avoided except in rare situations where the automatic publishing functionality is not working in Github. 29 | -------------------------------------------------------------------------------- /VALIDATION.md: -------------------------------------------------------------------------------- 1 | # Validation Steps 2 | 3 | ### Manual Steps 4 | 5 | #### Showcase 6 | 1. Beta package integrates into showcase without errors. 7 | 8 | #### Sandbox 9 | 1. Verify the ChannelValue component renders correctly in the sandbox environment, using available knobs. 10 | 2. Verify the Drawer component renders correctly in the sandbox environment, using available knobs. 11 | 3. Verify the Empty State component renders correctly in the sandbox environment, using available knobs. 12 | 4. Verify the Header component renders correctly in the sandbox environment, using available knobs. 13 | 5. Verify the Hero component renders correctly in the sandbox environment, using available knobs. 14 | 6. Verify the IconWrapper component renders correctly in the sandbox environment, using available knobs. 15 | 7. Verify the InfoListItem component renders correctly in the sandbox environment, using available knobs. 16 | 8. Verify the ListItemTag component renders correctly in the sandbox environment, using available knobs. 17 | 9. Verify the MobileStepper component renders correctly in the sandbox environment, using available knobs. 18 | 10. Verify the ScoreCard component renders correctly in the sandbox environment, using available knobs. 19 | 11. Verify the Spacer component renders correctly in the sandbox environment, using available knobs. 20 | 12. Verify the UserMenu component renders correctly in the sandbox environment, using available knobs. 21 | 22 | ### Unit Test Count 23 | 72 -------------------------------------------------------------------------------- /components/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | extends: ['@brightlayer-ui/eslint-config/tsx'], 4 | parserOptions: { 5 | project: "./tsconfig.json", 6 | }, 7 | env: { 8 | browser: true, 9 | jest: true 10 | }, 11 | // Uncomment these if you want to run the hook checks 12 | // plugins: [ 13 | // 'react-hooks' 14 | // ], 15 | // rules: { 16 | // 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks 17 | // 'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies 18 | // } 19 | }; -------------------------------------------------------------------------------- /components/LICENSES.json: -------------------------------------------------------------------------------- 1 | { 2 | "@brightlayer-ui/colors@3.0.1": { 3 | "licenses": "BSD-3-Clause", 4 | "repository": "https://github.com/etn-ccis/blui-colors", 5 | "licenseUrl": "https://github.com/etn-ccis/blui-colors/raw/master/LICENSE", 6 | "parents": "@brightlayer-ui/react-native-components" 7 | }, 8 | "color@3.1.3": { 9 | "licenses": "MIT", 10 | "repository": "https://github.com/Qix-/color", 11 | "licenseUrl": "https://github.com/Qix-/color/raw/master/LICENSE", 12 | "parents": "@brightlayer-ui/react-native-components" 13 | }, 14 | "react-native-collapsible@1.5.3": { 15 | "licenses": "MIT", 16 | "repository": "https://oblador@github.com/oblador/react-native-collapsible", 17 | "licenseUrl": "https://oblador@github.com/oblador/react-native-collapsible/raw/master/LICENSE", 18 | "parents": "@brightlayer-ui/react-native-components" 19 | }, 20 | "react-native-keyboard-aware-scroll-view@0.8.0": { 21 | "licenses": "MIT", 22 | "repository": "https://github.com/APSL/react-native-keyboard-aware-scroll-view", 23 | "licenseUrl": "https://github.com/APSL/react-native-keyboard-aware-scroll-view/raw/master/LICENSE", 24 | "parents": "@brightlayer-ui/react-native-components" 25 | }, 26 | "react-native-modal@12.0.2": { 27 | "licenses": "MIT", 28 | "repository": "https://github.com/react-native-community/react-native-modal", 29 | "licenseUrl": "https://github.com/react-native-community/react-native-modal/raw/master/LICENSE.md", 30 | "parents": "@brightlayer-ui/react-native-components" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /components/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | // react-native-reanimated/plugin must be listed last 4 | plugins: ['react-native-reanimated/plugin'], 5 | }; 6 | -------------------------------------------------------------------------------- /components/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 4 | moduleNameMapper: { 5 | '\\.svg$': 'identity-obj-proxy', 6 | }, 7 | testRegex: 'src/.*(test|spec)\\.[jt]sx?$', 8 | transform: { 9 | '^.+\\.tsx?$': 'ts-jest', 10 | }, 11 | collectCoverage: true, 12 | coverageThreshold: { 13 | "global": { 14 | "lines": 75 15 | } 16 | }, 17 | coverageReporters: ['text', 'cobertura'], 18 | transformIgnorePatterns: [ 19 | 'node_modules/(?!(react-native|@react-native/*|react-native-vector-icons|react-native-animatable|react-native-reanimated|react-native-iphone-x-helper|react-native-modal|react-native-collapsible|@react-native/polyfills)/)', 20 | ], 21 | }; 22 | -------------------------------------------------------------------------------- /components/src/core/AutoComplete/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AutoComplete'; 2 | -------------------------------------------------------------------------------- /components/src/core/ChannelValue/ChannelValue.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ChannelValue } from '.'; 3 | import { cleanup } from '@testing-library/react-native'; 4 | import TestRenderer from 'react-test-renderer'; 5 | 6 | describe('ChannelValue', () => { 7 | afterEach(cleanup); 8 | it('ChannelValue Renders', () => { 9 | const tree = TestRenderer.create().toJSON(); 10 | expect(tree).toMatchSnapshot(); 11 | }); 12 | 13 | it('Renders the background color and font color correctly', () => { 14 | const tree = TestRenderer.create( 15 | 21 | ).toJSON; 22 | expect(tree).toMatchSnapshot(); 23 | }); 24 | 25 | it('Accepts style override', () => { 26 | const tree = TestRenderer.create().toJSON; 27 | expect(tree).toMatchSnapshot(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /components/src/core/ChannelValue/__snapshots__/ChannelValue.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`ChannelValue Accepts style override 1`] = `[Function]`; 4 | 5 | exports[`ChannelValue ChannelValue Renders 1`] = ` 6 | 19 | 53 | 85 | 2 86 | 87 | 88 | 89 | `; 90 | 91 | exports[`ChannelValue Renders the background color and font color correctly 1`] = `[Function]`; 92 | -------------------------------------------------------------------------------- /components/src/core/ChannelValue/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ChannelValue'; 2 | -------------------------------------------------------------------------------- /components/src/core/Chip/Chip.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { cleanup, render } from '@testing-library/react-native'; 3 | import TestRenderer from 'react-test-renderer'; 4 | import { Chip } from './Chip'; 5 | import { Avatar } from 'react-native-paper'; 6 | 7 | describe('Chip component', () => { 8 | afterEach(() => { 9 | cleanup(); 10 | }); 11 | 12 | it('renders correctly with default props', () => { 13 | const tree = TestRenderer.create(Text).toJSON(); 14 | expect(tree).toMatchSnapshot(); 15 | }); 16 | 17 | it('renders correctly in outlined mode', () => { 18 | const tree = TestRenderer.create(Text).toJSON(); 19 | expect(tree).toMatchSnapshot(); 20 | }); 21 | 22 | it('renders correctly in elevated mode', () => { 23 | const tree = TestRenderer.create(Text).toJSON(); 24 | expect(tree).toMatchSnapshot(); 25 | }); 26 | 27 | it('renders correctly when selected', () => { 28 | const tree = TestRenderer.create(Text).toJSON(); 29 | expect(tree).toMatchSnapshot(); 30 | }); 31 | 32 | it('renders correctly when disabled', () => { 33 | const tree = TestRenderer.create(Text).toJSON(); 34 | expect(tree).toMatchSnapshot(); 35 | }); 36 | 37 | it('renders correctly with an icon', () => { 38 | const tree = TestRenderer.create( 39 | Text 40 | ).toJSON(); 41 | expect(tree).toMatchSnapshot(); 42 | }); 43 | 44 | it('renders correctly with an avatar', () => { 45 | const avatar = ; 46 | const tree = TestRenderer.create(Text).toJSON(); 47 | expect(tree).toMatchSnapshot(); 48 | }); 49 | 50 | it('renders only the icon when both an icon and an avatar are provided', () => { 51 | const avatar = ; 52 | const tree = TestRenderer.create( 53 | 54 | Text 55 | 56 | ).toJSON(); 57 | expect(tree).toMatchSnapshot(); 58 | }); 59 | 60 | it('renders with avatar', () => { 61 | const { getByTestId } = render( 62 | } testID="chip"> 63 | CHIP 64 | 65 | ); 66 | 67 | const avatarElement = getByTestId('avatar'); 68 | expect(avatarElement).toBeTruthy(); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /components/src/core/Chip/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Chip'; 2 | -------------------------------------------------------------------------------- /components/src/core/CollapsableHeaderLayout/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CollapsableHeaderLayout'; 2 | -------------------------------------------------------------------------------- /components/src/core/Drawer/DrawerBody.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ScrollView, StyleSheet, ScrollViewProps, ViewStyle } from 'react-native'; 3 | import { DrawerNavGroup } from './DrawerNavGroup'; 4 | import { AllSharedProps } from './types'; 5 | import { inheritSharedProps } from './utilities'; 6 | 7 | type DrawerBodyStyles = { 8 | root?: ViewStyle; 9 | }; 10 | const makeStyles = (): StyleSheet.NamedStyles => 11 | StyleSheet.create({ 12 | root: {}, 13 | }); 14 | 15 | export type DrawerBodyProps = ScrollViewProps & 16 | AllSharedProps & { 17 | /** Style overrides for internal elements. The styles you provide will be combined with the default styles. */ 18 | styles?: DrawerBodyStyles; 19 | }; 20 | 21 | /** 22 | * [DrawerBody](https://brightlayer-ui-components.github.io/react-native/?path=/info/components-documentation--drawer) component 23 | * 24 | * The DrawerBody is a wrapper for the main content of your navigation Drawer. This section sits between 25 | * the DrawerHeader (or optional DrawerSubheader) and the DrawerFooter. This part of the drawer should hold 26 | * your main navigation elements (either using the `items` prop or by passing in DrawerNavGroup and DrawerNavItem children 27 | * declaratively). 28 | */ 29 | export const DrawerBody: React.FC = (props) => { 30 | const { 31 | // Inheritable Props 32 | /* eslint-disable @typescript-eslint/no-unused-vars */ 33 | activeChevronColor, 34 | activeItemBackgroundColor, 35 | activeItemBackgroundShape, 36 | activeItemFontColor, 37 | activeItemIconColor, 38 | backgroundColor, 39 | chevron, 40 | chevronColor, 41 | collapseIcon, 42 | disableActiveItemParentStyles, 43 | divider, 44 | expandIcon, 45 | hidePadding, 46 | itemFontColor, 47 | itemIconColor, 48 | nestedBackgroundColor, 49 | nestedDivider, 50 | theme: themeOverride, 51 | /* eslint-enable @typescript-eslint/no-unused-vars */ 52 | // DrawerBody-specific props 53 | styles = {}, 54 | // Other ScrollView Props 55 | style, 56 | children: bodyChildren, 57 | ...scrollProps 58 | } = props; 59 | const children = React.Children.toArray(bodyChildren); 60 | const defaultStyles = makeStyles(); 61 | 62 | return ( 63 | 64 | {children.map((child: any, index: number) => { 65 | if (!child) return null; 66 | if (child.type && child.type.displayName !== 'DrawerNavGroup') return child; 67 | return ( 68 | 73 | ); 74 | })} 75 | 76 | ); 77 | }; 78 | 79 | DrawerBody.displayName = 'DrawerBody'; 80 | -------------------------------------------------------------------------------- /components/src/core/Drawer/DrawerFooter.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Divider } from 'react-native-paper'; 3 | 4 | type DrawerFooterProps = { 5 | /** 6 | * Whether to show a dividing line above the footer 7 | * 8 | * @default: true 9 | */ 10 | divider?: boolean; 11 | /** 12 | * children element that need to be rendered inside footer 13 | */ 14 | children?: JSX.Element; 15 | }; 16 | 17 | /** 18 | * [DrawerFooter](https://brightlayer-ui-components.github.io/react-native/?path=/info/components-documentation--drawer) component 19 | * 20 | * The DrawerFooter is a wrapper for the bottom of your navigation Drawer. This section will always 21 | * be pinned to the bottom of the Drawer. You can pass in any content you want as a child of this 22 | * component, but you are responsible for adjusting the styles as necessary when the drawer is opened 23 | * and closed. 24 | */ 25 | export const DrawerFooter: React.FC = (props) => { 26 | const { children, divider = true } = props; 27 | 28 | return ( 29 | <> 30 | {divider && } 31 | {children} 32 | 33 | ); 34 | }; 35 | 36 | DrawerFooter.displayName = 'DrawerFooter'; 37 | -------------------------------------------------------------------------------- /components/src/core/Drawer/DrawerSubHeader.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Divider } from 'react-native-paper'; 3 | 4 | type DrawerSubheaderProps = { 5 | /** 6 | * Whether to show a dividing line below the subheader 7 | * 8 | * @default: true 9 | */ 10 | divider?: boolean; 11 | children: JSX.Element; 12 | }; 13 | 14 | /** 15 | * [DrawerSubheader](https://brightlayer-ui-components.github.io/react-native/?path=/info/components-documentation--drawer) component 16 | * 17 | * The DrawerSubheader is a wrapper for additional content in your navigation Drawer. This section will always 18 | * be pinned between the DrawerHeader and the DrawerBody. You can pass in any content you want as a child of this 19 | * component, but you are responsible for adjusting the styles as necessary when the drawer is opened 20 | * and closed. 21 | */ 22 | export const DrawerSubheader: React.FC = (props) => { 23 | const { children, divider = true } = props; 24 | 25 | return ( 26 | <> 27 | {children} 28 | {divider && } 29 | 30 | ); 31 | }; 32 | 33 | DrawerSubheader.displayName = 'DrawerSubheader'; 34 | -------------------------------------------------------------------------------- /components/src/core/Drawer/context/drawer-context.ts: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | 3 | type DrawerContextType = { 4 | activeItem?: string; 5 | onItemSelect?: (id: string) => void; 6 | }; 7 | 8 | export const DrawerContext = createContext({}); 9 | 10 | /** 11 | * useDrawerContext hook 12 | * 13 | * This hook will provide you with the activeItem that is set at the top-level of the Drawer. It also provides access 14 | * to the onItemSelect callback function. We expose this through a Context in order to avoid passing this prop 15 | * through every layer of the component hierarchy. This hook can only be called from within a 16 | * DrawerContext.Provider. 17 | */ 18 | export const useDrawerContext = (): DrawerContextType => useContext(DrawerContext); 19 | -------------------------------------------------------------------------------- /components/src/core/Drawer/context/index.ts: -------------------------------------------------------------------------------- 1 | export * from './drawer-context'; 2 | export * from './nav-group-context'; 3 | -------------------------------------------------------------------------------- /components/src/core/Drawer/context/nav-group-context.ts: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | 3 | type NavGroupContextType = { 4 | activeHierarchy: string[]; 5 | }; 6 | 7 | export const NavGroupContext = createContext({ 8 | activeHierarchy: [], 9 | }); 10 | 11 | /** 12 | * useNavGroupContext hook 13 | * 14 | * This hook will provide you with the activeHierarchy array that is set at the top level 15 | * of the NavGroup component. We expose this through a Context in order to avoid passing this prop 16 | * through every layer of the component hierarchy. This hook can only be called from within a 17 | * NavGroupContext.Provider. 18 | */ 19 | export const useNavGroupContext = (): NavGroupContextType => useContext(NavGroupContext); 20 | -------------------------------------------------------------------------------- /components/src/core/Drawer/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Drawer'; 2 | export * from './DrawerHeader'; 3 | export * from './DrawerBody'; 4 | export * from './DrawerFooter'; 5 | export * from './DrawerNavGroup'; 6 | export * from './DrawerNavItem'; 7 | export * from './DrawerSubHeader'; 8 | export * from './types'; 9 | export * from './context'; 10 | -------------------------------------------------------------------------------- /components/src/core/EmptyState/index.ts: -------------------------------------------------------------------------------- 1 | export * from './EmptyState'; 2 | -------------------------------------------------------------------------------- /components/src/core/Grade/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Grade'; 2 | -------------------------------------------------------------------------------- /components/src/core/Header/HeaderBackgroundImage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Animated, Dimensions, ImageProps, ImageSourcePropType, ImageStyle, StyleSheet } from 'react-native'; 3 | import { useSearch } from './contexts/SearchContextProvider'; 4 | import { useHeaderHeight } from './contexts/HeaderHeightContextProvider'; 5 | import { useHeaderDimensions } from '../__hooks__/useHeaderDimensions'; 6 | 7 | type HeaderBackgroundImageStyles = { 8 | root: ImageStyle; 9 | }; 10 | 11 | const defaultStyles = (deviceWidth: number): HeaderBackgroundImageStyles => 12 | StyleSheet.create({ 13 | root: { 14 | position: 'absolute', 15 | top: 0, 16 | left: 0, 17 | right: 0, 18 | bottom: 0, 19 | resizeMode: 'cover', 20 | width: deviceWidth, 21 | }, 22 | }); 23 | type HeaderBackgroundProps = Omit & { 24 | /** Background image to render */ 25 | backgroundImage?: ImageSourcePropType; 26 | }; 27 | 28 | /** 29 | * HeaderBackgroundImage component 30 | * 31 | * The HeaderBackgroundImage is a helper component for organizing the contents in the Header. It is 32 | * used for displaying the background image and blending it with the background color. 33 | */ 34 | export const HeaderBackgroundImage: React.FC = (props) => { 35 | const { backgroundImage, style, ...otherImageProps } = props; 36 | const { searching } = useSearch(); 37 | const { headerHeight } = useHeaderHeight(); 38 | const { width } = Dimensions.get('screen'); 39 | 40 | const { REGULAR_HEIGHT, EXTENDED_HEIGHT } = useHeaderDimensions(); 41 | 42 | if (backgroundImage && !searching) { 43 | return ( 44 | 61 | ); 62 | } 63 | return null; 64 | }; 65 | -------------------------------------------------------------------------------- /components/src/core/Header/HeaderIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Icon } from '../Icon'; 3 | import { useFontScaleSettings } from '../__contexts__/font-scale-context'; 4 | import { IconSource } from '../__types__'; 5 | import { ICON_SIZE } from './constants'; 6 | 7 | type HeaderIconProps = { 8 | /** A component to render for the icon */ 9 | icon?: IconSource; 10 | 11 | /** the color of the icon */ 12 | color?: string; 13 | }; 14 | /** 15 | * HeaderIcon component 16 | * 17 | * The HeaderIcon is a helper component that is used to properly size and space icons in the Header component. 18 | */ 19 | export const HeaderIcon: React.FC = (props) => { 20 | const { icon, color } = props; 21 | const { disableScaling } = useFontScaleSettings(); 22 | if (icon) { 23 | return ; 24 | } 25 | return null; 26 | }; 27 | -------------------------------------------------------------------------------- /components/src/core/Header/HeaderNavigationIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TouchableOpacity, StyleSheet, StyleProp, ViewStyle, I18nManager } from 'react-native'; 3 | import { ICON_SIZE } from './constants'; 4 | import { IconSource } from '../__types__'; 5 | import Icon from 'react-native-vector-icons/MaterialIcons'; 6 | import { HeaderIcon } from './HeaderIcon'; 7 | import { useSearch } from './contexts/SearchContextProvider'; 8 | import { useColor } from './contexts/ColorContextProvider'; 9 | import { useFontScale, useFontScaleSettings } from '../__contexts__/font-scale-context'; 10 | 11 | const makeStyles = (): StyleSheet.NamedStyles<{ 12 | navigation: ViewStyle; 13 | flipIcon: ViewStyle; 14 | }> => { 15 | const fontScale = useFontScale(); 16 | return StyleSheet.create({ 17 | navigation: { 18 | height: 40 * fontScale, 19 | width: 40 * fontScale, 20 | marginLeft: -8 * fontScale, 21 | marginRight: 24, 22 | marginTop: 8 * fontScale, 23 | padding: 8 * fontScale, 24 | }, 25 | flipIcon: { 26 | transform: [{ scaleX: -1 }], 27 | }, 28 | }); 29 | }; 30 | type HeaderNavigationProps = { 31 | /** A component to render for the navigation icon */ 32 | icon?: IconSource; 33 | 34 | /** 35 | * The color used for the navigation Icon 36 | * 37 | * @default: theme.colors.onSurface 38 | */ 39 | navigationIconColor?: string; 40 | 41 | /** A callback function to call when the icon is pressed */ 42 | onPress?: () => void; 43 | 44 | /** Style to apply to the Touchable element */ 45 | style?: StyleProp; 46 | }; 47 | /** 48 | * HeaderNavigationIcon component 49 | * 50 | * The HeaderNavigationIcon is a helper component that is used to properly size and space the main navigation icon (on the left) in the Header component. 51 | */ 52 | export const HeaderNavigationIcon: React.FC = (props) => { 53 | const { icon, navigationIconColor, onPress, style } = props; 54 | const { searching, onClose } = useSearch(); 55 | const { color } = useColor(); 56 | const defaultStyles = makeStyles(); 57 | const { disableScaling, maxScale } = useFontScaleSettings(); 58 | 59 | if (searching) { 60 | return ( 61 | onClose() : undefined} 65 | style={[defaultStyles.navigation, style]} 66 | > 67 | 75 | 76 | ); 77 | } 78 | if (icon) { 79 | return ( 80 | 87 | 88 | 89 | ); 90 | } 91 | return null; 92 | }; 93 | -------------------------------------------------------------------------------- /components/src/core/Header/constants.ts: -------------------------------------------------------------------------------- 1 | export const ICON_SIZE = 24; 2 | export const ICON_SPACING = 16; 3 | export const ANIMATION_LENGTH = 300; 4 | -------------------------------------------------------------------------------- /components/src/core/Header/contexts/ColorContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | 3 | type ColorContextType = { 4 | color: string; 5 | }; 6 | 7 | export const ColorContext = createContext(null); 8 | 9 | /** 10 | * useColor hook 11 | * 12 | * This hook will provide you with the current text color value that is set at the top level 13 | * of the Header component. We expose this through a Context in order to avoid passing this prop 14 | * through every layer of the component hierarchy. This hook can only be called from within a 15 | * ColorContext.Provider. 16 | */ 17 | export const useColor = (): ColorContextType => { 18 | const context = useContext(ColorContext); 19 | if (context === null) { 20 | throw new Error('useColor must be used within a ColorContextProvider'); 21 | } 22 | return context; 23 | }; 24 | -------------------------------------------------------------------------------- /components/src/core/Header/contexts/HeaderHeightContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | import { Animated } from 'react-native'; 3 | 4 | type HeaderHeightContextType = { 5 | headerHeight: Animated.Value | Animated.AnimatedInterpolation; 6 | }; 7 | 8 | export const HeaderHeightContext = createContext(null); 9 | 10 | /** 11 | * useHeaderHeight hook 12 | * 13 | * This hook will provide you with the current height of the Header component. We expose this through a Context in order to avoid passing this prop 14 | * through every layer of the component hierarchy. This hook can only be called from within a 15 | * HeaderHeightContext.Provider. 16 | */ 17 | export const useHeaderHeight = (): HeaderHeightContextType => { 18 | const context = useContext(HeaderHeightContext); 19 | if (context === null) { 20 | throw new Error('useHeaderHeight must be used within a HeaderHeightContextProvider'); 21 | } 22 | return context; 23 | }; 24 | -------------------------------------------------------------------------------- /components/src/core/Header/contexts/SearchContextProvider.tsx: -------------------------------------------------------------------------------- 1 | import { Ref, createContext, useContext } from 'react'; 2 | import { SearchableConfig } from '../Header'; 3 | import { TextInput } from 'react-native'; 4 | 5 | type SearchContextType = { 6 | searchRef: Ref; 7 | query: string; 8 | searching: boolean; 9 | onQueryChange: (text: string) => void; 10 | searchConfig?: SearchableConfig; 11 | onSearch: () => void; 12 | onClear: () => void; 13 | onClose: () => void; 14 | }; 15 | 16 | export const SearchContext = createContext(null); 17 | 18 | /** 19 | * useSearch hook 20 | * 21 | * This hook will provide you with the current searchConfig that is set at the top level 22 | * of the Header component. We expose this through a Context in order to avoid passing this prop 23 | * through every layer of the component hierarchy. This hook can only be called from within a 24 | * SearchContext.Provider. 25 | */ 26 | export const useSearch = (): SearchContextType => { 27 | const context = useContext(SearchContext); 28 | if (context === null) { 29 | throw new Error('useSearch must be used within a SearchContextProvider'); 30 | } 31 | return context; 32 | }; 33 | -------------------------------------------------------------------------------- /components/src/core/Header/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Header'; 2 | export * from './constants'; 3 | -------------------------------------------------------------------------------- /components/src/core/Helpers/Utils.test.ts: -------------------------------------------------------------------------------- 1 | import { interleave, groupBy } from './Utils'; 2 | 3 | describe('utils', () => { 4 | describe('interleave', () => { 5 | it('returns an empty array if passed an empty array', () => { 6 | const output = interleave([], () => ' '); 7 | 8 | expect(output).toEqual([]); 9 | }); 10 | 11 | it('interleaves the separator into the array', () => { 12 | const output = interleave([1, 2, 3], () => ' '); 13 | 14 | expect(output).toEqual([1, ' ', 2, ' ', 3]); 15 | }); 16 | }); 17 | 18 | describe('groupBy', () => { 19 | const getFirstLetter = (str: string): string => str.slice(0, 1); 20 | 21 | it('returns an empty object when given an empty array', () => { 22 | const groups = groupBy(getFirstLetter, []); 23 | 24 | expect(groups).toEqual({}); 25 | }); 26 | 27 | it('creates mappings of label to array matching it', () => { 28 | const groups = groupBy(getFirstLetter, ['abc', 'aaa', 'bcd']); 29 | 30 | expect(groups).toEqual({ 31 | a: ['abc', 'aaa'], 32 | b: ['bcd'], 33 | }); 34 | }); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /components/src/core/Helpers/Utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interleave function 3 | * 4 | * This function is used to interleave a 'separator' element between the items of an array. 5 | * 6 | * @param array An array of initial elements 7 | * @param separator The separator to inject between all array elements 8 | * @returns a new array with a separator inserted between each of the original items 9 | */ 10 | export const interleave = ( 11 | array: TElement[], 12 | separator: () => TSeparator 13 | ): Array => { 14 | const output: Array = []; 15 | 16 | array.forEach((element, index) => { 17 | if (index) { 18 | output.push(separator()); 19 | } 20 | 21 | output.push(element); 22 | }); 23 | 24 | return output; 25 | }; 26 | 27 | export type LabeledArrays = { [label: string]: T[] }; 28 | 29 | /** 30 | * groupBy function 31 | * 32 | * This function is used to group items from a flat list into buckets 33 | * 34 | * @param getGroup A function that takes an item and returns the group that it should belong to as a string 35 | * @param array The array of elements to group 36 | * @returns An object whose keys are the groups and values are the elements from the original array who belong in that bucket 37 | */ 38 | export const groupBy = (getGroup: (data: T) => string, array: T[]): LabeledArrays => { 39 | const groups: LabeledArrays = {}; 40 | 41 | array.forEach((element) => { 42 | const label = getGroup(element); 43 | 44 | if (groups[label]) { 45 | groups[label].push(element); 46 | } else { 47 | groups[label] = [element]; 48 | } 49 | }); 50 | 51 | return groups; 52 | }; 53 | -------------------------------------------------------------------------------- /components/src/core/Hero/Hero.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { cleanup, fireEvent, render } from '@testing-library/react-native'; 3 | import TestRenderer from 'react-test-renderer'; 4 | import { Hero } from './Hero'; 5 | 6 | describe('Hero', () => { 7 | afterEach(cleanup); 8 | 9 | it('renders correctly with label', () => { 10 | const tree = TestRenderer.create().toJSON(); 11 | expect(tree).toMatchSnapshot(); 12 | }); 13 | 14 | it('renders correctly with icon', () => { 15 | const tree = TestRenderer.create().toJSON(); 16 | expect(tree).toMatchSnapshot(); 17 | }); 18 | 19 | it('renders correctly with custom icon size and color', () => { 20 | const tree = TestRenderer.create( 21 | 22 | ).toJSON(); 23 | expect(tree).toMatchSnapshot(); 24 | }); 25 | 26 | it('renders correctly with icon background color', () => { 27 | const tree = TestRenderer.create( 28 | 29 | ).toJSON(); 30 | expect(tree).toMatchSnapshot(); 31 | }); 32 | 33 | it('renders correctly with ChannelValueProps', () => { 34 | const tree = TestRenderer.create().toJSON(); 35 | expect(tree).toMatchSnapshot(); 36 | }); 37 | 38 | it('calls onPress when pressed', () => { 39 | const onPressMock = jest.fn(); 40 | const { getByText } = render(); 41 | 42 | fireEvent.press(getByText('Hero Label')); 43 | expect(onPressMock).toHaveBeenCalled(); 44 | }); 45 | it('renders correctly with custom styles', () => { 46 | const customStyles = { 47 | root: { backgroundColor: 'red' }, 48 | iconWrapper: { borderColor: 'green' }, 49 | values: { padding: 10 }, 50 | label: { color: 'blue' }, 51 | }; 52 | 53 | const tree = TestRenderer.create().toJSON(); 54 | expect(tree).toMatchSnapshot(); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /components/src/core/Hero/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Hero'; 2 | -------------------------------------------------------------------------------- /components/src/core/HeroBanner/HeroBanner.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TestRenderer from 'react-test-renderer'; 3 | import { HeroBanner, Hero } from '..'; 4 | import { View } from 'react-native'; 5 | import { IconFamily } from '../__types__'; 6 | import { cleanup } from '@testing-library/react-native'; 7 | import { Divider } from 'react-native-paper'; 8 | const Line: IconFamily = { family: 'material-community', name: 'chart-line-variant' }; 9 | 10 | describe('HeroBanner', () => { 11 | afterEach(cleanup); 12 | it('renders four children when four are passed in', () => { 13 | const instance = TestRenderer.create( 14 | 15 | 16 | 17 | 18 | 19 | 20 | ).root; 21 | 22 | expect(instance.findAllByType(Hero)).toHaveLength(4); 23 | }); 24 | 25 | describe('divider', () => { 26 | afterEach(cleanup); 27 | it('does not render if the prop is not specified', () => { 28 | const instance = TestRenderer.create().root; 29 | 30 | expect(instance.findAllByType(View)).toHaveLength(1); 31 | }); 32 | 33 | it('does render if the prop is set to true', () => { 34 | const instance = TestRenderer.create().root; 35 | expect(instance.findAllByType(Divider)).toHaveLength(1); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /components/src/core/HeroBanner/HeroBanner.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View, StyleProp, ViewStyle, ViewProps } from 'react-native'; 3 | import { Divider } from 'react-native-paper'; 4 | 5 | const defaultStyles = StyleSheet.create({ 6 | root: { 7 | flexDirection: 'row', 8 | alignItems: 'center', 9 | justifyContent: 'center', 10 | }, 11 | divider: { 12 | position: 'absolute', 13 | left: 0, 14 | right: 0, 15 | bottom: 0, 16 | }, 17 | }); 18 | 19 | export type HeroBannerProps = ViewProps & { 20 | /** 21 | * Whether to show a dividing line below the banner 22 | * 23 | * @default: false 24 | */ 25 | divider?: boolean; 26 | 27 | /** Style overrides for internal elements. The styles you provide will be combined with the default styles. */ 28 | styles?: { 29 | root?: StyleProp; 30 | divider?: StyleProp; 31 | }; 32 | }; 33 | 34 | /** 35 | * [HeroBanner](https://brightlayer-ui-components.github.io/react-native/?path=/info/components-documentation--hero) component 36 | * 37 | * The HeroBanner is a wrapper component that is used to properly space out 38 | * [Hero](https://brightlayer-ui-components.github.io/react-native/?path=/info/components-documentation--hero) component children in a flex container row. 39 | */ 40 | export const HeroBanner: React.FC = (props) => { 41 | const { divider, children, styles = {}, style, ...viewProps } = props; 42 | const childrenArray = Array.isArray(children) ? children : [children]; 43 | 44 | return ( 45 | 46 | 47 | {childrenArray} 48 | {divider && ( 49 | 50 | 51 | 52 | )} 53 | 54 | 55 | ); 56 | }; 57 | -------------------------------------------------------------------------------- /components/src/core/HeroBanner/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HeroBanner'; 2 | -------------------------------------------------------------------------------- /components/src/core/Icon/Icon.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TestRenderer from 'react-test-renderer'; 3 | import { Icon } from './index'; 4 | import BLUIIcon from '@brightlayer-ui/react-native-vector-icons'; 5 | import { EmptyState } from '../EmptyState'; 6 | 7 | describe('Icon Tests ', () => { 8 | it('renders with string source', () => { 9 | const tree = TestRenderer.create().toJSON(); 10 | expect(tree).toMatchSnapshot(); 11 | }); 12 | it('renders with emoji source', () => { 13 | const tree = TestRenderer.create().toJSON(); 14 | expect(tree).toMatchSnapshot(); 15 | }); 16 | it('renders with blui object source', () => { 17 | const tree = TestRenderer.create().toJSON(); 18 | expect(tree).toMatchSnapshot(); 19 | }); 20 | it('renders with material community object source', () => { 21 | const tree = TestRenderer.create( 22 | 23 | ).toJSON(); 24 | expect(tree).toMatchSnapshot(); 25 | }); 26 | it('renders with material object source', () => { 27 | const tree = TestRenderer.create().toJSON(); 28 | expect(tree).toMatchSnapshot(); 29 | const tree2 = TestRenderer.create().toJSON(); 30 | expect(tree2).toMatchSnapshot(); 31 | }); 32 | it('renders with function source', () => { 33 | const tree = TestRenderer.create( 34 | } /> 35 | ).toJSON(); 36 | expect(tree).toMatchSnapshot(); 37 | }); 38 | it('renders with remote image source', () => { 39 | const tree = TestRenderer.create( 40 | 45 | ).toJSON(); 46 | expect(tree).toMatchSnapshot(); 47 | }); 48 | it('renders with local image source', () => { 49 | const tree = TestRenderer.create().toJSON(); 50 | expect(tree).toMatchSnapshot(); 51 | }); 52 | it('renders in a component', () => { 53 | const tree = TestRenderer.create( 54 | 55 | ).toJSON(); 56 | expect(tree).toMatchSnapshot(); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /components/src/core/Icon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Icon'; 2 | -------------------------------------------------------------------------------- /components/src/core/IconSwitch/IconSwitch.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { cleanup } from '@testing-library/react-native'; 3 | import TestRenderer from 'react-test-renderer'; 4 | import { IconSwitch } from './IconSwitch'; 5 | 6 | describe('IconSwitch component', () => { 7 | afterEach(() => { 8 | cleanup(); 9 | }); 10 | 11 | const mockOnValueChange = jest.fn(); 12 | 13 | test('should render with default props', () => { 14 | const tree = TestRenderer.create().toJSON(); 15 | expect(tree).toMatchSnapshot(); 16 | }); 17 | 18 | test('should render with turned on state', () => { 19 | const tree = TestRenderer.create().toJSON(); 20 | expect(tree).toMatchSnapshot(); 21 | }); 22 | 23 | test('should render with turned on state and icon', () => { 24 | const tree = TestRenderer.create( 25 | 26 | ).toJSON(); 27 | expect(tree).toMatchSnapshot(); 28 | }); 29 | 30 | test('should render icon switch', () => { 31 | const tree = TestRenderer.create( 32 | 33 | ).toJSON(); 34 | expect(tree).toMatchSnapshot(); 35 | }); 36 | 37 | test('should render disabled switch with turned on state', () => { 38 | const tree = TestRenderer.create( 39 | 40 | ).toJSON(); 41 | expect(tree).toMatchSnapshot(); 42 | }); 43 | 44 | test('should render disabled switch with turned on state and icon', () => { 45 | const tree = TestRenderer.create( 46 | 47 | ).toJSON(); 48 | expect(tree).toMatchSnapshot(); 49 | }); 50 | 51 | test('should render disabled switch', () => { 52 | const tree = TestRenderer.create( 53 | 54 | ).toJSON(); 55 | expect(tree).toMatchSnapshot(); 56 | }); 57 | 58 | test('should render disabled switch with icon', () => { 59 | const tree = TestRenderer.create( 60 | 61 | ).toJSON(); 62 | expect(tree).toMatchSnapshot(); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /components/src/core/IconSwitch/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IconSwitch'; 2 | -------------------------------------------------------------------------------- /components/src/core/InfoListItem/index.ts: -------------------------------------------------------------------------------- 1 | export * from './InfoListItem'; 2 | -------------------------------------------------------------------------------- /components/src/core/InfoListItem/utilities.tsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import { interleave } from '../Helpers/Utils'; 3 | import { StyleProp, TextStyle } from 'react-native'; 4 | import { Text } from 'react-native-paper'; 5 | 6 | const renderSubtitleComponent = ( 7 | element: React.ReactNode, 8 | style?: StyleProp, 9 | isWrapped = false 10 | ): React.ReactNode => { 11 | switch (typeof element) { 12 | case 'string': 13 | case 'number': 14 | return ( 15 | 16 | {`${element}`} 17 | 18 | ); 19 | default: 20 | return element; 21 | } 22 | }; 23 | 24 | const renderInfoComponent = ( 25 | element: React.ReactNode, 26 | style?: StyleProp, 27 | isWrapped = false 28 | ): React.ReactNode => { 29 | switch (typeof element) { 30 | case 'string': 31 | case 'number': 32 | return ( 33 | 34 | {`${element}`} 35 | 36 | ); 37 | default: 38 | return element; 39 | } 40 | }; 41 | 42 | export const renderableSubtitleComponent = ( 43 | element: React.ReactNode, 44 | style?: StyleProp, 45 | wrapSubtitle = false 46 | ): React.ReactNode => renderSubtitleComponent(element, style, wrapSubtitle); 47 | 48 | export const renderableInfoComponent = ( 49 | element: React.ReactNode, 50 | style?: StyleProp, 51 | wrapInfo = false 52 | ): React.ReactNode => renderInfoComponent(element, style, wrapInfo); 53 | 54 | export const interpunct = (separator?: string, style?: StyleProp): JSX.Element => ( 55 | 56 | {separator || '\u00B7'} 57 | 58 | ); 59 | export const withKeys = (array: React.ReactNode[]): JSX.Element[] => 60 | array.map((element, index) => {element}); 61 | export const separate = (array: React.ReactNode[], separator?: string): React.ReactNode[] => 62 | interleave(array, () => interpunct(separator)); 63 | -------------------------------------------------------------------------------- /components/src/core/ListItemTag/ListItemTag.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ListItemTag } from '.'; 3 | import { cleanup } from '@testing-library/react-native'; 4 | import TestRenderer from 'react-test-renderer'; 5 | 6 | describe('ListItemTag', () => { 7 | afterEach(cleanup); 8 | it('ListItemTag Renders', () => { 9 | const tree = TestRenderer.create().toJSON(); 10 | expect(tree).toMatchSnapshot(); 11 | }); 12 | 13 | it('Renders the background color and font color correctly', () => { 14 | const tree = TestRenderer.create( 15 | 16 | ).toJSON; 17 | expect(tree).toMatchSnapshot(); 18 | }); 19 | 20 | it('Accepts style override', () => { 21 | const tree = TestRenderer.create( 22 | 23 | ).toJSON; 24 | expect(tree).toMatchSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /components/src/core/ListItemTag/ListItemTag.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TextStyle, StyleProp, StyleSheet } from 'react-native'; 3 | import { Text, TextProps } from 'react-native-paper'; 4 | import { useFontScale } from '../__contexts__/font-scale-context'; 5 | import { $DeepPartial } from '@callstack/react-theme-provider'; 6 | import { calculateHeight, fontStyleBold } from '../Utility/shared'; 7 | import { ExtendedTheme, useExtendedTheme } from '@brightlayer-ui/react-native-themes'; 8 | 9 | export type ListItemTagProps = Omit, 'children' | 'theme' | 'variant'> & { 10 | /** 11 | * Background color for the label. 12 | * 13 | * @default: theme.colors.primaryFilledContainer 14 | **/ 15 | backgroundColor?: string; 16 | 17 | /** 18 | * Text color for the label. 19 | * 20 | * @default: theme.colors.onPrimaryFilledContainer 21 | */ 22 | fontColor?: string; 23 | /** 24 | * The font size to use 25 | */ 26 | fontSize?: number; 27 | 28 | /** The label text. */ 29 | label: string; 30 | /** Style overrides for internal elements. The styles you provide will be combined with the default styles. */ 31 | styles?: { 32 | root?: StyleProp; 33 | }; 34 | 35 | /** 36 | * Theme value overrides specific to this component. 37 | */ 38 | theme?: $DeepPartial; 39 | }; 40 | 41 | const listItemTagStyles = ( 42 | props: ListItemTagProps, 43 | theme: ExtendedTheme, 44 | fontScale: number, 45 | fontSize: number 46 | ): StyleSheet.NamedStyles<{ 47 | root: TextStyle; 48 | }> => 49 | StyleSheet.create({ 50 | root: { 51 | backgroundColor: props.backgroundColor || theme.colors.primaryFilledContainer, 52 | color: props.fontColor || theme.colors.onPrimaryFilledContainer, 53 | height: calculateHeight(fontSize) * fontScale, 54 | padding: 0, 55 | paddingLeft: 4 * fontScale, 56 | paddingRight: 3 * fontScale, // to account for the 1px letter spacing on the last letter 57 | borderRadius: 4 * fontScale, 58 | ...fontStyleBold, 59 | overflow: 'hidden', 60 | lineHeight: calculateHeight(fontSize), 61 | fontSize, 62 | letterSpacing: 1, 63 | textTransform: 'uppercase', 64 | }, 65 | }); 66 | 67 | /** 68 | * [ListItemTag](https://brightlayer-ui-components.github.io/react-native/?path=/info/components-documentation--list-item-tag) component 69 | * 70 | * This component is primarily used as a tag for list elements. It is a stylized 71 | * text item with a colored background and rounded corners. 72 | */ 73 | export const ListItemTag: React.FC = (props) => { 74 | const { 75 | label, 76 | style, 77 | styles = {}, 78 | theme: themeOverride, 79 | /* eslint-disable @typescript-eslint/no-unused-vars */ 80 | fontColor, 81 | backgroundColor, 82 | /* eslint-enable @typescript-eslint/no-unused-vars */ 83 | ...otherTextProps 84 | } = props; 85 | const theme = useExtendedTheme(themeOverride); 86 | const fontScale = useFontScale(); 87 | const defaultStyles = listItemTagStyles(props, theme, fontScale, props.fontSize || 10); 88 | 89 | return ( 90 | 91 | {label} 92 | 93 | ); 94 | }; 95 | 96 | ListItemTag.displayName = 'ListItemTag'; 97 | -------------------------------------------------------------------------------- /components/src/core/ListItemTag/__snapshots__/ListItemTag.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`ListItemTag Accepts style override 1`] = `[Function]`; 4 | 5 | exports[`ListItemTag ListItemTag Renders 1`] = ` 6 | 48 | label text 49 | 50 | `; 51 | 52 | exports[`ListItemTag Renders the background color and font color correctly 1`] = `[Function]`; 53 | -------------------------------------------------------------------------------- /components/src/core/ListItemTag/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ListItemTag'; 2 | -------------------------------------------------------------------------------- /components/src/core/MobileStepper/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MobileStepper'; 2 | -------------------------------------------------------------------------------- /components/src/core/Overline/Overline.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Overline } from '.'; 3 | import { cleanup } from '@testing-library/react-native'; 4 | import TestRenderer from 'react-test-renderer'; 5 | 6 | describe('Overline', () => { 7 | afterEach(cleanup); 8 | it('Overline Renders', () => { 9 | const tree = TestRenderer.create(Overline).toJSON(); 10 | expect(tree).toMatchSnapshot(); 11 | }); 12 | 13 | it('Renders the color correctly', () => { 14 | const tree = TestRenderer.create(Overline ).toJSON; 15 | expect(tree).toMatchSnapshot(); 16 | }); 17 | 18 | it('Accepts style override', () => { 19 | const tree = TestRenderer.create(Overline ).toJSON; 20 | expect(tree).toMatchSnapshot(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /components/src/core/Overline/Overline.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TextStyle, StyleProp, StyleSheet } from 'react-native'; 3 | import { Text, TextProps } from 'react-native-paper'; 4 | import { $DeepPartial } from '@callstack/react-theme-provider'; 5 | import { useFontScaleSettings } from '../__contexts__/font-scale-context'; 6 | import { ExtendedTheme, useExtendedTheme } from '@brightlayer-ui/react-native-themes'; 7 | 8 | export type OverlineProps = Omit, 'theme' | 'variant'> & { 9 | /** Style overrides for internal elements. The styles you provide will be combined with the default styles. */ 10 | styles?: { 11 | root?: StyleProp; 12 | }; 13 | 14 | /** 15 | * Theme value overrides specific to this component. 16 | */ 17 | theme?: $DeepPartial; 18 | }; 19 | 20 | const overlineStyles = ( 21 | theme: ExtendedTheme 22 | ): StyleSheet.NamedStyles<{ 23 | root: TextStyle; 24 | }> => 25 | StyleSheet.create({ 26 | root: { 27 | color: theme.colors.onSurface, 28 | letterSpacing: 2, 29 | textTransform: 'uppercase', 30 | }, 31 | }); 32 | 33 | export const Overline: React.FC = (props) => { 34 | const { children, style, styles = {}, theme: themeOverride, ...otherTextProps } = props; 35 | const theme = useExtendedTheme(themeOverride); 36 | const defaultStyles = overlineStyles(theme); 37 | const { maxScale, disableScaling } = useFontScaleSettings(); 38 | 39 | return ( 40 | 47 | {children} 48 | 49 | ); 50 | }; 51 | -------------------------------------------------------------------------------- /components/src/core/Overline/__snapshots__/Overline.test.tsx.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Overline Accepts style override 1`] = `[Function]`; 4 | 5 | exports[`Overline Overline Renders 1`] = ` 6 | 39 | Overline 40 | 41 | `; 42 | 43 | exports[`Overline Renders the color correctly 1`] = `[Function]`; 44 | -------------------------------------------------------------------------------- /components/src/core/Overline/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Overline'; 2 | -------------------------------------------------------------------------------- /components/src/core/ScoreCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ScoreCard'; 2 | -------------------------------------------------------------------------------- /components/src/core/UserMenu/BottomSheet.tsx: -------------------------------------------------------------------------------- 1 | import { ExtendedTheme, useExtendedTheme } from '@brightlayer-ui/react-native-themes'; 2 | import React, { ReactNode } from 'react'; 3 | import { SafeAreaView, StyleSheet, ViewStyle } from 'react-native'; 4 | import Modal from 'react-native-modal'; 5 | 6 | type BottomSheetProps = { 7 | /** Make the bottom sheet visible */ 8 | show?: boolean; 9 | /** Callback function to execute when the bottom sheet is dismissed */ 10 | onClose?: () => void; 11 | /** Background color to use for the bottom sheet 12 | * 13 | * @default: theme.colors.surface 14 | */ 15 | backgroundColor?: string; 16 | /** Style overrides for internal elements. The styles you provide will be combined with the default styles. */ 17 | styles?: { 18 | root?: ViewStyle; 19 | background?: ViewStyle; 20 | }; 21 | }; 22 | 23 | const useStyles = ( 24 | theme: ExtendedTheme, 25 | props: BottomSheetProps 26 | ): StyleSheet.NamedStyles<{ 27 | root: ViewStyle; 28 | background: ViewStyle; 29 | }> => 30 | StyleSheet.create({ 31 | root: { 32 | justifyContent: 'flex-end', 33 | margin: 0, 34 | }, 35 | background: { 36 | backgroundColor: props.backgroundColor || theme.colors.surface, 37 | }, 38 | }); 39 | /** 40 | * BottomSheet component 41 | * 42 | * This is a utility component for the UserMenu. It handles rendering the menu items in 43 | * a bottom sheet that appears from the bottom of the screen. 44 | */ 45 | export const BottomSheet: React.FC = (props) => { 46 | const { show, children, onClose, styles = {} } = props; 47 | const theme = useExtendedTheme(); 48 | const defaultStyles = useStyles(theme, props); 49 | 50 | return ( 51 | 59 | {children} 60 | 61 | ); 62 | }; 63 | -------------------------------------------------------------------------------- /components/src/core/UserMenu/UserMenu.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Avatar } from 'react-native-paper'; 3 | import { EdgeInsets } from 'react-native-safe-area-context'; 4 | import { cleanup, fireEvent, render, screen } from '@testing-library/react-native'; 5 | import { UserMenu, UserMenuProps } from '.'; 6 | 7 | const defaultProps: UserMenuProps = { 8 | avatar: , 9 | menuItems: [{ title: 'Test Item' }], 10 | }; 11 | jest.mock('react-native-safe-area-context', () => ({ 12 | useSafeAreaInsets: (): EdgeInsets => ({ 13 | top: 0, 14 | left: 0, 15 | right: 0, 16 | bottom: 0, 17 | }), 18 | })); 19 | 20 | describe('UserMenu', () => { 21 | afterEach(cleanup); 22 | 23 | it('should render avatar with correct label', () => { 24 | render(); 25 | expect(screen.getByText('BLUI')).toBeDefined(); 26 | }); 27 | 28 | it('should render bottom sheet on avatar press', () => { 29 | const props = defaultProps; 30 | props.menuTitle = 'Bottom Sheet'; 31 | render(); 32 | expect(screen.queryByText('Bottom Sheet')).toBeNull(); 33 | fireEvent.press(screen.getByText('BLUI')); 34 | expect(screen.getByText('Bottom Sheet')).toBeDefined(); 35 | }); 36 | 37 | it('should render bottom sheet InfoListItem with correct content', () => { 38 | const props = defaultProps; 39 | props.menuTitle = 'Bottom Sheet'; 40 | props.menuItems = [{ title: 'Title', subtitle: 'Subtitle', info: 'Info' }]; 41 | render(); 42 | expect(screen.queryByText('Title')).toBeNull(); 43 | expect(screen.queryByText('Subtitle')).toBeNull(); 44 | expect(screen.queryByText('Info')).toBeNull(); 45 | fireEvent.press(screen.getByText('BLUI')); 46 | expect(screen.getByText('Title')).toBeDefined(); 47 | expect(screen.getByText('Subtitle')).toBeDefined(); 48 | expect(screen.getByText('Info')).toBeDefined(); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /components/src/core/UserMenu/index.ts: -------------------------------------------------------------------------------- 1 | export * from './UserMenu'; 2 | -------------------------------------------------------------------------------- /components/src/core/Utility/Spacer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleProp, StyleSheet, View, ViewStyle, ViewProps } from 'react-native'; 3 | 4 | const spacerStyles = (props: SpacerProps, flex: number): StyleSheet.NamedStyles<{ root: ViewStyle }> => 5 | StyleSheet.create({ 6 | root: { 7 | flex: flex, 8 | height: props.height || 'auto', 9 | width: props.width || 'auto', 10 | }, 11 | }); 12 | 13 | export type SpacerProps = ViewProps & { 14 | /** Flex grow/shrink value for use in flex layouts */ 15 | flex?: number; 16 | 17 | /** Height (in dp) for static layouts */ 18 | height?: number; 19 | 20 | /** Width (in dp) for static layouts */ 21 | width?: number; 22 | 23 | /** Style overrides for internal elements. The styles you provide will be combined with the default styles. */ 24 | styles?: { 25 | root?: StyleProp; 26 | }; 27 | }; 28 | 29 | /** 30 | * [Spacer](https://brightlayer-ui-components.github.io/react-native/?path=/info/components-documentation--spacer) component 31 | * 32 | * This is a helpful utility component for adding spacer elements 33 | * when working within flexbox containers. You can give it a flexible 34 | * or a fixed size. 35 | */ 36 | export const Spacer: React.FC = (props) => { 37 | const { 38 | children, 39 | style, 40 | styles = {}, 41 | // ignore unused vars so that we can do prop transferring to the root element 42 | /* eslint-disable @typescript-eslint/no-unused-vars */ 43 | flex = 1, 44 | height, 45 | width, 46 | /* eslint-enable @typescript-eslint/no-unused-vars */ 47 | ...otherViewProps 48 | } = props; 49 | const defaultStyles = spacerStyles(props, flex); 50 | 51 | return ( 52 | 53 | {children} 54 | 55 | ); 56 | }; 57 | 58 | Spacer.displayName = 'Spacer'; 59 | -------------------------------------------------------------------------------- /components/src/core/Utility/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Spacer'; 2 | -------------------------------------------------------------------------------- /components/src/core/Utility/shared.tsx: -------------------------------------------------------------------------------- 1 | import { MD3Theme } from 'react-native-paper'; 2 | import { useFontWeight } from '@brightlayer-ui/react-native-themes'; 3 | 4 | export const getPrimary500 = (theme: MD3Theme): string | undefined => theme.colors.primary; 5 | 6 | export const calculateHeight = (fontSize: number): number => Math.ceil((fontSize * 1.25) / 4) * 4; 7 | 8 | export const fontStyleLight = useFontWeight('300'); 9 | export const fontStyleRegular = useFontWeight('400'); 10 | export const fontStyleSemiBold = useFontWeight('600'); 11 | export const fontStyleBold = useFontWeight('700'); 12 | export const fontStyleExtraBold = useFontWeight('800'); 13 | -------------------------------------------------------------------------------- /components/src/core/__contexts__/font-scale-context.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, ReactNode, useContext } from 'react'; 2 | import { PixelRatio } from 'react-native'; 3 | 4 | type FontScaleContextType = { 5 | maxScale: number; 6 | disableScaling?: boolean; 7 | }; 8 | 9 | const FontScaleContext = createContext({ 10 | maxScale: 100, 11 | disableScaling: false, 12 | }); 13 | 14 | export const FontScaleProvider: React.FC = (props) => ( 15 | {props.children} 16 | ); 17 | /** 18 | * 19 | * @returns the current settings specified in the nearest FontScaleContext 20 | */ 21 | export const useFontScaleSettings = (): FontScaleContextType => useContext(FontScaleContext); 22 | /** 23 | * @param forceEnable if true, get the clamped fontScale even if the Context has disabled scaling 24 | * @returns the clamped fontScale value taking into account settings in the FontScaleContext 25 | */ 26 | export const useFontScale = (forceEnable = false): number => { 27 | const { disableScaling, maxScale } = useFontScaleSettings(); 28 | const systemScale = PixelRatio.getFontScale(); 29 | // Clamp the scale between min and max 30 | return disableScaling && !forceEnable ? 1 : Math.min(maxScale, systemScale); 31 | }; 32 | -------------------------------------------------------------------------------- /components/src/core/__contexts__/index.ts: -------------------------------------------------------------------------------- 1 | export * from './font-scale-context'; 2 | -------------------------------------------------------------------------------- /components/src/core/__hooks__/useHeaderDimensions.tsx: -------------------------------------------------------------------------------- 1 | import { useWindowDimensions } from 'react-native'; 2 | import { useSafeAreaInsets } from 'react-native-safe-area-context'; 3 | import { useFontScale } from '../__contexts__/font-scale-context'; 4 | 5 | export type HeaderDimensions = { 6 | REGULAR_HEIGHT: number; 7 | EXTENDED_HEIGHT: number; 8 | LANDSCAPE: boolean; 9 | getScaledHeight: (height: number) => number; 10 | }; 11 | /** 12 | * useHeaderDimensions hook 13 | * 14 | * This hook is used to provide the 'constant' values for the Header height in the collapsed 15 | * and expanded states. These values can change when the device rotates based on the safe areas 16 | * and presence or absence of a status bar. 17 | * 18 | * This hook listens for device rotation changes and makes sure the the correct constant values 19 | * are being returned 20 | * 21 | * @returns { REGULAR_HEIGHT, EXTENDED_HEIGHT, LANDSCAPE, getScaledHeight } 22 | */ 23 | export const useHeaderDimensions = (): HeaderDimensions => { 24 | const { width: deviceWidth, height: deviceHeight } = useWindowDimensions(); 25 | const fontScale = useFontScale(); 26 | const insets = useSafeAreaInsets(); 27 | const isLandscape = deviceWidth > deviceHeight; 28 | const heightWithStatusBar = (height: number): number => height * fontScale + insets.top; 29 | 30 | const HEIGHT = { 31 | EXTENDED: heightWithStatusBar(200), 32 | REGULAR: heightWithStatusBar(56), 33 | }; 34 | 35 | const REGULAR_HEIGHT = HEIGHT.REGULAR; 36 | const EXTENDED_HEIGHT = HEIGHT.EXTENDED; 37 | 38 | const getScaledHeight = heightWithStatusBar; 39 | 40 | return { 41 | REGULAR_HEIGHT, 42 | EXTENDED_HEIGHT, 43 | LANDSCAPE: isLandscape, 44 | getScaledHeight, 45 | }; 46 | }; 47 | -------------------------------------------------------------------------------- /components/src/core/__hooks__/usePrevious.tsx: -------------------------------------------------------------------------------- 1 | import { useRef, useEffect } from 'react'; 2 | 3 | /** 4 | * usePrevious hook 5 | * 6 | * This hook is used to track the previous version of a variable from a prior 7 | * render for the purposes of conditionally updating aspects of a component based on 8 | * whether particular variables have changed. 9 | */ 10 | /* eslint-disable-next-line @typescript-eslint/ban-types */ 11 | export const usePrevious = (value: T): T | undefined => { 12 | // The ref object is a generic container whose current property is mutable ... 13 | // ... and can hold any value, similar to an instance property on a class 14 | const ref = useRef(); 15 | 16 | // Store current value in ref 17 | useEffect(() => { 18 | ref.current = value; 19 | }, [value]); // Only re-run if value changes 20 | 21 | // Return previous value (happens before update in useEffect above) 22 | return ref.current; 23 | }; 24 | -------------------------------------------------------------------------------- /components/src/core/__types__/index.ts: -------------------------------------------------------------------------------- 1 | import { ComponentType } from 'react'; 2 | import { ImageSourcePropType } from 'react-native'; 3 | 4 | // Icon-Specific Types 5 | export type IconComponentProps = { 6 | /** The size of the icon to render */ 7 | size?: number; 8 | 9 | /** The color of the icon to render 10 | * @default: theme.colors.onSurface 11 | */ 12 | color?: string; 13 | 14 | /** If true, the icon should scale with the system font size 15 | * 16 | * @default: true 17 | */ 18 | allowFontScaling?: boolean; 19 | }; 20 | export type IconFunctionProps = IconComponentProps & { 21 | /** The direction of the current device language */ 22 | direction?: 'rtl' | 'ltr'; 23 | }; 24 | 25 | export type IconFamily = { 26 | name: string; 27 | family?: 'material' | 'brightlayer-ui' | 'material-community'; 28 | direction?: 'rtl' | 'ltr' | 'auto'; 29 | allowFontScaling?: boolean; 30 | }; 31 | export type IconSourceBase = string | ImageSourcePropType; 32 | export type IconSource = IconFamily | IconSourceBase | JSX.Element | ComponentType; 33 | 34 | export type HeaderIcon = { 35 | /** Component to render for the icon */ 36 | icon: IconSource; 37 | 38 | /** Callback when icon is pressed */ 39 | onPress?: () => void; 40 | }; 41 | 42 | export type HeaderActionComponent = { 43 | component: JSX.Element; 44 | width?: number; 45 | }; 46 | 47 | export type EdgeInsets = { 48 | top: number; 49 | left: number; 50 | bottom: number; 51 | right: number; 52 | }; 53 | -------------------------------------------------------------------------------- /components/src/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ChannelValue'; 2 | export * from './ListItemTag'; 3 | export * from './Icon'; 4 | export * from './Overline'; 5 | export * from './EmptyState'; 6 | export * from './Hero'; 7 | export * from './HeroBanner'; 8 | export * from './InfoListItem'; 9 | export * from './Header'; 10 | export * from './MobileStepper'; 11 | export * from './Drawer'; 12 | export * from './UserMenu'; 13 | export * from './ScoreCard'; 14 | export * from './CollapsableHeaderLayout'; 15 | export * from './Utility'; 16 | export * from './Grade'; 17 | export * from './IconSwitch'; 18 | export * from './Chip'; 19 | export * from './AutoComplete'; 20 | -------------------------------------------------------------------------------- /components/src/images/default-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/components/src/images/default-avatar.png -------------------------------------------------------------------------------- /components/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2021-present, Eaton 3 | All rights reserved. 4 | This code is licensed under the BSD-3 license found in the LICENSE file in the root directory of this source tree and at https://opensource.org/licenses/BSD-3-Clause. 5 | **/ 6 | 7 | export * from './core'; 8 | -------------------------------------------------------------------------------- /components/src/types/svg.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | import { SvgProps } from 'react-native-svg'; 3 | const content: React.ComponentClass; // eslint-disable-line 4 | export default content; 5 | } 6 | -------------------------------------------------------------------------------- /components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "declaration": true, 5 | "esModuleInterop": true, 6 | "jsx": "react", 7 | "lib": ["es6"], 8 | "module": "commonjs", 9 | "moduleResolution": "node", 10 | "noEmit": false, 11 | "strict": true, 12 | "skipLibCheck": true, 13 | "target": "esnext" 14 | }, 15 | "include": ["src"] 16 | } 17 | -------------------------------------------------------------------------------- /components/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "outDir": "../dist", 5 | "declaration": true 6 | }, 7 | "exclude": [ 8 | "src/**/*.test.tsx" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /demos/api/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | extends: ['@brightlayer-ui/eslint-config/tsx', 'plugin:storybook/recommended'], 4 | parserOptions: { 5 | project: './tsconfig.json', 6 | }, 7 | env: { 8 | browser: true, 9 | jest: true, 10 | }, 11 | rules: { 12 | '@typescript-eslint/no-var-requires': 'off', 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /demos/api/.storybook/config.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { addDecorator, addParameters } from '@storybook/react'; 3 | import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'; 4 | import { blue as ReactThemes } from '@brightlayer-ui/react-themes'; 5 | import * as Colors from '@brightlayer-ui/colors'; 6 | import '@brightlayer-ui/react-themes/open-sans'; 7 | import { bluiTheme } from '@brightlayer-ui/storybook-themes'; 8 | import { CssBaseline } from '@material-ui/core'; 9 | 10 | bluiTheme.brandTitle = 'Brightlayer UI React Native Component Library'; 11 | bluiTheme.brandUrl = 'https://brightlayer-ui.github.io'; 12 | if (window.top.location.hostname === 'localhost') { 13 | bluiTheme.brandImage = require('../assets/brightlayer-ui-react-native-alpha.svg'); 14 | } else if (window.top.location.pathname.slice(0, 18) === '/react-native-dev/') { 15 | bluiTheme.brandImage = require('../assets/brightlayer-ui-react-native-beta.svg'); 16 | } else { 17 | bluiTheme.brandImage = require('../assets/brightlayer-ui-react-native.svg'); 18 | } 19 | 20 | addParameters({ 21 | /* Users will see this while the component is loading. */ 22 | notes: { 23 | markdown: '
', 24 | }, 25 | options: { 26 | theme: bluiTheme, 27 | showRoots: true, 28 | }, 29 | }); 30 | 31 | export const appliedTheme = createMuiTheme(ReactThemes); 32 | 33 | addDecorator((storyFn) => ( 34 | 35 | 36 |
37 | {storyFn()} 38 |
39 |
40 | )); 41 | -------------------------------------------------------------------------------- /demos/api/.storybook/main.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | 3 | module.exports = { 4 | stories: ['../stories/welcome.stories.tsx', '../stories/*.stories.tsx'], 5 | addons: ['@storybook/addon-notes'], 6 | 7 | docs: { 8 | autodocs: true, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /demos/api/.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 2 | 35 | -------------------------------------------------------------------------------- /demos/api/.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 3 | 4 | module.exports = ({ config }) => { 5 | config.module.rules.push({ 6 | test: /\.(ts|tsx)$/, 7 | use: [ 8 | { 9 | loader: require.resolve('awesome-typescript-loader'), 10 | }, 11 | ], 12 | }); 13 | config.module.rules.push({ 14 | test: /\.s[ac]ss$/i, 15 | use: [ 16 | // Creates `style` nodes from JS strings 17 | MiniCssExtractPlugin.loader, 18 | // Translates CSS into CommonJS 19 | 'css-loader', 20 | // Compiles Sass to CSS 21 | 'sass-loader', 22 | ], 23 | }); 24 | config.plugins.push(new MiniCssExtractPlugin({ filename: '[name].css' })); 25 | config.watchOptions = { ignored: [/node_modules([\\]+|\/)+(?!@pxblue)/] }; 26 | config.resolve.extensions.push('.ts', '.tsx'); 27 | return config; 28 | }; 29 | -------------------------------------------------------------------------------- /demos/api/README.md: -------------------------------------------------------------------------------- 1 | # Storybook Demo 2 | The storybook demo shows the API documentation for Brightlayer UI React Native components. 3 | 4 | To start the storybook demo, run from the root folder: 5 | 6 | `yarn start:storybook-api` 7 | -------------------------------------------------------------------------------- /demos/api/assets/brightlayer-ui-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 12 | -------------------------------------------------------------------------------- /demos/api/assets/brightlayer-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/api/assets/brightlayer-ui.png -------------------------------------------------------------------------------- /demos/api/assets/circles-bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /demos/api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "storybook", 3 | "version": "0.1.0", 4 | "private": true, 5 | "prettier": "@brightlayer-ui/prettier-config", 6 | "dependencies": { 7 | "@brightlayer-ui/colors": "^3.0.1", 8 | "@brightlayer-ui/icons-mui": "^2.8.1", 9 | "@brightlayer-ui/react-native-components": "latest", 10 | "@brightlayer-ui/react-themes": "^6.1.0", 11 | "@brightlayer-ui/storybook-themes": "^1.0.4", 12 | "@material-ui/core": "^4.7.2", 13 | "@material-ui/icons": "^4.5.1", 14 | "@sambego/storybook-state": "^1.3.6", 15 | "@storybook/addon-notes": "^5.3.13", 16 | "@storybook/addons": "^5.3.13", 17 | "@storybook/preset-create-react-app": "^1.5.2", 18 | "@storybook/react": "^5.3.13", 19 | "@storybook/theming": "^5.3.13", 20 | "react": "^16.11.0", 21 | "react-dom": "^16.11.0", 22 | "react-scripts": "3.2.0", 23 | "typescript": "^3.6.4" 24 | }, 25 | "scripts": { 26 | "start": "yarn storybook", 27 | "storybook": "export NODE_OPTIONS=--openssl-legacy-provider && start-storybook -p 6006 -s ../../docs/,./assets", 28 | "build-storybook": "export NODE_OPTIONS=--openssl-legacy-provider && build-storybook -s ../../docs/,./assets", 29 | "lint": "eslint \"stories/**\"", 30 | "lint:fix": "eslint \"stories/**\" --fix", 31 | "prettier": "prettier \"**/**.{ts,tsx,js,jsx,json,css,scss,html}\" --write", 32 | "prettier:check": "prettier \"**/**.{ts,tsx,js,jsx,json,css,scss,html}\" --check" 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.2%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | }, 46 | "devDependencies": { 47 | "@babel/core": "^7.8.3", 48 | "@brightlayer-ui/eslint-config": "^1.1.5", 49 | "@brightlayer-ui/prettier-config": "^1.0.3", 50 | "@types/node": "12.11.7", 51 | "@types/react": "16.9.11", 52 | "@types/react-dom": "16.9.3", 53 | "@typescript-eslint/eslint-plugin": "^3.0.0", 54 | "@typescript-eslint/parser": "^3.0.0", 55 | "awesome-typescript-loader": "^5.2.1", 56 | "css-loader": "^3.4.2", 57 | "eslint": "^6.8.0", 58 | "eslint-config-prettier": "^6.9.0", 59 | "eslint-plugin-react": "^7.17.0", 60 | "eslint-plugin-storybook": "^0.6.15", 61 | "mini-css-extract-plugin": "^0.7.0", 62 | "prettier": "^1.19.1", 63 | "sass-loader": "^8.0.2" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /demos/api/src/utils.ts: -------------------------------------------------------------------------------- 1 | export const updateTitle = (): void => { 2 | setTimeout(() => { 3 | window.top.document.title = 'Brightlayer UI | React Native Components'; 4 | }, 10); 5 | (function () { 6 | var link = window.top.document.querySelector("link[rel*='icon']") || document.createElement('link'); 7 | // @ts-ignore 8 | link.type = 'image/x-icon'; 9 | // @ts-ignore 10 | link.rel = 'shortcut icon'; 11 | // @ts-ignore 12 | link.href = './brightlayer-ui.png'; 13 | window.top.document.getElementsByTagName('head')[0].appendChild(link); 14 | })(); 15 | }; 16 | -------------------------------------------------------------------------------- /demos/api/stories/api.stories.tsx: -------------------------------------------------------------------------------- 1 | import { storiesOf } from '@storybook/react'; 2 | import { docFn, getReadMe } from './utils'; 3 | 4 | export const stories = storiesOf('Components/Documentation', module); 5 | 6 | stories.add('Channel Value', docFn, { notes: { markdown: getReadMe('ChannelValue.md') } }); 7 | stories.add('Chip', docFn, { notes: { markdown: getReadMe('Chip.md') } }); 8 | stories.add('Collapsible Header Layout', docFn, { notes: { markdown: getReadMe('CollapsibleHeaderLayout.md') } }); 9 | stories.add('Drawer', docFn, { notes: { markdown: getReadMe('Drawer.md') } }); 10 | stories.add('Empty State', docFn, { notes: { markdown: getReadMe('EmptyState.md') } }); 11 | stories.add('Grade', docFn, { notes: { markdown: getReadMe('Grade.md') } }); 12 | stories.add('Header', docFn, { notes: { markdown: getReadMe('Header.md') } }); 13 | stories.add('Hero', docFn, { notes: { markdown: getReadMe('Hero.md') } }); 14 | stories.add('Icons', docFn, { notes: { markdown: getReadMe('Icons.md') } }); 15 | stories.add('Icon Switch', docFn, { notes: { markdown: getReadMe('IconSwitch.md') } }); 16 | stories.add('Info List Item', docFn, { notes: { markdown: getReadMe('InfoListItem.md') } }); 17 | stories.add('List Item Tag', docFn, { notes: { markdown: getReadMe('ListItemTag.md') } }); 18 | stories.add('Mobile Stepper', docFn, { notes: { markdown: getReadMe('MobileStepper.md') } }); 19 | stories.add('Overline', docFn, { notes: { markdown: getReadMe('Overline.md') } }); 20 | stories.add('Score Card', docFn, { notes: { markdown: getReadMe('ScoreCard.md') } }); 21 | stories.add('Spacer', docFn, { notes: { markdown: getReadMe('Spacer.md') } }); 22 | stories.add('User Menu', docFn, { notes: { markdown: getReadMe('UserMenu.md') } }); 23 | -------------------------------------------------------------------------------- /demos/api/stories/utils.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ 2 | import React from 'react'; 3 | import { updateTitle } from '../src/utils'; 4 | 5 | const autoNavToDocs = (): void => { 6 | const banner = window.top.document.getElementsByClassName('simplebar-content')[1]; 7 | banner.setAttribute('style', 'display: none'); 8 | // If we are currently on the 'Canvas' tab. 9 | if (window.top.location.href.includes('/story/')) { 10 | window.top.history.replaceState(null, '', window.top.location.href.replace('/story/', '/info/')); 11 | 12 | // click the notes tab 13 | // @ts-ignore 14 | banner.children[0].children[0].children[0].children[1].click(); // eslint-disable-line @typescript-eslint/no-unsafe-call 15 | } 16 | updateTitle(); 17 | }; 18 | 19 | export const getReadMe = (name: string): { default: string } => { 20 | const md: { default: string } = require(`./../../../docs/${name}`) as { default: string }; 21 | 22 | // Locate all relative links that use href syntax and replace them with absolute URLs. 23 | md.default = md.default.replace(/\(.\/.*md\)/g, (substring: string) => { 24 | // Example: http://localhost:6006/?path=/info/components-hero--get-read-me-story 25 | const root = window.top.location.href.split('/?')[0]; 26 | const path = `?path=/info/components-documentation-`; 27 | 28 | // Get component from link. (./HeroBanner.md) => HeroBanner 29 | const component = substring.split('/')[1].split('.')[0]; 30 | // Storybook uses dash-limited-syntax in their URL schema. 31 | const dashed = component.replace(/\.?([A-Z])/g, (x) => `-${x.toLowerCase()}`); 32 | return `(${root}${path}${dashed})`; 33 | }); 34 | return md; 35 | }; 36 | 37 | export const docFn = (): JSX.Element => <>{autoNavToDocs()}; 38 | -------------------------------------------------------------------------------- /demos/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "react" 17 | }, 18 | "include": ["src", "stories"] 19 | } 20 | -------------------------------------------------------------------------------- /demos/storybook/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /demos/storybook/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | extends: ['@pxblue/eslint-config/tsx'], 4 | parserOptions: { 5 | project: './tsconfig.json', 6 | }, 7 | env: { 8 | browser: true, 9 | jest: true, 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /demos/storybook/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /demos/storybook/.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 | # Visual Studio Code 33 | # 34 | .vscode/ 35 | 36 | # node.js 37 | # 38 | node_modules/ 39 | npm-debug.log 40 | yarn-error.log 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 | 59 | # Bundle artifact 60 | *.jsbundle 61 | 62 | # CocoaPods 63 | /ios/Pods/ 64 | -------------------------------------------------------------------------------- /demos/storybook/.prettierignore: -------------------------------------------------------------------------------- 1 | ios/ 2 | android 3 | -------------------------------------------------------------------------------- /demos/storybook/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /demos/storybook/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /demos/storybook/__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: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /demos/storybook/android/app/_BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.storybook", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.storybook", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /demos/storybook/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /demos/storybook/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/debug.keystore -------------------------------------------------------------------------------- /demos/storybook/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 | -------------------------------------------------------------------------------- /demos/storybook/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/storybook/android/app/src/debug/java/com/storybook/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its 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.storybook; 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.react.ReactFlipperPlugin; 21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 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 | public class ReactNativeFlipper { 28 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 29 | if (FlipperUtils.shouldEnableFlipper(context)) { 30 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 31 | 32 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 33 | client.addPlugin(new ReactFlipperPlugin()); 34 | client.addPlugin(new DatabasesFlipperPlugin(context)); 35 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 36 | client.addPlugin(CrashReporterPlugin.getInstance()); 37 | 38 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 39 | NetworkingModule.setCustomClientBuilder( 40 | new NetworkingModule.CustomClientBuilder() { 41 | @Override 42 | public void apply(OkHttpClient.Builder builder) { 43 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 44 | } 45 | }); 46 | client.addPlugin(networkFlipperPlugin); 47 | client.start(); 48 | 49 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 50 | // Hence we run if after all native modules have been initialized 51 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 52 | if (reactContext == null) { 53 | reactInstanceManager.addReactInstanceEventListener( 54 | new ReactInstanceManager.ReactInstanceEventListener() { 55 | @Override 56 | public void onReactContextInitialized(ReactContext reactContext) { 57 | reactInstanceManager.removeReactInstanceEventListener(this); 58 | reactContext.runOnNativeModulesQueueThread( 59 | new Runnable() { 60 | @Override 61 | public void run() { 62 | client.addPlugin(new FrescoFlipperPlugin()); 63 | } 64 | }); 65 | } 66 | }); 67 | } else { 68 | client.addPlugin(new FrescoFlipperPlugin()); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/AntDesign.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/AntDesign.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/Entypo.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/EvilIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/EvilIcons.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/Feather.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/Feather.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/Fontisto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/Fontisto.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/Foundation.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/Foundation.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/Ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/Ionicons.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/MaterialIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/MaterialIcons.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/Octicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/Octicons.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/OpenSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/OpenSans-ExtraBold.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/OpenSans-Light.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/OpenSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/OpenSans-SemiBold.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/SimpleLineIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/SimpleLineIcons.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/assets/fonts/Zocial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/assets/fonts/Zocial.ttf -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/java/com/storybook/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.storybook; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. This is used to schedule 9 | * rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "storybook"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/java/com/storybook/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.storybook; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactInstanceManager; 8 | import com.facebook.react.ReactNativeHost; 9 | import com.facebook.react.ReactPackage; 10 | import com.facebook.soloader.SoLoader; 11 | import java.lang.reflect.InvocationTargetException; 12 | import java.util.List; 13 | 14 | public class MainApplication extends Application implements ReactApplication { 15 | 16 | private final ReactNativeHost mReactNativeHost = 17 | new ReactNativeHost(this) { 18 | @Override 19 | public boolean getUseDeveloperSupport() { 20 | return BuildConfig.DEBUG; 21 | } 22 | 23 | @Override 24 | protected List getPackages() { 25 | @SuppressWarnings("UnnecessaryLocalVariable") 26 | List packages = new PackageList(this).getPackages(); 27 | // Packages that cannot be autolinked yet can be added manually here, for example: 28 | // packages.add(new MyReactNativePackage()); 29 | return packages; 30 | } 31 | 32 | @Override 33 | protected String getJSMainModuleName() { 34 | return "index"; 35 | } 36 | }; 37 | 38 | @Override 39 | public ReactNativeHost getReactNativeHost() { 40 | return mReactNativeHost; 41 | } 42 | 43 | @Override 44 | public void onCreate() { 45 | super.onCreate(); 46 | SoLoader.init(this, /* native exopackage */ false); 47 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 48 | } 49 | 50 | /** 51 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like 52 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 53 | * 54 | * @param context 55 | * @param reactInstanceManager 56 | */ 57 | private static void initializeFlipper( 58 | Context context, ReactInstanceManager reactInstanceManager) { 59 | if (BuildConfig.DEBUG) { 60 | try { 61 | /* 62 | We use reflection here to pick up the class that initializes Flipper, 63 | since Flipper library is not available in release mode 64 | */ 65 | Class aClass = Class.forName("com.storybook.ReactNativeFlipper"); 66 | aClass 67 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 68 | .invoke(null, context, reactInstanceManager); 69 | } catch (ClassNotFoundException e) { 70 | e.printStackTrace(); 71 | } catch (NoSuchMethodException e) { 72 | e.printStackTrace(); 73 | } catch (IllegalAccessException e) { 74 | e.printStackTrace(); 75 | } catch (InvocationTargetException e) { 76 | e.printStackTrace(); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | storybook 3 | 4 | -------------------------------------------------------------------------------- /demos/storybook/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /demos/storybook/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 = "28.0.3" 6 | minSdkVersion = 21 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | } 10 | repositories { 11 | google() 12 | jcenter() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle:3.5.2") 16 | 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | mavenLocal() 25 | maven { 26 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 27 | url("$rootDir/../node_modules/react-native/android") 28 | } 29 | maven { 30 | // Android JSC is installed from npm 31 | url("$rootDir/../node_modules/jsc-android/dist") 32 | } 33 | 34 | google() 35 | jcenter() 36 | maven { url 'https://www.jitpack.io' } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demos/storybook/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: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 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.33.1 29 | -------------------------------------------------------------------------------- /demos/storybook/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /demos/storybook/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /demos/storybook/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 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /demos/storybook/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'storybook' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /demos/storybook/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "storybook", 3 | "displayName": "storybook" 4 | } 5 | -------------------------------------------------------------------------------- /demos/storybook/assets/fonts/OpenSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/assets/fonts/OpenSans-Bold.ttf -------------------------------------------------------------------------------- /demos/storybook/assets/fonts/OpenSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/assets/fonts/OpenSans-ExtraBold.ttf -------------------------------------------------------------------------------- /demos/storybook/assets/fonts/OpenSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/assets/fonts/OpenSans-Light.ttf -------------------------------------------------------------------------------- /demos/storybook/assets/fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/assets/fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /demos/storybook/assets/fonts/OpenSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/assets/fonts/OpenSans-SemiBold.ttf -------------------------------------------------------------------------------- /demos/storybook/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /demos/storybook/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import { AppRegistry, LogBox } from 'react-native'; 6 | import App from './storybook'; 7 | import { name as appName } from './app.json'; 8 | 9 | LogBox.ignoreAllLogs(true); 10 | 11 | AppRegistry.registerComponent(appName, () => App); 12 | -------------------------------------------------------------------------------- /demos/storybook/ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '10.0' 2 | require_relative '../node_modules/react-native/scripts/react_native_pods' 3 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 4 | 5 | target 'storybook' do 6 | config = use_native_modules! 7 | 8 | use_react_native!( 9 | :path => config[:reactNativePath], 10 | # to enable hermes on iOS, change `false` to `true` and then install pods 11 | :hermes_enabled => false 12 | ) 13 | 14 | target 'storybookTests' do 15 | inherit! :complete 16 | # Pods for testing 17 | end 18 | 19 | # Enables Flipper. 20 | 21 | # Note that if you have use_frameworks! enabled, Flipper will not work and 22 | # you should disable these next few lines. 23 | use_flipper!() 24 | 25 | post_install do |installer| 26 | react_native_post_install(installer) 27 | end 28 | end -------------------------------------------------------------------------------- /demos/storybook/ios/storybook-tvOS/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 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 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 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | #import 6 | 7 | #if DEBUG 8 | #import 9 | #import 10 | #import 11 | #import 12 | #import 13 | #import 14 | 15 | static void InitializeFlipper(UIApplication *application) { 16 | FlipperClient *client = [FlipperClient sharedClient]; 17 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; 18 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; 19 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; 20 | [client addPlugin:[FlipperKitReactPlugin new]]; 21 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; 22 | [client start]; 23 | } 24 | #endif 25 | 26 | @implementation AppDelegate 27 | 28 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 29 | { 30 | #if DEBUG 31 | InitializeFlipper(application); 32 | #endif 33 | 34 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 35 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 36 | moduleName:@"storybook" 37 | initialProperties:nil]; 38 | 39 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 40 | 41 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 42 | UIViewController *rootViewController = [UIViewController new]; 43 | rootViewController.view = rootView; 44 | self.window.rootViewController = rootViewController; 45 | [self.window makeKeyAndVisible]; 46 | return YES; 47 | } 48 | 49 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 50 | { 51 | #if DEBUG 52 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 53 | #else 54 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 55 | #endif 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | storybook 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 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UIViewControllerBasedStatusBarAppearance 55 | 56 | UIAppFonts 57 | 58 | OpenSans-Bold.ttf 59 | OpenSans-ExtraBold.ttf 60 | OpenSans-Light.ttf 61 | OpenSans-Regular.ttf 62 | OpenSans-SemiBold.ttf 63 | AntDesign.ttf 64 | Entypo.ttf 65 | EvilIcons.ttf 66 | Feather.ttf 67 | FontAwesome.ttf 68 | FontAwesome5_Brands.ttf 69 | FontAwesome5_Regular.ttf 70 | FontAwesome5_Solid.ttf 71 | Fontisto.ttf 72 | Foundation.ttf 73 | Ionicons.ttf 74 | MaterialCommunityIcons.ttf 75 | MaterialIcons.ttf 76 | Octicons.ttf 77 | SimpleLineIcons.ttf 78 | Zocial.ttf 79 | PXBlueIcons.ttf 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybook/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybookTests/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 | -------------------------------------------------------------------------------- /demos/storybook/ios/storybookTests/storybookTests.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 storybookTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation storybookTests 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(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 38 | if (level >= RCTLogLevelError) { 39 | redboxError = message; 40 | } 41 | }); 42 | #endif 43 | 44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | 48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 50 | return YES; 51 | } 52 | return NO; 53 | }]; 54 | } 55 | 56 | #ifdef DEBUG 57 | RCTSetLogFunction(RCTDefaultLogFunction); 58 | #endif 59 | 60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /demos/storybook/metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig } = require('metro-config'); 2 | 3 | module.exports = (async () => { 4 | const { 5 | resolver: { sourceExts, assetExts }, 6 | } = await getDefaultConfig(); 7 | return { 8 | transformer: { 9 | babelTransformerPath: require.resolve('react-native-svg-transformer'), 10 | }, 11 | resolver: { 12 | assetExts: assetExts.filter((ext) => ext !== 'svg'), 13 | sourceExts: [...sourceExts, 'svg'], 14 | }, 15 | }; 16 | })(); 17 | -------------------------------------------------------------------------------- /demos/storybook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "storybook", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "start": "react-native start", 9 | "build": "react-native bundle --entry-file=index.js --bundle-output=build.bundle", 10 | "test": "echo \"Tests not configured yet.\"", 11 | "lint": "eslint \"**/**.{ts,tsx}\"", 12 | "lint:fix": "eslint \"**/**.{ts,tsx}\" --fix", 13 | "prettier": "prettier \"**/**.{ts,tsx,js,jsx,json,css,scss,html}\" --write", 14 | "prettier:check": "prettier \"**/**.{ts,tsx,js,jsx,json,css,scss,html}\" --check", 15 | "rnlink": "react-native link" 16 | }, 17 | "dependencies": { 18 | "@pxblue/colors": "^3.0.0", 19 | "@pxblue/icons-svg": "^1.2.0", 20 | "@pxblue/react-native-components": "^6.0.0", 21 | "@pxblue/react-native-progress-icons": "^1.0.2", 22 | "@pxblue/react-native-themes": "6.0.0", 23 | "@pxblue/react-native-vector-icons": "^1.0.0", 24 | "react": "^16.11.0", 25 | "react-native": "~0.64.0", 26 | "react-native-paper": "^4.7.1", 27 | "react-native-safe-area-context": "^3.0.0", 28 | "react-native-svg": "^12.1.0", 29 | "react-native-svg-transformer": "^0.14.3", 30 | "react-native-vector-icons": "^8.0.0" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.6.2", 34 | "@babel/runtime": "^7.6.2", 35 | "@pxblue/eslint-config": "^2.0.4", 36 | "@pxblue/prettier-config": "^1.0.2", 37 | "@storybook/addon-actions": "^5.2.3", 38 | "@storybook/addon-knobs": "^5.1.9", 39 | "@storybook/addon-links": "^5.2.3", 40 | "@storybook/addon-ondevice-knobs": "^5.1.9", 41 | "@storybook/addon-ondevice-notes": "^5.1.9", 42 | "@storybook/addons": "^5.2.3", 43 | "@storybook/react-native": "^5.3.19", 44 | "@types/color": "^3.0.0", 45 | "@types/faker": "^4.1.5", 46 | "@types/jest": "^25.0.0", 47 | "@types/lodash": "^4.14.136", 48 | "@types/react": "^16.8.23", 49 | "@types/react-native": "^0.63.0", 50 | "@types/react-native-material-textfield": "^0.12.3", 51 | "@types/react-native-vector-icons": "^6.4.6", 52 | "@types/react-test-renderer": "16.9.2", 53 | "@types/storybook__addon-actions": "^3.4.3", 54 | "@types/storybook__addon-links": "^3.3.5", 55 | "@types/storybook__react": "^4.0.2", 56 | "@types/storybook__react-native": "^3.0.5", 57 | "@typescript-eslint/eslint-plugin": "^3.0.2", 58 | "@typescript-eslint/parser": "^3.0.2", 59 | "babel-jest": "^25.0.0", 60 | "eslint": "^7.11.0", 61 | "eslint-config-prettier": "^6.11.0", 62 | "eslint-plugin-react": "^7.20.0", 63 | "jest": "^26.0.1", 64 | "metro-react-native-babel-preset": "^0.58.0", 65 | "prettier": "^2.0.5", 66 | "react-test-renderer": "^16.13.1", 67 | "typescript": "^3.8.3" 68 | }, 69 | "jest": { 70 | "preset": "react-native", 71 | "moduleFileExtensions": [ 72 | "ts", 73 | "tsx", 74 | "js", 75 | "jsx", 76 | "json", 77 | "node" 78 | ] 79 | }, 80 | "prettier": "@pxblue/prettier-config" 81 | } 82 | -------------------------------------------------------------------------------- /demos/storybook/react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | assets: ['./assets/fonts/'], 3 | }; 4 | -------------------------------------------------------------------------------- /demos/storybook/storybook/addons.ts: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | import '@storybook/addon-links/register'; 3 | -------------------------------------------------------------------------------- /demos/storybook/storybook/assets/eatonLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/storybook/assets/eatonLogo.png -------------------------------------------------------------------------------- /demos/storybook/storybook/assets/farm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/storybook/assets/farm.jpg -------------------------------------------------------------------------------- /demos/storybook/storybook/assets/test-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/demos/storybook/storybook/assets/test-avatar.png -------------------------------------------------------------------------------- /demos/storybook/storybook/decorators/index.tsx: -------------------------------------------------------------------------------- 1 | import { SafeAreaView, View } from 'react-native'; 2 | import React from 'react'; 3 | 4 | type AnyFunction = () => any; 5 | export const centered = (storyFn: AnyFunction): JSX.Element => ( 6 | {storyFn()} 7 | ); 8 | 9 | export const padded = (storyFn: AnyFunction): JSX.Element => ( 10 | 19 | {storyFn()} 20 | 21 | ); 22 | 23 | export const framedRow = (storyFn: AnyFunction): JSX.Element => ( 24 | 25 | 26 | {storyFn()} 27 | 28 | 29 | ); 30 | 31 | export const safeArea = (storyFn: AnyFunction): JSX.Element => {storyFn()}; 32 | -------------------------------------------------------------------------------- /demos/storybook/storybook/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { getStorybookUI, configure } from '@storybook/react-native'; 3 | import { Provider as ThemeProvider } from 'react-native-paper'; 4 | import * as PXBThemes from '@pxblue/react-native-themes'; 5 | import './rn-addons'; 6 | import { SafeAreaProvider } from 'react-native-safe-area-context'; 7 | 8 | // import stories 9 | configure(() => { 10 | require('./stories'); 11 | }, module); 12 | 13 | // Refer to https://github.com/storybookjs/storybook/tree/master/app/react-native#start-command-parameters 14 | // To find allowed options for getStorybookUI 15 | const StorybookUIRoot = getStorybookUI({}); 16 | 17 | const ThemedStorybook = (): JSX.Element => ( 18 | 19 | 20 | 21 | 22 | 23 | ); 24 | 25 | export default ThemedStorybook; 26 | -------------------------------------------------------------------------------- /demos/storybook/storybook/rn-addons.ts: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-ondevice-knobs/register'; 2 | import '@storybook/addon-ondevice-notes/register'; 3 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/channel-value.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react-native'; 3 | import { View } from 'react-native'; 4 | import { ChannelValue } from '@pxblue/react-native-components'; 5 | import { text, withKnobs, boolean, color, number, select } from '@storybook/addon-knobs'; 6 | import * as Colors from '@pxblue/colors'; 7 | import { IconFamily } from '@pxblue/react-native-components/core/__types__'; 8 | 9 | const notes = { 10 | notes: 'Any React Element may be passed in as `icon`; if using an svg, its color and size are not controlled by `ChannelValue`', 11 | }; 12 | 13 | const WrappedTrending: IconFamily = { name: 'trending-up' }; 14 | 15 | storiesOf('ChannelValue', module) 16 | .addDecorator(withKnobs) 17 | .add( 18 | 'with basic usage', 19 | () => ( 20 | 21 | 22 | 23 | ), 24 | notes 25 | ) 26 | .add( 27 | 'with units', 28 | () => ( 29 | 30 | 31 | 32 | ), 33 | notes 34 | ) 35 | .add( 36 | 'with icon', 37 | () => ( 38 | 39 | 45 | 46 | ), 47 | notes 48 | ) 49 | .add( 50 | 'with fontSize', 51 | () => ( 52 | 53 | 60 | 61 | ), 62 | notes 63 | ) 64 | .add( 65 | 'with full config', 66 | () => ( 67 | 68 | 78 | 79 | ), 80 | notes 81 | ); 82 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/collapsible-header-layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react-native'; 3 | import { number, withKnobs } from '@storybook/addon-knobs'; 4 | import { CollapsibleHeaderLayout } from '@pxblue/react-native-components'; 5 | 6 | const MailIcon: IconFamily = { name: 'mail' }; 7 | const MenuIcon: IconFamily = { name: 'menu' }; 8 | const MoreIcon: IconFamily = { name: 'more-vert' }; 9 | const CloudIcon: IconFamily = { name: 'cloud-upload' }; 10 | import { Text, View } from 'react-native'; 11 | import { IconFamily } from '@pxblue/react-native-components/core/__types__'; 12 | 13 | storiesOf('CollapsibleHeaderLayout', module) 14 | .addDecorator(withKnobs) 15 | .add('with basic usage', () => ( 16 | { 22 | /* do nothing */ 23 | }, 24 | actionItems: [ 25 | { 26 | icon: MailIcon, 27 | onPress: (): void => { 28 | /* do nothing */ 29 | }, 30 | }, 31 | { 32 | icon: CloudIcon, 33 | onPress: (): void => { 34 | /* do nothing */ 35 | }, 36 | }, 37 | { 38 | icon: MoreIcon, 39 | onPress: (): void => { 40 | /* do nothing */ 41 | }, 42 | }, 43 | ], 44 | variant: 'dynamic', 45 | expandable: true, 46 | startExpanded: true, 47 | expandedHeight: number('expandedHeight', 200, { range: true, min: 100, max: 500, step: 10 }), 48 | collapsedHeight: number('collapsedHeight', 56, { range: true, min: 50, max: 100, step: 5 }), 49 | }} 50 | > 51 | 52 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque faucibus nulla ut hendrerit 53 | imperdiet. Donec vel sapien venenatis, hendrerit quam sed, varius arcu. Pellentesque habitant morbi 54 | tristique senectus et netus et malesuada fames ac turpis egestas. Cras mollis lobortis ipsum, ut 55 | ullamcorper turpis eleifend vitae. Pellentesque ac sagittis ex, sed gravida turpis. Aliquam finibus 56 | consectetur dui quis cursus. Morbi ut enim quis dolor mollis pharetra id quis ligula. Nam vitae gravida 57 | odio. Donec neque erat, tincidunt suscipit ligula non, egestas vestibulum neque. Vestibulum feugiat in 58 | arcu at mollis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum at risus eu urna 59 | porta iaculis. Donec consequat at eros consectetur faucibus. Maecenas venenatis purus vitae ultricies 60 | ultricies. Quisque volutpat neque ac nibh pulvinar, et mollis nunc efficitur. 61 | 62 | 63 | 64 | )); 65 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/collapsible-section.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react-native'; 3 | import { View, StyleSheet } from 'react-native'; 4 | import { text, withKnobs, color } from '@storybook/addon-knobs'; 5 | import Leaf from '@pxblue/icons-svg/leaf.svg'; 6 | import { safeArea } from '../decorators'; 7 | import { CollapsibleSection } from '@pxblue/react-native-components'; 8 | import { red, blue } from '@pxblue/colors'; 9 | 10 | const styles = StyleSheet.create({ 11 | contentContainer: { 12 | height: 200, 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | }, 16 | }); 17 | 18 | storiesOf('CollapsibleSection', module) 19 | .addDecorator(withKnobs) 20 | .addDecorator(safeArea) 21 | .add('With a big icon', () => ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 36 | 37 | 38 | 39 | 40 | 41 | )); 42 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/empty-state.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react-native'; 3 | import { EmptyState } from '@pxblue/react-native-components'; 4 | import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; 5 | import { boolean, text, withKnobs } from '@storybook/addon-knobs'; 6 | import { ImageBackground } from 'react-native'; 7 | import { Button } from 'react-native-paper'; 8 | import * as Colors from '@pxblue/colors'; 9 | import { IconFamily } from '@pxblue/react-native-components/core/__types__'; 10 | const NoLocation: IconFamily = { name: 'not-listed-location' }; 11 | const LocationOff: IconFamily = { name: 'location-off' }; 12 | const Devices: IconFamily = { name: 'devices' }; 13 | const TrendingUp: IconFamily = { name: 'trending-up' }; 14 | 15 | storiesOf('EmptyState', module) 16 | .addDecorator(withKnobs) 17 | .add('with basic usage', () => ) 18 | .add('with description', () => ( 19 | 24 | )) 25 | .add('with actions', () => ( 26 | } 34 | > 35 | {text('button title', 'Add Device')} 36 | 37 | } 38 | /> 39 | )) 40 | .add('with full config', () => ( 41 | 52 | {text('button title', 'Learn More')}} 57 | /> 58 | 59 | )); 60 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/index.ts: -------------------------------------------------------------------------------- 1 | // import './bucket-view'; 2 | import './channel-value'; 3 | import './collapsible-header-layout'; 4 | import './drawer'; 5 | import './empty-state'; 6 | // import './collapsible-section'; 7 | import './header'; 8 | import './hero'; 9 | import './info-list-item'; 10 | import './list-item-tag'; 11 | import './mobile-stepper'; 12 | // import './layout-view'; 13 | import './score-card'; 14 | // import './search-screen'; 15 | import './spacer'; 16 | import './user-menu'; 17 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/info-list-item/index.ts: -------------------------------------------------------------------------------- 1 | import './info-list-item'; 2 | import './info-list'; 3 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/layout-view/index.ts: -------------------------------------------------------------------------------- 1 | import './layout-view'; 2 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/list-item-tag.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View } from 'react-native'; 3 | import { storiesOf } from '@storybook/react-native'; 4 | import { ListItemTag, InfoListItem } from '@pxblue/react-native-components'; 5 | import { withKnobs, color, text } from '@storybook/addon-knobs'; 6 | import { padded } from '../decorators'; 7 | import * as Colors from '@pxblue/colors'; 8 | import { IconFamily } from '@pxblue/react-native-components/core/__types__'; 9 | 10 | const notes = { 11 | notes: 'A text item with a colored background and rounded corners that is used to tag lists.', 12 | }; 13 | 14 | const Build: IconFamily = { name: 'build' }; 15 | 16 | storiesOf('ListItemTag', module) 17 | .addDecorator(withKnobs) 18 | .addDecorator(padded) 19 | .add('with basic usage', () => , notes) 20 | .add( 21 | 'with full config', 22 | () => ( 23 | 28 | ), 29 | notes 30 | ) 31 | .add( 32 | 'within an Info List Item', 33 | () => ( 34 | 35 | 36 | 46 | } 47 | /> 48 | 49 | 50 | ), 51 | notes 52 | ); 53 | -------------------------------------------------------------------------------- /demos/storybook/storybook/stories/search-screen.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react-native'; 3 | import { SearchScreen, InfoListItem } from '@pxblue/react-native-components'; 4 | import { View } from 'react-native'; 5 | import { blue, green, white } from '@pxblue/colors'; 6 | import Flow from '@pxblue/icons-svg/flow.svg'; 7 | import Apple from '@pxblue/icons-svg/apple.svg'; 8 | import { InfoListItemProps } from '@pxblue/react-native-components/dist/info-list-item/info-list-item'; 9 | import * as _ from 'lodash'; 10 | import faker from 'faker'; 11 | 12 | const Separator: React.FunctionComponent = () => ( 13 | 14 | ); 15 | 16 | const createInfoListItemProps = (): InfoListItemProps => { 17 | let subtitle: InfoListItemProps['subtitle']; 18 | let color: InfoListItemProps['color']; 19 | let icon: InfoListItemProps['icon']; 20 | let onPress: InfoListItemProps['onPress']; 21 | 22 | const subtitleNumber = Math.random(); 23 | if (subtitleNumber < 0.3) { 24 | subtitle = faker.lorem.sentence(); 25 | } else if (subtitleNumber < 0.6) { 26 | subtitle = [faker.lorem.word(), faker.lorem.word(), faker.lorem.word()]; 27 | } else if (subtitleNumber < 0.9) { 28 | subtitle = [, 'GPM']; 29 | } 30 | 31 | const colorNumber = Math.random(); 32 | if (colorNumber < 0.35) { 33 | color = green[700]; 34 | } else if (colorNumber < 0.7) { 35 | color = blue[700]; 36 | } 37 | 38 | if (Math.random() < 0.7) { 39 | icon = ; 40 | } 41 | 42 | if (Math.random() < 0.5) { 43 | onPress = (): void => { 44 | /* do nothing */ 45 | }; 46 | } 47 | 48 | return { 49 | title: faker.lorem.word(), 50 | subtitle, 51 | color, 52 | icon, 53 | onPress, 54 | }; 55 | }; 56 | 57 | const data: InfoListItemProps[] = _.range(100).map(createInfoListItemProps); 58 | 59 | storiesOf('Search Screen', module).add('search info list items', () => ( 60 | 61 | filterPredicate={(value: any, query: string): boolean => 62 | value.title.toLowerCase().startsWith(query.toLowerCase()) 63 | } 64 | headerProps={{ 65 | expandable: true, 66 | title: 'Info List', 67 | navigation: { 68 | icon: 'menu', 69 | onPress: (): void => { 70 | /* do nothing */ 71 | }, 72 | }, 73 | actionItems: [ 74 | { 75 | icon: 'more-vert', 76 | onPress: (): void => { 77 | /* do nothing */ 78 | }, 79 | }, 80 | ], 81 | backgroundColor: blue[500], 82 | fontColor: white[500], 83 | searchableConfig: { 84 | placeholder: 'Search', 85 | autoFocus: true, 86 | }, 87 | }} 88 | flatListProps={{ 89 | data: data, 90 | //eslint-disable-next-line react/display-name 91 | renderItem: (item: any): JSX.Element => , 92 | ItemSeparatorComponent: Separator, 93 | }} 94 | /> 95 | )); 96 | -------------------------------------------------------------------------------- /docs/ChannelValue.md: -------------------------------------------------------------------------------- 1 | # Channel Value 2 | 3 | The `` component is used to display a channel value (and units). This component abstracts the styles used to display the channel and units as well as an optional inline icon. These are used as part of the [Hero](./Hero.md) component, but can also be used inline (e.g., in a list) 4 | 5 | Channel Value component 6 | 7 | ## Usage 8 | 9 | ```tsx 10 | import { ChannelValue } from '@brightlayer-ui/react-native-components'; 11 | 12 | ; 13 | ``` 14 | 15 | ## API 16 | 17 |

18 | 19 | | Prop Name | Description | Type | Required | Default | 20 | | ----------- | --------------------------------------------------- | -------------------------------- | -------- | ------------------------ | 21 | | value | Text to display for the value | `string` \| `number` | yes | | 22 | | icon | A component to render for the icon | [`IconSource`](./Icons.md) | no | | 23 | | iconSize | The size to render the icon | `number` | no | `fontSize` | 24 | | iconColor | A component to render for the icon | `string` | no | `theme.colors.onSurface` | 25 | | units | Text to display for the units | `string` | no | | 26 | | unitSpace\* | Whether to show a space between the value and units | `'show'` \| `'hide'` \| `'auto'` | no | `'auto'` | 27 | | prefix | If true, shows units before the value | `boolean` | no | `false` | 28 | | fontSize | The size used for the text elements | `number` | no | 'medium' | 29 | | color | The color used for the text elements | `string` | no | `theme.colors.onSurface` | 30 | | theme | Theme value overrides | `$DeepPartial` | no | | 31 | 32 |
33 | 34 | Any other props will be provided to the root element ([**View**](https://reactnative.dev/docs/view)). 35 | 36 | > \*Setting `unitSpace` to `'auto'` will show a space for all units except for '%', '℉', '°F', '℃', '°C', and '°'. When `prefix` is true, the space will be shown for all units except for '$'. 37 | 38 | ### Styles 39 | 40 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following keys: 41 | 42 | | Name | Description | 43 | | ----- | ----------------------------------- | 44 | | root | Styles applied to the root element | 45 | | units | Styles applied to the units element | 46 | | value | Styles applied to the value element | 47 | -------------------------------------------------------------------------------- /docs/Chip.md: -------------------------------------------------------------------------------- 1 | # Chip 2 | 3 | The Chip component is a customizable [chip](https://callstack.github.io/react-native-paper/docs/components/Chip/)-based component that makes the chip component in alignment to BrightlayerUI. Chips are compact elements that can represent inputs, attributes, or actions. They can have an icon or avatar on the left, and a close button icon on the right. 4 | 5 | Chipcomponent 6 | 7 | ## Usage 8 | 9 | ```tsx 10 | import { Chip } from '@brightlayer-ui/react-native-components'; 11 | 12 | Unselect ; 13 | Select; 14 | ``` 15 | 16 | ### Chip API 17 | 18 | | Prop Name | Description | Type | Required | Default | 19 | | ----------- | ---------------------------------- | ----------------------------- | -------- | ------- | 20 | | chipColor | The color of the chip | `string` | no | | 21 | | textColor | The color of the text label | `string` | no | | 22 | | iconColor | The color of the icon | `string` | no | | 23 | | borderColor | The color of border color | `string` | no | | 24 | | icon | A component to render for the icon | [`IconSource`](./Icons.md) | no | | 25 | | mode | The size of the circle in px | `string` | no | | 26 | | avatar | Avatar to display in chip | `React.ReactNode` | no | | 27 | | theme | Theme value overrides | `$DeepPartial` | no | | 28 | 29 | Other Props of chip can be found at [Chip Props](https://callstack.github.io/react-native-paper/docs/components/Chip/) 30 | 31 | ### Styles 32 | 33 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following keys: 34 | 35 | | Name | Description | 36 | | ---- | ---------------------------------- | 37 | | root | Styles applied to the root element | 38 | -------------------------------------------------------------------------------- /docs/EmptyState.md: -------------------------------------------------------------------------------- 1 | # Empty State 2 | 3 | The `` component is an element that can be used as a placeholder when no data is present (such as an empty list, or a placeholder page for future content). This is only used when no data is available, rather than during loading (see [empty states pattern](https://brightlayer-ui.github.io/patterns/empty-states)). 4 | 5 | Empty state with all props 6 | 7 | ## Usage 8 | 9 | ```tsx 10 | import { EmptyState } from '@brightlayer-ui/react-native-components'; 11 | 12 | ; 17 | ``` 18 | 19 | ## API 20 | 21 |
22 | 23 | | Prop Name | Description | Type | Required | Default | 24 | | ----------- | ---------------------------------------------- | ----------------------------- | -------- | ----------------------- | 25 | | title | The primary text to display (first line) | `ReactNode` | yes | | 26 | | description | The secondary text to display (second line) | `ReactNode` | no | | 27 | | icon | A component to render for the primary icon | [`IconSource`](./Icons.md) | no | | 28 | | iconSize | The size of the primary icon (100-200) | `number` | no | 100 | 29 | | iconColor | The color of the primary icon | `string` | no | `theme.colors.disabled` | 30 | | actions | Additional components to render below the text | `JSX.Element` | no | | 31 | | theme | Theme value overrides | `$DeepPartial` | no | | 32 | 33 |
34 | 35 | Any other props will be provided to the root element ([**View**](https://reactnative.dev/docs/view)). 36 | 37 | ### Styles 38 | 39 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following keys: 40 | 41 | | Name | Description | 42 | | ----------- | ----------------------------------------- | 43 | | root | Styles applied to the root element | 44 | | title | Styles applied to the title element | 45 | | description | Styles applied to the description element | 46 | | actions | Styles applied to the actions element | 47 | -------------------------------------------------------------------------------- /docs/Grade.md: -------------------------------------------------------------------------------- 1 | # Grade 2 | 3 | The Grade component is a customizable [avatar](https://callstack.github.io/react-native-paper/4.0/avatar-text.html)-based component that represents different grades. It allows you to display a label with a specified background color and font color. 4 | 5 | Gradecomponent 6 | 7 | ## Usage 8 | 9 | ```tsx 10 | import { Grade } from '@brightlayer-ui/react-native-components'; 11 | 12 | ; 13 | ``` 14 | 15 | ### Grade API 16 | 17 | | Prop Name | Description | Type | Required | Default | 18 | | --------------- | ---------------------------------- | ----------------------------- | -------- | ------------------------ | 19 | | label | The text shown in the circle | `string` | yes | | 20 | | fontColor | The color of the text label | `string` | no | `theme.colors.onPrimary` | 21 | | backgroundColor | The background color of the circle | `string` | no | `theme.colors.primary` | 22 | | size | The size of the circle in px | `number` | no | 40 | 23 | | theme | Theme value overrides | `$DeepPartial` | no | | 24 | 25 | Any other props will be provided to the root element ([**View**](https://reactnative.dev/docs/view)). 26 | 27 | ## Grade Subcomponent 28 | 29 | The subcomponents are a set of preconfigured components that can be used directly for specific grades with in-built styling. 30 | 31 | grade subcomponent 32 | 33 | ### Grade Subcomponents Usage 34 | 35 | ```tsx 36 | import Grade from '@brightlayer-ui/react-native-components'; 37 | 38 | {/* Renders A+ grade */} 39 | {/* Renders A grade */} 40 | {/* Renders A- grade */} 41 | {/* Renders B+ grade */} 42 | {/* Renders B grade */} 43 | {/* Renders B- grade */} 44 | {/* Renders C+ grade */} 45 | {/* Renders C grade */} 46 | {/* Renders C- grade */} 47 | {/* Renders D+ grade */} 48 | {/* Renders D grade */} 49 | {/* Renders D- grade */} 50 | {/* Renders F grade */} 51 | ``` 52 | 53 | ### Grade Subcomponents API 54 | 55 | All Grade Subcomponents have the following Props 56 | 57 | | Prop Name | Description | Type | Required | Default | 58 | | --------- | ------------------- | -------- | -------- | ------- | 59 | | size | The radius of Grade | `number` | No | 40 | 60 | 61 | ### Styles 62 | 63 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following keys: 64 | 65 | | Name | Description | 66 | | ---- | ---------------------------------- | 67 | | root | Styles applied to the root element | 68 | -------------------------------------------------------------------------------- /docs/IconSwitch.md: -------------------------------------------------------------------------------- 1 | # Icon Switch 2 | 3 | The `` is a switch component that can optionally renders an icon in the switch's handle. 4 | 5 | icon switch picture 6 | 7 | ## Usage 8 | 9 | ```tsx 10 | import { IconSwitch } from '@brightlayer-ui/react-native-components'; 11 | 12 | ; 13 | 14 | ; 15 | ``` 16 | 17 | ### API 18 | 19 |
20 | 21 | | Prop Name | Description | Type | Required | Default | 22 | | ------------- | -------------------------------- | ----------------------------- | -------- | ------- | 23 | | showIcon | To display icon or not | `boolean` | no | | 24 | | disabled | Flag for render disabled switch | `boolean` | no | | 25 | | value | Pass state to the component | `boolean` | yes | | 26 | | onValueChange | Callback event handling function | `Function` | yes | | 27 | | theme | Theme value overrides | `$DeepPartial` | no | | 28 | 29 |
30 | 31 | Any other props will be provided to the root element ([**View**](https://reactnative.dev/docs/view)). 32 | 33 | ### Styles 34 | 35 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following keys: 36 | 37 | | Name | Description | 38 | | ------ | ------------------------------------ | 39 | | root | Styles applied to the root element | 40 | | handle | Styles applied to the handle element | 41 | -------------------------------------------------------------------------------- /docs/ListItemTag.md: -------------------------------------------------------------------------------- 1 | # List Item Tag 2 | 3 | `` is a text item with a colored background and rounded corners that is used to tag lists. 4 | 5 | List Item Tag 6 | 7 | ## Usage 8 | 9 | ```tsx 10 | import { ListItemTag } from '@brightlayer-ui/react-native-components'; 11 | 12 | 13 | 14 | ``` 15 | 16 | ## API 17 | 18 |
19 | 20 | | Prop Name | Description | Type | Required | Default | 21 | | --------------- | ----------------------------- | ----------------------------- | -------- | --------------------------------------- | 22 | | backgroundColor | Background color of the label | `string` | no | `theme.colors.primaryFilledContainer` | 23 | | fontColor | Text color for the label | `string` | no | `theme.colors.onPrimaryFilledContainer` | 24 | | fontSize | Size of the text | `number` | no | 10 | 25 | | label | The label text | `string` | yes | | 26 | | theme | Theme value overrides | `$DeepPartial` | no | | 27 | 28 |
29 | 30 | Any other props will be provided to the root element [``](https://callstack.github.io/react-native-paper/docs/components/Text). 31 | 32 | ### Styles 33 | 34 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following key: 35 | 36 | | Name | Description | 37 | | ---- | ---------------------------------- | 38 | | root | Styles applied to the root element | 39 | -------------------------------------------------------------------------------- /docs/MobileStepper.md: -------------------------------------------------------------------------------- 1 | # Mobile Stepper 2 | 3 | The `` is used to minimally display progress when completing a workflow that requires multiple steps. There are three types of progress indicators supported, `dots` (default), `text`, and `progress`. 4 | 5 | In Dot Variant: 6 | 7 | Mobile Stepper dot variant 8 | 9 | In Text Variant: 10 | 11 | Mobile Stepper Text variant 12 | 13 | In Progress Variant: 14 | 15 | Mobile Stepper Progress variant 16 | 17 | ## Usage 18 | 19 | ```tsx 20 | import { MobileStepper } from '@brightlayer-ui/react-native-components'; 21 | 22 | } 26 | rightButton={} 27 | variant={'dots'} 28 | />; 29 | ``` 30 | 31 | ## API 32 | 33 |
34 | 35 | | Prop Name | Description | Type | Required | Default | 36 | | ------------- | ---------------------------------------------- | ------------------------------------ | -------- | ----------------------- | 37 | | activeColor | Color of the active page indicator | `string` | no | `theme.colors.primary` | 38 | | activeStep | The index of the active step (>= 0) | `number` | yes | | 39 | | inactiveColor | Color of inactive dot when using 'dot' variant | `string` | no | `theme.colors.disabled` | 40 | | leftButton | Left button content | `JSX.Element` | no | | 41 | | rightButton | Right button content | `JSX.Element` | no | | 42 | | steps | Total number of steps to display (>0) | `number` | yes | | 43 | | variant | Which type of indicator to use | `'dots'` \| `'text'` \| `'progress'` | no | `dots` | 44 | | theme | Theme value overrides | `$DeepPartial` | no | | 45 | 46 |
47 | 48 | Any other props will be provided to the root element ([**View**](https://reactnative.dev/docs/view)). 49 | 50 | ### Styles 51 | 52 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following key: 53 | 54 | | Name | Description | 55 | | ---------------- | ---------------------------------------------------------------- | 56 | | root | Styles applied to the root element | 57 | | circle | Styles applied to dots when using 'dot' variant | 58 | | filled | Styles applied to active dot when using 'dot' variant | 59 | | stepperContainer | Styles applied to stepper container | 60 | | progressBar | Styles applied to the progress bar when using 'progress' variant | 61 | | text | Styles applied to the text when using 'text' variant | 62 | -------------------------------------------------------------------------------- /docs/Overline.md: -------------------------------------------------------------------------------- 1 | # Overline 2 | 3 | Overline component is used to render text on the screen. 4 | 5 | Overline 6 | 7 | ## Usage 8 | 9 | ```tsx 10 | import { Overline } from '@brightlayer-ui/react-native-components'; 11 | 12 | 13 | Overline 14 | ; 15 | ``` 16 | 17 | ## API 18 | 19 |
20 | 21 | | Prop Name | Description | Type | Required | Default | 22 | | --------- | --------------------- | ----------------------------- | -------- | ------- | 23 | | theme | Theme value overrides | `$DeepPartial` | no | | 24 | 25 |
26 | 27 | Any other props will be provided to the root element [``](https://callstack.github.io/react-native-paper/docs/components/Text). 28 | 29 | ### Styles 30 | 31 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following keys: 32 | 33 | | Name | Description | 34 | | ---- | ---------------------------------- | 35 | | root | Styles applied to the root element | 36 | -------------------------------------------------------------------------------- /docs/Spacer.md: -------------------------------------------------------------------------------- 1 | # Spacer 2 | 3 | An invisible utility component that acts as a spacer element in various layouts. It works with flexbox sizing or fixed sizing. 4 | 5 |
6 | Spacer used in Drawer Body
7 |
8 | 9 | ## Usage 10 | 11 | ```tsx 12 | import { Spacer } from '@brightlayer-ui/react-native-components'; 13 | 14 | 15 | {/* Left Content */} 16 | 17 | {/* Right Content */} 18 | ; 19 | ``` 20 | 21 | > Using flex elements (like Spacer) inside of a [ScrollView](https://reactnative.dev/docs/scrollview) will not have an effect unless the parent has a fixed height. 22 | 23 | ## API 24 | 25 |
26 | 27 | | Prop Name | Description | Type | Required | Default | 28 | | --------- | ---------------------------------------------- | -------- | -------- | ------- | 29 | | flex | Flex grow/shrink value for use in flex layouts | `number` | no | 1 | 30 | | height | Height (in dp) for static layouts | `number` | no | | 31 | | width | Width (in dp) for static layouts | `number` | no | | 32 | 33 |
34 | 35 | Any other props will be provided to the root element ([**View**](https://reactnative.dev/docs/view)). 36 | 37 | ### Styles 38 | 39 | You can override the classes used by Brightlayer UI by passing a `styles` prop. It supports the following key: 40 | 41 | | Name | Description | 42 | | ---- | ---------------------------------- | 43 | | root | Styles applied to the root element | 44 | -------------------------------------------------------------------------------- /docs/UserMenu.md: -------------------------------------------------------------------------------- 1 | # User Menu 2 | 3 | The `` is an Avatar that opens a Menu when clicked. It is typically used in the top-right corner of an application and indicates who is logged in. 4 | 5 |
6 | 7 | UserMenu Avatar 8 | UserMenu Opened 9 | 10 |
11 | 12 | ## Usage 13 | 14 | ```tsx 15 | import { UserMenu } from '@brightlayer-ui/react-native-components'; 16 | 17 | } 26 | />; 27 | ``` 28 | 29 | ## API 30 | 31 |
32 | 33 | | Prop Name | Description | Type | Required | Default | 34 | | --------------- | -------------------------------------------------------- | ----------------------------- | -------- | ------------------------------- | 35 | | avatar | Avatar to display as the menu trigger | `JSX.Element` | yes | | 36 | | backgroundColor | Background color of the bottom sheet | `string` | no | `theme.colors.surface` | 37 | | fontColor | Color of text for the bottom sheet header and menu items | `string` | no | | 38 | | iconColor | Color of icons for the bottom sheet menu items | `string` | no | `theme.colors.onSurfaceVariant` | 39 | | menuItems | An array of menu items to show in the bottom sheet | `InfoListItemProps[]` | yes | | 40 | | menuTitle | Title to display in the bottom sheet | `string` | no | | 41 | | menuSubtitle | Subtitle to display in the bottom sheet | `string` | no | | 42 | | theme | Theme value overrides | `$DeepPartial` | no | | 43 | 44 |
45 | 46 | ### Styles 47 | 48 | You can override the internal styles used by Brightlayer UI by passing a `styles` prop. It supports the following keys: 49 | 50 | | Name | Description | 51 | | ----------- | ----------------------------------------- | 52 | | root | Styles applied to the root element | 53 | | avatar | Styles applied to avatar wrapper | 54 | | bottomsheet | Styles applied to the bottomsheet wrapper | 55 | -------------------------------------------------------------------------------- /docs/images/ListItemTagInInfoListItem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/ListItemTagInInfoListItem.png -------------------------------------------------------------------------------- /docs/images/autocomplete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/autocomplete.png -------------------------------------------------------------------------------- /docs/images/channelValue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/channelValue.png -------------------------------------------------------------------------------- /docs/images/chip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/chip.png -------------------------------------------------------------------------------- /docs/images/collapsibleHeaderLayout.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/collapsibleHeaderLayout.gif -------------------------------------------------------------------------------- /docs/images/drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/drawer.png -------------------------------------------------------------------------------- /docs/images/emptyState.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/emptyState.png -------------------------------------------------------------------------------- /docs/images/grade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/grade.png -------------------------------------------------------------------------------- /docs/images/gradesSubcomponent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/gradesSubcomponent.png -------------------------------------------------------------------------------- /docs/images/header_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/header_large.png -------------------------------------------------------------------------------- /docs/images/header_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/header_small.png -------------------------------------------------------------------------------- /docs/images/hero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/hero.png -------------------------------------------------------------------------------- /docs/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/icon.png -------------------------------------------------------------------------------- /docs/images/iconswitch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/iconswitch.png -------------------------------------------------------------------------------- /docs/images/infoListItem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/infoListItem.png -------------------------------------------------------------------------------- /docs/images/listItemTag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/listItemTag.png -------------------------------------------------------------------------------- /docs/images/mobileStepper_dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/mobileStepper_dot.png -------------------------------------------------------------------------------- /docs/images/mobileStepper_progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/mobileStepper_progress.png -------------------------------------------------------------------------------- /docs/images/mobileStepper_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/mobileStepper_text.png -------------------------------------------------------------------------------- /docs/images/overline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/overline.png -------------------------------------------------------------------------------- /docs/images/scorecard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/scorecard.png -------------------------------------------------------------------------------- /docs/images/scorecard_alt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/scorecard_alt.png -------------------------------------------------------------------------------- /docs/images/spacer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/spacer.png -------------------------------------------------------------------------------- /docs/images/userMenuAvatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/userMenuAvatar.png -------------------------------------------------------------------------------- /docs/images/userMenuOpened.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/etn-ccis/blui-react-native-component-library/8fc9f1091b36d8c2e4183ad802b4ef61a284d84c/docs/images/userMenuOpened.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-components", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "initialize": "bash scripts/initializeSubmodule.sh", 6 | "build": "bash ./scripts/buildComponents.sh", 7 | "install:showcase-ios": "yarn initialize && cd demos/showcase && yarn && cd ios && pod install && cd ../../.. && yarn link:components", 8 | "install:showcase-android": "yarn initialize && cd demos/showcase && yarn && cd ../.. && yarn link:components", 9 | "install:storybook-ios": "cd demos/storybook && yarn && cd ios && pod install && cd ../../.. && yarn link:components", 10 | "install:storybook-android": "cd demos/storybook && yarn && cd ../.. && yarn link:components", 11 | "install:storybook-api": "cd demos/api && yarn && cd ../.. && yarn link:components", 12 | "install:all": "yarn && cd components && yarn install && cd .. && yarn install:showcase-ios && yarn install:storybook-ios && yarn install:storybook-api", 13 | "install:components": "yarn && cd components && yarn", 14 | "install:all-android": "cd components && yarn install && cd .. && yarn install:showcase-android && yarn install:storybook-android && yarn install:storybook-api", 15 | "link:components": "bash ./scripts/linkComponents.sh", 16 | "publish:package": "cd dist && rm -f *.tgz && set npm_config_yes=true && npx -p @brightlayer-ui/publish blui-publish", 17 | "tag:package": "cd dist && set npm_config_yes=true && npx -p @brightlayer-ui/tag blui-tag -s -blui-react-native-component-library", 18 | "start": "yarn start:showcase", 19 | "start:showcase": "yarn start:showcase-ios", 20 | "start:showcase-ios": "yarn install:showcase-ios && cd demos/showcase && yarn ios", 21 | "start:showcase-android": "yarn install:showcase-android && cd demos/showcase && yarn android", 22 | "start:storybook": "yarn start:storybook-ios", 23 | "start:storybook-ios": "yarn install:storybook-ios && cd demos/storybook && yarn ios", 24 | "start:storybook-android": "yarn install:storybook-android && cd demos/storybook && yarn android", 25 | "start:storybook-api": "yarn install:storybook-api && cd demos/api && yarn start", 26 | "test": "cd components && yarn test", 27 | "test:watch": "cd components && yarn test:watch", 28 | "test:artifacts": "echo \"TODO: TEST ARTIFACTS\"", 29 | "prettier": "prettier \"docs/**.{ts,tsx,js,jsx,json,css,scss,md,html}\" --write && cd components && yarn prettier", 30 | "prettier:check": "prettier \"docs/**.{ts,tsx,js,jsx,json,css,scss,md,html}\" --check && cd components && yarn prettier:check", 31 | "lint": "cd components && yarn lint", 32 | "lint:fix": "cd components && yarn lint:fix", 33 | "update:submodule": "git submodule update --remote", 34 | "precommit": "yarn install:all && yarn prettier && yarn lint && yarn test && yarn build && yarn test:artifacts && yarn generate:licenses", 35 | "coverage": "cd components && yarn test --coverage --watchAll=false", 36 | "generate:licenses": "cd ./components && npm-license-crawler -onlyDirectDependencies -json LICENSES.json", 37 | "prepare": "husky" 38 | }, 39 | "directories": { 40 | "doc": "docs" 41 | }, 42 | "prettier": "@brightlayer-ui/prettier-config", 43 | "devDependencies": { 44 | "@brightlayer-ui/prettier-config": "^1.0.3", 45 | "eslint-plugin-react-hooks": "^5.2.0", 46 | "husky": "^9.1.7", 47 | "npm-license-crawler": "^0.2.1", 48 | "prettier": "^3.5.3" 49 | }, 50 | "jest": { 51 | "coverageDirectory": "./components/coverage/", 52 | "collectCoverage": true 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /scripts/buildComponents.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | BLUE='\033[0;34m' 3 | BBLUE='\033[1;34m' #BOLD 4 | PURPLE='\033[0;35m' 5 | RED='\033[0;31m' 6 | BRED='\033[1;31m' #BOLD 7 | GREEN='\033[0;32m' 8 | BGREEN='\033[1;32m' #BOLD 9 | GRAY='\033[1;30m' 10 | NC='\033[0m' # No Color 11 | 12 | # Remove previous build 13 | rm -rf ./dist 14 | 15 | cd ./components 16 | yarn && yarn build 17 | cd .. 18 | 19 | echo -e "${BLUE}Copying Package Resources${NC}" 20 | cp -r ./components/package.json ./dist/package.json 21 | cp -r README.md ./dist/README.md 22 | cp -r LICENSE ./dist/LICENSE 23 | cp -r CHANGELOG.md ./dist/CHANGELOG.md 24 | cp -r components/LICENSES.json ./dist/LICENSES.json 25 | 26 | echo -e "${GRAY}Complete${NC}\r\n" 27 | -------------------------------------------------------------------------------- /scripts/initializeSubmodule.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | BLUE='\033[0;34m' 3 | BBLUE='\033[1;34m' #BOLD 4 | PURPLE='\033[0;35m' 5 | RED='\033[0;31m' 6 | BRED='\033[1;31m' #BOLD 7 | GREEN='\033[0;32m' 8 | BGREEN='\033[1;32m' #BOLD 9 | GRAY='\033[1;30m' 10 | NC='\033[0m' # No Color 11 | 12 | echo -e "${BLUE}Initializing Showcase Submodule...${NC}" 13 | if [ ! -f ./demos/showcase/package.json ]; 14 | then git submodule init && git submodule update; 15 | else echo -e "${BBLUE}Already initialized${NC}" && exit 0; 16 | fi 17 | echo -e "${BBLUE}Initialization Complete${NC}\r\n" -------------------------------------------------------------------------------- /scripts/linkComponents.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | BLUE='\033[0;34m' 3 | BBLUE='\033[1;34m' #BOLD 4 | PURPLE='\033[0;35m' 5 | RED='\033[0;31m' 6 | BRED='\033[1;31m' #BOLD 7 | GREEN='\033[0;32m' 8 | BGREEN='\033[1;32m' #BOLD 9 | GRAY='\033[1;30m' 10 | NC='\033[0m' # No Color 11 | 12 | echo -e "${BLUE}Building components...${NC}" 13 | bash ./scripts/buildComponents.sh 14 | 15 | echo -en "${BLUE}Creating new folder in node_modules...${NC}" 16 | rm -rf "./demos/showcase/node_modules/@brightlayer-ui/react-native-components" 17 | mkdir -p "./demos/showcase/node_modules/@brightlayer-ui/react-native-components" 18 | rm -rf "./demos/storybook/node_modules/@brightlayer-ui/react-native-components" 19 | mkdir -p "./demos/storybook/node_modules/@brightlayer-ui/react-native-components" 20 | rm -rf "./demos/api/node_modules/@brightlayer-ui/react-native-components" 21 | mkdir -p "./demos/api/node_modules/@brightlayer-ui/react-native-components" 22 | echo -e "${GREEN}Done${NC}" 23 | 24 | echo -en "${BLUE}Copying build output into node_modules...${NC}"; 25 | cp -r ./dist/. ./demos/showcase/node_modules/@brightlayer-ui/react-native-components 26 | cp -r ./dist/. ./demos/storybook/node_modules/@brightlayer-ui/react-native-components 27 | cp -r ./dist/. ./demos/api/node_modules/@brightlayer-ui/react-native-components 28 | echo -e "${GREEN}Done${NC}" 29 | 30 | echo -en "\r\n${BBLUE}Linking Components: ${NC}" 31 | if [ ! -f ./demos/showcase/node_modules/@brightlayer-ui/react-native-components/package.json ]; then echo -e "${BRED}Showcase Not Linked${NC}" && exit 1; fi 32 | if [ ! -s ./demos/showcase/node_modules/@brightlayer-ui/react-native-components/core ]; 33 | then 34 | if [ ! -f ./demos/showcase/node_modules/@brightlayer-ui/react-native-components/core/index.js ]; 35 | then echo -e "${BRED}Showcase Not Linked${NC}" && exit 1; 36 | fi; 37 | fi 38 | if [ ! -f ./demos/storybook/node_modules/@brightlayer-ui/react-native-components/package.json ]; then echo -e "${BRED}Storybook Not Linked${NC}" && exit 1; fi 39 | if [ ! -s ./demos/storybook/node_modules/@brightlayer-ui/react-native-components/core ]; 40 | then 41 | if [ ! -f ./demos/storybook/node_modules/@brightlayer-ui/react-native-components/core/index.js ]; 42 | then echo -e "${BRED}Storybook Not Linked${NC}" && exit 1; 43 | fi; 44 | fi 45 | if [ ! -f ./demos/api/node_modules/@brightlayer-ui/react-native-components/package.json ]; then echo -e "${BRED}Storybook API Not Linked${NC}" && exit 1; fi 46 | if [ ! -s ./demos/api/node_modules/@brightlayer-ui/react-native-components/core ]; 47 | then 48 | if [ ! -f ./demos/api/node_modules/@brightlayer-ui/react-native-components/core/index.js ]; 49 | then echo -e "${BRED}Storyboook API Not Linked${NC}" && exit 1; 50 | fi; 51 | fi 52 | echo -e "${GRAY}Complete${NC}\r\n" 53 | --------------------------------------------------------------------------------