├── .babelrc ├── .devbots ├── lock-issue.yml └── lock-pull-request.yml ├── .editorconfig ├── .eslintrc ├── .github ├── issue_label_bot.yaml ├── stale.yml └── workflows │ ├── applitools.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierrc.js ├── .storybook ├── addons.js ├── config.js └── webpack.config.js ├── .travis.yml ├── README.md ├── bundlesize.js ├── docs ├── .nojekyll ├── README.md ├── _coverpage.md ├── index.html └── logo.png ├── jest.config.js ├── logo.png ├── logo.svg ├── package.json ├── renovate.json ├── rollup.config.js ├── size.json ├── src ├── .eslintrc ├── components │ ├── async │ │ ├── Async.jsx │ │ ├── Async.stories.jsx │ │ └── _AsyncTablePropsStoryFix.jsx │ ├── creatable │ │ ├── CreatableSelect.jsx │ │ ├── CreatableSelect.stories.jsx │ │ ├── CreatableSelectControlledContainer.jsx │ │ ├── CreatableSelectRenderer.jsx │ │ ├── CreatableSelectUncontrolledContainer.jsx │ │ ├── _CreatableSelectTablePropsStoryFix.jsx │ │ └── state-reducer.js │ ├── fast-hover │ │ ├── FastHover.jsx │ │ └── index.js │ ├── fast-label │ │ ├── FastLabel.jsx │ │ └── index.js │ ├── fast-option │ │ ├── FastOption.jsx │ │ └── index.js │ ├── fast-react-select │ │ ├── FastReactSelect.jsx │ │ └── index.js │ ├── flat-virtualized-list │ │ ├── FlatVirtualizedList.factory.jsx │ │ ├── FlatVirtualizedList.jsx │ │ └── index.js │ ├── grouped-virtualized-list │ │ ├── GroupVirtualizedList.jsx │ │ ├── GroupedVirtualizedList.factory.jsx │ │ └── index.js │ ├── index.js │ ├── select │ │ ├── Select.jsx │ │ ├── Select.stories.css │ │ ├── Select.stories.jsx │ │ ├── SelectBigLoad.stories.jsx │ │ ├── _SelectTablePropsStoryFix.jsx │ │ └── styles.css │ └── test.js ├── hooks │ └── use-debaunced-callback │ │ └── index.js ├── index.js └── lib │ ├── data │ └── index.js │ ├── defaults │ └── index.js │ ├── error │ └── index.js │ ├── getters │ └── index.js │ ├── prop-types │ └── index.js │ ├── renderers │ ├── flat-list.jsx │ ├── grouped-list.jsx │ └── index.js │ ├── select │ └── index.js │ └── utils │ └── index.js ├── storybook-static ├── asset-manifest.json ├── favicon.ico ├── iframe.html ├── index.html ├── main.134ba73fff088321c094.bundle.js ├── main.134ba73fff088321c094.bundle.js.map ├── main.841d6cb694e7736fc069.bundle.js ├── main.css ├── main.css.map ├── precache-manifest.fd6d748e385c84158335b5863d333e2a.js ├── runtime~main.0c4d778cda1a0e417528.bundle.js ├── runtime~main.134ba73fff088321c094.bundle.js ├── runtime~main.134ba73fff088321c094.bundle.js.map ├── sb_dll │ ├── storybook_ui-manifest.json │ ├── storybook_ui_dll.LICENCE │ └── storybook_ui_dll.js ├── service-worker.js ├── vendors~main.134ba73fff088321c094.bundle.js ├── vendors~main.134ba73fff088321c094.bundle.js.map ├── vendors~main.7d9ca408ee8e2983681a.bundle.js ├── vendors~main.css └── vendors~main.css.map └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/preset-react" 5 | ], 6 | "env": { 7 | "production": { 8 | "presets": ["minify"], 9 | "plugins": [ 10 | [ 11 | "transform-react-remove-prop-types", 12 | { 13 | "mode": "remove", 14 | "removeImport": true, 15 | "ignoreFilenames": ["node_modules"] 16 | } 17 | ] 18 | ] 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.devbots/lock-issue.yml: -------------------------------------------------------------------------------- 1 | enabled: true 2 | comment: > 3 | This issue's conversation is now 4 | locked. If you want to continue 5 | this discussion please open a 6 | new issue. -------------------------------------------------------------------------------- /.devbots/lock-pull-request.yml: -------------------------------------------------------------------------------- 1 | enabled: true 2 | comment: > 3 | This pull request's conversation is 4 | now locked. If you want to continue 5 | this discussion or file a bug, please 6 | open a new issue. -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb", "prettier"], 3 | "parserOptions": { 4 | "sourceType": "module", 5 | "ecmaFeatures": { 6 | "jsx": true 7 | } 8 | }, 9 | "plugins": ["prettier", "react", "react-hooks"], 10 | "rules": { 11 | "prettier/prettier": "error", 12 | 13 | "eol-last": ["error", "always"], 14 | "no-plusplus": "off", 15 | 16 | "import/prefer-default-export": "off", 17 | "import/no-unresolved": "off", 18 | "import/no-extraneous-dependencies": ["error", { "devDependencies": true }], 19 | 20 | "jsx-a11y/no-static-element-interactions": "off", 21 | "jsx-a11y/click-events-have-key-events": "off", 22 | "jsx-a11y/mouse-events-have-key-events": "off", 23 | 24 | "prefer-arrow-callback": "error", 25 | "no-use-before-define": "off", 26 | "prefer-destructuring": "off", 27 | 28 | "react/prop-types": [2, { "skipUndeclared": true }], 29 | "react-hooks/rules-of-hooks": "error", 30 | "react-hooks/exhaustive-deps": "error", 31 | "react/destructuring-assignment": "off", 32 | "react/forbid-prop-types": "off", 33 | "react/jsx-wrap-multilines": "off", 34 | "react/no-unused-prop-types": "off", 35 | "react/no-array-index-key": "off", 36 | "react/jsx-one-expression-per-line": "off", 37 | "react/require-default-props": "off", 38 | "react/jsx-props-no-spreading": "off", 39 | "react/function-component-definition": "off" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /.github/issue_label_bot.yaml: -------------------------------------------------------------------------------- 1 | label-alias: 2 | bug: 'kind/bug' 3 | feature_request: 'enhancement' 4 | question: 'question' -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false -------------------------------------------------------------------------------- /.github/workflows/applitools.yml: -------------------------------------------------------------------------------- 1 | name: Visual Regression 2 | on: [push, pull_request] 3 | 4 | env: 5 | APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }} 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | 13 | - uses: actions/setup-node@v2 14 | with: 15 | node-version: '16.x' 16 | 17 | - run: yarn install 18 | - run: yarn build-prod 19 | - run: yarn bundle-size 20 | - run: yarn eyes-storybook 21 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | library: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | 13 | - uses: actions/setup-node@v2 14 | with: 15 | node-version: '14.x' 16 | registry-url: 'https://registry.npmjs.org' 17 | 18 | - name: Get yarn cache directory path 19 | id: yarn-cache-dir-path 20 | run: echo "::set-output name=dir::$(yarn cache dir)" 21 | 22 | - uses: actions/cache@v2 23 | id: yarn-cache 24 | with: 25 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 26 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 27 | restore-keys: | 28 | ${{ runner.os }}-yarn- 29 | 30 | - run: yarn 31 | 32 | - run: yarn build-prod 33 | 34 | - run: npm publish --access public 35 | env: 36 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 37 | 38 | - run: yarn bundle-size 39 | 40 | - name: Commit and Push size.json 41 | uses: stefanzweifel/git-auto-commit-action@v4 42 | with: 43 | branch: master 44 | commit_message: '[CI] publish new bundle size' 45 | commit_user_name: Guillermo Polit 46 | commit_user_email: guiyep@gmail.com 47 | commit_author: guiyep 48 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Testing 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v2 9 | 10 | - uses: actions/setup-node@v2 11 | with: 12 | node-version: '14.x' 13 | 14 | - name: Get yarn cache directory path 15 | id: yarn-cache-dir-path 16 | run: echo "::set-output name=dir::$(yarn cache dir)" 17 | 18 | - uses: actions/cache@v2 19 | id: yarn-cache 20 | with: 21 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 22 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 23 | restore-keys: | 24 | ${{ runner.os }}-yarn- 25 | 26 | - run: yarn 27 | - run: yarn lint 28 | - run: yarn test 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # See https://help.github.com/ignore-files/ for more about ignoring files. 3 | 4 | # dependencies 5 | node_modules 6 | 7 | # builds 8 | build 9 | dist 10 | .rpt2_cache 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn test 5 | yarn lint-s -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | singleQuote: true, 4 | trailingComma: "all", 5 | arrowParens: "always" 6 | }; -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-actions/register'; 2 | import '@storybook/addon-links/register'; 3 | import '@dump247/storybook-state/register'; 4 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react'; 2 | 3 | function loadStories() { 4 | require('../src/components/select/Select.stories'); 5 | require('../src/components/select/SelectBigLoad.stories'); 6 | require('../src/components/async/Async.stories'); 7 | require('../src/components/creatable/CreatableSelect.stories'); 8 | require('../src/components/select/Select.stories.css'); 9 | } 10 | 11 | configure(loadStories, module); 12 | -------------------------------------------------------------------------------- /.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = async ({ config }) => { 4 | config.resolve.alias['@rsv-lib'] = path.resolve(__dirname, '../src/lib'); 5 | config.resolve.alias['@rsv-hooks'] = path.resolve(__dirname, '../src/hooks'); 6 | config.resolve.alias['@rsv-components'] = path.resolve(__dirname, '../src/components'); 7 | return config; 8 | }; 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 9 4 | - 8 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-select-virtualized 2 | 3 |

4 | 5 |

6 |

7 | 8 | 9 | 10 | 11 | 12 |

13 | 14 | > react-select v5 + react-virtualized + react hooks! 15 | 16 | This project came up after hours of trying to find an autocomplete component that supports large sets of data to be displayed and searched for while maintain performance. The only libraries out there that allow this functionality are either not maintained anymore, use outdated libraries or are poorly performant. 17 | I created a component that uses the Airbnb library called `react-virtualized` for the virtual data loading of elements and plugged it to the `react-select` (the most used autocomplete library for react) menu list. 18 | 19 | ![Alt Text](https://imagizer.imageshack.com/img922/7402/CSd9cM.gif) 20 | 21 | ## Install 22 | 23 | ```bash 24 | yarn add react-select-virtualized 25 | ``` 26 | 27 | ### Peer Dependencies 28 | 29 | ```bash 30 | { 31 | "react", 32 | "react-dom", 33 | "react-virtualized", 34 | "react-select" 35 | } 36 | ``` 37 | 38 | ## API Documentation 39 | 40 | You can check the full library documentation [here](https://deluxe-blancmange-4a5494.netlify.app/#/)!!!!. 41 | 42 | ## Examples 43 | 44 | The select component will be the same from `react-select v5` so you will be able to use it with any select you already have. 45 | 46 | Check [Storybook](https://serene-hawking-021d7a.netlify.com/) for more examples 47 | 48 | ```jsx 49 | const options = [ 50 | { 51 | value: 1, 52 | label: `guiyep`, 53 | }, 54 | ... 55 | ]; 56 | 57 | const opsGroup = [ 58 | { label: `Group Name Header`, options }, 59 | ... 60 | ] 61 | ``` 62 | 63 | ## Basic 64 | 65 | ```jsx 66 | import React from 'react'; 67 | 68 | import Select from 'react-select-virtualized'; 69 | 70 | const Example1 = () => ; 83 | ``` 84 | 85 | [![Edit react-select-virtualized](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/angry-wing-5deq4) 86 | -------------------------------------------------------------------------------- /bundlesize.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const filesize = require('filesize'); 3 | const oldFile = require('./size.json'); 4 | 5 | const exec = () => { 6 | try { 7 | const stats = fs.statSync('./dist/index.min.js'); 8 | const size = stats.size; 9 | 10 | fs.unlink('./size.json', () => { 11 | const delta = size - oldFile.new.size || 0; 12 | 13 | const sizeObj = { 14 | old: { 15 | ...(oldFile.new || {}), 16 | old: undefined, 17 | }, 18 | new: { 19 | delta, 20 | prettyDelta: filesize(delta), 21 | size, 22 | prettySize: filesize(size), 23 | }, 24 | }; 25 | 26 | fs.writeFile('./size.json', JSON.stringify(sizeObj), (err) => { 27 | if (err) throw err; 28 | console.log('File is created successfully.'); 29 | if (delta > 8000) { 30 | console.log('Delta is bigger than 8k.'); 31 | } 32 | }); 33 | }); 34 | } catch (err) { 35 | console.error(err); 36 | } 37 | }; 38 | 39 | exec(); 40 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiyep/react-select-virtualized/0b3abc9513a562275307cd8594f689bde8df0c5b/docs/.nojekyll -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # react-select-virtualized 2 | 3 |

4 | 5 |

6 |

7 | 8 | 9 | 10 | 11 | 12 |

13 | 14 | > react-select v5 + react-virtualized + react hooks! 15 | 16 | This project came up after hours of trying to find an autocomplete component that supports large sets of data to be displayed and searched for while maintain performance. The only libraries out there that allow this functionality are either not maintained anymore, use outdated libraries or are poorly performant. 17 | I created a component that uses the Airbnb library called `react-virtualized` for the virtual data loading of elements and plugged it to the `react-select` (the most used autocomplete library for react) menu list. 18 | 19 | ![Alt Text](https://imagizer.imageshack.com/img922/7402/CSd9cM.gif) 20 | 21 | ## Install 22 | 23 | ```bash 24 | yarn add react-select-virtualized 25 | ``` 26 | 27 | ### Peer Dependencies 28 | 29 | ```bash 30 | { 31 | "react", 32 | "react-dom", 33 | "react-virtualized", 34 | "react-select" 35 | } 36 | ``` 37 | 38 | ## Note 39 | 40 | The select component will be the same from `react-select v5` so you will be able to use it with any select you already have. 41 | 42 | ## Try It 43 | 44 | [![Edit react-select-virtualized](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/vigilant-mclean-wpbk7) 45 | 46 | Check [Storybook](https://serene-hawking-021d7a.netlify.com/) for more examples 47 | 48 | ## What we do support and don't from react-select 49 | 50 | Components: `Select`, `Async`, `Creatable` 51 | 52 | - [x] We support all the UI related props for the input. Extension also. 53 | 54 | - [x] We do not support any related prop to the popup list. We extend it. \*Sorry no extension of any component inside the list.\* 55 | 56 | - [x] Sorry no multi selection yet. (no `isMulti`) 57 | 58 | # Examples 59 | 60 | ## Options Shape 61 | 62 | ```jsx 63 | const options = [ 64 | { 65 | value: 1, 66 | label: `guiyep`, 67 | }, 68 | ... 69 | ]; 70 | 71 | const opsGroup = [ 72 | { label: `Group Name Header`, options }, 73 | ... 74 | ] 75 | ``` 76 | 77 | ## Basic 78 | 79 | ```jsx 80 | import React from 'react'; 81 | 82 | import Select from 'react-select-virtualized'; 83 | 84 | const Example1 = () => ; 97 | ``` 98 | 99 | [![Edit react-select-virtualized](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/angry-wing-5deq4) 100 | 101 | ## Usage Async 102 | 103 | ```jsx 104 | 105 | import React from 'react'; 106 | 107 | import { Async } from 'react-select-virtualized'; 108 | 109 | const loadOptions = (input, callback) => {...}; 110 | 111 | const Example1 = () => 112 | 113 | const Example2 = () => 114 | 115 | const Example3 = () => 116 | ``` 117 | 118 | ##### Async - No Group 119 | 120 | [![Edit react-select-virtualized](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/quirky-swanson-egeh8) 121 | 122 | ##### Async - Grouped 123 | 124 | [![Edit react-select-virtualized](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/runtime-cloud-jow57) 125 | 126 | ## Usage with creatable 127 | 128 | ```jsx 129 | import React from 'react'; 130 | 131 | import { Creatable } from 'react-select-virtualized'; 132 | 133 | const Example1 = () => ; 134 | ``` 135 | 136 | [![Edit react-select-virtualized](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/twilight-cloud-nqwz1) 137 | 138 | ## Usage with creatable and group 139 | 140 | NOT YET DONE. 141 | 142 | ## Custom Styles 143 | 144 | For custom styling of the Input component read the `react-select` [documentation](https://react-select.com/home#custom-styles). 145 | 146 | The styling in the menu list is by css. 147 | 148 | #### How to leave the menu open so I can style my menu? 149 | 150 | Set the `menuIsOpen` prop to true, create an options list with less than 100 elements and use css for adjusting your css. 151 | 152 | Use this example as a guidance 153 | 154 | [![Edit react-select-virtualized](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/fragrant-thunder-bno6s) 155 | 156 |
157 | Possible classes 158 | 159 | `react-select-virtualized` `grouped-virtualized-list-item` `flat-virtualized-item` `fast-option` `fast-option` `fast-option-focused` `fast-option-selected` `fast-option-create` 160 | 161 |
162 | 163 | ## Documentation - this are special to this library and none is required 164 | 165 |
166 | Toggle 167 | 168 | | Props | Type | Default | Description | 169 | | -------------------------------------------- | ------------------------------------------ | ------- | ------------------------------------------------------------------------------------ | 170 | | grouped | boolean | false | Specify if options are grouped | 171 | | formatGroupHeaderLabel | function({ label, options}) => component | | Will render a custom component in the popup grouped header (only for grouped) | 172 | | formatOptionLabel (coming from react-select) | function(option, { context }) => component | | Will render a custom component in the label | 173 | | optionHeight | number | 31 | Height of each option | 174 | | groupHeaderHeight | number | | Header row height in the popover list | 175 | | maxHeight (coming from react-select) | number | auto | Max height popover list | 176 | | defaultValue | option | | Will set default value and set the component as an uncontrolled component | 177 | | value | option | | Will set the value and the component will be a controlled component | 178 | | onCreateOption (Only for Creatable) | function(option) => nothing | | Will be executed when a new option is created , it is only for controlled components | 179 | 180 |
181 | 182 | ## Roadmap 183 | 184 |
185 | Toggle 186 | 187 | - [x] useCallback everywhere. 188 | - [x] Move fast options to group. 189 | - [x] Fix minimum input search on grouped component. 190 | - [x] Upgrade alpha version. 191 | - [x] Review all the TODOs. 192 | - [x] Improve filtering function in `fast-react-select`. 193 | - [x] Improved performance by 50% 194 | - [x] Add gzip. 195 | - [x] Review support to all the react-select props. Should all work but multi-val. 196 | 197 | -- v 1.0.0 -- 198 | 199 | - [x] Add support to AsyncSelect. 200 | 201 | -- v 1.1.0 -- 202 | 203 | - [x] Add support to AsyncSelect with group. 204 | 205 | -- v 1.2.0 -- 206 | 207 | - [x] Upgrading packages and hooks. 208 | 209 | -- v 2.0.0 -- 210 | 211 | - [x] Adding react-select v3. 212 | - [x] Fixing addon-info. 213 | - [x] Remove classnames. 214 | - [x] Improve packaging. 215 | - [x] Remove react-hover-observer. 216 | - [x] Added controlled components support. 217 | 218 | -- v 2.1.0 -- 219 | 220 | - [x] Better debouncing 221 | 222 | -- v 2.2.0 -- 223 | 224 | - [x] Add support to create element props. 225 | - [x] Add better error handling. 226 | 227 | -- v 2.3.0 -- 228 | 229 | - [x] Move modules to lib. 230 | - [x] Improve debounce. 231 | 232 | -- v3.0.0 -- 233 | 234 | - [x] Move internal state of select and async select to reducer like creatable. 235 | 236 | -- v 3.1.0 -- 237 | 238 | - [ ] Add support to create element props with group. 239 | - [ ] Add testing so we do not only relay on storybook. 240 | 241 |
242 | 243 | ## More from me :) 244 | 245 | > my-react-form-state [![NPM](https://img.shields.io/npm/v/my-react-form-state.svg)](https://www.npmjs.com/package/my-react-form-state) 246 | 247 | This is a React form state management library that works with React/Redux/React-Native. 248 | 249 | ## License 250 | 251 | MIT © [guiyep](https://github.com/guiyep) 252 | -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | ![logo](./logo.png) 2 | 3 | > A super performant lightning fast select component for big data sets. 4 | 5 | [GitHub](https://github.com/guiyep/react-select-virtualized) 6 | [Getting Started](#react-select-virtualized) 7 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiyep/react-select-virtualized/0b3abc9513a562275307cd8594f689bde8df0c5b/docs/logo.png -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | moduleNameMapper: { 3 | '\\.(css|less|scss|sss|style)$': '/node_modules/jest-css-modules', 4 | '^@rsv-lib(.*)$': '/src/lib$1', 5 | '^@rsv-hooks(.*)$': '/src/hooks$1', 6 | '^@rsv-components(.*)$': '/src/components$1', 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiyep/react-select-virtualized/0b3abc9513a562275307cd8594f689bde8df0c5b/logo.png -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | Untitled-2 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-select-virtualized", 3 | "version": "5.6.0", 4 | "description": "Select virtualized component using: react-select v4 + react-virtualized + react hooks", 5 | "author": "guiyep", 6 | "license": "MIT", 7 | "repository": "guiyep/react-select-virtualized", 8 | "main": "dist/index.min.js", 9 | "engines": { 10 | "node": ">=12", 11 | "npm": ">=7" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "select", 16 | "virtualized", 17 | "hooks", 18 | "react hooks", 19 | "performance", 20 | "big" 21 | ], 22 | "scripts": { 23 | "test": "jest", 24 | "build": "rollup -c", 25 | "build-prod": "NODE_ENV=production BABEL_ENV=production rollup -c", 26 | "start": "rollup -c -w", 27 | "deploy": "gh-pages -d", 28 | "storybook": "start-storybook -p 9009", 29 | "build-storybook": "build-storybook -c .storybook", 30 | "prepare": "husky install", 31 | "lint": "yarn run eslint ./src/**/**/*.{js,jsx} && yarn run prettier ./src", 32 | "eslint": "eslint --fix", 33 | "prettier": "prettier --write", 34 | "eslint2": "eslint", 35 | "prettier2": "prettier", 36 | "lint-s": "lint-staged", 37 | "eyes-storybook": "eyes-storybook", 38 | "bundle-size": "node ./bundlesize.js", 39 | "audit-fix": "yarn-audit-fix", 40 | "doc": "docsify serve ./docs" 41 | }, 42 | "devDependencies": { 43 | "@applitools/eyes-storybook": "^3.27.2", 44 | "@babel/core": "7.16.7", 45 | "@babel/preset-env": "7.16.7", 46 | "@babel/preset-react": "7.16.7", 47 | "@dump247/storybook-state": "1.6.1", 48 | "@storybook/addon-actions": "6.4.9", 49 | "@storybook/addon-info": "5.3.21", 50 | "@storybook/addon-links": "6.4.9", 51 | "@storybook/addons": "6.4.9", 52 | "@storybook/react": "6.4.9", 53 | "babel-eslint": "10.1.0", 54 | "babel-loader": "8.2.3", 55 | "babel-plugin-transform-react-remove-prop-types": "0.4.24", 56 | "babel-preset-minify": "0.5.1", 57 | "docsify-cli": "^4.4.4", 58 | "eslint": "8.6.0", 59 | "eslint-config-airbnb": "19.0.4", 60 | "eslint-config-prettier": "8.3.0", 61 | "eslint-config-standard": "16.0.3", 62 | "eslint-config-standard-react": "11.0.1", 63 | "eslint-plugin-import": "2.25.4", 64 | "eslint-plugin-jsx-a11y": "6.5.1", 65 | "eslint-plugin-node": "11.1.0", 66 | "eslint-plugin-prettier": "^4.0.0", 67 | "eslint-plugin-promise": "6.0.0", 68 | "eslint-plugin-react": "7.28.0", 69 | "eslint-plugin-react-hooks": "4.3.0", 70 | "eslint-plugin-standard": "5.0.0", 71 | "extend-shallow": "3.0.2", 72 | "faker": "^5.5.3", 73 | "filesize": "^8.0.6", 74 | "husky": "7.0.4", 75 | "jest": "27.4.6", 76 | "jest-css-modules": "2.1.0", 77 | "lint-staged": "12.1.5", 78 | "postcss": "^8.4.5", 79 | "prettier": "2.5.1", 80 | "prop-types": "15.8.0", 81 | "react": "18.2.0", 82 | "react-dom": "18.2.0", 83 | "react-select": "5.7.3", 84 | "react-testing-library": "8.0.1", 85 | "react-virtualized": "9.22.5", 86 | "rollup": "2.63.0", 87 | "rollup-plugin-babel": "4.4.0", 88 | "rollup-plugin-babel-minify": "10.0.0", 89 | "rollup-plugin-cleaner": "1.0.0", 90 | "rollup-plugin-commonjs": "10.1.0", 91 | "rollup-plugin-gzip": "3.0.0", 92 | "rollup-plugin-import-alias": "1.0.10", 93 | "rollup-plugin-json": "4.0.0", 94 | "rollup-plugin-node-resolve": "5.2.0", 95 | "rollup-plugin-peer-deps-external": "2.2.4", 96 | "rollup-plugin-postcss": "4.0.2", 97 | "rollup-plugin-replace": "2.2.0", 98 | "rollup-plugin-terser": "7.0.2", 99 | "yarn-audit-fix": "^9.0.4" 100 | }, 101 | "files": [ 102 | "dist" 103 | ], 104 | "peerDependencies": { 105 | "react": "^18.3.1", 106 | "react-dom": "^18.3.1", 107 | "react-select": "^5.8.0", 108 | "react-virtualized": "^9.22.4" 109 | }, 110 | "dependencies": { 111 | "lodash.debounce": "4.0.8", 112 | "regenerator-runtime": "^0.13.9" 113 | }, 114 | "browserslist": [ 115 | "last 2 Chrome versions", 116 | "last 2 Edge versions", 117 | "last 2 Safari versions", 118 | "last 2 Firefox versions" 119 | ], 120 | "lint-staged": { 121 | "*.{js,jsx}": [ 122 | "yarn run prettier", 123 | "yarn run eslint" 124 | ] 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "baseBranches": ["develop"], 4 | "schedule": ["before 5:00am"], 5 | "minor": { 6 | "automerge": true 7 | }, 8 | "patch": { 9 | "automerge": true 10 | }, 11 | "pin": { 12 | "automerge": true 13 | }, 14 | "digest": { 15 | "automerge": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import commonjs from 'rollup-plugin-commonjs'; 3 | import external from 'rollup-plugin-peer-deps-external'; 4 | import postcss from 'rollup-plugin-postcss'; 5 | import resolve from 'rollup-plugin-node-resolve'; 6 | import replace from 'rollup-plugin-replace'; 7 | import gzipPlugin from 'rollup-plugin-gzip'; 8 | import cleaner from 'rollup-plugin-cleaner'; 9 | import json from 'rollup-plugin-json'; 10 | import { terser } from 'rollup-plugin-terser'; 11 | import importAlias from 'rollup-plugin-import-alias'; 12 | 13 | import pkg from './package.json'; 14 | 15 | const isProd = process.env.NODE_ENV === 'production'; 16 | 17 | export default { 18 | input: 'src/index.js', 19 | output: [ 20 | { 21 | file: pkg.main, 22 | format: 'cjs', 23 | sourcemap: !isProd, 24 | compact: true, 25 | exports: 'named', 26 | }, 27 | ], 28 | plugins: [ 29 | external(), 30 | postcss({ 31 | minimize: isProd, 32 | }), 33 | babel({ 34 | exclude: 'node_modules/**', 35 | runtimeHelpers: true, 36 | }), 37 | resolve({ 38 | extensions: ['.mjs', '.js', '.jsx', '.json'], 39 | }), 40 | commonjs(), 41 | replace({ 42 | ENV: JSON.stringify(process.env.NODE_ENV || 'development'), 43 | }), 44 | json(), 45 | !isProd && gzipPlugin(), 46 | importAlias({ 47 | Paths: { 48 | '@rsv-lib': './src/lib', 49 | '@rsv-hooks': './src/hooks', 50 | '@rsv-components': './src/components', 51 | }, 52 | Extensions: ['js'], 53 | }), 54 | isProd && 55 | cleaner({ 56 | targets: ['./dist/'], 57 | }), 58 | isProd && 59 | terser({ 60 | toplevel: true, 61 | }), 62 | ], 63 | }; 64 | -------------------------------------------------------------------------------- /size.json: -------------------------------------------------------------------------------- 1 | {"old":{"delta":0,"prettyDelta":"0 B","size":34743,"prettySize":"34.74 kB"},"new":{"delta":0,"prettyDelta":"0 B","size":34743,"prettySize":"34.74 kB"}} -------------------------------------------------------------------------------- /src/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "jest": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/components/async/Async.jsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useMemo, useCallback } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { optionsPropTypes } from '@rsv-lib/prop-types'; 4 | import Select from '../select/Select'; 5 | 6 | const Async = memo(({ defaultOptions, loadOptions, cacheOptions, onInputChange, minimumInputSearch, ...props }) => { 7 | const options = useMemo(() => defaultOptions || [], [defaultOptions]); 8 | 9 | const asyncLoadOptions = useCallback( 10 | (inputValue) => 11 | new Promise((resolve) => { 12 | loadOptions(inputValue, (result) => { 13 | resolve(result); 14 | }); 15 | }), 16 | [loadOptions], 17 | ); 18 | 19 | return ( 20 | ; 19 | }); 20 | 21 | CreatableSelect.displayName = 'CreatableSelect'; 22 | 23 | CreatableSelect.propTypes = { 24 | onValueChange: PropTypes.func, 25 | onOptionsChange: PropTypes.func, 26 | onNewOption: PropTypes.func, 27 | options: PropTypes.object, 28 | value: PropTypes.any, 29 | }; 30 | 31 | CreatableSelect.defaultProps = { 32 | onValueChange: () => {}, 33 | onOptionsChange: () => {}, 34 | onNewOption: () => {}, 35 | }; 36 | 37 | export default CreatableSelect; 38 | -------------------------------------------------------------------------------- /src/components/creatable/CreatableSelect.stories.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | import { withInfo } from '@storybook/addon-info'; 4 | import { optionsDefault, ops2500 } from '@rsv-lib/data'; 5 | import { withState } from '@dump247/storybook-state'; 6 | import { action } from '@storybook/addon-actions'; 7 | import CreatableSelect from './CreatableSelectRenderer'; 8 | 9 | storiesOf(`React Select Virtualized/Creatable`, module) 10 | .addDecorator((story) =>
{story()}
) 11 | .addDecorator(withInfo) 12 | .addParameters({ 13 | info: { 14 | source: true, 15 | maxPropsIntoLine: 1, 16 | }, 17 | }) 18 | .add('Basic', () => ) 19 | .add('Basic 2500 elements ', () => ) 20 | .add( 21 | 'Basic with onCreateOption callback (only with controlled)', 22 | withState({ options: optionsDefault, selected: null })(({ store }) => { 23 | const onCreateOption = (newItem) => { 24 | store.set({ options: store.state.options.concat([newItem]) }); 25 | store.set({ selected: newItem }); 26 | action(`onCreateOption`)(newItem); 27 | }; 28 | const onChange = (item) => { 29 | store.set({ selected: item }); 30 | action(`onChange`)(item); 31 | }; 32 | return ( 33 | 39 | ); 40 | }), 41 | ) 42 | .add( 43 | 'Basic 2500 elements with onCreateOption callback (only with controlled)', 44 | withState({ options: ops2500, selected: null })(({ store }) => { 45 | const onCreateOption = (newItem) => { 46 | store.set({ options: store.state.options.concat([newItem]) }); 47 | store.set({ selected: newItem }); 48 | action(`onCreateOption`)(newItem); 49 | }; 50 | const onChange = (item) => { 51 | store.set({ selected: item }); 52 | action(`onChange`)(item); 53 | }; 54 | return ( 55 | 61 | ); 62 | }), 63 | ); 64 | // .add( 65 | // 'Basic grouped to the first group', 66 | // withState({ options: opsGroup20000, selected: null })(({ store }) => { 67 | // const onCreateOption = (newItem) => { 68 | // store.set({ options: store.state.options[0].options.concat([newItem]) }); 69 | // store.set({ selected: newItem }); 70 | // action(`onCreateOption`)(newItem); 71 | // }; 72 | // const onChange = (item) => { 73 | // store.set({ selected: item }); 74 | // action(`onChange`)(item); 75 | // }; 76 | // return ( 77 | // 84 | // ); 85 | // }), 86 | // ); 87 | -------------------------------------------------------------------------------- /src/components/creatable/CreatableSelectControlledContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useCallback } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import { isDifferentValueOption } from '@rsv-lib/utils'; 5 | import CreatableSelect from './CreatableSelect'; 6 | 7 | const CreatableSelectControlledContainer = memo(({ onChange, onCreateOption, value, options, ...props }) => { 8 | const onCreateOptionHandler = useCallback( 9 | (newItem) => { 10 | onCreateOption({ value: newItem, label: newItem, isNewOption: true }); 11 | }, 12 | [onCreateOption], 13 | ); 14 | 15 | const onValueChangeHandler = useCallback( 16 | (option) => { 17 | if (isDifferentValueOption(option, value)) { 18 | if (option && option.isNew) { 19 | onCreateOptionHandler(option.value); 20 | } else { 21 | onChange(option); 22 | } 23 | } 24 | }, 25 | [onChange, onCreateOptionHandler, value], 26 | ); 27 | 28 | return ( 29 | 36 | ); 37 | }); 38 | 39 | CreatableSelectControlledContainer.displayName = 'CreatableSelectControlledContainer'; 40 | 41 | CreatableSelectControlledContainer.propTypes = { 42 | onCreateOption: PropTypes.func, 43 | options: PropTypes.object, 44 | value: PropTypes.any, 45 | onChange: PropTypes.func, 46 | }; 47 | 48 | CreatableSelectControlledContainer.defaultProps = { 49 | onCreateOption: undefined, 50 | }; 51 | 52 | export default CreatableSelectControlledContainer; 53 | -------------------------------------------------------------------------------- /src/components/creatable/CreatableSelectRenderer.jsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { buildErrorText } from '@rsv-lib/error'; 4 | import CreatableSelectControlledContainer from './CreatableSelectControlledContainer'; 5 | import CreatableSelectUncontrolledContainer from './CreatableSelectUncontrolledContainer'; 6 | 7 | const CreatableSelectRenderer = memo((props) => { 8 | const { value, onCreateOption, grouped } = props; 9 | 10 | if (grouped) { 11 | throw new Error(buildErrorText('Creatable component does not support grouped yet')); 12 | } 13 | 14 | // render a controlled component 15 | if (value !== undefined) { 16 | return ; 17 | } 18 | 19 | if (onCreateOption) { 20 | throw new Error(buildErrorText('Creatable component cannot be used as uncontrolled with onCreateOption')); 21 | } 22 | 23 | // render an uncontrolled component 24 | return ; 25 | }); 26 | 27 | CreatableSelectRenderer.displayName = 'CreatableSelectRenderer'; 28 | 29 | CreatableSelectRenderer.propTypes = { 30 | onCreateOption: PropTypes.func, 31 | value: PropTypes.any, 32 | grouped: PropTypes.bool, 33 | }; 34 | 35 | CreatableSelectRenderer.defaultProps = { 36 | onCreateOption: undefined, 37 | }; 38 | 39 | export default CreatableSelectRenderer; 40 | -------------------------------------------------------------------------------- /src/components/creatable/CreatableSelectUncontrolledContainer.jsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useCallback, useReducer } from 'react'; 2 | import { isDifferentValueOption } from '@rsv-lib/utils'; 3 | import CreatableSelect from './CreatableSelect'; 4 | 5 | import reducer, { SET_VALUE, SET_OPTIONS } from './state-reducer'; 6 | 7 | const CreatableSelectUncontrolledContainer = memo(({ onChange, defaultValue, value, options, ...props }) => { 8 | const [state, dispatch] = useReducer(reducer, { 9 | value: defaultValue, 10 | options, 11 | }); 12 | 13 | const onNewOptionHandler = useCallback( 14 | (newItem) => { 15 | const newItemObj = { value: newItem, label: newItem, isNewOption: true }; 16 | dispatch({ type: SET_OPTIONS, payload: state.options.concat([newItemObj]) }); 17 | dispatch({ type: SET_VALUE, payload: newItemObj }); 18 | return newItemObj; 19 | }, 20 | [state.options, dispatch], 21 | ); 22 | 23 | const onOptionsChangeHandler = useCallback( 24 | (changeOptions) => { 25 | if (changeOptions !== state.options) { 26 | dispatch({ type: SET_OPTIONS, payload: changeOptions }); 27 | } 28 | }, 29 | [dispatch, state.options], 30 | ); 31 | 32 | const onValueChangeHandler = useCallback( 33 | (option) => { 34 | if (isDifferentValueOption(option, state.value)) { 35 | if (option && option.isNew) { 36 | onNewOptionHandler(option.value); 37 | } else { 38 | dispatch({ type: SET_VALUE, payload: option }); 39 | } 40 | } 41 | if (onChange) { 42 | onChange(option); 43 | } 44 | }, 45 | [dispatch, onNewOptionHandler, onChange, state.value], 46 | ); 47 | 48 | return ( 49 | 56 | ); 57 | }); 58 | 59 | CreatableSelectUncontrolledContainer.displayName = 'CreatableSelectUncontrolledContainer'; 60 | 61 | export default CreatableSelectUncontrolledContainer; 62 | -------------------------------------------------------------------------------- /src/components/creatable/_CreatableSelectTablePropsStoryFix.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import { optionsPropTypes } from '@rsv-lib/prop-types'; 5 | import CreatableSelect from './CreatableSelect'; 6 | 7 | const Select = (props) => ; 8 | 9 | Select.propTypes = { 10 | minimumInputSearch: PropTypes.number, 11 | options: optionsPropTypes.isRequired, 12 | onChange: PropTypes.func, 13 | grouped: PropTypes.bool, // this is only for performance enhancement so we do not need to iterate in the array many times. It is not needed if formatGroupHeaderLabel or groupHeaderHeight are defined 14 | formatGroupHeaderLabel: PropTypes.func, 15 | optionHeight: PropTypes.number, 16 | groupHeaderHeight: PropTypes.number, 17 | defaultValue: PropTypes.object, 18 | }; 19 | 20 | Select.defaultProps = { 21 | grouped: false, 22 | optionHeight: 31, 23 | minimumInputSearch: 0, 24 | }; 25 | 26 | Select.displayName = 'Select'; 27 | 28 | export default Select; 29 | -------------------------------------------------------------------------------- /src/components/creatable/state-reducer.js: -------------------------------------------------------------------------------- 1 | import { buildErrorText } from '@rsv-lib/error'; 2 | 3 | export const SET_VALUE = 'set-value'; 4 | export const SET_OPTIONS = 'set-options'; 5 | 6 | export default function reducer(state, action) { 7 | switch (action.type) { 8 | case SET_VALUE: 9 | return { ...state, value: action.payload }; 10 | case SET_OPTIONS: 11 | return { ...state, options: action.payload }; 12 | default: 13 | throw new Error(buildErrorText(`Unknown reducer action ${action}`)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/components/fast-hover/FastHover.jsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useState } from 'react'; 2 | 3 | const FastHover = ({ children }) => { 4 | const [isHovering, setHovering] = useState(false); 5 | 6 | const onMouseOverHandler = useCallback(() => setHovering(true), []); 7 | 8 | const onMouseOutHandler = useCallback(() => setHovering(false), []); 9 | 10 | return ( 11 |
12 | {children({ isHovering })} 13 |
14 | ); 15 | }; 16 | 17 | FastHover.displayName = 'FastHover'; 18 | 19 | export default FastHover; 20 | -------------------------------------------------------------------------------- /src/components/fast-hover/index.js: -------------------------------------------------------------------------------- 1 | import FastHover from './FastHover'; 2 | 3 | export { FastHover }; 4 | -------------------------------------------------------------------------------- /src/components/fast-label/FastLabel.jsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useMemo } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const configFastLabelOption = { 5 | context: 'menu', 6 | }; 7 | 8 | const FastLabel = memo(({ data, setValue, isHovering, isSelected, isFocused, style, formatOptionLabel }) => { 9 | const onClickHandler = () => setValue(data); 10 | 11 | const label = useMemo( 12 | () => (formatOptionLabel ? formatOptionLabel(data, configFastLabelOption) : data.label), 13 | [data, formatOptionLabel], 14 | ); 15 | 16 | return ( 17 |
25 | {label} 26 |
27 | ); 28 | }); 29 | 30 | FastLabel.propTypes = { 31 | data: PropTypes.object.isRequired, 32 | setValue: PropTypes.func, 33 | isHovering: PropTypes.bool.isRequired, 34 | isFocused: PropTypes.bool, 35 | isSelected: PropTypes.bool.isRequired, 36 | style: PropTypes.object, 37 | formatOptionLabel: PropTypes.func, 38 | }; 39 | 40 | FastLabel.defaultProps = { 41 | setValue: undefined, 42 | style: undefined, 43 | formatOptionLabel: undefined, 44 | }; 45 | 46 | FastLabel.displayName = 'FastLabel'; 47 | 48 | export default FastLabel; 49 | -------------------------------------------------------------------------------- /src/components/fast-label/index.js: -------------------------------------------------------------------------------- 1 | import FastLabel from './FastLabel'; 2 | 3 | export { FastLabel }; 4 | -------------------------------------------------------------------------------- /src/components/fast-option/FastOption.jsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { FastHover } from '../fast-hover'; 4 | import { FastLabel } from '../fast-label'; 5 | 6 | const FastOption = memo( 7 | ({ data, isScrolling, isSelected, isVisible, setValue, optionHeight, isFocused, formatOptionLabel }) => ( 8 | <> 9 | {(isScrolling || !isVisible || isFocused) && ( 10 | 19 | )} 20 | {!isScrolling && isVisible && !isFocused && ( 21 | 22 | {({ isHovering }) => ( 23 | 31 | )} 32 | 33 | )} 34 | 35 | ), 36 | ); 37 | 38 | FastOption.propTypes = { 39 | data: PropTypes.object.isRequired, 40 | isScrolling: PropTypes.bool.isRequired, 41 | isVisible: PropTypes.bool.isRequired, 42 | setValue: PropTypes.func.isRequired, 43 | optionHeight: PropTypes.number.isRequired, 44 | isFocused: PropTypes.bool, 45 | isSelected: PropTypes.bool, 46 | formatOptionLabel: PropTypes.func, 47 | }; 48 | 49 | export default FastOption; 50 | -------------------------------------------------------------------------------- /src/components/fast-option/index.js: -------------------------------------------------------------------------------- 1 | import FastOption from './FastOption'; 2 | 3 | export { FastOption }; 4 | -------------------------------------------------------------------------------- /src/components/fast-react-select/FastReactSelect.jsx: -------------------------------------------------------------------------------- 1 | import React, { forwardRef, memo, useMemo, useState, useCallback } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import ReactSelect from 'react-select'; 4 | import ReactAsync from 'react-select/async'; 5 | import ReactSelectCreatableSelect from 'react-select/creatable'; 6 | import ReactSelectAsyncCreatableSelect from 'react-select/async-creatable'; 7 | import { mapLowercaseLabel, getFilteredItems, calculateTotalGroupedListSize } from '@rsv-lib/utils'; 8 | import { optionsPropTypes } from '@rsv-lib/prop-types'; 9 | import { useDebouncedCallback } from '@rsv-hooks/use-debaunced-callback'; 10 | import { buildErrorText } from '@rsv-lib/error'; 11 | 12 | const LAG_INDICATOR = 1000; 13 | 14 | const loadingMessage = () =>
...
; 15 | 16 | const FastReactSelectComponent = (propsIn, ref) => { 17 | const { 18 | asyncLoadOptions, 19 | asyncInputChange, 20 | minimumInputSearch, 21 | options, 22 | formatOptionLabel, 23 | grouped, 24 | filterOption, 25 | creatable, 26 | menuIsOpen, 27 | ...props 28 | } = propsIn; 29 | 30 | const minimumInputSearchIsSet = minimumInputSearch >= 1; 31 | 32 | const listSize = useMemo( 33 | () => (grouped && calculateTotalGroupedListSize(options)) || options.length, 34 | [options, grouped], 35 | ); 36 | const [menuIsOpenState, setMenuIsOpen] = useState({ currentInput: '' }); 37 | 38 | const updateSetMenuIsOpen = useCallback( 39 | (inputValue, state) => { 40 | if (minimumInputSearchIsSet) { 41 | setMenuIsOpen({ 42 | ...menuIsOpenState, 43 | currentInput: inputValue, 44 | [inputValue || '']: state, 45 | }); 46 | } 47 | }, 48 | [minimumInputSearchIsSet, setMenuIsOpen, menuIsOpenState], 49 | ); 50 | 51 | // avoid destructuring to best performance 52 | const memoOptions = useMemo( 53 | () => 54 | mapLowercaseLabel(options, formatOptionLabel, (itemOption) => { 55 | if (itemOption.options && grouped) { 56 | return { 57 | options: mapLowercaseLabel(itemOption.options, formatOptionLabel), 58 | }; 59 | } 60 | return {}; 61 | }), 62 | [options, formatOptionLabel, grouped], 63 | ); 64 | 65 | const onInputChange = useCallback( 66 | (inputValue) => { 67 | if (minimumInputSearchIsSet) { 68 | const inputValLowercase = (inputValue && inputValue.toLowerCase()) || ''; 69 | updateSetMenuIsOpen(inputValLowercase, minimumInputSearch <= inputValLowercase.length); 70 | } 71 | asyncInputChange(inputValue); 72 | }, 73 | [asyncInputChange, updateSetMenuIsOpen, minimumInputSearchIsSet, minimumInputSearch], 74 | ); 75 | 76 | // debounce the filter since it is going to be an expensive operation 77 | const loadOptions = useDebouncedCallback((inputValue, callback) => { 78 | if (minimumInputSearchIsSet && !menuIsOpenState[menuIsOpenState.currentInput]) { 79 | return callback(undefined); 80 | } 81 | if (asyncLoadOptions) { 82 | // create an async function that will resolve the callback 83 | const asyncLoad = async () => { 84 | const newList = await asyncLoadOptions(inputValue); 85 | callback(newList); 86 | }; 87 | 88 | return asyncLoad(); 89 | } 90 | return callback(getFilteredItems({ inputValue, memoOptions, grouped, filterOption })); 91 | }); 92 | 93 | if (creatable && listSize <= LAG_INDICATOR) { 94 | return ( 95 | 102 | ); 103 | } 104 | 105 | if (creatable && listSize > LAG_INDICATOR) { 106 | return ( 107 | = 1 || memoOptions.length === 0 ? true : memoOptions} 115 | menuIsOpen={minimumInputSearchIsSet ? !!menuIsOpenState[menuIsOpenState.currentInput] : menuIsOpen} 116 | onInputChange={onInputChange} 117 | captureMenuScroll={false} 118 | /> 119 | ); 120 | } 121 | 122 | if (!creatable && listSize <= LAG_INDICATOR && !minimumInputSearchIsSet && !asyncLoadOptions) { 123 | return ( 124 | 132 | ); 133 | } 134 | 135 | if (listSize > LAG_INDICATOR || minimumInputSearchIsSet || !!asyncLoadOptions) { 136 | return ( 137 | = 1 || memoOptions.length === 0 ? true : memoOptions} 145 | menuIsOpen={minimumInputSearchIsSet ? !!menuIsOpenState[menuIsOpenState.currentInput] : menuIsOpen} 146 | onInputChange={onInputChange} 147 | captureMenuScroll={false} 148 | /> 149 | ); 150 | } 151 | 152 | throw new Error(buildErrorText('Nothing to render, something is wrong in FastReactSelect component')); 153 | }; 154 | 155 | const FastReactSelectForward = forwardRef(FastReactSelectComponent); 156 | const FastReactSelect = memo(FastReactSelectForward); 157 | 158 | FastReactSelect.propTypes = { 159 | options: optionsPropTypes.isRequired, 160 | minimumInputSearch: PropTypes.number, 161 | asyncLoadOptions: PropTypes.func, 162 | asyncInputChange: PropTypes.func, 163 | creatable: PropTypes.bool, 164 | }; 165 | 166 | FastReactSelect.defaultProps = { 167 | minimumInputSearch: 0, 168 | asyncLoadOptions: undefined, 169 | asyncInputChange: () => {}, 170 | creatable: false, 171 | }; 172 | 173 | export default FastReactSelect; 174 | -------------------------------------------------------------------------------- /src/components/fast-react-select/index.js: -------------------------------------------------------------------------------- 1 | import FastReactSelect from './FastReactSelect'; 2 | 3 | export { FastReactSelect }; 4 | -------------------------------------------------------------------------------- /src/components/flat-virtualized-list/FlatVirtualizedList.factory.jsx: -------------------------------------------------------------------------------- 1 | import { components as ReactSelectComponents } from 'react-select'; 2 | import React, { memo } from 'react'; 3 | import { menuListItemHeight } from '@rsv-lib/defaults'; 4 | import FlatVirtualizedList from './FlatVirtualizedList'; 5 | 6 | const FlatVirtualizedListFactory = ({ 7 | optionHeight = menuListItemHeight, 8 | defaultValue, 9 | valueGetter, 10 | formatOptionLabel, 11 | }) => 12 | memo((props) => { 13 | const selectedValue = props.getValue() ? props.getValue()[0] : undefined; 14 | 15 | if (props.children && !props.children.length) { 16 | return ; 17 | } 18 | 19 | return ( 20 | 28 | ); 29 | }); 30 | 31 | export default FlatVirtualizedListFactory; 32 | -------------------------------------------------------------------------------- /src/components/flat-virtualized-list/FlatVirtualizedList.jsx: -------------------------------------------------------------------------------- 1 | import { List, InfiniteLoader, AutoSizer } from 'react-virtualized'; 2 | import React, { useEffect, memo, useMemo, useState, useCallback } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import { getListHeight, getScrollIndex, getNextRowIndex } from '@rsv-lib/getters'; 5 | import { flatVirtualizedListRowRenderer } from '@rsv-lib/renderers'; 6 | import { useDebouncedCallback } from '@rsv-hooks/use-debaunced-callback'; 7 | 8 | const FlatListVirtualizedComponent = (props) => { 9 | let listComponent; 10 | 11 | const [focusedItemIndex, setFocusedItemIndex] = useState(undefined); 12 | const [queueScrollToIdx, setQueueScrollToIdx] = useState(undefined); 13 | 14 | const { maxHeight, children, optionHeight, options, selectedValue, defaultValue, valueGetter, formatOptionLabel } = 15 | props; 16 | 17 | useEffect(() => { 18 | // only scroll to index when we have something in the queue of focused and not visible 19 | if (listComponent && queueScrollToIdx !== undefined && focusedItemIndex !== undefined) { 20 | listComponent.current.scrollToRow(getNextRowIndex(focusedItemIndex, queueScrollToIdx, options)); 21 | setQueueScrollToIdx(undefined); 22 | } 23 | }, [listComponent, queueScrollToIdx, focusedItemIndex, options]); 24 | 25 | const onOptionFocused = useCallback( 26 | ({ index, isVisible }) => { 27 | // enqueue the changes to the task queue so we do not interrupt rendering 28 | setTimeout(() => { 29 | if (index !== undefined && focusedItemIndex !== index && isVisible) { 30 | setFocusedItemIndex(index); 31 | } else if (index !== undefined && !isVisible && !queueScrollToIdx) { 32 | setQueueScrollToIdx(index); 33 | } 34 | }, 100); 35 | }, 36 | [setFocusedItemIndex, focusedItemIndex, setQueueScrollToIdx, queueScrollToIdx], 37 | ); 38 | 39 | const height = useMemo( 40 | () => 41 | getListHeight({ 42 | maxHeight, 43 | totalSize: children.length, 44 | optionHeight, 45 | }), 46 | [maxHeight, children.length, optionHeight], 47 | ); 48 | 49 | const scrollToIndex = useMemo( 50 | () => 51 | getScrollIndex({ 52 | children: options, 53 | selected: selectedValue || defaultValue, 54 | valueGetter, 55 | }), 56 | [options, selectedValue, defaultValue, valueGetter], 57 | ); 58 | 59 | const rowRenderer = useMemo( 60 | () => 61 | flatVirtualizedListRowRenderer({ 62 | children, 63 | onOptionFocused, 64 | optionHeight, 65 | formatOptionLabel, 66 | }), 67 | [children, onOptionFocused, optionHeight, formatOptionLabel], 68 | ); 69 | 70 | const list = useMemo(() => [], []); 71 | 72 | const isRowLoaded = useCallback(({ index }) => !!list[index], [list]); 73 | 74 | const loadMoreRows = useDebouncedCallback(({ startIndex, stopIndex }) => { 75 | for (let i = startIndex; i <= stopIndex; i++) { 76 | list.push(children[i]); 77 | } 78 | }, 100); 79 | 80 | return ( 81 | 82 | {({ width }) => ( 83 | 90 | {({ onRowsRendered, registerChild }) => ( 91 | { 93 | registerChild(element); 94 | listComponent = { 95 | current: element, 96 | }; 97 | return element; 98 | }} 99 | onRowsRendered={onRowsRendered} 100 | height={height} 101 | scrollToIndex={scrollToIndex} 102 | rowCount={props.children.length} 103 | rowHeight={props.optionHeight} 104 | rowRenderer={rowRenderer} 105 | width={width} 106 | /> 107 | )} 108 | 109 | )} 110 | 111 | ); 112 | }; 113 | 114 | const FlatListVirtualized = memo(FlatListVirtualizedComponent); 115 | 116 | FlatListVirtualized.propTypes = { 117 | maxHeight: PropTypes.number, // this prop is coming from react-select 118 | children: PropTypes.node.isRequired, 119 | optionHeight: PropTypes.number, 120 | selectedValue: PropTypes.object, 121 | defaultValue: PropTypes.object, 122 | valueGetter: PropTypes.func, 123 | options: PropTypes.array.isRequired, 124 | minimumBatchSize: PropTypes.number, 125 | }; 126 | 127 | FlatListVirtualized.defaultProps = { 128 | valueGetter: (item) => item && item.value, 129 | maxHeight: 200, 130 | minimumBatchSize: 100, 131 | }; 132 | 133 | FlatListVirtualized.displayName = 'FlatListVirtualized'; 134 | 135 | export default FlatListVirtualized; 136 | -------------------------------------------------------------------------------- /src/components/flat-virtualized-list/index.js: -------------------------------------------------------------------------------- 1 | import FlatVirtualizedList from './FlatVirtualizedList'; 2 | import FlatVirtualizedListFactory from './FlatVirtualizedList.factory'; 3 | 4 | export { FlatVirtualizedList, FlatVirtualizedListFactory }; 5 | -------------------------------------------------------------------------------- /src/components/grouped-virtualized-list/GroupVirtualizedList.jsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useCallback, memo, useMemo, useState } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { List, InfiniteLoader, AutoSizer } from 'react-virtualized'; 4 | import { getListHeight, getScrollIndex, getNextRowIndex, getGroupRowHeight } from '@rsv-lib/getters'; 5 | import { groupVirtualizedListRowRenderer } from '@rsv-lib/renderers'; 6 | import { useDebouncedCallback } from '@rsv-hooks/use-debaunced-callback'; 7 | 8 | const GroupVirtualizedListComponent = (props) => { 9 | const [focusedItemIndex, setFocusedItemIndex] = useState(undefined); 10 | const [queueScrollToIdx, setQueueScrollToIdx] = useState(undefined); 11 | let listComponent; 12 | 13 | const { 14 | maxHeight, 15 | formatGroupHeader, 16 | formatOptionLabel, 17 | flatCollection, 18 | optionHeight, 19 | children, 20 | selectedValue, 21 | defaultValue, 22 | groupHeaderHeight, 23 | valueGetter, 24 | } = props; 25 | 26 | useEffect(() => { 27 | // only scroll to index when we have something in the queue of focused and not visible 28 | if (listComponent && queueScrollToIdx) { 29 | listComponent.current.scrollToRow(getNextRowIndex(focusedItemIndex, queueScrollToIdx, flatCollection)); 30 | setQueueScrollToIdx(undefined); 31 | } 32 | }, [listComponent, queueScrollToIdx, focusedItemIndex, flatCollection]); 33 | 34 | const onOptionFocused = useCallback( 35 | ({ index, isVisible }) => { 36 | // enqueue the changes to the task queue so we do not interrupt rendering 37 | setTimeout(() => { 38 | if (index !== undefined && isVisible) { 39 | setFocusedItemIndex(index); 40 | } else if (index !== undefined && !isVisible && !queueScrollToIdx) { 41 | setQueueScrollToIdx(index); 42 | } 43 | }, 100); 44 | }, 45 | [queueScrollToIdx], 46 | ); 47 | 48 | const height = useMemo( 49 | () => 50 | getListHeight({ 51 | maxHeight, 52 | totalSize: flatCollection.length, 53 | groupSize: children.length, 54 | optionHeight, 55 | groupHeaderHeight, 56 | }), 57 | [maxHeight, flatCollection.length, children.length, optionHeight, groupHeaderHeight], 58 | ); 59 | 60 | const scrollToIndex = useMemo( 61 | () => 62 | getScrollIndex({ 63 | children: flatCollection, 64 | selected: selectedValue || defaultValue, 65 | valueGetter, 66 | }), 67 | [flatCollection, selectedValue, defaultValue, valueGetter], 68 | ); 69 | 70 | const rowHeight = useMemo( 71 | () => 72 | getGroupRowHeight({ 73 | children: flatCollection, 74 | optionHeight, 75 | groupHeaderHeight, 76 | }), 77 | [flatCollection, optionHeight, groupHeaderHeight], 78 | ); 79 | 80 | const list = useMemo(() => [], []); 81 | 82 | const rowRenderer = useMemo( 83 | () => 84 | groupVirtualizedListRowRenderer({ 85 | children: flatCollection, 86 | formatGroupHeader, 87 | onOptionFocused, 88 | optionHeight, 89 | formatOptionLabel, 90 | }), 91 | [flatCollection, formatGroupHeader, onOptionFocused, optionHeight, formatOptionLabel], 92 | ); 93 | 94 | const isRowLoaded = useCallback(({ index }) => !!list[index], [list]); 95 | 96 | const loadMoreRows = useDebouncedCallback( 97 | ({ startIndex, stopIndex }) => { 98 | for (let i = startIndex; i <= stopIndex; i++) { 99 | list.push(children[i]); 100 | } 101 | }, 102 | 100, 103 | [flatCollection, list], 104 | ); 105 | 106 | return ( 107 | 108 | {({ width }) => ( 109 | 116 | {({ onRowsRendered, registerChild }) => ( 117 | { 119 | registerChild(element); 120 | listComponent = { 121 | current: element, 122 | }; 123 | return element; 124 | }} 125 | onRowsRendered={onRowsRendered} 126 | height={height} 127 | scrollToIndex={scrollToIndex} 128 | rowCount={props.flatCollection.length || 0} 129 | rowHeight={rowHeight} 130 | rowRenderer={rowRenderer} 131 | width={width} 132 | /> 133 | )} 134 | 135 | )} 136 | 137 | ); 138 | }; 139 | 140 | const GroupVirtualizedList = memo(GroupVirtualizedListComponent); 141 | 142 | GroupVirtualizedList.propTypes = { 143 | maxHeight: PropTypes.number, // this prop is coming from react-select 144 | children: PropTypes.node.isRequired, 145 | optionHeight: PropTypes.number, 146 | groupHeaderHeight: PropTypes.number, 147 | selectedValue: PropTypes.object, 148 | defaultValue: PropTypes.object, 149 | valueGetter: PropTypes.func, 150 | formatGroupHeader: PropTypes.func.isRequired, 151 | formatOptionLabel: PropTypes.func, 152 | flatCollection: PropTypes.array.isRequired, 153 | minimumBatchSize: PropTypes.number, 154 | }; 155 | 156 | GroupVirtualizedList.defaultProps = { 157 | valueGetter: (item) => item && item.value, 158 | formatOptionLabel: undefined, 159 | minimumBatchSize: 1000, 160 | }; 161 | 162 | GroupVirtualizedList.displayName = 'GroupVirtualizedList'; 163 | 164 | export default GroupVirtualizedList; 165 | -------------------------------------------------------------------------------- /src/components/grouped-virtualized-list/GroupedVirtualizedList.factory.jsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import { components as ReactSelectComponents } from 'react-select'; 3 | import { menuListItemHeight } from '@rsv-lib/defaults'; 4 | import { flattenGroupedOptions } from '@rsv-lib/utils'; 5 | import GroupListVirtualized from './GroupVirtualizedList'; 6 | 7 | const GroupedVirtualizedListFactory = ({ 8 | formatGroupHeader, 9 | optionHeight = menuListItemHeight, 10 | groupHeaderHeight = menuListItemHeight, 11 | defaultValue, 12 | valueGetter, 13 | }) => 14 | memo((props) => { 15 | const children = [...flattenGroupedOptions(props.children)]; 16 | const selectedValue = props.getValue() ? props.getValue()[0] : undefined; 17 | 18 | if (props.children && !props.children.length) { 19 | return ; 20 | } 21 | 22 | return ( 23 | 33 | ); 34 | }); 35 | 36 | export default GroupedVirtualizedListFactory; 37 | -------------------------------------------------------------------------------- /src/components/grouped-virtualized-list/index.js: -------------------------------------------------------------------------------- 1 | import GroupVirtualizedList from './GroupVirtualizedList'; 2 | import GroupVirtualizedListFactory from './GroupedVirtualizedList.factory'; 3 | 4 | export { GroupVirtualizedList, GroupVirtualizedListFactory }; 5 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | import Select from './select/Select'; 2 | import Async from './async/Async'; 3 | import Creatable from './creatable/CreatableSelectRenderer'; 4 | 5 | export { Select, Async, Creatable }; 6 | 7 | export default Select; 8 | -------------------------------------------------------------------------------- /src/components/select/Select.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React, { useRef, useImperativeHandle, useState, forwardRef, useMemo, memo, useCallback, useEffect } from 'react'; 3 | import './styles.css'; 4 | import { buildListComponents, getStyles } from '@rsv-lib/select'; 5 | import { defaultGroupFormat } from '@rsv-lib/renderers'; 6 | import 'react-virtualized/styles.css'; 7 | import { optionsPropTypes } from '@rsv-lib/prop-types'; 8 | import { buildErrorText } from '@rsv-lib/error'; 9 | import { FastReactSelect } from '../fast-react-select'; 10 | 11 | const throwMixControlledError = () => { 12 | throw new Error( 13 | buildErrorText( 14 | `Select do not support using defaultValue and value at the same time. Choose between uncontrolled or controlled component. 15 | Clear and Select component methods can only be used with uncontrolled components`, 16 | ), 17 | ); 18 | }; 19 | 20 | const SelectComponent = (props, ref) => { 21 | const reactSelect = useRef('react-select'); 22 | 23 | const { grouped, formatGroupHeaderLabel, groupHeaderHeight, onChange, defaultValue, value, optionHeight, creatable } = 24 | props; 25 | 26 | if (defaultValue && value) { 27 | throwMixControlledError(); 28 | } 29 | 30 | const [selection, setSelection] = useState(defaultValue || value); 31 | 32 | const defaultProps = { 33 | isMulti: false, 34 | isClearable: true, 35 | isDisabled: false, 36 | className: `react-select-virtualized`, 37 | isSearchable: true, 38 | blurInputOnSelect: true, 39 | }; 40 | 41 | useEffect(() => setSelection(value), [value]); 42 | 43 | const memoGroupHeaderOptions = useMemo(() => { 44 | if (!grouped && !formatGroupHeaderLabel && !groupHeaderHeight) return { formatGroupHeaderLabel: false }; 45 | 46 | const groupHeaderHeightValue = groupHeaderHeight || optionHeight; 47 | return { 48 | groupHeaderHeight: groupHeaderHeightValue, 49 | formatGroupHeaderLabel: formatGroupHeaderLabel || defaultGroupFormat(groupHeaderHeightValue), 50 | }; 51 | }, [grouped, formatGroupHeaderLabel, groupHeaderHeight, optionHeight]); 52 | 53 | const onChangeHandler = useCallback( 54 | (valueChanged, { action }) => { 55 | onChange(valueChanged, { action }); 56 | setSelection(valueChanged); 57 | }, 58 | [onChange, setSelection], 59 | ); 60 | 61 | useImperativeHandle(ref, () => ({ 62 | clear: () => { 63 | if (value) { 64 | throwMixControlledError(); 65 | } 66 | setSelection(null); 67 | }, 68 | focus: () => { 69 | reactSelect.current.focus(); 70 | }, 71 | blur: () => { 72 | reactSelect.current.blur(); 73 | }, 74 | select: (item) => { 75 | if (value) { 76 | throwMixControlledError(); 77 | } 78 | setSelection(item); 79 | }, 80 | })); 81 | 82 | return ( 83 | 100 | ); 101 | }; 102 | 103 | const SelectForward = forwardRef(SelectComponent); 104 | 105 | const Select = memo(SelectForward); 106 | 107 | Select.propTypes = { 108 | ...FastReactSelect.propTypes, 109 | options: optionsPropTypes.isRequired, 110 | onChange: PropTypes.func, 111 | grouped: PropTypes.bool, // this is only for performance enhancement so we do not need to iterate in the array many times. It is not needed if formatGroupHeaderLabel or groupHeaderHeight are defined 112 | formatGroupHeaderLabel: PropTypes.func, 113 | optionHeight: PropTypes.number, 114 | groupHeaderHeight: PropTypes.number, 115 | defaultValue: PropTypes.object, 116 | creatable: PropTypes.bool, 117 | }; 118 | 119 | Select.defaultProps = { 120 | grouped: false, 121 | optionHeight: 31, 122 | creatable: false, 123 | onChange: () => {}, 124 | }; 125 | 126 | Select.displayName = 'Select'; 127 | 128 | export default Select; 129 | -------------------------------------------------------------------------------- /src/components/select/Select.stories.css: -------------------------------------------------------------------------------- 1 | .react-select-virtualized { 2 | font-family: monospace; 3 | } 4 | 5 | .button { 6 | background-color: #4caf50; 7 | border: none; 8 | color: white; 9 | padding: 15px 32px; 10 | text-align: center; 11 | text-decoration: none; 12 | display: inline-block; 13 | font-size: 16px; 14 | margin: 4px 2px; 15 | cursor: pointer; 16 | } 17 | -------------------------------------------------------------------------------- /src/components/select/Select.stories.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { storiesOf } from '@storybook/react'; 3 | import { withInfo } from '@storybook/addon-info'; 4 | import { withState } from '@dump247/storybook-state'; 5 | import { action } from '@storybook/addon-actions'; 6 | import { optionsDefault, opsGroup, defaultValue, op1500, ops2500, op100 } from '@rsv-lib/data'; 7 | import Select from './_SelectTablePropsStoryFix'; 8 | import fileSizeRef from '../../../size.json'; 9 | 10 | storiesOf(`React Select Virtualized/props`, module) 11 | .addDecorator((story) =>
{story()}
) 12 | .addDecorator(withInfo) 13 | .addParameters({ 14 | info: { 15 | source: true, 16 | maxPropsIntoLine: 1, 17 | }, 18 | }) 19 | .add('Basic', () => ) 21 | .add('with default value controlled', () => { 39 | store.set({ value: val }); 40 | }} 41 | /> 42 | 43 | )), 44 | ) 45 | .add('with minimum input to 3', () => ; 50 | }) 51 | .add('with filterOptions(value with $$$number)', () => { 52 | const op1500Mapped = op1500.map((option, index) => ({ ...option, value: `${option.value}$$$${index}` })); 53 | const customFilter = (option, rawInput) => option && option.value.indexOf(rawInput) >= 0; 54 | return ) 57 | .add('empty options in the select', () => ; 65 | }) 66 | .add('select with custom labels format 2', () => { 67 | const labelFormat = ({ label, lang }, { context }) => { 68 | if (context === 'value') return `${label} - ${lang}`; 69 | return `${label} - this is great`; 70 | }; 71 | 72 | return ) 75 | .add('with grouped filterOptions(use index)', () => { 76 | const customFilter = (option, rawInput) => option && option.value.indexOf(rawInput) >= 0; 77 | return { 86 | store.set({ value: val }); 87 | action(`onChange`)(val); 88 | }} 89 | grouped 90 | /> 91 | )), 92 | ) 93 | .add('grouped custom format', () => { 94 | // this can be a css also 95 | const groupStyle = { 96 | background: 'lightcoral', 97 | height: '4em', 98 | lineHeight: '4em', 99 | textAlign: 'center', 100 | fontFamily: 'monospace', 101 | }; 102 | 103 | const groupHeaderHeight = 50; 104 | 105 | const groupFormat = ({ label, options }) => ( 106 |
107 | {label} --- ({options.length}) items in this group 108 |
109 | ); 110 | 111 | return ( 112 | 129 | 130 | ); 131 | }) 132 | .add('open selector', () => ) 34 | .add('with 100 elements', () => ) 36 | .add('with 500 elements', () => ) 38 | .add('with 1000 elements', () => ) 40 | .add('with 2500 elements', () => ) 42 | .add('with 6000 elements', () => ) 44 | .add('with 10500 elements', () => 47 | )) 48 | .add('with 20000 grouped elements', () => 51 | )); 52 | -------------------------------------------------------------------------------- /src/components/select/_SelectTablePropsStoryFix.jsx: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | import React from 'react'; 3 | 4 | import { optionsPropTypes } from '@rsv-lib/prop-types'; 5 | import SelectComponent from './Select'; 6 | 7 | const Select = (props) => ; 8 | 9 | Select.propTypes = { 10 | minimumInputSearch: PropTypes.number, 11 | options: optionsPropTypes.isRequired, 12 | onChange: PropTypes.func, 13 | grouped: PropTypes.bool, // this is only for performance enhancement so we do not need to iterate in the array many times. It is not needed if formatGroupHeaderLabel or groupHeaderHeight are defined 14 | formatGroupHeaderLabel: PropTypes.func, 15 | optionHeight: PropTypes.number, 16 | groupHeaderHeight: PropTypes.number, 17 | defaultValue: PropTypes.object, 18 | }; 19 | 20 | Select.defaultProps = { 21 | grouped: false, 22 | optionHeight: 31, 23 | minimumInputSearch: 0, 24 | }; 25 | 26 | Select.displayName = 'Select'; 27 | 28 | export default Select; 29 | -------------------------------------------------------------------------------- /src/components/select/styles.css: -------------------------------------------------------------------------------- 1 | .select-popup { 2 | z-index: 9; 3 | } 4 | 5 | .select-popup .ReactVirtualized__List { 6 | border: 1px solid lightgray; 7 | background: white; 8 | } 9 | 10 | .flat-virtualized-item, 11 | .grouped-virtualized-list-item { 12 | cursor: pointer; 13 | background-color: transparent; 14 | user-select: none; 15 | box-sizing: border-box; 16 | display: flex; 17 | } 18 | 19 | .flat-virtualized-item > div, 20 | .grouped-virtualized-list-item > div { 21 | width: 100%; 22 | height: 100%; 23 | } 24 | 25 | .fast-option { 26 | padding-left: 1em; 27 | text-overflow: ellipsis; 28 | height: 100%; 29 | } 30 | 31 | .fast-option-focused { 32 | background-color: #deebff; 33 | user-select: none; 34 | box-sizing: border-box; 35 | } 36 | 37 | .fast-option-selected { 38 | background-color: rgb(38, 132, 255); 39 | user-select: none; 40 | box-sizing: border-box; 41 | } 42 | 43 | .grouped-virtualized-list-item div[role='option'] { 44 | cursor: pointer; 45 | } 46 | 47 | .fast-option-create { 48 | cursor: default !important; 49 | } 50 | -------------------------------------------------------------------------------- /src/components/test.js: -------------------------------------------------------------------------------- 1 | import defaultSelect, { Select, Async, Creatable } from './index'; 2 | 3 | describe('exports expected', () => { 4 | it('packages available', () => { 5 | expect(defaultSelect).toStrictEqual(Select); 6 | expect(Select).toBeDefined(); 7 | expect(Async).toBeDefined(); 8 | expect(Creatable).toBeDefined(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /src/hooks/use-debaunced-callback/index.js: -------------------------------------------------------------------------------- 1 | import debounce from 'lodash.debounce'; 2 | import { useCallback } from 'react'; 3 | 4 | export const useDebouncedCallback = (callback, wait = 40) => { 5 | const debouncedCallbackHandler = useCallback( 6 | () => debounce(callback, wait, { leading: false, trailing: true }), 7 | [callback, wait], 8 | ); 9 | 10 | return debouncedCallbackHandler(); 11 | }; 12 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { Select, Async, Creatable } from './components'; 2 | 3 | export { Select, Async, Creatable }; 4 | 5 | export default Select; 6 | -------------------------------------------------------------------------------- /src/lib/data/index.js: -------------------------------------------------------------------------------- 1 | import faker from 'faker'; 2 | 3 | faker.seed(999); 4 | 5 | export const optionsDefaultStatic = new Array(20) 6 | .fill(null) 7 | .map((item, index) => ({ value: index, label: `label ${index}` })); 8 | 9 | export const defaultValueStatic = optionsDefaultStatic[0]; 10 | 11 | export const optionsDefault = new Array(20).fill(null).map(() => ({ 12 | value: faker.random.uuid(), 13 | label: `${faker.name.firstName()} - ${faker.internet.email()}`, 14 | lang: faker.address.country(), 15 | })); 16 | 17 | export const defaultValue = { ...optionsDefault[faker.random.number(19)] }; 18 | 19 | const guid = faker.random.uuid(); 20 | 21 | export const buildOptionsSize = (size) => 22 | new Array(Math.round(size)).fill(null).map((item, index) => ({ 23 | value: `${guid}-${index}`, 24 | label: `${faker.name.firstName()} - ${index} - ${faker.internet.email()}`, 25 | lang: faker.address.country(), 26 | })); 27 | 28 | export const op50 = buildOptionsSize(50); 29 | export const op100 = buildOptionsSize(100); 30 | export const op300 = buildOptionsSize(300); 31 | export const op500 = buildOptionsSize(500); 32 | export const op800 = buildOptionsSize(800); 33 | export const op1000 = buildOptionsSize(1000); 34 | export const op1500 = buildOptionsSize(1500); 35 | export const ops2500 = buildOptionsSize(2500); 36 | export const ops4500 = buildOptionsSize(4500); 37 | export const ops6000 = buildOptionsSize(6000); 38 | export const ops8000 = buildOptionsSize(8000); 39 | export const ops10500 = buildOptionsSize(10500); 40 | export const group1 = buildOptionsSize(40); 41 | export const group2 = buildOptionsSize(40); 42 | export const group3 = buildOptionsSize(40); 43 | export const group4 = buildOptionsSize(40); 44 | export const group5 = buildOptionsSize(40); 45 | export const group6 = buildOptionsSize(40); 46 | export const group7 = buildOptionsSize(40); 47 | export const group8 = buildOptionsSize(40); 48 | 49 | export const opsGroup = [ 50 | { label: `Group ${faker.name.firstName()}`, options: group1 }, 51 | { label: `Group ${faker.name.firstName()}`, options: group2 }, 52 | { label: `Group ${faker.name.firstName()}`, options: group3 }, 53 | { label: `Group ${faker.name.firstName()}`, options: group4 }, 54 | { label: `Group ${faker.name.firstName()}`, options: group5 }, 55 | { label: `Group ${faker.name.firstName()}`, options: group6 }, 56 | { label: `Group ${faker.name.firstName()}`, options: group7 }, 57 | { label: `Group ${faker.name.firstName()}`, options: group8 }, 58 | ]; 59 | 60 | export const opsGroup20000 = [ 61 | { label: `Group ${faker.name.firstName()}`, options: ops2500 }, 62 | { label: `Group ${faker.name.firstName()}`, options: ops2500 }, 63 | { label: `Group ${faker.name.firstName()}`, options: ops2500 }, 64 | { label: `Group ${faker.name.firstName()}`, options: ops2500 }, 65 | { label: `Group ${faker.name.firstName()}`, options: ops2500 }, 66 | { label: `Group ${faker.name.firstName()}`, options: ops2500 }, 67 | { label: `Group ${faker.name.firstName()}`, options: ops2500 }, 68 | { label: `Group ${faker.name.firstName()}`, options: ops2500 }, 69 | ]; 70 | 71 | export const opsGroupF = () => [ 72 | { label: `Group ${faker.name.firstName()}`, options: group1 }, 73 | { label: `Group ${faker.name.firstName()}`, options: group2 }, 74 | { label: `Group ${faker.name.firstName()}`, options: group3 }, 75 | { label: `Group ${faker.name.firstName()}`, options: group4 }, 76 | { label: `Group ${faker.name.firstName()}`, options: group5 }, 77 | { label: `Group ${faker.name.firstName()}`, options: group6 }, 78 | { label: `Group ${faker.name.firstName()}`, options: group7 }, 79 | { label: `Group ${faker.name.firstName()}`, options: group8 }, 80 | ]; 81 | -------------------------------------------------------------------------------- /src/lib/defaults/index.js: -------------------------------------------------------------------------------- 1 | export const offset = 4; 2 | 3 | export const menuListItemHeight = 40; 4 | -------------------------------------------------------------------------------- /src/lib/error/index.js: -------------------------------------------------------------------------------- 1 | import pkg from '../../../package.json'; 2 | 3 | export const buildErrorText = (error) => 4 | `REACT-SELECT-VIRTUALIZED: V:${pkg.version}- Problem Found: ${ 5 | error || 'Unknown' 6 | }. Please check the repo for any update: https://github.com/guiyep/react-select-virtualized (${pkg.description}) `; 7 | -------------------------------------------------------------------------------- /src/lib/getters/index.js: -------------------------------------------------------------------------------- 1 | import { offset } from '../defaults'; 2 | 3 | export const getListHeight = ({ 4 | maxHeight = 0, 5 | totalSize = 0, 6 | groupSize = 0, 7 | optionHeight = 1, 8 | groupHeaderHeight = 1, 9 | }) => Math.min(maxHeight, totalSize * optionHeight - groupSize * Math.abs(optionHeight - groupHeaderHeight)); 10 | 11 | export const getScrollIndex = ({ children, selected, valueGetter }) => { 12 | if (children && selected && valueGetter) 13 | return children.findIndex((child) => { 14 | // tru getting the value from the children 15 | let value = valueGetter(child); 16 | const selectedValue = valueGetter(selected); 17 | if (value !== undefined && value === selectedValue) { 18 | return true; 19 | } 20 | // try getting the item from the data otherwise 21 | value = child.props && valueGetter(child.props.data); 22 | if (value !== undefined && value === selectedValue) { 23 | return true; 24 | } 25 | return false; 26 | }); 27 | return undefined; 28 | }; 29 | 30 | export const getNextRowIndex = (prevFocusIndex = 0, nextIndex = 0, options = []) => { 31 | const goingDown = prevFocusIndex < nextIndex; 32 | const toRow = nextIndex + ((goingDown && offset) || -offset); 33 | const listSize = options.length; 34 | const nextOffsetItem = toRow < listSize ? toRow : listSize; 35 | const prevOffsetItem = toRow > 0 ? toRow : 0; 36 | return goingDown ? nextOffsetItem : prevOffsetItem; 37 | }; 38 | 39 | export const isGroupHeader = ({ typeGroup }) => !!typeGroup; 40 | 41 | export const getGroupRowHeight = 42 | ({ children, optionHeight, groupHeaderHeight }) => 43 | ({ index }) => { 44 | const thisProps = children[index].props || {}; 45 | return isGroupHeader(thisProps) ? groupHeaderHeight : optionHeight; 46 | }; 47 | -------------------------------------------------------------------------------- /src/lib/prop-types/index.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | const oneOptionPropType = PropTypes.shape({ 4 | label: PropTypes.string, 5 | value: PropTypes.oneOf([PropTypes.string, PropTypes.number]), 6 | }); 7 | 8 | export const optionsPropTypes = PropTypes.arrayOf( 9 | PropTypes.oneOfType([ 10 | oneOptionPropType, 11 | PropTypes.shape({ 12 | label: PropTypes.string, 13 | options: PropTypes.arrayOf(oneOptionPropType), 14 | }), 15 | ]), 16 | ); 17 | -------------------------------------------------------------------------------- /src/lib/renderers/flat-list.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { FastOption } from '@rsv-components/fast-option'; 4 | 5 | export const flatVirtualizedListRowRenderer = 6 | ({ children, onOptionFocused, optionHeight, formatOptionLabel }) => 7 | ({ key, index, style, isVisible, isScrolling }) => { 8 | // reality is that we do not need to pass the list here. we can work straight with the children. 9 | // since the actual behavior will be handled by the renderer 10 | const thisProps = children[index].props; 11 | 12 | if (thisProps.isFocused && !isScrolling) { 13 | onOptionFocused({ data: thisProps.data, index, isVisible, isScrolling }); 14 | } 15 | 16 | return ( 17 |
18 | 28 |
29 | ); 30 | }; 31 | -------------------------------------------------------------------------------- /src/lib/renderers/grouped-list.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { isGroupHeader } from '@rsv-lib/getters'; 3 | import { FastOption } from '@rsv-components/fast-option'; 4 | 5 | export const groupVirtualizedListRowRenderer = 6 | ({ children, formatGroupHeader, formatOptionLabel, optionHeight, onOptionFocused }) => 7 | ({ key, index, style, isVisible, isScrolling }) => { 8 | const thisProps = children[index].props; 9 | const isGroupHeaderValue = isGroupHeader(thisProps); 10 | 11 | if (thisProps.isSelected && !isGroupHeaderValue) { 12 | onOptionFocused({ data: thisProps.data, index, isVisible, isScrolling }); 13 | } 14 | 15 | return ( 16 |
17 | {isGroupHeaderValue ? ( 18 | formatGroupHeader({ 19 | label: thisProps.label, 20 | options: thisProps.options, 21 | }) 22 | ) : ( 23 | 33 | )} 34 |
35 | ); 36 | }; 37 | 38 | // TODO RENAME THIS 39 | export const defaultGroupFormat = (height) => { 40 | // this can be a css also 41 | const groupStyle = { 42 | color: 'grey', 43 | height, 44 | lineHeight: `${height}px`, 45 | textAlign: 'center', 46 | display: 'flex', 47 | alignItems: 'center', 48 | justifyContent: 'space-between', 49 | padding: '0 1em 0 1em', 50 | }; 51 | 52 | const groupBadgeStyles = { 53 | backgroundColor: '#EBECF0', 54 | borderRadius: '2em', 55 | color: '#172B4D', 56 | display: 'inline-block', 57 | fontSize: 12, 58 | fontWeight: 'normal', 59 | lineHeight: '1', 60 | minWidth: 1, 61 | padding: '0.16666666666667em 0.5em', 62 | textAlign: 'center', 63 | }; 64 | 65 | return ({ label, options }) => ( 66 |
67 |
{label}
68 |
{options.length}
69 |
70 | ); 71 | }; 72 | -------------------------------------------------------------------------------- /src/lib/renderers/index.js: -------------------------------------------------------------------------------- 1 | export * from './flat-list'; 2 | export * from './grouped-list'; 3 | -------------------------------------------------------------------------------- /src/lib/select/index.js: -------------------------------------------------------------------------------- 1 | import { GroupVirtualizedListFactory } from '@rsv-components/grouped-virtualized-list'; 2 | import { FlatVirtualizedListFactory } from '@rsv-components/flat-virtualized-list'; 3 | 4 | export const buildListComponents = (props) => { 5 | const components = {}; 6 | components.MenuList = props.grouped 7 | ? GroupVirtualizedListFactory({ 8 | formatGroupHeader: props.formatGroupHeaderLabel, 9 | groupHeaderHeight: props.groupHeaderHeight, 10 | optionHeight: props.optionHeight, 11 | defaultValue: props.defaultValue, 12 | }) 13 | : FlatVirtualizedListFactory({ 14 | optionHeight: props.optionHeight, 15 | defaultValue: props.defaultValue, 16 | formatOptionLabel: props.formatOptionLabel, 17 | }); 18 | 19 | return components; 20 | }; 21 | 22 | export const getStyles = () => ({ 23 | clearIndicator: (provided) => ({ 24 | ...provided, 25 | ':hover': { 26 | cursor: 'pointer', 27 | color: '#f22', 28 | }, 29 | }), 30 | }); 31 | -------------------------------------------------------------------------------- /src/lib/utils/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import { buildErrorText } from '@rsv-lib/error'; 3 | 4 | // this is very basic analize a bit more 5 | export const calculateDebounce = (size) => { 6 | if (size <= 30000) { 7 | return (size + 100) * 0.001; // approx 0.001 ms per action, calculate 100 extra actions. this is a constant value. pefromance degradation starts after 30000 elements 8 | } 9 | return (size + 100) * 0.005; // increase the action time so we have a buffer. 10 | }; 11 | 12 | // we have to go as low level as possible. so we get the best performance here. this is the most expensive operation 13 | export const filterByLowercaseLabel = (list, value, filterOption) => { 14 | const result = []; 15 | const size = list.length; 16 | 17 | if (typeof filterOption === 'function') { 18 | for (var i = 0; i < size; i++) { 19 | if (filterOption(list[i], value)) { 20 | result.push(list[i]); 21 | } 22 | } 23 | return result; 24 | } 25 | 26 | for (var i = 0; i < size; i++) { 27 | if (list[i].lowercaseLabel.indexOf(value) >= 0) { 28 | result.push(list[i]); 29 | } 30 | } 31 | return result; 32 | }; 33 | 34 | export const defaultFormatOptionLabel = (item) => item && item.label; 35 | 36 | export const mapLowercaseLabel = (list, formatOptionLabel = defaultFormatOptionLabel, iterator = () => ({})) => 37 | list.map((item) => { 38 | let label = formatOptionLabel(item, {}); 39 | 40 | // this is not a plain text 41 | if (typeof label !== 'string') { 42 | label = defaultFormatOptionLabel(item); 43 | } 44 | 45 | if (label === undefined || label === null) { 46 | throw new Error( 47 | buildErrorText( 48 | 'For performance reasons, if formatOptionLabel returns something different from text, the label element must be in the option. The label to display cannot be undefined or null.', 49 | ), 50 | ); 51 | } 52 | 53 | return { lowercaseLabel: label.toLowerCase(), ...item, ...iterator(item) }; 54 | }); 55 | 56 | // todo improve this 57 | export const filterGroupedElementsBy = (list, inputValLowercase, filterBy, filterOption) => 58 | list.reduce((acc, item) => { 59 | acc.push({ 60 | ...item, 61 | options: filterBy(item.options, inputValLowercase, filterOption), 62 | }); 63 | return acc; 64 | }, []); 65 | 66 | export const getFilteredItems = ({ inputValue, memoOptions, grouped, filterOption }) => { 67 | const inputValLowercase = inputValue && inputValue.toLowerCase(); 68 | if (!inputValue) { 69 | return memoOptions; 70 | } 71 | if (grouped) { 72 | return filterGroupedElementsBy(memoOptions, inputValLowercase, filterByLowercaseLabel, filterOption); 73 | } 74 | return filterByLowercaseLabel(memoOptions, inputValLowercase, filterOption); 75 | }; 76 | 77 | export const flattenGroupedOptions = (reactComponent) => 78 | (reactComponent && reactComponent.length ? reactComponent : []) 79 | .map((child) => [ 80 | { 81 | props: { 82 | typeGroup: 'group', 83 | label: child.props.data.label, 84 | options: child.props.options, 85 | }, 86 | }, 87 | ...child.props.children, 88 | ]) 89 | .reduce((accumulator, currentValue) => accumulator.concat(currentValue), []); 90 | 91 | // 1 is for the group item 92 | export const calculateTotalGroupedListSize = (options) => 93 | options.reduce((acc, item) => acc + 1 + item.options.length, 0); 94 | 95 | export const isDifferentValueOption = (op, val) => 96 | (op && val && op.value != val.value) || (!op && !!val) || (!!op && !val); 97 | -------------------------------------------------------------------------------- /storybook-static/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.css": "/main.css", 4 | "main.js": "/main.134ba73fff088321c094.bundle.js", 5 | "main.css.map": "/main.css.map", 6 | "main.js.map": "/main.134ba73fff088321c094.bundle.js.map", 7 | "runtime~main.js": "/runtime~main.134ba73fff088321c094.bundle.js", 8 | "runtime~main.js.map": "/runtime~main.134ba73fff088321c094.bundle.js.map", 9 | "vendors~main.css": "/vendors~main.css", 10 | "vendors~main.js": "/vendors~main.134ba73fff088321c094.bundle.js", 11 | "vendors~main.css.map": "/vendors~main.css.map", 12 | "vendors~main.js.map": "/vendors~main.134ba73fff088321c094.bundle.js.map", 13 | "iframe.html": "/iframe.html", 14 | "precache-manifest.fd6d748e385c84158335b5863d333e2a.js": "/precache-manifest.fd6d748e385c84158335b5863d333e2a.js", 15 | "service-worker.js": "/service-worker.js" 16 | } 17 | } -------------------------------------------------------------------------------- /storybook-static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guiyep/react-select-virtualized/0b3abc9513a562275307cd8594f689bde8df0c5b/storybook-static/favicon.ico -------------------------------------------------------------------------------- /storybook-static/iframe.html: -------------------------------------------------------------------------------- 1 | Storybook

No Preview

Sorry, but you either have no stories or none are selected somehow.

  • Please check the Storybook config.
  • Try reloading the page.

If the problem persists, check the browser console, or the terminal you've run Storybook from.

-------------------------------------------------------------------------------- /storybook-static/index.html: -------------------------------------------------------------------------------- 1 | Storybook
-------------------------------------------------------------------------------- /storybook-static/main.134ba73fff088321c094.bundle.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{12:function(module,__webpack_exports__,__webpack_require__){"use strict";__webpack_require__.d(__webpack_exports__,"q",function(){return optionsDefault}),__webpack_require__.d(__webpack_exports__,"b",function(){return defaultValue}),__webpack_require__.d(__webpack_exports__,"a",function(){return buildOptionsSize}),__webpack_require__.d(__webpack_exports__,"g",function(){return op50}),__webpack_require__.d(__webpack_exports__,"c",function(){return op100}),__webpack_require__.d(__webpack_exports__,"f",function(){return op300}),__webpack_require__.d(__webpack_exports__,"h",function(){return op500}),__webpack_require__.d(__webpack_exports__,"i",function(){return op800}),__webpack_require__.d(__webpack_exports__,"d",function(){return op1000}),__webpack_require__.d(__webpack_exports__,"e",function(){return op1500}),__webpack_require__.d(__webpack_exports__,"k",function(){return ops2500}),__webpack_require__.d(__webpack_exports__,"l",function(){return ops4500}),__webpack_require__.d(__webpack_exports__,"m",function(){return ops6000}),__webpack_require__.d(__webpack_exports__,"n",function(){return ops8000}),__webpack_require__.d(__webpack_exports__,"j",function(){return ops10500}),__webpack_require__.d(__webpack_exports__,"o",function(){return opsGroup}),__webpack_require__.d(__webpack_exports__,"p",function(){return opsGroup20000});var _Volumes_Guille_Desarollo_react_select_virtualized_node_modules_babel_preset_react_app_node_modules_babel_runtime_helpers_esm_objectSpread__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(50),generate_random_data__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(14),generate_random_data__WEBPACK_IMPORTED_MODULE_1___default=__webpack_require__.n(generate_random_data__WEBPACK_IMPORTED_MODULE_1__),optionsDefault=(Array(20).fill(null).map(function(a,b){return{value:b,label:"label ".concat(b)}})[0],Array(20).fill(null).map(function(){return{value:generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.guid(),label:"".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()," - ").concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.email("test.com.au")),lang:generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.language()}})),defaultValue=Object(_Volumes_Guille_Desarollo_react_select_virtualized_node_modules_babel_preset_react_app_node_modules_babel_runtime_helpers_esm_objectSpread__WEBPACK_IMPORTED_MODULE_0__.a)({},optionsDefault[generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.int(1,19)]),guid=generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.guid(),email=generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.email("test.com.au"),buildOptionsSize=function(a){return Array(Math.round(a)).fill(null).map(function(a,b){return{value:"".concat(guid,"-").concat(b),label:"".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()," - ").concat(b," - ").concat(email),lang:generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.language()}})},op50=buildOptionsSize(50),op100=buildOptionsSize(100),op300=buildOptionsSize(300),op500=buildOptionsSize(500),op800=buildOptionsSize(800),op1000=buildOptionsSize(1e3),op1500=buildOptionsSize(1500),ops2500=buildOptionsSize(2500),ops4500=buildOptionsSize(4500),ops6000=buildOptionsSize(6e3),ops8000=buildOptionsSize(8e3),ops10500=buildOptionsSize(10500),group1=buildOptionsSize(40),group2=buildOptionsSize(40),group3=buildOptionsSize(40),group4=buildOptionsSize(40),group5=buildOptionsSize(40),group6=buildOptionsSize(40),group7=buildOptionsSize(40),group8=buildOptionsSize(40),opsGroup=[{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:group1},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:group2},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:group3},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:group4},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:group5},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:group6},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:group7},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:group8}],opsGroup20000=[{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:ops2500},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:ops2500},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:ops2500},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:ops2500},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:ops2500},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:ops2500},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:ops2500},{label:"Group ".concat(generate_random_data__WEBPACK_IMPORTED_MODULE_1___default.a.maleFirstName()),options:ops2500}]},157:function(module,__webpack_exports__,__webpack_require__){"use strict";var prop_types__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(5),prop_types__WEBPACK_IMPORTED_MODULE_0___default=__webpack_require__.n(prop_types__WEBPACK_IMPORTED_MODULE_0__),oneOptionPropType=prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.shape({label:prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.string,value:prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.oneOf([prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.string,prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.number])});prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.arrayOf(prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.oneOfType([oneOptionPropType,prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.shape({label:prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.string,options:prop_types__WEBPACK_IMPORTED_MODULE_0___default.a.arrayOf(oneOptionPropType)})]))},165:function(module,__webpack_exports__,__webpack_require__){"use strict";var react=__webpack_require__(0),react_default=__webpack_require__.n(react),objectWithoutProperties=(__webpack_require__(157),__webpack_require__(433)),Select=__webpack_require__(214),Async=Object(react.memo)(function(a){var b=a.defaultOptions,c=a.loadOptions,e=(a.cacheOptions,a.onInputChange),f=a.minimumInputSearch,g=Object(objectWithoutProperties.a)(a,["defaultOptions","loadOptions","cacheOptions","onInputChange","minimumInputSearch"]),h=Object(react.useMemo)(function(){return b||[]},[b]),i=Object(react.useCallback)(function(a){return new Promise(function(b){c(a,function(a){b(a)})})},[c]);return react_default.a.createElement(Select.a,Object.assign({},g,{options:h,minimumInputSearch:f||!b&&1||0,asyncInputChange:e,asyncLoadOptions:i}))});Async.displayName="Async",Async.defaultProps={defaultOptions:void 0,onInputChange:void 0,cacheOptions:!0,minimumInputSearch:void 0};var async_Async=Async,_AsyncTablePropsStoryFix_Async=function(a){return react_default.a.createElement(async_Async,a)};_AsyncTablePropsStoryFix_Async.defaultProps={grouped:!1,optionHeight:31,minimumInputSearch:0,cacheOptions:!0},_AsyncTablePropsStoryFix_Async.displayName="Async";__webpack_exports__.a=_AsyncTablePropsStoryFix_Async;_AsyncTablePropsStoryFix_Async.__docgenInfo={description:"",methods:[],displayName:"Async",props:{grouped:{defaultValue:{value:"false",computed:!1},required:!1},optionHeight:{defaultValue:{value:"31",computed:!1},required:!1},minimumInputSearch:{defaultValue:{value:"0",computed:!1},required:!1},cacheOptions:{defaultValue:{value:"true",computed:!1},required:!1}}},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["src/select-virtualized/components/async/_AsyncTablePropsStoryFix.jsx"]={name:"Async",docgenInfo:_AsyncTablePropsStoryFix_Async.__docgenInfo,path:"src/select-virtualized/components/async/_AsyncTablePropsStoryFix.jsx"})},20:function(module,__webpack_exports__,__webpack_require__){"use strict";var react__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(0),react__WEBPACK_IMPORTED_MODULE_0___default=__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__),_Select__WEBPACK_IMPORTED_MODULE_2__=(__webpack_require__(157),__webpack_require__(214)),Select=function(a){return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Select__WEBPACK_IMPORTED_MODULE_2__.a,a)};Select.defaultProps={grouped:!1,optionHeight:31,minimumInputSearch:0},Select.displayName="Select",__webpack_exports__.a=Select,Select.__docgenInfo={description:"",methods:[],displayName:"Select",props:{grouped:{defaultValue:{value:"false",computed:!1},required:!1},optionHeight:{defaultValue:{value:"31",computed:!1},required:!1},minimumInputSearch:{defaultValue:{value:"0",computed:!1},required:!1}}},"undefined"!=typeof STORYBOOK_REACT_CLASSES&&(STORYBOOK_REACT_CLASSES["src/select-virtualized/components/select/_SelectTablePropsStoryFix.jsx"]={name:"Select",docgenInfo:Select.__docgenInfo,path:"src/select-virtualized/components/select/_SelectTablePropsStoryFix.jsx"})},214:function(module,__webpack_exports__,__webpack_require__){"use strict";var objectSpread=__webpack_require__(50),slicedToArray=__webpack_require__(81),defineProperty=__webpack_require__(211),react=__webpack_require__(0),react_default=__webpack_require__.n(react),react_select_browser_esm=__webpack_require__(206),dist_react_select_browser_esm=__webpack_require__(426),filterByLowercaseLabel=function(a,b){for(var c=[],d=a.length,e=0;e=a?.001*(a+100):.005*(a+100)}(j)},[j]),l=Object(react.useState)({currentInput:""}),m=Object(slicedToArray.a)(l,2),n=m[0],o=m[1],p=Object(react.useCallback)(function(a,b){c&&o(Object(objectSpread.a)({},n,Object(defineProperty.a)({currentInput:a},a||"",b)))},[c,o,n]),q=Object(react.useMemo)(function(){return mapLowercaseLabel(g,h,function(a){return a.options&&i?{options:mapLowercaseLabel(a.options,h)}:{}})},[g,h,i]),r=Object(react.useCallback)(function(a){if(c){var b=a&&a.toLowerCase()||"";p(b,f<=b.length)}e(a)},[e,p,c,f]),s=Object(react.useCallback)(function(a,b){return c&&!n[n.currentInput]?b(void 0):d?d(a).then(function(a){b(a)}):setTimeout(function(){b(getFilteredItems({inputValue:a,memoOptions:q,grouped:i}))},k)},[c,n,d,k,i,q]);return react_default.a.createElement(react.Fragment,null,j<=1e3&&!c&&!a.asyncLoadOptions&&react_default.a.createElement(react_select_browser_esm.a,Object.assign({ref:b},a)),(j>1e3||c||!!a.asyncLoadOptions)&&react_default.a.createElement(dist_react_select_browser_esm.a,Object.assign({ref:b},a,{loadingMessage:loadingMessage,cacheOptions:!a.grouped,loadOptions:s,defaultOptions:!!(1<=a.minimumInputSearch||0===q.length)||q,menuIsOpen:c?!!n[n.currentInput]:void 0,onInputChange:r})))};FastReactSelect=Object(react.forwardRef)(FastReactSelect),(FastReactSelect=Object(react.memo)(FastReactSelect)).defaultProps={minimumInputSearch:0,asyncLoadOptions:void 0,asyncInputChange:function(){}};var fast_react_select_FastReactSelect=FastReactSelect,es=(__webpack_require__(816),__webpack_require__(130)),getListHeight=function(a){var b=a.maxHeight,c=void 0===b?0:b,d=a.totalSize,e=void 0===d?0:d,f=a.groupSize,g=void 0===f?0:f,h=a.optionHeight,i=void 0===h?1:h,j=a.groupHeaderHeight,k=void 0===j?1:j;return Math.min(c,e*i-g*Math.abs(i-k))},getScrollIndex=function(a){var b=a.children,c=a.selected,d=a.valueGetter;return b&&c&&d?b.findIndex(function(a){return(d(a)||d(a.props.data))===d(c)}):void 0},getNextRowIndex=function(){var a=0 ({ value: index, label: `label ${index}` }));\n\nexport const defaultValueStatic = optionsDefaultStatic[0];\n\nexport const optionsDefault = new Array(20).fill(null).map(() => ({\n value: random.guid(),\n label: `${random.maleFirstName()} - ${random.email('test.com.au')}`,\n lang: random.language(),\n}));\n\nexport const defaultValue = { ...optionsDefault[random.int(1, 19)] };\n\nconst guid = random.guid();\nconst email = random.email('test.com.au');\n\nexport const buildOptionsSize = (size) => {\n return new Array(Math.round(size)).fill(null).map((item, index) => ({\n value: `${guid}-${index}`,\n label: `${random.maleFirstName()} - ${index} - ${email}`,\n lang: random.language(),\n }));\n};\n\nexport const op50 = buildOptionsSize(50);\nexport const op100 = buildOptionsSize(100);\nexport const op300 = buildOptionsSize(300);\nexport const op500 = buildOptionsSize(500);\nexport const op800 = buildOptionsSize(800);\nexport const op1000 = buildOptionsSize(1000);\nexport const op1500 = buildOptionsSize(1500);\nexport const ops2500 = buildOptionsSize(2500);\nexport const ops4500 = buildOptionsSize(4500);\nexport const ops6000 = buildOptionsSize(6000);\nexport const ops8000 = buildOptionsSize(8000);\nexport const ops10500 = buildOptionsSize(10500);\nexport const group1 = buildOptionsSize(40);\nexport const group2 = buildOptionsSize(40);\nexport const group3 = buildOptionsSize(40);\nexport const group4 = buildOptionsSize(40);\nexport const group5 = buildOptionsSize(40);\nexport const group6 = buildOptionsSize(40);\nexport const group7 = buildOptionsSize(40);\nexport const group8 = buildOptionsSize(40);\n\nexport const opsGroup = [\n { label: `Group ${random.maleFirstName()}`, options: group1 },\n { label: `Group ${random.maleFirstName()}`, options: group2 },\n { label: `Group ${random.maleFirstName()}`, options: group3 },\n { label: `Group ${random.maleFirstName()}`, options: group4 },\n { label: `Group ${random.maleFirstName()}`, options: group5 },\n { label: `Group ${random.maleFirstName()}`, options: group6 },\n { label: `Group ${random.maleFirstName()}`, options: group7 },\n { label: `Group ${random.maleFirstName()}`, options: group8 },\n];\n\nexport const opsGroup20000 = [\n { label: `Group ${random.maleFirstName()}`, options: ops2500 },\n { label: `Group ${random.maleFirstName()}`, options: ops2500 },\n { label: `Group ${random.maleFirstName()}`, options: ops2500 },\n { label: `Group ${random.maleFirstName()}`, options: ops2500 },\n { label: `Group ${random.maleFirstName()}`, options: ops2500 },\n { label: `Group ${random.maleFirstName()}`, options: ops2500 },\n { label: `Group ${random.maleFirstName()}`, options: ops2500 },\n { label: `Group ${random.maleFirstName()}`, options: ops2500 },\n];\n\nexport const opsGroupF = () => [\n { label: `Group ${random.maleFirstName()}`, options: group1 },\n { label: `Group ${random.maleFirstName()}`, options: group2 },\n { label: `Group ${random.maleFirstName()}`, options: group3 },\n { label: `Group ${random.maleFirstName()}`, options: group4 },\n { label: `Group ${random.maleFirstName()}`, options: group5 },\n { label: `Group ${random.maleFirstName()}`, options: group6 },\n { label: `Group ${random.maleFirstName()}`, options: group7 },\n { label: `Group ${random.maleFirstName()}`, options: group8 },\n];\n"],"mappings":"AAQA","sourceRoot":""} -------------------------------------------------------------------------------- /storybook-static/main.841d6cb694e7736fc069.bundle.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{0:function(n,o,p){p(329),p(432),n.exports=p(583)},432:function(n,o,p){"use strict";p.r(o);p(433),p(580)}},[[0,1,2]]]); -------------------------------------------------------------------------------- /storybook-static/main.css: -------------------------------------------------------------------------------- 1 | .select-popup { 2 | z-index: 9; 3 | } 4 | 5 | .select-popup .ReactVirtualized__List { 6 | border: 1px solid lightgray; 7 | background: white; 8 | } 9 | 10 | .flat-virtualized-item, .grouped-virtualized-list-item { 11 | cursor: pointer; 12 | background-color: transparent; 13 | -webkit-user-select: none; 14 | -moz-user-select: none; 15 | -ms-user-select: none; 16 | user-select: none; 17 | box-sizing: border-box; 18 | display: flex; 19 | } 20 | 21 | .flat-virtualized-item > div, .grouped-virtualized-list-item > div{ 22 | width: 100%; 23 | height: 100%; 24 | } 25 | 26 | .fast-option { 27 | padding-left: 1em; 28 | text-overflow: ellipsis; 29 | height: 100%; 30 | } 31 | 32 | 33 | .fast-option-focused { 34 | background-color: #DEEBFF; 35 | -webkit-user-select: none; 36 | -moz-user-select: none; 37 | -ms-user-select: none; 38 | user-select: none; 39 | box-sizing: border-box; 40 | } 41 | 42 | .grouped-virtualized-list-item div[role="option"]{ 43 | cursor: pointer; 44 | } 45 | .react-select-virtualized { 46 | font-family: monospace; 47 | } 48 | 49 | .button { 50 | background-color: #4CAF50; 51 | border: none; 52 | color: white; 53 | padding: 15px 32px; 54 | text-align: center; 55 | text-decoration: none; 56 | display: inline-block; 57 | font-size: 16px; 58 | margin: 4px 2px; 59 | cursor: pointer; 60 | } 61 | 62 | /*# sourceMappingURL=main.css.map*/ -------------------------------------------------------------------------------- /storybook-static/main.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"main.css","sources":["webpack:///styles.css","webpack:///Select.stories.css"],"sourcesContent":[".select-popup {\n z-index: 9;\n}\n\n.select-popup .ReactVirtualized__List {\n border: 1px solid lightgray;\n background: white;\n}\n\n.flat-virtualized-item, .grouped-virtualized-list-item {\n cursor: pointer;\n background-color: transparent;\n user-select: none;\n box-sizing: border-box;\n display: flex;\n}\n\n.flat-virtualized-item > div, .grouped-virtualized-list-item > div{\n width: 100%;\n height: 100%;\n}\n\n.fast-option {\n padding-left: 1em;\n text-overflow: ellipsis;\n height: 100%;\n}\n\n\n.fast-option-focused {\n background-color: #DEEBFF;\n user-select: none;\n box-sizing: border-box;\n}\n\n.grouped-virtualized-list-item div[role=\"option\"]{\n cursor: pointer;\n}",".react-select-virtualized {\n font-family: monospace;\n}\n\n.button {\n background-color: #4CAF50;\n border: none;\n color: white;\n padding: 15px 32px;\n text-align: center;\n text-decoration: none;\n display: inline-block;\n font-size: 16px;\n margin: 4px 2px;\n cursor: pointer;\n}"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;","sourceRoot":""} -------------------------------------------------------------------------------- /storybook-static/precache-manifest.fd6d748e385c84158335b5863d333e2a.js: -------------------------------------------------------------------------------- 1 | self.__precacheManifest = (self.__precacheManifest || []).concat([ 2 | { 3 | "revision": "96809159e21309a19808e3aacc63a99b", 4 | "url": "iframe.html" 5 | }, 6 | { 7 | "url": "main.134ba73fff088321c094.bundle.js" 8 | }, 9 | { 10 | "revision": "8416dd878ccbb170735a", 11 | "url": "main.css" 12 | }, 13 | { 14 | "url": "runtime~main.134ba73fff088321c094.bundle.js" 15 | }, 16 | { 17 | "url": "vendors~main.134ba73fff088321c094.bundle.js" 18 | }, 19 | { 20 | "revision": "79404c75bb92f7563344", 21 | "url": "vendors~main.css" 22 | } 23 | ]); -------------------------------------------------------------------------------- /storybook-static/runtime~main.0c4d778cda1a0e417528.bundle.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,f,i=r[0],l=r[1],a=r[2],c=0,s=[];c 34 | * 35 | * Copyright (c) 2014-2017, Jon Schlinkert. 36 | * Released under the MIT License. 37 | */ 38 | 39 | /** @license React v16.8.6 40 | * react-dom-server.browser.production.min.js 41 | * 42 | * Copyright (c) Facebook, Inc. and its affiliates. 43 | * 44 | * This source code is licensed under the MIT license found in the 45 | * LICENSE file in the root directory of this source tree. 46 | */ 47 | 48 | /*! 49 | * https://github.com/paulmillr/es6-shim 50 | * @license es6-shim Copyright 2013-2016 by Paul Miller (http://paulmillr.com) 51 | * and contributors, MIT License 52 | * es6-shim: v0.35.4 53 | * see https://github.com/paulmillr/es6-shim/blob/0.35.3/LICENSE 54 | * Details and documentation: 55 | * https://github.com/paulmillr/es6-shim/ 56 | */ 57 | 58 | /** @license React v16.8.6 59 | * react.production.min.js 60 | * 61 | * Copyright (c) Facebook, Inc. and its affiliates. 62 | * 63 | * This source code is licensed under the MIT license found in the 64 | * LICENSE file in the root directory of this source tree. 65 | */ 66 | 67 | /** @license React v16.8.6 68 | * react-is.production.min.js 69 | * 70 | * Copyright (c) Facebook, Inc. and its affiliates. 71 | * 72 | * This source code is licensed under the MIT license found in the 73 | * LICENSE file in the root directory of this source tree. 74 | */ 75 | 76 | /** @license React v0.13.6 77 | * scheduler.production.min.js 78 | * 79 | * Copyright (c) Facebook, Inc. and its affiliates. 80 | * 81 | * This source code is licensed under the MIT license found in the 82 | * LICENSE file in the root directory of this source tree. 83 | */ 84 | 85 | /* 86 | object-assign 87 | (c) Sindre Sorhus 88 | @license MIT 89 | */ 90 | 91 | /*! scrollbarWidth.js v0.1.3 | felixexter | MIT | https://github.com/felixexter/scrollbarWidth */ 92 | 93 | /*! 94 | * Fuse.js v3.4.4 - Lightweight fuzzy-search (http://fusejs.io) 95 | * 96 | * Copyright (c) 2012-2017 Kirollos Risk (http://kiro.me) 97 | * All Rights Reserved. Apache Software License 2.0 98 | * 99 | * http://www.apache.org/licenses/LICENSE-2.0 100 | */ 101 | 102 | /** @license React v16.8.6 103 | * react-dom.production.min.js 104 | * 105 | * Copyright (c) Facebook, Inc. and its affiliates. 106 | * 107 | * This source code is licensed under the MIT license found in the 108 | * LICENSE file in the root directory of this source tree. 109 | */ 110 | 111 | /*! 112 | Copyright (c) 2016 Jed Watson. 113 | Licensed under the MIT License (MIT), see 114 | http://jedwatson.github.io/classnames 115 | */ 116 | -------------------------------------------------------------------------------- /storybook-static/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to your Workbox-powered service worker! 3 | * 4 | * You'll need to register this file in your web app and you should 5 | * disable HTTP caching for this file too. 6 | * See https://goo.gl/nhQhGp 7 | * 8 | * The rest of the code is auto-generated. Please don't update this file 9 | * directly; instead, make changes to your Workbox build configuration 10 | * and re-run your build process. 11 | * See https://goo.gl/2aRDsh 12 | */ 13 | 14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); 15 | 16 | importScripts( 17 | "precache-manifest.fd6d748e385c84158335b5863d333e2a.js" 18 | ); 19 | 20 | self.addEventListener('message', (event) => { 21 | if (event.data && event.data.type === 'SKIP_WAITING') { 22 | self.skipWaiting(); 23 | } 24 | }); 25 | 26 | workbox.core.clientsClaim(); 27 | 28 | /** 29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to 30 | * requests for URLs in the manifest. 31 | * See https://goo.gl/S9QRab 32 | */ 33 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 35 | 36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/index.html"), { 37 | 38 | blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/], 39 | }); 40 | -------------------------------------------------------------------------------- /storybook-static/vendors~main.css: -------------------------------------------------------------------------------- 1 | .info-table { 2 | width: 100%; 3 | } 4 | 5 | .info-table, .info-table td, .info-table th { 6 | border-collapse: collapse; 7 | border: 1px solid #cccccc; 8 | color: #444444; 9 | margin-top: 0.25rem; 10 | padding-right: 0.5rem; 11 | padding: 0.25rem; 12 | text-align: left; 13 | vertical-align: top; 14 | } 15 | 16 | .info-table-monospace { 17 | font-family: Menlo, Monaco, "Courier New", monospace; 18 | font-size: 0.88em; 19 | } 20 | 21 | /* Collection default theme */ 22 | 23 | .ReactVirtualized__Collection { 24 | } 25 | 26 | .ReactVirtualized__Collection__innerScrollContainer { 27 | } 28 | 29 | /* Grid default theme */ 30 | 31 | .ReactVirtualized__Grid { 32 | } 33 | 34 | .ReactVirtualized__Grid__innerScrollContainer { 35 | } 36 | 37 | /* Table default theme */ 38 | 39 | .ReactVirtualized__Table { 40 | } 41 | 42 | .ReactVirtualized__Table__Grid { 43 | } 44 | 45 | .ReactVirtualized__Table__headerRow { 46 | font-weight: 700; 47 | text-transform: uppercase; 48 | display: flex; 49 | flex-direction: row; 50 | align-items: center; 51 | } 52 | .ReactVirtualized__Table__row { 53 | display: flex; 54 | flex-direction: row; 55 | align-items: center; 56 | } 57 | 58 | .ReactVirtualized__Table__headerTruncatedText { 59 | display: inline-block; 60 | max-width: 100%; 61 | white-space: nowrap; 62 | text-overflow: ellipsis; 63 | overflow: hidden; 64 | } 65 | 66 | .ReactVirtualized__Table__headerColumn, 67 | .ReactVirtualized__Table__rowColumn { 68 | margin-right: 10px; 69 | min-width: 0px; 70 | } 71 | .ReactVirtualized__Table__rowColumn { 72 | text-overflow: ellipsis; 73 | white-space: nowrap; 74 | } 75 | 76 | .ReactVirtualized__Table__headerColumn:first-of-type, 77 | .ReactVirtualized__Table__rowColumn:first-of-type { 78 | margin-left: 10px; 79 | } 80 | .ReactVirtualized__Table__sortableHeaderColumn { 81 | cursor: pointer; 82 | } 83 | 84 | .ReactVirtualized__Table__sortableHeaderIconContainer { 85 | display: flex; 86 | align-items: center; 87 | } 88 | .ReactVirtualized__Table__sortableHeaderIcon { 89 | flex: 0 0 24px; 90 | height: 1em; 91 | width: 1em; 92 | fill: currentColor; 93 | } 94 | 95 | /* List default theme */ 96 | 97 | .ReactVirtualized__List { 98 | } 99 | 100 | /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS9zdHlsZXMuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDhCQUE4Qjs7QUFFOUI7Q0FDQzs7QUFFRDtDQUNDOztBQUVELHdCQUF3Qjs7QUFFeEI7Q0FDQzs7QUFFRDtDQUNDOztBQUVELHlCQUF5Qjs7QUFFekI7Q0FDQzs7QUFFRDtDQUNDOztBQUVEO0VBQ0UsaUJBQWlCO0VBQ2pCLDBCQUEwQjtFQUMxQixxQkFBYztFQUFkLHFCQUFjO0VBQWQsY0FBYztFQUNkLCtCQUFvQjtFQUFwQiw4QkFBb0I7TUFBcEIsd0JBQW9CO1VBQXBCLG9CQUFvQjtFQUNwQiwwQkFBb0I7TUFBcEIsdUJBQW9CO1VBQXBCLG9CQUFvQjtDQUNyQjtBQUNEO0VBQ0UscUJBQWM7RUFBZCxxQkFBYztFQUFkLGNBQWM7RUFDZCwrQkFBb0I7RUFBcEIsOEJBQW9CO01BQXBCLHdCQUFvQjtVQUFwQixvQkFBb0I7RUFDcEIsMEJBQW9CO01BQXBCLHVCQUFvQjtVQUFwQixvQkFBb0I7Q0FDckI7O0FBRUQ7RUFDRSxzQkFBc0I7RUFDdEIsZ0JBQWdCO0VBQ2hCLG9CQUFvQjtFQUNwQix3QkFBd0I7RUFDeEIsaUJBQWlCO0NBQ2xCOztBQUVEOztFQUVFLG1CQUFtQjtFQUNuQixlQUFlO0NBQ2hCO0FBQ0Q7RUFDRSx3QkFBd0I7RUFDeEIsb0JBQW9CO0NBQ3JCOztBQUVEOztFQUVFLGtCQUFrQjtDQUNuQjtBQUNEO0VBQ0UsZ0JBQWdCO0NBQ2pCOztBQUVEO0VBQ0UscUJBQWM7RUFBZCxxQkFBYztFQUFkLGNBQWM7RUFDZCwwQkFBb0I7TUFBcEIsdUJBQW9CO1VBQXBCLG9CQUFvQjtDQUNyQjtBQUNEO0VBQ0Usb0JBQWU7TUFBZixtQkFBZTtVQUFmLGVBQWU7RUFDZixZQUFZO0VBQ1osV0FBVztFQUNYLG1CQUFtQjtDQUNwQjs7QUFFRCx3QkFBd0I7O0FBRXhCO0NBQ0MiLCJmaWxlIjoic3R5bGVzLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIENvbGxlY3Rpb24gZGVmYXVsdCB0aGVtZSAqL1xuXG4uUmVhY3RWaXJ0dWFsaXplZF9fQ29sbGVjdGlvbiB7XG59XG5cbi5SZWFjdFZpcnR1YWxpemVkX19Db2xsZWN0aW9uX19pbm5lclNjcm9sbENvbnRhaW5lciB7XG59XG5cbi8qIEdyaWQgZGVmYXVsdCB0aGVtZSAqL1xuXG4uUmVhY3RWaXJ0dWFsaXplZF9fR3JpZCB7XG59XG5cbi5SZWFjdFZpcnR1YWxpemVkX19HcmlkX19pbm5lclNjcm9sbENvbnRhaW5lciB7XG59XG5cbi8qIFRhYmxlIGRlZmF1bHQgdGhlbWUgKi9cblxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlIHtcbn1cblxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19HcmlkIHtcbn1cblxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19oZWFkZXJSb3cge1xuICBmb250LXdlaWdodDogNzAwO1xuICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xufVxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19yb3cge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xufVxuXG4uUmVhY3RWaXJ0dWFsaXplZF9fVGFibGVfX2hlYWRlclRydW5jYXRlZFRleHQge1xuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gIG1heC13aWR0aDogMTAwJTtcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gIG92ZXJmbG93OiBoaWRkZW47XG59XG5cbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9faGVhZGVyQ29sdW1uLFxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19yb3dDb2x1bW4ge1xuICBtYXJnaW4tcmlnaHQ6IDEwcHg7XG4gIG1pbi13aWR0aDogMHB4O1xufVxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19yb3dDb2x1bW4ge1xuICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbn1cblxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19oZWFkZXJDb2x1bW46Zmlyc3Qtb2YtdHlwZSxcbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9fcm93Q29sdW1uOmZpcnN0LW9mLXR5cGUge1xuICBtYXJnaW4tbGVmdDogMTBweDtcbn1cbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9fc29ydGFibGVIZWFkZXJDb2x1bW4ge1xuICBjdXJzb3I6IHBvaW50ZXI7XG59XG5cbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9fc29ydGFibGVIZWFkZXJJY29uQ29udGFpbmVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbn1cbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9fc29ydGFibGVIZWFkZXJJY29uIHtcbiAgZmxleDogMCAwIDI0cHg7XG4gIGhlaWdodDogMWVtO1xuICB3aWR0aDogMWVtO1xuICBmaWxsOiBjdXJyZW50Q29sb3I7XG59XG5cbi8qIExpc3QgZGVmYXVsdCB0aGVtZSAqL1xuXG4uUmVhY3RWaXJ0dWFsaXplZF9fTGlzdCB7XG59XG4iXX0= */ 101 | 102 | /*# sourceMappingURL=vendors~main.css.map*/ -------------------------------------------------------------------------------- /storybook-static/vendors~main.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"vendors~main.css","sources":["webpack:///style.css","webpack:///source/styles.css","webpack:///styles.css"],"sourcesContent":[".info-table {\n width: 100%;\n}\n\n.info-table, .info-table td, .info-table th {\n border-collapse: collapse;\n border: 1px solid #cccccc;\n color: #444444;\n margin-top: 0.25rem;\n padding-right: 0.5rem;\n padding: 0.25rem;\n text-align: left;\n vertical-align: top;\n}\n\n.info-table-monospace {\n font-family: Menlo, Monaco, \"Courier New\", monospace;\n font-size: 0.88em;\n}\n","/* Collection default theme */\n\n.ReactVirtualized__Collection {\n}\n\n.ReactVirtualized__Collection__innerScrollContainer {\n}\n\n/* Grid default theme */\n\n.ReactVirtualized__Grid {\n}\n\n.ReactVirtualized__Grid__innerScrollContainer {\n}\n\n/* Table default theme */\n\n.ReactVirtualized__Table {\n}\n\n.ReactVirtualized__Table__Grid {\n}\n\n.ReactVirtualized__Table__headerRow {\n font-weight: 700;\n text-transform: uppercase;\n display: flex;\n flex-direction: row;\n align-items: center;\n}\n.ReactVirtualized__Table__row {\n display: flex;\n flex-direction: row;\n align-items: center;\n}\n\n.ReactVirtualized__Table__headerTruncatedText {\n display: inline-block;\n max-width: 100%;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.ReactVirtualized__Table__headerColumn,\n.ReactVirtualized__Table__rowColumn {\n margin-right: 10px;\n min-width: 0px;\n}\n.ReactVirtualized__Table__rowColumn {\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.ReactVirtualized__Table__headerColumn:first-of-type,\n.ReactVirtualized__Table__rowColumn:first-of-type {\n margin-left: 10px;\n}\n.ReactVirtualized__Table__sortableHeaderColumn {\n cursor: pointer;\n}\n\n.ReactVirtualized__Table__sortableHeaderIconContainer {\n display: flex;\n align-items: center;\n}\n.ReactVirtualized__Table__sortableHeaderIcon {\n flex: 0 0 24px;\n height: 1em;\n width: 1em;\n fill: currentColor;\n}\n\n/* List default theme */\n\n.ReactVirtualized__List {\n}\n","/* Collection default theme */\n\n.ReactVirtualized__Collection {\n}\n\n.ReactVirtualized__Collection__innerScrollContainer {\n}\n\n/* Grid default theme */\n\n.ReactVirtualized__Grid {\n}\n\n.ReactVirtualized__Grid__innerScrollContainer {\n}\n\n/* Table default theme */\n\n.ReactVirtualized__Table {\n}\n\n.ReactVirtualized__Table__Grid {\n}\n\n.ReactVirtualized__Table__headerRow {\n font-weight: 700;\n text-transform: uppercase;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-orient: horizontal;\n -webkit-box-direction: normal;\n -ms-flex-direction: row;\n flex-direction: row;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n}\n.ReactVirtualized__Table__row {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-orient: horizontal;\n -webkit-box-direction: normal;\n -ms-flex-direction: row;\n flex-direction: row;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n}\n\n.ReactVirtualized__Table__headerTruncatedText {\n display: inline-block;\n max-width: 100%;\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.ReactVirtualized__Table__headerColumn,\n.ReactVirtualized__Table__rowColumn {\n margin-right: 10px;\n min-width: 0px;\n}\n.ReactVirtualized__Table__rowColumn {\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.ReactVirtualized__Table__headerColumn:first-of-type,\n.ReactVirtualized__Table__rowColumn:first-of-type {\n margin-left: 10px;\n}\n.ReactVirtualized__Table__sortableHeaderColumn {\n cursor: pointer;\n}\n\n.ReactVirtualized__Table__sortableHeaderIconContainer {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n}\n.ReactVirtualized__Table__sortableHeaderIcon {\n -webkit-box-flex: 0;\n -ms-flex: 0 0 24px;\n flex: 0 0 24px;\n height: 1em;\n width: 1em;\n fill: currentColor;\n}\n\n/* List default theme */\n\n.ReactVirtualized__List {\n}\n\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInNvdXJjZS9zdHlsZXMuY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDhCQUE4Qjs7QUFFOUI7Q0FDQzs7QUFFRDtDQUNDOztBQUVELHdCQUF3Qjs7QUFFeEI7Q0FDQzs7QUFFRDtDQUNDOztBQUVELHlCQUF5Qjs7QUFFekI7Q0FDQzs7QUFFRDtDQUNDOztBQUVEO0VBQ0UsaUJBQWlCO0VBQ2pCLDBCQUEwQjtFQUMxQixxQkFBYztFQUFkLHFCQUFjO0VBQWQsY0FBYztFQUNkLCtCQUFvQjtFQUFwQiw4QkFBb0I7TUFBcEIsd0JBQW9CO1VBQXBCLG9CQUFvQjtFQUNwQiwwQkFBb0I7TUFBcEIsdUJBQW9CO1VBQXBCLG9CQUFvQjtDQUNyQjtBQUNEO0VBQ0UscUJBQWM7RUFBZCxxQkFBYztFQUFkLGNBQWM7RUFDZCwrQkFBb0I7RUFBcEIsOEJBQW9CO01BQXBCLHdCQUFvQjtVQUFwQixvQkFBb0I7RUFDcEIsMEJBQW9CO01BQXBCLHVCQUFvQjtVQUFwQixvQkFBb0I7Q0FDckI7O0FBRUQ7RUFDRSxzQkFBc0I7RUFDdEIsZ0JBQWdCO0VBQ2hCLG9CQUFvQjtFQUNwQix3QkFBd0I7RUFDeEIsaUJBQWlCO0NBQ2xCOztBQUVEOztFQUVFLG1CQUFtQjtFQUNuQixlQUFlO0NBQ2hCO0FBQ0Q7RUFDRSx3QkFBd0I7RUFDeEIsb0JBQW9CO0NBQ3JCOztBQUVEOztFQUVFLGtCQUFrQjtDQUNuQjtBQUNEO0VBQ0UsZ0JBQWdCO0NBQ2pCOztBQUVEO0VBQ0UscUJBQWM7RUFBZCxxQkFBYztFQUFkLGNBQWM7RUFDZCwwQkFBb0I7TUFBcEIsdUJBQW9CO1VBQXBCLG9CQUFvQjtDQUNyQjtBQUNEO0VBQ0Usb0JBQWU7TUFBZixtQkFBZTtVQUFmLGVBQWU7RUFDZixZQUFZO0VBQ1osV0FBVztFQUNYLG1CQUFtQjtDQUNwQjs7QUFFRCx3QkFBd0I7O0FBRXhCO0NBQ0MiLCJmaWxlIjoic3R5bGVzLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIENvbGxlY3Rpb24gZGVmYXVsdCB0aGVtZSAqL1xuXG4uUmVhY3RWaXJ0dWFsaXplZF9fQ29sbGVjdGlvbiB7XG59XG5cbi5SZWFjdFZpcnR1YWxpemVkX19Db2xsZWN0aW9uX19pbm5lclNjcm9sbENvbnRhaW5lciB7XG59XG5cbi8qIEdyaWQgZGVmYXVsdCB0aGVtZSAqL1xuXG4uUmVhY3RWaXJ0dWFsaXplZF9fR3JpZCB7XG59XG5cbi5SZWFjdFZpcnR1YWxpemVkX19HcmlkX19pbm5lclNjcm9sbENvbnRhaW5lciB7XG59XG5cbi8qIFRhYmxlIGRlZmF1bHQgdGhlbWUgKi9cblxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlIHtcbn1cblxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19HcmlkIHtcbn1cblxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19oZWFkZXJSb3cge1xuICBmb250LXdlaWdodDogNzAwO1xuICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xufVxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19yb3cge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LWRpcmVjdGlvbjogcm93O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xufVxuXG4uUmVhY3RWaXJ0dWFsaXplZF9fVGFibGVfX2hlYWRlclRydW5jYXRlZFRleHQge1xuICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gIG1heC13aWR0aDogMTAwJTtcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbiAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7XG4gIG92ZXJmbG93OiBoaWRkZW47XG59XG5cbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9faGVhZGVyQ29sdW1uLFxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19yb3dDb2x1bW4ge1xuICBtYXJnaW4tcmlnaHQ6IDEwcHg7XG4gIG1pbi13aWR0aDogMHB4O1xufVxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19yb3dDb2x1bW4ge1xuICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbiAgd2hpdGUtc3BhY2U6IG5vd3JhcDtcbn1cblxuLlJlYWN0VmlydHVhbGl6ZWRfX1RhYmxlX19oZWFkZXJDb2x1bW46Zmlyc3Qtb2YtdHlwZSxcbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9fcm93Q29sdW1uOmZpcnN0LW9mLXR5cGUge1xuICBtYXJnaW4tbGVmdDogMTBweDtcbn1cbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9fc29ydGFibGVIZWFkZXJDb2x1bW4ge1xuICBjdXJzb3I6IHBvaW50ZXI7XG59XG5cbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9fc29ydGFibGVIZWFkZXJJY29uQ29udGFpbmVyIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbn1cbi5SZWFjdFZpcnR1YWxpemVkX19UYWJsZV9fc29ydGFibGVIZWFkZXJJY29uIHtcbiAgZmxleDogMCAwIDI0cHg7XG4gIGhlaWdodDogMWVtO1xuICB3aWR0aDogMWVtO1xuICBmaWxsOiBjdXJyZW50Q29sb3I7XG59XG5cbi8qIExpc3QgZGVmYXVsdCB0aGVtZSAqL1xuXG4uUmVhY3RWaXJ0dWFsaXplZF9fTGlzdCB7XG59XG4iXX0= */"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;ACCA;AACA;ADCA;ACCA;AACA;ADCA;AACA;AACA;ACCA;AACA;ADCA;ACCA;AACA;ADCA;AACA;AACA;ACCA;AACA;ADCA;ACCA;AACA;ADCA;AACA;AACA;AACA;AACA;AACA;ACQA;ADNA;AACA;AACA;AACA;ACeA;AACA;ADbA;AACA;AACA;AACA;AACA;AACA;ACeA;AACA;ADbA;;AAEA;AACA;ACeA;ADbA;AACA;AACA;ACeA;AACA;ADbA;;AAEA;ACeA;ADbA;AACA;ACeA;AACA;ADbA;AACA;AACA;ACmBA;ADjBA;AACA;AACA;AACA;AACA;ACqBA;AACA;ADnBA;AACA;AACA;ACqBA;AACA;AACA;","sourceRoot":""} --------------------------------------------------------------------------------