├── .all-contributorsrc ├── .babelrc ├── .circleci └── config.yml ├── .eslintrc.json ├── .gitattributes ├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .npmignore ├── .npmrc ├── .prettierrc.json ├── .snyk ├── .storybook ├── config.yml ├── main.js ├── old-docs │ ├── bundle.js │ └── index.html └── webpack.config.js ├── API └── index.js ├── CHANGELOG.md ├── LICENSE ├── bot-usage.png ├── bundle.js ├── commitlint.config.js ├── index.html ├── ld-react-components.png ├── package.json ├── readme.md ├── src └── lib │ ├── FeatureCase │ └── index.ts │ ├── FeatureDefault │ └── index.ts │ ├── FeatureFalse │ └── index.ts │ ├── FeatureFlag │ ├── FeatureFlag.stories.jsx │ ├── README.md │ ├── index.js │ └── index.tsx │ ├── FeatureSwitch │ └── index.tsx │ ├── FeatureTrue │ └── index.ts │ ├── LaunchDarklyClient │ └── index.ts │ └── index.js ├── test-reports └── jest │ └── results.xml ├── test ├── __snapshots__ │ └── react.test.js.snap ├── main.test.js └── react.test.js ├── tsconfig.json ├── webpack.config.js └── yarn.lock /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "LD-React-Components", 3 | "projectOwner": "intuit", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "readme.md" 8 | ], 9 | "imageSize": 100, 10 | "commit": true, 11 | "commitConvention": "none", 12 | "contributors": [ 13 | { 14 | "login": "poorpaddy", 15 | "name": "Dave Bergschneider", 16 | "avatar_url": "https://avatars3.githubusercontent.com/u/2213076?v=4", 17 | "profile": "http://www.cmscode.com", 18 | "contributions": [ 19 | "code", 20 | "design", 21 | "doc", 22 | "example", 23 | "maintenance" 24 | ] 25 | }, 26 | { 27 | "login": "hipstersmoothie", 28 | "name": "Andrew Lisowski", 29 | "avatar_url": "https://avatars3.githubusercontent.com/u/1192452?v=4", 30 | "profile": "http://hipstersmoothie.com", 31 | "contributions": [ 32 | "infra" 33 | ] 34 | }, 35 | { 36 | "login": "hjaintech", 37 | "name": "Harshit Jain", 38 | "avatar_url": "https://avatars2.githubusercontent.com/u/1290501?v=4", 39 | "profile": "http://www.harshitjain.in", 40 | "contributions": [ 41 | "doc" 42 | ] 43 | }, 44 | { 45 | "login": "zjael", 46 | "name": "Jakob S", 47 | "avatar_url": "https://avatars3.githubusercontent.com/u/13909277?s=460&v=4", 48 | "profile": "https://github.com/zjael", 49 | "contributions": [ 50 | "maintenance" 51 | ] 52 | }, 53 | { 54 | "login": "vvscode", 55 | "name": "Vasiliy Vanchuk", 56 | "avatar_url": "https://avatars1.githubusercontent.com/u/6904368?v=4", 57 | "profile": "http://bit.ly/vvscodeli", 58 | "contributions": [ 59 | "infra" 60 | ] 61 | }, 62 | { 63 | "login": "Buranch", 64 | "name": "Buranch", 65 | "avatar_url": "https://avatars2.githubusercontent.com/u/17932362?v=4", 66 | "profile": "https://github.com/Buranch", 67 | "contributions": [ 68 | "code" 69 | ] 70 | }, 71 | { 72 | "login": "ishubhamarora", 73 | "name": "Shubham Arora", 74 | "avatar_url": "https://avatars2.githubusercontent.com/u/55948973?v=4", 75 | "profile": "https://github.com/ishubhamarora", 76 | "contributions": [ 77 | "code" 78 | ] 79 | }, 80 | { 81 | "login": "ggrumbley", 82 | "name": "Gary Grumbley", 83 | "avatar_url": "https://avatars0.githubusercontent.com/u/15022042?v=4", 84 | "profile": "https://twitter.com/StumblinG", 85 | "contributions": [ 86 | "infra", 87 | "doc" 88 | ] 89 | }, 90 | { 91 | "login": "Hreherch", 92 | "name": "Bennett Hreherchuk", 93 | "avatar_url": "https://avatars1.githubusercontent.com/u/10092939?v=4", 94 | "profile": "https://github.com/Hreherch", 95 | "contributions": [ 96 | "test" 97 | ] 98 | }, 99 | { 100 | "login": "josediego", 101 | "name": "Jose Diego", 102 | "avatar_url": "https://avatars0.githubusercontent.com/u/5665920?v=4", 103 | "profile": "https://github.com/josediego", 104 | "contributions": [ 105 | "infra", 106 | "code", 107 | "doc", 108 | "test" 109 | ] 110 | }, 111 | { 112 | "login": "Swazimodo", 113 | "name": "Sam Nesbitt", 114 | "avatar_url": "https://avatars3.githubusercontent.com/u/10536879?v=4", 115 | "profile": "https://www.linkedin.com/in/sam-nesbitt-74ba6a34/", 116 | "contributions": [ 117 | "code" 118 | ] 119 | }, 120 | { 121 | "login": "pramodrhegde", 122 | "name": "Pramod", 123 | "avatar_url": "https://avatars1.githubusercontent.com/u/9020200?v=4", 124 | "profile": "https://github.com/pramodrhegde", 125 | "contributions": [ 126 | "code" 127 | ] 128 | }, 129 | { 130 | "login": "cueo", 131 | "name": "Mohit Mayank", 132 | "avatar_url": "https://avatars1.githubusercontent.com/u/13873846?v=4", 133 | "profile": "https://github.com/cueo", 134 | "contributions": [ 135 | "code" 136 | ] 137 | }, 138 | { 139 | "login": "anki08", 140 | "name": "ankita sinha", 141 | "avatar_url": "https://avatars2.githubusercontent.com/u/8593629?v=4", 142 | "profile": "https://github.com/anki08", 143 | "contributions": [ 144 | "code" 145 | ] 146 | }, 147 | { 148 | "login": "Kausam", 149 | "name": "Kausam", 150 | "avatar_url": "https://avatars2.githubusercontent.com/u/19550684?v=4", 151 | "profile": "https://github.com/Kausam", 152 | "contributions": [ 153 | "code" 154 | ] 155 | }, 156 | { 157 | "login": "rohan8594", 158 | "name": "Rohan Patel", 159 | "avatar_url": "https://avatars1.githubusercontent.com/u/23509745?v=4", 160 | "profile": "http://rohanpatel.xyz", 161 | "contributions": [ 162 | "doc" 163 | ] 164 | }, 165 | { 166 | "login": "tekgal", 167 | "name": "tekgal", 168 | "avatar_url": "https://avatars0.githubusercontent.com/u/23368862?v=4", 169 | "profile": "https://github.com/tekgal", 170 | "contributions": [ 171 | "infra" 172 | ] 173 | }, 174 | { 175 | "login": "funkadelic", 176 | "name": "Norman Yee", 177 | "avatar_url": "https://avatars2.githubusercontent.com/u/155019?v=4", 178 | "profile": "https://github.com/funkadelic", 179 | "contributions": [ 180 | "infra" 181 | ] 182 | }, 183 | { 184 | "login": "himanshupnt", 185 | "name": "Himanshu Pant", 186 | "avatar_url": "https://avatars3.githubusercontent.com/u/8342344?v=4", 187 | "profile": "https://himanshupnt.com", 188 | "contributions": [ 189 | "doc" 190 | ] 191 | }, 192 | { 193 | "login": "erwintj", 194 | "name": "Trevor Erwin", 195 | "avatar_url": "https://avatars0.githubusercontent.com/u/13356723?v=4", 196 | "profile": "https://github.com/erwintj", 197 | "contributions": [ 198 | "bug" 199 | ] 200 | }, 201 | { 202 | "login": "faulker", 203 | "name": "Winter Faulk", 204 | "avatar_url": "https://avatars0.githubusercontent.com/u/2238782?v=4", 205 | "profile": "http://faulk.me", 206 | "contributions": [ 207 | "maintenance" 208 | ] 209 | }, 210 | { 211 | "login": "skodamarthi", 212 | "name": "Susmitha Kodamarthi", 213 | "avatar_url": "https://avatars0.githubusercontent.com/u/4538858?v=4", 214 | "profile": "https://github.com/skodamarthi", 215 | "contributions": [ 216 | "test" 217 | ] 218 | } 219 | ], 220 | "contributorsPerLine": 7, 221 | "skipCi": true 222 | } 223 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-typescript", 4 | "@babel/env", 5 | "@babel/react" 6 | ], 7 | "plugins": [ 8 | "@babel/plugin-proposal-object-rest-spread", 9 | "@babel/plugin-proposal-class-properties" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | defaults: &defaults 4 | working_directory: ~/ld-react-components 5 | docker: 6 | - image: circleci/node:12.14-browsers 7 | environment: 8 | TEST_REPORTS: ~/ld-react-components/test-reports 9 | 10 | aliases: 11 | # Circle related commands 12 | - &restore-cache 13 | keys: 14 | # Find a cache corresponding to this specific package.json checksum 15 | # when this file is changed, this key will fail 16 | - ld-react-components-{{ checksum "yarn.lock" }}-{{ checksum ".circleci/config.yml" }} 17 | - ld-react-components-{{ checksum "yarn.lock" }} 18 | # Find the most recent cache used from any branch 19 | - ld-react-components- 20 | - &save-cache 21 | key: ld-react-components-{{ checksum "yarn.lock" }}-{{ checksum ".circleci/config.yml" }} 22 | paths: 23 | - ~/.cache/yarn 24 | - node_modules 25 | # Yarn commands 26 | - &yarn 27 | name: Install Dependencies 28 | command: yarn install --frozen-lockfile --non-interactive --cache-folder=~/.cache/yarn 29 | - &lint 30 | name: Lint 31 | command: yarn lint 32 | - &test 33 | name: Test 34 | command: yarn test 35 | - &build 36 | name: Build 37 | command: yarn build 38 | 39 | jobs: 40 | install: 41 | <<: *defaults 42 | steps: 43 | - checkout 44 | - restore_cache: *restore-cache 45 | - run: *yarn 46 | - save_cache: *save-cache 47 | - persist_to_workspace: 48 | root: . 49 | paths: 50 | - . 51 | 52 | build: 53 | <<: *defaults 54 | steps: 55 | - attach_workspace: 56 | at: ~/ld-react-components 57 | - run: *build 58 | - persist_to_workspace: 59 | root: . 60 | paths: 61 | - . 62 | 63 | lint: 64 | <<: *defaults 65 | steps: 66 | - attach_workspace: 67 | at: ~/ld-react-components 68 | - run: *lint 69 | 70 | test: 71 | <<: *defaults 72 | steps: 73 | - attach_workspace: 74 | at: ~/ld-react-components 75 | - run: 76 | command: | 77 | mkdir -p ${TEST_REPORTS} 78 | - run: *test 79 | - run: 80 | name: Send CodeCov Results 81 | command: bash <(curl -s https://codecov.io/bash) -t $CODECOV_KEY 82 | - store_test_results: 83 | path: test-reports 84 | 85 | release: 86 | <<: *defaults 87 | steps: 88 | - attach_workspace: 89 | at: ~/ld-react-components 90 | - add_ssh_keys: 91 | fingerprints: 92 | - "23:b5:04:c6:6a:82:2b:c8:ae:25:39:90:6a:b7:de:cd" 93 | - run: git config user.email dave@cmscode.com 94 | - run: git config user.name "poorpaddy" 95 | - run: rm -rf ~/.ssh/ && mkdir ~/.ssh/ && echo -e "Host github.com\n\tStrictHostKeyChecking no\n" > ~/.ssh/config 96 | - run: 97 | name: Release 98 | command: yarn release 99 | 100 | publishDocs: 101 | <<: *defaults 102 | steps: 103 | - attach_workspace: 104 | at: ~/ld-react-components 105 | - add_ssh_keys: 106 | fingerprints: 107 | - "23:b5:04:c6:6a:82:2b:c8:ae:25:39:90:6a:b7:de:cd" 108 | - run: git config user.email dave@cmscode.com 109 | - run: git config user.name "poorpaddy" 110 | - run: rm -rf ~/.ssh/ && mkdir ~/.ssh/ && echo -e "Host github.com\n\tStrictHostKeyChecking no\n" > ~/.ssh/config 111 | - run: 112 | name: Build Docs 113 | command: yarn docs:build 114 | - run: 115 | name: Config Docs 116 | command: yarn docs:config 117 | - run: 118 | name: Publish Docs 119 | command: yarn docs:publish 120 | 121 | workflows: 122 | version: 2 123 | build_and_test: 124 | jobs: 125 | - install 126 | 127 | - build: 128 | requires: 129 | - install 130 | filters: 131 | branches: 132 | only: 133 | - master 134 | ignore: 135 | - gh-pages 136 | 137 | - lint: 138 | requires: 139 | - build 140 | 141 | - test: 142 | requires: 143 | - build 144 | 145 | - release: 146 | requires: 147 | - test 148 | - lint 149 | 150 | - publishDocs: 151 | requires: 152 | - release 153 | filters: 154 | branches: 155 | only: 156 | - master 157 | ignore: 158 | - gh-pages 159 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb", 4 | "plugin:prettier/recommended", 5 | "prettier/react" 6 | ], 7 | "env": { 8 | "browser": true, 9 | "commonjs": true, 10 | "es6": true, 11 | "jest": true, 12 | "node": true 13 | }, 14 | "rules": { 15 | "jsx-a11y/href-no-hash": ["off"], 16 | "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }], 17 | "max-len": [ 18 | "warn", 19 | { 20 | "code": 100, 21 | "tabWidth": 2, 22 | "comments": 120, 23 | "ignoreComments": false, 24 | "ignoreTrailingComments": true, 25 | "ignoreUrls": true, 26 | "ignoreStrings": true, 27 | "ignoreTemplateLiterals": true, 28 | "ignoreRegExpLiterals": true 29 | } 30 | ], 31 | "import/extensions": [ 32 | "error", 33 | "ignorePackages", 34 | { 35 | "js": "never", 36 | "jsx": "never", 37 | "ts": "never", 38 | "tsx": "never" 39 | } 40 | ] 41 | }, 42 | "settings": { 43 | "import/resolver": { 44 | "node": { 45 | "extensions": [".js", ".jsx", ".ts", ".tsx"] 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Handle line endings automatically for files detected as text 2 | # and leave all files detected as binary untouched. 3 | * text=auto 4 | 5 | # 6 | # The above will handle all files NOT found below 7 | # These files are text and should be normalized (Convert crlf => lf) 8 | # 9 | 10 | # source code 11 | *.php text 12 | *.css text 13 | *.sass text 14 | *.scss text 15 | *.less text 16 | *.styl text 17 | *.js text eol=lf 18 | *.coffee text 19 | *.json text 20 | *.htm text 21 | *.html text 22 | *.xml text 23 | *.svg text 24 | *.txt text 25 | *.ini text 26 | *.inc text 27 | *.pl text 28 | *.rb text 29 | *.py text 30 | *.scm text 31 | *.sql text 32 | *.sh text 33 | *.bat text 34 | 35 | # templates 36 | *.ejs text 37 | *.hbt text 38 | *.jade text 39 | *.haml text 40 | *.hbs text 41 | *.dot text 42 | *.tmpl text 43 | *.phtml text 44 | 45 | # server config 46 | .htaccess text 47 | .nginx.conf text 48 | 49 | # git config 50 | .gitattributes text 51 | .gitignore text 52 | .gitconfig text 53 | 54 | # code analysis config 55 | .jshintrc text 56 | .jscsrc text 57 | .jshintignore text 58 | .csslintrc text 59 | 60 | # misc config 61 | *.yaml text 62 | *.yml text 63 | .editorconfig text 64 | 65 | # build config 66 | *.npmignore text 67 | *.bowerrc text 68 | 69 | # Heroku 70 | Procfile text 71 | .slugignore text 72 | 73 | # Documentation 74 | *.md text 75 | LICENSE text 76 | AUTHORS text 77 | 78 | 79 | # 80 | ## These files are binary and should be left untouched 81 | # 82 | 83 | # (binary is a macro for -text -diff) 84 | *.png binary 85 | *.jpg binary 86 | *.jpeg binary 87 | *.gif binary 88 | *.ico binary 89 | *.mov binary 90 | *.mp4 binary 91 | *.mp3 binary 92 | *.flv binary 93 | *.fla binary 94 | *.swf binary 95 | *.gz binary 96 | *.zip binary 97 | *.7z binary 98 | *.ttf binary 99 | *.eot binary 100 | *.woff binary 101 | *.pyc binary 102 | *.pdf binary 103 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | @poorpaddy -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Open source projects are “living.” Contributions in the form of issues and pull requests are welcomed and encouraged. When you contribute, you explicitly say you are part of the community and abide by its Code of Conduct. 2 | 3 | # The Code 4 | 5 | At Intuit, we foster a kind, respectful, harassment-free cooperative community. Our open source community works to: 6 | 7 | - Be kind and respectful; 8 | - Act as a global community; 9 | - Conduct ourselves professionally. 10 | 11 | As members of this community, we will not tolerate behaviors including, but not limited to: 12 | 13 | - Violent threats or language; 14 | - Discriminatory or derogatory jokes or language; 15 | - Public or private harassment of any kind; 16 | - Other conduct considered inappropriate in a professional setting. 17 | 18 | ## Reporting Concerns 19 | 20 | If you see someone violating the Code of Conduct please email TechOpenSource@intuit.com 21 | 22 | ## Scope 23 | 24 | This code of conduct applies to: 25 | 26 | All repos and communities for Intuit-managed projects, whether or not the text is included in a Intuit-managed project’s repository; 27 | 28 | Individuals or teams representing projects in official capacity, such as via official social media channels or at in-person meetups. 29 | 30 | ## Attribution 31 | 32 | This Code of Conduct is partly inspired by and based on those of Amazon, CocoaPods, GitHub, Microsoft, thoughtbot, and on the Contributor Covenant version 1.4.1. 33 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | [](# Contributing Guidelines 2 | 3 | So you're interested in giving us a hand? That's awesome! We are putting together some guidelines that should help you get started quickly and easily. If you need help with anything, please let us know. Thank you for stopping by! 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intuit/LD-React-Components/2362c78f968b48ec8c8eeb6cea171a296cba15cb/.github/ISSUE_TEMPLATE.md -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | 12 | 13 | 14 | **To Reproduce** 15 | 16 | 17 | 18 | **Expected behavior** 19 | 20 | 21 | 22 | **Screenshots** 23 | 24 | 25 | 26 | **Desktop (please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Version [e.g. 22] 31 | 32 | **Additional context** 33 | 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | 12 | 13 | 14 | **Describe the solution you'd like** 15 | 16 | 17 | 18 | **Describe alternatives you've considered** 19 | 20 | 21 | 22 | **Additional context** 23 | 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # What Changed 2 | 3 | # Why 4 | 5 | Todo: 6 | 7 | - [ ] Add tests 8 | - [ ] Add docs 9 | - [ ] Add yourself to contributors (run `yarn contributors:add`)) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Hidden Environment Files # 2 | .* 3 | !.eslintrc 4 | !.github 5 | !.gitignore 6 | !.babelrc 7 | !.npmrc 8 | !.npmignore 9 | !.circleci 10 | !.storybook 11 | 12 | # LOG Files # 13 | *.log 14 | log/ 15 | 16 | # IDE # 17 | .idea/ 18 | .vscode/ 19 | *.swp 20 | 21 | # Node Files # 22 | /node_modules 23 | 24 | # Tests # 25 | /coverage/ 26 | /errorShots/ 27 | /screenshots/ 28 | stats.json 29 | /test-results/ 30 | # Build folder # 31 | local 32 | build 33 | dist 34 | 35 | #IDE Specific files 36 | 37 | #SublimeText 38 | *.sublime-project 39 | *.sublime-workspace 40 | 41 | #IntelliJ 42 | .idea/ 43 | *.iml 44 | atlassian-ide-plugin.xml 45 | *.ipr 46 | *.iws 47 | 48 | #Eclipse 49 | .project 50 | 51 | #OSX 52 | .DS_Store 53 | .vscode 54 | 55 | # Docs 56 | /docs -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | docs 4 | .babelrc 5 | webpack.config.js 6 | .vscode 7 | .eslintrc 8 | .npmrc 9 | test 10 | src -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.yarnpkg.com -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "trailingComma": "none" 5 | } 6 | -------------------------------------------------------------------------------- /.snyk: -------------------------------------------------------------------------------- 1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. 2 | version: v1.14.1 3 | ignore: {} 4 | # patches apply the minimum changes required to fix a vulnerability 5 | patch: 6 | SNYK-JS-LODASH-567746: 7 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/addons > @storybook/api > @storybook/router > @storybook/csf > lodash': 8 | patched: '2020-05-19T19:43:54.266Z' 9 | - '@storybook/addon-knobs > lodash': 10 | patched: '2020-05-20T00:43:57.311Z' 11 | - '@storybook/addon-knobs > @storybook/api > lodash': 12 | patched: '2020-05-20T00:43:57.311Z' 13 | - '@storybook/addon-knobs > @storybook/client-api > lodash': 14 | patched: '2020-05-20T00:43:57.311Z' 15 | - '@storybook/addon-knobs > @storybook/components > lodash': 16 | patched: '2020-05-20T00:43:57.311Z' 17 | - '@storybook/addon-knobs > react-color > lodash': 18 | patched: '2020-05-20T00:43:57.311Z' 19 | - '@storybook/addon-knobs > @storybook/api > @storybook/csf > lodash': 20 | patched: '2020-05-20T00:43:57.311Z' 21 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/csf > lodash': 22 | patched: '2020-05-20T00:43:57.311Z' 23 | - '@storybook/addon-knobs > @storybook/api > @storybook/router > lodash': 24 | patched: '2020-05-20T00:43:57.311Z' 25 | - '@storybook/addon-knobs > @storybook/api > telejson > lodash': 26 | patched: '2020-05-20T00:43:57.311Z' 27 | - '@storybook/addon-knobs > @storybook/addons > @storybook/api > lodash': 28 | patched: '2020-05-20T00:43:57.311Z' 29 | - '@storybook/addon-knobs > react-color > reactcss > lodash': 30 | patched: '2020-05-20T00:43:57.311Z' 31 | - '@storybook/addon-knobs > @storybook/api > @storybook/router > @storybook/csf > lodash': 32 | patched: '2020-05-20T00:43:57.311Z' 33 | - '@storybook/addon-knobs > @storybook/addons > @storybook/api > @storybook/csf > lodash': 34 | patched: '2020-05-20T00:43:57.311Z' 35 | - '@storybook/addon-knobs > @storybook/addons > @storybook/api > @storybook/router > lodash': 36 | patched: '2020-05-20T00:43:57.311Z' 37 | - '@storybook/addon-knobs > @storybook/addons > @storybook/api > telejson > lodash': 38 | patched: '2020-05-20T00:43:57.311Z' 39 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/channel-postmessage > telejson > lodash': 40 | patched: '2020-05-20T00:43:57.311Z' 41 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/addons > @storybook/api > lodash': 42 | patched: '2020-05-20T00:43:57.311Z' 43 | - '@storybook/addon-knobs > @storybook/addons > @storybook/api > @storybook/router > @storybook/csf > lodash': 44 | patched: '2020-05-20T00:43:57.311Z' 45 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/addons > @storybook/api > @storybook/csf > lodash': 46 | patched: '2020-05-20T00:43:57.311Z' 47 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/addons > @storybook/api > @storybook/router > lodash': 48 | patched: '2020-05-20T00:43:57.311Z' 49 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/addons > @storybook/api > telejson > lodash': 50 | patched: '2020-05-20T00:43:57.311Z' 51 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/addons > @storybook/api > @storybook/router > @storybook/csf > lodash': 52 | patched: '2020-05-20T00:43:57.311Z' 53 | - '@storybook/addon-knobs > react-select > @emotion/css > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 54 | patched: '2020-05-20T00:43:57.311Z' 55 | - '@storybook/addon-knobs > @storybook/theming > @emotion/styled > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 56 | patched: '2020-05-20T00:43:57.311Z' 57 | - '@storybook/addon-knobs > @storybook/theming > @emotion/core > @emotion/css > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 58 | patched: '2020-05-20T00:43:57.311Z' 59 | - '@storybook/addon-knobs > react-select > @emotion/core > @emotion/css > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 60 | patched: '2020-05-20T00:43:57.311Z' 61 | - '@storybook/addon-knobs > @storybook/api > @storybook/theming > @emotion/styled > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 62 | patched: '2020-05-20T00:43:57.311Z' 63 | - '@storybook/addon-knobs > @storybook/components > @storybook/theming > @emotion/styled > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 64 | patched: '2020-05-20T00:43:57.311Z' 65 | - '@storybook/addon-knobs > @storybook/api > @storybook/theming > @emotion/core > @emotion/css > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 66 | patched: '2020-05-20T00:43:57.311Z' 67 | - '@storybook/addon-knobs > @storybook/components > @storybook/theming > @emotion/core > @emotion/css > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 68 | patched: '2020-05-20T00:43:57.311Z' 69 | - '@storybook/addon-knobs > @storybook/addons > @storybook/api > @storybook/theming > @emotion/styled > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 70 | patched: '2020-05-20T00:43:57.311Z' 71 | - '@storybook/addon-knobs > @storybook/addons > @storybook/api > @storybook/theming > @emotion/core > @emotion/css > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 72 | patched: '2020-05-20T00:43:57.311Z' 73 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/addons > @storybook/api > @storybook/theming > @emotion/styled > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 74 | patched: '2020-05-20T00:43:57.311Z' 75 | - '@storybook/addon-knobs > @storybook/client-api > @storybook/addons > @storybook/api > @storybook/theming > @emotion/core > @emotion/css > babel-plugin-emotion > @babel/helper-module-imports > @babel/types > lodash': 76 | patched: '2020-05-20T00:43:57.311Z' 77 | -------------------------------------------------------------------------------- /.storybook/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | defaults: &defaults 4 | docker: 5 | - image: circleci/node:8.14-browsers 6 | 7 | jobs: 8 | install: 9 | <<: *defaults 10 | steps: 11 | - checkout 12 | - run: echo "dont build me" 13 | 14 | workflows: 15 | version: 2 16 | build_and_test: 17 | jobs: 18 | - install -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../src/lib/**/*.stories.@(js|jsx|mdx)'], 3 | addons: [ 4 | '@storybook/addon-docs', 5 | '@storybook/addon-knobs/register', 6 | '@storybook/addon-storysource/register', 7 | '@storybook/addon-actions/register', 8 | '@storybook/addon-links/register', 9 | '@storybook/addon-a11y/register' 10 | ], 11 | options: { 12 | panelPosition: 'bottom', 13 | name: 'Launch Darkly React Components', 14 | }, 15 | backgrounds: [ 16 | { 17 | name: 'white', 18 | value: '#fff', 19 | default: true, 20 | }, 21 | { 22 | name: 'grey', 23 | value: '#f4f5f8', 24 | }, 25 | ], 26 | a11y: { 27 | // ... axe options 28 | element: '#root', // optional selector which element to inspect 29 | config: {}, // axe-core configurationOptions (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#parameters-1) 30 | options: {}, // axe-core optionsParameter (https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#options-parameter) 31 | }, 32 | presets: [ 33 | '@storybook/preset-create-react-app', 34 | ], 35 | }; 36 | -------------------------------------------------------------------------------- /.storybook/old-docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example 5 | 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | // you can use this file to add your custom webpack plugins, loaders and anything you like. 2 | // This is just the basic way to add additional webpack configurations. 3 | // For more information refer the docs: https://storybook.js.org/configurations/custom-webpack-config 4 | 5 | // IMPORTANT 6 | // When you add this file, we won't add the default configurations which is similar 7 | // to "React Create App". This only has babel loader to load JavaScript. 8 | 9 | module.exports = { 10 | optimization: { 11 | minimize: false, 12 | }, 13 | plugins: [ 14 | // your custom plugins 15 | ], 16 | module: { 17 | rules: [ 18 | { 19 | test: /\.(ts|tsx)$/, 20 | use: [ 21 | { 22 | loader: require.resolve('awesome-typescript-loader'), 23 | }, 24 | // Optional 25 | { 26 | loader: require.resolve('react-docgen-typescript-loader'), 27 | }, 28 | ], 29 | }, 30 | { 31 | test: /\.stories\.jsx?$/, 32 | use: [ 33 | { 34 | loaders: require.resolve('@storybook/source-loader'), 35 | }, 36 | ], 37 | enforce: 'pre', 38 | }, 39 | ], 40 | }, 41 | resolve: { 42 | extensions: ['.ts', '.tsx'], 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /API/index.js: -------------------------------------------------------------------------------- 1 | var LDApi = require('../dist/LaunchDarklyClient/index.js'); 2 | module.exports = new LDApi(); 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # v1.0.83 (Tue Feb 15 2022) 2 | 3 | #### 🐛 Bug Fix 4 | 5 | - Bump shelljs from 0.8.4 to 0.8.5 [#121](https://github.com/intuit/LD-React-Components/pull/121) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 6 | - Bump ws from 5.2.2 to 5.2.3 [#120](https://github.com/intuit/LD-React-Components/pull/120) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 7 | - Bump trim-off-newlines from 1.0.1 to 1.0.3 [#119](https://github.com/intuit/LD-React-Components/pull/119) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 8 | 9 | #### Authors: 2 10 | 11 | - [@dependabot[bot]](https://github.com/dependabot[bot]) 12 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 13 | 14 | --- 15 | 16 | # v1.0.82 (Tue Feb 15 2022) 17 | 18 | #### 🐛 Bug Fix 19 | 20 | - Bump follow-redirects from 1.11.0 to 1.14.8 [#118](https://github.com/intuit/LD-React-Components/pull/118) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 21 | 22 | #### Authors: 2 23 | 24 | - [@dependabot[bot]](https://github.com/dependabot[bot]) 25 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 26 | 27 | --- 28 | 29 | # v1.0.81 (Tue Feb 15 2022) 30 | 31 | #### 🐛 Bug Fix 32 | 33 | - Bump ajv from 6.12.2 to 6.12.6 [#117](https://github.com/intuit/LD-React-Components/pull/117) ([@dependabot[bot]](https://github.com/dependabot[bot])) 34 | - Bump pathval from 1.1.0 to 1.1.1 [#116](https://github.com/intuit/LD-React-Components/pull/116) ([@dependabot[bot]](https://github.com/dependabot[bot])) 35 | - Bump tmpl from 1.0.4 to 1.0.5 [#114](https://github.com/intuit/LD-React-Components/pull/114) ([@dependabot[bot]](https://github.com/dependabot[bot])) 36 | 37 | #### Authors: 1 38 | 39 | - [@dependabot[bot]](https://github.com/dependabot[bot]) 40 | 41 | --- 42 | 43 | # v1.0.80 (Wed Sep 01 2021) 44 | 45 | #### 🐛 Bug Fix 46 | 47 | - Bump package [#113](https://github.com/intuit/LD-React-Components/pull/113) ([@poorpaddy](https://github.com/poorpaddy)) 48 | - Bump tar from 6.0.5 to 6.1.11 [#111](https://github.com/intuit/LD-React-Components/pull/111) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 49 | - Bump path-parse from 1.0.6 to 1.0.7 [#109](https://github.com/intuit/LD-React-Components/pull/109) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 50 | - Bump trim-newlines from 3.0.0 to 3.0.1 [#105](https://github.com/intuit/LD-React-Components/pull/105) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 51 | - Bump dns-packet from 1.3.1 to 1.3.4 [#104](https://github.com/intuit/LD-React-Components/pull/104) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 52 | - Bump url-parse from 1.4.7 to 1.5.1 [#102](https://github.com/intuit/LD-React-Components/pull/102) ([@dependabot[bot]](https://github.com/dependabot[bot])) 53 | - Bump ssri from 6.0.1 to 6.0.2 [#101](https://github.com/intuit/LD-React-Components/pull/101) ([@dependabot[bot]](https://github.com/dependabot[bot])) 54 | - Bump gitlog from 4.0.0 to 4.0.4 [#100](https://github.com/intuit/LD-React-Components/pull/100) ([@dependabot[bot]](https://github.com/dependabot[bot]) [@poorpaddy](https://github.com/poorpaddy)) 55 | - Bump y18n from 3.2.1 to 3.2.2 [#98](https://github.com/intuit/LD-React-Components/pull/98) ([@dependabot[bot]](https://github.com/dependabot[bot])) 56 | - [Snyk] Security upgrade snyk from 1.436.0 to 1.465.0 [#97](https://github.com/intuit/LD-React-Components/pull/97) ([@snyk-bot](https://github.com/snyk-bot) [@poorpaddy](https://github.com/poorpaddy)) 57 | - Bump elliptic from 6.5.3 to 6.5.4 [#96](https://github.com/intuit/LD-React-Components/pull/96) ([@dependabot[bot]](https://github.com/dependabot[bot])) 58 | 59 | #### Authors: 3 60 | 61 | - [@dependabot[bot]](https://github.com/dependabot[bot]) 62 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 63 | - Snyk bot ([@snyk-bot](https://github.com/snyk-bot)) 64 | 65 | --- 66 | 67 | # v1.0.79 (Thu Feb 25 2021) 68 | 69 | #### 🐛 Bug Fix 70 | 71 | - Bump ini from 1.3.5 to 1.3.8 [#95](https://github.com/intuit/LD-React-Components/pull/95) ([@dependabot[bot]](https://github.com/dependabot[bot])) 72 | - docs: add skodamarthi as a contributor [#92](https://github.com/intuit/LD-React-Components/pull/92) ([@allcontributors[bot]](https://github.com/allcontributors[bot])) 73 | - chore: added commitlint support [#89](https://github.com/intuit/LD-React-Components/pull/89) (susmitha_kodamarthi@intuit.com [@skodamarthi](https://github.com/skodamarthi)) 74 | - docs: add faulker as a contributor [#90](https://github.com/intuit/LD-React-Components/pull/90) ([@allcontributors[bot]](https://github.com/allcontributors[bot])) 75 | - feat(storybook): updates storybook to v6 [#88](https://github.com/intuit/LD-React-Components/pull/88) (Winter_Faulk@intuit.com) 76 | 77 | #### Authors: 5 78 | 79 | - [@allcontributors[bot]](https://github.com/allcontributors[bot]) 80 | - [@dependabot[bot]](https://github.com/dependabot[bot]) 81 | - skodamarthi (susmitha_kodamarthi@intuit.com) 82 | - Susmitha Kodamarthi ([@skodamarthi](https://github.com/skodamarthi)) 83 | - Winter Faulk ([@faulker](https://github.com/faulker)) 84 | 85 | --- 86 | 87 | # v1.0.78 (Fri Aug 21 2020) 88 | 89 | #### 🐛 Bug Fix 90 | 91 | - Bump elliptic from 6.5.2 to 6.5.3 [#83](https://github.com/intuit/LD-React-Components/pull/83) ([@dependabot[bot]](https://github.com/dependabot[bot])) 92 | - Bump lodash from 4.17.15 to 4.17.19 [#82](https://github.com/intuit/LD-React-Components/pull/82) ([@dependabot[bot]](https://github.com/dependabot[bot])) 93 | 94 | #### Authors: 1 95 | 96 | - [@dependabot[bot]](https://github.com/dependabot[bot]) 97 | 98 | --- 99 | 100 | # v1.0.77 (Tue Jun 09 2020) 101 | 102 | #### 🐛 Bug Fix 103 | 104 | - Bump websocket-extensions from 0.1.3 to 0.1.4 [#81](https://github.com/intuit/LD-React-Components/pull/81) ([@dependabot[bot]](https://github.com/dependabot[bot])) 105 | 106 | #### Authors: 1 107 | 108 | - [@dependabot[bot]](https://github.com/dependabot[bot]) 109 | 110 | --- 111 | 112 | # v1.0.76 (Wed May 20 2020) 113 | 114 | #### 🐛 Bug Fix 115 | 116 | - [Snyk] Fix for 1 vulnerabilities [#80](https://github.com/intuit/LD-React-Components/pull/80) ([@snyk-bot](https://github.com/snyk-bot) [@poorpaddy](https://github.com/poorpaddy)) 117 | 118 | #### Authors: 2 119 | 120 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 121 | - Snyk bot ([@snyk-bot](https://github.com/snyk-bot)) 122 | 123 | --- 124 | 125 | # v1.0.75 (Wed May 20 2020) 126 | 127 | #### 🐛 Bug Fix 128 | 129 | - Second part of NPM updates [#79](https://github.com/intuit/LD-React-Components/pull/79) ([@poorpaddy](https://github.com/poorpaddy)) 130 | 131 | #### Authors: 1 132 | 133 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 134 | 135 | --- 136 | 137 | # v1.0.74 (Tue May 19 2020) 138 | 139 | #### 🐛 Bug Fix 140 | 141 | - [Snyk] Fix for 1 vulnerabilities [#78](https://github.com/intuit/LD-React-Components/pull/78) ([@snyk-bot](https://github.com/snyk-bot) [@poorpaddy](https://github.com/poorpaddy)) 142 | 143 | #### Authors: 2 144 | 145 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 146 | - Snyk bot ([@snyk-bot](https://github.com/snyk-bot)) 147 | 148 | --- 149 | 150 | # v1.0.73 (Tue May 19 2020) 151 | 152 | #### 🐛 Bug Fix 153 | 154 | - First round of NPM Updates [#77](https://github.com/intuit/LD-React-Components/pull/77) ([@poorpaddy](https://github.com/poorpaddy)) 155 | 156 | #### ⚠️ Pushed to master 157 | 158 | - fix for eslint ([@poorpaddy](https://github.com/poorpaddy)) 159 | 160 | #### Authors: 1 161 | 162 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 163 | 164 | --- 165 | 166 | # v1.0.72 (Mon Apr 13 2020) 167 | 168 | #### ⚠️ Pushed to master 169 | 170 | - updating minor dependency to force build in circleci (dave_bergschneider@intuit.com) 171 | 172 | #### Authors: 1 173 | 174 | - Bergschneider, Dave (dave_bergschneider@intuit.com) 175 | 176 | --- 177 | 178 | # v1.0.65 (Wed Nov 20 2019) 179 | 180 | #### 🐛 Bug Fix 181 | 182 | - updated the count [#73](https://github.com/intuit/LD-React-Components/pull/73) (dave_bergschneider@intuit.com [@poorpaddy](https://github.com/poorpaddy)) 183 | - Fix/payload [#70](https://github.com/intuit/LD-React-Components/pull/70) ([@Buranch](https://github.com/Buranch)) 184 | - Changing the entry to the index.js instead of .ts [#72](https://github.com/intuit/LD-React-Components/pull/72) ([@Buranch](https://github.com/Buranch)) 185 | - fix the typescript build [#71](https://github.com/intuit/LD-React-Components/pull/71) ([@Buranch](https://github.com/Buranch)) 186 | 187 | #### ⚠️ Pushed to master 188 | 189 | - manual ssh key (dave_bergschneider@intuit.com) 190 | 191 | #### Authors: 3 192 | 193 | - Buranch ([@Buranch](https://github.com/Buranch)) 194 | - Bergschneider, Dave (dave_bergschneider@intuit.com) 195 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 196 | 197 | --- 198 | 199 | # v1.0.64 (Thu Oct 31 2019) 200 | 201 | #### 🐛 Bug Fix 202 | 203 | - docs: add erwintj as a contributor [#69](https://github.com/intuit/LD-React-Components/pull/69) ([@allcontributors[bot]](https://github.com/allcontributors[bot]) [@poorpaddy](https://github.com/poorpaddy)) 204 | 205 | #### Authors: 2 206 | 207 | - [@allcontributors[bot]](https://github.com/allcontributors[bot]) 208 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 209 | 210 | --- 211 | 212 | # v1.0.63 (Thu Oct 31 2019) 213 | 214 | #### 🐛 Bug Fix 215 | 216 | - Updating import extension from js to ts [#68](https://github.com/intuit/LD-React-Components/pull/68) ([@erwintj](https://github.com/erwintj)) 217 | 218 | #### Authors: 1 219 | 220 | - Trevor Erwin ([@erwintj](https://github.com/erwintj)) 221 | 222 | --- 223 | 224 | # v1.0.62 (Thu Oct 31 2019) 225 | 226 | #### 🐛 Bug Fix 227 | 228 | - Follow-up to pull#59 (saving CircleCI test summaries) [#62](https://github.com/intuit/LD-React-Components/pull/62) ([@funkadelic](https://github.com/funkadelic) [@poorpaddy](https://github.com/poorpaddy)) 229 | 230 | #### Authors: 2 231 | 232 | - Norman Yee ([@funkadelic](https://github.com/funkadelic)) 233 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 234 | 235 | --- 236 | 237 | # v1.0.61 (Wed Oct 30 2019) 238 | 239 | #### 🐛 Bug Fix 240 | 241 | - docs: add himanshupnt as a contributor [#66](https://github.com/intuit/LD-React-Components/pull/66) ([@allcontributors[bot]](https://github.com/allcontributors[bot]) [@poorpaddy](https://github.com/poorpaddy)) 242 | 243 | #### Authors: 2 244 | 245 | - [@allcontributors[bot]](https://github.com/allcontributors[bot]) 246 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 247 | 248 | --- 249 | 250 | # v1.0.60 (Wed Oct 30 2019) 251 | 252 | #### 🐛 Bug Fix 253 | 254 | - ISSUE# 52 - add storybook stories [#65](https://github.com/intuit/LD-React-Components/pull/65) ([@himanshupnt](https://github.com/himanshupnt)) 255 | 256 | #### Authors: 1 257 | 258 | - Himanshu Pant ([@himanshupnt](https://github.com/himanshupnt)) 259 | 260 | --- 261 | 262 | # v1.0.59 (Wed Oct 30 2019) 263 | 264 | #### 🐛 Bug Fix 265 | 266 | - docs: add funkadelic as a contributor [#64](https://github.com/intuit/LD-React-Components/pull/64) ([@allcontributors[bot]](https://github.com/allcontributors[bot])) 267 | 268 | #### Authors: 1 269 | 270 | - [@allcontributors[bot]](https://github.com/allcontributors[bot]) 271 | 272 | --- 273 | 274 | # v1.0.58 (Wed Oct 30 2019) 275 | 276 | #### 🐛 Bug Fix 277 | 278 | - docs: add tekgal as a contributor [#63](https://github.com/intuit/LD-React-Components/pull/63) ([@allcontributors[bot]](https://github.com/allcontributors[bot]) [@poorpaddy](https://github.com/poorpaddy)) 279 | 280 | #### Authors: 2 281 | 282 | - [@allcontributors[bot]](https://github.com/allcontributors[bot]) 283 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 284 | 285 | --- 286 | 287 | # v1.0.57 (Wed Oct 30 2019) 288 | 289 | #### 🐛 Bug Fix 290 | 291 | - Add test summary to circleci [#61](https://github.com/intuit/LD-React-Components/pull/61) (puja_baid@intuit.com [@tekgal](https://github.com/tekgal)) 292 | 293 | #### Authors: 2 294 | 295 | - [@tekgal](https://github.com/tekgal) 296 | - pbaid (puja_baid@intuit.com) 297 | 298 | --- 299 | 300 | # v1.0.56 (Wed Oct 30 2019) 301 | 302 | #### 🐛 Bug Fix 303 | 304 | - Revert "feat(build): use webpack to compile build (#57)" [#60](https://github.com/intuit/LD-React-Components/pull/60) ([@poorpaddy](https://github.com/poorpaddy)) 305 | 306 | #### Authors: 1 307 | 308 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 309 | 310 | --- 311 | 312 | # v1.0.55 (Wed Oct 30 2019) 313 | 314 | #### 🐛 Bug Fix 315 | 316 | - Add test summaries for CircleCI [#59](https://github.com/intuit/LD-React-Components/pull/59) ([@funkadelic](https://github.com/funkadelic)) 317 | 318 | #### Authors: 1 319 | 320 | - Norman Yee ([@funkadelic](https://github.com/funkadelic)) 321 | 322 | --- 323 | 324 | # v1.0.54 (Mon Oct 28 2019) 325 | 326 | #### 🐛 Bug Fix 327 | 328 | - feat(build): use webpack to compile build [#57](https://github.com/intuit/LD-React-Components/pull/57) ([@Hreherch](https://github.com/Hreherch) [@poorpaddy](https://github.com/poorpaddy)) 329 | 330 | #### Authors: 2 331 | 332 | - Bennett Hreherchuk ([@Hreherch](https://github.com/Hreherch)) 333 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 334 | 335 | --- 336 | 337 | # v1.0.53 (Mon Oct 28 2019) 338 | 339 | #### 🐛 Bug Fix 340 | 341 | - docs: add rohan8594 as a contributor [#56](https://github.com/intuit/LD-React-Components/pull/56) ([@allcontributors[bot]](https://github.com/allcontributors[bot]) [@poorpaddy](https://github.com/poorpaddy)) 342 | 343 | #### Authors: 2 344 | 345 | - [@allcontributors[bot]](https://github.com/allcontributors[bot]) 346 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 347 | 348 | --- 349 | 350 | # v1.0.52 (Mon Oct 28 2019) 351 | 352 | #### 🐛 Bug Fix 353 | 354 | - All Contributors Bot [#55](https://github.com/intuit/LD-React-Components/pull/55) ([@rohan8594](https://github.com/rohan8594)) 355 | 356 | #### Authors: 1 357 | 358 | - Rohan Patel ([@rohan8594](https://github.com/rohan8594)) 359 | 360 | --- 361 | 362 | # v1.0.51 (Thu Oct 24 2019) 363 | 364 | #### 🐛 Bug Fix 365 | 366 | - Refactor for TypeScript: LaunchDarklyClient [#54](https://github.com/intuit/LD-React-Components/pull/54) ([@Kausam](https://github.com/Kausam)) 367 | 368 | #### Authors: 1 369 | 370 | - [@Kausam](https://github.com/Kausam) 371 | 372 | --- 373 | 374 | # v1.0.50 (Fri Oct 18 2019) 375 | 376 | #### ⚠️ Pushed to master 377 | 378 | - added old docs for examples in storybook ([@poorpaddy](https://github.com/poorpaddy)) 379 | 380 | #### Authors: 1 381 | 382 | - poorpaddy ([@poorpaddy](https://github.com/poorpaddy)) 383 | 384 | --- 385 | 386 | # v1.0.49 (Thu Oct 17 2019) 387 | 388 | #### ⚠️ Pushed to master 389 | 390 | - Pushing old docs for example of upcoming hacktoberfest issues ([@poorpaddy](https://github.com/poorpaddy)) 391 | 392 | #### Authors: 1 393 | 394 | - poorpaddy ([@poorpaddy](https://github.com/poorpaddy)) 395 | 396 | --- 397 | 398 | # v1.0.48 (Fri Oct 11 2019) 399 | 400 | #### 🐛 Bug Fix 401 | 402 | - fix: somehow unminifying storybook fixes the static build [#49](https://github.com/intuit/LD-React-Components/pull/49) ([@mmissey](https://github.com/mmissey)) 403 | 404 | #### Authors: 1 405 | 406 | - Marc Missey ([@mmissey](https://github.com/mmissey)) 407 | 408 | --- 409 | 410 | # v1.0.47 (Mon Oct 07 2019) 411 | 412 | #### 🐛 Bug Fix 413 | 414 | - Refactor for TypeScript: FeatureCase Component #32 [#46](https://github.com/intuit/LD-React-Components/pull/46) ([@anki08](https://github.com/anki08) [@poorpaddy](https://github.com/poorpaddy)) 415 | 416 | #### Authors: 2 417 | 418 | - ankita sinha ([@anki08](https://github.com/anki08)) 419 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 420 | 421 | --- 422 | 423 | # v1.0.46 (Mon Oct 07 2019) 424 | 425 | #### 🐛 Bug Fix 426 | 427 | - Fix TS2367 : No overlap for comparison [#47](https://github.com/intuit/LD-React-Components/pull/47) ([@cueo](https://github.com/cueo)) 428 | 429 | #### Authors: 1 430 | 431 | - Mohit Mayank ([@cueo](https://github.com/cueo)) 432 | 433 | --- 434 | 435 | # v1.0.45 (Sun Oct 06 2019) 436 | 437 | #### 🐛 Bug Fix 438 | 439 | - Refactor FeatureDefault to use TS [#45](https://github.com/intuit/LD-React-Components/pull/45) ([@cueo](https://github.com/cueo) [@poorpaddy](https://github.com/poorpaddy)) 440 | 441 | #### Authors: 2 442 | 443 | - Mohit Mayank ([@cueo](https://github.com/cueo)) 444 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 445 | 446 | --- 447 | 448 | # v1.0.44 (Sun Oct 06 2019) 449 | 450 | #### 🐛 Bug Fix 451 | 452 | - Refactor FeatureFalse to use TS [#44](https://github.com/intuit/LD-React-Components/pull/44) ([@cueo](https://github.com/cueo) [@poorpaddy](https://github.com/poorpaddy)) 453 | 454 | #### Authors: 2 455 | 456 | - Mohit Mayank ([@cueo](https://github.com/cueo)) 457 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 458 | 459 | --- 460 | 461 | # v1.0.43 (Sun Oct 06 2019) 462 | 463 | #### 🐛 Bug Fix 464 | 465 | - Refactor LaunchDarklyClient to use TypeScript [#43](https://github.com/intuit/LD-React-Components/pull/43) ([@cueo](https://github.com/cueo)) 466 | 467 | #### Authors: 1 468 | 469 | - Mohit Mayank ([@cueo](https://github.com/cueo)) 470 | 471 | --- 472 | 473 | # v1.0.42 (Sun Oct 06 2019) 474 | 475 | #### 🐛 Bug Fix 476 | 477 | - Moved FeatureTrue component to typescript. Issue #37 [#42](https://github.com/intuit/LD-React-Components/pull/42) (pramod_hegde@intuit.com [@pramodrhegde](https://github.com/pramodrhegde)) 478 | 479 | #### Authors: 2 480 | 481 | - Pramod ([@pramodrhegde](https://github.com/pramodrhegde)) 482 | - phegde2 (pramod_hegde@intuit.com) 483 | 484 | --- 485 | 486 | # v1.0.41 (Sat Oct 05 2019) 487 | 488 | #### 🐛 Bug Fix 489 | 490 | - Feature/type switch [#41](https://github.com/intuit/LD-React-Components/pull/41) ([@Swazimodo](https://github.com/Swazimodo)) 491 | 492 | #### Authors: 1 493 | 494 | - Sam Nesbitt ([@Swazimodo](https://github.com/Swazimodo)) 495 | 496 | --- 497 | 498 | # v1.0.40 (Fri Oct 04 2019) 499 | 500 | #### ⚠️ Pushed to master 501 | 502 | - Add @josediego as a contributor ([@poorpaddy](https://github.com/poorpaddy)) 503 | 504 | #### Authors: 1 505 | 506 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 507 | 508 | --- 509 | 510 | # v1.0.39 (Fri Oct 04 2019) 511 | 512 | #### ⚠️ Pushed to master 513 | 514 | - Merge branch 'master' of https://github.com/intuit/LD-React-Components ([@poorpaddy](https://github.com/poorpaddy)) 515 | - Add @Hreherch as a contributor ([@poorpaddy](https://github.com/poorpaddy)) 516 | 517 | #### Authors: 1 518 | 519 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 520 | 521 | --- 522 | 523 | # v1.0.38 (Fri Oct 04 2019) 524 | 525 | #### 🐛 Bug Fix 526 | 527 | - Add configuration for Typescript support on Storybook, build and Jest [#40](https://github.com/intuit/LD-React-Components/pull/40) ([@josediego](https://github.com/josediego)) 528 | 529 | #### Authors: 1 530 | 531 | - Jose Diego ([@josediego](https://github.com/josediego)) 532 | 533 | --- 534 | 535 | # v1.0.37 (Fri Oct 04 2019) 536 | 537 | #### ⚠️ Pushed to master 538 | 539 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 540 | 541 | #### Authors: 1 542 | 543 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 544 | 545 | --- 546 | 547 | # v1.0.36 (Fri Oct 04 2019) 548 | 549 | #### ⚠️ Pushed to master 550 | 551 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 552 | 553 | #### Authors: 1 554 | 555 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 556 | 557 | --- 558 | 559 | # v1.0.35 (Fri Oct 04 2019) 560 | 561 | #### ⚠️ Pushed to master 562 | 563 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 564 | 565 | #### Authors: 1 566 | 567 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 568 | 569 | --- 570 | 571 | # v1.0.34 (Fri Oct 04 2019) 572 | 573 | #### ⚠️ Pushed to master 574 | 575 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 576 | 577 | #### Authors: 1 578 | 579 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 580 | 581 | --- 582 | 583 | # v1.0.33 (Thu Oct 03 2019) 584 | 585 | #### ⚠️ Pushed to master 586 | 587 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 588 | 589 | #### Authors: 1 590 | 591 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 592 | 593 | --- 594 | 595 | # v1.0.32 (Thu Oct 03 2019) 596 | 597 | #### ⚠️ Pushed to master 598 | 599 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 600 | 601 | #### Authors: 1 602 | 603 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 604 | 605 | --- 606 | 607 | # v1.0.31 (Thu Oct 03 2019) 608 | 609 | #### ⚠️ Pushed to master 610 | 611 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 612 | 613 | #### Authors: 1 614 | 615 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 616 | 617 | --- 618 | 619 | # v1.0.30 (Thu Oct 03 2019) 620 | 621 | #### ⚠️ Pushed to master 622 | 623 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 624 | - Merge branch 'master' of https://github.com/intuit/LD-React-Components ([@poorpaddy](https://github.com/poorpaddy)) 625 | 626 | #### Authors: 1 627 | 628 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 629 | 630 | --- 631 | 632 | # v1.0.29 (Thu Oct 03 2019) 633 | 634 | #### ⚠️ Pushed to master 635 | 636 | - testing ignore of gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 637 | 638 | #### Authors: 1 639 | 640 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 641 | 642 | --- 643 | 644 | # v1.0.28 (Thu Oct 03 2019) 645 | 646 | #### 🐛 Bug Fix 647 | 648 | - Increased code coverage :) [#39](https://github.com/intuit/LD-React-Components/pull/39) ([@Hreherch](https://github.com/Hreherch)) 649 | 650 | #### Authors: 1 651 | 652 | - Bennett Hreherchuk ([@Hreherch](https://github.com/Hreherch)) 653 | 654 | --- 655 | 656 | # v1.0.27 (Thu Oct 03 2019) 657 | 658 | #### ⚠️ Pushed to master 659 | 660 | - forcing build ([@poorpaddy](https://github.com/poorpaddy)) 661 | 662 | #### Authors: 1 663 | 664 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 665 | 666 | --- 667 | 668 | # v1.0.26 (Thu Oct 03 2019) 669 | 670 | #### ⚠️ Pushed to master 671 | 672 | - Add @ggrumbley as a contributor ([@poorpaddy](https://github.com/poorpaddy)) 673 | 674 | #### Authors: 1 675 | 676 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 677 | 678 | --- 679 | 680 | # v1.0.25 (Thu Oct 03 2019) 681 | 682 | #### ⚠️ Pushed to master 683 | 684 | - forcing push ([@poorpaddy](https://github.com/poorpaddy)) 685 | 686 | #### Authors: 1 687 | 688 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 689 | 690 | --- 691 | 692 | # v1.0.24 (Thu Oct 03 2019) 693 | 694 | #### 🐛 Bug Fix 695 | 696 | - 18 setup docs ci [#31](https://github.com/intuit/LD-React-Components/pull/31) (gary_grumbley@intuit.com [@poorpaddy](https://github.com/poorpaddy)) 697 | 698 | #### ⚠️ Pushed to master 699 | 700 | - fixed frozen lock file ([@poorpaddy](https://github.com/poorpaddy)) 701 | 702 | #### Authors: 2 703 | 704 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 705 | - gary (gary_grumbley@intuit.com) 706 | 707 | --- 708 | 709 | # v1.0.23 (Thu Oct 03 2019) 710 | 711 | #### ⚠️ Pushed to master 712 | 713 | - Merge branch 'master' of https://github.com/intuit/LD-React-Components ([@poorpaddy](https://github.com/poorpaddy)) 714 | - remove storybook directory ([@poorpaddy](https://github.com/poorpaddy)) 715 | 716 | #### Authors: 1 717 | 718 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 719 | 720 | --- 721 | 722 | # v1.0.22 (Thu Oct 03 2019) 723 | 724 | #### ⚠️ Pushed to master 725 | 726 | - remove storybook directory ([@poorpaddy](https://github.com/poorpaddy)) 727 | 728 | #### Authors: 1 729 | 730 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 731 | 732 | --- 733 | 734 | # v1.0.21 (Thu Oct 03 2019) 735 | 736 | #### ⚠️ Pushed to master 737 | 738 | - remove storybook director ([@poorpaddy](https://github.com/poorpaddy)) 739 | 740 | #### Authors: 1 741 | 742 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 743 | 744 | --- 745 | 746 | # v1.0.20 (Thu Oct 03 2019) 747 | 748 | #### ⚠️ Pushed to master 749 | 750 | - troubleshooting docs ([@poorpaddy](https://github.com/poorpaddy)) 751 | 752 | #### Authors: 1 753 | 754 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 755 | 756 | --- 757 | 758 | # v1.0.19 (Wed Oct 02 2019) 759 | 760 | #### 🐛 Bug Fix 761 | 762 | - 18 Update CircleCI yaml to build storybook docs [#28](https://github.com/intuit/LD-React-Components/pull/28) (gary_grumbley@intuit.com [@ggrumbley](https://github.com/ggrumbley)) 763 | - Adding @ishubhamarora to contributor list [#29](https://github.com/intuit/LD-React-Components/pull/29) (shubham_arora@intuit.com) 764 | - updating ESLinting rules and fixing the linting issues [#27](https://github.com/intuit/LD-React-Components/pull/27) (shubham_arora@intuit.com) 765 | - 18 Add Storybook dependencies [#26](https://github.com/intuit/LD-React-Components/pull/26) (gary_grumbley@intuit.com [@ggrumbley](https://github.com/ggrumbley)) 766 | 767 | #### ⚠️ Pushed to master 768 | 769 | - corrected lockfile ([@poorpaddy](https://github.com/poorpaddy)) 770 | 771 | #### Authors: 4 772 | 773 | - Shubham Arora ([@ishubhamarora](https://github.com/ishubhamarora)) 774 | - poorpaddy ([@poorpaddy](https://github.com/poorpaddy)) 775 | - Gary Grumbley ([@ggrumbley](https://github.com/ggrumbley)) 776 | - gary (gary_grumbley@intuit.com) 777 | 778 | --- 779 | 780 | # v1.0.18 (Tue Oct 01 2019) 781 | 782 | #### ⚠️ Pushed to master 783 | 784 | - Add @Buranch as a contributor ([@poorpaddy](https://github.com/poorpaddy)) 785 | - Add @vvscode as a contributor ([@poorpaddy](https://github.com/poorpaddy)) 786 | 787 | #### Authors: 1 788 | 789 | - poorpaddy ([@poorpaddy](https://github.com/poorpaddy)) 790 | 791 | --- 792 | 793 | # v1.0.17 (Tue Oct 01 2019) 794 | 795 | #### ⚠️ Pushed to master 796 | 797 | - readme formatting changes (dave_bergschneider@intuit.com) 798 | 799 | #### Authors: 1 800 | 801 | - Bergschneider, Dave (dave_bergschneider@intuit.com) 802 | 803 | --- 804 | 805 | # v1.0.16 (Tue Oct 01 2019) 806 | 807 | #### ⚠️ Pushed to master 808 | 809 | - updated package.json and readme to reflect correct contributor commands. ([@poorpaddy](https://github.com/poorpaddy)) 810 | 811 | #### Authors: 1 812 | 813 | - poorpaddy ([@poorpaddy](https://github.com/poorpaddy)) 814 | 815 | --- 816 | 817 | # v1.0.15 (Tue Oct 01 2019) 818 | 819 | #### 🐛 Bug Fix 820 | 821 | - Fixing Contribution Generation issue [#24](https://github.com/intuit/LD-React-Components/pull/24) ([@hjaintech](https://github.com/hjaintech)) 822 | 823 | #### Authors: 1 824 | 825 | - Harshit Jain ([@hjaintech](https://github.com/hjaintech)) 826 | 827 | --- 828 | 829 | # v1.0.13 (Tue Oct 01 2019) 830 | 831 | #### 🐛 Bug Fix 832 | 833 | - updated all dependencies [#21](https://github.com/intuit/LD-React-Components/pull/21) ([@zjael](https://github.com/zjael) dave_bergschneider@intuit.com) 834 | 835 | #### ⚠️ Pushed to master 836 | 837 | - fixes lock file (dave_bergschneider@intuit.com) 838 | - Merge branch 'master' of https://github.com/intuit/LD-React-Components (dave_bergschneider@intuit.com) 839 | 840 | #### Authors: 2 841 | 842 | - Jakob S ([@zjael](https://github.com/zjael)) 843 | - Bergschneider, Dave (dave_bergschneider@intuit.com) 844 | 845 | --- 846 | 847 | # v1.0.12 (Fri Sep 27 2019) 848 | 849 | #### 🐛 Bug Fix 850 | 851 | - Update readme badge [#17](https://github.com/intuit/LD-React-Components/pull/17) ([@poorpaddy](https://github.com/poorpaddy)) 852 | 853 | #### Authors: 1 854 | 855 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 856 | 857 | --- 858 | 859 | # v1.0.11 (Fri Sep 27 2019) 860 | 861 | #### ⚠️ Pushed to master 862 | 863 | - custom commit message ([@hipstersmoothie](https://github.com/hipstersmoothie)) 864 | - fix docs ([@hipstersmoothie](https://github.com/hipstersmoothie)) 865 | 866 | #### Authors: 1 867 | 868 | - Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie)) 869 | 870 | --- 871 | 872 | # v1.0.10 (Fri Sep 27 2019) 873 | 874 | #### ⚠️ Pushed to master 875 | 876 | - corrected script name ([@poorpaddy](https://github.com/poorpaddy)) 877 | 878 | #### Authors: 1 879 | 880 | - poorpaddy ([@poorpaddy](https://github.com/poorpaddy)) 881 | 882 | --- 883 | 884 | # v1.0.9 (Fri Sep 27 2019) 885 | 886 | #### ⚠️ Pushed to master 887 | 888 | - correct json for gh-pages ([@poorpaddy](https://github.com/poorpaddy)) 889 | - changed docs publish command ([@poorpaddy](https://github.com/poorpaddy)) 890 | 891 | #### Authors: 1 892 | 893 | - poorpaddy ([@poorpaddy](https://github.com/poorpaddy)) 894 | 895 | --- 896 | 897 | # v1.0.8 (Fri Sep 27 2019) 898 | 899 | #### ⚠️ Pushed to master 900 | 901 | - Merge branch 'master' of https://github.com/intuit/LD-React-Components ([@poorpaddy](https://github.com/poorpaddy)) 902 | - changed docs publish command ([@poorpaddy](https://github.com/poorpaddy)) 903 | 904 | #### Authors: 1 905 | 906 | - poorpaddy ([@poorpaddy](https://github.com/poorpaddy)) 907 | 908 | --- 909 | 910 | # v1.0.6 (Wed Sep 25 2019) 911 | 912 | #### 🐛 Bug Fix 913 | 914 | - --force for push-dir [#15](https://github.com/intuit/LD-React-Components/pull/15) ([@vvscode](https://github.com/vvscode)) 915 | 916 | #### Authors: 1 917 | 918 | - Vasiliy Vanchuk ([@vvscode](https://github.com/vvscode)) 919 | 920 | --- 921 | 922 | # v1.0.5 (Mon Sep 23 2019) 923 | 924 | #### ⚠️ Pushed to master 925 | 926 | - NPM Dependencies ` (dave@cmscode.com) 927 | 928 | #### Authors: 1 929 | 930 | - poorpaddy (dave@cmscode.com) 931 | 932 | --- 933 | 934 | # v1.0.3 (Sat Sep 21 2019) 935 | 936 | #### 🐛 Bug Fix 937 | 938 | - Bump version to: 1.0.3 [#13](https://github.com/intuit/LD-React-Components/pull/13) ([@Buranch](https://github.com/Buranch)) 939 | 940 | #### Authors: 1 941 | 942 | - Buranch ([@Buranch](https://github.com/Buranch)) 943 | 944 | --- 945 | 946 | # v1.0.2 (Sat Sep 21 2019) 947 | 948 | #### 🐛 Bug Fix 949 | 950 | - gh-pages [#12](https://github.com/intuit/LD-React-Components/pull/12) ([@poorpaddy](https://github.com/poorpaddy)) 951 | 952 | #### Authors: 1 953 | 954 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 955 | 956 | --- 957 | 958 | # v1.0.1 (Fri Sep 20 2019) 959 | 960 | #### 🐛 Bug Fix 961 | 962 | - re-added gh-pages packages to troubleshoot doc builds [#9](https://github.com/intuit/LD-React-Components/pull/9) ([@poorpaddy](https://github.com/poorpaddy)) 963 | 964 | #### Authors: 1 965 | 966 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 967 | 968 | --- 969 | 970 | # v1.0.0 (Fri Sep 20 2019) 971 | 972 | #### 💥 Breaking Change 973 | 974 | - updated npm dependencies and correct package link on npm badge [#6](https://github.com/intuit/LD-React-Components/pull/6) ([@poorpaddy](https://github.com/poorpaddy)) 975 | 976 | #### Authors: 1 977 | 978 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 979 | 980 | --- 981 | 982 | # v0.0.10 (Wed Sep 11 2019) 983 | 984 | #### 🐛 Bug Fix 985 | 986 | - feat: update the plugin for the new feature flag payload and update tests [#4](https://github.com/intuit/LD-React-Components/pull/4) ([@Buranch](https://github.com/Buranch)) 987 | 988 | #### Authors: 1 989 | 990 | - Buranch ([@Buranch](https://github.com/Buranch)) 991 | 992 | --- 993 | 994 | # v0.0.9 (Fri Jul 19 2019) 995 | 996 | #### ⚠️ Pushed to master 997 | 998 | - corrected linting errors (dave@cmscode.com) 999 | - updated dependencies (dave@cmscode.com) 1000 | 1001 | #### Authors: 2 1002 | 1003 | - poorpaddy (dave@cmscode.com) 1004 | - poorpaddu (dave@cmscode.com) 1005 | 1006 | --- 1007 | 1008 | # v0.0.8 (Tue Jun 11 2019) 1009 | 1010 | #### ⚠️ Pushed to master 1011 | 1012 | - updated circleci config (dave_bergschneider@intuit.com) 1013 | 1014 | #### Authors: 1 1015 | 1016 | - Bergschneider, Dave (dave_bergschneider@intuit.com) 1017 | 1018 | --- 1019 | 1020 | # v0.0.7 (Tue Jun 11 2019) 1021 | 1022 | #### 🐛 Bug Fix 1023 | 1024 | - Added contributors section, license and updated some badges [#3](https://github.com/intuit/LD-React-Components/pull/3) ([@poorpaddy](https://github.com/poorpaddy)) 1025 | 1026 | #### Authors: 1 1027 | 1028 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 1029 | 1030 | --- 1031 | 1032 | # v0.0.6 (Tue Jun 11 2019) 1033 | 1034 | #### ⚠️ Pushed to master 1035 | 1036 | - initial commit (dave@cmscode.com) 1037 | 1038 | #### Authors: 1 1039 | 1040 | - poorpaddy (dave@cmscode.com) 1041 | 1042 | --- 1043 | 1044 | # v0.0.1 (Mon Jun 10 2019) 1045 | 1046 | #### 🐛 Bug Fix 1047 | 1048 | - Removing intuit [#1](https://github.com/intuit/LD-React-Components/pull/1) ([@poorpaddy](https://github.com/poorpaddy)) 1049 | 1050 | #### ⚠️ Pushed to master 1051 | 1052 | - [FP-] - testing docs (dave@cmscode.com) 1053 | - add auto ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1054 | - guhhh ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1055 | - more debug ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1056 | - remove debug info ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1057 | - need to build the docs first ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1058 | - get rid of unneeded config ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1059 | - debug ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1060 | - reverted (dave@cmscode.com) 1061 | - testing (dave@cmscode.com) 1062 | - reverting everything back (dave@cmscode.com) 1063 | - another approach (dave@cmscode.com) 1064 | - adding docs to build command (dave@cmscode.com) 1065 | - adding verbose (dave@cmscode.com) 1066 | - testing build and publish of docs (dave@cmscode.com) 1067 | - remved gh-pages from package (dave@cmscode.com) 1068 | - trying gh-pages (dave@cmscode.com) 1069 | - running both scripts (dave@cmscode.com) 1070 | - testing publsih (dave@cmscode.com) 1071 | - adding build command (dave@cmscode.com) 1072 | - reverting my stupid changes (dave@cmscode.com) 1073 | - ensure we can push to github ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1074 | - adding build to publish docs step (dave@cmscode.com) 1075 | - testing publish docs (dave@cmscode.com) 1076 | - updated dependencies and ensured both yarn and package lock is available (dave@cmscode.com) 1077 | - fixed tests (dave@cmscode.com) 1078 | - fixed linting (dave@cmscode.com) 1079 | - added clean script (dave@cmscode.com) 1080 | - set public path for dev ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1081 | - hmmm ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1082 | - nvm ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1083 | - set public path for publish ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1084 | - set up built docs + publishing ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1085 | - audit deps ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1086 | - set version to 0 while setting up ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1087 | - fix circle link ([@hipstersmoothie](https://github.com/hipstersmoothie)) 1088 | - wiped yarn lock file due to intuit registry (dave@cmscode.com) 1089 | - troubleshooting circleci (dave@cmscode.com) 1090 | - now I'm just being silly (dave@cmscode.com) 1091 | - changed to image badge (dave@cmscode.com) 1092 | - added token to badge (dave@cmscode.com) 1093 | - adding circleci badge to readme (dave@cmscode.com) 1094 | - updating a first draft of circleci config (dave@cmscode.com) 1095 | 1096 | #### Authors: 2 1097 | 1098 | - Dave Bergschneider ([@poorpaddy](https://github.com/poorpaddy)) 1099 | - Andrew Lisowski ([@hipstersmoothie](https://github.com/hipstersmoothie)) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Intuit 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 19 | OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /bot-usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intuit/LD-React-Components/2362c78f968b48ec8c8eeb6cea171a296cba15cb/bot-usage.png -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {extends: ['@commitlint/config-conventional']} 2 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Example 5 | 6 | 7 |
8 | 9 | 10 | -------------------------------------------------------------------------------- /ld-react-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intuit/LD-React-Components/2362c78f968b48ec8c8eeb6cea171a296cba15cb/ld-react-components.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ld-react-components", 3 | "version": "1.0.84", 4 | "description": "Semantic component helpers to support LaunchDarkly in your react app.", 5 | "main": "dist/index.js", 6 | "author": { 7 | "name": "Dave Bergschneider", 8 | "email": "dave@cmscode.com" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/intuit/LD-React-Components" 13 | }, 14 | "publishConfig": { 15 | "registry": "https://registry.npmjs.com/" 16 | }, 17 | "scripts": { 18 | "start": "start-storybook -p 6010", 19 | "prepare": "npm run snyk-protect && yarn build", 20 | "clean": "rimraf ./dist ./coverage ./docs ./test-results", 21 | "test": "yarn add --dev jest-junit && yarn build && jest --coverage --reporters=default --reporters=jest-junit && mkdir -p test-reports/jest && mv junit.xml test-reports/jest/results.xml", 22 | "lint": "eslint src/", 23 | "build": "babel src/lib -d dist --copy-files && tsc", 24 | "build:watch": "babel src/lib -w -d lib --copy-files", 25 | "docs:build": "build-storybook -o docs", 26 | "docs:config": "mkdirp ./docs/.circleci/ && cp .storybook/config.yml docs/.circleci/ && cp -R .storybook/old-docs docs/", 27 | "docs:publish": "push-dir --cleanup --dir=docs --branch=gh-pages --force", 28 | "release": "auto shipit", 29 | "snyk-protect": "snyk protect" 30 | }, 31 | "husky": { 32 | "hooks": { 33 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 34 | } 35 | }, 36 | "keywords": [ 37 | "launch-darkly", 38 | "feature", 39 | "flags", 40 | "react", 41 | "open source" 42 | ], 43 | "license": "MIT", 44 | "devDependencies": { 45 | "@babel/cli": "^7.8.4", 46 | "@babel/core": "^7.9.6", 47 | "@babel/plugin-proposal-class-properties": "^7.8.3", 48 | "@babel/plugin-proposal-object-rest-spread": "^7.9.6", 49 | "@babel/preset-env": "^7.9.6", 50 | "@babel/preset-react": "^7.9.4", 51 | "@babel/preset-typescript": "^7.9.0", 52 | "@commitlint/cli": "^11.0.0", 53 | "@commitlint/config-conventional": "^11.0.0", 54 | "@storybook/addon-a11y": "^6.0.26", 55 | "@storybook/addon-actions": "^6.0.26", 56 | "@storybook/addon-docs": "^6.0.26", 57 | "@storybook/addon-knobs": "^6.0.26", 58 | "@storybook/addon-links": "^6.0.26", 59 | "@storybook/addon-storysource": "^6.0.26", 60 | "@storybook/addons": "^6.0.26", 61 | "@storybook/preset-create-react-app": "^3.1.4", 62 | "@storybook/react": "^6.0.26", 63 | "@types/enzyme": "^3.10.5", 64 | "@types/enzyme-adapter-react-16": "^1.0.5", 65 | "@types/jest": "^24.0.18", 66 | "@types/node": "^12.7.10", 67 | "@types/react": "^16.9.4", 68 | "@types/react-dom": "^16.9.1", 69 | "@types/storybook__react": "^5.2.1", 70 | "all-contributors-cli": "^6.14.2", 71 | "auto": "^9.34.1", 72 | "awesome-typescript-loader": "^5.2.1", 73 | "babel-eslint": "^10.1.0", 74 | "babel-jest": "^26.0.1", 75 | "babel-loader": "^8.1.0", 76 | "chai": "^4.2.0", 77 | "concurrently": "^5.2.0", 78 | "css-loader": "^3.5.3", 79 | "enzyme": "^3.11.0", 80 | "enzyme-adapter-react-16": "^1.15.2", 81 | "eslint": "^7.0.0", 82 | "eslint-config-airbnb": "^18.1.0", 83 | "eslint-config-prettier": "^6.11.0", 84 | "eslint-config-standard": "~14.1.1", 85 | "eslint-plugin-import": "^2.20.2", 86 | "eslint-plugin-jsx-a11y": "^6.2.3", 87 | "eslint-plugin-node": "~11.1.0", 88 | "eslint-plugin-prettier": "^3.1.3", 89 | "eslint-plugin-promise": "~4.2.1", 90 | "eslint-plugin-react": "^7.20.0", 91 | "eslint-plugin-standard": "~4.0.1", 92 | "expect": "^26.0.1", 93 | "gh-pages": "^2.2.0", 94 | "html-webpack-plugin": "^4.3.0", 95 | "husky": "^4.3.0", 96 | "jest": "^26.0.1", 97 | "jest-junit": "^12.0.0", 98 | "jsdom": "16.2.2", 99 | "jsdom-global": "3.0.2", 100 | "mkdirp": "^1.0.4", 101 | "mocha": "^7.1.2", 102 | "nyc": "^15.0.1", 103 | "prettier": "^2.0.5", 104 | "push-dir": "^0.4.1", 105 | "react": "^16.10.1", 106 | "react-docgen-typescript-loader": "^3.7.2", 107 | "react-dom": "^16.3.2", 108 | "react-hot-loader": "^4.12.21", 109 | "react-scripts": "^3.4.3", 110 | "react-test-renderer": "^16.13.1", 111 | "sinon": "^9.0.2", 112 | "source-map-loader": "^0.2.4", 113 | "style-loader": "^1.2.1", 114 | "ts-jest": "^26.0.0", 115 | "typescript": "^3.9.3", 116 | "webpack": "^4.43.0", 117 | "webpack-cli": "^3.3.11", 118 | "webpack-dev-server": "^3.11.0" 119 | }, 120 | "dependencies": { 121 | "hash.js": "~1.1.7", 122 | "ldclient-js": "^2.10.2", 123 | "prop-types": "^15.7.2", 124 | "snyk": "^1.518.0" 125 | }, 126 | "peerDependencies": { 127 | "react": "^16.13.1", 128 | "react-dom": "^16.13.1" 129 | }, 130 | "snyk": true 131 | } 132 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |
2 | 4 |

LD React Components

5 |

Semantic component helpers to support LaunchDarkly in your react app.

6 |
7 | 8 | [![Build](https://img.shields.io/circleci/project/github/intuit/LD-React-Components/master.svg?style=flat-square&logo=circleci)](https://circleci.com/gh/intuit/LD-React-Components) 9 | [![Coverage](https://codecov.io/gh/intuit/LD-React-Components/branch/master/graph/badge.svg?token=L6URIkiDin)](https://codecov.io/gh/intuit/LD-React-Components) 10 | [![All Contributors](https://img.shields.io/badge/all_contributors-20-orange.svg?style=flat-square&logo=github)](#contributors) 11 | [![Npm](https://img.shields.io/npm/v/ld-react-components.svg?style=flat-square&logo=npm)](https://www.npmjs.com/package/ld-react-components) 12 | [![Downloads](https://img.shields.io/npm/dt/ld-react-components.svg?style=flat-square&logo=npm)](https://www.npmjs.com/package/ld-react-components) 13 | [![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/intuit/LD-React-Components/package.json.svg?style=flat-square&logo=snyk&logoColor=lightgrey)](https://app.snyk.io/org/poorpaddy/project/c1415dab-3e6f-4438-8e73-26a3e5ce9f55) 14 | [![License Scan](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fintuit%2FLD-React-Components.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fintuit%2FLD-React-Components?ref=badge_shield) 15 | [![Auto Release](https://img.shields.io/badge/release-auto.svg?style=flat-square&colorA=888888&colorB=9B065A&label=auto&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAACzElEQVR4AYXBW2iVBQAA4O+/nLlLO9NM7JSXasko2ASZMaKyhRKEDH2ohxHVWy6EiIiiLOgiZG9CtdgG0VNQoJEXRogVgZYylI1skiKVITPTTtnv3M7+v8UvnG3M+r7APLIRxStn69qzqeBBrMYyBDiL4SD0VeFmRwtrkrI5IjP0F7rjzrSjvbTqwubiLZffySrhRrSghBJa8EBYY0NyLJt8bDBOtzbEY72TldQ1kRm6otana8JK3/kzN/3V/NBPU6HsNnNlZAz/ukOalb0RBJKeQnykd7LiX5Fp/YXuQlfUuhXbg8Di5GL9jbXFq/tLa86PpxPhAPrwCYaiorS8L/uuPJh1hZFbcR8mewrx0d7JShr3F7pNW4vX0GRakKWVk7taDq7uPvFWw8YkMcPVb+vfvfRZ1i7zqFwjtmFouL72y6C/0L0Ie3GvaQXRyYVB3YZNE32/+A/D9bVLcRB3yw3hkRCdaDUtFl6Ykr20aaLvKoqIXUdbMj6GFzAmdxfWx9iIRrkDr1f27cFONGMUo/gRI/jNbIMYxJOoR1cY0OGaVPb5z9mlKbyJP/EsdmIXvsFmM7Ql42nEblX3xI1BbYbTkXCqRnxUbgzPo4T7sQBNeBG7zbAiDI8nWfZDhQWYCG4PFr+HMBQ6l5VPJybeRyJXwsdYJ/cRnlJV0yB4ZlUYtFQIkMZnst8fRrPcKezHCblz2IInMIkPzbbyb9mW42nWInc2xmE0y61AJ06oGsXL5rcOK1UdCbEXiVwNXsEy/6+EbaiVG8eeEAfxvaoSBnCH61uOD7BS1Ul8ESHBKWxCrdyd6EYNKihgEVrwOAbQruoytuBYIFfAc3gVN6iawhjKyNCEpYhVJXgbOzARyaU4hCtYizq5EI1YgiUoIlT1B7ZjByqmRWYbwtdYjoWoN7+LOIQefIqKawLzK6ID69GGpQgwhhEcwGGUzfEPAiPqsCXadFsAAAAASUVORK5CYII=)](https://github.com/intuit/LD-React-Components) 16 | [![Example](https://img.shields.io/badge/example-demo-blue.svg?style=flat-square&logo=github)](https://intuit.github.io/LD-React-Components/) 17 | 18 | 19 | ## Usage 20 | 21 | Install node module 22 | 23 | You can use `npm` or `yarn` however it is advised to choose one and stick with it. For the purposes of documentation `yarn` is being used. 24 | 25 | ```shell 26 | yarn add ld-react-components 27 | ``` 28 | 29 | ### Importing the components 30 | 31 | ```js 32 | import { 33 | FeatureFlag, 34 | FeatureSwitch, 35 | FeatureCase, 36 | FeatureTrue, 37 | FeatureFalse 38 | } from 'ld-react-components'; 39 | ``` 40 | 41 | #### API initialization 42 | 43 | ```js 44 | this._ldclientPromise = launchDarklyClient.initWithPromise( 45 | user, 46 | this._sdkKey, 47 | 500 48 | ); 49 | 50 | const endpoints = { 51 | baseUrl: 'https://app.launchdarkly.com', 52 | eventsUrl: 'https://events.launchdarkly.com', 53 | streamUrl: 'https://stream.launchdarkly.com', 54 | baseTimeout: 100 55 | }; 56 | 57 | this._ldclientPromise = launchDarklyClient.initWithPromise( 58 | user, 59 | this._sdkKey, 60 | endpoints, 61 | 500 62 | ); 63 | ``` 64 | 65 | ### FeatureFlag 66 | 67 | Takes `flagKey` and `appFlags` as `props`, which is an object containing list of features. 68 | 69 | ```jsx 70 | const applicationKeys = { 71 | 'integration-test': { value: true, version: 3 }, 72 | 'multivariate-test': { value: 'multivariate-test-1', version: 5 } 73 | } 74 | 75 | ``` 76 | 77 | ### FeatureSwitch, FeatureCase and FeatureDefault 78 | 79 | `FeatureSwitch` should be a child of `FeatureFlag` and can take `FeatureCase` and `FeatureDefault` as children. 80 | 81 | `FeatureCase` component takes `condition` and `allowBreak`(a boolean) as props, 82 | `condition` is the `case` feature, while `allowBreak` used as a `break`. The reason for name change is `case` and `break` are reserved words on JS. 83 | 84 | ```jsx 85 | 86 | 87 | 88 |

Multivariate Test 1 Rendered

89 |
90 | 91 |

Multivariate Test 2 Rendered

92 |
93 | 94 |

Multivariate Test 3 Rendered

95 |
96 | 97 |

Multivariate Test 4 Rendered

98 |
99 | 100 |

If no conditions are met then render the default

101 |
102 |
103 |
104 | ``` 105 | 106 | ### FeatureTrue and FeatureFalse 107 | 108 | ```jsx 109 | 110 | 111 |

If feature flag is true, then is content will render.

112 |
113 | 114 |

If feature flag is false, then is content will render.

115 |
116 |
117 | ``` 118 | 119 | ### Another Use Case 120 | 121 | ```js 122 | const applicationKeys = { 123 | 'multivariate-test': { value: 'multivariate-test-2', version: 1}, 124 | 'integration-test': { value: true } 125 | }; 126 | ``` 127 | 128 | ```jsx 129 | 130 |

This non-component should get rendered

131 | This is also should get rendered. 132 | This one should throw a warning and wont be rendred 133 | 134 | this one should throw a warning and wont be rendred 135 | 136 | 137 | 138 |

This one should throw an error and wont be rendred

139 |
140 |
141 |
142 | ``` 143 | 144 | ### Nested FeatureFlag 145 | 146 | ```js 147 | const applicationKeys = { 148 | 'multivariate-test': { value: 'multivariate-test-2' }, 149 | 'integration-test': { value: true } 150 | }; 151 | ``` 152 | 153 | ```jsx 154 | 155 |

This non-component will get rendered

156 | 157 | 158 | 159 |

Multivariate Test 1 Rendered

160 |
161 | 162 |

This one will get rendered(Multivariate Test 2 Rendered)

163 |
164 | 165 |

Multivariate Test 3 Rendered

166 |
167 | 168 |

This is the default content if no other cases are matched.

169 |
170 |
171 |
172 |
173 | ``` 174 | 175 | ## Using the React Hooks 176 | 177 | ```jsx 178 | const appFlags = { 179 | a: { value: 'a' }, 180 | b: { value: 'b' }, 181 | c: { value: 'c' }, 182 | d: { value: 'd' }, 183 | e: { value: 'e' } 184 | }; 185 | 186 | const UsingHooks = () => { 187 | const [count, setCount] = useState(65); 188 | return ( 189 |
190 | 191 | 195 | 196 | 197 | A is being rendered 198 | 199 | 200 | B is being rendered 201 | 202 | 203 | C is being rendered 204 | 205 | 206 | D is being rendered 207 | 208 | 209 | E is being rendered 210 | 211 | No value matches, this is default 212 | 213 | 214 |
215 | ); 216 | }; 217 | ``` 218 | 219 | ## Using the API 220 | 221 | ### Importing 222 | 223 | ```js 224 | import launchDarklyClient from 'ld-react-components/API'; 225 | 226 | const endpoints = { 227 | baseUrl: 'https://app.launchdarkly.com', 228 | eventsUrl: 'https://events.launchdarkly.com', 229 | streamUrl: 'https://stream.launchdarkly.com', 230 | baseTimeout: 100 231 | }; 232 | this._ldclientPromise = launchDarklyClient.initWithPromise(user, this._sdkKey, endpoints, 500); 233 | 234 | getFeatureFlag(featureId, defaultValue = false) { 235 | if (typeof window !== 'undefined') { 236 | return new Promise((resolve, reject) => { 237 | this._ldclientPromise 238 | .then((client) => { 239 | resolve(client.getFeatureFlag(featureId, defaultValue)); 240 | }) 241 | .catch((error) => { 242 | reject(error); 243 | }); 244 | }); 245 | } 246 | } 247 | ``` 248 | 249 | ## For development 250 | 251 | ### For the API 252 | 253 | #### Testing 254 | 255 | ```shell 256 | yarn 257 | yarn test 258 | ``` 259 | 260 | ### For React 261 | 262 | The module includes a demo demonstrating how to use the components 263 | 264 | ```shell 265 | yarn 266 | yarn dev 267 | ``` 268 | 269 | To see the demo go to http://localhost:8080 270 | 271 | ## Contributors ✨ 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 |

Dave Bergschneider

💻 🎨 📖 💡 🚧

Andrew Lisowski

🚇

Harshit Jain

📖

Jakob S

🚧

Vasiliy Vanchuk

🚇

Buranch

💻

Shubham Arora

💻

Gary Grumbley

🚇 📖

Bennett Hreherchuk

⚠️

Jose Diego

🚇 💻 📖 ⚠️

Sam Nesbitt

💻

Pramod

💻

Mohit Mayank

💻

ankita sinha

💻

Kausam

💻

Rohan Patel

📖

tekgal

🚇

Norman Yee

🚇

Himanshu Pant

📖

Trevor Erwin

🐛

Winter Faulk

🚧

Susmitha Kodamarthi

⚠️
308 | 309 | 310 | 311 | 312 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 313 | 314 | 315 | 316 | 317 | 318 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 319 | 320 | 321 | 322 | 323 | ### Adding a Contributor 324 | 325 | To add a contributor comment on Issue or Pull Request, asking @all-contributors to add a contributor:

326 | Example: `@all-contributors please add for `

327 | **`:`** See the [Emoji Key (Contribution Types Reference)](https://allcontributors.org/docs/en/emoji-key) for a list of valid contribution types. 328 | 329 | The bot will then create a Pull Request to add the contributor, then reply with the pull request details. 330 | 331 | 332 | 333 | ## License 334 | 335 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fintuit%2FLD-React-Components.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fintuit%2FLD-React-Components?ref=badge_large) 336 | -------------------------------------------------------------------------------- /src/lib/FeatureCase/index.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | /** 3 | * FeatureCase 4 | */ 5 | function FeatureCase(props) { 6 | const { children } = props; 7 | return React.Children.map(children, child => child); 8 | } 9 | 10 | export default FeatureCase; 11 | -------------------------------------------------------------------------------- /src/lib/FeatureDefault/index.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | /** 3 | * FeatureDefault 4 | */ 5 | function FeatureDefault(props) { 6 | const { children } = props; 7 | return React.Children.map(children, child => child); 8 | } 9 | 10 | export default FeatureDefault; 11 | -------------------------------------------------------------------------------- /src/lib/FeatureFalse/index.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | /** 3 | * FeatureFalse 4 | */ 5 | function FeatureFalse(props) { 6 | const { children } = props; 7 | return React.Children.map(children, child => child); 8 | } 9 | 10 | export default FeatureFalse; 11 | -------------------------------------------------------------------------------- /src/lib/FeatureFlag/FeatureFlag.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { withKnobs, text, object } from '@storybook/addon-knobs'; 3 | 4 | import FeatureFlag from './index.tsx'; 5 | import FeatureSwitch from '../FeatureSwitch'; 6 | import FeatureCase from '../FeatureCase'; 7 | import FeatureDefault from '../FeatureDefault'; 8 | import FeatureTrue from '../FeatureTrue'; 9 | import FeatureFalse from '../FeatureFalse'; 10 | 11 | import notes from './README.md'; 12 | 13 | export default { 14 | title: 'Component|Feature Flag', 15 | decorators: [withKnobs], 16 | component: FeatureFlag, 17 | parameters: { notes } 18 | }; 19 | 20 | const applicationKeys = { 21 | 'integration-test': true, 22 | 'multivariate-test': 'multivariate-test-1' 23 | }; 24 | 25 | export const standardUsage = () => ( 26 | 30 | 31 | 32 |

Multivariate Test 1 Rendered

33 |
34 | 35 |

Multivariate Test 2 Rendered

36 |
37 | 38 |

Multivariate Test 3 Rendered

39 |
40 | 41 |

Multivariate Test 4 Rendered

42 |
43 | 44 |

If no conditions are met then render the default

45 |
46 |
47 |
48 | ); 49 | 50 | export const withFeatureTrueAndFeatureFalse = () => ( 51 | 52 | Output: FeatureTrue being rendered 53 | Output: FeatureFalse being rendered 54 | 55 | ); 56 | 57 | export const withNesting = () => { 58 | const flags = { 59 | 'nested-flag-key': 'nested-flag-key-1' 60 | }; 61 | return ( 62 | 63 |

64 | A non-component (in this case, a p tag) is being rendered, under the parent FeatureFlag 65 | component. Check out the story below to see the code. 66 |

67 | 68 | 69 | 70 |

Nested feature 1 Rendered

71 |
72 | 73 |

Nested feature 2 Rendered

74 |
75 | 76 |

Nested feature 3 Rendered

77 |
78 | 79 |

This is the default content if no other cases are matched.

80 |
81 |
82 |
83 |
84 | ); 85 | }; 86 | -------------------------------------------------------------------------------- /src/lib/FeatureFlag/README.md: -------------------------------------------------------------------------------- 1 | ### FeatureFlag 2 | 3 | Takes `flagKey` and `appFlags` as `props`, which is an object containing list of features. 4 | 5 | ### FeatureSwitch, FeatureCase and FeatureDefault 6 | 7 | `FeatureSwitch` should be a child of `FeatureFlag` and can take `FeatureCase` and `FeatureDefault` as children. 8 | 9 | `FeatureCase` component takes `condition` and `allowBreak`(a boolean) as props, 10 | `condition` is the `case` feature, while `allowBreak` used as a `break`. The reason for name change is `case` and `break` are reserved words on JS. -------------------------------------------------------------------------------- /src/lib/FeatureFlag/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | /** 4 | * FeatureFlag 5 | */ 6 | function FeatureFlag(props) { 7 | const { children, flagKey, appFlags } = props; 8 | // isChildPluginComponent is true if the child is one of 9 | // [ FeatureFlag, FeatureTrue, FeatureSwitch, FeatureFalse, FeatureDefault] 10 | let isChildPluginComponent = false; 11 | // isNonPluginComponent is true if the child is not a component from this plugin. 12 | let isNonPluginComponent = false; 13 | // childArray to render 14 | const childArray = []; 15 | React.Children.forEach(children, (element) => { 16 | if ( 17 | React.isValidElement(element) && 18 | (element.type.displayName === 'FeatureTrue' || element.type.name === 'FeatureTrue') 19 | ) { 20 | if (isNonPluginComponent) { 21 | // telling the developer to not use NonPlugin components under FeatureFlag. 22 | // eslint-disable-next-line no-console 23 | console.warn( 24 | 'Dont Use among other elements/components under only use it with , No mix allowed' 25 | ); 26 | return; 27 | } 28 | // if the appFlags has the flagKey, render the child 29 | if (appFlags[flagKey]) { 30 | childArray.push(element); 31 | } 32 | isChildPluginComponent = true; 33 | } 34 | 35 | if ( 36 | React.isValidElement(element) && 37 | (element.type.displayName === 'FeatureFalse' || element.type.name === 'FeatureFalse') 38 | ) { 39 | if (isNonPluginComponent) { 40 | // eslint-disable-next-line no-console 41 | console.warn( 42 | 'Dont Use among other elements/components under only use it with , No mix allowed' 43 | ); 44 | return; 45 | } 46 | if (!appFlags[flagKey]) { 47 | childArray.push(element); 48 | } 49 | isChildPluginComponent = true; 50 | } 51 | // } 52 | 53 | if ( 54 | React.isValidElement(element) && 55 | (element.type.displayName === 'FeatureSwitch' || element.type.name === 'FeatureSwitch') 56 | ) { 57 | if (isNonPluginComponent) { 58 | // eslint-disable-next-line no-console 59 | console.warn( 60 | 'Dont Use unless its the immediate children of , No mix allowed' 61 | ); 62 | return; 63 | } 64 | childArray.push( 65 | React.cloneElement(element, { 66 | flagKey, 67 | appFlags 68 | }) 69 | ); 70 | isChildPluginComponent = true; 71 | } 72 | // if the component is neither of the above components it must be NonPlugin Component, 73 | // therefore, we simply render it as its under FeatureTrue 74 | if (!isChildPluginComponent) { 75 | isNonPluginComponent = true; 76 | if (appFlags[flagKey]) { 77 | childArray.push(element); 78 | } 79 | } 80 | }); 81 | 82 | return React.Children.map(childArray, (child) => child); 83 | } 84 | 85 | FeatureFlag.propTypes = { 86 | flagKey: PropTypes.string.isRequired, 87 | // eslint-disable-next-line react/forbid-prop-types 88 | appFlags: PropTypes.object.isRequired 89 | }; 90 | 91 | export default FeatureFlag; 92 | -------------------------------------------------------------------------------- /src/lib/FeatureFlag/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | /** 4 | * FeatureFlag Props 5 | */ 6 | type FeatureFlagProps = { 7 | children?: React.ReactNode; 8 | flagKey: string; 9 | appFlags: object; 10 | } 11 | 12 | /** 13 | * FeatureFlag renders your child components based on LD flags 14 | */ 15 | function FeatureFlag({ children, flagKey, appFlags }: FeatureFlagProps) { 16 | function elementMatchPluginName(element: any, name: string) { 17 | return (element.type.displayName === name || element.type.name === name) 18 | } 19 | // isChildPluginComponent is true if the child is one of 20 | // [ FeatureFlag, FeatureTrue, FeatureSwitch, FeatureFalse, FeatureDefault] 21 | let isChildPluginComponent = false; 22 | // isNonPluginComponent is true if the child is not a component from this plugin. 23 | let isNonPluginComponent = false; 24 | // childArray to render 25 | const childArray: React.ReactNode[] = []; 26 | React.Children.forEach(children, element => { 27 | if ( 28 | React.isValidElement(element) && elementMatchPluginName(element, 'FeatureTrue') 29 | ) { 30 | if (isNonPluginComponent) { 31 | // telling the developer to not use NonPlugin components under FeatureFlag. 32 | // eslint-disable-next-line no-console 33 | console.warn( 34 | 'Dont Use among other elements/components under only use it with , No mix allowed' 35 | ); 36 | return; 37 | } 38 | // if the appFlags has the flagKey, render the child 39 | if (appFlags[flagKey]) { 40 | childArray.push(element); 41 | } 42 | isChildPluginComponent = true; 43 | } 44 | 45 | if ( 46 | React.isValidElement(element) && elementMatchPluginName(element, 'FeatureFalse') 47 | ) { 48 | if (isNonPluginComponent) { 49 | // eslint-disable-next-line no-console 50 | console.warn( 51 | 'Dont Use among other elements/components under only use it with , No mix allowed' 52 | ); 53 | return; 54 | } 55 | if (!appFlags[flagKey]) { 56 | childArray.push(element); 57 | } 58 | isChildPluginComponent = true; 59 | } 60 | // } 61 | 62 | if ( 63 | React.isValidElement(element) && elementMatchPluginName(element, 'FeatureSwitch') 64 | ) { 65 | if (isNonPluginComponent) { 66 | // eslint-disable-next-line no-console 67 | console.warn( 68 | 'Dont Use unless its the immediate children of , No mix allowed' 69 | ); 70 | return; 71 | } 72 | const partial: Partial<{}> = {}; 73 | partial['flagKey'] = flagKey; 74 | partial['appFlags'] = appFlags; 75 | childArray.push( 76 | React.cloneElement(element, partial) 77 | ); 78 | isChildPluginComponent = true; 79 | } 80 | // if the component is neither of the above components it must be NonPlugin Component, 81 | // therefore, we simply render it as its under FeatureTrue 82 | if (!isChildPluginComponent) { 83 | isNonPluginComponent = true; 84 | if (appFlags[flagKey]) { 85 | childArray.push(element); 86 | } 87 | } 88 | }); 89 | 90 | return React.Children.map(childArray, child => child); 91 | } 92 | 93 | export default FeatureFlag; -------------------------------------------------------------------------------- /src/lib/FeatureSwitch/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import FeatureCase from '../FeatureCase'; 3 | import FeatureDefault from '../FeatureDefault'; 4 | 5 | interface IAppFlag { 6 | value: any, 7 | version: number, 8 | variation: number, 9 | trackEvents: boolean 10 | } 11 | 12 | interface IComponentProps { 13 | flagKey: string; 14 | appFlags: { 15 | [x: string]: IAppFlag; 16 | }; 17 | } 18 | 19 | /** 20 | * FeatureSwitch 21 | */ 22 | const FeatureSwitch: React.FC = (props) => { 23 | const { children, flagKey, appFlags } = props; 24 | 25 | const childArray: React.ReactNode[] = []; 26 | 27 | let breakIt = false; 28 | 29 | React.Children.forEach(children, element => { 30 | // if the Component is FeatureCase and break is false, compare the feature flag and render the element if its true 31 | if (React.isValidElement(element) && (element as any).type === FeatureCase && !breakIt) { 32 | // TODO use proper type cast here once they are defined 33 | const { condition, allowBreak } = (element as any).props; 34 | if (appFlags[flagKey] === condition) { 35 | childArray.push(element); 36 | breakIt = allowBreak; 37 | } 38 | } 39 | // if its Default and it is not breaked yet, render the element. 40 | if (React.isValidElement(element) && (element as any).type === FeatureDefault && !breakIt) { 41 | childArray.push(element); 42 | } 43 | }); 44 | 45 | return {childArray}; 46 | }; 47 | 48 | export default FeatureSwitch; 49 | -------------------------------------------------------------------------------- /src/lib/FeatureTrue/index.ts: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from 'react'; 2 | /** 3 | * FeatureTrue 4 | */ 5 | 6 | type FeatureTrueProps = { 7 | children: ReactNode 8 | } 9 | 10 | const FeatureTrue = ({ children }: FeatureTrueProps) => React.Children.map(children, (child: ReactNode) => child); 11 | 12 | export default FeatureTrue; 13 | -------------------------------------------------------------------------------- /src/lib/LaunchDarklyClient/index.ts: -------------------------------------------------------------------------------- 1 | import hash from 'hash.js'; 2 | import * as LDClient from 'ldclient-js'; 3 | 4 | interface IUser extends LDClient.LDUser { 5 | authId: string 6 | } 7 | interface IOptions extends LDClient.LDOptions { 8 | baseTimeout: number 9 | } 10 | interface IClientParams { 11 | user: IUser 12 | envClientKey: string 13 | options: IOptions 14 | } 15 | interface IInitParams { 16 | clientParams: IClientParams 17 | timeout: number 18 | logUpdates?: boolean 19 | } 20 | 21 | 22 | class LDApi { 23 | 24 | private ldClient: LDClient.LDClient; 25 | private readonly env: String; 26 | 27 | constructor(env: string) { 28 | this.env = env; 29 | } 30 | 31 | init({clientParams:{user, envClientKey, options}, timeout, logUpdates=false}: IInitParams) { 32 | // makes the flags available to the client 33 | this.ldClient = this.createClient({user, envClientKey, options}); 34 | if (!options) { 35 | // eslint-disable-next-line no-console 36 | return console.log('Endpoint Options is not provided'); 37 | } 38 | // returns the library and it's methods to use outside of the module 39 | // eslint-disable-next-line no-param-reassign 40 | this.handleEvents((timeout = options.baseTimeout), this.ldClient, logUpdates); 41 | return this; 42 | } 43 | 44 | /** 45 | * Initializes the launch darkly client and returns a promise to ensure that 46 | * methods won't be called until the client emits the 'ready' event 47 | */ 48 | initWithPromise({clientParams:{user, envClientKey, options}, timeout, logUpdates=false}: IInitParams): Promise { 49 | this.ldClient = this.createClient({user, envClientKey, options}); 50 | 51 | return new Promise((resolve, reject) => { 52 | return this.handleEvents(timeout, this.ldClient, logUpdates, resolve, reject); 53 | }); 54 | } 55 | 56 | /** 57 | * Create the LD client 58 | * 59 | * @param user user object 60 | * @param envClientKey SDK key for the env 61 | * @returns {LDClient.LDClient} fresh instance of launch darkly client 62 | */ 63 | createClient({user, envClientKey, options}: IClientParams): LDClient.LDClient { 64 | if (typeof user.authId === 'undefined') { 65 | throw new Error('AuthId was not passed to launchDarkly client'); 66 | } 67 | 68 | if (!envClientKey) { 69 | throw new Error('There was no environment key provided.'); 70 | } 71 | 72 | const ldUser = { 73 | key: hash 74 | .sha256() 75 | .update(user.authId) 76 | .digest('hex'), 77 | custom: {} 78 | }; 79 | 80 | // take whatever is in the tags object and put it into the user object 81 | /* eslint-disable no-restricted-syntax, guard-for-in */ 82 | // TO-DO: check if inherited properties of obj 'user' has to iterated or not 83 | // and remove these eslint-disable as per that. 84 | for (const key in user) { 85 | let userKey = key; 86 | if (key.indexOf('_') > -1) { 87 | userKey = key.replace('_', ''); 88 | } 89 | 90 | if (key === 'authId') { 91 | // eslint-disable-next-line no-param-reassign 92 | user[key] = hash 93 | .sha256() 94 | .update(user[key]) 95 | .digest('hex'); 96 | } 97 | 98 | ldUser.custom[userKey] = user[key]; 99 | } 100 | /* eslint-enable */ 101 | 102 | return this.env === 'test' 103 | ? LDClient.default.initialize(envClientKey, ldUser, options) 104 | : LDClient.initialize(envClientKey, ldUser, options); 105 | } 106 | 107 | /** 108 | * LD client posts events. This function handles them. 109 | * First set a timeout for the ready event. 110 | * If it takes too long time out. 111 | * Log updates when they happen 112 | * 113 | * @param timeout LD client timeout 114 | * @param ldClient initialized client 115 | * @param logUpdates Set to true if you want to see the update events 116 | */ 117 | // eslint-disable-next-line no-unused-vars 118 | handleEvents(timeout:number, ldClient:LDClient.LDClient, logUpdates = false, resolve?, reject?) { 119 | if (ldClient === undefined) { 120 | const error = new Error('ERROR: ldClient is undefined'); 121 | if (reject !== undefined) { 122 | return reject(error); 123 | } 124 | throw error; 125 | } 126 | 127 | const initTimeout = setTimeout(() => { 128 | clearTimeout(initTimeout); 129 | const error = new Error('ERROR: Creation of Launch Darkly client has timed out'); 130 | if (reject !== undefined) { 131 | return reject(error); 132 | } 133 | throw error; 134 | }, timeout); 135 | 136 | ldClient.on('error', error => { 137 | if (reject !== undefined) { 138 | return reject(error); 139 | } 140 | throw error; 141 | }); 142 | 143 | ldClient.on('ready', () => { 144 | clearTimeout(initTimeout); 145 | 146 | if (resolve !== undefined) { 147 | return resolve(this); 148 | } 149 | return undefined; 150 | }); 151 | return undefined; 152 | } 153 | 154 | /** 155 | * Grab the feature flag value. If the LD client does not exist return the default 156 | * value. 157 | * 158 | * @param featureId LD feature flag id 159 | * @param defaultValue boolean value that is the default (this is used we can get the feature flag from LD) 160 | * @returns {any} Value of feature flag. Flags can be boolean or enums, depending on their configuration 161 | */ 162 | getFeatureFlag(featureId: string, defaultValue: boolean) { 163 | if (defaultValue === undefined) { 164 | throw new Error('Default value must be passed to getPromiseFeatureFlag'); 165 | } 166 | if (!this.ldClient) { 167 | return defaultValue; 168 | } 169 | // eslint-disable-next-line no-console 170 | console.log('featureId ', featureId); 171 | if (!featureId) { 172 | throw new Error('ERROR: featureId is undefined'); 173 | } 174 | return this.ldClient.variation(featureId, defaultValue); 175 | } 176 | 177 | /** 178 | * Grab the feature flag value resolved as a Promise If the LD client does not exist return the default 179 | * value. 180 | * 181 | * @param featureFlag LD feature flag id 182 | * @param defaultValue boolean value (this is used we can get the feature flag from LD) 183 | * @returns {Promise} Value of feature flag as a promise. 184 | * Flags can be boolean or enums, depending on their configuration 185 | */ 186 | getPromiseFeatureFlag(featureFlag: string, defaultValue: boolean): Promise { 187 | return new Promise(resolve => { 188 | resolve(this.getFeatureFlag(featureFlag, defaultValue)); 189 | }); 190 | } 191 | 192 | /** 193 | * Grab All feature flags for the user. If the LD client does not exist, return the default 194 | * value. 195 | * 196 | * @returns {LDClient.LDFlagSet} Value of feature flags. Flags can be boolean or enums, depending on their configuration 197 | */ 198 | 199 | getAllFlags(): LDClient.LDFlagSet { 200 | if (!this.ldClient) { 201 | return {}; 202 | } 203 | 204 | return this.ldClient.allFlags(); 205 | } 206 | } 207 | 208 | module.exports = LDApi; 209 | -------------------------------------------------------------------------------- /src/lib/index.js: -------------------------------------------------------------------------------- 1 | import FeatureDefault from './FeatureDefault'; 2 | import FeatureTrue from './FeatureTrue'; 3 | import FeatureSwitch from './FeatureSwitch'; 4 | import FeatureCase from './FeatureCase'; 5 | import FeatureFalse from './FeatureFalse'; 6 | import FeatureFlag from './FeatureFlag'; 7 | import launchDarklyClient from './LaunchDarklyClient'; 8 | 9 | module.exports = { 10 | FeatureDefault, 11 | FeatureTrue, 12 | FeatureSwitch, 13 | FeatureFalse, 14 | FeatureFlag, 15 | FeatureCase, 16 | launchDarklyClient 17 | }; 18 | -------------------------------------------------------------------------------- /test-reports/jest/results.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /test/__snapshots__/react.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Launch Darkly Plugin FeatureFlag: should not render component if flagKey does not exist in appFlags object 1`] = `""`; 4 | 5 | exports[`Launch Darkly Plugin FeatureFlag: should not render component if flagKey value is false in appFlags object 1`] = `""`; 6 | 7 | exports[`Launch Darkly Plugin FeatureFlag: should not render either FeatureTrue or FeatureFalse when it gets mixed with NonPluginElement and should throw a warnring 1`] = ` 8 | "
9 | Non Plugin Element 10 |
" 11 | `; 12 | 13 | exports[`Launch Darkly Plugin FeatureFlag: should not render the FeatureSwitch and throw a warning when FeatureSwitch gets mixed with NonPlugin elements 1`] = ` 14 | " 15 |
16 | Hello 17 |
18 |
" 19 | `; 20 | 21 | exports[`Launch Darkly Plugin FeatureFlag: should render component if flagKey value is true in appFlags object 1`] = ` 22 | "
23 | hello 24 |
" 25 | `; 26 | 27 | exports[`Launch Darkly Plugin FeatureFlag: should render only the FeatureFalse when flagKey value is false 1`] = ` 28 | " 29 | 30 |
31 | Gets rendered when flagKey value is false 32 |
33 |
34 |
" 35 | `; 36 | 37 | exports[`Launch Darkly Plugin FeatureFlag: should render only the FeatureTrue when flagKey value is true 1`] = ` 38 | " 39 | 40 |
41 | Gets rendered when flagKey value is true 42 |
43 |
44 |
" 45 | `; 46 | 47 | exports[`Launch Darkly Plugin FeatureSwitch: renders the FeatureCase component that matches the flagKey 1`] = ` 48 | " 49 | 50 | 51 |

52 | Multivariate Test 1 Rendered 53 |

54 |
55 |
56 |
" 57 | `; 58 | 59 | exports[`Launch Darkly Plugin FeatureSwitch: renders the FeatureDefault component when the no FeatureCase found that matches the flagKey 1`] = ` 60 | " 61 | 62 | 63 |

64 | If no conditions are met then render the default 65 |

66 |
67 |
68 |
" 69 | `; 70 | -------------------------------------------------------------------------------- /test/main.test.js: -------------------------------------------------------------------------------- 1 | import sinon from 'sinon'; 2 | import { expect } from 'chai'; 3 | import LDClient from 'ldclient-js'; 4 | import LDApi from '../src/lib/LaunchDarklyClient'; 5 | 6 | const config = { 7 | environment: 'development', 8 | features: { 9 | default: { 10 | client_key: 'somekey' 11 | }, 12 | development: { 13 | client_key: 'somekey' 14 | }, 15 | user: { 16 | key: 'test_user' 17 | }, 18 | timeout: 500 19 | } 20 | }; 21 | 22 | const options = { 23 | baseUrl: 'https://app.launchdarkly.com', 24 | eventsUrl: 'https://events.launchdarkly.com', 25 | streamUrl: 'https://stream.launchdarkly.com', 26 | baseTimeout: 100 27 | }; 28 | 29 | // mock values to return from mocked functions 30 | const featureValue = true; 31 | 32 | const flags = { 33 | 'forms-mode': false, 34 | 'other-forms-mode': false 35 | }; 36 | 37 | const user = { authId: 'ode_user', country: 'USA' }; 38 | 39 | const envClientKey = '59x74xxxx9x1x30x6x0x3xxx'; 40 | 41 | // mock func to init launch darkly 42 | // let ldInit = () => {}; 43 | let ldClient; 44 | 45 | const variation = () => featureValue; 46 | 47 | // Call the callback after 250ms to simulate the delay launch darkly has 48 | const on = (event, cb) => { 49 | setTimeout(() => { 50 | if (event === 'ready') { 51 | cb(); 52 | } 53 | }, 10); 54 | }; 55 | 56 | const allFlags = () => flags; 57 | 58 | const errorMessage = 'ERROR: Creation of Launch Darkly client has timed out'; 59 | const timeout = 500; 60 | 61 | describe('Launch Darkly:', () => { 62 | beforeEach(() => { 63 | ldClient = sinon.stub(LDClient, 'initialize').callsFake(() => { 64 | return { 65 | allFlags, 66 | variation, 67 | on 68 | }; 69 | }); 70 | }); 71 | 72 | afterEach(() => { 73 | if (ldClient !== undefined) { 74 | ldClient.restore(); 75 | } 76 | }); 77 | 78 | it('init', () => { 79 | const ldApi = new LDApi('test'); 80 | const client = ldApi.init({clientParams:{user, envClientKey, options}, timeout}); 81 | expect(client !== undefined).to.equal(true); 82 | }); 83 | 84 | it('init without option should throw warning', () => { 85 | const ldApi = new LDApi('test'); 86 | const client = ldApi.init({clientParams:{user, envClientKey, options:null}, timeout}); 87 | console.log('client on without ', client); 88 | expect(client === undefined).to.equal(true); 89 | }); 90 | 91 | it('initPromise', done => { 92 | const ldApi = new LDApi('test'); 93 | 94 | ldApi.initWithPromise({clientParams:{user, envClientKey, options}, timeout}).then(client => { 95 | expect(client !== undefined).to.equal(true); 96 | done(); 97 | }); 98 | }); 99 | 100 | it('createClient', done => { 101 | const ldApi = new LDApi('test'); 102 | 103 | const client = ldApi.createClient({user, envClientKey, options}); 104 | expect(client !== undefined).to.equal(true); 105 | done(); 106 | }); 107 | 108 | it('createClient accepts underscored user keys', done => { 109 | const ldApi = new LDApi('test'); 110 | const usser = { ...user, key_With_Underscore: 'test' }; 111 | const client = ldApi.createClient({user:usser, envClientKey, options}); 112 | expect(client !== undefined).to.equal(true); 113 | done(); 114 | }); 115 | 116 | it('createClient no user', done => { 117 | const ldApi = new LDApi('test'); 118 | 119 | try { 120 | ldApi.createClient({user:undefined, envClientKey, options}); 121 | } catch (ex) { 122 | expect(ex !== null).to.equal(true); 123 | done(); 124 | } 125 | }); 126 | 127 | it('createClient no client key', done => { 128 | const ldApi = new LDApi('test'); 129 | 130 | try { 131 | ldApi.createClient({user, envClientKey:null, options}); 132 | } catch (ex) { 133 | expect(ex !== null).to.equal(true); 134 | done(); 135 | } 136 | }); 137 | 138 | it('createClient no user authID key', done => { 139 | const ldApi = new LDApi('test'); 140 | 141 | const userr = {}; 142 | try { 143 | ldApi.createClient({user:userr, envClientKey:null, options}); 144 | } catch (ex) { 145 | expect(ex !== null).to.equal(true); 146 | done(); 147 | } 148 | }); 149 | 150 | it('handleEvents', done => { 151 | const ldApi = new LDApi('test'); 152 | 153 | const client = ldApi.createClient({user, envClientKey, options}); 154 | ldApi.handleEvents(timeout, client); 155 | expect(true).to.equal(true); 156 | done(); 157 | }); 158 | 159 | it('handleEvents promise', done => { 160 | const ldApi = new LDApi('test'); 161 | 162 | new Promise((resolve, reject) => { 163 | const client = ldApi.createClient({user, envClientKey, options}); 164 | ldApi.handleEvents(timeout, client, false, resolve, reject); 165 | }).then( 166 | resolve => { 167 | expect(true).to.equal(true); 168 | done(); 169 | }, 170 | reject => { 171 | expect(reject !== undefined).to.equal(true); 172 | done(); 173 | } 174 | ); 175 | }); 176 | 177 | it('handleEvents no client', done => { 178 | const ldApi = new LDApi('test'); 179 | 180 | try { 181 | ldApi.handleEvents(timeout); 182 | } catch (ex) { 183 | expect(ex !== null).to.equal(true); 184 | expect(ex.message === 'ERROR: ldClient is undefined').to.equal(true); 185 | done(); 186 | } 187 | }); 188 | 189 | it('handleEvents no client with reject callback', done => { 190 | const ldApi = new LDApi('test'); 191 | const reject = error => { 192 | expect(error !== null).to.equal(true); 193 | expect(error.message === 'ERROR: ldClient is undefined').to.equal(true); 194 | done(); 195 | }; 196 | 197 | ldApi.handleEvents(timeout, undefined, undefined, undefined, reject); 198 | }); 199 | 200 | it('handleEvents timeout with reject callback', done => { 201 | const ldApi = new LDApi('test'); 202 | 203 | new Promise((resolve, reject) => { 204 | const client = ldApi.createClient({user, envClientKey, options}); 205 | ldApi.handleEvents(1, client, false, resolve, reject); 206 | }).then( 207 | resolve => {}, 208 | reject => { 209 | expect(reject.message).to.equal('ERROR: Creation of Launch Darkly client has timed out'); 210 | done(); 211 | } 212 | ); 213 | }); 214 | 215 | it('handleEvents error event', done => { 216 | const events = {}; 217 | const ldApi = new LDApi(); 218 | const mockClient = { 219 | emit: (event, ...args) => (events[event] ? events[event](...args) : null), 220 | on: (event, cb) => { 221 | events[event] = cb; 222 | } 223 | }; 224 | ldApi.handleEvents(timeout, mockClient, false, null, error => { 225 | expect(error.message).to.equal('Testing Error'); 226 | done(); 227 | }); 228 | mockClient.emit('error', Error('Testing Error')); 229 | }); 230 | 231 | it('getFeatureFlag throws and error when there is no default value provided', done => { 232 | const noClientLDAPI = new LDApi('test'); 233 | noClientLDAPI.init({clientParams:{user, envClientKey, options}, timeout:500, LDClient}); 234 | 235 | try { 236 | noClientLDAPI.getFeatureFlag(undefined, 'defaultValue'); 237 | done(); 238 | } catch (ex) { 239 | expect(ex !== null).to.equal(true); 240 | // eslint-disable 241 | expect(ex.message === 'ERROR: featureId is undefined').to.equal(true); 242 | done(); 243 | } 244 | try { 245 | noClientLDAPI.getFeatureFlag(config.features); 246 | done(); 247 | } catch (ex) { 248 | expect(ex !== null).to.equal(true); 249 | // eslint-disable 250 | expect(ex.message).to.equal('Default value must be passed to getPromiseFeatureFlag'); 251 | } 252 | }); 253 | 254 | it('getFeatureFlag returns default value when there is no ldClient but a default value(false) is provided', done => { 255 | const noClientLDAPI = new LDApi('test'); 256 | const expected = false; 257 | const actual = noClientLDAPI.getFeatureFlag(config.features, false); 258 | // t.is(actual, expected); 259 | expect(actual).to.equal(expected); 260 | done(); 261 | }); 262 | 263 | it("getAllFlags returns an empty object if the ldclient doesn't exist", done => { 264 | const noClientLDAPI = new LDApi('test'); 265 | const expected = {}; 266 | const actual = noClientLDAPI.getAllFlags(); 267 | expect(actual).to.deep.equal(expected); 268 | done(); 269 | }); 270 | 271 | it('LD API initializes with appropriate api', done => { 272 | // Initialize the api with the mocked LDClient and the config 273 | const ldApi = new LDApi('test'); 274 | 275 | ldApi.init({clientParams:{user, envClientKey, options}, timeout:500}); 276 | expect(typeof ldApi.getFeatureFlag).to.equal('function'); 277 | expect(typeof ldApi.getAllFlags).to.equal('function'); 278 | done(); 279 | }); 280 | 281 | it('LD API returns promise that will return a ready client', done => { 282 | const ldApi = new LDApi('test'); 283 | 284 | // The 'ready' event will be emitted within 500ms, resolving the promise and returning the client 285 | ldApi.initWithPromise({clientParams:{user, envClientKey, options}, timeout:500}).then(client => { 286 | expect(typeof client.getFeatureFlag).to.equal('function'); 287 | expect(typeof client.getAllFlags).to.equal('function'); 288 | done(); 289 | }); 290 | }); 291 | 292 | it('LD API returns promise that rejects if the client does not initialize in time', done => { 293 | const ldApi = new LDApi('test'); 294 | 295 | // Only wait 100ms for the on ready event, the promise will reject 296 | ldApi.initWithPromise({clientParams:{user, envClientKey, options}, timeout:1}).catch(err => { 297 | expect(err.message).to.deep.equal(errorMessage); 298 | done(); 299 | // t.deepEqual(err.message, errorMessage); 300 | }); 301 | }); 302 | 303 | it('getFeatureFlag returns the feature value', done => { 304 | const ldApi = new LDApi('test'); 305 | ldApi.init({clientParams:{user, envClientKey, options}, timeout:500, LDClient}); 306 | const expected = true; 307 | const actual = ldApi.getFeatureFlag(config.features, false); 308 | expect(actual).to.equal(expected); 309 | done(); 310 | }); 311 | 312 | it('getPromiseFeatureFlag returns reject when there is no default value is provided', done => { 313 | const noClientLDAPI = new LDApi('test'); 314 | // const expected = false; 315 | 316 | noClientLDAPI.getPromiseFeatureFlag(config.features).catch(err => { 317 | // t.deepEqual(err.message, 'Default value must be passed to getPromiseFeatureFlag'); 318 | // eslint-disable 319 | expect(err.message).to.equal('Default value must be passed to getPromiseFeatureFlag'); 320 | done(); 321 | }); 322 | }); 323 | 324 | it('getAllFlags returns all flags belonging to that userKey', done => { 325 | const ldApi = new LDApi('test'); 326 | ldApi.init({clientParams:{user, envClientKey, options}, timeout:500, LDClient}); 327 | const expected = { 328 | 'forms-mode': false, 329 | 'other-forms-mode': false 330 | }; 331 | const actual = ldApi.getAllFlags(); 332 | // t.deepEqual(actual, expected); 333 | expect(actual).to.deep.equal(expected); 334 | done(); 335 | }); 336 | }); 337 | -------------------------------------------------------------------------------- /test/react.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Enzyme, { mount, shallow } from 'enzyme'; 3 | import Adapter from 'enzyme-adapter-react-16'; 4 | import { 5 | FeatureTrue, 6 | FeatureFlag, 7 | FeatureFalse, 8 | FeatureSwitch, 9 | FeatureCase, 10 | FeatureDefault 11 | } from '../src/lib/index'; 12 | 13 | Enzyme.configure({ adapter: new Adapter() }); 14 | 15 | const appFlags = { 16 | a: true, 17 | b: false, 18 | switcher: 'switch' 19 | }; 20 | 21 | describe('Launch Darkly Plugin ', () => { 22 | it.only('FeatureFlag: should render component if flagKey value is true in appFlags object ', () => { 23 | const component = shallow( 24 | 25 |
hello
26 |
27 | ); 28 | expect(component.exists()).toBe(true); 29 | expect(component.find('#hello').exists()).toBe(true); 30 | expect(component.debug()).toMatchSnapshot(); 31 | }); 32 | 33 | it.only('FeatureFlag: should not render component if flagKey value is false in appFlags object ', () => { 34 | const component = shallow( 35 | 36 |
hello
37 |
38 | ); 39 | expect(component.exists()).toBe(false); 40 | expect(component.debug()).toMatchSnapshot(); 41 | }); 42 | 43 | it.only('FeatureFlag: should not render component if flagKey does not exist in appFlags object ', () => { 44 | const component = shallow( 45 | 46 |
hello
47 |
48 | ); 49 | expect(component.exists()).toBe(false); 50 | expect(component.debug()).toMatchSnapshot(); 51 | }); 52 | 53 | it.only('FeatureFlag: should render only the FeatureTrue when flagKey value is true', () => { 54 | const component = mount( 55 | 56 | 57 |
Gets rendered when flagKey value is true
58 |
59 | 60 |
Gets rendered when flagKey value is false
61 |
62 |
63 | ); 64 | expect(component.exists()).toBe(true); 65 | expect(component.find('FeatureTrue').exists()).toBe(true); 66 | expect(component.debug()).toMatchSnapshot(); 67 | }); 68 | 69 | it.only('FeatureFlag: should render only the FeatureFalse when flagKey value is false', () => { 70 | const component = mount( 71 | 72 | 73 |
Gets rendered when flagKey value is true
74 |
75 | 76 |
Gets rendered when flagKey value is false
77 |
78 |
79 | ); 80 | expect(component.exists()).toBe(true); 81 | expect(component.find('FeatureFalse').exists()).toBe(true); 82 | expect(component.debug()).toMatchSnapshot(); 83 | }); 84 | 85 | it.only('FeatureFlag: should not render either FeatureTrue or FeatureFalse when it gets mixed with NonPluginElement and should throw a warnring', () => { 86 | const component = shallow( 87 | 88 |
Non Plugin Element
89 | 90 |
Hello there
91 |
92 | 93 |
Hello there
94 |
95 |
96 | ); 97 | expect(component.exists()).toBe(true); 98 | expect(component.debug()).toMatchSnapshot(); 99 | }); 100 | 101 | it.only('FeatureSwitch: renders the FeatureCase component that matches the flagKey ', () => { 102 | const component = mount( 103 | 104 | 105 | 106 |

Multivariate Test 1 Rendered

107 |
108 | 109 |

Multivariate Test 2 Rendered

110 |
111 | 112 |

If no conditions are met then render the default

113 |
114 |
115 |
116 | ); 117 | expect(component.exists()).toBe(true); 118 | expect(component.find({ condition: 'switch' }).exists()).toBe(true); 119 | expect(component.debug()).toMatchSnapshot(); 120 | }); 121 | 122 | it.only('FeatureSwitch: renders the FeatureDefault component when the no FeatureCase found that matches the flagKey ', () => { 123 | const component = mount( 124 | 125 | 126 | 127 |

Multivariate Test 1 Rendered

128 |
129 | 130 |

Multivariate Test 2 Rendered

131 |
132 | 133 |

If no conditions are met then render the default

134 |
135 |
136 |
137 | ); 138 | expect(component.exists()).toBe(true); 139 | expect(component.find('FeatureDefault').exists()).toBe(true); 140 | expect(component.debug()).toMatchSnapshot(); 141 | }); 142 | 143 | it.only('FeatureFlag: should not render the FeatureSwitch and throw a warning when FeatureSwitch gets mixed with NonPlugin elements', () => { 144 | const component = mount( 145 | 146 |
Hello
147 | 148 | 149 |

Multivariate Test 1 Rendered

150 |
151 | 152 |

Multivariate Test 2 Rendered

153 |
154 | 155 |

If no conditions are met then render the default

156 |
157 |
158 |
159 | ); 160 | expect(component.exists()).toBe(true); 161 | expect(component.find({ id: 'hello' }).exists()).toBe(true); 162 | expect(component.debug()).toMatchSnapshot(); 163 | }); 164 | }); 165 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "baseUrl": "src", 5 | "declaration": true, 6 | "emitDecoratorMetadata": true, 7 | "esModuleInterop": true, 8 | "experimentalDecorators": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "jsx": "react", 11 | "lib": ["dom", "dom.iterable", "esnext"], 12 | "module": "commonjs", 13 | "moduleResolution": "node", 14 | "noImplicitReturns": true, 15 | "noImplicitThis": true, 16 | "noImplicitAny": false, 17 | "noUnusedLocals": true, 18 | "outDir": "dist", 19 | "resolveJsonModule": true, 20 | "rootDirs": ["src", "stories"], 21 | "sourceMap": true, 22 | "strictNullChecks": true, 23 | "target": "es5" 24 | }, 25 | "include": ["src/**/*"], 26 | "exclude": ["node_modules", "build", "scripts"] 27 | } 28 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | export default () => ({ 4 | mode: 'production', 5 | entry: { 6 | index: path.join(__dirname, 'src/docs/index.js') 7 | }, 8 | output: { 9 | path: path.join(__dirname, 'src/dist'), 10 | filename: '[name].js', 11 | libraryTarget: 'umd', 12 | globalObject: 'this' 13 | }, 14 | 15 | module: { 16 | rules: [ 17 | // All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'. 18 | { 19 | test: /\.tsx?$/, 20 | loader: 'awesome-typescript-loader' 21 | }, 22 | // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. 23 | { 24 | enforce: 'pre', 25 | test: /\.js$/, 26 | loader: 'source-map-loader' 27 | }, 28 | { 29 | test: /.jsx?$/, 30 | exclude: /node_modules/, 31 | include: path.join(__dirname, 'src'), 32 | use: [ 33 | { 34 | loader: 'babel-loader', 35 | options: { 36 | presets: ['@babel/preset-env', '@babel/preset-react'] 37 | } 38 | } 39 | ] 40 | }, 41 | { 42 | test: /\.(scss)$/, 43 | loader: 'style-loader!css-loader!sass-loader' 44 | } 45 | ] 46 | }, 47 | 48 | resolve: { 49 | extensions: ['.js', '.jsx', '.ts', '.tsx', '.scss'] 50 | }, 51 | 52 | externals: { 53 | react: 'react', 54 | reactDOM: 'react-dom' 55 | } 56 | }); 57 | --------------------------------------------------------------------------------