diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000000..93cda006dd --- /dev/null +++ b/.browserslistrc @@ -0,0 +1,3 @@ +> 0.25% +ie 11 +not op_mini all diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000000..26f218eda3 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,36 @@ +# Changesets + +Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with `bolt` to help you release components from a mono-repository. You can find the full documentation for it [here](https://www.npmjs.com/package/@changesets/cli) + +To help you get started though, here are some things you should know about this folder: + +## Changesets are automatically generated + +Changesets are generated by the `yarn changeset` or `npx changeset` command. As long as you are following a changeset release flow, you shouldn't have any problems. + +## Each changeset is its own folder + +We use hashes by default for these folder names to avoid collisions when generating them, but there's no harm that will come from renaming them. + +## Changesets are automatically removed + +When `changeset bump` or equivalent command is run, all the changeset folders are removed. This is so we only ever use a changeset once. This makes this a very bad place to store any other information. + +## Changesets come in two parts + +You should treat these parts quite differently: + +- `changes.md` is a file you should feel free to edit as much as you want. It will be prepended to your changelog when you next run your version command. +- `changes.json` is a file that includes information about releases, what should be versioned by the version command. We strongly recommend against editing this directly, as you may make a new changeset that puts your bolt repository into an invalid state. + +## I want to edit the information in a `changes.json` - how do I do it safely? + +The best option is to make a new changeset using the changeset command, copy over the `changes.md`, then delete the old changeset. + +## Can I rename the folder for my changeset? + +Absolutely! We need unique hashes to make changesets play nicely with git, but changing your folder from our hash to your own name isn't going to cause any problems. + +## Can I manually delete changesets? + +You can, but you should be aware this will remove the intent to release communicated by the changeset, and should be done with caution. diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000000..71ec72852f --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@0.2.1/schema.json", + "changelog": "./getChangelogEntry", + "commit": false, + "linked": [], + "access": "public" +} diff --git a/.changeset/getChangelogEntry.js b/.changeset/getChangelogEntry.js new file mode 100644 index 0000000000..91554cbd2f --- /dev/null +++ b/.changeset/getChangelogEntry.js @@ -0,0 +1,34 @@ +require('dotenv').config(); +const { getInfo } = require('@changesets/get-github-info'); + +const getReleaseLine = async (changeset, type) => { + const [firstLine, ...futureLines] = changeset.summary + .split('\n') + .map((l) => l.trimRight()); + let { links } = await getInfo({ + repo: 'JedWatson/react-select', + commit: changeset.commit, + }); + return `- ${links.commit}${links.pull === null ? '' : ` ${links.pull}`}${ + links.user === null ? '' : ` Thanks ${links.user}!` + } - ${firstLine}\n${futureLines.map((l) => ` ${l}`).join('\n')}`; +}; + +const getDependencyReleaseLine = async (changesets, dependenciesUpdated) => { + if (dependenciesUpdated.length === 0) return ''; + + const changesetLinks = changesets.map( + (changeset) => `- Updated dependencies [${changeset.commit}]:` + ); + + const updatedDepenenciesList = dependenciesUpdated.map( + (dependency) => ` - ${dependency.name}@${dependency.version}` + ); + + return [...changesetLinks, ...updatedDepenenciesList].join('\n'); +}; + +module.exports = { + getReleaseLine, + getDependencyReleaseLine, +}; diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000..0664c44068 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,75 @@ +version: 2 + +docker_defaults: &docker_defaults + docker: + - image: cypress/browsers:latest + environment: + TERM: xterm + working_directory: ~/project/repo + +attach_workspace: &attach_workspace + attach_workspace: + at: ~/project + +install_steps: &install_steps + steps: + - checkout + - restore_cache: + name: Restore node_modules cache + keys: + - dependency-cache-{{ .Branch }}-{{ checksum "yarn.lock" }} + - dependency-cache-{{ .Branch }}- + - dependency-cache- + - cache-{{ checksum "package.json" }} + - run: + name: Installing Dependencies + command: | + yarn install --silent + - save_cache: + name: Save node_modules cache + key: dependency-cache-{{ .Branch }}-{{ checksum "package.json" }} + paths: + - ~/.cache + - persist_to_workspace: + root: ~/project + paths: + - repo + +workflows: + version: 2 + build_pipeline: + jobs: + - build + - unit_test: + requires: + - build + - end_to_end: + requires: + - build +jobs: + build: + <<: *docker_defaults + <<: *install_steps + unit_test: + <<: *docker_defaults + steps: + - *attach_workspace + - run: + name: Running unit tests + command: | + yarn prettier:check + yarn lint + yarn type-check + yarn test:jest + yarn coveralls + end_to_end: + <<: *docker_defaults + steps: + - *attach_workspace + - run: + name: Running E2E tests + command: | + yarn global add cypress + yarn install --silent + yarn cypress install + yarn e2e diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json new file mode 100644 index 0000000000..22e243ad13 --- /dev/null +++ b/.codesandbox/ci.json @@ -0,0 +1,6 @@ +{ + "buildCommand": "build", + "packages": ["packages/*"], + "sandboxes": ["nfmxw"], + "node": "20" +} diff --git a/.coveralls.yml b/.coveralls.yml index 6c493c85ba..842b65017b 100644 --- a/.coveralls.yml +++ b/.coveralls.yml @@ -1,2 +1,2 @@ service-name: travis-ci -repo_token: itdMRdBNgDK8Gb5nIA63zVMEryaxTQxkR +repo_token: itdMRdBNgDK8Gb5nIA63zVMEryaxTQxkR diff --git a/.editorconfig b/.editorconfig index 2d16f58976..f83c0c4d6b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,16 +7,11 @@ end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true -indent_style = tab -translate_tabs_to_spaces = false - -[*.json] -indent_style = space -indent_size = 2 - -[*.yml] indent_style = space indent_size = 2 [*.md] trim_trailing_whitespace = false + +[.circleci/config.yml] +indent_size = 4 diff --git a/.eslintignore b/.eslintignore index fd87c8299d..b7d748ace5 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,7 @@ +coverage/* +cypress/plugins/* +cypress/support/* +**/dist/* lib/* -dist/* -examples/dist/* node_modules/* -bower_components/* +**/node_modules/* diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index f4253545b1..0000000000 --- a/.eslintrc +++ /dev/null @@ -1,35 +0,0 @@ -{ - "parser": "babel-eslint", - "env": { - "browser": true, - "node": true - }, - "plugins": [ - "react" - ], - "rules": { - "curly": [2, "multi-line"], - "jsx-quotes": 1, - "no-shadow": 0, - "no-trailing-spaces": 0, - "no-underscore-dangle": 0, - "no-unused-expressions": 0, - "object-curly-spacing": [1, "always"], - "quotes": [2, "single", "avoid-escape"], - "react/jsx-boolean-value": 1, - "react/jsx-no-undef": 1, - "react/jsx-sort-prop-types": 1, - "react/jsx-uses-react": 1, - "react/jsx-uses-vars": 1, - "react/no-did-mount-set-state": 1, - "react/no-did-update-set-state": 1, - "react/no-unknown-property": 1, - "react/prop-types": 1, - "react/react-in-jsx-scope": 1, - "react/self-closing-comp": 1, - "react/sort-comp": 1, - "react/wrap-multilines": 1, - "semi": 2, - "strict": 0 - } -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..aec4f80df3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,50 @@ +module.exports = { + extends: ['plugin:react-hooks/recommended', 'plugin:@typescript-eslint/base'], + parser: '@typescript-eslint/parser', + env: { + browser: true, + es6: true, + node: true, + }, + plugins: ['react', '@typescript-eslint'], + rules: { + '@typescript-eslint/no-unused-vars': [ + 'error', + { + args: 'after-used', + argsIgnorePattern: '^event$', + ignoreRestSiblings: true, + vars: 'all', + varsIgnorePattern: 'jsx|emotionJSX', + }, + ], + curly: [2, 'multi-line'], + 'jsx-quotes': 1, + 'no-shadow': 0, + '@typescript-eslint/no-shadow': 2, + 'no-trailing-spaces': 1, + 'no-underscore-dangle': 1, + '@typescript-eslint/no-unused-expressions': 1, + 'object-curly-spacing': [1, 'always'], + '@typescript-eslint/quotes': [2, 'single', 'avoid-escape'], + 'react/jsx-boolean-value': 1, + 'react/jsx-no-undef': 1, + 'react/jsx-uses-react': 1, + 'react/jsx-uses-vars': 1, + 'react/jsx-wrap-multilines': 1, + 'react/no-did-mount-set-state': 1, + 'react/no-did-update-set-state': 1, + 'react/no-unknown-property': 1, + 'react/react-in-jsx-scope': 1, + 'react/self-closing-comp': 1, + 'react/sort-prop-types': 1, + '@typescript-eslint/semi': 2, + '@typescript-eslint/no-inferrable-types': 2, + strict: 0, + }, + settings: { + react: { + version: 'detect', + }, + }, +}; diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index f3f4a7c2d7..0000000000 --- a/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -dist/* binary -examples/dist/* binary -lib/* binary diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000000..12f58f0116 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing + +Thanks for your interest in React-Select. All forms of contribution are +welcome, from issue reports to PRs and documentation / write-ups. + +Before you open a PR: + +- In development, run `yarn start` to build (+watch) the project source, and run + the [development server](http://localhost:8000). +- Please ensure all the examples work correctly after your change. If you're + adding a major new use-case, add a new example demonstrating its use. +- Be careful to follow the code style of the project. Run `yarn lint` after + your changes and ensure you do not introduce any new errors or warnings. +- This repository uses TypeScript, please run `yarn type-check` after your changes to ensure + that you do not introduce any new type errors. + +- Ensure that your effort is aligned with the project's roadmap by talking to + the maintainers, especially if you are going to spend a lot of time on it. +- Make sure there's an issue open for any work you take on and intend to submit + as a pull request - it helps core members review your concept and direction + early and is a good way to discuss what you're planning to do. +- If you open an issue and are interested in working on a fix, please let us + know. We'll help you get started, rather than adding it to the queue. +- Make sure you do not add regressions by running `yarn test`. +- Where possible, include tests with your changes, either that demonstrates the + bug, or tests the new functionality. If you're not sure how to test your + changes, feel free to ping @gwyneplaine or @JedWatson +- Run `yarn coveralls` to check that the coverage hasn't dropped, and look at the + report (under the generated `coverage` directory) to check that your changes are + covered diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..0a80e34e6f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,27 @@ +--- +name: Bug report +about: File a bug report +title: '' +labels: [issue/bug-unconfirmed] +assignees: '' +--- + +**Thanks for using react-select!** + +If you are going to ask a question or want to propose a change or a new feature, then please don't file an issue for this. +Questions and feature requests have their own place in our discussions section. + +## Are you reporting a bug or runtime error? + +Please include a test case that demonstrates the issue you're reporting! + +This is very helpful to maintainers in order to help us see the issue you're seeing. + +Please note we are currently only directing our efforts towards the current major (v5) version and beyond. + +We understand this might be inconvenient but it is in the best interest of supporting the broader community and to sustain the `react-select` project going forward. + +To report bugs against react-select v5 please fork the following code-sandbox: +https://codesandbox.io/s/react-select-v5-sandbox-y5jtm + +You may also find the [online Babel tool](https://babeljs.io/repl/) quite helpful if you wish to use ES6/ES7 syntax not yet supported by the browser you are using. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..f3cffab5d4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Feature request + url: https://github.com/JedWatson/react-select/discussions/categories/ideas + about: Got an idea for a feature or want to propose a change? Then this is the place for you. + - name: Question on usage + url: https://github.com/JedWatson/react-select/discussions/categories/q-a + about: If you have a question regarding the usage of the library. + - name: StackOverflow + url: https://stackoverflow.com/questions/tagged/react-select + about: Alternatively you can visit StackOverflow with the `[react-select]` tag diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..902ebdae29 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: 'npm' + directory: '/' + schedule: + interval: 'weekly' + ignore: + - dependency-name: '*' + update-types: + ['version-update:semver-minor', 'version-update:semver-patch'] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..65b2c9e3ba --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: Release + +on: + push: + branches: + - master + +permissions: + contents: read + +jobs: + release: + permissions: + # for changesets/action + contents: write + pull-requests: write + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + with: + # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits + fetch-depth: 0 + + - name: Setup Node.js 22.x + uses: actions/setup-node@v4 + with: + node-version: 22.x + + - name: Install Dependencies + run: yarn + + - name: Create Release Pull Request or Publish to npm + uses: changesets/action@v1 + with: + publish: yarn release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.gitignore b/.gitignore index d2dfea8f34..d44aafc2e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +# Build +lib +dist +docs/dist +.env + # Logs logs *.log @@ -10,6 +16,13 @@ pids # Coverage tools lib-cov coverage +.nyc_output + +# Cypress +cypress/videos +cypress/screenshots +cypress/support +cypress/plugins # Dependency directory node_modules @@ -18,10 +31,15 @@ bower_components # Publish directory .publish -# Editor artifacts +# Editor artefacts .idea # Other .DS_Store +.env +package-lock.json + +# Notes +.NOTES.md -yarn.lock +magical-types diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 56c959651c..0000000000 --- a/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -.editorconfig -bower.json -examples/dist diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..2bd5a0a98a --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..201bf7f3af --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +coverage/* +cypress/plugins/* +cypress/support/* +**/dist/* +lib/* +node_modules/* +**/node_modules/* +**/magical-types/* diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000000..0b8804b51d --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,10 @@ +module.exports = { + singleQuote: true, + trailingComma: 'es5', + overrides: [ + { + files: '.changeset/pre.json', + options: { parser: 'json-stringify' }, + }, + ], +}; diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8278823bda..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -sudo: false -language: node_js -node_js: - - "v4" -script: - - npm run coveralls diff --git a/CHANGES.md b/CHANGES.md deleted file mode 100644 index 451b929481..0000000000 --- a/CHANGES.md +++ /dev/null @@ -1,33 +0,0 @@ -# Changes - -## Breaking Changes - -Major API changes to Component props, SingleValue and Value have been merged - -The component is now "controlled", which means you have to pass value as a prop and always handle the `onChange` event. See https://facebook.github.io/react/docs/forms.html#controlled-components - -Using values that aren't in the `options` array is still supported, but they have to be full options (previous versions would expand strings into `{ label: string, value: string }`) - -Options & Value components get their label as their Children - -new `simpleValue` prop for when you want to deal with values as strings or numbers (legacy behaviour, defaults to false). onChange no longer receives an array of expanded values as the second argument. - -`onOptionLabelClick` -> `onValueClick` - -Multiple values are now submitted in multiple form fields, which results in an array of values in the form data. To use the old method of submitting a single string of all values joined with the delimiter option, use the `joinValues` prop. - -## New Select.Async Component - -`loadingPlaceholder` prop -`cacheAsyncResults` -> `cache` (new external cache support) - defaults to true - -## Fixes & Other Changes - -new `ignoreAccents` prop (on by default), thanks [Guilherme Guerchmann](https://github.com/Agamennon) -new `escapeClearsValue` prop (on by default) -bug where the filter wouldn't be reset after blur -complex option values are much better supported now, won't throw duplicate key errors and will serialize to the input correctly - -## Notes - -`undefined` default props are no longer declared diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6afd856a9d..e8a43d8534 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,52 +3,20 @@ Thanks for your interest in React-Select. All forms of contribution are welcome, from issue reports to PRs and documentation / write-ups. -* We use node.js v4 for development and testing. Due to incompatibilities with -JSDOM and older versions of node.js, you'll need to use node 4 to run the -tests. If you can't install node v4 as your "default" node installation, you -could try using [nvm](https://github.com/creationix/nvm) to install multiple -versions concurrently. -* If you're upgrading your node.js 0.x environment, it's sometimes necessary -to remove the node_modules directory under react-select, and run npm install -again, in order to ensure all the correct dependencies for the new version -of node.js (as a minimum, you'll need to remove the `jsdom` module, and -reinstall that). - Before you open a PR: -* If you're planning to add or change a major feature in a PR, please ensure -the change is aligned with the project roadmap by opening an issue first, -especially if you're going to spend a lot of time on it. -* In development, run `npm start` to build (+watch) the project source, and run -the [development server](http://localhost:8000). -* Please ensure all the examples work correctly after your change. If you're -adding a major new use-case, add a new example demonstrating its use. -* Please **do not** commit the build files. Make sure **only** your changes to -`/src/`, `/less/` and `/examples/src` are included in your PR. -* Be careful to follow the code style of the project. Run `npm run lint` after -your changes and ensure you do not introduce any new errors or warnings. - -* Ensure that your effort is aligned with the project's roadmap by talking to -the maintainers, especially if you are going to spend a lot of time on it. -* Make sure there's an issue open for any work you take on and intend to submit -as a pull request - it helps core members review your concept and direction -early and is a good way to discuss what you're planning to do. -* If you open an issue and are interested in working on a fix, please let us -know. We'll help you get started, rather than adding it to the queue. -* Make sure you do not add regressions by running `npm test`. -* Where possible, include tests with your changes, either that demonstrates the -bug, or tests the new functionality. If you're not sure how to test your -changes, feel free to ping @bruderstein -* Run `npm run cover` to check that the coverage hasn't dropped, and look at the -report (under the generated `coverage` directory) to check that your changes are -covered -* Please [follow our established coding conventions](https://github.com/keystonejs/keystone/wiki/Coding-Standards) -(with regards to formatting, etc) -* You can also run `npm run lint` and `npm run style` - our linter is a WIP -but please ensure there are not more violations than before your changes. -* All new features and changes need documentation. We have three translations, -please read our [Documentation Guidelines](https://github.com/keystonejs/keystone/wiki/Documentation-Translation-Guidelines). - -* _Make sure you revert your build before submitting a PR_ to reduce the chance -of conflicts. `gulp build-scripts` is run after PRs are merged and before any -releases are made. +- In development, run `yarn start` to build (and watch) the project source, and run + the [development server](http://localhost:8000). +- Please ensure all the examples work correctly after your change. If you're + adding a major new use-case, add a new example `/docs/examples` and subsequent documentation demonstrating its use `/docs/pages`. +- Ensure that your effort is aligned with the project's roadmap by talking to + the maintainers, especially if you are going to spend a lot of time on it. +- Make sure there's an issue open for any work you take on and intend to submit + as a pull request - it helps core members review your concept and direction + early and is a good way to discuss what you're planning to do. +- If you open an issue and are interested in working on a fix, please let us + know. We'll help you get started, rather than inadvertently doubling up on your hard work. +- Make sure you do not add regressions by running `yarn test`. +- Where possible, include tests with your changes, either that demonstrates the + bug, or tests the new functionality. +- All new features and changes need documentation. diff --git a/HISTORY.md b/HISTORY.md deleted file mode 100644 index 5862bb2f37..0000000000 --- a/HISTORY.md +++ /dev/null @@ -1,539 +0,0 @@ -# React-Select - -## v1.0.0-rc.3 / 2017-02-01 - -* added; `arrowRenderer` prop, thanks [Brian Vaughn](https://github.com/bvaughn) -* added; child-function support to `Async` and `Creatable` components so that they can compose each other (or future HOCs), thanks [Brian Vaughn](https://github.com/bvaughn) -* added; `asyncCreatable` HOC that combines `Async` and `Creatable` so they can be used together, thanks [Brian Vaughn](https://github.com/bvaughn) -* added; undocumented arguments for `menuRenderer`, thanks [Julian Krispel-Samsel](https://github.com/juliankrispel) -* fixed; Do not focus and open menu when disabled, thanks [nhducit](https://github.com/nhducit) -* fixed; Scrolling with arrow-keys is not working correctly, thanks [Damian Pieczynski](https://github.com/piecyk) -* added; "select all text" functionality `Shift+Home|Del`, thanks [Damian Pieczynski](https://github.com/piecyk) -* added; support for `boolean` values, thanks [Aaron Hardy](https://github.com/Aaronius) -* fixed; Remove duplicated `promptTextCreator` field from readme, thanks [Jih-Chi Lee](https://github.com/jihchi) -* fixed; Adding back ref that was removed in rc2, thanks [Martin Jujou](https://github.com/jooj123) -* fixed; `Creatable` component doesn't allow input key down handling, thanks [Ivan Leonenko](https://github.com/IvanLeonenko) -* added; Allow react nodes to be passed as loadingPlaceholder, thanks [Daniel Heath](https://github.com/DanielHeath) -* fixed; IE8 compatibility issues, thanks [Kirill Mesnyankin](https://github.com/strayiker) -* improved; Allow users to specify noResultsText, thanks [Daniel Heath](https://github.com/DanielHeath) -* added; Only remove options if a loading placeholder is available, thanks [Daniel Heath](https://github.com/DanielHeath) -* fixed; firefox display items in two rows due to reflow, thanks [Daniel Heath](https://github.com/DanielHeath) -* fixed; `Creatable` readme typo, thanks [Ben](https://github.com/rockingskier) -* fixed; explain way to implement `allowCreate` functionality with `Creatable` to readme, thanks [mayerwin](https://github.com/mayerwin) -* added; delete key removes an item when there is no input, thanks [forum-is](https://github.com/forum-is) -* added; `onNewOptionClick` handler for `Creatable`, thanks [Lee Siong Chan](https://github.com/leesiongchan) -* fixed; `onInputChange` consistent for `Creatable`, thanks [Lee Siong Chan](https://github.com/leesiongchan) -* fixed; `menuRenderer` is treated consistently between `Creatable` and `Select`, thanks [Brian Vaughn](https://github.com/bvaughn) -* fixed; `asyncCreatable` options parsing will not parse undefined values into props, thanks [Romain Dardour](https://github.com/unity) -* added; pass `inputProps` to `inputRenderer`, thanks [Alec Winograd](https://github.com/awinograd) -* fixed; no exception when clearing an Async field that is not set to multi, thanks [Patrik Stutz](https://github.com/VanCoding) -* added; allow rendering a custom clear component, thanks [Conor Hastings](https://github.com/conorhastings) -* fixed; document `ignoreAccents`, thanks [Domenico Matteo](https://github.com/dmatteo) -* fixed; arrowing up or down in `Select` with 0 options does not throw type error, thanks [Alex Howard](https://github.com/thezanke) -* fixed; `Creatable` handles null children prop, thanks [Jack Coulter](https://github.com/jscinoz) -* added; provide `isOpen` to arrowRenderer, thanks [Kuan](https://github.com/khankuan) -* fixed; re-added the `focus()` method on `Select.Async`, thanks, [Maarten Claes](https://github.com/mcls) -* fixed; focus the next available option after a selection, not the top option, thanks [Nicolas Raynaud](https://github.com/nraynaud) - -Note there has also been a breaking change to the props for the `Async` component: both `minimumInput` and `searchingText` have been removed. See #1226 for more details. Apologies for doing this in an RC release, but we had to trade off between resolving some important bugs and breaking the API, and figured it was better to do this before declaring 1.0.0 stable. - - -## v1.0.0-rc.1 / 2016-09-04 - -* fixed; reset value to `[]` when `multi=true`, thanks [Michael Williamson](https://github.com/mwilliamson) -* added; pass index to `renderLabel` method, thanks [nhducit](https://github.com/nhducit) -* fixed; uncontrolled to controlled component warning in React 15.3 -* fixed; props cleanup, thanks [Forbes Lindesay](https://github.com/ForbesLindesay) -* fixed; issue where a value of the number `0` would be assumed to be no value, thanks [Hanwen Cheng](https://github.com/hanwencheng) -* fixed; internal refs converted to callbacks instead of strings, thanks [Johnny Nguyen](https://github.com/gojohnnygo) -* added; optional `instanceId` prop for server-side rendering, thanks [Jevin Anderson](https://github.com/JevinAnderson) -* added; `onCloseResetsInput` prop, thanks [Frankie](https://github.com/frankievx) -* added; `Creatable` component, replaces pre-1.0 `allowCreate` prop, thanks [Brian Vaughn](https://github.com/bvaughn) - -## v1.0.0-beta14 / 2016-07-17 - -* fixed; `react-input-autosize` has been udpated to `1.1.0`, which includes fixes for the new warnings that React 15.2 logs -* fixed; "Unknown prop `inputClassName` on <div> tag" warning, thanks [Max Stoiber](https://github.com/mxstbr) -* fixed; Removed unnecessary `onUnfocus`, thanks [Johnny Nguyen](https://github.com/gojohnnygo) -* added; Support for react components in `searchPromptText`, thanks [Matt](https://github.com/hellaeon) -* fixed; focus bug on iOS, thanks [Tony deCatanzaro](https://github.com/tonydecat) -* fixed; Async bugs with Promises, thanks [Vladimir](https://github.com/VladimirPal) and [Ian Firkin](https://github.com/lobsteropteryx) -* fixed; `searchingText` bug, thanks [Tony deCatanzaro](https://github.com/tonydecat) -* improved; More antive-like input behaviour, thanks [Johnny Nguyen](https://github.com/gojohnnygo) -* fixed; Added missing unit (px) to `minWidth` attribute, thanks [Ian Witherow](https://github.com/ianwitherow) -* added; Support for assistive technologies, thanks [Dave Brotherstone](https://github.com/bruderstein) -* fixed; React error if `onChange` callback causes a root component to unmount, thanks [Nathan Norton](https://github.com/Xesued) -* fixed; Open menu is now closed if `disabled` becomes true, thanks [Jason Moon](https://github.com/jsnmoon) -* fixed; Prevent `getFocusableOptionIndex` from returning a disabled option, thanks [Brian Powers](https://github.com/brianspowers) -* added; Home, End, Page Up/Down support, thanks [Jason Kadrmas](https://github.com/blackjk3) -* fixed; Don't render `backspaceToRemoveMessage` if `backspaceRemoves` is set to false, thanks [Ryan Zec](https://github.com/ryanzec) -* fixed; Issue with an outline appearing on the auto sized input, thanks [Ryan Zec](https://github.com/ryanzec) -* fixed; Events don't propagate when `esc` is pressed, thanks [Yoshihide Jimbo](https://github.com/jmblog) -* fixed; Update `required` prop based on nextProps on update, thanks [Matt Shwery](https://github.com/mshwery) -* fixed; On focus check whether input ref is a real input or an input component, thanks [Peter Brant](https://github.com/pbrant) and [Greg Poole](https://github.com/gpoole) - -Also a big thanks to [Brian Vaughn](https://github.com/bvaughn) for his help triaging issues for this release! - -## v1.0.0-beta13 / 2016-05-30 - -* added; `inputRenderer` prop, allows you to override the input component, thanks [Sean Burke](https://github.com/leftmostcat) -* added; `openOnFocus` prop, causes the menu to always open when the select control is focused, thanks [HuysentruytRuben](https://github.com/HuysentruytRuben) -* added; `react-virtualised-select` HOC example, thanks [Brian Vaughn](https://github.com/bvaughn) -* added; `tabSelectsValue` prop can be set to false to prevent selection of focused option when tab is pressed, thanks [Byron Anderson](https://github.com/byronanderson) -* added; ability to override `resetValue` when clearing the control, thanks [Alexander Luberg](https://github.com/LubergAlexander) -* added; input can be updated with `onInputChange`, thanks [Brett DeWoody](https://github.com/brettdewoody) -* added; Styles for .is-selected class, thanks [Danny Herran](https://github.com/dherran) -* fixed; `noResultsText` prop type is now `stringOrNode` for Async component, thanks [Michael Groeneman](https://github.com/mgroeneman) -* fixed; `onInputChange` is wrapped by Async component, thanks [Eric O'Connell](https://github.com/drd) -* fixed; `scrollMenuIntoView` behaviour in IE10, thanks [Ivan Jager](https://github.com/aij) -* fixed; isEqualNode replaced with strict equality check, thanks [Alexandre Balhier](https://github.com/abalhier) -* fixed; issue with value object not being passed to `handleRequired`, thanks [Andrew Hite](https://github.com/andyhite) -* fixed; the menu-outer container is no longer rendered when it does not contain anything, thanks [Kuan](https://github.com/khankuan) -* improved; better support for IE8 in styles, thanks [Rockallite Wulf](https://github.com/rockallite) - -## v1.0.0-beta12 / 2016-04-02 - -* added; `menuRenderer` method and example for effeciently rendering thousands of options, thanks [Brian Vaughn](https://github.com/bvaughn) -* added; `optionClassName` prop, thanks [Max Tyler](https://github.com/iam4x) - -## v1.0.0-beta11 / 2016-03-09 - -* updated dependencies to allow use with React 15.x -* changed; multiple selected values are now submitted using multiple inputs, thanks [Trinh Hoang Nhu](https://github.com/james4388) -* added; `joinValues` prop to revert the above change and submit multiple values in a single field with the delimiter - -## v1.0.0-beta10 / 2016-02-23 - -* fixed build issues with v1.0.0-beta9 - -## v1.0.0-beta9 / 2016-02-12 - -* added; onBlurResetsInput prop, thanks [Sly Bridges](https://github.com/slybridges) -* changed; Enter selects and retains focus, Tab selects and shifts focus, thanks [RDX](https://github.com/rdsubhas) -* fixed; Hide noResultsText when value is falsy, thanks [Fernando Alex Helwanger](https://github.com/fhelwanger) -* added; `required` prop, adds HTML5 required attribute, thanks [Domenico Matteo](https://github.com/dmatteo) -* fixed; Touch drag behaviour, thanks [Pavel Tarnopolsky](https://github.com/Paveltarno) -* added; `onOpen` and `onClose` event props, thanks [Jacob Page](https://github.com/DullReferenceException) -* fixed; Pressing Enter on open Select should stop propagation, thanks [Jeremy Liberman](https://github.com/MrLeebo) -* fixed; Missing handleMouseDownOnMenu, thanks [Jeremy Liberman](https://github.com/MrLeebo) -* added; Ensures the selected option is immediately visible when the menu is open, thanks [Martin Jujou](https://github.com/jooj123) -* added; `autoBlur` prop, blurs the input when a value is selected, thanks [Pavel Tarnopolsky](https://github.com/Paveltarno) -* fixed; Several isFocused checks weren't working properly - -## v1.0.0-beta8 / 2015-12-20 - -* fixed; input focus bug when toggling `disabled` prop, thanks [Davide Curletti](https://github.com/dcurletti) -* fixed; `focus()` is now exposed on the `Async` component, thanks [AugustinLF](https://github.com/AugustinLF) - -## v1.0.0-beta7 / 2015-12-15 - -* You can now use React elements for placeholders and the text props, thanks [kromit](https://github.com/kromit) and [Alyssa Biasi](https://github.com/alyssaBiasi) -* Fixed a problem where the border doesn't show when the element is inside a table, thanks [Rodrigo Boratto](https://github.com/rwrz) -* New prop `scrollMenuIntoView` scrolls the viewport to display the menu, thanks [Alexander Zaharakis](https://github.com/azaharakis) -* New LESS / SCSS variable `select-option-bg` lets you control the menu option background color, thanks [Evan Goldenberg](https://github.com/Naveg) -* Fixed an error in the blur handler on IE when the menu is not visible, thanks [Gaston Sanchez](https://github.com/gaastonsr) -* Added support for a `clearableValue` option property in `multi` mode, thanks [Sly Bridges](https://github.com/slybridges) - -## v1.0.0-beta6 / 2015-11-29 - -* Test suite complete and passing, with a couple of minor fixes thanks to @bruderstein - -## v1.0.0-beta5 / 2015-11-08 - -* Fixes issues relating to serializing simple values into the hidden field - -## v1.0.0-beta4 / 2015-11-08 - -* New default styles that match [Elemental UI](http://elemental-ui.com) and look right at home in the new [KeystoneJS Admin UI](http://keystonejs.com) - -We're potentially going to ship some theme stylesheets in the future, shout out on GitHub if this interests you. - -## v1.0.0-beta3 / 2015-11-08 - -* The selected value populated in the hidden field has been fixed (was `"[object Object]"` before) -* Added new `autofocus` prop -* Fixed duplicate key error for options and values with duplicate `value` properties -* SCSS variables now have `!default` so you can override them - -## v1.0.0-beta2 / 2015-11-06 - -Changed since beta 1: - -* Async options cache works again -* New style props for custom styling the component without modifying css classes: `style` `wrapperStyle` `menuStyle` `menuContainerStyle` -* The menu opens and closes correctly when `searchable={false}`, there is still some work to do on this use-case - -## v1.0.0-beta1 / 2015-11-06 - -This is a complete rewrite. Major changes include: - -* Everything is simpler (I'm nearly done and the source code is only 60% of the size of the last version) -* No more timeouts or weird handlers, the restructuring has let me make everything more straight-forward -* The options array is no longer preprocessed into state, just retrieved from props -* The values array is now initialised in the Options array during render, and not stored in state, which along with the change to options makes the component more reliable and fixes issues with props not updating correctly -* The component no longer stores its own value in state (ever) - it needs to be passed as a prop and handled with `onChange`. -* Complex values are now enabled by default (so you're passed the option object, not its value); you can enable the legacy mode with a prop -* The Value and Option components have been cleaned up as well for consistency -* The hidden `<input>` field is now optional and the component is better suited to use in a rich React.js app than it was -* You can disable options filtering to do the filtering externally with `onInputChange` -* Accents on characters can now be ignored -* The `asyncOptions` prop has been replaced by a new wrapper component: `Select.Async` - -Note that "Tag mode" (creating options on the fly) isn't reimplemented yet. - -A full guide to the breaking changes and new features will be written up soon. In the meantime please see the new examples. - -## v0.9.1 / 2015-11-01 - -* added; new Contributors example w/ async options loading and custom value / label keys -* fixed; several issues with custom `valueKey` and `labelKey` props -* fixed; autoload now loads options with no search input - -## v0.9.0 / 2015-10-29 - -* added; SCSS stylesheets! -* improved; Options rendering should be more performant -* breaking change; Custom `Option` components now need to pass their `option` prop to event handlers; see [this commit](https://github.com/JedWatson/react-select/commit/89af12a80a972794222b193a767f44234bbe9817) for an example of the required change. - -## v0.8.4 / 2015-10-27 - -* fixed; LESS math operations now work with --strict-math=on, thanks [Vincent Fretin](https://github.com/vincentfretin) - -## v0.8.3 / 2015-10-27 - -* fixed; IE issue where clicking the scrollbar would close the menu, thanks [Pete Nykänen](https://github.com/petetnt) - -## v0.8.2 / 2015-10-22 - -* added; Promise support for `loadAsyncOptions`, thanks [Domenico Matteo](https://github.com/dmatteo) - -## v0.8.1 / 2015-10-20 - -* fixed; `loadAsyncOptions` raises TypeError in setup, see #439 for details, thanks [Pancham Mehrunkar](https://github.com/pancham348) - -## v0.8.0 / 2015-10-19 - -This release contains significant DOM structure and CSS improvements by @jossmac, including: - -* no more `position: absolute` for inner controls -* `display: table` is used for layout, which works in IE8 and above, and [all other modern browsers](http://caniuse.com/#feat=css-table) -* less "magic numbers" used for layout, should fix various browser-specific alignment issues -* clear "x" control now animates in -* clearer `.Select--multi` className replaces `.Select.is-multi` -* new height & theme variables -* "dropdown" indicator chevron is no longer displayed for multi-select controls - -There are no functional changes, but if you've forked the LESS / CSS to create your own theme you'll want to pay close attention to PR #527 when upgrading to this version. - -## v0.7.0 / 2015-10-10 - -React Select is updated for React 0.14. If you're still using React 0.13, please continue to use `react-select@0.6.x`. There are no functional differences between v0.7.0 and v0.6.12. - -Additionally, our tests now require Node.js 4.x. If you are developing `react-select`, please make sure you are running the latest version of node. - -Thanks to @bruderstein, @dmatteo and @hull for their help getting these updates shipped! - -## v0.6.12 / 2015-10-02 - -* added; `labelKey` and `valueKey` props, so you can now use different keys in `option` objects for the label and value -* fixed; additional `isMounted()` checks in timeouts -* fixed; componentDidUpdate timeout is reset correctly, see #208 and #434, thanks [Petr Gladkikh](https://github.com/PetrGlad) -* fixed; mousedown event on scrollbar in menu no longer hides it, thanks [Yishai Burt](https://github.com/burtyish) - -## v0.6.11 / 2015-09-28 - -* added; `isLoading` prop, allows indication of async options loading in situations where more control is required, thanks [Jon Gautsch](https://github.com/jgautsch) - -## v0.6.10 / 2015-09-24 - -* fixed; a build issue with the previous release that prevented the stylesheet being generated / included -* fixed; a LESS syntax issue, thanks [Bob Cardenas](https://github.com/bcardi) - -## v0.6.9 / 2015-09-19 - -* added; `style` key for package.json, thanks [Stephen Wan](https://github.com/stephen) -* added; `onInputChange` handler that returns the current input value, thanks [Tom Leslie](https://github.com/lomteslie) -* fixed; simplifying handleKey function & preventDefault behaviour, thanks [davidpene](https://github.com/davidpene) -* fixed; Display spinner while auto-loading initial data, thanks [Ben Jenkinson](https://github.com/BenJenkinson) -* fixed; better support for touch events, thanks [Montlouis-Calixte Stéphane](https://github.com/bulby97) -* fixed; prevent value splitting on non-multi-value select, thanks [Alan R. Soares](https://github.com/alanrsoares) - -## v0.6.8 / 2015-09-16 - -* fixed; broader range of allowed prereleases for React 0.14, including rc1 -* fixed; preventing backspace from navigating back in the browser history, thanks [davidpene](https://github.com/davidpene) - -## v0.6.7 / 2015-08-28 - -* fixed; missing styles for `.Select-search-prompt` and `.Select-searching` issues, thanks [Jaak Erisalu](https://github.com/jaakerisalu) and [davidpene](https://github.com/davidpene) - -## v0.6.6 / 2015-08-26 - -* fixed; issue in Chrome where clicking the scrollbar would close the menu, thanks [Vladimir Matsola](https://github.com/vomchik) - -## v0.6.5 / 2015-08-24 - -* fixed; completely ignores clicks on disabled items, unless the target of the click is a link, thanks [Ben Stahl](https://github.com/bhstahl) - -## v0.6.4 / 2015-08-24 - -This release includes a huge improvement to the examples / website thanks to @jossmac. Also: - -* added; support for React 0.14 beta3 -* fixed; disabled options after searching, thanks @bruderstein -* added; support for "Searching..." text (w/ prop) while loading async results, thanks @bruderstein and @johnomalley -* added; `className`, `style` and `title` keys are now supported in option properties, thanks @bruderstein - -## v0.6.3 / 2015-08-18 - -Otherwise known as "the real 0.6.2" this includes the updated build for the last version; sorry about that! - -## v0.6.2 / 2015-08-13 - -* changed; if the `searchable` prop is `false`, the menu is opened _or closed_ on click, more like a standard Select input. thanks [MaaikeB](https://github.com/MaaikeB) - -## v0.6.1 / 2015-08-09 - -* added; Support for options with numeric values, thanks [Dave Brotherstone](https://github.com/bruderstein) -* changed; Disabled options now appear in the search results
, thanks [Dave Brotherstone](https://github.com/bruderstein) -* fixed; asyncOptions are reloaded on componentWillReceiveProps when the value has changed, thanks [Francis Cote](https://github.com/drfeelgoud) -* added; `cacheAsyncResults` prop (default `true`) now controls whether the internal cache is used for `asyncOptions` - -## v0.6.0 / 2015-08-05 - -* improved; option, value and single value have been split out into their own components, and can be customised with props. see [#328](https://github.com/JedWatson/react-select/pull/328) for more details. -* improved; Near-complete test coverage thanks to the awesome work of [Dave Brotherstone](https://github.com/bruderstein) -* improved; Support all alpha/beta/rc's of React 0.14.0, thanks [Sébastien Lorber](https://github.com/slorber) -* fixed; Close multi-select menu when tabbing away, thanks [Ben Alpert](https://github.com/spicyj) -* fixed; Bug where Select shows the value instead of the label (reapplying fix) -* fixed; `valueRenderer` now works when `multi={false}`, thanks [Chris Portela](https://github.com/0xCMP) -* added; New property `backspaceRemoves` (default `true`), allows the default behaviour of removing values with backspace when `multi={true}`, thanks [Leo Lehikoinen](https://github.com/lehikol2) - -## v0.5.6 / 2015-07-27 - -* fixed; Allow entering of commas when allowCreate is on but multi is off, thanks [Angelo DiNardi](https://github.com/adinardi) -* fixed; Times (clear) character is now rendered from string unicode character for consistent output, thanks [Nibbles](https://github.com/Siliconrob) -* fixed; allowCreate bug, thanks [goodzsq](https://github.com/goodzsq) -* fixed; changes to props.placeholder weren't being reflected correctly, thanks [alesn](https://github.com/alesn) -* fixed; error when escape is pressedn where `clearValue` was not passed the event, thanks [Mikhail Kotelnikov](https://github.com/mkotelnikov) -* added; More tests, thanks [Dave Brotherstone](https://github.com/bruderstein) - -## v0.5.5 / 2015-07-12 - -* fixed; replaced usage of `component.getDOMNode()` with `React.findDOMNode(component)` for compatibility with React 0.14 - -## v0.5.4 / 2015-07-06 - -* fixed; regression in 0.5.3 that broke componentWillMount, sorry everyone! -* added; `addLabelText` prop for customising the "add {label}?" text when in tags mode, thanks [Fenn](https://github.com/Fenntasy) - -## v0.5.3 / 2015-07-05 - -* fixed; autoload issues, thanks [Maxime Tyler](https://github.com/iam4x) -* fixed; style incompatibilities with Foundation framework, thanks [Timothy Kempf](https://github.com/Fauntleroy) - -## v0.5.2 / 2015-06-28 - -* fixed; bug where Select shows the value instead of the label, thanks [Stephen Demjanenko](https://github.com/sdemjanenko) -* added; 'is-selected' classname is added to the selected option, thanks [Alexey Volodkin](https://github.com/miraks) -* fixed; async options are now loaded with the initial value, thanks [Pokai Chang](https://github.com/Neson) -* fixed; `react-input-autosize` now correctly escapes ampersands (&), not actually a fix in react-select but worth noting here because it would have been causing a problem in `react-select` as well. - -## v0.5.1 / 2015-06-21 - -* added; custom option and value rendering capability, thanks [Brian Reavis](https://github.com/brianreavis) -* fixed; collapsing issue when single-select or empty multi-select fields are disabled -* fixed; issue where an empty value would be left after clearing all values in a multi-select field - -## v0.5.0 / 2015-06-20 - -* fixed; `esc` key incorrectly created empty options, thanks [rgrzelak](https://github.com/rgrzelak) -* adeed; New feature to allow option creation ("tags mode"), enable with `allowCreate` prop, thanks [Florent Vilmart](https://github.com/flovilmart) and [Brian Reavis](https://github.com/brianreavis) -* fixed; IE8 compatibility fallback for `addEventListener/removeEventListener`, which don't exist in IE8, thanks [Stefan Billiet](https://github.com/StefanBilliet) -* fixed; Undefined values when using asyncOptions, thanks [bannaN](https://github.com/bannaN) -* fixed; Prevent add the last focused value when the drop down menu is closed / Pushing enter without dropdown open adds a value, thanks [Giuseppe](https://github.com/giuse88) -* fixed; Callback context is undefined, thanks [Giuseppe](https://github.com/giuse88) -* fixed; Issue with event being swallowed on Enter `keydown`, thanks [Kevin Burke](https://github.com/kembuco) -* added; Support for case-insensitive filtering when `matchPos="start"`, thanks [wesrage](https://github.com/wesrage) -* added; Support for customizable background color, thanks [John Morales](https://github.com/JohnMorales) -* fixed; Updated ESLint and cleared up warnings, thanks [Alexander Shemetovsky](https://github.com/AlexKVal) -* fixed; Close dropdown when clicking on select, thanks [Nik Butenko](https://github.com/nkbt) -* added; Tests, and mocha test framework, thanks [Craig Dallimore](https://github.com/craigdallimore) -* fixed; You can now start the example server and watch for changes with `npm start` - - -## v0.4.9 / 2015-05-11 - -* fixed; focus was being grabbed by the select when `autoload` and `asyncOptions` were set -* added; `focus` method on the component -* added; support for disabled options, thanks [Pasha Palangpour](https://github.com/pashap) -* improved; more closures, less binds, for better performance, thanks [Daniel Cousens](https://github.com/dcousens) - -## v0.4.8 / 2015-05-02 - -* fixed; restored `dist/default.css` -* fixed; standalone example works again -* fixed; clarified dependency documentation and added dependencies for Bower -* fixed; Scoping issues in `_bindCloseMenuIfClickedOutside`, thanks [bannaN](https://github.com/bannaN) -* fixed; Doesnt try to set focus afterupdate if component is disabled, thanks [bannaN](https://github.com/bannaN) - -## v0.4.7 / 2015-04-21 - -* improved; lodash is no longer a dependency, thanks [Daniel Lo Nigro](https://github.com/Daniel15) - -## v0.4.6 / 2015-04-06 - -* updated; dependencies, build process and input-autosize component - -## v0.4.5 / 2015-03-28 - -* fixed; issue with long options overlapping arrow and clear icons, thanks [Rohit Kalkur](https://github.com/rovolution) - -## v0.4.4 / 2015-03-26 - -* fixed; error handling click events when the menu is closed, thanks [Ilya Petrov](https://github.com/muromec) -* fixed; issue where options will not be filtered in certain conditions, thanks [G. Kay Lee](https://github.com/gsklee) - -## v0.4.3 / 2015-03-25 - -* added tests and updated dependencies - -## v0.4.2 / 2015-03-23 - -* added; ESLint and contributing guide -* fixed; incorrect `classnames` variable assignment in window scope -* fixed; all ESLint errors and warnings (except invalid JSX undefined/unused vars due to ESLint bug) -* fixed; first option is now focused correctly, thanks [Eivind Siqveland Larsen](https://github.com/esiqveland) - -## v0.4.1 / 2015-03-20 - -* fixed; IE11 issue: clicking on scrollbar within menu no longer closes menu, thanks [Rohit Kalkur](https://github.com/rovolution) - -## v0.4.0 / 2015-03-12 - -* updated; compatible with React 0.13 - -## v0.3.5 / 2015-03-09 - -* improved; less/no repaint on scroll for performance wins, thanks [jsmunich](https://github.com/jsmunich) -* added; `onBlur` and `onFocus` event handlers, thanks [Jonas Budelmann](https://github.com/cloudkite) -* added; support for `inputProps` prop, passed to the `<input>` component, thanks [Yann Plantevin](https://github.com/YannPl) -* changed; now using [react-component-gulp-tasks](https://github.com/JedWatson/react-component-gulp-tasks) for build -* fixed; issue w/ remote callbacks overriding cached options, thanks [Corey McMahon](https://github.com/coreymcmahon) -* fixed; if not `this.props.multi`, menu doesn't need handleMouseDown, thanks [wenbing](https://github.com/wenbing) - -## v0.3.4 / 2015-02-23 - -* fixed; issues with the underscore/lodash dependency change, thanks [Aaron Powell](https://github.com/aaronpowell) - -## v0.3.3 / 2015-02-22 - -* added; `disabled` prop, thanks [Danny Shaw](https://github.com/dannyshaw) -* added; `searchable` prop - set to `false` to disable the search box, thanks [Julen Ruiz Aizpuru](https://github.com/julen) -* added; `onOptionLabelClick` prop - see [#66](https://github.com/JedWatson/react-select/pull/66) for docs, thanks [Dmitry Smirnov](https://github.com/dmitry-smirnov) -* fixed; `text-overflow: ellipsis;` typo, thanks [Andru Vallance](https://github.com/andru) - -## v0.3.2 / 2015-01-30 - -* fixed; issue adding undefined values to multiselect, thanks [Tejas Dinkar](https://github.com/gja) - -## v0.3.1 / 2015-01-20 - -* fixed; missing `var` statement - -## v0.3.0 / 2015-01-20 - -* added; node compatible build now available in `/lib` - -## v0.2.14 / 2015-01-07 - -* added; `searchPromptText` property that is displayed when `asyncOptions` is set and there are (a) no options loaded, and (b) no input entered to search on, thanks [Anton Fedchenko](https://github.com/kompot) -* added; `clearable` property (defaults to `true`) to control whether the "clear" control is available, thanks [Anton Fedchenko](https://github.com/kompot) - -## v0.2.13 / 2015-01-05 - -* fixed; height issues in Safari, thanks [Joss Mackison](https://github.com/jossmac) -* added; Option to specify "Clear value" label as prop for i18n - -## v0.2.12 / 2015-01-04 - -* fixed; UI now responds to touch events, and works on mobile devices! thanks [Fraser Xu](https://github.com/fraserxu) - -## v0.2.11 / 2015-01-04 - -* fixed; Options in the dropdown now scroll into view when they are focused, thanks [Adam](https://github.com/fmovlex) -* improved; Example dist is now excluded from the npm package - -## v0.2.10 / 2015-01-01 - -* fixed; More specific mixin name to avoid conflicts (css) -* fixed; Example CSS now correctly rebuilds on changes in development -* fixed; Values are now expanded correctly when options change (see #28) -* added; Option to specify "No results found" label as prop for i18n, thanks [Julen Ruiz Aizpuru](https://github.com/julen) - -## v0.2.9 / 2014-12-09 - -* added; `filterOption` and `filterOptions` props for more control over filtering - -## v0.2.8 / 2014-12-08 - -* added; `matchPos` option to control whether to match the `start` or `any` position in the string when filtering options (default: `any`) -* added; `matchProp` option to control whether to match the `value`, `label` or `any` property of each option when filtering (default: `any`) - -## v0.2.7 / 2014-12-01 - -* fixed; screen-readers will now read "clear value" instead of "times" for the clear button -* fixed; non-left-click mousedown events aren't blocked by the control - - -## v0.2.6 / 2014-11-30 - -* improved; better comparison of changes to [options] in `willReceiveProps` -* fixed; now focuses the first option correctly when in multiselect mode -* fixed; fixed focused option behaviour on value change -* fixed; when filtering, there is always a focused option (#19) -* changed; using ^ in package.json to compare dependencies - -## v0.2.5 / 2014-11-20 - -* fixed; compatibility with case-sensitive file systems - -## v0.2.4 / 2014-11-20 - -* fixed; package.json pointed at the right file - -## v0.2.3 / 2014-11-17 - -* fixed; Updating state correctly when props change -* improved; Build tasks and docs -* added; Working standalone build -* added; Minified dist version -* added; Publised to Bower - -## v0.2.2 / 2014-11-15 - -* fixed; backspace event being incorrectly cancelled - -## v0.2.1 / 2014-11-15 - -* fixed; issue where backspace incorrectly clears the value (#14) - -## v0.2.0 / 2014-11-15 - -* changed; Major rewrite to improve focus handling and internal state management -* added; Support for `multi` prop, enable multiselect mode - -## v0.1.1 / 2014-11-03 - -* added; Support for `onChange` event -* added; `propTypes` are defined by the `Select` component now -* added; `className` property, sets the `className` on the outer `div` element -* fixed; Removed deprecated `React.DOM.x` calls - -## v0.1.0 / 2014-11-01 - -* updated; React to 0.12.0 - -## v0.0.6 / 2014-10-14 - -* fixed; Error keeping value when using Async Options diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index b7451a6bd3..0000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,9 +0,0 @@ -### Thanks for using react-select! - -If you are reporting an error please include a test case that demonstrates the issue you're reporting! -This is very helpful to maintainers in order to help us see the issue you're seeing. - -Here is a Plunker you can fork that has react-select loaded and supports JSX syntax: -https://plnkr.co/edit/HTmtER9AMNcPoWhXV707?p=preview - -You may also find the [online Babel tool](https://babeljs.io/repl/) quite helpful if you wish to use ES6/ES7 syntax not yet supported by the browser you are using. diff --git a/LICENSE b/LICENSE index e6620b5895..841ac571fa 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 Jed Watson +Copyright (c) 2022 Jed Watson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 5a0202284b..99367b05d5 100644 --- a/README.md +++ b/README.md @@ -1,424 +1,134 @@ [![NPM](https://img.shields.io/npm/v/react-select.svg)](https://www.npmjs.com/package/react-select) -[![Build Status](https://travis-ci.org/JedWatson/react-select.svg?branch=master)](https://travis-ci.org/JedWatson/react-select) +[![CircleCI](https://circleci.com/gh/JedWatson/react-select/tree/master.svg?style=shield)](https://circleci.com/gh/JedWatson/react-select/tree/master) [![Coverage Status](https://coveralls.io/repos/JedWatson/react-select/badge.svg?branch=master&service=github)](https://coveralls.io/github/JedWatson/react-select?branch=master) [![Supported by Thinkmill](https://thinkmill.github.io/badge/heart.svg)](http://thinkmill.com.au/?utm_source=github&utm_medium=badge&utm_campaign=react-select) -[![CDNJS](https://img.shields.io/cdnjs/v/react-select.svg)](https://cdnjs.com/libraries/react-select) -React-Select -============ +# React-Select -A Select control built with and for [React](http://facebook.github.io/react/index.html). Initially built for use in [KeystoneJS](http://www.keystonejs.com). +The Select control for [React](https://reactjs.org). Initially built for use in [KeystoneJS](https://www.keystonejs.com). +See [react-select.com](https://www.react-select.com) for live demos and comprehensive docs. -## New version 1.0.0-rc +`react-select` is funded by [Thinkmill](https://www.thinkmill.com.au) and [Atlassian](https://atlaskit.atlassian.com). +We are an open source project that is continuously supported by the community. -I've nearly completed a major rewrite of this component (see issue [#568](https://github.com/JedWatson/react-select/issues/568) for details and progress). The new code has been merged into `master`, and `react-select@1.0.0-rc` has been published to npm and bower. +React Select helps you develop powerful select components that _just work_ out of the box, without stopping you from customising the parts that are important to you. -1.0.0 has some breaking changes. The documentation is still being updated for the new API; notes on the changes can be found in [CHANGES.md](https://github.com/JedWatson/react-select/blob/master/CHANGES.md) and will be finalised into [HISTORY.md](https://github.com/JedWatson/react-select/blob/master/HISTORY.md) soon. +For the story behind this component, watch Jed's talk at React Conf 2019 - [building React Select](https://youtu.be/yS0jUnmBujE) -Testing, feedback and PRs for the new version are appreciated. +Features include: +- Flexible approach to data, with customisable functions +- Extensible styling API with [emotion](https://emotion.sh) +- Component Injection API for complete control over the UI behaviour +- Controllable state props and modular architecture +- Long-requested features like option groups, portal support, animation, and more -## Demo & Examples +## Using an older version? -Live demo: [jedwatson.github.io/react-select](http://jedwatson.github.io/react-select/) +- [v3, v4, and v5 upgrade guide](https://react-select.com/upgrade) +- [v2 upgrade guide](https://react-select.com/upgrade-to-v2) +- React Select v1 documentation and examples are available at [v1.react-select.com](https://v1.react-select.com) -The live demo is still running `v0.9.1`. +# Installation and usage -To build the **new 1.0.0** examples locally, clone this repo then run: +The easiest way to use react-select is to install it from npm and build it into your app with Webpack. -```javascript -npm install -npm start ``` - -Then open [`localhost:8000`](http://localhost:8000) in a browser. - - -## Installation - -The easiest way to use React-Select is to install it from NPM and include it in your own React build process (using [Browserify](http://browserify.org), etc). - -```javascript -npm install react-select --save +yarn add react-select ``` -At this point you can import react-select and its styles in your application as follows: +Then use it in your app: ```js +import React, { useState } from 'react'; import Select from 'react-select'; -// Be sure to include styles at some point, probably during your bootstrapping -import 'react-select/dist/react-select.css'; -``` - -You can also use the standalone build by including `react-select.js` and `react-select.css` in your page. (If you do this though you'll also need to include the dependencies.) For example: -```html -<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> -<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> -<script src="https://unpkg.com/classnames/index.js"></script> -<script src="https://unpkg.com/react-input-autosize/dist/react-input-autosize.js"></script> -<script src="https://unpkg.com/react-select/dist/react-select.js"></script> - -<link rel="stylesheet" href="https://unpkg.com/react-select/dist/react-select.css"> -``` - - -## Usage - -React-Select generates a hidden text field containing the selected value, so you can submit it as part of a standard form. You can also listen for changes with the `onChange` event property. - -Options should be provided as an `Array` of `Object`s, each with a `value` and `label` property for rendering and searching. You can use a `disabled` property to indicate whether the option is disabled or not. - -The `value` property of each option should be set to either a string or a number. - -When the value is changed, `onChange(selectedValueOrValues)` will fire. - -```javascript -var Select = require('react-select'); - -var options = [ - { value: 'one', label: 'One' }, - { value: 'two', label: 'Two' } -]; - -function logChange(val) { - console.log("Selected: " + val); -} - -<Select - name="form-field-name" - value="one" - options={options} - onChange={logChange} -/> -``` - -### Custom classNames - -You can provide a custom `className` prop to the `<Select>` component, which will be added to the base `.Select` className for the outer container. - -The built-in Options renderer also support custom classNames, just add a `className` property to objects in the `options` array. - -### Multiselect options - -You can enable multi-value selection by setting `multi={true}`. In this mode: - -* Selected options will be removed from the dropdown menu -* The selected values are submitted in multiple `<input type="hidden">` fields, use `joinValues` to submit joined values in a single field instead -* The values of the selected items are joined using the `delimiter` prop to create the input value when `joinValues` is true -* A simple value, if provided, will be split using the `delimiter` prop -* The `onChange` event provides an array of selected options _or_ a comma-separated string of values (eg `"1,2,3"`) if `simpleValue` is true -* By default, only options in the `options` array can be selected. Use the `Creatable` Component (which wraps `Select`) to allow new options to be created if they do not already exist. Hitting comma (','), ENTER or TAB will add a new option. Versions `0.9.x` and below provided a boolean attribute on the `Select` Component (`allowCreate`) to achieve the same functionality. It is no longer available starting with version `1.0.0`. -* By default, selected options can be cleared. To disable the possibility of clearing a particular option, add `clearableValue: false` to that option: -```javascript -var options = [ - { value: 'one', label: 'One' }, - { value: 'two', label: 'Two', clearableValue: false } +const options = [ + { value: 'chocolate', label: 'Chocolate' }, + { value: 'strawberry', label: 'Strawberry' }, + { value: 'vanilla', label: 'Vanilla' }, ]; -``` -Note: the `clearable` prop of the Select component should also be set to `false` to prevent allowing clearing all fields at once - -### Async options - -If you want to load options asynchronously, instead of providing an `options` Array, provide a `loadOptions` Function. - -The function takes two arguments `String input, Function callback`and will be called when the input text is changed. - -When your async process finishes getting the options, pass them to `callback(err, data)` in a Object `{ options: [] }`. - -The select control will intelligently cache options for input strings that have already been fetched. The cached result set will be filtered as more specific searches are input, so if your async process would only return a smaller set of results for a more specific query, also pass `complete: true` in the callback object. Caching can be disabled by setting `cache` to `false` (Note that `complete: true` will then have no effect). - -Unless you specify the property `autoload={false}` the control will automatically load the default set of options (i.e. for `input: ''`) when it is mounted. - -```javascript -var Select = require('react-select'); - -var getOptions = function(input, callback) { - setTimeout(function() { - callback(null, { - options: [ - { value: 'one', label: 'One' }, - { value: 'two', label: 'Two' } - ], - // CAREFUL! Only set this to true when there are no more options, - // or more specific queries will not be sent to the server. - complete: true - }); - }, 500); -}; - -<Select.Async - name="form-field-name" - loadOptions={getOptions} -/> -``` - -### Async options with Promises - -`loadOptions` supports Promises, which can be used in very much the same way as callbacks. - -Everything that applies to `loadOptions` with callbacks still applies to the Promises approach (e.g. caching, autoload, ...) - -An example using the `fetch` API and ES6 syntax, with an API that returns an object like: - -```javascript -import Select from 'react-select'; - -/* - * assuming the API returns something like this: - * const json = [ - * { value: 'one', label: 'One' }, - * { value: 'two', label: 'Two' } - * ] - */ - -const getOptions = (input) => { - return fetch(`/users/${input}.json`) - .then((response) => { - return response.json(); - }).then((json) => { - return { options: json }; - }); -} - -<Select.Async - name="form-field-name" - value="one" - loadOptions={getOptions} -/> -``` - -### Async options loaded externally - -If you want to load options asynchronously externally from the `Select` component, you can have the `Select` component show a loading spinner by passing in the `isLoading` prop set to `true`. - -```javascript -var Select = require('react-select'); - -var isLoadingExternally = true; - -<Select - name="form-field-name" - isLoading={isLoadingExternally} - ... -/> -``` - -### User-created tags - -The `Creatable` component enables users to create new tags within react-select. -It decorates a `Select` and so it supports all of the default properties (eg single/multi mode, filtering, etc) in addition to a couple of custom ones (shown below). -The easiest way to use it is like so: -```js -import { Creatable } from 'react-select'; - -function render (selectProps) { - return <Creatable {...selectProps} />; -}; -``` - -##### Creatable properties - -Property | Type | Description -:---|:---|:--- -`children` | function | Child function responsible for creating the inner Select component. This component can be used to compose HOCs (eg Creatable and Async). Expected signature: `(props: Object): PropTypes.element` | -`isOptionUnique` | function | Searches for any matching option within the set of options. This function prevents duplicate options from being created. By default this is a basic, case-sensitive comparison of label and value. Expected signature: `({ option: Object, options: Array, labelKey: string, valueKey: string }): boolean` | -`isValidNewOption` | function | Determines if the current input text represents a valid option. By default any non-empty string will be considered valid. Expected signature: `({ label: string }): boolean` | -`newOptionCreator` | function | Factory to create new option. Expected signature: `({ label: string, labelKey: string, valueKey: string }): Object` | -`onNewOptionClick` | function | new option click handler, it calls when new option has been selected. `function(option) {}` | -`shouldKeyDownEventCreateNewOption` | function | Decides if a keyDown event (eg its `keyCode`) should result in the creation of a new option. ENTER, TAB and comma keys create new options by default. Expected signature: `({ keyCode: number }): boolean` | -`promptTextCreator` | function | Factory for overriding default option creator prompt label. By default it will read 'Create option "{label}"'. Expected signature: `(label: String): String` | +export default function App() { + const [selectedOption, setSelectedOption] = useState(null); -### Combining Async and Creatable - -Use the `AsyncCreatable` HOC if you want both _async_ and _creatable_ functionality. -It ties `Async` and `Creatable` components together and supports a union of their properties (listed above). -Use it as follows: - -```jsx -import React from 'react'; -import { AsyncCreatable } from 'react-select'; - -function render (props) { - // props can be a mix of Async, Creatable, and Select properties return ( - <AsyncCreatable {...props} /> + <div className="App"> + <Select + defaultValue={selectedOption} + onChange={setSelectedOption} + options={options} + /> + </div> ); } ``` -### Filtering options +## Props -You can control how options are filtered with the following properties: +Common props you may want to specify include: -* `matchPos`: `"start"` or `"any"`: whether to match the text entered at the start or any position in the option value -* `matchProp`: `"label"`, `"value"` or `"any"`: whether to match the value, label or both values of each option when filtering -* `ignoreCase`: `Boolean`: whether to ignore case or match the text exactly when filtering -* `ignoreAccents`: `Boolean`: whether to ignore accents on characters like ø or å +- `autoFocus` - focus the control when it mounts +- `className` - apply a className to the control +- `classNamePrefix` - apply classNames to inner elements with the given prefix +- `isDisabled` - disable the control +- `isMulti` - allow the user to select multiple values +- `isSearchable` - allow the user to search for matching options +- `name` - generate an HTML input with this name, containing the current value +- `onChange` - subscribe to change events +- `options` - specify the options the user can select from +- `placeholder` - change the text displayed when no option is selected +- `noOptionsMessage` - ({ inputValue: string }) => string | null - Text to display when there are no options +- `value` - control the current value -`matchProp` and `matchPos` both default to `"any"`. -`ignoreCase` defaults to `true`. -`ignoreAccents` defaults to `true`. +See the [props documentation](https://www.react-select.com/props) for complete documentation on the props react-select supports. -#### Advanced filters +## Controllable Props -You can also completely replace the method used to filter either a single option, or the entire options array (allowing custom sort mechanisms, etc.) +You can control the following props by providing values for them. If you don't, react-select will manage them for you. -* `filterOption`: `function(Object option, String filter)` returns `Boolean`. Will override `matchPos`, `matchProp`, `ignoreCase` and `ignoreAccents` options. -* `filterOptions`: `function(Array options, String filter, Array currentValues)` returns `Array filteredOptions`. Will override `filterOption`, `matchPos`, `matchProp`, `ignoreCase` and `ignoreAccents` options. +- `value` / `onChange` - specify the current value of the control +- `menuIsOpen` / `onMenuOpen` / `onMenuClose` - control whether the menu is open +- `inputValue` / `onInputChange` - control the value of the search input (changing this will update the available options) -For multi-select inputs, when providing a custom `filterOptions` method, remember to exclude current values from the returned array of options. +If you don't provide these props, you can set the initial value of the state they control: -#### Filtering large lists +- `defaultValue` - set the initial value of the control +- `defaultMenuIsOpen` - set the initial open value of the menu +- `defaultInputValue` - set the initial value of the search input -The default `filterOptions` method scans the options array for matches each time the filter text changes. -This works well but can get slow as the options array grows to several hundred objects. -For larger options lists a custom filter function like [`react-select-fast-filter-options`](https://github.com/bvaughn/react-select-fast-filter-options) will produce better results. +## Methods -### Effeciently rendering large lists with windowing +React-select exposes two public methods: -The `menuRenderer` property can be used to override the default drop-down list of options. -This should be done when the list is large (hundreds or thousands of items) for faster rendering. -Windowing libraries like [`react-virtualized`](https://github.com/bvaughn/react-virtualized) can then be used to more efficiently render the drop-down menu like so. -The easiest way to do this is with the [`react-virtualized-select`](https://github.com/bvaughn/react-virtualized-select/) HOC. -This component decorates a `Select` and uses the react-virtualized `VirtualScroll` component to render options. -Demo and documentation for this component are available [here](https://bvaughn.github.io/react-virtualized-select/). +- `focus()` - focus the control programmatically +- `blur()` - blur the control programmatically -You can also specify your own custom renderer. -The custom `menuRenderer` property accepts the following named parameters: +## Customisation -| Parameter | Type | Description | -|:---|:---|:---| -| focusedOption | `Object` | The currently focused option; should be visible in the menu by default. | -| focusOption | `Function` | Callback to focus a new option; receives the option as a parameter. | -| labelKey | `String` | Option labels are accessible with this string key. | -| optionClassName | `String` | The className that gets used for options | -| optionComponent | `ReactClass` | The react component that gets used for rendering an option | -| optionRenderer | `Function` | The function that gets used to render the content of an option | -| options | `Array<Object>` | Ordered array of options to render. | -| selectValue | `Function` | Callback to select a new option; receives the option as a parameter. | -| valueArray | `Array<Object>` | Array of currently selected options. | +Check the docs for more information on: -### Updating input values with onInputChange +- [Customising the styles](https://www.react-select.com/styles) +- [Using custom components](https://www.react-select.com/components) +- [Using the built-in animated components](https://www.react-select.com/home#animated-components) +- [Creating an async select](https://www.react-select.com/async) +- [Allowing users to create new options](https://www.react-select.com/creatable) +- [Advanced use-cases](https://www.react-select.com/advanced) +- [TypeScript guide](https://www.react-select.com/typescript) -You can manipulate the input using the onInputChange and returning a new value. +## TypeScript -```js -function cleanInput(inputValue) { - // Strip all non-number characters from the input - return inputValue.replace(/[^0-9]/g, ""); -} - -<Select - name="form-field-name" - onInputChange={cleanInput} -/> -``` - -### Overriding default key-down behavior with onInputKeyDown - -`Select` listens to `keyDown` events to select items, navigate drop-down list via arrow keys, etc. -You can extend or override this behavior by providing a `onInputKeyDown` callback. - -```js -function onInputKeyDown(event) { - switch (event.keyCode) { - case 9: // TAB - // Extend default TAB behavior by doing something here - break; - case 13: // ENTER - // Override default ENTER behavior by doing stuff here and then preventing default - event.preventDefault(); - break; - } -} - -<Select - {...otherProps} - onInputKeyDown={onInputKeyDown} -/> -``` - -### Further options - - - Property | Type | Default | Description -:-----------------------|:--------------|:--------------|:-------------------------------- - addLabelText | string | 'Add "{label}"?' | text to display when `allowCreate` is true - arrowRenderer | func | undefined | Renders a custom drop-down arrow to be shown in the right-hand side of the select: `arrowRenderer({ onMouseDown, isOpen })` - autoBlur | bool | false | Blurs the input element after a selection has been made. Handy for lowering the keyboard on mobile devices - autofocus | bool | undefined | autofocus the component on mount - autoload | bool | true | whether to auto-load the default async options set - autosize | bool | true | If enabled, the input will expand as the length of its value increases - backspaceRemoves | bool | true | whether pressing backspace removes the last item when there is no input value - backspaceToRemoveMessage | string | 'Press backspace to remove {last label}' | prompt shown in input when at least one option in a multiselect is shown, set to '' to clear - cache | bool | true | enables the options cache for `asyncOptions` (default: `true`) - className | string | undefined | className for the outer element - clearable | bool | true | should it be possible to reset value - clearAllText | string | 'Clear all' | title for the "clear" control when `multi` is true - clearRenderer | func | undefined | Renders a custom clear to be shown in the right-hand side of the select when clearable true: `clearRenderer()` - clearValueText | string | 'Clear value' | title for the "clear" control - resetValue | any | null | value to use when you clear the control - deleteRemoves | bool | true | whether pressing delete key removes the last item when there is no input value - delimiter | string | ',' | delimiter to use to join multiple values - disabled | bool | false | whether the Select is disabled or not - filterOption | func | undefined | method to filter a single option: `function(option, filterString)` - filterOptions | func | undefined | method to filter the options array: `function([options], filterString, [values])` - ignoreAccents | bool | true | whether to strip accents when filtering - ignoreCase | bool | true | whether to perform case-insensitive filtering - inputProps | object | {} | custom attributes for the Input (in the Select-control) e.g: `{'data-foo': 'bar'}` - isLoading | bool | false | whether the Select is loading externally or not (such as options being loaded) - joinValues | bool | false | join multiple values into a single hidden input using the `delimiter` - labelKey | string | 'label' | the option property to use for the label - loadOptions | func | undefined | function that returns a promise or calls a callback with the options: `function(input, [callback])` - matchPos | string | 'any' | (any, start) match the start or entire string when filtering - matchProp | string | 'any' | (any, label, value) which option property to filter on - menuBuffer | number | 0 | buffer of px between the base of the dropdown and the viewport to shift if menu doesnt fit in viewport - menuRenderer | func | undefined | Renders a custom menu with options; accepts the following named parameters: `menuRenderer({ focusedOption, focusOption, options, selectValue, valueArray })` - multi | bool | undefined | multi-value input - name | string | undefined | field name, for hidden `<input />` tag - noResultsText | string | 'No results found' | placeholder displayed when there are no matching search results or a falsy value to hide it (can also be a react component) - onBlur | func | undefined | onBlur handler: `function(event) {}` - onBlurResetsInput | bool | true | whether to clear input on blur or not - onChange | func | undefined | onChange handler: `function(newValue) {}` - onClose | func | undefined | handler for when the menu closes: `function () {}` - onCloseResetsInput | bool | true | whether to clear input when closing the menu through the arrow - onFocus | func | undefined | onFocus handler: `function(event) {}` - onInputChange | func | undefined | onInputChange handler: `function(inputValue) {}` - onInputKeyDown | func | undefined | input keyDown handler; call `event.preventDefault()` to override default `Select` behavior: `function(event) {}` - onOpen | func | undefined | handler for when the menu opens: `function () {}` - onValueClick | func | undefined | onClick handler for value labels: `function (value, event) {}` - openOnFocus | bool | false | open the options menu when the input gets focus (requires searchable = true) - optionRenderer | func | undefined | function which returns a custom way to render the options in the menu - options | array | undefined | array of options - placeholder | string\|node | 'Select ...' | field placeholder, displayed when there's no value - scrollMenuIntoView | bool | true | whether the viewport will shift to display the entire menu when engaged - searchable | bool | true | whether to enable searching feature or not - searchPromptText | string\|node | 'Type to search' | label to prompt for search input - loadingPlaceholder | string\|node | 'Loading...' | label to prompt for loading search result - tabSelectsValue | bool | true | whether to select the currently focused value when the `[tab]` key is pressed - value | any | undefined | initial field value - valueKey | string | 'value' | the option property to use for the value - valueRenderer | func | undefined | function which returns a custom way to render the value selected `function (option) {}` - -### Methods - -Right now there's simply a `focus()` method that gives the control focus. All other methods on `<Select>` elements should be considered private and prone to change. - -```javascript -// focuses the input element -<instance>.focus(); -``` +The v5 release represents a rewrite from JavaScript to TypeScript. The types for v4 and earlier releases are available at [@types](https://www.npmjs.com/package/@types/react-select). See the [TypeScript guide](https://www.react-select.com/typescript) for how to use the types starting with v5. -# Contributing +# Thanks -See our [CONTRIBUTING.md](https://github.com/JedWatson/react-select/blob/master/CONTRIBUTING.md) for information on how to contribute. +Thank you to everyone who has contributed to this project. It's been a wild ride. -Thanks to the projects this was inspired by: [Selectize](http://brianreavis.github.io/selectize.js/) (in terms of behaviour and user experience), [React-Autocomplete](https://github.com/rackt/react-autocomplete) (as a quality React Combobox implementation), as well as other select controls including [Chosen](http://harvesthq.github.io/chosen/) and [Select2](http://ivaynberg.github.io/select2/). +If you like React Select, you should [follow me on Twitter](https://twitter.com/jedwatson)! +Shout out to [Joss Mackison](https://github.com/jossmac), [Charles Lee](https://github.com/gwyneplaine), [Ben Conolly](https://github.com/Noviny), [Tom Walker](https://github.com/bladey), [Nathan Bierema](https://github.com/Methuselah96), [Eric Bonow](https://github.com/ebonow), [Emma Hamilton](https://github.com/emmatown), [Dave Brotherstone](https://github.com/bruderstein), [Brian Vaughn](https://github.com/bvaughn), and the [Atlassian Design System](https://atlassian.design) team who along with many other contributors have made this possible ❤️ -# License +## License -MIT Licensed. Copyright (c) Jed Watson 2016. +MIT Licensed. Copyright (c) Jed Watson 2022. diff --git a/TODO.md b/TODO.md deleted file mode 100644 index ac57413dce..0000000000 --- a/TODO.md +++ /dev/null @@ -1,34 +0,0 @@ -# TODO - -* options creation (was part of buildMenu and selectFocusedOption) -* handle comma keypress for tags mode (handleKeyDown keyCode 188) -* use componentDidUpdate for binding the closeMenuIfClicked... handlers (are these still needed?) -* the behaviour of searchable=false isn't very good yet, needs docus handling & close on body click -* pagination support in Async component - -## Component Methods - -* handle _ closeMenuIfClickedOutside -* handle _ bindCloseMenuIfClickedOutside -* handle _ unbindCloseMenuIfClickedOutside - -* componentWillUnmount -* clickedOutsideElement -* handleMouseDownOnMenu - -## Performance concerns - -* checking the focused option after every render -* filtering the options on every render - -## Questions - -* Why is the reference check in filterOptions for excluded values not matching options? - -## Later - -* asyncDelay - wait x ms before calling getOptions in Async - -## Notes - -* You need to provide complex values when using Select.Async or values may not be found in the result set. isLoading can be used to indicate that values are being loaded asynchronously while the component is initialised. diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000000..1a658f42d8 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,13 @@ +module.exports = { + plugins: [ + '@emotion/babel-plugin', + ['@babel/plugin-proposal-class-properties', { loose: true }], + ['@babel/plugin-proposal-private-methods', { loose: true }], + '@babel/plugin-transform-runtime', + ], + presets: [ + '@babel/preset-env', + '@babel/preset-react', + '@babel/preset-typescript', + ], +}; diff --git a/bower.json b/bower.json deleted file mode 100644 index 19cc369235..0000000000 --- a/bower.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "name": "react-select", - "main": [ - "dist/react-select.min.js", - "dist/react-select.min.css" - ], - "version": "1.0.0-beta14", - "homepage": "https://github.com/JedWatson/react-select", - "authors": [ - "Jed Watson" - ], - "description": "A Select control built with and for ReactJS", - "moduleType": [ - "amd", - "globals", - "node" - ], - "dependencies": { - "classnames": "^2.2.0", - "react-input-autosize": "^1.1.0" - }, - "keywords": [ - "react", - "react-component", - "select", - "multiselect", - "combobox", - "input", - "form", - "ui" - ], - "license": "MIT", - "ignore": [ - ".editorconfig", - ".gitignore", - "package.json", - "src", - "node_modules", - "example", - "test" - ] -} diff --git a/cypress.json b/cypress.json new file mode 100644 index 0000000000..db4974eedf --- /dev/null +++ b/cypress.json @@ -0,0 +1,4 @@ +{ + "baseUrl": "http://localhost:8000/cypress-tests", + "video": false +} diff --git a/cypress/fixtures/selectors.json b/cypress/fixtures/selectors.json new file mode 100644 index 0000000000..da975f7e1c --- /dev/null +++ b/cypress/fixtures/selectors.json @@ -0,0 +1,28 @@ +{ + "singleBasic": "#cypress-single", + "singleBasicSelect": "#basic-select-single", + "singleClearable": "#cypress-single-clearable", + "singleClearableSelect": "#clearable-select-single", + "singleGroupedSelect": "#grouped-options-single", + "checkboxDisable": ".disable-checkbox", + "checkboxEscapeClearsValue": ".escape-clears-value-checkbox", + "groupHeading": ".react-select__group-heading", + "indicatorClear": ".react-select__clear-indicator", + "indicatorDropdown": ".react-select__dropdown-indicator", + "menu": ".react-select__menu", + "control": ".react-select__control", + "menuOption": ".react-select__option", + "noOptionsValue": ".react-select__menu-notice--no-options", + "placeholder": ".react-select__placeholder", + "singleValue": ".react-select__single-value", + "menuSingle": "#basic-select-single .react-select__menu", + "singleSelectSingleInput": "#react-select-basic-select-single-input", + "toggleMenuSingle": "#basic-select-single .react-select__dropdown-indicator", + "firstMultiValueRemove": "#multi-select .react-select__multi-value__remove:first", + "menuMulti": "#multi-select .react-select__menu", + "multiSelectDefaultValues": "#multi-select .react-select__multi-value", + "multiSelectInput": "#react-select-multi-select-input", + "placeHolderMulti": "#multi-select .react-select__placeholder", + "toggleMenuMulti": "#multi-select .react-select__dropdown-indicator", + "focusedOption": ".react-select__option--is-focused" +} diff --git a/cypress/integration/multi-select.spec.ts b/cypress/integration/multi-select.spec.ts new file mode 100644 index 0000000000..eab428c3ce --- /dev/null +++ b/cypress/integration/multi-select.spec.ts @@ -0,0 +1,87 @@ +import selector from '../fixtures/selectors.json'; +import cypressJson from '../../cypress.json'; + +const setup = [ + { width: 1440, height: 900, viewport: 'macbook-15', device: 'Laptop' }, + { width: 375, height: 667, viewport: 'iphone-6', device: 'Mobile' }, + { width: 768, height: 1024, viewport: 'ipad-2', device: 'Tablet' }, +]; + +describe('Multi Select', () => { + before(() => { + cy.visit(cypressJson.baseUrl); + cy.title().should('equal', 'React-Select'); + cy.get('h1').should('contain', 'Test Page for Cypress'); + }); + beforeEach(() => { + cy.reload(); + }); + + for (let config of setup) { + const { viewport } = config; + it(`Should display several default values that can be removed in view: ${viewport}`, () => { + cy.get(selector.multiSelectDefaultValues).then(function ($defaultValue) { + expect($defaultValue).to.have.length(2); + expect($defaultValue.eq(0)).to.contain('Purple'); + expect($defaultValue.eq(1)).to.contain('Red'); + }); + + cy.get(selector.firstMultiValueRemove) + .click() + .get(selector.multiSelectDefaultValues) + .then(function ($defaultValue) { + expect($defaultValue).to.have.length(1); + expect($defaultValue.eq(0)).to.contain('Red'); + }) + .get(selector.menuMulti) + .should('not.be.visible'); + }); + + it(`Should be able to remove values on keyboard actions in view: ${viewport}`, () => { + cy.get(selector.multiSelectInput) + .click() + .type('{backspace}', { force: true }) + .get(selector.multiSelectDefaultValues) + .then(function ($defaultValue) { + expect($defaultValue).to.have.length(1); + expect($defaultValue.eq(0)).to.contain('Purple'); + }) + .get(selector.multiSelectInput) + .type('{backspace}', { force: true }) + .get(selector.placeHolderMulti) + .should('contain', 'Select...'); + }); + + it(`Should select different options using - click and enter in view: ${viewport}`, () => { + cy.get(selector.menuMulti) + .should('not.exist') + .get(selector.toggleMenuMulti) + .click() + .get(selector.menuMulti) + .should('exist') + .get(selector.menuMulti) + .should('be.visible') + .get(selector.menuOption) + .contains('Orange') + .click() + .get(selector.toggleMenuMulti) + .click() + .get(selector.menuOption) + .contains('Yellow') + .click() + .get(selector.multiSelectInput) + .click({ force: true }) + .type('Slate', { force: true }) + .type('{enter}', { force: true }) + .get(selector.multiSelectDefaultValues) + .then(function ($defaultValue) { + expect($defaultValue).to.have.length(5); + expect($defaultValue.eq(0)).to.contain('Purple'); + expect($defaultValue.eq(1)).to.contain('Red'); + expect($defaultValue.eq(2)).to.contain('Orange'); + expect($defaultValue.eq(3)).to.contain('Yellow'); + expect($defaultValue.eq(4)).to.contain('Slate'); + }); + }); + } +}); diff --git a/cypress/integration/single-select.spec.ts b/cypress/integration/single-select.spec.ts new file mode 100644 index 0000000000..2e7effeca5 --- /dev/null +++ b/cypress/integration/single-select.spec.ts @@ -0,0 +1,308 @@ +import selector from '../fixtures/selectors.json'; +import cypressJson from '../../cypress.json'; + +const setup = [ + { + width: 1440, + height: 900, + viewport: 'macbook-15' as const, + device: 'Laptop', + }, + { width: 375, height: 667, viewport: 'iphone-6' as const, device: 'Mobile' }, + { width: 768, height: 1024, viewport: 'ipad-2' as const, device: 'Tablet' }, +]; + +describe('Single Select', () => { + before(() => { + cy.visit(cypressJson.baseUrl); + cy.title().should('equal', 'React-Select'); + cy.get('h1').should('contain', 'Test Page for Cypress'); + }); + + for (let config of setup) { + const { viewport } = config; + + context(`Basic in view: ${viewport}`, () => { + before(() => { + cy.viewport(viewport); + }); + + beforeEach(() => { + cy.reload(); + }); + + // TODO: + // This test seems to fail when cypress tab is focused. + // Also, manual testing does not confirm the desired behavior. + it.skip(`Should not display the options menu when touched and dragged in view: ${viewport}`, () => { + cy.get(selector.toggleMenuSingle) + .click() + .click() + .get(selector.menuSingle) + .should('not.be.visible') + // to be sure it says focus and the menu is closed + .get(selector.singleSelectSingleInput) + .trigger('mousedown') + .get(selector.menuSingle) + .should('not.be.visible'); + }); + it(`Should display a default value in view: ${viewport}`, () => { + cy.get(selector.singleBasicSelect) + .find(selector.singleValue) + .should('contain', 'Ocean'); + }); + + it(`Should expand the menu when expand icon is clicked in view: ${viewport}`, () => { + cy + // Menu is not yet open + .get(selector.singleBasicSelect) + .find(selector.menu) + .should('not.exist') + // A dropdown icon is shown + .get(selector.singleBasicSelect) + .find(selector.indicatorDropdown) + .should('be.visible') + // Click the icon to open the menu + .click() + .get(selector.singleBasicSelect) + .find(selector.menu) + .should('exist') + .should('be.visible') + .contains('Green'); + }); + + it(`Should close the menu after selecting an option in view: ${viewport}`, () => { + cy.get(selector.singleBasicSelect) + .find(selector.indicatorDropdown) + .click() + .get(selector.singleBasicSelect) + .find(selector.menu) + .should('contain', 'Green') + .contains('Green') + .click() + // Value has updated + .get(selector.singleBasicSelect) + .find(selector.singleValue) + .should('contain', 'Green') + // Menu has closed + .get(selector.singleBasicSelect) + .find(selector.menu) + .should('not.exist'); + }); + + it(`Should be disabled once disabled is checked in view: ${viewport}`, () => { + cy + // Does not start out disabled + .get(selector.singleBasicSelect) + // .click() + .find('input') + .should('exist') + .should('not.be.disabled') + // Disable the select component + .get(selector.singleBasic) + .find(selector.checkboxDisable) + .click() + // Now the input should be disabled + .get(selector.singleBasicSelect) + .click({ force: true }) + .find('input') + .should('exist') + .should('be.disabled') + // control should have aria-disabled + .get(selector.singleBasicSelect) + .find(selector.control) + .should('have.attr', 'aria-disabled', 'true'); + }); + + it(`Should filter options when searching in view: ${viewport}`, () => { + cy.get(selector.singleBasicSelect) + .click() + .find('input') + .type('For', { force: true }) + .get(selector.singleBasicSelect) + .find(selector.menu) + .should('contain', 'Forest') + .find(selector.menuOption) + .should('have.length', 1); + }); + + it(`Should show "No options" if searched value is not found in view: ${viewport}`, () => { + cy.get(selector.singleBasicSelect) + .click() + .find('input') + .type('/', { force: true }) + .get(selector.noOptionsValue) + .should('contain', 'No options'); + }); + + it(`Should not clear the value when backspace is pressed in view: ${viewport}`, () => { + cy.get(selector.singleBasicSelect) + .click() + .find('input') + .type('{backspace}', { force: true }) + .get(selector.singleBasicSelect) + .find(selector.placeholder) + .should('not.be.visible'); + }); + }); + + context(`Grouped in view: ${viewport}`, () => { + before(() => { + cy.viewport(viewport); + }); + + beforeEach(() => { + cy.reload(); + }); + + it(`Should display a default value in view: ${viewport}`, () => { + cy.get(selector.singleGroupedSelect) + .find(selector.singleValue) + .should('contain', 'Blue'); + }); + + it(`Should display group headings in the menu in view: ${viewport}`, () => { + cy.get(selector.singleGroupedSelect) + .find(selector.indicatorDropdown) + .click() + .get(selector.singleGroupedSelect) + .find(selector.menu) + .should('be.visible') + .find(selector.groupHeading) + .should('have.length', 2); + }); + + it(`Should focus next option on down arrow key press: ${viewport}`, () => { + cy.get(selector.singleGroupedSelect) + .click() + .find('input') + .type('{downarrow}', { force: true }) + .get(selector.focusedOption) + .should('exist'); + }); + + it(`Should focus next option on down arrow key press after filtering: ${viewport}`, () => { + cy.get(selector.singleGroupedSelect) + .click() + .find('input') + .type('o', { force: true }) + .type('{downarrow}', { force: true }) + .get(selector.focusedOption) + .should('exist'); + }); + }); + + context(`Clearable in view: ${viewport}`, () => { + before(() => { + cy.viewport(viewport); + }); + + beforeEach(() => { + cy.reload(); + }); + + it(`Should display a default value in view: ${viewport}`, () => { + cy.get(selector.singleClearableSelect) + .find(selector.singleValue) + .should('contain', 'Blue'); + }); + + it(`Should display a clear indicator in view: ${viewport}`, () => { + cy.get(selector.singleClearableSelect) + .find(selector.indicatorClear) + .should('be.visible'); + }); + + it(`Should clear the default value when clear is clicked in view: ${viewport}`, () => { + cy.get(selector.singleClearableSelect) + .find(selector.indicatorClear) + .click() + .get(selector.singleClearableSelect) + .find(selector.placeholder) + .should('be.visible') + .should('contain', 'Select...'); + }); + + // 'backspaceRemovesValue' is true by default + it(`Should clear the value when backspace is pressed in view: ${viewport}`, () => { + cy.get(selector.singleClearableSelect) + .click() + .find('input') + .type('{backspace}', { force: true }) + .get(selector.singleClearableSelect) + .find(selector.placeholder) + .should('be.visible') + .should('contain', 'Select...'); + }); + + // 'backspaceRemovesValue' is true by default, and delete is included + it(`Should clear the value when delete is pressed in view: ${viewport}`, () => { + cy.get(selector.singleClearableSelect) + .click() + .find('input') + .type('{del}', { force: true }) + .get(selector.singleClearableSelect) + .find(selector.placeholder) + .should('be.visible') + .should('contain', 'Select...'); + }); + + it(`Should not open the menu when a value is cleared with backspace in view: ${viewport}`, () => { + cy.get(selector.singleClearableSelect) + .click() + .find('input') + // Close the menu, but leave focused + .type('{esc}', { force: true }) + .get(selector.singleClearableSelect) + .find(selector.menu) + .should('not.be.visible') + // Clear the value, verify menu doesn't pop + .get(selector.singleClearableSelect) + .find('input') + .type('{backspace}', { force: true }) + .get(selector.singleClearableSelect) + .find(selector.menu) + .should('not.be.visible'); + }); + + it(`Should clear the value when escape is pressed if escapeClearsValue and menu is closed in view: ${viewport}`, () => { + cy + // nothing happens if escapeClearsValue is false + .get(selector.singleClearableSelect) + .click() + .find('input') + // Escape once to close the menu + .type('{esc}', { force: true }) + .get(selector.singleBasicSelect) + .find(selector.menu) + .should('not.be.visible') + // Escape again to verify value is not cleared + .get(selector.singleClearableSelect) + .find('input') + .type('{esc}', { force: true }) + .get(selector.singleClearableSelect) + .find(selector.placeholder) + .should('not.be.visible') + // Enable escapeClearsValue and try again, it should clear the value + .get(selector.singleClearable) + .find(selector.checkboxEscapeClearsValue) + .click() + .get(selector.singleClearableSelect) + .click() + .find('input') + // Escape once to close the menu + .type('{esc}', { force: true }) + .get(selector.singleBasicSelect) + .find(selector.menu) + .should('not.be.visible') + // Escape again to clear value + .get(selector.singleClearableSelect) + .find('input') + .type('{esc}', { force: true }) + .get(selector.singleClearableSelect) + .find(selector.placeholder) + .should('be.visible'); + }); + }); + } +}); diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json new file mode 100644 index 0000000000..9e0343e3cc --- /dev/null +++ b/cypress/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "noEmit": true, + "strict": true, + "types": ["cypress"], + "esModuleInterop": true, + "resolveJsonModule": true + } +} diff --git a/dist/react-select.css b/dist/react-select.css deleted file mode 100644 index 658cc59b11..0000000000 --- a/dist/react-select.css +++ /dev/null @@ -1,375 +0,0 @@ -/** - * React Select - * ============ - * Created by Jed Watson and Joss Mackison for KeystoneJS, http://www.keystonejs.com/ - * https://twitter.com/jedwatson https://twitter.com/jossmackison https://twitter.com/keystonejs - * MIT License: https://github.com/JedWatson/react-select -*/ -.Select { - position: relative; -} -.Select, -.Select div, -.Select input, -.Select span { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -.Select.is-disabled > .Select-control { - background-color: #f9f9f9; -} -.Select.is-disabled > .Select-control:hover { - box-shadow: none; -} -.Select.is-disabled .Select-arrow-zone { - cursor: default; - pointer-events: none; - opacity: 0.35; -} -.Select-control { - background-color: #fff; - border-color: #d9d9d9 #ccc #b3b3b3; - border-radius: 4px; - border: 1px solid #ccc; - color: #333; - cursor: default; - display: table; - border-spacing: 0; - border-collapse: separate; - height: 36px; - outline: none; - overflow: hidden; - position: relative; - width: 100%; -} -.Select-control:hover { - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); -} -.Select-control .Select-input:focus { - outline: none; -} -.is-searchable.is-open > .Select-control { - cursor: text; -} -.is-open > .Select-control { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; - background: #fff; - border-color: #b3b3b3 #ccc #d9d9d9; -} -.is-open > .Select-control .Select-arrow { - top: -2px; - border-color: transparent transparent #999; - border-width: 0 5px 5px; -} -.is-searchable.is-focused:not(.is-open) > .Select-control { - cursor: text; -} -.is-focused:not(.is-open) > .Select-control { - border-color: #007eff; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 0 3px rgba(0, 126, 255, 0.1); -} -.Select-placeholder, -.Select--single > .Select-control .Select-value { - bottom: 0; - color: #aaa; - left: 0; - line-height: 34px; - padding-left: 10px; - padding-right: 10px; - position: absolute; - right: 0; - top: 0; - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.has-value.Select--single > .Select-control .Select-value .Select-value-label, -.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value .Select-value-label { - color: #333; -} -.has-value.Select--single > .Select-control .Select-value a.Select-value-label, -.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label { - cursor: pointer; - text-decoration: none; -} -.has-value.Select--single > .Select-control .Select-value a.Select-value-label:hover, -.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label:hover, -.has-value.Select--single > .Select-control .Select-value a.Select-value-label:focus, -.has-value.is-pseudo-focused.Select--single > .Select-control .Select-value a.Select-value-label:focus { - color: #007eff; - outline: none; - text-decoration: underline; -} -.Select-input { - height: 34px; - padding-left: 10px; - padding-right: 10px; - vertical-align: middle; -} -.Select-input > input { - width: 100%; - background: none transparent; - border: 0 none; - box-shadow: none; - cursor: default; - display: inline-block; - font-family: inherit; - font-size: inherit; - margin: 0; - outline: none; - line-height: 14px; - /* For IE 8 compatibility */ - padding: 8px 0 12px; - /* For IE 8 compatibility */ - -webkit-appearance: none; -} -.is-focused .Select-input > input { - cursor: text; -} -.has-value.is-pseudo-focused .Select-input { - opacity: 0; -} -.Select-control:not(.is-searchable) > .Select-input { - outline: none; -} -.Select-loading-zone { - cursor: pointer; - display: table-cell; - position: relative; - text-align: center; - vertical-align: middle; - width: 16px; -} -.Select-loading { - -webkit-animation: Select-animation-spin 400ms infinite linear; - -o-animation: Select-animation-spin 400ms infinite linear; - animation: Select-animation-spin 400ms infinite linear; - width: 16px; - height: 16px; - box-sizing: border-box; - border-radius: 50%; - border: 2px solid #ccc; - border-right-color: #333; - display: inline-block; - position: relative; - vertical-align: middle; -} -.Select-clear-zone { - -webkit-animation: Select-animation-fadeIn 200ms; - -o-animation: Select-animation-fadeIn 200ms; - animation: Select-animation-fadeIn 200ms; - color: #999; - cursor: pointer; - display: table-cell; - position: relative; - text-align: center; - vertical-align: middle; - width: 17px; -} -.Select-clear-zone:hover { - color: #D0021B; -} -.Select-clear { - display: inline-block; - font-size: 18px; - line-height: 1; -} -.Select--multi .Select-clear-zone { - width: 17px; -} -.Select-arrow-zone { - cursor: pointer; - display: table-cell; - position: relative; - text-align: center; - vertical-align: middle; - width: 25px; - padding-right: 5px; -} -.Select-arrow { - border-color: #999 transparent transparent; - border-style: solid; - border-width: 5px 5px 2.5px; - display: inline-block; - height: 0; - width: 0; - position: relative; -} -.is-open .Select-arrow, -.Select-arrow-zone:hover > .Select-arrow { - border-top-color: #666; -} -.Select--multi .Select-multi-value-wrapper { - display: inline-block; -} -.Select .Select-aria-only { - display: inline-block; - height: 1px; - width: 1px; - margin: -1px; - clip: rect(0, 0, 0, 0); - overflow: hidden; - float: left; -} -@-webkit-keyframes Select-animation-fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -@keyframes Select-animation-fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} -.Select-menu-outer { - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; - background-color: #fff; - border: 1px solid #ccc; - border-top-color: #e6e6e6; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06); - box-sizing: border-box; - margin-top: -1px; - max-height: 200px; - position: absolute; - top: 100%; - width: 100%; - z-index: 1; - -webkit-overflow-scrolling: touch; -} -.Select-menu { - max-height: 198px; - overflow-y: auto; -} -.Select-option { - box-sizing: border-box; - background-color: #fff; - color: #666666; - cursor: pointer; - display: block; - padding: 8px 10px; -} -.Select-option:last-child { - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.Select-option.is-selected { - background-color: #f5faff; - /* Fallback color for IE 8 */ - background-color: rgba(0, 126, 255, 0.04); - color: #333; -} -.Select-option.is-focused { - background-color: #ebf5ff; - /* Fallback color for IE 8 */ - background-color: rgba(0, 126, 255, 0.08); - color: #333; -} -.Select-option.is-disabled { - color: #cccccc; - cursor: default; -} -.Select-noresults { - box-sizing: border-box; - color: #999999; - cursor: default; - display: block; - padding: 8px 10px; -} -.Select--multi .Select-input { - vertical-align: middle; - margin-left: 10px; - padding: 0; -} -.Select--multi.has-value .Select-input { - margin-left: 5px; -} -.Select--multi .Select-value { - background-color: #ebf5ff; - /* Fallback color for IE 8 */ - background-color: rgba(0, 126, 255, 0.08); - border-radius: 2px; - border: 1px solid #c2e0ff; - /* Fallback color for IE 8 */ - border: 1px solid rgba(0, 126, 255, 0.24); - color: #007eff; - display: inline-block; - font-size: 0.9em; - line-height: 1.4; - margin-left: 5px; - margin-top: 5px; - vertical-align: top; -} -.Select--multi .Select-value-icon, -.Select--multi .Select-value-label { - display: inline-block; - vertical-align: middle; -} -.Select--multi .Select-value-label { - border-bottom-right-radius: 2px; - border-top-right-radius: 2px; - cursor: default; - padding: 2px 5px; -} -.Select--multi a.Select-value-label { - color: #007eff; - cursor: pointer; - text-decoration: none; -} -.Select--multi a.Select-value-label:hover { - text-decoration: underline; -} -.Select--multi .Select-value-icon { - cursor: pointer; - border-bottom-left-radius: 2px; - border-top-left-radius: 2px; - border-right: 1px solid #c2e0ff; - /* Fallback color for IE 8 */ - border-right: 1px solid rgba(0, 126, 255, 0.24); - padding: 1px 5px 3px; -} -.Select--multi .Select-value-icon:hover, -.Select--multi .Select-value-icon:focus { - background-color: #d8eafd; - /* Fallback color for IE 8 */ - background-color: rgba(0, 113, 230, 0.08); - color: #0071e6; -} -.Select--multi .Select-value-icon:active { - background-color: #c2e0ff; - /* Fallback color for IE 8 */ - background-color: rgba(0, 126, 255, 0.24); -} -.Select--multi.is-disabled .Select-value { - background-color: #fcfcfc; - border: 1px solid #e3e3e3; - color: #333; -} -.Select--multi.is-disabled .Select-value-icon { - cursor: not-allowed; - border-right: 1px solid #e3e3e3; -} -.Select--multi.is-disabled .Select-value-icon:hover, -.Select--multi.is-disabled .Select-value-icon:focus, -.Select--multi.is-disabled .Select-value-icon:active { - background-color: #fcfcfc; -} -@keyframes Select-animation-spin { - to { - transform: rotate(1turn); - } -} -@-webkit-keyframes Select-animation-spin { - to { - -webkit-transform: rotate(1turn); - } -} diff --git a/dist/react-select.js b/dist/react-select.js deleted file mode 100644 index caad9d23f4..0000000000 --- a/dist/react-select.js +++ /dev/null @@ -1,2282 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Select = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ -(function (global){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - -var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - -function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var _Select = require('./Select'); - -var _Select2 = _interopRequireDefault(_Select); - -var _utilsStripDiacritics = require('./utils/stripDiacritics'); - -var _utilsStripDiacritics2 = _interopRequireDefault(_utilsStripDiacritics); - -var propTypes = { - autoload: _react2['default'].PropTypes.bool.isRequired, // automatically call the `loadOptions` prop on-mount; defaults to true - cache: _react2['default'].PropTypes.any, // object to use to cache results; set to null/false to disable caching - children: _react2['default'].PropTypes.func.isRequired, // Child function responsible for creating the inner Select component; (props: Object): PropTypes.element - ignoreAccents: _react2['default'].PropTypes.bool, // strip diacritics when filtering; defaults to true - ignoreCase: _react2['default'].PropTypes.bool, // perform case-insensitive filtering; defaults to true - loadingPlaceholder: _react2['default'].PropTypes.oneOfType([// replaces the placeholder while options are loading - _react2['default'].PropTypes.string, _react2['default'].PropTypes.node]), - loadOptions: _react2['default'].PropTypes.func.isRequired, // callback to load options asynchronously; (inputValue: string, callback: Function): ?Promise - options: _react.PropTypes.array.isRequired, // array of options - placeholder: _react2['default'].PropTypes.oneOfType([// field placeholder, displayed when there's no value (shared with Select) - _react2['default'].PropTypes.string, _react2['default'].PropTypes.node]), - noResultsText: _react2['default'].PropTypes.oneOfType([// field noResultsText, displayed when no options come back from the server - _react2['default'].PropTypes.string, _react2['default'].PropTypes.node]), - onChange: _react2['default'].PropTypes.func, // onChange handler: function (newValue) {} - searchPromptText: _react2['default'].PropTypes.oneOfType([// label to prompt for search input - _react2['default'].PropTypes.string, _react2['default'].PropTypes.node]), - onInputChange: _react2['default'].PropTypes.func, // optional for keeping track of what is being typed - value: _react2['default'].PropTypes.any }; - -// initial field value -var defaultCache = {}; - -var defaultProps = { - autoload: true, - cache: defaultCache, - children: defaultChildren, - ignoreAccents: true, - ignoreCase: true, - loadingPlaceholder: 'Loading...', - options: [], - searchPromptText: 'Type to search' -}; - -var Async = (function (_Component) { - _inherits(Async, _Component); - - function Async(props, context) { - _classCallCheck(this, Async); - - _get(Object.getPrototypeOf(Async.prototype), 'constructor', this).call(this, props, context); - - this._cache = props.cache === defaultCache ? {} : props.cache; - - this.state = { - isLoading: false, - options: props.options - }; - - this._onInputChange = this._onInputChange.bind(this); - } - - _createClass(Async, [{ - key: 'componentDidMount', - value: function componentDidMount() { - var autoload = this.props.autoload; - - if (autoload) { - this.loadOptions(''); - } - } - }, { - key: 'componentWillUpdate', - value: function componentWillUpdate(nextProps, nextState) { - var _this = this; - - var propertiesToSync = ['options']; - propertiesToSync.forEach(function (prop) { - if (_this.props[prop] !== nextProps[prop]) { - _this.setState(_defineProperty({}, prop, nextProps[prop])); - } - }); - } - }, { - key: 'clearOptions', - value: function clearOptions() { - this.setState({ options: [] }); - } - }, { - key: 'loadOptions', - value: function loadOptions(inputValue) { - var _this2 = this; - - var loadOptions = this.props.loadOptions; - - var cache = this._cache; - - if (cache && cache.hasOwnProperty(inputValue)) { - this.setState({ - options: cache[inputValue] - }); - - return; - } - - var callback = function callback(error, data) { - if (callback === _this2._callback) { - _this2._callback = null; - - var options = data && data.options || []; - - if (cache) { - cache[inputValue] = options; - } - - _this2.setState({ - isLoading: false, - options: options - }); - } - }; - - // Ignore all but the most recent request - this._callback = callback; - - var promise = loadOptions(inputValue, callback); - if (promise) { - promise.then(function (data) { - return callback(null, data); - }, function (error) { - return callback(error); - }); - } - - if (this._callback && !this.state.isLoading) { - this.setState({ - isLoading: true - }); - } - - return inputValue; - } - }, { - key: '_onInputChange', - value: function _onInputChange(inputValue) { - var _props = this.props; - var ignoreAccents = _props.ignoreAccents; - var ignoreCase = _props.ignoreCase; - var onInputChange = _props.onInputChange; - - if (ignoreAccents) { - inputValue = (0, _utilsStripDiacritics2['default'])(inputValue); - } - - if (ignoreCase) { - inputValue = inputValue.toLowerCase(); - } - - if (onInputChange) { - onInputChange(inputValue); - } - - return this.loadOptions(inputValue); - } - }, { - key: 'inputValue', - value: function inputValue() { - if (this.select) { - return this.select.state.inputValue; - } - return ''; - } - }, { - key: 'noResultsText', - value: function noResultsText() { - var _props2 = this.props; - var loadingPlaceholder = _props2.loadingPlaceholder; - var noResultsText = _props2.noResultsText; - var searchPromptText = _props2.searchPromptText; - var isLoading = this.state.isLoading; - - var inputValue = this.inputValue(); - - if (isLoading) { - return loadingPlaceholder; - } - if (inputValue && noResultsText) { - return noResultsText; - } - return searchPromptText; - } - }, { - key: 'focus', - value: function focus() { - this.select.focus(); - } - }, { - key: 'render', - value: function render() { - var _this3 = this; - - var _props3 = this.props; - var children = _props3.children; - var loadingPlaceholder = _props3.loadingPlaceholder; - var placeholder = _props3.placeholder; - var _state = this.state; - var isLoading = _state.isLoading; - var options = _state.options; - - var props = { - noResultsText: this.noResultsText(), - placeholder: isLoading ? loadingPlaceholder : placeholder, - options: isLoading && loadingPlaceholder ? [] : options, - ref: function ref(_ref) { - return _this3.select = _ref; - }, - onChange: function onChange(newValues) { - if (_this3.props.multi && _this3.props.value && newValues.length > _this3.props.value.length) { - _this3.clearOptions(); - } - _this3.props.onChange(newValues); - } - }; - - return children(_extends({}, this.props, props, { - isLoading: isLoading, - onInputChange: this._onInputChange - })); - } - }]); - - return Async; -})(_react.Component); - -exports['default'] = Async; - -Async.propTypes = propTypes; -Async.defaultProps = defaultProps; - -function defaultChildren(props) { - return _react2['default'].createElement(_Select2['default'], props); -}; -module.exports = exports['default']; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./Select":5,"./utils/stripDiacritics":11}],2:[function(require,module,exports){ -(function (global){ -'use strict'; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var _Select = require('./Select'); - -var _Select2 = _interopRequireDefault(_Select); - -function reduce(obj) { - var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; - - return Object.keys(obj).reduce(function (props, key) { - var value = obj[key]; - if (value !== undefined) props[key] = value; - return props; - }, props); -} - -var AsyncCreatable = _react2['default'].createClass({ - displayName: 'AsyncCreatableSelect', - - render: function render() { - var _this = this; - - return _react2['default'].createElement( - _Select2['default'].Async, - this.props, - function (asyncProps) { - return _react2['default'].createElement( - _Select2['default'].Creatable, - _this.props, - function (creatableProps) { - return _react2['default'].createElement(_Select2['default'], _extends({}, reduce(asyncProps, reduce(creatableProps, {})), { - onInputChange: function (input) { - creatableProps.onInputChange(input); - return asyncProps.onInputChange(input); - }, - ref: function (ref) { - creatableProps.ref(ref); - asyncProps.ref(ref); - } - })); - } - ); - } - ); - } -}); - -module.exports = AsyncCreatable; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./Select":5}],3:[function(require,module,exports){ -(function (global){ -'use strict'; - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var _Select = require('./Select'); - -var _Select2 = _interopRequireDefault(_Select); - -var _utilsDefaultFilterOptions = require('./utils/defaultFilterOptions'); - -var _utilsDefaultFilterOptions2 = _interopRequireDefault(_utilsDefaultFilterOptions); - -var _utilsDefaultMenuRenderer = require('./utils/defaultMenuRenderer'); - -var _utilsDefaultMenuRenderer2 = _interopRequireDefault(_utilsDefaultMenuRenderer); - -var Creatable = _react2['default'].createClass({ - displayName: 'CreatableSelect', - - propTypes: { - // Child function responsible for creating the inner Select component - // This component can be used to compose HOCs (eg Creatable and Async) - // (props: Object): PropTypes.element - children: _react2['default'].PropTypes.func, - - // See Select.propTypes.filterOptions - filterOptions: _react2['default'].PropTypes.any, - - // Searches for any matching option within the set of options. - // This function prevents duplicate options from being created. - // ({ option: Object, options: Array, labelKey: string, valueKey: string }): boolean - isOptionUnique: _react2['default'].PropTypes.func, - - // Determines if the current input text represents a valid option. - // ({ label: string }): boolean - isValidNewOption: _react2['default'].PropTypes.func, - - // See Select.propTypes.menuRenderer - menuRenderer: _react2['default'].PropTypes.any, - - // Factory to create new option. - // ({ label: string, labelKey: string, valueKey: string }): Object - newOptionCreator: _react2['default'].PropTypes.func, - - // input change handler: function (inputValue) {} - onInputChange: _react2['default'].PropTypes.func, - - // input keyDown handler: function (event) {} - onInputKeyDown: _react2['default'].PropTypes.func, - - // new option click handler: function (option) {} - onNewOptionClick: _react2['default'].PropTypes.func, - - // See Select.propTypes.options - options: _react2['default'].PropTypes.array, - - // Creates prompt/placeholder option text. - // (filterText: string): string - promptTextCreator: _react2['default'].PropTypes.func, - - // Decides if a keyDown event (eg its `keyCode`) should result in the creation of a new option. - shouldKeyDownEventCreateNewOption: _react2['default'].PropTypes.func - }, - - // Default prop methods - statics: { - isOptionUnique: isOptionUnique, - isValidNewOption: isValidNewOption, - newOptionCreator: newOptionCreator, - promptTextCreator: promptTextCreator, - shouldKeyDownEventCreateNewOption: shouldKeyDownEventCreateNewOption - }, - - getDefaultProps: function getDefaultProps() { - return { - filterOptions: _utilsDefaultFilterOptions2['default'], - isOptionUnique: isOptionUnique, - isValidNewOption: isValidNewOption, - menuRenderer: _utilsDefaultMenuRenderer2['default'], - newOptionCreator: newOptionCreator, - promptTextCreator: promptTextCreator, - shouldKeyDownEventCreateNewOption: shouldKeyDownEventCreateNewOption - }; - }, - - createNewOption: function createNewOption() { - var _props = this.props; - var isValidNewOption = _props.isValidNewOption; - var newOptionCreator = _props.newOptionCreator; - var onNewOptionClick = _props.onNewOptionClick; - var _props$options = _props.options; - var options = _props$options === undefined ? [] : _props$options; - var shouldKeyDownEventCreateNewOption = _props.shouldKeyDownEventCreateNewOption; - - if (isValidNewOption({ label: this.inputValue })) { - var option = newOptionCreator({ label: this.inputValue, labelKey: this.labelKey, valueKey: this.valueKey }); - var _isOptionUnique = this.isOptionUnique({ option: option }); - - // Don't add the same option twice. - if (_isOptionUnique) { - if (onNewOptionClick) { - onNewOptionClick(option); - } else { - options.unshift(option); - - this.select.selectValue(option); - } - } - } - }, - - filterOptions: function filterOptions() { - var _props2 = this.props; - var filterOptions = _props2.filterOptions; - var isValidNewOption = _props2.isValidNewOption; - var options = _props2.options; - var promptTextCreator = _props2.promptTextCreator; - - // TRICKY Check currently selected options as well. - // Don't display a create-prompt for a value that's selected. - // This covers async edge-cases where a newly-created Option isn't yet in the async-loaded array. - var excludeOptions = arguments[2] || []; - - var filteredOptions = filterOptions.apply(undefined, arguments) || []; - - if (isValidNewOption({ label: this.inputValue })) { - var _newOptionCreator = this.props.newOptionCreator; - - var option = _newOptionCreator({ - label: this.inputValue, - labelKey: this.labelKey, - valueKey: this.valueKey - }); - - // TRICKY Compare to all options (not just filtered options) in case option has already been selected). - // For multi-selects, this would remove it from the filtered list. - var _isOptionUnique2 = this.isOptionUnique({ - option: option, - options: excludeOptions.concat(filteredOptions) - }); - - if (_isOptionUnique2) { - var _prompt = promptTextCreator(this.inputValue); - - this._createPlaceholderOption = _newOptionCreator({ - label: _prompt, - labelKey: this.labelKey, - valueKey: this.valueKey - }); - - filteredOptions.unshift(this._createPlaceholderOption); - } - } - - return filteredOptions; - }, - - isOptionUnique: function isOptionUnique(_ref2) { - var option = _ref2.option; - var options = _ref2.options; - var isOptionUnique = this.props.isOptionUnique; - - options = options || this.select.filterOptions(); - - return isOptionUnique({ - labelKey: this.labelKey, - option: option, - options: options, - valueKey: this.valueKey - }); - }, - - menuRenderer: function menuRenderer(params) { - var menuRenderer = this.props.menuRenderer; - - return menuRenderer(_extends({}, params, { - onSelect: this.onOptionSelect, - selectValue: this.onOptionSelect - })); - }, - - onInputChange: function onInputChange(input) { - var onInputChange = this.props.onInputChange; - - if (onInputChange) { - onInputChange(input); - } - - // This value may be needed in between Select mounts (when this.select is null) - this.inputValue = input; - }, - - onInputKeyDown: function onInputKeyDown(event) { - var _props3 = this.props; - var shouldKeyDownEventCreateNewOption = _props3.shouldKeyDownEventCreateNewOption; - var onInputKeyDown = _props3.onInputKeyDown; - - var focusedOption = this.select.getFocusedOption(); - - if (focusedOption && focusedOption === this._createPlaceholderOption && shouldKeyDownEventCreateNewOption({ keyCode: event.keyCode })) { - this.createNewOption(); - - // Prevent decorated Select from doing anything additional with this keyDown event - event.preventDefault(); - } else if (onInputKeyDown) { - onInputKeyDown(event); - } - }, - - onOptionSelect: function onOptionSelect(option, event) { - if (option === this._createPlaceholderOption) { - this.createNewOption(); - } else { - this.select.selectValue(option); - } - }, - - render: function render() { - var _this = this; - - var _props4 = this.props; - var newOptionCreator = _props4.newOptionCreator; - var shouldKeyDownEventCreateNewOption = _props4.shouldKeyDownEventCreateNewOption; - - var restProps = _objectWithoutProperties(_props4, ['newOptionCreator', 'shouldKeyDownEventCreateNewOption']); - - var children = this.props.children; - - // We can't use destructuring default values to set the children, - // because it won't apply work if `children` is null. A falsy check is - // more reliable in real world use-cases. - if (!children) { - children = defaultChildren; - } - - var props = _extends({}, restProps, { - allowCreate: true, - filterOptions: this.filterOptions, - menuRenderer: this.menuRenderer, - onInputChange: this.onInputChange, - onInputKeyDown: this.onInputKeyDown, - ref: function ref(_ref) { - _this.select = _ref; - - // These values may be needed in between Select mounts (when this.select is null) - if (_ref) { - _this.labelKey = _ref.props.labelKey; - _this.valueKey = _ref.props.valueKey; - } - } - }); - - return children(props); - } -}); - -function defaultChildren(props) { - return _react2['default'].createElement(_Select2['default'], props); -}; - -function isOptionUnique(_ref3) { - var option = _ref3.option; - var options = _ref3.options; - var labelKey = _ref3.labelKey; - var valueKey = _ref3.valueKey; - - return options.filter(function (existingOption) { - return existingOption[labelKey] === option[labelKey] || existingOption[valueKey] === option[valueKey]; - }).length === 0; -}; - -function isValidNewOption(_ref4) { - var label = _ref4.label; - - return !!label; -}; - -function newOptionCreator(_ref5) { - var label = _ref5.label; - var labelKey = _ref5.labelKey; - var valueKey = _ref5.valueKey; - - var option = {}; - option[valueKey] = label; - option[labelKey] = label; - option.className = 'Select-create-option-placeholder'; - return option; -}; - -function promptTextCreator(label) { - return 'Create option "' + label + '"'; -} - -function shouldKeyDownEventCreateNewOption(_ref6) { - var keyCode = _ref6.keyCode; - - switch (keyCode) { - case 9: // TAB - case 13: // ENTER - case 188: - // COMMA - return true; - } - - return false; -}; - -module.exports = Creatable; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./Select":5,"./utils/defaultFilterOptions":9,"./utils/defaultMenuRenderer":10}],4:[function(require,module,exports){ -(function (global){ -'use strict'; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = (typeof window !== "undefined" ? window['classNames'] : typeof global !== "undefined" ? global['classNames'] : null); - -var _classnames2 = _interopRequireDefault(_classnames); - -var Option = _react2['default'].createClass({ - displayName: 'Option', - - propTypes: { - children: _react2['default'].PropTypes.node, - className: _react2['default'].PropTypes.string, // className (based on mouse position) - instancePrefix: _react2['default'].PropTypes.string.isRequired, // unique prefix for the ids (used for aria) - isDisabled: _react2['default'].PropTypes.bool, // the option is disabled - isFocused: _react2['default'].PropTypes.bool, // the option is focused - isSelected: _react2['default'].PropTypes.bool, // the option is selected - onFocus: _react2['default'].PropTypes.func, // method to handle mouseEnter on option element - onSelect: _react2['default'].PropTypes.func, // method to handle click on option element - onUnfocus: _react2['default'].PropTypes.func, // method to handle mouseLeave on option element - option: _react2['default'].PropTypes.object.isRequired, // object that is base for that option - optionIndex: _react2['default'].PropTypes.number }, - // index of the option, used to generate unique ids for aria - blockEvent: function blockEvent(event) { - event.preventDefault(); - event.stopPropagation(); - if (event.target.tagName !== 'A' || !('href' in event.target)) { - return; - } - if (event.target.target) { - window.open(event.target.href, event.target.target); - } else { - window.location.href = event.target.href; - } - }, - - handleMouseDown: function handleMouseDown(event) { - event.preventDefault(); - event.stopPropagation(); - this.props.onSelect(this.props.option, event); - }, - - handleMouseEnter: function handleMouseEnter(event) { - this.onFocus(event); - }, - - handleMouseMove: function handleMouseMove(event) { - this.onFocus(event); - }, - - handleTouchEnd: function handleTouchEnd(event) { - // Check if the view is being dragged, In this case - // we don't want to fire the click event (because the user only wants to scroll) - if (this.dragging) return; - - this.handleMouseDown(event); - }, - - handleTouchMove: function handleTouchMove(event) { - // Set a flag that the view is being dragged - this.dragging = true; - }, - - handleTouchStart: function handleTouchStart(event) { - // Set a flag that the view is not being dragged - this.dragging = false; - }, - - onFocus: function onFocus(event) { - if (!this.props.isFocused) { - this.props.onFocus(this.props.option, event); - } - }, - render: function render() { - var _props = this.props; - var option = _props.option; - var instancePrefix = _props.instancePrefix; - var optionIndex = _props.optionIndex; - - var className = (0, _classnames2['default'])(this.props.className, option.className); - - return option.disabled ? _react2['default'].createElement( - 'div', - { className: className, - onMouseDown: this.blockEvent, - onClick: this.blockEvent }, - this.props.children - ) : _react2['default'].createElement( - 'div', - { className: className, - style: option.style, - role: 'option', - onMouseDown: this.handleMouseDown, - onMouseEnter: this.handleMouseEnter, - onMouseMove: this.handleMouseMove, - onTouchStart: this.handleTouchStart, - onTouchMove: this.handleTouchMove, - onTouchEnd: this.handleTouchEnd, - id: instancePrefix + '-option-' + optionIndex, - title: option.title }, - this.props.children - ); - } -}); - -module.exports = Option; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],5:[function(require,module,exports){ -(function (global){ -/*! - Copyright (c) 2016 Jed Watson. - Licensed under the MIT License (MIT), see - http://jedwatson.github.io/react-select -*/ - -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = (typeof window !== "undefined" ? window['ReactDOM'] : typeof global !== "undefined" ? global['ReactDOM'] : null); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _reactInputAutosize = (typeof window !== "undefined" ? window['AutosizeInput'] : typeof global !== "undefined" ? global['AutosizeInput'] : null); - -var _reactInputAutosize2 = _interopRequireDefault(_reactInputAutosize); - -var _classnames = (typeof window !== "undefined" ? window['classNames'] : typeof global !== "undefined" ? global['classNames'] : null); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _utilsDefaultArrowRenderer = require('./utils/defaultArrowRenderer'); - -var _utilsDefaultArrowRenderer2 = _interopRequireDefault(_utilsDefaultArrowRenderer); - -var _utilsDefaultFilterOptions = require('./utils/defaultFilterOptions'); - -var _utilsDefaultFilterOptions2 = _interopRequireDefault(_utilsDefaultFilterOptions); - -var _utilsDefaultMenuRenderer = require('./utils/defaultMenuRenderer'); - -var _utilsDefaultMenuRenderer2 = _interopRequireDefault(_utilsDefaultMenuRenderer); - -var _utilsDefaultClearRenderer = require('./utils/defaultClearRenderer'); - -var _utilsDefaultClearRenderer2 = _interopRequireDefault(_utilsDefaultClearRenderer); - -var _Async = require('./Async'); - -var _Async2 = _interopRequireDefault(_Async); - -var _AsyncCreatable = require('./AsyncCreatable'); - -var _AsyncCreatable2 = _interopRequireDefault(_AsyncCreatable); - -var _Creatable = require('./Creatable'); - -var _Creatable2 = _interopRequireDefault(_Creatable); - -var _Option = require('./Option'); - -var _Option2 = _interopRequireDefault(_Option); - -var _Value = require('./Value'); - -var _Value2 = _interopRequireDefault(_Value); - -function stringifyValue(value) { - var valueType = typeof value; - if (valueType === 'string') { - return value; - } else if (valueType === 'object') { - return JSON.stringify(value); - } else if (valueType === 'number' || valueType === 'boolean') { - return String(value); - } else { - return ''; - } -} - -var stringOrNode = _react2['default'].PropTypes.oneOfType([_react2['default'].PropTypes.string, _react2['default'].PropTypes.node]); - -var instanceId = 1; - -var Select = _react2['default'].createClass({ - - displayName: 'Select', - - propTypes: { - addLabelText: _react2['default'].PropTypes.string, // placeholder displayed when you want to add a label on a multi-value input - 'aria-label': _react2['default'].PropTypes.string, // Aria label (for assistive tech) - 'aria-labelledby': _react2['default'].PropTypes.string, // HTML ID of an element that should be used as the label (for assistive tech) - arrowRenderer: _react2['default'].PropTypes.func, // Create drop-down caret element - autoBlur: _react2['default'].PropTypes.bool, // automatically blur the component when an option is selected - autofocus: _react2['default'].PropTypes.bool, // autofocus the component on mount - autosize: _react2['default'].PropTypes.bool, // whether to enable autosizing or not - backspaceRemoves: _react2['default'].PropTypes.bool, // whether backspace removes an item if there is no text input - backspaceToRemoveMessage: _react2['default'].PropTypes.string, // Message to use for screenreaders to press backspace to remove the current item - {label} is replaced with the item label - className: _react2['default'].PropTypes.string, // className for the outer element - clearAllText: stringOrNode, // title for the "clear" control when multi: true - clearRenderer: _react2['default'].PropTypes.func, // create clearable x element - clearValueText: stringOrNode, // title for the "clear" control - clearable: _react2['default'].PropTypes.bool, // should it be possible to reset value - deleteRemoves: _react2['default'].PropTypes.bool, // whether backspace removes an item if there is no text input - delimiter: _react2['default'].PropTypes.string, // delimiter to use to join multiple values for the hidden field value - disabled: _react2['default'].PropTypes.bool, // whether the Select is disabled or not - escapeClearsValue: _react2['default'].PropTypes.bool, // whether escape clears the value when the menu is closed - filterOption: _react2['default'].PropTypes.func, // method to filter a single option (option, filterString) - filterOptions: _react2['default'].PropTypes.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values]) - ignoreAccents: _react2['default'].PropTypes.bool, // whether to strip diacritics when filtering - ignoreCase: _react2['default'].PropTypes.bool, // whether to perform case-insensitive filtering - inputProps: _react2['default'].PropTypes.object, // custom attributes for the Input - inputRenderer: _react2['default'].PropTypes.func, // returns a custom input component - instanceId: _react2['default'].PropTypes.string, // set the components instanceId - isLoading: _react2['default'].PropTypes.bool, // whether the Select is loading externally or not (such as options being loaded) - joinValues: _react2['default'].PropTypes.bool, // joins multiple values into a single form field with the delimiter (legacy mode) - labelKey: _react2['default'].PropTypes.string, // path of the label value in option objects - matchPos: _react2['default'].PropTypes.string, // (any|start) match the start or entire string when filtering - matchProp: _react2['default'].PropTypes.string, // (any|label|value) which option property to filter on - menuBuffer: _react2['default'].PropTypes.number, // optional buffer (in px) between the bottom of the viewport and the bottom of the menu - menuContainerStyle: _react2['default'].PropTypes.object, // optional style to apply to the menu container - menuRenderer: _react2['default'].PropTypes.func, // renders a custom menu with options - menuStyle: _react2['default'].PropTypes.object, // optional style to apply to the menu - multi: _react2['default'].PropTypes.bool, // multi-value input - name: _react2['default'].PropTypes.string, // generates a hidden <input /> tag with this field name for html forms - noResultsText: stringOrNode, // placeholder displayed when there are no matching search results - onBlur: _react2['default'].PropTypes.func, // onBlur handler: function (event) {} - onBlurResetsInput: _react2['default'].PropTypes.bool, // whether input is cleared on blur - onChange: _react2['default'].PropTypes.func, // onChange handler: function (newValue) {} - onClose: _react2['default'].PropTypes.func, // fires when the menu is closed - onCloseResetsInput: _react2['default'].PropTypes.bool, // whether input is cleared when menu is closed through the arrow - onFocus: _react2['default'].PropTypes.func, // onFocus handler: function (event) {} - onInputChange: _react2['default'].PropTypes.func, // onInputChange handler: function (inputValue) {} - onInputKeyDown: _react2['default'].PropTypes.func, // input keyDown handler: function (event) {} - onMenuScrollToBottom: _react2['default'].PropTypes.func, // fires when the menu is scrolled to the bottom; can be used to paginate options - onOpen: _react2['default'].PropTypes.func, // fires when the menu is opened - onValueClick: _react2['default'].PropTypes.func, // onClick handler for value labels: function (value, event) {} - openAfterFocus: _react2['default'].PropTypes.bool, // boolean to enable opening dropdown when focused - openOnFocus: _react2['default'].PropTypes.bool, // always open options menu on focus - optionClassName: _react2['default'].PropTypes.string, // additional class(es) to apply to the <Option /> elements - optionComponent: _react2['default'].PropTypes.func, // option component to render in dropdown - optionRenderer: _react2['default'].PropTypes.func, // optionRenderer: function (option) {} - options: _react2['default'].PropTypes.array, // array of options - pageSize: _react2['default'].PropTypes.number, // number of entries to page when using page up/down keys - placeholder: stringOrNode, // field placeholder, displayed when there's no value - required: _react2['default'].PropTypes.bool, // applies HTML5 required attribute when needed - resetValue: _react2['default'].PropTypes.any, // value to use when you clear the control - scrollMenuIntoView: _react2['default'].PropTypes.bool, // boolean to enable the viewport to shift so that the full menu fully visible when engaged - searchable: _react2['default'].PropTypes.bool, // whether to enable searching feature or not - simpleValue: _react2['default'].PropTypes.bool, // pass the value to onChange as a simple value (legacy pre 1.0 mode), defaults to false - style: _react2['default'].PropTypes.object, // optional style to apply to the control - tabIndex: _react2['default'].PropTypes.string, // optional tab index of the control - tabSelectsValue: _react2['default'].PropTypes.bool, // whether to treat tabbing out while focused to be value selection - value: _react2['default'].PropTypes.any, // initial field value - valueComponent: _react2['default'].PropTypes.func, // value component to render - valueKey: _react2['default'].PropTypes.string, // path of the label value in option objects - valueRenderer: _react2['default'].PropTypes.func, // valueRenderer: function (option) {} - wrapperStyle: _react2['default'].PropTypes.object }, - - // optional style to apply to the component wrapper - statics: { Async: _Async2['default'], AsyncCreatable: _AsyncCreatable2['default'], Creatable: _Creatable2['default'] }, - - getDefaultProps: function getDefaultProps() { - return { - addLabelText: 'Add "{label}"?', - arrowRenderer: _utilsDefaultArrowRenderer2['default'], - autosize: true, - backspaceRemoves: true, - backspaceToRemoveMessage: 'Press backspace to remove {label}', - clearable: true, - clearAllText: 'Clear all', - clearRenderer: _utilsDefaultClearRenderer2['default'], - clearValueText: 'Clear value', - deleteRemoves: true, - delimiter: ',', - disabled: false, - escapeClearsValue: true, - filterOptions: _utilsDefaultFilterOptions2['default'], - ignoreAccents: true, - ignoreCase: true, - inputProps: {}, - isLoading: false, - joinValues: false, - labelKey: 'label', - matchPos: 'any', - matchProp: 'any', - menuBuffer: 0, - menuRenderer: _utilsDefaultMenuRenderer2['default'], - multi: false, - noResultsText: 'No results found', - onBlurResetsInput: true, - onCloseResetsInput: true, - openAfterFocus: false, - optionComponent: _Option2['default'], - pageSize: 5, - placeholder: 'Select...', - required: false, - scrollMenuIntoView: true, - searchable: true, - simpleValue: false, - tabSelectsValue: true, - valueComponent: _Value2['default'], - valueKey: 'value' - }; - }, - - getInitialState: function getInitialState() { - return { - inputValue: '', - isFocused: false, - isOpen: false, - isPseudoFocused: false, - required: false - }; - }, - - componentWillMount: function componentWillMount() { - this._instancePrefix = 'react-select-' + (this.props.instanceId || ++instanceId) + '-'; - var valueArray = this.getValueArray(this.props.value); - - if (this.props.required) { - this.setState({ - required: this.handleRequired(valueArray[0], this.props.multi) - }); - } - }, - - componentDidMount: function componentDidMount() { - if (this.props.autofocus) { - this.focus(); - } - }, - - componentWillReceiveProps: function componentWillReceiveProps(nextProps) { - var valueArray = this.getValueArray(nextProps.value, nextProps); - - if (nextProps.required) { - this.setState({ - required: this.handleRequired(valueArray[0], nextProps.multi) - }); - } - }, - - componentWillUpdate: function componentWillUpdate(nextProps, nextState) { - if (nextState.isOpen !== this.state.isOpen) { - this.toggleTouchOutsideEvent(nextState.isOpen); - var handler = nextState.isOpen ? nextProps.onOpen : nextProps.onClose; - handler && handler(); - } - }, - - componentDidUpdate: function componentDidUpdate(prevProps, prevState) { - // focus to the selected option - if (this.menu && this.focused && this.state.isOpen && !this.hasScrolledToOption) { - var focusedOptionNode = _reactDom2['default'].findDOMNode(this.focused); - var menuNode = _reactDom2['default'].findDOMNode(this.menu); - menuNode.scrollTop = focusedOptionNode.offsetTop; - this.hasScrolledToOption = true; - } else if (!this.state.isOpen) { - this.hasScrolledToOption = false; - } - - if (this._scrollToFocusedOptionOnUpdate && this.focused && this.menu) { - this._scrollToFocusedOptionOnUpdate = false; - var focusedDOM = _reactDom2['default'].findDOMNode(this.focused); - var menuDOM = _reactDom2['default'].findDOMNode(this.menu); - var focusedRect = focusedDOM.getBoundingClientRect(); - var menuRect = menuDOM.getBoundingClientRect(); - if (focusedRect.bottom > menuRect.bottom || focusedRect.top < menuRect.top) { - menuDOM.scrollTop = focusedDOM.offsetTop + focusedDOM.clientHeight - menuDOM.offsetHeight; - } - } - if (this.props.scrollMenuIntoView && this.menuContainer) { - var menuContainerRect = this.menuContainer.getBoundingClientRect(); - if (window.innerHeight < menuContainerRect.bottom + this.props.menuBuffer) { - window.scrollBy(0, menuContainerRect.bottom + this.props.menuBuffer - window.innerHeight); - } - } - if (prevProps.disabled !== this.props.disabled) { - this.setState({ isFocused: false }); // eslint-disable-line react/no-did-update-set-state - this.closeMenu(); - } - }, - - componentWillUnmount: function componentWillUnmount() { - if (!document.removeEventListener && document.detachEvent) { - document.detachEvent('ontouchstart', this.handleTouchOutside); - } else { - document.removeEventListener('touchstart', this.handleTouchOutside); - } - }, - - toggleTouchOutsideEvent: function toggleTouchOutsideEvent(enabled) { - if (enabled) { - if (!document.addEventListener && document.attachEvent) { - document.attachEvent('ontouchstart', this.handleTouchOutside); - } else { - document.addEventListener('touchstart', this.handleTouchOutside); - } - } else { - if (!document.removeEventListener && document.detachEvent) { - document.detachEvent('ontouchstart', this.handleTouchOutside); - } else { - document.removeEventListener('touchstart', this.handleTouchOutside); - } - } - }, - - handleTouchOutside: function handleTouchOutside(event) { - // handle touch outside on ios to dismiss menu - if (this.wrapper && !this.wrapper.contains(event.target)) { - this.closeMenu(); - } - }, - - focus: function focus() { - if (!this.input) return; - this.input.focus(); - - if (this.props.openAfterFocus) { - this.setState({ - isOpen: true - }); - } - }, - - blurInput: function blurInput() { - if (!this.input) return; - this.input.blur(); - }, - - handleTouchMove: function handleTouchMove(event) { - // Set a flag that the view is being dragged - this.dragging = true; - }, - - handleTouchStart: function handleTouchStart(event) { - // Set a flag that the view is not being dragged - this.dragging = false; - }, - - handleTouchEnd: function handleTouchEnd(event) { - // Check if the view is being dragged, In this case - // we don't want to fire the click event (because the user only wants to scroll) - if (this.dragging) return; - - // Fire the mouse events - this.handleMouseDown(event); - }, - - handleTouchEndClearValue: function handleTouchEndClearValue(event) { - // Check if the view is being dragged, In this case - // we don't want to fire the click event (because the user only wants to scroll) - if (this.dragging) return; - - // Clear the value - this.clearValue(event); - }, - - handleMouseDown: function handleMouseDown(event) { - // if the event was triggered by a mousedown and not the primary - // button, or if the component is disabled, ignore it. - if (this.props.disabled || event.type === 'mousedown' && event.button !== 0) { - return; - } - - if (event.target.tagName === 'INPUT') { - return; - } - - // prevent default event handlers - event.stopPropagation(); - event.preventDefault(); - - // for the non-searchable select, toggle the menu - if (!this.props.searchable) { - this.focus(); - return this.setState({ - isOpen: !this.state.isOpen - }); - } - - if (this.state.isFocused) { - // On iOS, we can get into a state where we think the input is focused but it isn't really, - // since iOS ignores programmatic calls to input.focus() that weren't triggered by a click event. - // Call focus() again here to be safe. - this.focus(); - - var input = this.input; - if (typeof input.getInput === 'function') { - // Get the actual DOM input if the ref is an <AutosizeInput /> component - input = input.getInput(); - } - - // clears the value so that the cursor will be at the end of input when the component re-renders - input.value = ''; - - // if the input is focused, ensure the menu is open - this.setState({ - isOpen: true, - isPseudoFocused: false - }); - } else { - // otherwise, focus the input and open the menu - this._openAfterFocus = true; - this.focus(); - } - }, - - handleMouseDownOnArrow: function handleMouseDownOnArrow(event) { - // if the event was triggered by a mousedown and not the primary - // button, or if the component is disabled, ignore it. - if (this.props.disabled || event.type === 'mousedown' && event.button !== 0) { - return; - } - // If the menu isn't open, let the event bubble to the main handleMouseDown - if (!this.state.isOpen) { - return; - } - // prevent default event handlers - event.stopPropagation(); - event.preventDefault(); - // close the menu - this.closeMenu(); - }, - - handleMouseDownOnMenu: function handleMouseDownOnMenu(event) { - // if the event was triggered by a mousedown and not the primary - // button, or if the component is disabled, ignore it. - if (this.props.disabled || event.type === 'mousedown' && event.button !== 0) { - return; - } - event.stopPropagation(); - event.preventDefault(); - - this._openAfterFocus = true; - this.focus(); - }, - - closeMenu: function closeMenu() { - if (this.props.onCloseResetsInput) { - this.setState({ - isOpen: false, - isPseudoFocused: this.state.isFocused && !this.props.multi, - inputValue: '' - }); - } else { - this.setState({ - isOpen: false, - isPseudoFocused: this.state.isFocused && !this.props.multi, - inputValue: this.state.inputValue - }); - } - this.hasScrolledToOption = false; - }, - - handleInputFocus: function handleInputFocus(event) { - if (this.props.disabled) return; - var isOpen = this.state.isOpen || this._openAfterFocus || this.props.openOnFocus; - if (this.props.onFocus) { - this.props.onFocus(event); - } - this.setState({ - isFocused: true, - isOpen: isOpen - }); - this._openAfterFocus = false; - }, - - handleInputBlur: function handleInputBlur(event) { - // The check for menu.contains(activeElement) is necessary to prevent IE11's scrollbar from closing the menu in certain contexts. - if (this.menu && (this.menu === document.activeElement || this.menu.contains(document.activeElement))) { - this.focus(); - return; - } - - if (this.props.onBlur) { - this.props.onBlur(event); - } - var onBlurredState = { - isFocused: false, - isOpen: false, - isPseudoFocused: false - }; - if (this.props.onBlurResetsInput) { - onBlurredState.inputValue = ''; - } - this.setState(onBlurredState); - }, - - handleInputChange: function handleInputChange(event) { - var newInputValue = event.target.value; - - if (this.state.inputValue !== event.target.value && this.props.onInputChange) { - var nextState = this.props.onInputChange(newInputValue); - // Note: != used deliberately here to catch undefined and null - if (nextState != null && typeof nextState !== 'object') { - newInputValue = '' + nextState; - } - } - - this.setState({ - isOpen: true, - isPseudoFocused: false, - inputValue: newInputValue - }); - }, - - handleKeyDown: function handleKeyDown(event) { - if (this.props.disabled) return; - - if (typeof this.props.onInputKeyDown === 'function') { - this.props.onInputKeyDown(event); - if (event.defaultPrevented) { - return; - } - } - - switch (event.keyCode) { - case 8: - // backspace - if (!this.state.inputValue && this.props.backspaceRemoves) { - event.preventDefault(); - this.popValue(); - } - return; - case 9: - // tab - if (event.shiftKey || !this.state.isOpen || !this.props.tabSelectsValue) { - return; - } - this.selectFocusedOption(); - return; - case 13: - // enter - if (!this.state.isOpen) return; - event.stopPropagation(); - this.selectFocusedOption(); - break; - case 27: - // escape - if (this.state.isOpen) { - this.closeMenu(); - event.stopPropagation(); - } else if (this.props.clearable && this.props.escapeClearsValue) { - this.clearValue(event); - event.stopPropagation(); - } - break; - case 38: - // up - this.focusPreviousOption(); - break; - case 40: - // down - this.focusNextOption(); - break; - case 33: - // page up - this.focusPageUpOption(); - break; - case 34: - // page down - this.focusPageDownOption(); - break; - case 35: - // end key - if (event.shiftKey) { - return; - } - this.focusEndOption(); - break; - case 36: - // home key - if (event.shiftKey) { - return; - } - this.focusStartOption(); - break; - case 46: - // backspace - if (!this.state.inputValue && this.props.deleteRemoves) { - event.preventDefault(); - this.popValue(); - } - return; - default: - return; - } - event.preventDefault(); - }, - - handleValueClick: function handleValueClick(option, event) { - if (!this.props.onValueClick) return; - this.props.onValueClick(option, event); - }, - - handleMenuScroll: function handleMenuScroll(event) { - if (!this.props.onMenuScrollToBottom) return; - var target = event.target; - - if (target.scrollHeight > target.offsetHeight && !(target.scrollHeight - target.offsetHeight - target.scrollTop)) { - this.props.onMenuScrollToBottom(); - } - }, - - handleRequired: function handleRequired(value, multi) { - if (!value) return true; - return multi ? value.length === 0 : Object.keys(value).length === 0; - }, - - getOptionLabel: function getOptionLabel(op) { - return op[this.props.labelKey]; - }, - - /** - * Turns a value into an array from the given options - * @param {String|Number|Array} value - the value of the select input - * @param {Object} nextProps - optionally specify the nextProps so the returned array uses the latest configuration - * @returns {Array} the value of the select represented in an array - */ - getValueArray: function getValueArray(value, nextProps) { - var _this = this; - - /** support optionally passing in the `nextProps` so `componentWillReceiveProps` updates will function as expected */ - var props = typeof nextProps === 'object' ? nextProps : this.props; - if (props.multi) { - if (typeof value === 'string') value = value.split(props.delimiter); - if (!Array.isArray(value)) { - if (value === null || value === undefined) return []; - value = [value]; - } - return value.map(function (value) { - return _this.expandValue(value, props); - }).filter(function (i) { - return i; - }); - } - var expandedValue = this.expandValue(value, props); - return expandedValue ? [expandedValue] : []; - }, - - /** - * Retrieve a value from the given options and valueKey - * @param {String|Number|Array} value - the selected value(s) - * @param {Object} props - the Select component's props (or nextProps) - */ - expandValue: function expandValue(value, props) { - var valueType = typeof value; - if (valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean') return value; - var options = props.options; - var valueKey = props.valueKey; - - if (!options) return; - for (var i = 0; i < options.length; i++) { - if (options[i][valueKey] === value) return options[i]; - } - }, - - setValue: function setValue(value) { - var _this2 = this; - - if (this.props.autoBlur) { - this.blurInput(); - } - if (!this.props.onChange) return; - if (this.props.required) { - var required = this.handleRequired(value, this.props.multi); - this.setState({ required: required }); - } - if (this.props.simpleValue && value) { - value = this.props.multi ? value.map(function (i) { - return i[_this2.props.valueKey]; - }).join(this.props.delimiter) : value[this.props.valueKey]; - } - this.props.onChange(value); - }, - - selectValue: function selectValue(value) { - var _this3 = this; - - //NOTE: update value in the callback to make sure the input value is empty so that there are no styling issues (Chrome had issue otherwise) - this.hasScrolledToOption = false; - if (this.props.multi) { - this.setState({ - inputValue: '', - focusedIndex: null - }, function () { - _this3.addValue(value); - }); - } else { - this.setState({ - isOpen: false, - inputValue: '', - isPseudoFocused: this.state.isFocused - }, function () { - _this3.setValue(value); - }); - } - }, - - addValue: function addValue(value) { - var valueArray = this.getValueArray(this.props.value); - var visibleOptions = this._visibleOptions.filter(function (val) { - return !val.disabled; - }); - var lastValueIndex = visibleOptions.indexOf(value); - this.setValue(valueArray.concat(value)); - if (visibleOptions.length - 1 === lastValueIndex) { - // the last option was selected; focus the second-last one - this.focusOption(visibleOptions[lastValueIndex - 1]); - } else if (visibleOptions.length > lastValueIndex) { - // focus the option below the selected one - this.focusOption(visibleOptions[lastValueIndex + 1]); - } - }, - - popValue: function popValue() { - var valueArray = this.getValueArray(this.props.value); - if (!valueArray.length) return; - if (valueArray[valueArray.length - 1].clearableValue === false) return; - this.setValue(valueArray.slice(0, valueArray.length - 1)); - }, - - removeValue: function removeValue(value) { - var valueArray = this.getValueArray(this.props.value); - this.setValue(valueArray.filter(function (i) { - return i !== value; - })); - this.focus(); - }, - - clearValue: function clearValue(event) { - // if the event was triggered by a mousedown and not the primary - // button, ignore it. - if (event && event.type === 'mousedown' && event.button !== 0) { - return; - } - event.stopPropagation(); - event.preventDefault(); - this.setValue(this.getResetValue()); - this.setState({ - isOpen: false, - inputValue: '' - }, this.focus); - }, - - getResetValue: function getResetValue() { - if (this.props.resetValue !== undefined) { - return this.props.resetValue; - } else if (this.props.multi) { - return []; - } else { - return null; - } - }, - - focusOption: function focusOption(option) { - this.setState({ - focusedOption: option - }); - }, - - focusNextOption: function focusNextOption() { - this.focusAdjacentOption('next'); - }, - - focusPreviousOption: function focusPreviousOption() { - this.focusAdjacentOption('previous'); - }, - - focusPageUpOption: function focusPageUpOption() { - this.focusAdjacentOption('page_up'); - }, - - focusPageDownOption: function focusPageDownOption() { - this.focusAdjacentOption('page_down'); - }, - - focusStartOption: function focusStartOption() { - this.focusAdjacentOption('start'); - }, - - focusEndOption: function focusEndOption() { - this.focusAdjacentOption('end'); - }, - - focusAdjacentOption: function focusAdjacentOption(dir) { - var options = this._visibleOptions.map(function (option, index) { - return { option: option, index: index }; - }).filter(function (option) { - return !option.option.disabled; - }); - this._scrollToFocusedOptionOnUpdate = true; - if (!this.state.isOpen) { - this.setState({ - isOpen: true, - inputValue: '', - focusedOption: this._focusedOption || (options.length ? options[dir === 'next' ? 0 : options.length - 1].option : null) - }); - return; - } - if (!options.length) return; - var focusedIndex = -1; - for (var i = 0; i < options.length; i++) { - if (this._focusedOption === options[i].option) { - focusedIndex = i; - break; - } - } - if (dir === 'next' && focusedIndex !== -1) { - focusedIndex = (focusedIndex + 1) % options.length; - } else if (dir === 'previous') { - if (focusedIndex > 0) { - focusedIndex = focusedIndex - 1; - } else { - focusedIndex = options.length - 1; - } - } else if (dir === 'start') { - focusedIndex = 0; - } else if (dir === 'end') { - focusedIndex = options.length - 1; - } else if (dir === 'page_up') { - var potentialIndex = focusedIndex - this.props.pageSize; - if (potentialIndex < 0) { - focusedIndex = 0; - } else { - focusedIndex = potentialIndex; - } - } else if (dir === 'page_down') { - var potentialIndex = focusedIndex + this.props.pageSize; - if (potentialIndex > options.length - 1) { - focusedIndex = options.length - 1; - } else { - focusedIndex = potentialIndex; - } - } - - if (focusedIndex === -1) { - focusedIndex = 0; - } - - this.setState({ - focusedIndex: options[focusedIndex].index, - focusedOption: options[focusedIndex].option - }); - }, - - getFocusedOption: function getFocusedOption() { - return this._focusedOption; - }, - - getInputValue: function getInputValue() { - return this.state.inputValue; - }, - - selectFocusedOption: function selectFocusedOption() { - if (this._focusedOption) { - return this.selectValue(this._focusedOption); - } - }, - - renderLoading: function renderLoading() { - if (!this.props.isLoading) return; - return _react2['default'].createElement( - 'span', - { className: 'Select-loading-zone', 'aria-hidden': 'true' }, - _react2['default'].createElement('span', { className: 'Select-loading' }) - ); - }, - - renderValue: function renderValue(valueArray, isOpen) { - var _this4 = this; - - var renderLabel = this.props.valueRenderer || this.getOptionLabel; - var ValueComponent = this.props.valueComponent; - if (!valueArray.length) { - return !this.state.inputValue ? _react2['default'].createElement( - 'div', - { className: 'Select-placeholder' }, - this.props.placeholder - ) : null; - } - var onClick = this.props.onValueClick ? this.handleValueClick : null; - if (this.props.multi) { - return valueArray.map(function (value, i) { - return _react2['default'].createElement( - ValueComponent, - { - id: _this4._instancePrefix + '-value-' + i, - instancePrefix: _this4._instancePrefix, - disabled: _this4.props.disabled || value.clearableValue === false, - key: 'value-' + i + '-' + value[_this4.props.valueKey], - onClick: onClick, - onRemove: _this4.removeValue, - value: value - }, - renderLabel(value, i), - _react2['default'].createElement( - 'span', - { className: 'Select-aria-only' }, - ' ' - ) - ); - }); - } else if (!this.state.inputValue) { - if (isOpen) onClick = null; - return _react2['default'].createElement( - ValueComponent, - { - id: this._instancePrefix + '-value-item', - disabled: this.props.disabled, - instancePrefix: this._instancePrefix, - onClick: onClick, - value: valueArray[0] - }, - renderLabel(valueArray[0]) - ); - } - }, - - renderInput: function renderInput(valueArray, focusedOptionIndex) { - var _classNames, - _this5 = this; - - var className = (0, _classnames2['default'])('Select-input', this.props.inputProps.className); - var isOpen = !!this.state.isOpen; - - var ariaOwns = (0, _classnames2['default'])((_classNames = {}, _defineProperty(_classNames, this._instancePrefix + '-list', isOpen), _defineProperty(_classNames, this._instancePrefix + '-backspace-remove-message', this.props.multi && !this.props.disabled && this.state.isFocused && !this.state.inputValue), _classNames)); - - // TODO: Check how this project includes Object.assign() - var inputProps = _extends({}, this.props.inputProps, { - role: 'combobox', - 'aria-expanded': '' + isOpen, - 'aria-owns': ariaOwns, - 'aria-haspopup': '' + isOpen, - 'aria-activedescendant': isOpen ? this._instancePrefix + '-option-' + focusedOptionIndex : this._instancePrefix + '-value', - 'aria-labelledby': this.props['aria-labelledby'], - 'aria-label': this.props['aria-label'], - className: className, - tabIndex: this.props.tabIndex, - onBlur: this.handleInputBlur, - onChange: this.handleInputChange, - onFocus: this.handleInputFocus, - ref: function ref(_ref) { - return _this5.input = _ref; - }, - required: this.state.required, - value: this.state.inputValue - }); - - if (this.props.inputRenderer) { - return this.props.inputRenderer(inputProps); - } - - if (this.props.disabled || !this.props.searchable) { - var _props$inputProps = this.props.inputProps; - var inputClassName = _props$inputProps.inputClassName; - - var divProps = _objectWithoutProperties(_props$inputProps, ['inputClassName']); - - return _react2['default'].createElement('div', _extends({}, divProps, { - role: 'combobox', - 'aria-expanded': isOpen, - 'aria-owns': isOpen ? this._instancePrefix + '-list' : this._instancePrefix + '-value', - 'aria-activedescendant': isOpen ? this._instancePrefix + '-option-' + focusedOptionIndex : this._instancePrefix + '-value', - className: className, - tabIndex: this.props.tabIndex || 0, - onBlur: this.handleInputBlur, - onFocus: this.handleInputFocus, - ref: function (ref) { - return _this5.input = ref; - }, - 'aria-readonly': '' + !!this.props.disabled, - style: { border: 0, width: 1, display: 'inline-block' } })); - } - - if (this.props.autosize) { - return _react2['default'].createElement(_reactInputAutosize2['default'], _extends({}, inputProps, { minWidth: '5' })); - } - return _react2['default'].createElement( - 'div', - { className: className }, - _react2['default'].createElement('input', inputProps) - ); - }, - - renderClear: function renderClear() { - if (!this.props.clearable || !this.props.value || this.props.value === 0 || this.props.multi && !this.props.value.length || this.props.disabled || this.props.isLoading) return; - var clear = this.props.clearRenderer(); - - return _react2['default'].createElement( - 'span', - { className: 'Select-clear-zone', title: this.props.multi ? this.props.clearAllText : this.props.clearValueText, - 'aria-label': this.props.multi ? this.props.clearAllText : this.props.clearValueText, - onMouseDown: this.clearValue, - onTouchStart: this.handleTouchStart, - onTouchMove: this.handleTouchMove, - onTouchEnd: this.handleTouchEndClearValue - }, - clear - ); - }, - - renderArrow: function renderArrow() { - var onMouseDown = this.handleMouseDownOnArrow; - var isOpen = this.state.isOpen; - var arrow = this.props.arrowRenderer({ onMouseDown: onMouseDown, isOpen: isOpen }); - - return _react2['default'].createElement( - 'span', - { - className: 'Select-arrow-zone', - onMouseDown: onMouseDown - }, - arrow - ); - }, - - filterOptions: function filterOptions(excludeOptions) { - var filterValue = this.state.inputValue; - var options = this.props.options || []; - if (this.props.filterOptions) { - // Maintain backwards compatibility with boolean attribute - var filterOptions = typeof this.props.filterOptions === 'function' ? this.props.filterOptions : _utilsDefaultFilterOptions2['default']; - - return filterOptions(options, filterValue, excludeOptions, { - filterOption: this.props.filterOption, - ignoreAccents: this.props.ignoreAccents, - ignoreCase: this.props.ignoreCase, - labelKey: this.props.labelKey, - matchPos: this.props.matchPos, - matchProp: this.props.matchProp, - valueKey: this.props.valueKey - }); - } else { - return options; - } - }, - - onOptionRef: function onOptionRef(ref, isFocused) { - if (isFocused) { - this.focused = ref; - } - }, - - renderMenu: function renderMenu(options, valueArray, focusedOption) { - if (options && options.length) { - return this.props.menuRenderer({ - focusedOption: focusedOption, - focusOption: this.focusOption, - instancePrefix: this._instancePrefix, - labelKey: this.props.labelKey, - onFocus: this.focusOption, - onSelect: this.selectValue, - optionClassName: this.props.optionClassName, - optionComponent: this.props.optionComponent, - optionRenderer: this.props.optionRenderer || this.getOptionLabel, - options: options, - selectValue: this.selectValue, - valueArray: valueArray, - valueKey: this.props.valueKey, - onOptionRef: this.onOptionRef - }); - } else if (this.props.noResultsText) { - return _react2['default'].createElement( - 'div', - { className: 'Select-noresults' }, - this.props.noResultsText - ); - } else { - return null; - } - }, - - renderHiddenField: function renderHiddenField(valueArray) { - var _this6 = this; - - if (!this.props.name) return; - if (this.props.joinValues) { - var value = valueArray.map(function (i) { - return stringifyValue(i[_this6.props.valueKey]); - }).join(this.props.delimiter); - return _react2['default'].createElement('input', { - type: 'hidden', - ref: function (ref) { - return _this6.value = ref; - }, - name: this.props.name, - value: value, - disabled: this.props.disabled }); - } - return valueArray.map(function (item, index) { - return _react2['default'].createElement('input', { key: 'hidden.' + index, - type: 'hidden', - ref: 'value' + index, - name: _this6.props.name, - value: stringifyValue(item[_this6.props.valueKey]), - disabled: _this6.props.disabled }); - }); - }, - - getFocusableOptionIndex: function getFocusableOptionIndex(selectedOption) { - var options = this._visibleOptions; - if (!options.length) return null; - - var focusedOption = this.state.focusedOption || selectedOption; - if (focusedOption && !focusedOption.disabled) { - var focusedOptionIndex = options.indexOf(focusedOption); - if (focusedOptionIndex !== -1) { - return focusedOptionIndex; - } - } - - for (var i = 0; i < options.length; i++) { - if (!options[i].disabled) return i; - } - return null; - }, - - renderOuter: function renderOuter(options, valueArray, focusedOption) { - var _this7 = this; - - var menu = this.renderMenu(options, valueArray, focusedOption); - if (!menu) { - return null; - } - - return _react2['default'].createElement( - 'div', - { ref: function (ref) { - return _this7.menuContainer = ref; - }, className: 'Select-menu-outer', style: this.props.menuContainerStyle }, - _react2['default'].createElement( - 'div', - { ref: function (ref) { - return _this7.menu = ref; - }, role: 'listbox', className: 'Select-menu', id: this._instancePrefix + '-list', - style: this.props.menuStyle, - onScroll: this.handleMenuScroll, - onMouseDown: this.handleMouseDownOnMenu }, - menu - ) - ); - }, - - render: function render() { - var _this8 = this; - - var valueArray = this.getValueArray(this.props.value); - var options = this._visibleOptions = this.filterOptions(this.props.multi ? this.getValueArray(this.props.value) : null); - var isOpen = this.state.isOpen; - if (this.props.multi && !options.length && valueArray.length && !this.state.inputValue) isOpen = false; - var focusedOptionIndex = this.getFocusableOptionIndex(valueArray[0]); - - var focusedOption = null; - if (focusedOptionIndex !== null) { - focusedOption = this._focusedOption = options[focusedOptionIndex]; - } else { - focusedOption = this._focusedOption = null; - } - var className = (0, _classnames2['default'])('Select', this.props.className, { - 'Select--multi': this.props.multi, - 'Select--single': !this.props.multi, - 'is-disabled': this.props.disabled, - 'is-focused': this.state.isFocused, - 'is-loading': this.props.isLoading, - 'is-open': isOpen, - 'is-pseudo-focused': this.state.isPseudoFocused, - 'is-searchable': this.props.searchable, - 'has-value': valueArray.length - }); - - var removeMessage = null; - if (this.props.multi && !this.props.disabled && valueArray.length && !this.state.inputValue && this.state.isFocused && this.props.backspaceRemoves) { - removeMessage = _react2['default'].createElement( - 'span', - { id: this._instancePrefix + '-backspace-remove-message', className: 'Select-aria-only', 'aria-live': 'assertive' }, - this.props.backspaceToRemoveMessage.replace('{label}', valueArray[valueArray.length - 1][this.props.labelKey]) - ); - } - - return _react2['default'].createElement( - 'div', - { ref: function (ref) { - return _this8.wrapper = ref; - }, - className: className, - style: this.props.wrapperStyle }, - this.renderHiddenField(valueArray), - _react2['default'].createElement( - 'div', - { ref: function (ref) { - return _this8.control = ref; - }, - className: 'Select-control', - style: this.props.style, - onKeyDown: this.handleKeyDown, - onMouseDown: this.handleMouseDown, - onTouchEnd: this.handleTouchEnd, - onTouchStart: this.handleTouchStart, - onTouchMove: this.handleTouchMove - }, - _react2['default'].createElement( - 'span', - { className: 'Select-multi-value-wrapper', id: this._instancePrefix + '-value' }, - this.renderValue(valueArray, isOpen), - this.renderInput(valueArray, focusedOptionIndex) - ), - removeMessage, - this.renderLoading(), - this.renderClear(), - this.renderArrow() - ), - isOpen ? this.renderOuter(options, !this.props.multi ? valueArray : null, focusedOption) : null - ); - } - -}); - -exports['default'] = Select; -module.exports = exports['default']; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./Async":1,"./AsyncCreatable":2,"./Creatable":3,"./Option":4,"./Value":6,"./utils/defaultArrowRenderer":7,"./utils/defaultClearRenderer":8,"./utils/defaultFilterOptions":9,"./utils/defaultMenuRenderer":10}],6:[function(require,module,exports){ -(function (global){ -'use strict'; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -var _classnames = (typeof window !== "undefined" ? window['classNames'] : typeof global !== "undefined" ? global['classNames'] : null); - -var _classnames2 = _interopRequireDefault(_classnames); - -var Value = _react2['default'].createClass({ - - displayName: 'Value', - - propTypes: { - children: _react2['default'].PropTypes.node, - disabled: _react2['default'].PropTypes.bool, // disabled prop passed to ReactSelect - id: _react2['default'].PropTypes.string, // Unique id for the value - used for aria - onClick: _react2['default'].PropTypes.func, // method to handle click on value label - onRemove: _react2['default'].PropTypes.func, // method to handle removal of the value - value: _react2['default'].PropTypes.object.isRequired }, - - // the option object for this value - handleMouseDown: function handleMouseDown(event) { - if (event.type === 'mousedown' && event.button !== 0) { - return; - } - if (this.props.onClick) { - event.stopPropagation(); - this.props.onClick(this.props.value, event); - return; - } - if (this.props.value.href) { - event.stopPropagation(); - } - }, - - onRemove: function onRemove(event) { - event.preventDefault(); - event.stopPropagation(); - this.props.onRemove(this.props.value); - }, - - handleTouchEndRemove: function handleTouchEndRemove(event) { - // Check if the view is being dragged, In this case - // we don't want to fire the click event (because the user only wants to scroll) - if (this.dragging) return; - - // Fire the mouse events - this.onRemove(event); - }, - - handleTouchMove: function handleTouchMove(event) { - // Set a flag that the view is being dragged - this.dragging = true; - }, - - handleTouchStart: function handleTouchStart(event) { - // Set a flag that the view is not being dragged - this.dragging = false; - }, - - renderRemoveIcon: function renderRemoveIcon() { - if (this.props.disabled || !this.props.onRemove) return; - return _react2['default'].createElement( - 'span', - { className: 'Select-value-icon', - 'aria-hidden': 'true', - onMouseDown: this.onRemove, - onTouchEnd: this.handleTouchEndRemove, - onTouchStart: this.handleTouchStart, - onTouchMove: this.handleTouchMove }, - '×' - ); - }, - - renderLabel: function renderLabel() { - var className = 'Select-value-label'; - return this.props.onClick || this.props.value.href ? _react2['default'].createElement( - 'a', - { className: className, href: this.props.value.href, target: this.props.value.target, onMouseDown: this.handleMouseDown, onTouchEnd: this.handleMouseDown }, - this.props.children - ) : _react2['default'].createElement( - 'span', - { className: className, role: 'option', 'aria-selected': 'true', id: this.props.id }, - this.props.children - ); - }, - - render: function render() { - return _react2['default'].createElement( - 'div', - { className: (0, _classnames2['default'])('Select-value', this.props.value.className), - style: this.props.value.style, - title: this.props.value.title - }, - this.renderRemoveIcon(), - this.renderLabel() - ); - } - -}); - -module.exports = Value; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],7:[function(require,module,exports){ -(function (global){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports["default"] = arrowRenderer; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -function arrowRenderer(_ref) { - var onMouseDown = _ref.onMouseDown; - - return _react2["default"].createElement("span", { - className: "Select-arrow", - onMouseDown: onMouseDown - }); -} - -; -module.exports = exports["default"]; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],8:[function(require,module,exports){ -(function (global){ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -exports['default'] = clearRenderer; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -function clearRenderer() { - return _react2['default'].createElement('span', { - className: 'Select-clear', - dangerouslySetInnerHTML: { __html: '×' } - }); -} - -; -module.exports = exports['default']; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],9:[function(require,module,exports){ -'use strict'; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _stripDiacritics = require('./stripDiacritics'); - -var _stripDiacritics2 = _interopRequireDefault(_stripDiacritics); - -function filterOptions(options, filterValue, excludeOptions, props) { - var _this = this; - - if (props.ignoreAccents) { - filterValue = (0, _stripDiacritics2['default'])(filterValue); - } - - if (props.ignoreCase) { - filterValue = filterValue.toLowerCase(); - } - - if (excludeOptions) excludeOptions = excludeOptions.map(function (i) { - return i[props.valueKey]; - }); - - return options.filter(function (option) { - if (excludeOptions && excludeOptions.indexOf(option[props.valueKey]) > -1) return false; - if (props.filterOption) return props.filterOption.call(_this, option, filterValue); - if (!filterValue) return true; - var valueTest = String(option[props.valueKey]); - var labelTest = String(option[props.labelKey]); - if (props.ignoreAccents) { - if (props.matchProp !== 'label') valueTest = (0, _stripDiacritics2['default'])(valueTest); - if (props.matchProp !== 'value') labelTest = (0, _stripDiacritics2['default'])(labelTest); - } - if (props.ignoreCase) { - if (props.matchProp !== 'label') valueTest = valueTest.toLowerCase(); - if (props.matchProp !== 'value') labelTest = labelTest.toLowerCase(); - } - return props.matchPos === 'start' ? props.matchProp !== 'label' && valueTest.substr(0, filterValue.length) === filterValue || props.matchProp !== 'value' && labelTest.substr(0, filterValue.length) === filterValue : props.matchProp !== 'label' && valueTest.indexOf(filterValue) >= 0 || props.matchProp !== 'value' && labelTest.indexOf(filterValue) >= 0; - }); -} - -module.exports = filterOptions; - -},{"./stripDiacritics":11}],10:[function(require,module,exports){ -(function (global){ -'use strict'; - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -var _classnames = (typeof window !== "undefined" ? window['classNames'] : typeof global !== "undefined" ? global['classNames'] : null); - -var _classnames2 = _interopRequireDefault(_classnames); - -var _react = (typeof window !== "undefined" ? window['React'] : typeof global !== "undefined" ? global['React'] : null); - -var _react2 = _interopRequireDefault(_react); - -function menuRenderer(_ref) { - var focusedOption = _ref.focusedOption; - var instancePrefix = _ref.instancePrefix; - var labelKey = _ref.labelKey; - var onFocus = _ref.onFocus; - var onSelect = _ref.onSelect; - var optionClassName = _ref.optionClassName; - var optionComponent = _ref.optionComponent; - var optionRenderer = _ref.optionRenderer; - var options = _ref.options; - var valueArray = _ref.valueArray; - var valueKey = _ref.valueKey; - var onOptionRef = _ref.onOptionRef; - - var Option = optionComponent; - - return options.map(function (option, i) { - var isSelected = valueArray && valueArray.indexOf(option) > -1; - var isFocused = option === focusedOption; - var optionClass = (0, _classnames2['default'])(optionClassName, { - 'Select-option': true, - 'is-selected': isSelected, - 'is-focused': isFocused, - 'is-disabled': option.disabled - }); - - return _react2['default'].createElement( - Option, - { - className: optionClass, - instancePrefix: instancePrefix, - isDisabled: option.disabled, - isFocused: isFocused, - isSelected: isSelected, - key: 'option-' + i + '-' + option[valueKey], - onFocus: onFocus, - onSelect: onSelect, - option: option, - optionIndex: i, - ref: function (ref) { - onOptionRef(ref, isFocused); - } - }, - optionRenderer(option, i) - ); - }); -} - -module.exports = menuRenderer; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],11:[function(require,module,exports){ -'use strict'; - -var map = [{ 'base': 'A', 'letters': /[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g }, { 'base': 'AA', 'letters': /[\uA732]/g }, { 'base': 'AE', 'letters': /[\u00C6\u01FC\u01E2]/g }, { 'base': 'AO', 'letters': /[\uA734]/g }, { 'base': 'AU', 'letters': /[\uA736]/g }, { 'base': 'AV', 'letters': /[\uA738\uA73A]/g }, { 'base': 'AY', 'letters': /[\uA73C]/g }, { 'base': 'B', 'letters': /[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g }, { 'base': 'C', 'letters': /[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g }, { 'base': 'D', 'letters': /[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g }, { 'base': 'DZ', 'letters': /[\u01F1\u01C4]/g }, { 'base': 'Dz', 'letters': /[\u01F2\u01C5]/g }, { 'base': 'E', 'letters': /[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g }, { 'base': 'F', 'letters': /[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g }, { 'base': 'G', 'letters': /[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g }, { 'base': 'H', 'letters': /[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g }, { 'base': 'I', 'letters': /[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g }, { 'base': 'J', 'letters': /[\u004A\u24BF\uFF2A\u0134\u0248]/g }, { 'base': 'K', 'letters': /[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g }, { 'base': 'L', 'letters': /[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g }, { 'base': 'LJ', 'letters': /[\u01C7]/g }, { 'base': 'Lj', 'letters': /[\u01C8]/g }, { 'base': 'M', 'letters': /[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g }, { 'base': 'N', 'letters': /[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g }, { 'base': 'NJ', 'letters': /[\u01CA]/g }, { 'base': 'Nj', 'letters': /[\u01CB]/g }, { 'base': 'O', 'letters': /[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g }, { 'base': 'OI', 'letters': /[\u01A2]/g }, { 'base': 'OO', 'letters': /[\uA74E]/g }, { 'base': 'OU', 'letters': /[\u0222]/g }, { 'base': 'P', 'letters': /[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g }, { 'base': 'Q', 'letters': /[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g }, { 'base': 'R', 'letters': /[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g }, { 'base': 'S', 'letters': /[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g }, { 'base': 'T', 'letters': /[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g }, { 'base': 'TZ', 'letters': /[\uA728]/g }, { 'base': 'U', 'letters': /[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g }, { 'base': 'V', 'letters': /[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g }, { 'base': 'VY', 'letters': /[\uA760]/g }, { 'base': 'W', 'letters': /[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g }, { 'base': 'X', 'letters': /[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g }, { 'base': 'Y', 'letters': /[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g }, { 'base': 'Z', 'letters': /[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g }, { 'base': 'a', 'letters': /[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g }, { 'base': 'aa', 'letters': /[\uA733]/g }, { 'base': 'ae', 'letters': /[\u00E6\u01FD\u01E3]/g }, { 'base': 'ao', 'letters': /[\uA735]/g }, { 'base': 'au', 'letters': /[\uA737]/g }, { 'base': 'av', 'letters': /[\uA739\uA73B]/g }, { 'base': 'ay', 'letters': /[\uA73D]/g }, { 'base': 'b', 'letters': /[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g }, { 'base': 'c', 'letters': /[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g }, { 'base': 'd', 'letters': /[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g }, { 'base': 'dz', 'letters': /[\u01F3\u01C6]/g }, { 'base': 'e', 'letters': /[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g }, { 'base': 'f', 'letters': /[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g }, { 'base': 'g', 'letters': /[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g }, { 'base': 'h', 'letters': /[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g }, { 'base': 'hv', 'letters': /[\u0195]/g }, { 'base': 'i', 'letters': /[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g }, { 'base': 'j', 'letters': /[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g }, { 'base': 'k', 'letters': /[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g }, { 'base': 'l', 'letters': /[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g }, { 'base': 'lj', 'letters': /[\u01C9]/g }, { 'base': 'm', 'letters': /[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g }, { 'base': 'n', 'letters': /[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g }, { 'base': 'nj', 'letters': /[\u01CC]/g }, { 'base': 'o', 'letters': /[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g }, { 'base': 'oi', 'letters': /[\u01A3]/g }, { 'base': 'ou', 'letters': /[\u0223]/g }, { 'base': 'oo', 'letters': /[\uA74F]/g }, { 'base': 'p', 'letters': /[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g }, { 'base': 'q', 'letters': /[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g }, { 'base': 'r', 'letters': /[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g }, { 'base': 's', 'letters': /[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g }, { 'base': 't', 'letters': /[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g }, { 'base': 'tz', 'letters': /[\uA729]/g }, { 'base': 'u', 'letters': /[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g }, { 'base': 'v', 'letters': /[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g }, { 'base': 'vy', 'letters': /[\uA761]/g }, { 'base': 'w', 'letters': /[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g }, { 'base': 'x', 'letters': /[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g }, { 'base': 'y', 'letters': /[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g }, { 'base': 'z', 'letters': /[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g }]; - -module.exports = function stripDiacritics(str) { - for (var i = 0; i < map.length; i++) { - str = str.replace(map[i].letters, map[i].base); - } - return str; -}; - -},{}]},{},[5])(5) -}); \ No newline at end of file diff --git a/dist/react-select.min.css b/dist/react-select.min.css deleted file mode 100644 index cfb7baee9a..0000000000 --- a/dist/react-select.min.css +++ /dev/null @@ -1 +0,0 @@ -.Select,.Select-control{position:relative}.Select-control,.Select-input>input{width:100%;cursor:default;outline:0}.Select-arrow-zone,.Select-clear-zone,.Select-loading-zone{text-align:center;cursor:pointer}.Select,.Select div,.Select input,.Select span{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.Select.is-disabled>.Select-control{background-color:#f9f9f9}.Select.is-disabled>.Select-control:hover{box-shadow:none}.Select.is-disabled .Select-arrow-zone{cursor:default;pointer-events:none;opacity:.35}.Select-control{background-color:#fff;border-radius:4px;border:1px solid #ccc;color:#333;display:table;border-spacing:0;border-collapse:separate;height:36px;overflow:hidden}.is-searchable.is-focused:not(.is-open)>.Select-control,.is-searchable.is-open>.Select-control{cursor:text}.Select-control:hover{box-shadow:0 1px 0 rgba(0,0,0,.06)}.Select-control .Select-input:focus{outline:0}.is-open>.Select-control{border-bottom-right-radius:0;border-bottom-left-radius:0;background:#fff;border-color:#b3b3b3 #ccc #d9d9d9}.is-open>.Select-control .Select-arrow{top:-2px;border-color:transparent transparent #999;border-width:0 5px 5px}.is-focused:not(.is-open)>.Select-control{border-color:#007eff;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 0 3px rgba(0,126,255,.1)}.Select--single>.Select-control .Select-value,.Select-placeholder{bottom:0;color:#aaa;left:0;line-height:34px;padding-left:10px;padding-right:10px;position:absolute;right:0;top:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.has-value.Select--single>.Select-control .Select-value .Select-value-label,.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value .Select-value-label{color:#333}.has-value.Select--single>.Select-control .Select-value a.Select-value-label,.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label{cursor:pointer;text-decoration:none}.has-value.Select--single>.Select-control .Select-value a.Select-value-label:focus,.has-value.Select--single>.Select-control .Select-value a.Select-value-label:hover,.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:focus,.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value a.Select-value-label:hover{color:#007eff;outline:0;text-decoration:underline}.Select-input{height:34px;padding-left:10px;padding-right:10px;vertical-align:middle}.Select-input>input{background:none;border:0;box-shadow:none;display:inline-block;font-family:inherit;font-size:inherit;margin:0;line-height:14px;padding:8px 0 12px;-webkit-appearance:none}.Select-loading,.Select-loading-zone{width:16px;position:relative;vertical-align:middle}.is-focused .Select-input>input{cursor:text}.has-value.is-pseudo-focused .Select-input{opacity:0}.Select-control:not(.is-searchable)>.Select-input{outline:0}.Select-loading-zone{display:table-cell}.Select-loading{-webkit-animation:Select-animation-spin .4s infinite linear;-o-animation:Select-animation-spin .4s infinite linear;animation:Select-animation-spin .4s infinite linear;height:16px;box-sizing:border-box;border-radius:50%;border:2px solid #ccc;border-right-color:#333;display:inline-block}.Select-clear-zone{-webkit-animation:Select-animation-fadeIn .2s;-o-animation:Select-animation-fadeIn .2s;animation:Select-animation-fadeIn .2s;color:#999;display:table-cell;position:relative;vertical-align:middle;width:17px}.Select-clear-zone:hover{color:#D0021B}.Select-clear{display:inline-block;font-size:18px;line-height:1}.Select--multi .Select-clear-zone{width:17px}.Select-arrow-zone{display:table-cell;position:relative;vertical-align:middle;width:25px;padding-right:5px}.Select--multi .Select-multi-value-wrapper,.Select-arrow{display:inline-block}.Select-arrow{border-color:#999 transparent transparent;border-style:solid;border-width:5px 5px 2.5px;height:0;width:0;position:relative}.Select-arrow-zone:hover>.Select-arrow,.is-open .Select-arrow{border-top-color:#666}.Select .Select-aria-only{display:inline-block;height:1px;width:1px;margin:-1px;clip:rect(0,0,0,0);overflow:hidden;float:left}.Select-noresults,.Select-option{box-sizing:border-box;display:block;padding:8px 10px}@-webkit-keyframes Select-animation-fadeIn{from{opacity:0}to{opacity:1}}@keyframes Select-animation-fadeIn{from{opacity:0}to{opacity:1}}.Select-menu-outer{border-bottom-right-radius:4px;border-bottom-left-radius:4px;background-color:#fff;border:1px solid #ccc;border-top-color:#e6e6e6;box-shadow:0 1px 0 rgba(0,0,0,.06);box-sizing:border-box;margin-top:-1px;max-height:200px;position:absolute;top:100%;width:100%;z-index:1;-webkit-overflow-scrolling:touch}.Select-menu{max-height:198px;overflow-y:auto}.Select-option{background-color:#fff;color:#666;cursor:pointer}.Select-option:last-child{border-bottom-right-radius:4px;border-bottom-left-radius:4px}.Select-option.is-selected{background-color:#f5faff;background-color:rgba(0,126,255,.04);color:#333}.Select-option.is-focused{background-color:#ebf5ff;background-color:rgba(0,126,255,.08);color:#333}.Select-option.is-disabled{color:#ccc;cursor:default}.Select-noresults{color:#999;cursor:default}.Select--multi .Select-input{vertical-align:middle;margin-left:10px;padding:0}.Select--multi.has-value .Select-input{margin-left:5px}.Select--multi .Select-value{background-color:#ebf5ff;background-color:rgba(0,126,255,.08);border-radius:2px;border:1px solid #c2e0ff;border:1px solid rgba(0,126,255,.24);color:#007eff;display:inline-block;font-size:.9em;line-height:1.4;margin-left:5px;margin-top:5px;vertical-align:top}.Select--multi .Select-value-icon,.Select--multi .Select-value-label{display:inline-block;vertical-align:middle}.Select--multi .Select-value-label{border-bottom-right-radius:2px;border-top-right-radius:2px;cursor:default;padding:2px 5px}.Select--multi a.Select-value-label{color:#007eff;cursor:pointer;text-decoration:none}.Select--multi a.Select-value-label:hover{text-decoration:underline}.Select--multi .Select-value-icon{cursor:pointer;border-bottom-left-radius:2px;border-top-left-radius:2px;border-right:1px solid #c2e0ff;border-right:1px solid rgba(0,126,255,.24);padding:1px 5px 3px}.Select--multi .Select-value-icon:focus,.Select--multi .Select-value-icon:hover{background-color:#d8eafd;background-color:rgba(0,113,230,.08);color:#0071e6}.Select--multi .Select-value-icon:active{background-color:#c2e0ff;background-color:rgba(0,126,255,.24)}.Select--multi.is-disabled .Select-value{background-color:#fcfcfc;border:1px solid #e3e3e3;color:#333}.Select--multi.is-disabled .Select-value-icon{cursor:not-allowed;border-right:1px solid #e3e3e3}.Select--multi.is-disabled .Select-value-icon:active,.Select--multi.is-disabled .Select-value-icon:focus,.Select--multi.is-disabled .Select-value-icon:hover{background-color:#fcfcfc}@keyframes Select-animation-spin{to{transform:rotate(1turn)}}@-webkit-keyframes Select-animation-spin{to{-webkit-transform:rotate(1turn)}} \ No newline at end of file diff --git a/dist/react-select.min.js b/dist/react-select.min.js deleted file mode 100644 index 7d2a0b0309..0000000000 --- a/dist/react-select.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.Select=e()}}(function(){return function e(t,u,n){function s(i,a){if(!u[i]){if(!t[i]){var r="function"==typeof require&&require;if(!a&&r)return r(i,!0);if(o)return o(i,!0);var l=new Error("Cannot find module '"+i+"'");throw l.code="MODULE_NOT_FOUND",l}var p=u[i]={exports:{}};t[i][0].call(p.exports,function(e){var u=t[i][1][e];return s(u?u:e)},p,p.exports,e,t,u,n)}return u[i].exports}for(var o="function"==typeof require&&require,i=0;i<n.length;i++)s(n[i]);return s}({1:[function(e,t,u){(function(n){"use strict";function s(e){return e&&e.__esModule?e:{"default":e}}function o(e,t,u){return t in e?Object.defineProperty(e,t,{value:u,enumerable:!0,configurable:!0,writable:!0}):e[t]=u,e}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function r(e){return f["default"].createElement(E["default"],e)}Object.defineProperty(u,"__esModule",{value:!0});var l=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var u=arguments[t];for(var n in u)Object.prototype.hasOwnProperty.call(u,n)&&(e[n]=u[n])}return e},p=function(){function e(e,t){for(var u=0;u<t.length;u++){var n=t[u];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,u,n){return u&&e(t.prototype,u),n&&e(t,n),t}}(),d=function(e,t,u){for(var n=!0;n;){var s=e,o=t,i=u;n=!1,null===s&&(s=Function.prototype);var a=Object.getOwnPropertyDescriptor(s,o);if(void 0!==a){if("value"in a)return a.value;var r=a.get;if(void 0===r)return;return r.call(i)}var l=Object.getPrototypeOf(s);if(null===l)return;e=l,t=o,u=i,n=!0,a=l=void 0}},c="undefined"!=typeof window?window.React:"undefined"!=typeof n?n.React:null,f=s(c),h=e("./Select"),E=s(h),y=e("./utils/stripDiacritics"),g=s(y),b={autoload:f["default"].PropTypes.bool.isRequired,cache:f["default"].PropTypes.any,children:f["default"].PropTypes.func.isRequired,ignoreAccents:f["default"].PropTypes.bool,ignoreCase:f["default"].PropTypes.bool,loadingPlaceholder:f["default"].PropTypes.oneOfType([f["default"].PropTypes.string,f["default"].PropTypes.node]),loadOptions:f["default"].PropTypes.func.isRequired,options:c.PropTypes.array.isRequired,placeholder:f["default"].PropTypes.oneOfType([f["default"].PropTypes.string,f["default"].PropTypes.node]),noResultsText:f["default"].PropTypes.oneOfType([f["default"].PropTypes.string,f["default"].PropTypes.node]),onChange:f["default"].PropTypes.func,searchPromptText:f["default"].PropTypes.oneOfType([f["default"].PropTypes.string,f["default"].PropTypes.node]),onInputChange:f["default"].PropTypes.func,value:f["default"].PropTypes.any},v={},m={autoload:!0,cache:v,children:r,ignoreAccents:!0,ignoreCase:!0,loadingPlaceholder:"Loading...",options:[],searchPromptText:"Type to search"},C=function(e){function t(e,u){i(this,t),d(Object.getPrototypeOf(t.prototype),"constructor",this).call(this,e,u),this._cache=e.cache===v?{}:e.cache,this.state={isLoading:!1,options:e.options},this._onInputChange=this._onInputChange.bind(this)}return a(t,e),p(t,[{key:"componentDidMount",value:function(){var e=this.props.autoload;e&&this.loadOptions("")}},{key:"componentWillUpdate",value:function(e,t){var u=this,n=["options"];n.forEach(function(t){u.props[t]!==e[t]&&u.setState(o({},t,e[t]))})}},{key:"clearOptions",value:function(){this.setState({options:[]})}},{key:"loadOptions",value:function u(e){var t=this,u=this.props.loadOptions,n=this._cache;if(n&&n.hasOwnProperty(e))return void this.setState({options:n[e]});var s=function i(u,s){if(i===t._callback){t._callback=null;var o=s&&s.options||[];n&&(n[e]=o),t.setState({isLoading:!1,options:o})}};this._callback=s;var o=u(e,s);return o&&o.then(function(e){return s(null,e)},function(e){return s(e)}),this._callback&&!this.state.isLoading&&this.setState({isLoading:!0}),e}},{key:"_onInputChange",value:function(e){var t=this.props,u=t.ignoreAccents,n=t.ignoreCase,s=t.onInputChange;return u&&(e=(0,g["default"])(e)),n&&(e=e.toLowerCase()),s&&s(e),this.loadOptions(e)}},{key:"inputValue",value:function(){return this.select?this.select.state.inputValue:""}},{key:"noResultsText",value:function n(){var e=this.props,t=e.loadingPlaceholder,n=e.noResultsText,u=e.searchPromptText,s=this.state.isLoading,o=this.inputValue();return s?t:o&&n?n:u}},{key:"focus",value:function(){this.select.focus()}},{key:"render",value:function(){var e=this,t=this.props,u=t.children,n=t.loadingPlaceholder,s=t.placeholder,o=this.state,i=o.isLoading,a=o.options,r={noResultsText:this.noResultsText(),placeholder:i?n:s,options:i&&n?[]:a,ref:function(t){return e.select=t},onChange:function(t){e.props.multi&&e.props.value&&t.length>e.props.value.length&&e.clearOptions(),e.props.onChange(t)}};return u(l({},this.props,r,{isLoading:i,onInputChange:this._onInputChange}))}}]),t}(c.Component);u["default"]=C,C.propTypes=b,C.defaultProps=m,t.exports=u["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./Select":5,"./utils/stripDiacritics":11}],2:[function(e,t,u){(function(u){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function s(e){var t=arguments.length<=1||void 0===arguments[1]?{}:arguments[1];return Object.keys(e).reduce(function(t,u){var n=e[u];return void 0!==n&&(t[u]=n),t},t)}var o=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var u=arguments[t];for(var n in u)Object.prototype.hasOwnProperty.call(u,n)&&(e[n]=u[n])}return e},i="undefined"!=typeof window?window.React:"undefined"!=typeof u?u.React:null,a=n(i),r=e("./Select"),l=n(r),p=a["default"].createClass({displayName:"AsyncCreatableSelect",render:function(){var e=this;return a["default"].createElement(l["default"].Async,this.props,function(t){return a["default"].createElement(l["default"].Creatable,e.props,function(e){return a["default"].createElement(l["default"],o({},s(t,s(e,{})),{onInputChange:function(u){return e.onInputChange(u),t.onInputChange(u)},ref:function(u){e.ref(u),t.ref(u)}}))})})}});t.exports=p}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./Select":5}],3:[function(e,t,u){(function(u){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function s(e,t){var u={};for(var n in e)t.indexOf(n)>=0||Object.prototype.hasOwnProperty.call(e,n)&&(u[n]=e[n]);return u}function o(e){return f["default"].createElement(E["default"],e)}function i(e){var t=e.option,u=e.options,n=e.labelKey,s=e.valueKey;return 0===u.filter(function(e){return e[n]===t[n]||e[s]===t[s]}).length}function a(e){var t=e.label;return!!t}function r(e){var t=e.label,u=e.labelKey,n=e.valueKey,s={};return s[n]=t,s[u]=t,s.className="Select-create-option-placeholder",s}function l(e){return'Create option "'+e+'"'}function p(e){var t=e.keyCode;switch(t){case 9:case 13:case 188:return!0}return!1}var d=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var u=arguments[t];for(var n in u)Object.prototype.hasOwnProperty.call(u,n)&&(e[n]=u[n])}return e},c="undefined"!=typeof window?window.React:"undefined"!=typeof u?u.React:null,f=n(c),h=e("./Select"),E=n(h),y=e("./utils/defaultFilterOptions"),g=n(y),b=e("./utils/defaultMenuRenderer"),v=n(b),m=f["default"].createClass({displayName:"CreatableSelect",propTypes:{children:f["default"].PropTypes.func,filterOptions:f["default"].PropTypes.any,isOptionUnique:f["default"].PropTypes.func,isValidNewOption:f["default"].PropTypes.func,menuRenderer:f["default"].PropTypes.any,newOptionCreator:f["default"].PropTypes.func,onInputChange:f["default"].PropTypes.func,onInputKeyDown:f["default"].PropTypes.func,onNewOptionClick:f["default"].PropTypes.func,options:f["default"].PropTypes.array,promptTextCreator:f["default"].PropTypes.func,shouldKeyDownEventCreateNewOption:f["default"].PropTypes.func},statics:{isOptionUnique:i,isValidNewOption:a,newOptionCreator:r,promptTextCreator:l,shouldKeyDownEventCreateNewOption:p},getDefaultProps:function(){return{filterOptions:g["default"],isOptionUnique:i,isValidNewOption:a,menuRenderer:v["default"],newOptionCreator:r,promptTextCreator:l,shouldKeyDownEventCreateNewOption:p}},createNewOption:function(){var e=this.props,t=e.isValidNewOption,u=e.newOptionCreator,n=e.onNewOptionClick,s=e.options,o=void 0===s?[]:s;e.shouldKeyDownEventCreateNewOption;if(t({label:this.inputValue})){var i=u({label:this.inputValue,labelKey:this.labelKey,valueKey:this.valueKey}),a=this.isOptionUnique({option:i});a&&(n?n(i):(o.unshift(i),this.select.selectValue(i)))}},filterOptions:function C(){var e=this.props,C=e.filterOptions,t=e.isValidNewOption,u=(e.options,e.promptTextCreator),n=arguments[2]||[],s=C.apply(void 0,arguments)||[];if(t({label:this.inputValue})){var o=this.props.newOptionCreator,i=o({label:this.inputValue,labelKey:this.labelKey,valueKey:this.valueKey}),a=this.isOptionUnique({option:i,options:n.concat(s)});if(a){var r=u(this.inputValue);this._createPlaceholderOption=o({label:r,labelKey:this.labelKey,valueKey:this.valueKey}),s.unshift(this._createPlaceholderOption)}}return s},isOptionUnique:function F(e){var t=e.option,u=e.options,F=this.props.isOptionUnique;return u=u||this.select.filterOptions(),F({labelKey:this.labelKey,option:t,options:u,valueKey:this.valueKey})},menuRenderer:function O(e){var O=this.props.menuRenderer;return O(d({},e,{onSelect:this.onOptionSelect,selectValue:this.onOptionSelect}))},onInputChange:function w(e){var w=this.props.onInputChange;w&&w(e),this.inputValue=e},onInputKeyDown:function A(e){var t=this.props,u=t.shouldKeyDownEventCreateNewOption,A=t.onInputKeyDown,n=this.select.getFocusedOption();n&&n===this._createPlaceholderOption&&u({keyCode:e.keyCode})?(this.createNewOption(),e.preventDefault()):A&&A(e)},onOptionSelect:function(e,t){e===this._createPlaceholderOption?this.createNewOption():this.select.selectValue(e)},render:function(){var e=this,t=this.props,u=(t.newOptionCreator,t.shouldKeyDownEventCreateNewOption,s(t,["newOptionCreator","shouldKeyDownEventCreateNewOption"])),n=this.props.children;n||(n=o);var i=d({},u,{allowCreate:!0,filterOptions:this.filterOptions,menuRenderer:this.menuRenderer,onInputChange:this.onInputChange,onInputKeyDown:this.onInputKeyDown,ref:function(t){e.select=t,t&&(e.labelKey=t.props.labelKey,e.valueKey=t.props.valueKey)}});return n(i)}});t.exports=m}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./Select":5,"./utils/defaultFilterOptions":9,"./utils/defaultMenuRenderer":10}],4:[function(e,t,u){(function(e){"use strict";function u(e){return e&&e.__esModule?e:{"default":e}}var n="undefined"!=typeof window?window.React:"undefined"!=typeof e?e.React:null,s=u(n),o="undefined"!=typeof window?window.classNames:"undefined"!=typeof e?e.classNames:null,i=u(o),a=s["default"].createClass({displayName:"Option",propTypes:{children:s["default"].PropTypes.node,className:s["default"].PropTypes.string,instancePrefix:s["default"].PropTypes.string.isRequired,isDisabled:s["default"].PropTypes.bool,isFocused:s["default"].PropTypes.bool,isSelected:s["default"].PropTypes.bool,onFocus:s["default"].PropTypes.func,onSelect:s["default"].PropTypes.func,onUnfocus:s["default"].PropTypes.func,option:s["default"].PropTypes.object.isRequired,optionIndex:s["default"].PropTypes.number},blockEvent:function(e){e.preventDefault(),e.stopPropagation(),"A"===e.target.tagName&&"href"in e.target&&(e.target.target?window.open(e.target.href,e.target.target):window.location.href=e.target.href)},handleMouseDown:function(e){e.preventDefault(),e.stopPropagation(),this.props.onSelect(this.props.option,e)},handleMouseEnter:function(e){this.onFocus(e)},handleMouseMove:function(e){this.onFocus(e)},handleTouchEnd:function(e){this.dragging||this.handleMouseDown(e)},handleTouchMove:function(e){this.dragging=!0},handleTouchStart:function(e){this.dragging=!1},onFocus:function(e){this.props.isFocused||this.props.onFocus(this.props.option,e)},render:function(){var e=this.props,t=e.option,u=e.instancePrefix,n=e.optionIndex,o=(0,i["default"])(this.props.className,t.className);return t.disabled?s["default"].createElement("div",{className:o,onMouseDown:this.blockEvent,onClick:this.blockEvent},this.props.children):s["default"].createElement("div",{className:o,style:t.style,role:"option",onMouseDown:this.handleMouseDown,onMouseEnter:this.handleMouseEnter,onMouseMove:this.handleMouseMove,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove,onTouchEnd:this.handleTouchEnd,id:u+"-option-"+n,title:t.title},this.props.children)}});t.exports=a}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],5:[function(e,t,u){(function(n){"use strict";function s(e){return e&&e.__esModule?e:{"default":e}}function o(e,t){var u={};for(var n in e)t.indexOf(n)>=0||Object.prototype.hasOwnProperty.call(e,n)&&(u[n]=e[n]);return u}function i(e,t,u){return t in e?Object.defineProperty(e,t,{value:u,enumerable:!0,configurable:!0,writable:!0}):e[t]=u,e}function a(e){var t=typeof e;return"string"===t?e:"object"===t?JSON.stringify(e):"number"===t||"boolean"===t?String(e):""}Object.defineProperty(u,"__esModule",{value:!0});var r=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var u=arguments[t];for(var n in u)Object.prototype.hasOwnProperty.call(u,n)&&(e[n]=u[n])}return e},l="undefined"!=typeof window?window.React:"undefined"!=typeof n?n.React:null,p=s(l),d="undefined"!=typeof window?window.ReactDOM:"undefined"!=typeof n?n.ReactDOM:null,c=s(d),f="undefined"!=typeof window?window.AutosizeInput:"undefined"!=typeof n?n.AutosizeInput:null,h=s(f),E="undefined"!=typeof window?window.classNames:"undefined"!=typeof n?n.classNames:null,y=s(E),g=e("./utils/defaultArrowRenderer"),b=s(g),v=e("./utils/defaultFilterOptions"),m=s(v),C=e("./utils/defaultMenuRenderer"),F=s(C),O=e("./utils/defaultClearRenderer"),w=s(O),A=e("./Async"),P=s(A),T=e("./AsyncCreatable"),D=s(T),V=e("./Creatable"),S=s(V),R=e("./Option"),B=s(R),x=e("./Value"),M=s(x),_=p["default"].PropTypes.oneOfType([p["default"].PropTypes.string,p["default"].PropTypes.node]),N=1,I=p["default"].createClass({displayName:"Select",propTypes:{addLabelText:p["default"].PropTypes.string,"aria-label":p["default"].PropTypes.string,"aria-labelledby":p["default"].PropTypes.string,arrowRenderer:p["default"].PropTypes.func,autoBlur:p["default"].PropTypes.bool,autofocus:p["default"].PropTypes.bool,autosize:p["default"].PropTypes.bool,backspaceRemoves:p["default"].PropTypes.bool,backspaceToRemoveMessage:p["default"].PropTypes.string,className:p["default"].PropTypes.string,clearAllText:_,clearRenderer:p["default"].PropTypes.func,clearValueText:_,clearable:p["default"].PropTypes.bool,deleteRemoves:p["default"].PropTypes.bool,delimiter:p["default"].PropTypes.string,disabled:p["default"].PropTypes.bool,escapeClearsValue:p["default"].PropTypes.bool,filterOption:p["default"].PropTypes.func,filterOptions:p["default"].PropTypes.any,ignoreAccents:p["default"].PropTypes.bool,ignoreCase:p["default"].PropTypes.bool,inputProps:p["default"].PropTypes.object,inputRenderer:p["default"].PropTypes.func,instanceId:p["default"].PropTypes.string,isLoading:p["default"].PropTypes.bool,joinValues:p["default"].PropTypes.bool,labelKey:p["default"].PropTypes.string,matchPos:p["default"].PropTypes.string,matchProp:p["default"].PropTypes.string,menuBuffer:p["default"].PropTypes.number,menuContainerStyle:p["default"].PropTypes.object,menuRenderer:p["default"].PropTypes.func,menuStyle:p["default"].PropTypes.object,multi:p["default"].PropTypes.bool,name:p["default"].PropTypes.string,noResultsText:_,onBlur:p["default"].PropTypes.func,onBlurResetsInput:p["default"].PropTypes.bool,onChange:p["default"].PropTypes.func,onClose:p["default"].PropTypes.func,onCloseResetsInput:p["default"].PropTypes.bool,onFocus:p["default"].PropTypes.func,onInputChange:p["default"].PropTypes.func,onInputKeyDown:p["default"].PropTypes.func,onMenuScrollToBottom:p["default"].PropTypes.func,onOpen:p["default"].PropTypes.func,onValueClick:p["default"].PropTypes.func,openAfterFocus:p["default"].PropTypes.bool,openOnFocus:p["default"].PropTypes.bool,optionClassName:p["default"].PropTypes.string,optionComponent:p["default"].PropTypes.func,optionRenderer:p["default"].PropTypes.func,options:p["default"].PropTypes.array,pageSize:p["default"].PropTypes.number,placeholder:_,required:p["default"].PropTypes.bool,resetValue:p["default"].PropTypes.any,scrollMenuIntoView:p["default"].PropTypes.bool,searchable:p["default"].PropTypes.bool,simpleValue:p["default"].PropTypes.bool,style:p["default"].PropTypes.object,tabIndex:p["default"].PropTypes.string,tabSelectsValue:p["default"].PropTypes.bool,value:p["default"].PropTypes.any,valueComponent:p["default"].PropTypes.func,valueKey:p["default"].PropTypes.string,valueRenderer:p["default"].PropTypes.func,wrapperStyle:p["default"].PropTypes.object},statics:{Async:P["default"],AsyncCreatable:D["default"],Creatable:S["default"]},getDefaultProps:function(){return{addLabelText:'Add "{label}"?',arrowRenderer:b["default"],autosize:!0,backspaceRemoves:!0,backspaceToRemoveMessage:"Press backspace to remove {label}",clearable:!0,clearAllText:"Clear all",clearRenderer:w["default"],clearValueText:"Clear value",deleteRemoves:!0,delimiter:",",disabled:!1,escapeClearsValue:!0,filterOptions:m["default"],ignoreAccents:!0,ignoreCase:!0,inputProps:{},isLoading:!1,joinValues:!1,labelKey:"label",matchPos:"any",matchProp:"any",menuBuffer:0,menuRenderer:F["default"],multi:!1,noResultsText:"No results found",onBlurResetsInput:!0,onCloseResetsInput:!0,openAfterFocus:!1,optionComponent:B["default"],pageSize:5,placeholder:"Select...",required:!1,scrollMenuIntoView:!0,searchable:!0,simpleValue:!1,tabSelectsValue:!0,valueComponent:M["default"],valueKey:"value"}},getInitialState:function(){return{inputValue:"",isFocused:!1,isOpen:!1,isPseudoFocused:!1,required:!1}},componentWillMount:function(){this._instancePrefix="react-select-"+(this.props.instanceId||++N)+"-";var e=this.getValueArray(this.props.value);this.props.required&&this.setState({required:this.handleRequired(e[0],this.props.multi)})},componentDidMount:function(){this.props.autofocus&&this.focus()},componentWillReceiveProps:function(e){var t=this.getValueArray(e.value,e);e.required&&this.setState({required:this.handleRequired(t[0],e.multi)})},componentWillUpdate:function(e,t){if(t.isOpen!==this.state.isOpen){this.toggleTouchOutsideEvent(t.isOpen);var u=t.isOpen?e.onOpen:e.onClose;u&&u()}},componentDidUpdate:function(e,t){if(this.menu&&this.focused&&this.state.isOpen&&!this.hasScrolledToOption){var u=c["default"].findDOMNode(this.focused),n=c["default"].findDOMNode(this.menu);n.scrollTop=u.offsetTop,this.hasScrolledToOption=!0}else this.state.isOpen||(this.hasScrolledToOption=!1);if(this._scrollToFocusedOptionOnUpdate&&this.focused&&this.menu){this._scrollToFocusedOptionOnUpdate=!1;var s=c["default"].findDOMNode(this.focused),o=c["default"].findDOMNode(this.menu),i=s.getBoundingClientRect(),a=o.getBoundingClientRect();(i.bottom>a.bottom||i.top<a.top)&&(o.scrollTop=s.offsetTop+s.clientHeight-o.offsetHeight)}if(this.props.scrollMenuIntoView&&this.menuContainer){var r=this.menuContainer.getBoundingClientRect();window.innerHeight<r.bottom+this.props.menuBuffer&&window.scrollBy(0,r.bottom+this.props.menuBuffer-window.innerHeight)}e.disabled!==this.props.disabled&&(this.setState({isFocused:!1}),this.closeMenu())},componentWillUnmount:function(){!document.removeEventListener&&document.detachEvent?document.detachEvent("ontouchstart",this.handleTouchOutside):document.removeEventListener("touchstart",this.handleTouchOutside)},toggleTouchOutsideEvent:function(e){e?!document.addEventListener&&document.attachEvent?document.attachEvent("ontouchstart",this.handleTouchOutside):document.addEventListener("touchstart",this.handleTouchOutside):!document.removeEventListener&&document.detachEvent?document.detachEvent("ontouchstart",this.handleTouchOutside):document.removeEventListener("touchstart",this.handleTouchOutside)},handleTouchOutside:function(e){this.wrapper&&!this.wrapper.contains(e.target)&&this.closeMenu()},focus:function(){this.input&&(this.input.focus(),this.props.openAfterFocus&&this.setState({isOpen:!0}))},blurInput:function(){this.input&&this.input.blur()},handleTouchMove:function(e){this.dragging=!0},handleTouchStart:function(e){this.dragging=!1},handleTouchEnd:function(e){this.dragging||this.handleMouseDown(e)},handleTouchEndClearValue:function(e){this.dragging||this.clearValue(e)},handleMouseDown:function(e){if(!(this.props.disabled||"mousedown"===e.type&&0!==e.button)&&"INPUT"!==e.target.tagName){if(e.stopPropagation(),e.preventDefault(),!this.props.searchable)return this.focus(),this.setState({isOpen:!this.state.isOpen});if(this.state.isFocused){this.focus();var t=this.input;"function"==typeof t.getInput&&(t=t.getInput()),t.value="",this.setState({isOpen:!0,isPseudoFocused:!1})}else this._openAfterFocus=!0,this.focus()}},handleMouseDownOnArrow:function(e){this.props.disabled||"mousedown"===e.type&&0!==e.button||this.state.isOpen&&(e.stopPropagation(),e.preventDefault(),this.closeMenu())},handleMouseDownOnMenu:function(e){this.props.disabled||"mousedown"===e.type&&0!==e.button||(e.stopPropagation(),e.preventDefault(),this._openAfterFocus=!0,this.focus())},closeMenu:function(){this.props.onCloseResetsInput?this.setState({isOpen:!1,isPseudoFocused:this.state.isFocused&&!this.props.multi,inputValue:""}):this.setState({isOpen:!1,isPseudoFocused:this.state.isFocused&&!this.props.multi,inputValue:this.state.inputValue}),this.hasScrolledToOption=!1},handleInputFocus:function(e){if(!this.props.disabled){var t=this.state.isOpen||this._openAfterFocus||this.props.openOnFocus;this.props.onFocus&&this.props.onFocus(e),this.setState({isFocused:!0,isOpen:t}),this._openAfterFocus=!1}},handleInputBlur:function(e){if(this.menu&&(this.menu===document.activeElement||this.menu.contains(document.activeElement)))return void this.focus();this.props.onBlur&&this.props.onBlur(e);var t={isFocused:!1,isOpen:!1,isPseudoFocused:!1};this.props.onBlurResetsInput&&(t.inputValue=""),this.setState(t)},handleInputChange:function(e){var t=e.target.value;if(this.state.inputValue!==e.target.value&&this.props.onInputChange){var u=this.props.onInputChange(t);null!=u&&"object"!=typeof u&&(t=""+u)}this.setState({isOpen:!0,isPseudoFocused:!1,inputValue:t})},handleKeyDown:function(e){if(!(this.props.disabled||"function"==typeof this.props.onInputKeyDown&&(this.props.onInputKeyDown(e),e.defaultPrevented))){switch(e.keyCode){case 8:return void(!this.state.inputValue&&this.props.backspaceRemoves&&(e.preventDefault(),this.popValue()));case 9:if(e.shiftKey||!this.state.isOpen||!this.props.tabSelectsValue)return;return void this.selectFocusedOption();case 13:if(!this.state.isOpen)return;e.stopPropagation(),this.selectFocusedOption();break;case 27:this.state.isOpen?(this.closeMenu(),e.stopPropagation()):this.props.clearable&&this.props.escapeClearsValue&&(this.clearValue(e),e.stopPropagation());break;case 38:this.focusPreviousOption();break;case 40:this.focusNextOption();break;case 33:this.focusPageUpOption();break;case 34:this.focusPageDownOption();break;case 35:if(e.shiftKey)return;this.focusEndOption();break;case 36:if(e.shiftKey)return;this.focusStartOption();break;case 46:return void(!this.state.inputValue&&this.props.deleteRemoves&&(e.preventDefault(),this.popValue()));default:return}e.preventDefault()}},handleValueClick:function(e,t){this.props.onValueClick&&this.props.onValueClick(e,t)},handleMenuScroll:function(e){if(this.props.onMenuScrollToBottom){var t=e.target;t.scrollHeight>t.offsetHeight&&!(t.scrollHeight-t.offsetHeight-t.scrollTop)&&this.props.onMenuScrollToBottom()}},handleRequired:function(e,t){return!e||(t?0===e.length:0===Object.keys(e).length)},getOptionLabel:function(e){return e[this.props.labelKey]},getValueArray:function(e,t){var u=this,n="object"==typeof t?t:this.props;if(n.multi){if("string"==typeof e&&(e=e.split(n.delimiter)),!Array.isArray(e)){if(null===e||void 0===e)return[];e=[e]}return e.map(function(e){return u.expandValue(e,n)}).filter(function(e){return e})}var s=this.expandValue(e,n);return s?[s]:[]},expandValue:function(e,t){var u=typeof e;if("string"!==u&&"number"!==u&&"boolean"!==u)return e;var n=t.options,s=t.valueKey;if(n)for(var o=0;o<n.length;o++)if(n[o][s]===e)return n[o]},setValue:function(e){var t=this;if(this.props.autoBlur&&this.blurInput(),this.props.onChange){if(this.props.required){var u=this.handleRequired(e,this.props.multi);this.setState({required:u})}this.props.simpleValue&&e&&(e=this.props.multi?e.map(function(e){return e[t.props.valueKey]}).join(this.props.delimiter):e[this.props.valueKey]),this.props.onChange(e)}},selectValue:function(e){var t=this;this.hasScrolledToOption=!1,this.props.multi?this.setState({inputValue:"",focusedIndex:null},function(){t.addValue(e)}):this.setState({isOpen:!1,inputValue:"",isPseudoFocused:this.state.isFocused},function(){t.setValue(e)})},addValue:function(e){var t=this.getValueArray(this.props.value),u=this._visibleOptions.filter(function(e){return!e.disabled}),n=u.indexOf(e);this.setValue(t.concat(e)),u.length-1===n?this.focusOption(u[n-1]):u.length>n&&this.focusOption(u[n+1])},popValue:function(){var e=this.getValueArray(this.props.value);e.length&&e[e.length-1].clearableValue!==!1&&this.setValue(e.slice(0,e.length-1))},removeValue:function(e){var t=this.getValueArray(this.props.value);this.setValue(t.filter(function(t){return t!==e})),this.focus()},clearValue:function(e){e&&"mousedown"===e.type&&0!==e.button||(e.stopPropagation(),e.preventDefault(),this.setValue(this.getResetValue()),this.setState({isOpen:!1,inputValue:""},this.focus))},getResetValue:function(){return void 0!==this.props.resetValue?this.props.resetValue:this.props.multi?[]:null},focusOption:function(e){this.setState({focusedOption:e})},focusNextOption:function(){this.focusAdjacentOption("next")},focusPreviousOption:function(){this.focusAdjacentOption("previous")},focusPageUpOption:function(){this.focusAdjacentOption("page_up")},focusPageDownOption:function(){this.focusAdjacentOption("page_down")},focusStartOption:function(){this.focusAdjacentOption("start")},focusEndOption:function(){this.focusAdjacentOption("end")},focusAdjacentOption:function(e){var t=this._visibleOptions.map(function(e,t){return{option:e,index:t}}).filter(function(e){return!e.option.disabled});if(this._scrollToFocusedOptionOnUpdate=!0,!this.state.isOpen)return void this.setState({isOpen:!0,inputValue:"",focusedOption:this._focusedOption||(t.length?t["next"===e?0:t.length-1].option:null)});if(t.length){for(var u=-1,n=0;n<t.length;n++)if(this._focusedOption===t[n].option){u=n;break}if("next"===e&&u!==-1)u=(u+1)%t.length;else if("previous"===e)u>0?u-=1:u=t.length-1;else if("start"===e)u=0;else if("end"===e)u=t.length-1;else if("page_up"===e){var s=u-this.props.pageSize;u=s<0?0:s}else if("page_down"===e){var s=u+this.props.pageSize;u=s>t.length-1?t.length-1:s}u===-1&&(u=0),this.setState({focusedIndex:t[u].index,focusedOption:t[u].option})}},getFocusedOption:function(){return this._focusedOption},getInputValue:function(){return this.state.inputValue},selectFocusedOption:function(){if(this._focusedOption)return this.selectValue(this._focusedOption)},renderLoading:function(){if(this.props.isLoading)return p["default"].createElement("span",{className:"Select-loading-zone","aria-hidden":"true"},p["default"].createElement("span",{className:"Select-loading"}))},renderValue:function(e,t){var u=this,n=this.props.valueRenderer||this.getOptionLabel,s=this.props.valueComponent;if(!e.length)return this.state.inputValue?null:p["default"].createElement("div",{className:"Select-placeholder"},this.props.placeholder);var o=this.props.onValueClick?this.handleValueClick:null;return this.props.multi?e.map(function(e,t){return p["default"].createElement(s,{id:u._instancePrefix+"-value-"+t,instancePrefix:u._instancePrefix,disabled:u.props.disabled||e.clearableValue===!1,key:"value-"+t+"-"+e[u.props.valueKey],onClick:o,onRemove:u.removeValue,value:e},n(e,t),p["default"].createElement("span",{className:"Select-aria-only"}," "))}):this.state.inputValue?void 0:(t&&(o=null),p["default"].createElement(s,{id:this._instancePrefix+"-value-item",disabled:this.props.disabled,instancePrefix:this._instancePrefix,onClick:o,value:e[0]},n(e[0])))},renderInput:function(e,t){var u,n=this,s=(0,y["default"])("Select-input",this.props.inputProps.className),a=!!this.state.isOpen,l=(0,y["default"])((u={},i(u,this._instancePrefix+"-list",a),i(u,this._instancePrefix+"-backspace-remove-message",this.props.multi&&!this.props.disabled&&this.state.isFocused&&!this.state.inputValue),u)),d=r({},this.props.inputProps,{role:"combobox","aria-expanded":""+a,"aria-owns":l,"aria-haspopup":""+a,"aria-activedescendant":a?this._instancePrefix+"-option-"+t:this._instancePrefix+"-value","aria-labelledby":this.props["aria-labelledby"],"aria-label":this.props["aria-label"],className:s,tabIndex:this.props.tabIndex,onBlur:this.handleInputBlur,onChange:this.handleInputChange,onFocus:this.handleInputFocus,ref:function(e){return n.input=e},required:this.state.required,value:this.state.inputValue});if(this.props.inputRenderer)return this.props.inputRenderer(d);if(this.props.disabled||!this.props.searchable){var c=this.props.inputProps,f=(c.inputClassName,o(c,["inputClassName"]));return p["default"].createElement("div",r({},f,{role:"combobox","aria-expanded":a,"aria-owns":a?this._instancePrefix+"-list":this._instancePrefix+"-value","aria-activedescendant":a?this._instancePrefix+"-option-"+t:this._instancePrefix+"-value",className:s,tabIndex:this.props.tabIndex||0,onBlur:this.handleInputBlur,onFocus:this.handleInputFocus,ref:function(e){return n.input=e},"aria-readonly":""+!!this.props.disabled,style:{border:0,width:1,display:"inline-block"}}))}return this.props.autosize?p["default"].createElement(h["default"],r({},d,{minWidth:"5"})):p["default"].createElement("div",{className:s},p["default"].createElement("input",d))},renderClear:function(){if(this.props.clearable&&this.props.value&&0!==this.props.value&&(!this.props.multi||this.props.value.length)&&!this.props.disabled&&!this.props.isLoading){var e=this.props.clearRenderer();return p["default"].createElement("span",{className:"Select-clear-zone",title:this.props.multi?this.props.clearAllText:this.props.clearValueText,"aria-label":this.props.multi?this.props.clearAllText:this.props.clearValueText,onMouseDown:this.clearValue,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove,onTouchEnd:this.handleTouchEndClearValue},e)}},renderArrow:function(){var e=this.handleMouseDownOnArrow,t=this.state.isOpen,u=this.props.arrowRenderer({onMouseDown:e,isOpen:t});return p["default"].createElement("span",{className:"Select-arrow-zone",onMouseDown:e},u)},filterOptions:function K(e){var t=this.state.inputValue,u=this.props.options||[];if(this.props.filterOptions){var K="function"==typeof this.props.filterOptions?this.props.filterOptions:m["default"];return K(u,t,e,{filterOption:this.props.filterOption,ignoreAccents:this.props.ignoreAccents,ignoreCase:this.props.ignoreCase,labelKey:this.props.labelKey,matchPos:this.props.matchPos,matchProp:this.props.matchProp,valueKey:this.props.valueKey})}return u},onOptionRef:function(e,t){t&&(this.focused=e)},renderMenu:function(e,t,u){return e&&e.length?this.props.menuRenderer({focusedOption:u,focusOption:this.focusOption, -instancePrefix:this._instancePrefix,labelKey:this.props.labelKey,onFocus:this.focusOption,onSelect:this.selectValue,optionClassName:this.props.optionClassName,optionComponent:this.props.optionComponent,optionRenderer:this.props.optionRenderer||this.getOptionLabel,options:e,selectValue:this.selectValue,valueArray:t,valueKey:this.props.valueKey,onOptionRef:this.onOptionRef}):this.props.noResultsText?p["default"].createElement("div",{className:"Select-noresults"},this.props.noResultsText):null},renderHiddenField:function(e){var t=this;if(this.props.name){if(this.props.joinValues){var u=e.map(function(e){return a(e[t.props.valueKey])}).join(this.props.delimiter);return p["default"].createElement("input",{type:"hidden",ref:function(e){return t.value=e},name:this.props.name,value:u,disabled:this.props.disabled})}return e.map(function(e,u){return p["default"].createElement("input",{key:"hidden."+u,type:"hidden",ref:"value"+u,name:t.props.name,value:a(e[t.props.valueKey]),disabled:t.props.disabled})})}},getFocusableOptionIndex:function(e){var t=this._visibleOptions;if(!t.length)return null;var u=this.state.focusedOption||e;if(u&&!u.disabled){var n=t.indexOf(u);if(n!==-1)return n}for(var s=0;s<t.length;s++)if(!t[s].disabled)return s;return null},renderOuter:function(e,t,u){var n=this,s=this.renderMenu(e,t,u);return s?p["default"].createElement("div",{ref:function(e){return n.menuContainer=e},className:"Select-menu-outer",style:this.props.menuContainerStyle},p["default"].createElement("div",{ref:function(e){return n.menu=e},role:"listbox",className:"Select-menu",id:this._instancePrefix+"-list",style:this.props.menuStyle,onScroll:this.handleMenuScroll,onMouseDown:this.handleMouseDownOnMenu},s)):null},render:function(){var e=this,t=this.getValueArray(this.props.value),u=this._visibleOptions=this.filterOptions(this.props.multi?this.getValueArray(this.props.value):null),n=this.state.isOpen;this.props.multi&&!u.length&&t.length&&!this.state.inputValue&&(n=!1);var s=this.getFocusableOptionIndex(t[0]),o=null;o=null!==s?this._focusedOption=u[s]:this._focusedOption=null;var i=(0,y["default"])("Select",this.props.className,{"Select--multi":this.props.multi,"Select--single":!this.props.multi,"is-disabled":this.props.disabled,"is-focused":this.state.isFocused,"is-loading":this.props.isLoading,"is-open":n,"is-pseudo-focused":this.state.isPseudoFocused,"is-searchable":this.props.searchable,"has-value":t.length}),a=null;return this.props.multi&&!this.props.disabled&&t.length&&!this.state.inputValue&&this.state.isFocused&&this.props.backspaceRemoves&&(a=p["default"].createElement("span",{id:this._instancePrefix+"-backspace-remove-message",className:"Select-aria-only","aria-live":"assertive"},this.props.backspaceToRemoveMessage.replace("{label}",t[t.length-1][this.props.labelKey]))),p["default"].createElement("div",{ref:function(t){return e.wrapper=t},className:i,style:this.props.wrapperStyle},this.renderHiddenField(t),p["default"].createElement("div",{ref:function(t){return e.control=t},className:"Select-control",style:this.props.style,onKeyDown:this.handleKeyDown,onMouseDown:this.handleMouseDown,onTouchEnd:this.handleTouchEnd,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove},p["default"].createElement("span",{className:"Select-multi-value-wrapper",id:this._instancePrefix+"-value"},this.renderValue(t,n),this.renderInput(t,s)),a,this.renderLoading(),this.renderClear(),this.renderArrow()),n?this.renderOuter(u,this.props.multi?null:t,o):null)}});u["default"]=I,t.exports=u["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./Async":1,"./AsyncCreatable":2,"./Creatable":3,"./Option":4,"./Value":6,"./utils/defaultArrowRenderer":7,"./utils/defaultClearRenderer":8,"./utils/defaultFilterOptions":9,"./utils/defaultMenuRenderer":10}],6:[function(e,t,u){(function(e){"use strict";function u(e){return e&&e.__esModule?e:{"default":e}}var n="undefined"!=typeof window?window.React:"undefined"!=typeof e?e.React:null,s=u(n),o="undefined"!=typeof window?window.classNames:"undefined"!=typeof e?e.classNames:null,i=u(o),a=s["default"].createClass({displayName:"Value",propTypes:{children:s["default"].PropTypes.node,disabled:s["default"].PropTypes.bool,id:s["default"].PropTypes.string,onClick:s["default"].PropTypes.func,onRemove:s["default"].PropTypes.func,value:s["default"].PropTypes.object.isRequired},handleMouseDown:function(e){if("mousedown"!==e.type||0===e.button)return this.props.onClick?(e.stopPropagation(),void this.props.onClick(this.props.value,e)):void(this.props.value.href&&e.stopPropagation())},onRemove:function(e){e.preventDefault(),e.stopPropagation(),this.props.onRemove(this.props.value)},handleTouchEndRemove:function(e){this.dragging||this.onRemove(e)},handleTouchMove:function(e){this.dragging=!0},handleTouchStart:function(e){this.dragging=!1},renderRemoveIcon:function(){if(!this.props.disabled&&this.props.onRemove)return s["default"].createElement("span",{className:"Select-value-icon","aria-hidden":"true",onMouseDown:this.onRemove,onTouchEnd:this.handleTouchEndRemove,onTouchStart:this.handleTouchStart,onTouchMove:this.handleTouchMove},"×")},renderLabel:function(){var e="Select-value-label";return this.props.onClick||this.props.value.href?s["default"].createElement("a",{className:e,href:this.props.value.href,target:this.props.value.target,onMouseDown:this.handleMouseDown,onTouchEnd:this.handleMouseDown},this.props.children):s["default"].createElement("span",{className:e,role:"option","aria-selected":"true",id:this.props.id},this.props.children)},render:function(){return s["default"].createElement("div",{className:(0,i["default"])("Select-value",this.props.value.className),style:this.props.value.style,title:this.props.value.title},this.renderRemoveIcon(),this.renderLabel())}});t.exports=a}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],7:[function(e,t,u){(function(e){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function s(e){var t=e.onMouseDown;return i["default"].createElement("span",{className:"Select-arrow",onMouseDown:t})}Object.defineProperty(u,"__esModule",{value:!0}),u["default"]=s;var o="undefined"!=typeof window?window.React:"undefined"!=typeof e?e.React:null,i=n(o);t.exports=u["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],8:[function(e,t,u){(function(e){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function s(){return i["default"].createElement("span",{className:"Select-clear",dangerouslySetInnerHTML:{__html:"×"}})}Object.defineProperty(u,"__esModule",{value:!0}),u["default"]=s;var o="undefined"!=typeof window?window.React:"undefined"!=typeof e?e.React:null,i=n(o);t.exports=u["default"]}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],9:[function(e,t,u){"use strict";function n(e){return e&&e.__esModule?e:{"default":e}}function s(e,t,u,n){var s=this;return n.ignoreAccents&&(t=(0,i["default"])(t)),n.ignoreCase&&(t=t.toLowerCase()),u&&(u=u.map(function(e){return e[n.valueKey]})),e.filter(function(e){if(u&&u.indexOf(e[n.valueKey])>-1)return!1;if(n.filterOption)return n.filterOption.call(s,e,t);if(!t)return!0;var o=String(e[n.valueKey]),a=String(e[n.labelKey]);return n.ignoreAccents&&("label"!==n.matchProp&&(o=(0,i["default"])(o)),"value"!==n.matchProp&&(a=(0,i["default"])(a))),n.ignoreCase&&("label"!==n.matchProp&&(o=o.toLowerCase()),"value"!==n.matchProp&&(a=a.toLowerCase())),"start"===n.matchPos?"label"!==n.matchProp&&o.substr(0,t.length)===t||"value"!==n.matchProp&&a.substr(0,t.length)===t:"label"!==n.matchProp&&o.indexOf(t)>=0||"value"!==n.matchProp&&a.indexOf(t)>=0})}var o=e("./stripDiacritics"),i=n(o);t.exports=s},{"./stripDiacritics":11}],10:[function(e,t,u){(function(e){"use strict";function u(e){return e&&e.__esModule?e:{"default":e}}function n(e){var t=e.focusedOption,u=e.instancePrefix,n=(e.labelKey,e.onFocus),s=e.onSelect,i=e.optionClassName,r=e.optionComponent,l=e.optionRenderer,p=e.options,d=e.valueArray,c=e.valueKey,f=e.onOptionRef,h=r;return p.map(function(e,r){var p=d&&d.indexOf(e)>-1,E=e===t,y=(0,o["default"])(i,{"Select-option":!0,"is-selected":p,"is-focused":E,"is-disabled":e.disabled});return a["default"].createElement(h,{className:y,instancePrefix:u,isDisabled:e.disabled,isFocused:E,isSelected:p,key:"option-"+r+"-"+e[c],onFocus:n,onSelect:s,option:e,optionIndex:r,ref:function(e){f(e,E)}},l(e,r))})}var s="undefined"!=typeof window?window.classNames:"undefined"!=typeof e?e.classNames:null,o=u(s),i="undefined"!=typeof window?window.React:"undefined"!=typeof e?e.React:null,a=u(i);t.exports=n}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],11:[function(e,t,u){"use strict";var n=[{base:"A",letters:/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},{base:"AA",letters:/[\uA732]/g},{base:"AE",letters:/[\u00C6\u01FC\u01E2]/g},{base:"AO",letters:/[\uA734]/g},{base:"AU",letters:/[\uA736]/g},{base:"AV",letters:/[\uA738\uA73A]/g},{base:"AY",letters:/[\uA73C]/g},{base:"B",letters:/[\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},{base:"C",letters:/[\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},{base:"D",letters:/[\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},{base:"DZ",letters:/[\u01F1\u01C4]/g},{base:"Dz",letters:/[\u01F2\u01C5]/g},{base:"E",letters:/[\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},{base:"F",letters:/[\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},{base:"G",letters:/[\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g},{base:"H",letters:/[\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},{base:"I",letters:/[\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},{base:"J",letters:/[\u004A\u24BF\uFF2A\u0134\u0248]/g},{base:"K",letters:/[\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},{base:"L",letters:/[\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},{base:"LJ",letters:/[\u01C7]/g},{base:"Lj",letters:/[\u01C8]/g},{base:"M",letters:/[\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},{base:"N",letters:/[\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},{base:"NJ",letters:/[\u01CA]/g},{base:"Nj",letters:/[\u01CB]/g},{base:"O",letters:/[\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},{base:"OI",letters:/[\u01A2]/g},{base:"OO",letters:/[\uA74E]/g},{base:"OU",letters:/[\u0222]/g},{base:"P",letters:/[\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},{base:"Q",letters:/[\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},{base:"R",letters:/[\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},{base:"S",letters:/[\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},{base:"T",letters:/[\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g},{base:"TZ",letters:/[\uA728]/g},{base:"U",letters:/[\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},{base:"V",letters:/[\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},{base:"VY",letters:/[\uA760]/g},{base:"W",letters:/[\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},{base:"X",letters:/[\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},{base:"Y",letters:/[\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},{base:"Z",letters:/[\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g},{base:"a",letters:/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250]/g},{base:"aa",letters:/[\uA733]/g},{base:"ae",letters:/[\u00E6\u01FD\u01E3]/g},{base:"ao",letters:/[\uA735]/g},{base:"au",letters:/[\uA737]/g},{base:"av",letters:/[\uA739\uA73B]/g},{base:"ay",letters:/[\uA73D]/g},{base:"b",letters:/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253]/g},{base:"c",letters:/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184]/g},{base:"d",letters:/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A]/g},{base:"dz",letters:/[\u01F3\u01C6]/g},{base:"e",letters:/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD]/g},{base:"f",letters:/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C]/g},{base:"g",letters:/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F]/g},{base:"h",letters:/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265]/g},{base:"hv",letters:/[\u0195]/g},{base:"i",letters:/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131]/g},{base:"j",letters:/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249]/g},{base:"k",letters:/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3]/g},{base:"l",letters:/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747]/g},{base:"lj",letters:/[\u01C9]/g},{base:"m",letters:/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F]/g},{base:"n",letters:/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5]/g},{base:"nj",letters:/[\u01CC]/g},{base:"o",letters:/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275]/g},{base:"oi",letters:/[\u01A3]/g},{base:"ou",letters:/[\u0223]/g},{base:"oo",letters:/[\uA74F]/g},{base:"p",letters:/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755]/g},{base:"q",letters:/[\u0071\u24E0\uFF51\u024B\uA757\uA759]/g},{base:"r",letters:/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783]/g},{base:"s",letters:/[\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B]/g},{base:"t",letters:/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787]/g},{base:"tz",letters:/[\uA729]/g},{base:"u",letters:/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289]/g},{base:"v",letters:/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C]/g},{base:"vy",letters:/[\uA761]/g},{base:"w",letters:/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73]/g},{base:"x",letters:/[\u0078\u24E7\uFF58\u1E8B\u1E8D]/g},{base:"y",letters:/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF]/g},{base:"z",letters:/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763]/g}];t.exports=function(e){for(var t=0;t<n.length;t++)e=e.replace(n[t].letters,n[t].base);return e}},{}]},{},[5])(5)}); \ No newline at end of file diff --git a/docs/App/Footer.tsx b/docs/App/Footer.tsx new file mode 100644 index 0000000000..bca7ed5e0c --- /dev/null +++ b/docs/App/Footer.tsx @@ -0,0 +1,74 @@ +/** @jsx jsx */ +import { jsx } from '@emotion/react'; + +// const smallDevice = '@media (max-width: 769px)'; +const largeDevice = '@media (min-width: 770px)'; + +const Wrapper = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + backgroundColor: '#FAFBFC', + borderTop: '1px solid #EBECF0', + color: '#7A869A', + fontSize: '0.85em', + zIndex: 1, + }} + {...props} + /> +); +const Container = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + boxSizing: 'border-box', + maxWidth: 800, + marginLeft: 'auto', + marginRight: 'auto', + paddingLeft: 20, + paddingRight: 20, + + [largeDevice]: { + alignItems: 'center', + display: 'flex', + justifyContent: 'space-between', + paddingBottom: 20, + paddingTop: 20, + }, + }} + {...props} + /> +); +const A = (props: JSX.IntrinsicElements['a']) => ( + <a + {...props} + css={{ + color: '#505F79', + textDecoration: 'none', + + ':visited': { + color: '#505F79', + }, + ':hover': { + textDecoration: 'underline', + }, + }} + target="_blank" + /> +); + +export default function Footer() { + return ( + <Wrapper> + <Container> + <p> + Copyright © <A href="https://twitter.com/JedWatson">Jed Watson</A>, + 2022. MIT Licensed. + </p> + <p> + Thanks to <A href="https://www.thinkmill.com.au">Thinkmill</A> and{' '} + <A href="https://www.atlassian.com">Atlassian</A> for supporting this + project. + </p> + </Container> + </Wrapper> + ); +} diff --git a/docs/App/GitHubButton.tsx b/docs/App/GitHubButton.tsx new file mode 100644 index 0000000000..383649b038 --- /dev/null +++ b/docs/App/GitHubButton.tsx @@ -0,0 +1,96 @@ +/** @jsx jsx */ +import { jsx } from '@emotion/react'; + +interface Props { + readonly count: number; + readonly repo: string; +} + +const StarButton = ({ count, repo }: Props) => ( + <div css={{ alignItems: 'center', display: 'inline-flex', minWidth: 128 }}> + <a + aria-label="Star react-select on GitHub" + css={{ + alignItems: 'center', + display: 'flex', + borderRadius: 2, + color: '#253858', + backgroundColor: 'white', + boxShadow: '0 1px 0 rgba(0, 0, 0, 0.2)', + cursor: 'pointer', + fontSize: 13, + fontWeight: 'bold', + padding: '6px 10px', + position: 'relative', + textDecoration: 'none', + + ':hover': { + boxShadow: '0 1px 0 rgba(0, 0, 0, 0.2), 0 2px 5px rgba(0, 0, 0, 0.2)', + color: '#091e42', + }, + ':active': { + background: '#DFE1E5', + boxShadow: '0 1px 0 rgba(0, 0, 0, 0.2)', + color: '#091e42', + bottom: -1, + }, + }} + style={{ + backgroundImage: 'linear-gradient(180deg, #fff 33%, #DFE1E5 100%)', + }} + href={repo} + target="_blank" + > + <svg + version="1.1" + width="16" + height="16" + viewBox="0 0 16 16" + fill="currentColor" + aria-hidden="true" + > + <path + fillRule="evenodd" + d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z" + /> + </svg> + <span css={{ paddingLeft: 4 }}>Star</span> + </a> + <a + css={{ + backgroundColor: 'white', + borderRadius: 2, + color: '#253858', + cursor: 'pointer', + display: 'inline-block', + fontSize: 13, + fontWeight: 500, + letterSpacing: '-0.01em', + marginLeft: 6, + opacity: count > 0 ? 1 : 0, + padding: '6px 7px', + position: 'relative', + textDecoration: 'none', + transition: 'opacity 200ms', + + '&:before': { + border: '4px solid transparent', + borderRightColor: 'white', + content: '" "', + height: 0, + left: -8, + top: '50%', + marginTop: -4, + position: 'absolute', + width: 0, + }, + }} + href={`${repo}/stargazers`} + target="_blank" + > + <span>{count && count.toLocaleString()}</span> + </a> + </div> +); + +export default StarButton; diff --git a/docs/App/Header.tsx b/docs/App/Header.tsx new file mode 100644 index 0000000000..1eff8b463f --- /dev/null +++ b/docs/App/Header.tsx @@ -0,0 +1,285 @@ +/** @jsx jsx */ +import fetch from 'unfetch'; +import { Component, Ref, RefCallback } from 'react'; +import { jsx } from '@emotion/react'; +import { RouteComponentProps, withRouter } from 'react-router-dom'; + +import Select, { StylesConfig } from 'react-select'; +import GitHubButton from './GitHubButton'; +import TwitterButton from './TwitterButton'; +import isArray from '../isArray'; + +const smallDevice = '@media (max-width: 769px)'; +const largeDevice = '@media (min-width: 770px)'; + +interface Change { + value: string; + icon: string; + label: string; +} + +const changes = [ + { + value: '/typescript', + icon: '🛠️', + label: 'Written in TypeScript', + }, + { + value: '/props', + icon: '❤️', + label: 'Simpler and more extensible', + }, + { + value: '/styles', + icon: '🎨', + label: 'CSS-in-JS styling API', + }, + { + value: '/components', + icon: '📦', + label: 'Replaceable component architecture', + }, + { + value: '/advanced', + icon: '🔥', + label: 'Lots of advanced functionality', + }, + { + value: '/upgrade', + icon: '🗺', + label: 'Check out the Upgrade Guide', + }, +]; + +function getLabel({ icon, label }: Change) { + return ( + <div style={{ alignItems: 'center', display: 'flex' }}> + <span style={{ fontSize: 18, marginRight: '0.5em' }}>{icon}</span> + <span style={{ fontSize: 14 }}>{label}</span> + </div> + ); +} + +const headerSelectStyles: StylesConfig<Change, boolean> = { + control: (base, { isFocused }) => ({ + ...base, + backgroundClip: 'padding-box', + borderColor: 'rgba(0,0,0,0.1)', + boxShadow: isFocused ? '0 0 0 1px #4C9AFF' : undefined, + + ':hover': { + borderColor: 'rgba(0,0,0,0.2)', + }, + }), + option: (base) => ({ + ...base, + padding: '4px 12px', + }), + placeholder: (base) => ({ + ...base, + color: 'black', + }), +}; + +const Gradient = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + backgroundColor: '#2684FF', + backgroundImage: 'linear-gradient(135deg, #2684FF 0%, #0747A6 100%)', + color: 'white', + position: 'relative', + zIndex: 2, + + [largeDevice]: { + boxShadow: '0 5px 0 rgba(0, 0, 0, 0.08)', + }, + }} + {...props} + /> +); +const Container = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + boxSizing: 'border-box', + maxWidth: 800, + marginLeft: 'auto', + marginRight: 'auto', + padding: 20, + + [largeDevice]: { + paddingBottom: 40, + paddingTop: 40, + }, + }} + {...props} + /> +); + +interface HeaderState { + readonly stars: number; +} + +const apiUrl = 'https://api.github.com/repos/jedwatson/react-select'; + +class Header extends Component<RouteComponentProps, HeaderState> { + nav: HTMLElement | undefined; + content!: HTMLElement; + state: HeaderState = { stars: 0 }; + componentDidMount() { + this.getStarCount(); + } + getStarCount = () => { + fetch(apiUrl) + .then((res) => res.json()) + .then((data) => { + const stars = data.stargazers_count; + this.setState({ stars }); + }) + .catch((err) => { + console.error('Error retrieving data', err); + }); + }; + isHome = (props = this.props) => { + const valid = ['/', '/home']; + return valid.includes(props.location.pathname); + }; + setContentRef: RefCallback<HTMLDivElement> = (ref) => { + if (!ref) return; + this.content = ref; + }; + getContentHeight = () => { + if (!this.content) { + return 'auto'; + } + + return this.content.scrollHeight; + }; + render() { + const { children, history } = this.props; + const { stars } = this.state; + + return ( + <Gradient> + {children} + <Collapse + isCollapsed={!this.isHome()} + height={this.getContentHeight()} + innerRef={this.setContentRef} + > + <Container> + <h1 + css={{ + fontSize: '2.4em', + fontWeight: 'bold', + lineHeight: 1, + margin: 0, + marginTop: '-0.2em', + textShadow: '1px 1px 0 rgba(0, 82, 204, 0.33)', + color: 'inherit', + + [largeDevice]: { + fontSize: '3.6em', + }, + }} + > + React Select + </h1> + <Content + stars={stars} + onChange={(opt) => { + history.push(opt.value); + }} + /> + </Container> + </Collapse> + </Gradient> + ); + } +} + +interface CollapseProps { + readonly height: 'auto' | number; + readonly isCollapsed: boolean; + readonly innerRef: Ref<HTMLDivElement>; +} + +const Collapse = ({ + height, + isCollapsed, + innerRef, + ...props +}: CollapseProps & JSX.IntrinsicElements['div']) => { + return ( + <div + ref={innerRef} + css={{ + height: isCollapsed ? 0 : height, + overflow: isCollapsed ? 'hidden' : undefined, + transition: 'height 260ms cubic-bezier(0.2, 0, 0, 1)', + }} + {...props} + /> + ); +}; + +interface ContentProps { + readonly onChange: (option: Change) => void; + readonly stars: number; +} + +const Content = ({ onChange, stars }: ContentProps) => ( + <div + css={{ + marginTop: 16, + + [largeDevice]: { display: 'flex' }, + }} + > + <div css={{ flex: 1, [largeDevice]: { paddingRight: 30 } }}> + <p + style={{ + fontSize: '1.25em', + lineHeight: 1.4, + marginTop: -5, + }} + > + A flexible and beautiful Select Input control for ReactJS with + multiselect, autocomplete, async and creatable support. + </p> + <div css={{ flex: 1, alignItems: 'center' }}> + <GitHubButton + count={stars} + repo="https://github.com/jedwatson/react-select" + /> + <TwitterButton /> + </div> + </div> + <div + css={{ + color: 'black', + flex: '0 1 320px', + [smallDevice]: { + paddingTop: 30, + }, + }} + > + <div className="animate-dropin"> + <Select + formatOptionLabel={getLabel} + isSearchable={false} + options={changes} + onChange={(option) => { + if (option && !isArray(option)) { + onChange(option); + } + }} + value={null} + placeholder="🎉 Feature Highlights" + styles={headerSelectStyles} + /> + </div> + </div> + </div> +); + +export default withRouter(Header); diff --git a/docs/App/PageNav.tsx b/docs/App/PageNav.tsx new file mode 100644 index 0000000000..b00dd52485 --- /dev/null +++ b/docs/App/PageNav.tsx @@ -0,0 +1,185 @@ +/** @jsx jsx */ +import { Component, FunctionComponent, MouseEvent, RefCallback } from 'react'; +import { jsx } from '@emotion/react'; +import { Route, RouteComponentProps, Switch } from 'react-router-dom'; + +import { animatedScrollTo } from 'react-select/src/utils'; +import routes from './routes'; +import ScrollSpy from './ScrollSpy'; +import Sticky from './Sticky'; +import store, { Data } from '../markdown/store'; + +const navWidth = 180; +const appGutter = 20; +const contentGutter = 30; + +const smallDevice = '@media (max-width: 769px)'; +const largeDevice = '@media (min-width: 770px)'; + +const NavSection: FunctionComponent<RouteComponentProps> = () => { + const routeKeys = Object.keys(routes); + return ( + <Switch> + {routeKeys.map((r) => ( + <Route key={r} path={r} render={(p) => <PageNav {...p} />} /> + ))} + </Switch> + ); +}; + +interface NavState { + readonly links: readonly Data[]; + readonly activeId: string | null; +} + +class PageNav extends Component<RouteComponentProps, NavState> { + scrollSpy!: ScrollSpy; + state: NavState = { activeId: null, links: [] }; + componentDidMount() { + const { match } = this.props; + + // eslint-disable-next-line + this.setState({ links: store.getPageHeadings(match.path) }); + } + componentDidUpdate({ history, location }: RouteComponentProps) { + const { hash } = this.props.location; // old hash + const shouldRefresh = location.hash !== hash && history.action !== 'POP'; + + // this makes everything work, need those fresh nodes + if (shouldRefresh && this.scrollSpy.buildNodeList) { + this.scrollSpy.buildNodeList(); + } + } + getSelected = (ids: readonly (string | null)[]) => { + const activeId = ids[0]; + if (activeId !== this.state.activeId) { + this.setState({ activeId }); + } + }; + getScrollSpy: RefCallback<ScrollSpy> = (ref) => { + if (!ref) return; + this.scrollSpy = ref; + }; + handleItemClick = ({ + event, + hash, + }: { + readonly event: MouseEvent<HTMLDivElement>; + readonly hash: string; + }) => { + event.preventDefault(); + const path = `#${hash}`; + const el = document.querySelector<HTMLElement>(path); + const { history } = this.props; + + if (el && el.offsetTop) { + history.replace(path); + animatedScrollTo(window, el.offsetTop); + } + }; + render() { + const { activeId, links } = this.state; + const isSmallDevice = window.innerWidth <= 769; + + return links && links.length ? ( + <Sticky preserveHeight={isSmallDevice}> + <ScrollSpy ref={this.getScrollSpy} onChange={this.getSelected}> + <Nav> + {links.map((l) => { + const hash = l.path.slice(1); + const selected = hash === activeId; + + return l.level > 0 ? ( + <NavItem + data-hash={hash} + key={hash} + selected={selected} + level={l.level} + onClick={(event) => { + this.handleItemClick({ event, hash }); + }} + > + {l.label} + </NavItem> + ) : null; + })} + </Nav> + </ScrollSpy> + </Sticky> + ) : null; + } +} + +export default NavSection; + +const Nav = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + [smallDevice]: { + backgroundColor: 'rgba(255, 255, 255, 0.96)', + boxShadow: 'inset 0 -1px 0 rgba(0, 0, 0, 0.1)', + display: 'flex', + fontSize: 13, + marginLeft: -appGutter, + marginRight: -appGutter, + overflowX: 'auto', + WebkitOverflowScrolling: 'touch', + }, + + [largeDevice]: { + display: 'block', + float: 'left', + paddingBottom: contentGutter, + paddingTop: contentGutter, + width: navWidth, + zIndex: 1, + }, + }} + {...props} + /> +); + +interface NavItemProps { + readonly level: number; + readonly selected: boolean; +} + +const NavItem = ({ + level, + selected, + ...props +}: NavItemProps & JSX.IntrinsicElements['div']) => ( + <div + role="button" + css={{ + color: selected ? '#091e42' : '#7A869A', + cursor: 'pointer', + display: 'inline-block', + padding: `15px ${appGutter}px`, + position: 'relative', + textDecoration: 'none', + whiteSpace: 'nowrap', + + ':hover, :active': { + color: selected ? 'hsl(0, 0%, 10%)' : '#2684FF', + }, + + [smallDevice]: { + display: level === 3 ? 'none' : undefined, + boxShadow: selected ? 'inset 0 -1px 0 black' : undefined, + padding: `10px ${appGutter}px`, + }, + + [largeDevice]: { + backgroundColor: selected ? 'white' : 'transparent', + display: 'block', + fontSize: level === 3 ? '0.9em' : undefined, + fontWeight: selected ? 800 : 'inherit', + padding: '10px 20px 10px 0', + paddingLeft: level === 3 ? 10 : 0, + transition: 'padding-left 150ms ease-out', + }, + }} + {...props} + /> +); diff --git a/docs/App/ScrollSpy.tsx b/docs/App/ScrollSpy.tsx new file mode 100644 index 0000000000..6bb0bec6a7 --- /dev/null +++ b/docs/App/ScrollSpy.tsx @@ -0,0 +1,76 @@ +import React, { Component, ReactElement, RefCallback } from 'react'; +import rafSchedule from 'raf-schd'; +import NodeResolver from 'react-node-resolver'; + +interface Props { + readonly children: ReactElement; + readonly onChange: (elements: readonly (string | null)[]) => void; +} +interface State { + readonly elements: readonly HTMLElement[]; +} + +function getStyle(el: HTMLElement, prop: string) { + const val = window.getComputedStyle(el, null).getPropertyValue(prop); + return parseFloat(val); +} +function isInView(el: HTMLElement) { + let rect = el.getBoundingClientRect(); + + const topOffset = + (getStyle(el, 'padding-top') + getStyle(el, 'margin-top')) * -1; + + if (rect.top >= topOffset && rect.bottom <= window.innerHeight) { + return true; + } + + return false; +} + +export default class ScrollSpy extends Component<Props, State> { + nav: HTMLElement | undefined; + allIds = []; + state: State = { elements: [] }; + static defaultProps = { preserveHeight: false }; + componentDidMount() { + window.addEventListener('scroll', this.handleScroll, false); + this.buildNodeList(); + } + componentWillUnmount() { + window.removeEventListener('scroll', this.handleScroll); + } + handleScroll = rafSchedule((event: Event) => { + event.preventDefault(); + const { onChange } = this.props; + const { elements } = this.state; + if (!elements.length) return; + + const idsInView = elements + .filter(isInView) + .map((i) => i.getAttribute('id')); + if (idsInView.length) { + onChange(idsInView); + } + }); + getElements: RefCallback<HTMLElement> = (ref) => { + if (!ref) return; + this.nav = ref; + }; + buildNodeList = () => { + if (!this.nav) return; + + const anchorList = this.nav.querySelectorAll<HTMLElement>('[data-hash]'); + const elements = Array.from(anchorList).map( + (i) => document.querySelector<HTMLElement>(`#${i.dataset.hash}`)! + ); + + this.setState({ elements }); + }; + render() { + return ( + <NodeResolver innerRef={this.getElements}> + {this.props.children} + </NodeResolver> + ); + } +} diff --git a/docs/App/Section.tsx b/docs/App/Section.tsx new file mode 100644 index 0000000000..f21605af7d --- /dev/null +++ b/docs/App/Section.tsx @@ -0,0 +1,33 @@ +import React, { FunctionComponent } from 'react'; +import { Redirect, Route, RouteComponentProps, Switch } from 'react-router-dom'; + +import routes from './routes'; + +const Section: FunctionComponent<RouteComponentProps> = () => { + const routeKeys = Object.keys(routes); + return ( + <Switch> + {routeKeys.map((r) => ( + <Route key={r} path={r} render={(p) => <Content {...p} />} /> + ))} + <Redirect from="/" to="/home" /> + </Switch> + ); +}; + +const Content = ({ location, match }: RouteComponentProps) => { + const page = routes[match.path]; + + return ( + <Route + path={match.path} + render={() => ( + <Switch> + <Route exact key={location.key} path={match.path} component={page} /> + </Switch> + )} + /> + ); +}; + +export default Section; diff --git a/docs/App/Sticky.tsx b/docs/App/Sticky.tsx new file mode 100644 index 0000000000..b9ac213532 --- /dev/null +++ b/docs/App/Sticky.tsx @@ -0,0 +1,108 @@ +import React, { Component, CSSProperties, RefCallback } from 'react'; +import rafSchedule from 'raf-schd'; + +interface Props { + readonly preserveHeight: boolean; +} +interface State { + readonly height: number | 'auto'; + readonly isFixed: boolean; + readonly overScroll: number; + readonly scrollHeight: number | null | undefined; + readonly width: number | 'auto'; +} + +export default class Sticky extends Component<Props, State> { + innerEl: HTMLDivElement | undefined; + outerEl: HTMLDivElement | undefined; + state: State = { + height: 'auto', + isFixed: false, + overScroll: 0, + scrollHeight: null, + width: 'auto', + }; + static defaultProps = { preserveHeight: false }; + componentDidMount() { + window.addEventListener('scroll', this.handleScroll, false); + // this.handleScroll(); + } + componentWillUnmount() { + window.removeEventListener('scroll', this.handleScroll); + } + handleScroll = rafSchedule((event: Event) => { + if (!this.innerEl || !this.outerEl) return; + + const offsetBottom = 88; // footer height + const { top: outerTop } = this.outerEl.getBoundingClientRect(); + const innerTop = (this.innerEl.offsetTop && this.innerEl.offsetTop) || 0; + const scrollY = window.pageYOffset; + const maxScroll = + document.body && + document.body.scrollHeight - window.innerHeight - offsetBottom; + const { isFixed, overScroll } = this.state; + + // check for `isFixed` before setting state to prevent thrashing + if (isFixed && outerTop > 0) { + this.setState({ isFixed: false }); + } else if (!isFixed && scrollY >= innerTop) { + this.setState({ isFixed: true }); + } + + // handle over scroll + if (maxScroll && scrollY >= maxScroll) { + this.setState({ overScroll: scrollY - maxScroll }); + } else if (overScroll > 0 && scrollY < maxScroll) { + this.setState({ overScroll: 0 }); + } + }); + getOuterEl: RefCallback<HTMLDivElement> = (ref) => { + if (!ref) return; + + this.outerEl = ref; + }; + getInnerEl: RefCallback<HTMLDivElement> = (ref) => { + if (!ref) return; + + this.innerEl = ref; + + // get dimensions once, we're not interested in resize events + const firstChild = ref.firstElementChild!; + const availableHeight = window.innerHeight; + let { height, width } = firstChild.getBoundingClientRect(); + let scrollHeight; + + if (typeof this.state.height !== 'number') { + if (height > availableHeight) scrollHeight = availableHeight; + this.setState({ height, scrollHeight, width }); + } + }; + render() { + const { preserveHeight } = this.props; + const { height, isFixed, overScroll, scrollHeight, width } = this.state; + const outerStyle = isFixed && preserveHeight ? { height } : undefined; + const fixedStyles: CSSProperties = { + position: 'fixed', + top: 0, + width, + zIndex: 1, + }; + const scrollStyles = scrollHeight + ? { + height: overScroll ? scrollHeight - overScroll : scrollHeight, + overflow: 'scroll', + } + : null; + const innerStyle = isFixed + ? { ...fixedStyles, ...scrollStyles } + : undefined; + + return ( + <div ref={this.getOuterEl} style={outerStyle}> + <div ref={this.getInnerEl} style={innerStyle}> + {this.props.children} + </div> + </div> + ); + } +} diff --git a/docs/App/TwitterButton.tsx b/docs/App/TwitterButton.tsx new file mode 100644 index 0000000000..350e1654d9 --- /dev/null +++ b/docs/App/TwitterButton.tsx @@ -0,0 +1,46 @@ +/** @jsx jsx */ +import { jsx } from '@emotion/react'; + +const TwitterButton = () => ( + <div css={{ alignItems: 'center', display: 'inline-flex' }}> + <a + aria-label="Follow @JedWatson on Twitter" + css={{ + alignItems: 'center', + display: 'flex', + borderRadius: 2, + color: 'white', + border: '1px solid rgba(255, 255, 255, 0.3)', + background: 'rgba(255, 255, 255, 0.1)', + cursor: 'pointer', + fontSize: 13, + fontWeight: 'bold', + padding: '5px 12px 5px 8px', + marginLeft: '16px', + position: 'relative', + textDecoration: 'none', + + ':hover': { + border: '1px solid rgba(255, 255, 255, 0.4)', + background: 'rgba(255, 255, 255, 0.15)', + }, + }} + href="https://twitter.com/JedWatson" + target="_blank" + > + <svg + version="1.1" + width="16" + height="16" + viewBox="0 0 2000 1625.36" + fill="currentColor" + aria-hidden="true" + > + <path d="m 1999.9999,192.4 c -73.58,32.64 -152.67,54.69 -235.66,64.61 84.7,-50.78 149.77,-131.19 180.41,-227.01 -79.29,47.03 -167.1,81.17 -260.57,99.57 C 1609.3399,49.82 1502.6999,0 1384.6799,0 c -226.6,0 -410.328,183.71 -410.328,410.31 0,32.16 3.628,63.48 10.625,93.51 -341.016,-17.11 -643.368,-180.47 -845.739,-428.72 -35.324,60.6 -55.5583,131.09 -55.5583,206.29 0,142.36 72.4373,267.95 182.5433,341.53 -67.262,-2.13 -130.535,-20.59 -185.8519,-51.32 -0.039,1.71 -0.039,3.42 -0.039,5.16 0,198.803 141.441,364.635 329.145,402.342 -34.426,9.375 -70.676,14.395 -108.098,14.395 -26.441,0 -52.145,-2.578 -77.203,-7.364 52.215,163.008 203.75,281.649 383.304,284.946 -140.429,110.062 -317.351,175.66 -509.5972,175.66 -33.1211,0 -65.7851,-1.949 -97.8828,-5.738 181.586,116.4176 397.27,184.359 628.988,184.359 754.732,0 1167.462,-625.238 1167.462,-1167.47 0,-17.79 -0.41,-35.48 -1.2,-53.08 80.1799,-57.86 149.7399,-130.12 204.7499,-212.41" /> + </svg> + <span css={{ paddingLeft: 8 }}>Follow</span> + </a> + </div> +); + +export default TwitterButton; diff --git a/docs/App/components.tsx b/docs/App/components.tsx new file mode 100644 index 0000000000..519e79fb70 --- /dev/null +++ b/docs/App/components.tsx @@ -0,0 +1,137 @@ +/** @jsx jsx */ +import { Component } from 'react'; +import { + Link, + LinkProps, + RouteComponentProps, + withRouter, +} from 'react-router-dom'; +import { jsx } from '@emotion/react'; + +const navWidth = 180; +const appWidth = 800; +const appGutter = 20; +const contentGutter = 30; +const smallDevice = '@media (max-width: 769px)'; +const largeDevice = '@media (min-width: 770px)'; + +export const AppContainer = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + boxSizing: 'border-box', + marginLeft: 'auto', + marginRight: 'auto', + maxWidth: appWidth, + minHeight: '100vh', + padding: `0 ${appGutter}px`, + }} + {...props} + /> +); +export const PageContent = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + paddingBottom: contentGutter * 4, + paddingTop: contentGutter, + + [smallDevice]: { + paddingTop: contentGutter * 2, + }, + }} + {...props} + /> +); +export const AppContent = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + flex: '1 1 auto', + marginLeft: 'auto', + marginRight: 'auto', + + [largeDevice]: { + paddingLeft: navWidth + contentGutter, + }, + }} + {...props} + /> +); + +// ============================== +// Navigation +// ============================== + +export const PrimaryNav = (props: JSX.IntrinsicElements['div']) => ( + <div + css={{ + backgroundColor: 'rgba(0, 0, 0, 0.11)', + fontWeight: 500, + overflowX: 'auto', + top: 0, + width: '100%', + WebkitOverflowScrolling: 'touch', + }} + > + <div + css={{ + boxSizing: 'border-box', + display: 'flex', + maxWidth: 800, + marginLeft: 'auto', + marginRight: 'auto', + }} + {...props} + /> + </div> +); +export const PrimaryNavItem = ({ + selected, + ...props +}: LinkProps & { readonly selected: boolean }) => ( + <Link + css={{ + color: selected ? 'white' : '#DEEBFF', + display: 'inline-block', + opacity: selected ? 1 : 0.8, + padding: `20px ${appGutter}px`, + position: 'relative', + textDecoration: 'none', + whiteSpace: 'nowrap', + + ':hover, :active': { + opacity: 1, + }, + + [smallDevice]: { + fontSize: 13, + padding: `10px ${appGutter}px`, + }, + }} + {...props} + /> +); + +// ============================== +// Scroll Restoration +// ============================== + +// Return scroll to top on route change +class ScrollToTop extends Component<RouteComponentProps> { + componentDidUpdate(prevProps: RouteComponentProps) { + const { history, location } = this.props; + + // do not influence scroll on browser back/forward + if (history.action === 'POP') return; + + // no scroll when extending the current path + const pathArr = location.pathname.split('/'); + if (!prevProps.location.pathname.includes(pathArr[1])) { + window.scrollTo(0, 0); + } + } + + render() { + return this.props.children; + } +} + +export const ScrollRestoration = withRouter(ScrollToTop); diff --git a/docs/App/index.tsx b/docs/App/index.tsx new file mode 100644 index 0000000000..7e0ac0642b --- /dev/null +++ b/docs/App/index.tsx @@ -0,0 +1,93 @@ +import React, { Component, Fragment } from 'react'; +import { BrowserRouter, Route, Switch } from 'react-router-dom'; +import { Helmet } from 'react-helmet'; + +import Header from './Header'; +import Footer from './Footer'; +// import NoMatch from '../NoMatch'; + +import { + AppContainer, + AppContent, + PageContent, + PrimaryNav, + PrimaryNavItem, + ScrollRestoration, +} from './components'; +import Section from './Section'; +import PageNav from './PageNav'; +import Tests from '../Tests'; + +const sections = [ + { label: 'Home', path: '/home' }, + { label: 'Props', path: '/props' }, + { label: 'Styles', path: '/styles' }, + { label: 'Components', path: '/components' }, + { label: 'Async', path: '/async' }, + { label: 'Creatable', path: '/creatable' }, + { label: 'Advanced', path: '/advanced' }, + { label: 'TypeScript', path: '/typescript' }, + { label: 'Upgrading', path: '/upgrade' }, +]; + +export default class App extends Component { + render() { + return ( + <BrowserRouter> + <Switch> + <Route exact path="/cypress-tests" component={Tests} /> + <Route> + <div> + <Header> + <Route + render={({ location }) => ( + <PrimaryNav> + {sections.map((l) => { + const selected = location.pathname.includes(l.path); + + return ( + <PrimaryNavItem + key={l.path} + selected={selected} + to={l.path} + > + {l.label} + </PrimaryNavItem> + ); + })} + </PrimaryNav> + )} + /> + </Header> + + <ScrollRestoration> + <AppContainer> + <Helmet> + <title>React Select + + + ( + + + + +
+ + + + )} + /> + + +