├── .TODO.md ├── .browserslistrc ├── .changeset ├── README.md ├── config.json └── getChangelogEntry.js ├── .circleci └── config.yml ├── .codesandbox └── ci.json ├── .coveralls.yml ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .flowconfig ├── .flowconfig-ci ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── workflows │ └── release.yml ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc.js ├── .sweet-changelogs.js ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── babel.config.js ├── cypress.json ├── cypress ├── fixtures │ └── selectors.json └── integration │ └── select_spec.js ├── docs ├── App │ ├── API.js │ ├── Footer.js │ ├── GitHubButton.js │ ├── Guide.js │ ├── Header.js │ ├── PageNav.js │ ├── ScrollSpy.js │ ├── Section.js │ ├── Sticky.js │ ├── TwitterButton.js │ ├── components.js │ ├── index.js │ └── routes.js ├── CHANGELOG.md ├── ExampleWrapper.js ├── NoMatch.js ├── PropTypes │ ├── Async.js │ ├── Creatable.js │ ├── Select.js │ ├── components │ │ ├── ClearIndicator.js │ │ ├── Control.js │ │ ├── DropdownIndicator.js │ │ ├── Group.js │ │ ├── IndicatorsContainer.js │ │ ├── IndicatorsSeparator.js │ │ ├── Input.js │ │ ├── LoadingIndicator.js │ │ ├── LoadingMessage.js │ │ ├── Menu.js │ │ ├── MenuList.js │ │ ├── MultiValue.js │ │ ├── MultiValueContainer.js │ │ ├── MultiValueLabel.js │ │ ├── MultiValueRemove.js │ │ ├── NoOptionsMessage.js │ │ ├── Option.js │ │ ├── Placeholder.js │ │ ├── SelectContainer.js │ │ ├── SingleValue.js │ │ └── ValueContainer.js │ └── stateManager.js ├── Svg.js ├── Tests.js ├── _redirects ├── data.js ├── examples │ ├── AccessingInternals.js │ ├── AnimatedMulti.js │ ├── AsyncCallbacks.js │ ├── AsyncCreatable.js │ ├── AsyncMulti.js │ ├── AsyncPromises.js │ ├── BasicGrouped.js │ ├── BasicMulti.js │ ├── BasicSingle.js │ ├── ControlledMenu.js │ ├── CreatableAdvanced.js │ ├── CreatableInputOnly.js │ ├── CreatableMulti.js │ ├── CreatableSingle.js │ ├── CreateFilter.js │ ├── CustomClearIndicator.js │ ├── CustomControl.js │ ├── CustomDropdownIndicator.js │ ├── CustomFilterOptions.js │ ├── CustomGetOptionLabel.js │ ├── CustomGetOptionValue.js │ ├── CustomGroup.js │ ├── CustomGroupHeading.js │ ├── CustomIndicatorSeparator.js │ ├── CustomIndicatorsContainer.js │ ├── CustomInput.js │ ├── CustomIsOptionDisabled.js │ ├── CustomLoadingIndicator.js │ ├── CustomLoadingMessage.js │ ├── CustomMenu.js │ ├── CustomMenuList.js │ ├── CustomMultiValueContainer.js │ ├── CustomMultiValueLabel.js │ ├── CustomMultiValueRemove.js │ ├── CustomNoOptionsMessage.js │ ├── CustomOption.js │ ├── CustomPlaceholder.js │ ├── CustomSelectContainer.js │ ├── CustomSingleValue.js │ ├── CustomValueContainer.js │ ├── DefaultOptions.js │ ├── Experimental.js │ ├── FixedOptions.js │ ├── MenuBuffer.js │ ├── MenuPortal.js │ ├── MultiSelectSort.js │ ├── OnSelectResetsInput.js │ ├── Popout.js │ ├── StyleCompositionExample.js │ ├── StyledMulti.js │ ├── StyledSingle.js │ ├── Theme.js │ └── index.js ├── favicon.ico ├── index.css ├── index.html ├── index.js ├── markdown │ ├── renderer.js │ └── store.js ├── package.json ├── pages │ ├── advanced │ │ └── index.js │ ├── async │ │ └── index.js │ ├── components │ │ └── index.js │ ├── creatable │ │ └── index.js │ ├── home │ │ └── index.js │ ├── props │ │ └── index.js │ ├── styles │ │ └── index.js │ └── upgradeGuide │ │ ├── index.js │ │ └── props.js ├── styled-components.js ├── types.js └── webpack.config.js ├── enzymeAdapter.setup.js ├── flow-typed └── npm │ ├── jest_v22.x.x.js │ └── react-router-dom_v4.x.x.js ├── netlify.toml ├── package.json ├── packages └── react-select │ ├── CHANGELOG.md │ ├── README.md │ ├── animated │ └── package.json │ ├── async-creatable │ └── package.json │ ├── async │ └── package.json │ ├── base │ └── package.json │ ├── creatable │ └── package.json │ ├── package.json │ └── src │ ├── Async.js │ ├── AsyncCreatable.js │ ├── Creatable.js │ ├── NonceProvider.js │ ├── Select.js │ ├── __tests__ │ ├── Async.test.js │ ├── AsyncCreatable.test.js │ ├── Creatable.test.js │ ├── Select.test.js │ ├── StateManaged.test.js │ ├── __snapshots__ │ │ ├── Async.test.js.snap │ │ ├── AsyncCreatable.test.js.snap │ │ ├── Creatable.test.js.snap │ │ ├── Select.test.js.snap │ │ └── StateManaged.test.js.snap │ └── constants.js │ ├── accessibility │ └── index.js │ ├── animated │ ├── Input.js │ ├── MultiValue.js │ ├── Placeholder.js │ ├── SingleValue.js │ ├── ValueContainer.js │ ├── index.js │ └── transitions.js │ ├── builtins.js │ ├── components │ ├── Control.js │ ├── Group.js │ ├── Input.js │ ├── Menu.js │ ├── MultiValue.js │ ├── Option.js │ ├── Placeholder.js │ ├── SingleValue.js │ ├── containers.js │ ├── index.js │ └── indicators.js │ ├── diacritics.js │ ├── filters.js │ ├── index.js │ ├── internal │ ├── A11yText.js │ ├── DummyInput.js │ ├── NodeResolver.js │ ├── ScrollBlock.js │ ├── ScrollCaptor.js │ ├── ScrollLock │ │ ├── constants.js │ │ ├── index.js │ │ └── utils.js │ ├── index.js │ └── react-fast-compare.js │ ├── stateManager.js │ ├── styles.js │ ├── theme.js │ ├── types.js │ └── utils.js ├── typings ├── extract-react-types-loader.js └── raw-loader.js └── yarn.lock /.TODO.md: -------------------------------------------------------------------------------- 1 | # Changes planned from Beta -> RC: 2 | 3 | * [ ] Look into package size reduction, extract optional modules, e.g 4 | * createFilter could be optional, saving 2.6k gz 5 | * vendor simple Menu by default, allow opt-in to advanced usage 6 | * [ ] Bind getStyles for each component 7 | 8 | --- 9 | 10 | # Order of focus: 11 | 12 | * [ ] Review how the `required` state of the `` can be handled 13 | * [ ] Example of how to implement Separators 14 | * [ ] Handle Header and Footer elements in the Menu 15 | * [ ] Keyboard focusing of values in multi select 16 | 17 | --- 18 | 19 | # Review: 20 | 21 | ### Select Component Props 22 | 23 | * [ ] `backspaceToRemoveMessage` _investigate_ 24 | * [x] `className` _investigate_ might need to move the className util into commonProps 25 | * [x] `openOnClick` / `openOnFocus` needs implementation 26 | * [ ] `required` _|||_ this has some complex behaviour in v1 which may or may not be needed 27 | * [x] `tabIndex` needs implementation 28 | 29 | #### Done 30 | 31 | * [x] `id` 32 | * [x] `inputId` falls back to `react-select-${props.instanceId}-input` 33 | * [x] `autoBlur` **REMOVED** can be handled with `onChange` 34 | * [x] `autosize` **REMOVED** can replace `` component 35 | * [x] `onClose` --> `onMenuClose` 36 | * [x] `onOpen` --> `onMenuOpen` 37 | * [x] `onBlurResetsInput` / `onCloseResetsInput` / `onSelectResetsInput` **REMOVED** now that `inputValue` can be controlled, these should be unnecessary 38 | * [x] `onMenuScrollToBottom` implemented 39 | * [x] `clearable` --> `isClearable` 40 | * [x] `rtl` --> `isRTL` 41 | * [x] `pageSize` 42 | * [x] `menuShouldScrollIntoView` 43 | * [x] `searchable` --> `isSearchable` 44 | * [x] `resetValue` **REMOVED** can be handled with `onInputChange` 45 | * [x] `clearAllText` / `clearValueText` **REMOVED** title no longer applied, can replace `` 46 | 47 | ### Async Component Props 48 | 49 | * [ ] `autoLoad` _investigate_ should be considered in conjunction with `searchPromptText`, may affect `defaultOptions` behaviour 50 | * [ ] `searchPromptText` _investigate_ how do we know to display it? (https://goo.gl/PLTwV5) 51 | 52 | --- 53 | 54 | # Maybe: 55 | 56 | * [ ] Virtualisation 57 | * [ ] Prevent values from being popped, was `option.clearableValue === false` 58 | * [ ] Async w/ pagination 59 | * [ ] Extention point to reorder / change menu options array when it's created 60 | 61 | --- 62 | 63 | # Later: 64 | 65 | * [ ] Reordering of Options (drag and drop) 66 | 67 | --- 68 | 69 | # Done: 70 | 71 | * [x] Tags mode (Creatable) 72 | * [x] Handle changing of isDisabled prop 73 | * [x] Better mobile support and touch handling 74 | * [x] Better control of flip behaviour 75 | * [x] Scroll the menu into view when it opens 76 | * [x] Handle touch outside (see v1 implementation) 77 | * [x] Review implementation of `isSearchable` prop (creates a "fake" input) 78 | * [x] Async + Creatable variant 79 | * [x] Cleanup 80 | * [x] Documentation - Props, Customisation 81 | * [x] Upgrade Guide from v1 -> v2 82 | * [x] Lock scrolling on Menu (enable with prop) 83 | * [x] Make inputValue a controllable prop 84 | * [x] Make menuIsOpen a controllable prop 85 | * [x] Finalise theme and style customisation framework 86 | * [x] Remove `disabledKey`, clean up similar functionality 87 | * [x] Pseudo-focus Options 88 | * [x] Keyboard navigation 89 | * [x] Make `isDisabled` / `isSelected` etc. props 90 | * [x] Scroll to focused option 91 | * [x] Add `autofocus` prop 92 | * [x] Add HTML Form Input 93 | * [x] Async with: 94 | * [x] * promises 95 | * [x] * better loading state and behaviour 96 | * [x] Pass more (and consistent?) props and state from Select to Components 97 | * [x] Fix issue with how the mouse hover interacts with keyboard scrolling 98 | * [x] Ability to customise built-in strings 99 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 0.25% 2 | ie 11 3 | not op_mini all 4 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | 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) 4 | 5 | To help you get started though, here are some things you should know about this folder: 6 | 7 | ## Changesets are automatically generated 8 | 9 | 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. 10 | 11 | ## Each changeset is its own folder 12 | 13 | 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. 14 | 15 | ## Changesets are automatically removed 16 | 17 | 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. 18 | 19 | ## Changesets come in two parts 20 | 21 | You should treat these parts quite differently: 22 | 23 | - `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. 24 | - `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. 25 | 26 | ## I want to edit the information in a `changes.json` - how do I do it safely? 27 | 28 | The best option is to make a new changeset using the changeset command, copy over the `changes.md`, then delete the old changeset. 29 | 30 | ## Can I rename the folder for my changeset? 31 | 32 | 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. 33 | 34 | ## Can I manually delete changesets? 35 | 36 | You can, but you should be aware this will remove the intent to release communicated by the changeset, and should be done with caution. 37 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@0.2.1/schema.json", 3 | "changelog": "./getChangelogEntry", 4 | "commit": false, 5 | "linked": [], 6 | "access": "public" 7 | } 8 | -------------------------------------------------------------------------------- /.changeset/getChangelogEntry.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const { getInfo } = require('@changesets/get-github-info'); 3 | 4 | const getReleaseLine = async (changeset, type) => { 5 | const [firstLine, ...futureLines] = changeset.summary 6 | .split('\n') 7 | .map(l => l.trimRight()); 8 | let { links } = await getInfo({ 9 | repo: 'marcelltoth/react-select-reborn', 10 | commit: changeset.commit, 11 | }); 12 | return `- ${links.commit}${links.pull === null ? '' : ` ${links.pull}`}${ 13 | links.user === null ? '' : ` Thanks ${links.user}!` 14 | } - ${firstLine}\n${futureLines.map(l => ` ${l}`).join('\n')}`; 15 | }; 16 | 17 | const getDependencyReleaseLine = async (changesets, dependenciesUpdated) => { 18 | if (dependenciesUpdated.length === 0) return ''; 19 | 20 | const changesetLinks = changesets.map( 21 | changeset => `- Updated dependencies [${changeset.commit}]:` 22 | ); 23 | 24 | const updatedDepenenciesList = dependenciesUpdated.map( 25 | dependency => ` - ${dependency.name}@${dependency.version}` 26 | ); 27 | 28 | return [...changesetLinks, ...updatedDepenenciesList].join('\n'); 29 | }; 30 | 31 | module.exports = { 32 | getReleaseLine, 33 | getDependencyReleaseLine, 34 | }; 35 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | docker_defaults: &docker_defaults 4 | docker: 5 | - image: cypress/base:8 6 | environment: 7 | TERM: xterm 8 | working_directory: ~/project/repo 9 | 10 | attach_workspace: &attach_workspace 11 | attach_workspace: 12 | at: ~/project 13 | 14 | install_steps: &install_steps 15 | steps: 16 | - checkout 17 | - restore_cache: 18 | name: Restore node_modules cache 19 | keys: 20 | - dependency-cache-{{ .Branch }}-{{ checksum "package.json" }} 21 | - dependency-cache-{{ .Branch }}- 22 | - dependency-cache- 23 | - run: 24 | name: Installing Dependencies 25 | command: | 26 | yarn install --silent 27 | - save_cache: 28 | name: Save node_modules cache 29 | key: dependency-cache-{{ .Branch }}-{{ checksum "package.json" }} 30 | paths: 31 | - node_modules/ 32 | - persist_to_workspace: 33 | root: ~/project 34 | paths: 35 | - repo 36 | 37 | workflows: 38 | version: 2 39 | build_pipeline: 40 | jobs: 41 | - build 42 | - unit_test: 43 | requires: 44 | - build 45 | - end_to_end: 46 | requires: 47 | - build 48 | jobs: 49 | build: 50 | <<: *docker_defaults 51 | <<: *install_steps 52 | unit_test: 53 | <<: *docker_defaults 54 | steps: 55 | - *attach_workspace 56 | - run: 57 | name: Running unit tests 58 | command: | 59 | yarn lint 60 | yarn flow check --flowconfig-name=.flowconfig-ci 61 | yarn test:jest 62 | yarn coveralls 63 | end_to_end: 64 | <<: *docker_defaults 65 | steps: 66 | - *attach_workspace 67 | - run: 68 | name: Running E2E tests 69 | command: | 70 | yarn e2e 71 | -------------------------------------------------------------------------------- /.codesandbox/ci.json: -------------------------------------------------------------------------------- 1 | 2 | 3 | { 4 | "buildCommand": "build", 5 | "packages": ["packages/*"], 6 | "sandboxes": ["nfmxw"] 7 | } 8 | 9 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service-name: travis-ci 2 | repo_token: EOOUxYQKrQRMVR81s6aqhNHfU8VJhmSz7 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | 16 | [.circleci/config.yml] 17 | indent_size = 4 18 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | coverage/* 2 | cypress/plugins/* 3 | cypress/support/* 4 | **/dist/* 5 | flow-typed/* 6 | lib/* 7 | node_modules/* 8 | **/node_modules/* 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: 'babel-eslint', 3 | env: { 4 | browser: true, 5 | es6: true, 6 | node: true, 7 | }, 8 | plugins: ['react'], 9 | rules: { 10 | 'no-unused-vars': [ 11 | 'error', 12 | { 13 | args: 'after-used', 14 | argsIgnorePattern: '^event$', 15 | ignoreRestSiblings: true, 16 | vars: 'all', 17 | varsIgnorePattern: 'jsx|emotionJSX' 18 | }, 19 | ], 20 | curly: [2, 'multi-line'], 21 | 'jsx-quotes': 1, 22 | 'no-shadow': 1, 23 | 'no-trailing-spaces': 1, 24 | 'no-underscore-dangle': 1, 25 | 'no-unused-expressions': 1, 26 | 'object-curly-spacing': [1, 'always'], 27 | quotes: [2, 'single', 'avoid-escape'], 28 | 'react/jsx-boolean-value': 1, 29 | 'react/jsx-no-undef': 1, 30 | 'react/jsx-uses-react': 1, 31 | 'react/jsx-uses-vars': 1, 32 | 'react/jsx-wrap-multilines': 1, 33 | 'react/no-did-mount-set-state': 1, 34 | 'react/no-did-update-set-state': 1, 35 | 'react/no-unknown-property': 1, 36 | 'react/react-in-jsx-scope': 1, 37 | 'react/self-closing-comp': 1, 38 | 'react/sort-prop-types': 1, 39 | semi: 2, 40 | strict: 0, 41 | }, 42 | }; 43 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | .*/node_modules/cypress/.* 3 | 4 | [untyped] 5 | .*/node_modules/@atlaskit/tooltip/dist/cjs/components/Marshal.js.flow 6 | .*/node_modules/@atlaskit/layer-manager/dist/cjs/components/FocusLock/index.js.flow 7 | .*/node_modules/@atlaskit/layer-manager/dist/cjs/components/gateway/components/Gateway.js.flow 8 | .*/node_modules/@atlaskit/layer-manager/dist/cjs/components/withRenderTarget.js.flow 9 | 10 | [include] 11 | 12 | [libs] 13 | flow-typed 14 | 15 | [lints] 16 | unclear-type=warn 17 | untyped-type-import=error 18 | 19 | [options] 20 | module.name_mapper='\!\!raw-loader\!.*' -> '/typings/raw-loader.js' 21 | module.name_mapper='\!\!extract-react-types-loader\!.*' -> '/typings/extract-react-types-loader.js' 22 | 23 | [strict] 24 | -------------------------------------------------------------------------------- /.flowconfig-ci: -------------------------------------------------------------------------------- 1 | [ignore] 2 | .*/node_modules/cypress/.* 3 | 4 | [untyped] 5 | .*/node_modules/@atlaskit/tooltip/dist/cjs/components/Marshal.js.flow 6 | .*/node_modules/@atlaskit/layer-manager/dist/cjs/components/FocusLock/index.js.flow 7 | .*/node_modules/@atlaskit/layer-manager/dist/cjs/components/gateway/components/Gateway.js.flow 8 | .*/node_modules/@atlaskit/layer-manager/dist/cjs/components/withRenderTarget.js.flow 9 | 10 | [include] 11 | 12 | [libs] 13 | flow-typed 14 | 15 | [lints] 16 | unclear-type=warn 17 | untyped-type-import=error 18 | 19 | [options] 20 | module.name_mapper='\!\!raw-loader\!.*' -> '/typings/raw-loader.js' 21 | module.name_mapper='\!\!extract-react-types-loader\!.*' -> '/typings/extract-react-types-loader.js' 22 | server.max_workers=1 23 | sharedmemory.hash_table_pow=21 24 | 25 | [strict] 26 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for your interest in React-Select. All forms of contribution are 4 | welcome, from issue reports to PRs and documentation / write-ups. 5 | 6 | Before you open a PR: 7 | 8 | * In development, run `yarn start` to build (+watch) the project source, and run 9 | the [development server](http://localhost:8000). 10 | * Please ensure all the examples work correctly after your change. If you're 11 | adding a major new use-case, add a new example demonstrating its use. 12 | * Be careful to follow the code style of the project. Run `yarn lint` after 13 | your changes and ensure you do not introduce any new errors or warnings. 14 | * This repository uses `flow`, please run `yarn flow` after your changes to ensure 15 | that you do not introduce any new type errors. 16 | 17 | * Ensure that your effort is aligned with the project's roadmap by talking to 18 | the maintainers, especially if you are going to spend a lot of time on it. 19 | * Make sure there's an issue open for any work you take on and intend to submit 20 | as a pull request - it helps core members review your concept and direction 21 | early and is a good way to discuss what you're planning to do. 22 | * If you open an issue and are interested in working on a fix, please let us 23 | know. We'll help you get started, rather than adding it to the queue. 24 | * Make sure you do not add regressions by running `yarn test`. 25 | * Where possible, include tests with your changes, either that demonstrates the 26 | bug, or tests the new functionality. If you're not sure how to test your 27 | changes, feel free to ping @gwyneplaine or @JedWatson 28 | * Run `yarn coveralls` to check that the coverage hasn't dropped, and look at the 29 | report (under the generated `coverage` directory) to check that your changes are 30 | covered 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Thanks for using react-select! 2 | 3 | Before creating an issue... 4 | 5 | # Are you asking a question? 6 | Please don't file GitHub issues to ask questions. Use Stack Overflow with a [#react-select](http://stackoverflow.com/questions/tagged/react-select) tag 7 | 8 | 9 | # Are you reporting a bug or runtime error? 10 | Please include a test case that demonstrates the issue you're reporting! 11 | This is very helpful to maintainers in order to help us see the issue you're seeing. 12 | 13 | To report bugs against react-select v2 please fork the following code-sandbox: 14 | https://codesandbox.io/s/k5rvn9z3lv 15 | 16 | To report bugs against react-select v1 please fork the following code-sandbox: 17 | https://codesandbox.io/s/n34mq0743j 18 | 19 | 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. 20 | 21 | 22 | # Are you making a feature request? 23 | Provide as much information as possible about your requested feature. Here are a few questions you may consider answering: 24 | 25 | * What's your use case? (Tell us about your application and what problem you're trying to solve.) 26 | * What interface do you have in mind? (What new properties or methods do you think might be helpful?) 27 | * Can you point to similar functionality with any existing libraries or components? (Working demos can be helpful.) 28 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | release: 10 | name: Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout Repo 14 | uses: actions/checkout@master 15 | with: 16 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 17 | fetch-depth: 0 18 | 19 | - name: Setup Node.js 10.x 20 | uses: actions/setup-node@master 21 | with: 22 | node-version: 10.x 23 | 24 | - name: Install Yarn 25 | run: npm install --global yarn 26 | 27 | - name: Install Dependencies 28 | run: yarn 29 | 30 | - name: Create Release Pull Request or Publish to npm 31 | uses: changesets/action@master 32 | with: 33 | publish: yarn release 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build 2 | lib 3 | dist 4 | docs/dist 5 | .env 6 | 7 | # Logs 8 | logs 9 | *.log 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | 16 | # Coverage tools 17 | lib-cov 18 | coverage 19 | .nyc_output 20 | 21 | # Cypress 22 | cypress/videos 23 | cypress/screenshots 24 | cypress/support 25 | cypress/plugins 26 | 27 | # Dependency directory 28 | node_modules 29 | bower_components 30 | 31 | # Publish directory 32 | .publish 33 | 34 | # Editor artefacts 35 | .idea 36 | 37 | # Other 38 | .DS_Store 39 | .env 40 | package-lock.json 41 | 42 | # Notes 43 | .NOTES.md 44 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | trailingComma: 'es5', 4 | }; 5 | -------------------------------------------------------------------------------- /.sweet-changelogs.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | filename: 'HISTORY.md', 3 | message: ({ pr, user }) => 4 | `* ${pr.title}, thanks [${user.name || 5 | user.login}](${user.url}) - [see PR](${pr.url})`, 6 | }; 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for your interest in React-Select. All forms of contribution are 4 | welcome, from issue reports to PRs and documentation / write-ups. 5 | 6 | Before you open a PR: 7 | 8 | * In development, run `yarn start` to build (and watch) the project source, and run 9 | the [development server](http://localhost:8000). 10 | * Please ensure all the examples work correctly after your change. If you're 11 | adding a major new use-case, add a new example `/docs/examples` and subsequent documentation demonstrating its use `/docs/pages`. 12 | * Ensure that your effort is aligned with the project's roadmap by talking to 13 | the maintainers, especially if you are going to spend a lot of time on it. 14 | * Make sure there's an issue open for any work you take on and intend to submit 15 | as a pull request - it helps core members review your concept and direction 16 | early and is a good way to discuss what you're planning to do. 17 | * If you open an issue and are interested in working on a fix, please let us 18 | know. We'll help you get started, rather than inadvertently doubling up on your hard work. 19 | * Make sure you do not add regressions by running `yarn test`. 20 | * Where possible, include tests with your changes, either that demonstrates the 21 | bug, or tests the new functionality. If you're not sure how to test your 22 | changes, feel free to ping @gwyneplaine 23 | * Please [follow our established coding conventions](https://github.com/keystonejs/keystone/wiki/Coding-Standards) 24 | (with regards to formatting, etc) 25 | * All new features and changes need documentation. 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Jed Watson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | 'emotion', 4 | ['@babel/plugin-proposal-class-properties', { loose: true }], 5 | ], 6 | presets: [ 7 | ['@babel/preset-env', { loose: true }], 8 | '@babel/preset-react', 9 | '@babel/preset-flow', 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "http://localhost:8000/cypress-tests", 3 | "screenshotOnHeadlessFailure": false, 4 | "videoRecording": false 5 | } 6 | -------------------------------------------------------------------------------- /cypress/fixtures/selectors.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleBasic": "#cypress-single", 3 | "singleBasicSelect": "#basic-select-single", 4 | "singleClearable": "#cypress-single-clearable", 5 | "singleClearableSelect": "#clearable-select-single", 6 | "singleGroupedSelect": "#grouped-options-single", 7 | "checkboxDisable": ".disable-checkbox", 8 | "checkboxEscapeClearsValue": ".escape-clears-value-checkbox", 9 | "groupHeading": ".react-select__group-heading", 10 | "indicatorClear": ".react-select__clear-indicator", 11 | "indicatorDropdown": ".react-select__dropdown-indicator", 12 | "menu": ".react-select__menu", 13 | "menuOption": ".react-select__option", 14 | "noOptionsValue": ".react-select__menu-notice--no-options", 15 | "placeholder": ".react-select__placeholder", 16 | "singleValue": ".react-select__single-value", 17 | "menuSingle": "#basic-select-single .react-select__menu", 18 | "singleSelectSingleInput": "#react-select-basic-select-single-input", 19 | "toggleMenuSingle": "#basic-select-single .react-select__dropdown-indicator", 20 | "firstMultiValueRemove": "#multi-select .react-select__multi-value__remove:first", 21 | "menuMulti": "#multi-select .react-select__menu", 22 | "multiSelectDefaultValues": "#multi-select .react-select__multi-value", 23 | "multiSelectInput": "#react-select-multi-select-input", 24 | "placeHolderMulti": "#multi-select .react-select__placeholder", 25 | "toggleMenuMulti": "#multi-select .react-select__dropdown-indicator" 26 | } -------------------------------------------------------------------------------- /docs/App/API.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import { Route, Switch } from 'react-router-dom'; 5 | 6 | import type { RouterProps } from '../types'; 7 | import routes from './routes'; 8 | 9 | const API = ({ match }: RouterProps) => { 10 | const { path, Component } = routes[match.params.section]; 11 | return ( 12 | 13 | 14 | 15 | ); 16 | }; 17 | 18 | export default API; 19 | -------------------------------------------------------------------------------- /docs/App/Footer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /** @jsx jsx */ 3 | import { type Node } from 'react'; 4 | import { jsx } from '@emotion/core'; 5 | 6 | // const smallDevice = '@media (max-width: 769px)'; 7 | const largeDevice = '@media (min-width: 770px)'; 8 | 9 | const Wrapper = props => ( 10 |
20 | ); 21 | const Container = props => ( 22 |
41 | ); 42 | const A = props => ( 43 | 55 | ); 56 | 57 | export default function Footer(): Node { 58 | return ( 59 | 60 | 61 |

Copyright © Jed Watson, 2019. MIT Licensed.

62 |

63 | Thanks to Thinkmill and{' '} 64 | Atlassian for supporting this 65 | project. 66 |

67 | 68 | 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /docs/App/GitHubButton.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /** @jsx jsx */ 3 | import { jsx } from '@emotion/core'; 4 | 5 | type Props = { count: number, repo: string }; 6 | 7 | const StarButton = ({ count, repo }: Props) => ( 8 | 92 | ); 93 | 94 | export default StarButton; 95 | -------------------------------------------------------------------------------- /docs/App/Guide.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import { Route, Switch } from 'react-router-dom'; 5 | 6 | import type { RouterProps } from '../types'; 7 | import routes from './routes'; 8 | 9 | const Guide = ({ match }: RouterProps) => { 10 | const { path, Component } = routes[match.params.guide]; 11 | return ( 12 | 13 | 14 | 15 | ); 16 | }; 17 | 18 | export default Guide; 19 | -------------------------------------------------------------------------------- /docs/App/ScrollSpy.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React, { 4 | Component, 5 | type ElementRef, 6 | type Element as ReactElement, 7 | } from 'react'; 8 | import rafSchedule from 'raf-schd'; 9 | import NodeResolver from 'react-node-resolver'; 10 | 11 | type Props = { 12 | children: ReactElement<*>, 13 | onChange: (Array) => void, 14 | }; 15 | type State = { 16 | elements: Array, 17 | }; 18 | 19 | function getStyle(el, prop, numeric = true) { 20 | const val = window.getComputedStyle(el, null).getPropertyValue(prop); 21 | return numeric ? parseFloat(val) : val; 22 | } 23 | function isInView(el) { 24 | let rect = el.getBoundingClientRect(); 25 | 26 | const topOffset = 27 | (getStyle(el, 'padding-top') + getStyle(el, 'margin-top')) * -1; 28 | 29 | if (rect.top >= topOffset && rect.bottom <= window.innerHeight) { 30 | return true; 31 | } 32 | 33 | return false; 34 | } 35 | 36 | export default class ScrollSpy extends Component { 37 | nav: Element; 38 | allIds = []; 39 | state = { elements: [] }; 40 | static defaultProps = { preserveHeight: false }; 41 | componentDidMount() { 42 | window.addEventListener('scroll', this.handleScroll, false); 43 | this.buildNodeList(); 44 | } 45 | componentWillUnmount() { 46 | window.removeEventListener('scroll', this.handleScroll); 47 | } 48 | handleScroll = rafSchedule((event: Event) => { 49 | event.preventDefault(); 50 | const { onChange } = this.props; 51 | const { elements } = this.state; 52 | if (!elements.length) return; 53 | 54 | const idsInView = elements.filter(isInView).map(i => i.getAttribute('id')); 55 | if (idsInView.length) { 56 | onChange(idsInView); 57 | } 58 | }); 59 | getElements = (ref: ElementRef<*>) => { 60 | if (!ref) return; 61 | this.nav = ref; 62 | }; 63 | buildNodeList = () => { 64 | if (!this.nav) return; 65 | 66 | const anchorList = this.nav.querySelectorAll('[data-hash]'); 67 | const els = Array.from(anchorList).map(i => 68 | document.querySelector(`#${i.dataset.hash}`) 69 | ); 70 | 71 | const elements = ((els: any): Array); // suck it flow... 72 | 73 | this.setState({ elements }); 74 | }; 75 | render() { 76 | return ( 77 | 78 | {this.props.children} 79 | 80 | ); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /docs/App/Section.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import { Redirect, Route, Switch } from 'react-router-dom'; 4 | 5 | import type { RouterProps } from '../types'; 6 | import routes from './routes'; 7 | 8 | const Section = () => { 9 | const routeKeys = Object.keys(routes); 10 | return ( 11 | 12 | {routeKeys.map(r => ( 13 | } /> 14 | ))} 15 | 16 | 17 | ); 18 | }; 19 | 20 | const Content = ({ location, match }: RouterProps) => { 21 | const page = routes[match.path]; 22 | 23 | return ( 24 | ( 27 | 28 | 29 | 30 | )} 31 | /> 32 | ); 33 | }; 34 | 35 | export default Section; 36 | -------------------------------------------------------------------------------- /docs/App/Sticky.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React, { 4 | Component, 5 | type ElementRef, 6 | type Element as ReactElement, 7 | } from 'react'; 8 | import rafSchedule from 'raf-schd'; 9 | 10 | type Props = { 11 | children: ReactElement<*>, // Component | Element 12 | preserveHeight: boolean, 13 | }; 14 | type State = { 15 | height: number | 'auto', 16 | isFixed: boolean, 17 | overScroll: number, 18 | scrollHeight: number | null, 19 | width: number | 'auto', 20 | }; 21 | 22 | export default class Sticky extends Component { 23 | innerEl: ElementRef<'div'>; 24 | outerEl: ElementRef<'div'>; 25 | state = { 26 | height: 'auto', 27 | isFixed: false, 28 | overScroll: 0, 29 | scrollHeight: null, 30 | width: 'auto', 31 | }; 32 | static defaultProps = { preserveHeight: false }; 33 | componentDidMount() { 34 | window.addEventListener('scroll', this.handleScroll, false); 35 | // this.handleScroll(); 36 | } 37 | componentWillUnmount() { 38 | window.removeEventListener('scroll', this.handleScroll); 39 | } 40 | handleScroll = rafSchedule((event: Event) => { 41 | if (!this.innerEl || !this.outerEl) return; 42 | 43 | const offsetBottom = 88; // footer height 44 | const { top: outerTop } = this.outerEl.getBoundingClientRect(); 45 | const innerTop = (this.innerEl.offsetTop && this.innerEl.offsetTop) || 0; 46 | const scrollY = window.pageYOffset; 47 | const maxScroll = 48 | document.body && 49 | document.body.scrollHeight - window.innerHeight - offsetBottom; 50 | const { isFixed, overScroll } = this.state; 51 | 52 | // check for `isFixed` before setting state to prevent thrashing 53 | if (isFixed && outerTop > 0) { 54 | this.setState({ isFixed: false }); 55 | } else if (!isFixed && scrollY >= innerTop) { 56 | this.setState({ isFixed: true }); 57 | } 58 | 59 | // handle over scroll 60 | if (maxScroll && scrollY >= maxScroll) { 61 | this.setState({ overScroll: scrollY - maxScroll }); 62 | } else if (overScroll > 0 && scrollY < maxScroll) { 63 | this.setState({ overScroll: 0 }); 64 | } 65 | }); 66 | getOuterEl = (ref: ElementRef<*>) => { 67 | if (!ref) return; 68 | 69 | this.outerEl = ref; 70 | }; 71 | getInnerEl = (ref: ElementRef<*>) => { 72 | if (!ref) return; 73 | 74 | this.innerEl = ref; 75 | 76 | // get dimensions once, we're not interested in resize events 77 | const firstChild = ref.firstElementChild; 78 | const availableHeight = window.innerHeight; 79 | let { height, width } = firstChild.getBoundingClientRect(); 80 | let scrollHeight; 81 | 82 | if (typeof this.state.height !== 'number') { 83 | if (height > availableHeight) scrollHeight = availableHeight; 84 | this.setState({ height, scrollHeight, width }); 85 | } 86 | }; 87 | render() { 88 | const { preserveHeight } = this.props; 89 | const { height, isFixed, overScroll, scrollHeight, width } = this.state; 90 | const outerStyle = isFixed && preserveHeight ? { height } : null; 91 | const fixedStyles = { position: 'fixed', top: 0, width, zIndex: 1 }; 92 | const scrollStyles = scrollHeight 93 | ? { 94 | height: overScroll ? scrollHeight - overScroll : scrollHeight, 95 | overflow: 'scroll', 96 | } 97 | : null; 98 | const innerStyle = isFixed ? { ...fixedStyles, ...scrollStyles } : null; 99 | 100 | return ( 101 |
102 |
103 | {this.props.children} 104 |
105 |
106 | ); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /docs/App/TwitterButton.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /** @jsx jsx */ 3 | import { jsx } from '@emotion/core'; 4 | 5 | const TwitterButton = () => ( 6 | 45 | ); 46 | 47 | export default TwitterButton; 48 | -------------------------------------------------------------------------------- /docs/App/components.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /** @jsx jsx */ 3 | import { Component, type ElementConfig } from 'react'; 4 | import { Link, withRouter } from 'react-router-dom'; 5 | import { jsx } from '@emotion/core'; 6 | 7 | const navWidth = 180; 8 | const appWidth = 800; 9 | const appGutter = 20; 10 | const contentGutter = 30; 11 | const smallDevice = '@media (max-width: 769px)'; 12 | const largeDevice = '@media (min-width: 770px)'; 13 | 14 | export const AppContainer = (props: any) => ( 15 |
26 | ); 27 | export const PageContent = (props: any) => ( 28 |
39 | ); 40 | export const AppContent = (props: any) => ( 41 |
53 | ); 54 | 55 | // ============================== 56 | // Navigation 57 | // ============================== 58 | 59 | export const PrimaryNav = (props: any) => ( 60 |
70 |
80 |
81 | ); 82 | type PrimaryNavItemProps = ElementConfig & { selected: boolean }; 83 | export const PrimaryNavItem = ({ selected, ...props }: PrimaryNavItemProps) => ( 84 | 105 | ); 106 | 107 | // ============================== 108 | // Scroll Restoration 109 | // ============================== 110 | 111 | // Return scroll to top on route change 112 | class ScrollToTop extends Component<*> { 113 | componentDidUpdate(prevProps) { 114 | const { history, location } = this.props; 115 | 116 | // do not influence scroll on browser back/forward 117 | if (history.action === 'POP') return; 118 | 119 | // no scroll when extending the current path 120 | const pathArr = location.pathname.split('/'); 121 | if (!prevProps.location.pathname.includes(pathArr[1])) { 122 | window.scrollTo(0, 0); 123 | } 124 | } 125 | 126 | render() { 127 | return this.props.children; 128 | } 129 | } 130 | 131 | export const ScrollRestoration = withRouter(ScrollToTop); 132 | -------------------------------------------------------------------------------- /docs/App/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React, { Component, Fragment } from 'react'; 4 | import { BrowserRouter, Route, Switch } from 'react-router-dom'; 5 | import { Helmet } from 'react-helmet'; 6 | 7 | import Header from './Header'; 8 | import Footer from './Footer'; 9 | // import NoMatch from '../NoMatch'; 10 | 11 | import { 12 | AppContainer, 13 | AppContent, 14 | PageContent, 15 | PrimaryNav, 16 | PrimaryNavItem, 17 | ScrollRestoration, 18 | } from './components'; 19 | import Section from './Section'; 20 | import PageNav from './PageNav'; 21 | import Tests from '../Tests'; 22 | 23 | const sections = [ 24 | { label: 'Home', path: '/home' }, 25 | { label: 'Props', path: '/props' }, 26 | { label: 'Styles', path: '/styles' }, 27 | { label: 'Components', path: '/components' }, 28 | { label: 'Async', path: '/async' }, 29 | { label: 'Creatable', path: '/creatable' }, 30 | { label: 'Advanced', path: '/advanced' }, 31 | { label: 'Upgrading', path: '/upgrade-guide' }, 32 | ]; 33 | 34 | export default class App extends Component<*> { 35 | render() { 36 | return ( 37 | 38 | 39 | 40 | 41 |
42 |
43 | ( 45 | 46 | {sections.map(l => { 47 | const selected = location.pathname.includes(l.path); 48 | 49 | return ( 50 | 55 | {l.label} 56 | 57 | ); 58 | })} 59 | 60 | )} 61 | /> 62 |
63 | 64 | 65 | 66 | 67 | React Select 68 | 72 | 73 | ( 75 | 76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | )} 84 | /> 85 | 86 | 87 |
88 |
89 |
90 |
91 |
92 | ); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /docs/App/routes.js: -------------------------------------------------------------------------------- 1 | import Home from '../pages/home'; 2 | import Props from '../pages/props'; 3 | import Styles from '../pages/styles'; 4 | import Components from '../pages/components'; 5 | import Async from '../pages/async'; 6 | import Creatable from '../pages/creatable'; 7 | import Advanced from '../pages/advanced'; 8 | import UpgradeGuide from '../pages/upgradeGuide'; 9 | 10 | export default { 11 | '/home': Home, 12 | '/props': Props, 13 | '/styles': Styles, 14 | '/components': Components, 15 | '/async': Async, 16 | '/creatable': Creatable, 17 | '/advanced': Advanced, 18 | '/upgrade-guide': UpgradeGuide 19 | }; 20 | -------------------------------------------------------------------------------- /docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @react-select/docs 2 | 3 | ## 2.4.5 4 | - Updated dependencies [[9ad152b](https://github.com/JedWatson/react-select/commit/9ad152b)]: 5 | - react-select@3.0.0 6 | -------------------------------------------------------------------------------- /docs/NoMatch.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import { Link } from 'react-router-dom'; 4 | import { H1 } from './styled-components'; 5 | 6 | export default function NoMatch() { 7 | return ( 8 |
9 |

Oops!

10 |

Couldn't find this page.

11 | Back home 12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /docs/PropTypes/Async.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | 3 | import { type AsyncProps, defaultProps } from 'react-select-reborn/src/Async'; 4 | 5 | export default class Select extends Component { 6 | defaultProps = defaultProps; 7 | } 8 | -------------------------------------------------------------------------------- /docs/PropTypes/Creatable.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | 3 | import { type CreatableProps, defaultProps } from 'react-select-reborn/src/Creatable'; 4 | 5 | export default class Select extends Component { 6 | defaultProps = defaultProps; 7 | } 8 | -------------------------------------------------------------------------------- /docs/PropTypes/Select.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type Props, defaultProps } from 'react-select-reborn/src/Select'; 3 | 4 | export default class Select extends Component { 5 | defaultProps = defaultProps; 6 | } 7 | -------------------------------------------------------------------------------- /docs/PropTypes/components/ClearIndicator.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type IndicatorProps } from 'react-select-reborn/src/components/indicators'; 3 | 4 | export default class ClearIndicator extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/Control.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type ControlProps } from 'react-select-reborn/src/components/Control'; 3 | 4 | export default class Control extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/DropdownIndicator.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type IndicatorProps } from 'react-select-reborn/src/components/indicators'; 3 | 4 | export default class DropdownIndicator extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/Group.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type GroupProps } from 'react-select-reborn/src/components/Group'; 3 | 4 | export default class Group extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/IndicatorsContainer.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type IndicatorContainerProps } from 'react-select-reborn/src/components/containers'; 3 | 4 | export default class IndicatorContainer extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/IndicatorsSeparator.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type IndicatorProps } from 'react-select-reborn/src/components/indicators'; 3 | 4 | export default class DropdownIndicator extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/Input.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type InputProps } from 'react-select-reborn/src/components/Input'; 3 | 4 | export default class Input extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/LoadingIndicator.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type LoadingIconProps } from 'react-select-reborn/src/components/indicators'; 3 | 4 | export default class LoadingIndicator extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/LoadingMessage.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type NoticeProps } from 'react-select-reborn/src/components/Menu'; 3 | 4 | export default class LoadingMessage extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/Menu.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type MenuProps } from 'react-select-reborn/src/components/Menu'; 3 | 4 | export default class Menu extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/MenuList.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type MenuListComponentProps } from 'react-select-reborn/src/components/Menu'; 3 | 4 | export default class MenuList extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/MultiValue.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type MultiValueProps } from 'react-select-reborn/src/components/MultiValue'; 3 | 4 | export default class MultiValue extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/MultiValueContainer.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type MultiValueGenericProps } from 'react-select-reborn/src/components/MultiValue'; 3 | 4 | export default class MultiValueContainer extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/MultiValueLabel.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type MultiValueGenericProps } from 'react-select-reborn/src/components/MultiValue'; 3 | 4 | export default class MultiValueLabel extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/MultiValueRemove.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type MultiValueGenericProps } from 'react-select-reborn/src/components/MultiValue'; 3 | 4 | export default class MultiValueRemove extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/NoOptionsMessage.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type NoticeProps } from 'react-select-reborn/src/components/Menu'; 3 | 4 | export default class NoOptionsMessage extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/Option.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type OptionProps } from 'react-select-reborn/src/components/Option'; 3 | 4 | export default class Option extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/Placeholder.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type PlaceholderProps } from 'react-select-reborn/src/components/Placeholder'; 3 | 4 | export default class Placeholder extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/SelectContainer.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type ContainerProps } from 'react-select-reborn/src/components/containers'; 3 | 4 | export default class SelectContainer extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/SingleValue.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type SingleValueProps } from 'react-select-reborn/src/components/SingleValue'; 3 | 4 | export default class SingleValue extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/components/ValueContainer.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type ValueContainerProps } from 'react-select-reborn/src/components/containers'; 3 | 4 | export default class ValueContainer extends Component {} 5 | -------------------------------------------------------------------------------- /docs/PropTypes/stateManager.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import { type Props, defaultProps } from 'react-select-reborn/src/stateManager'; 3 | 4 | export default class StateManager extends Component { 5 | defaultProps = defaultProps; 6 | } 7 | -------------------------------------------------------------------------------- /docs/Svg.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /** @jsx jsx */ 3 | import { jsx } from '@emotion/core'; 4 | 5 | const Svg = ({ size, ...props }: { size: number }) => ( 6 | 22 | ); 23 | 24 | export default Svg; 25 | -------------------------------------------------------------------------------- /docs/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 2 | -------------------------------------------------------------------------------- /docs/examples/AccessingInternals.js: -------------------------------------------------------------------------------- 1 | import React, { Component, type ElementRef, Fragment } from 'react'; 2 | 3 | import Select from 'react-select-reborn'; 4 | import AsyncSelect from 'react-select-reborn/async'; 5 | import CreatableSelect from 'react-select-reborn/creatable'; 6 | 7 | import { Note } from '../styled-components'; 8 | import { colourOptions } from '../data'; 9 | 10 | const filterColors = (inputValue: string) => { 11 | return colourOptions.filter(i => 12 | i.label.toLowerCase().includes(inputValue.toLowerCase()) 13 | ); 14 | }; 15 | 16 | const promiseOptions = inputValue => 17 | new Promise(resolve => { 18 | setTimeout(() => { 19 | resolve(filterColors(inputValue)); 20 | }, 1000); 21 | }); 22 | 23 | export default class AccessingInterals extends Component { 24 | selectRef: ElementRef<*>; 25 | asyncRef: ElementRef<*>; 26 | creatableRef: ElementRef<*>; 27 | focus = () => { 28 | console.log(this.selectRef); 29 | this.selectRef.focus(); 30 | }; 31 | focusCreatable = () => { 32 | console.log(this.creatableRef); 33 | this.creatableRef.focus(); 34 | }; 35 | focusAsync = () => { 36 | console.log(this.asyncRef); 37 | this.asyncRef.focus(); 38 | }; 39 | blurAsync = () => { 40 | this.asyncRef.blur(); 41 | }; 42 | blurCreatable = () => { 43 | this.creatableRef.blur(); 44 | }; 45 | blur = () => this.selectRef.blur(); 46 | onSelectRef = ref => { 47 | console.log(ref); 48 | this.selectRef = ref; 49 | }; 50 | render() { 51 | return ( 52 | 53 |

Creatable Select

54 | { 56 | this.creatableRef = ref; 57 | }} 58 | isClearable 59 | onChange={this.handleChange} 60 | options={colourOptions} 61 | /> 62 | 63 | 69 | 70 | 71 | 77 | 78 |

Async Select

79 | { 81 | this.asyncRef = ref; 82 | }} 83 | cacheOptions 84 | defaultOptions 85 | loadOptions={promiseOptions} 86 | /> 87 | 88 | 94 | 95 | 96 | 102 | 103 |

Select

104 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /docs/examples/AsyncCallbacks.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import AsyncSelect from 'react-select-reborn/async'; 4 | import { colourOptions } from '../data'; 5 | 6 | type State = { 7 | inputValue: string, 8 | }; 9 | 10 | const filterColors = (inputValue: string) => { 11 | return colourOptions.filter(i => 12 | i.label.toLowerCase().includes(inputValue.toLowerCase()) 13 | ); 14 | }; 15 | 16 | const loadOptions = (inputValue, callback) => { 17 | setTimeout(() => { 18 | callback(filterColors(inputValue)); 19 | }, 1000); 20 | }; 21 | 22 | export default class WithCallbacks extends Component<*, State> { 23 | state = { inputValue: '' }; 24 | handleInputChange = (newValue: string) => { 25 | const inputValue = newValue.replace(/\W/g, ''); 26 | this.setState({ inputValue }); 27 | return inputValue; 28 | }; 29 | render() { 30 | return ( 31 |
32 |
inputValue: "{this.state.inputValue}"
33 | 39 |
40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /docs/examples/AsyncCreatable.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import AsyncCreatableSelect from 'react-select-reborn/async-creatable'; 4 | import { colourOptions } from '../data'; 5 | 6 | const filterColors = (inputValue: string) => { 7 | return colourOptions.filter(i => 8 | i.label.toLowerCase().includes(inputValue.toLowerCase()) 9 | ); 10 | }; 11 | 12 | const promiseOptions = inputValue => 13 | new Promise(resolve => { 14 | setTimeout(() => { 15 | resolve(filterColors(inputValue)); 16 | }, 1000); 17 | }); 18 | 19 | export default class WithPromises extends Component<*, State> { 20 | render() { 21 | return ( 22 | 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docs/examples/AsyncMulti.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import AsyncSelect from 'react-select-reborn/async'; 4 | import { colourOptions } from '../data'; 5 | 6 | type State = { 7 | inputValue: string, 8 | }; 9 | 10 | const filterColors = (inputValue: string) => { 11 | return colourOptions.filter(i => 12 | i.label.toLowerCase().includes(inputValue.toLowerCase()) 13 | ); 14 | }; 15 | 16 | const promiseOptions = inputValue => 17 | new Promise(resolve => { 18 | setTimeout(() => { 19 | resolve(filterColors(inputValue)); 20 | }, 1000); 21 | }); 22 | 23 | export default class AsyncMulti extends Component<*, State> { 24 | state = { inputValue: '' }; 25 | handleInputChange = (newValue: string) => { 26 | const inputValue = newValue.replace(/\W/g, ''); 27 | this.setState({ inputValue }); 28 | return inputValue; 29 | }; 30 | render() { 31 | return ( 32 | 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /docs/examples/AsyncPromises.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import AsyncSelect from 'react-select-reborn/async'; 4 | import { colourOptions } from '../data'; 5 | 6 | const filterColors = (inputValue: string) => { 7 | return colourOptions.filter(i => 8 | i.label.toLowerCase().includes(inputValue.toLowerCase()) 9 | ); 10 | }; 11 | 12 | const promiseOptions = inputValue => 13 | new Promise(resolve => { 14 | setTimeout(() => { 15 | resolve(filterColors(inputValue)); 16 | }, 1000); 17 | }); 18 | 19 | export default class WithPromises extends Component { 20 | render() { 21 | return ( 22 | 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/examples/BasicGrouped.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Select from 'react-select-reborn'; 4 | import { colourOptions, groupedOptions } from '../data'; 5 | 6 | const groupStyles = { 7 | display: 'flex', 8 | alignItems: 'center', 9 | justifyContent: 'space-between', 10 | }; 11 | const groupBadgeStyles = { 12 | backgroundColor: '#EBECF0', 13 | borderRadius: '2em', 14 | color: '#172B4D', 15 | display: 'inline-block', 16 | fontSize: 12, 17 | fontWeight: 'normal', 18 | lineHeight: '1', 19 | minWidth: 1, 20 | padding: '0.16666666666667em 0.5em', 21 | textAlign: 'center', 22 | }; 23 | 24 | const formatGroupLabel = data => ( 25 |
26 | {data.label} 27 | {data.options.length} 28 |
29 | ); 30 | 31 | export default () => ( 32 | 15 | ); 16 | -------------------------------------------------------------------------------- /docs/examples/BasicSingle.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from 'react'; 2 | 3 | import Select from 'react-select-reborn'; 4 | import { colourOptions } from '../data'; 5 | import { Note } from '../styled-components'; 6 | 7 | const Checkbox = props => ; 8 | 9 | type State = { 10 | isClearable: boolean, 11 | isDisabled: boolean, 12 | isLoading: boolean, 13 | isRtl: boolean, 14 | isSearchable: boolean, 15 | }; 16 | 17 | export default class SingleSelect extends Component<*, State> { 18 | state = { 19 | isClearable: true, 20 | isDisabled: false, 21 | isLoading: false, 22 | isRtl: false, 23 | isSearchable: true, 24 | }; 25 | 26 | toggleClearable = () => 27 | this.setState(state => ({ isClearable: !state.isClearable })); 28 | toggleDisabled = () => 29 | this.setState(state => ({ isDisabled: !state.isDisabled })); 30 | toggleLoading = () => 31 | this.setState(state => ({ isLoading: !state.isLoading })); 32 | toggleRtl = () => this.setState(state => ({ isRtl: !state.isRtl })); 33 | toggleSearchable = () => 34 | this.setState(state => ({ isSearchable: !state.isSearchable })); 35 | render() { 36 | const { 37 | isClearable, 38 | isSearchable, 39 | isDisabled, 40 | isLoading, 41 | isRtl, 42 | } = this.state; 43 | return ( 44 | 45 | ; 8 | 9 | type State = { 10 | menuIsOpen: boolean, 11 | }; 12 | 13 | export default class controlledMenu extends Component<*, State> { 14 | state = { 15 | menuIsOpen: false, 16 | }; 17 | select: ElementRef<*>; 18 | toggleMenuIsOpen = () => { 19 | this.setState(state => ({ menuIsOpen: !state.menuIsOpen })); 20 | if (this.select) { 21 | return !this.state.menuIsOpen ? this.select.focus() : this.select.blur(); 22 | } 23 | }; 24 | render() { 25 | const { menuIsOpen } = this.state; 26 | return ( 27 | 28 | ; 7 | 8 | type State = { 9 | ignoreCase: boolean, 10 | ignoreAccents: boolean, 11 | trim: boolean, 12 | matchFrom: boolean, 13 | }; 14 | 15 | export default class SelectCreateFilter extends Component<*, State> { 16 | state: State = { 17 | ignoreCase: false, 18 | ignoreAccents: false, 19 | trim: false, 20 | matchFromStart: false, 21 | }; 22 | toggleOption = key => () => { 23 | this.setState(state => ({ [key]: !state[key] })); 24 | }; 25 | render() { 26 | const { ignoreCase, ignoreAccents, trim, matchFromStart } = this.state; 27 | 28 | const filterConfig = { 29 | ignoreCase, 30 | ignoreAccents, 31 | trim, 32 | matchFrom: this.state.matchFromStart ? 'start' : 'any', 33 | }; 34 | 35 | return ( 36 | 37 | 42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /docs/examples/CustomControl.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import Select, { components } from 'react-select-reborn'; 4 | import { colourOptions } from '../data'; 5 | const controlStyles = { 6 | borderRadius: '1px solid black', 7 | padding: '5px', 8 | background: colourOptions[2].color, 9 | color: 'white', 10 | }; 11 | 12 | const ControlComponent = props => ( 13 |
14 | {

Custom Control

} 15 | 16 |
17 | ); 18 | 19 | type State = {}; 20 | 21 | export default class CustomControl extends Component<*, State> { 22 | state = {}; 23 | render() { 24 | return ( 25 | 26 | ); 27 | -------------------------------------------------------------------------------- /docs/examples/CustomFilterOptions.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Select from 'react-select-reborn'; 3 | import { colourOptions } from '../data'; 4 | 5 | type State = { 6 | ignoreCase: boolean, 7 | ignoreAccents: boolean, 8 | trim: boolean, 9 | matchFrom: boolean, 10 | }; 11 | const filterOptions = (candidate, input) => { 12 | if (input) { 13 | return candidate.value === customOptions[0].value; 14 | } 15 | return true; 16 | }; 17 | 18 | const customOptions = [ 19 | { 20 | value: 'custom', 21 | label: 'Using a custom filter to always display this option on search', 22 | }, 23 | ...colourOptions, 24 | ]; 25 | 26 | export default class SelectCreateFilter extends Component<*, State> { 27 | render() { 28 | return ( 29 | `${option.label}: ${option.rating}`} 20 | /> 21 |
22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/examples/CustomGetOptionValue.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment } from 'react'; 2 | import Select from 'react-select-reborn'; 3 | import { dogOptions } from '../data'; 4 | 5 | export default function CustomGetOptionValue() { 6 | return ( 7 | 8 |

Using id property, instead of value property.

9 | 24 | ); 25 | -------------------------------------------------------------------------------- /docs/examples/CustomGroupHeading.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Select, { components } from 'react-select-reborn'; 4 | import { colourOptions, groupedOptions } from '../data'; 5 | import EditorPanelIcon from '@atlaskit/icon/glyph/editor/panel'; 6 | import Tooltip from '@atlaskit/tooltip'; 7 | 8 | const groupStyles = { 9 | border: `2px dotted ${colourOptions[2].color}`, 10 | color: 'white', 11 | background: colourOptions[2].color, 12 | padding: '5px 0px', 13 | display: 'flex', 14 | }; 15 | 16 | const GroupHeading = props => ( 17 |
18 | 19 | 20 | 21 | 22 |
23 | ); 24 | 25 | export default () => ( 26 | 27 | ); 28 | -------------------------------------------------------------------------------- /docs/examples/CustomIndicatorsContainer.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import Select, { components } from 'react-select-reborn'; 5 | import { colourOptions } from '../data'; 6 | 7 | const IndicatorsContainer = props => { 8 | return ( 9 |
10 | 11 |
12 | ); 13 | }; 14 | 15 | export default () => ( 16 | 29 | ); 30 | -------------------------------------------------------------------------------- /docs/examples/CustomIsOptionDisabled.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from 'react'; 2 | import Select from 'react-select-reborn'; 3 | import { flavourOptions } from '../data'; 4 | 5 | export default class CustomIsOptionDisabled extends Component<*> { 6 | render() { 7 | return ( 8 | 9 |

10 | Disable all options that do not have a 'safe' rating, via the 11 | isOptionsDisabled fn prop 12 |

13 | 35 | ); 36 | -------------------------------------------------------------------------------- /docs/examples/CustomMenuList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Select, { components } from 'react-select-reborn'; 4 | import { colourOptions, groupedOptions } from '../data'; 5 | 6 | const menuHeaderStyle = { 7 | padding: '8px 12px', 8 | background: colourOptions[2].color, 9 | color: 'white', 10 | }; 11 | 12 | const MenuList = props => { 13 | return ( 14 | 15 |
Custom Menu List
16 | {props.children} 17 |
18 | ); 19 | }; 20 | 21 | export default () => ( 22 | ({ 22 | ...base, 23 | border: `2px dotted ${colourOptions[2].color}`, 24 | }), 25 | }} 26 | defaultValue={[colourOptions[4], colourOptions[5]]} 27 | isMulti 28 | options={colourOptions} 29 | /> 30 | ); 31 | -------------------------------------------------------------------------------- /docs/examples/CustomMultiValueLabel.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React from 'react'; 4 | import Tooltip from '@atlaskit/tooltip'; 5 | import Select, { components } from 'react-select-reborn'; 6 | import { colourOptions } from '../data'; 7 | 8 | const MultiValueLabel = props => { 9 | return ( 10 | 11 | 12 | 13 | ); 14 | }; 15 | 16 | export default () => ( 17 | ({ 28 | ...base, 29 | border: `1px dotted ${colourOptions[2].color}`, 30 | height: '100%', 31 | }), 32 | }} 33 | defaultValue={[colourOptions[4], colourOptions[5]]} 34 | isMulti 35 | options={colourOptions} 36 | /> 37 | ); 38 | -------------------------------------------------------------------------------- /docs/examples/CustomNoOptionsMessage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Tooltip from '@atlaskit/tooltip'; 3 | import Select, { components } from 'react-select-reborn'; 4 | import { colourOptions } from '../data'; 5 | const msgStyles = { 6 | background: colourOptions[2].color, 7 | color: 'white', 8 | }; 9 | 10 | const NoOptionsMessage = props => { 11 | return ( 12 | 13 | 14 | 15 | ); 16 | }; 17 | 18 | const CustomNoOptionsMessage = () => { 19 | return ( 20 | ({ 20 | ...base, 21 | border: `1px dotted ${colourOptions[2].color}`, 22 | height: '100%', 23 | }), 24 | }} 25 | defaultValue={colourOptions[4]} 26 | options={colourOptions} 27 | /> 28 | ); 29 | -------------------------------------------------------------------------------- /docs/examples/CustomPlaceholder.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Select, { components } from 'react-select-reborn'; 3 | import { colourOptions } from '../data'; 4 | 5 | const Placeholder = props => { 6 | return ; 7 | }; 8 | 9 | export default () => ( 10 | ({ 22 | ...base, 23 | backgroundColor: colourOptions[2].color, 24 | padding: 5, 25 | }), 26 | }} 27 | options={colourOptions} 28 | /> 29 | ); 30 | -------------------------------------------------------------------------------- /docs/examples/CustomSingleValue.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Select, { components } from 'react-select-reborn'; 3 | import { colourOptions } from '../data'; 4 | 5 | const SingleValue = ({ children, ...props }) => ( 6 | {children} 7 | ); 8 | 9 | type State = {}; 10 | 11 | export default class CustomControl extends Component<*, State> { 12 | state = {}; 13 | render() { 14 | return ( 15 | ({ ...base, color: 'white' }), 20 | valueContainer: base => ({ 21 | ...base, 22 | background: colourOptions[2].color, 23 | color: 'white', 24 | width: '100%', 25 | }), 26 | }} 27 | components={{ ValueContainer }} 28 | isSearchable 29 | name="color" 30 | options={colourOptions} 31 | /> 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/examples/DefaultOptions.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import AsyncSelect from 'react-select-reborn/async'; 4 | import { colourOptions } from '../data'; 5 | 6 | type State = { 7 | inputValue: string, 8 | }; 9 | 10 | const filterColors = (inputValue: string) => { 11 | return colourOptions.filter(i => 12 | i.label.toLowerCase().includes(inputValue.toLowerCase()) 13 | ); 14 | }; 15 | 16 | const promiseOptions = inputValue => 17 | new Promise(resolve => { 18 | setTimeout(() => { 19 | resolve(filterColors(inputValue)); 20 | }, 1000); 21 | }); 22 | 23 | export default class WithPromises extends Component<*, State> { 24 | state = { inputValue: '' }; 25 | handleInputChange = (newValue: string) => { 26 | const inputValue = newValue.replace(/\W/g, ''); 27 | this.setState({ inputValue }); 28 | return inputValue; 29 | }; 30 | render() { 31 | return ( 32 | 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/examples/FixedOptions.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | 3 | import Select from 'react-select-reborn'; 4 | import { colourOptions } from '../data'; 5 | 6 | type State = { 7 | value: [{ [string]: string }], 8 | }; 9 | 10 | const styles = { 11 | multiValue: (base, state) => { 12 | return state.data.isFixed ? { ...base, backgroundColor: 'gray' } : base; 13 | }, 14 | multiValueLabel: (base, state) => { 15 | return state.data.isFixed 16 | ? { ...base, fontWeight: 'bold', color: 'white', paddingRight: 6 } 17 | : base; 18 | }, 19 | multiValueRemove: (base, state) => { 20 | return state.data.isFixed ? { ...base, display: 'none' } : base; 21 | }, 22 | }; 23 | 24 | const orderOptions = values => { 25 | return values.filter(v => v.isFixed).concat(values.filter(v => !v.isFixed)); 26 | }; 27 | 28 | export default class FixedOptions extends Component<*, State> { 29 | state = { 30 | value: orderOptions([colourOptions[0], colourOptions[1], colourOptions[3]]), 31 | }; 32 | 33 | constructor(props) { 34 | super(props); 35 | 36 | this.onChange = this.onChange.bind(this); 37 | } 38 | 39 | onChange(value, { action, removedValue }) { 40 | switch (action) { 41 | case 'remove-value': 42 | case 'pop-value': 43 | if (removedValue.isFixed) { 44 | return; 45 | } 46 | break; 47 | case 'clear': 48 | value = colourOptions.filter(v => v.isFixed); 49 | break; 50 | } 51 | 52 | value = orderOptions(value); 53 | this.setState({ value: value }); 54 | } 55 | 56 | render() { 57 | return ( 58 | ({ ...base, marginBottom: 76 }) }} 11 | /> 12 | ); 13 | -------------------------------------------------------------------------------- /docs/examples/MenuPortal.js: -------------------------------------------------------------------------------- 1 | import React, { Component, Fragment } from 'react'; 2 | import Modal from '@atlaskit/modal-dialog'; 3 | import Button from '@atlaskit/button'; 4 | import Select from 'react-select-reborn'; 5 | import { H1, Note } from '../styled-components'; 6 | 7 | import { colourOptions } from '../data'; 8 | 9 | type State = { 10 | isOpen: boolean, 11 | isFixed: boolean, 12 | portalPlacement: 'auto' | 'bottom' | 'top', 13 | }; 14 | 15 | export default class MenuPortal extends Component<*, State> { 16 | state = { 17 | isOpen: false, 18 | isFixed: false, 19 | portalPlacement: 'bottom', 20 | }; 21 | open = () => { 22 | console.log('menuPortal is Open'); 23 | this.setState({ isOpen: true }); 24 | }; 25 | close = () => { 26 | this.setState({ isOpen: false }); 27 | }; 28 | setPlacement = ({ currentTarget }: SyntheticEvent) => { 29 | const portalPlacement = currentTarget && currentTarget.value; 30 | this.setState({ portalPlacement }); 31 | }; 32 | toggleMode = () => { 33 | this.setState(state => ({ isFixed: !state.isFixed })); 34 | }; 35 | render() { 36 | const { close, open } = this; 37 | const { isOpen, isFixed, portalPlacement } = this.state; 38 | return ( 39 | 40 | 41 | {isOpen ? ( 42 | 43 |

Portaled Menu Element

44 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 75 | Fixed 76 | 77 | 78 | 85 | Portal 86 | 87 |
88 | ) : null} 89 |
90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /docs/examples/MultiSelectSort.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Select, { components } from 'react-select-reborn'; 4 | import { SortableContainer, SortableElement } from 'react-sortable-hoc'; 5 | import { colourOptions } from '../data'; 6 | 7 | function arrayMove(array, from, to) { 8 | array = array.slice(); 9 | array.splice(to < 0 ? array.length + to : to, 0, array.splice(from, 1)[0]); 10 | return array; 11 | } 12 | 13 | const SortableMultiValue = SortableElement(props => { 14 | // this prevents the menu from being opened/closed when the user clicks 15 | // on a value to begin dragging it. ideally, detecting a click (instead of 16 | // a drag) would still focus the control and toggle the menu, but that 17 | // requires some magic with refs that are out of scope for this example 18 | const onMouseDown = e => { 19 | e.preventDefault(); 20 | e.stopPropagation(); 21 | }; 22 | const innerProps = { onMouseDown }; 23 | return ; 24 | }); 25 | const SortableSelect = SortableContainer(Select); 26 | 27 | export default function MultiSelectSort() { 28 | const [selected, setSelected] = React.useState([ 29 | colourOptions[4], 30 | colourOptions[5], 31 | ]); 32 | 33 | const onChange = selectedOptions => setSelected(selectedOptions); 34 | 35 | const onSortEnd = ({ oldIndex, newIndex }) => { 36 | const newValue = arrayMove(selected, oldIndex, newIndex); 37 | setSelected(newValue); 38 | console.log('Values sorted:', newValue.map(i => i.value)); 39 | }; 40 | 41 | return ( 42 | node.getBoundingClientRect()} 49 | // react-select props: 50 | isMulti 51 | options={colourOptions} 52 | value={selected} 53 | onChange={onChange} 54 | components={{ 55 | MultiValue: SortableMultiValue, 56 | }} 57 | closeMenuOnSelect={false} 58 | /> 59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /docs/examples/OnSelectResetsInput.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Select from 'react-select-reborn'; 3 | import { colourOptions } from '../data'; 4 | 5 | export default class OnSelectResetsInput extends Component { 6 | state = { 7 | inputValue: '', 8 | } 9 | onInputChange = (inputValue, { action }) => { 10 | console.log(inputValue, action); 11 | switch (action) { 12 | case 'input-change': 13 | this.setState({ inputValue }); 14 | return; 15 | case 'menu-close': 16 | console.log(this.state.inputValue); 17 | let menuIsOpen = undefined; 18 | if (this.state.inputValue) { 19 | menuIsOpen = true; 20 | } 21 | this.setState({ 22 | menuIsOpen 23 | }); 24 | return; 25 | default: 26 | return; 27 | } 28 | } 29 | render () { 30 | const { inputValue, menuIsOpen } = this.state; 31 | return ( 32 | 59 | 60 | ); 61 | } 62 | } 63 | 64 | // styled components 65 | 66 | const Menu = props => { 67 | const shadow = 'hsla(218, 50%, 10%, 0.1)'; 68 | return ( 69 |
80 | ); 81 | }; 82 | const Blanket = props => ( 83 |
94 | ); 95 | const Dropdown = ({ children, isOpen, target, onClose }) => ( 96 |
97 | {target} 98 | {isOpen ? {children} : null} 99 | {isOpen ? : null} 100 |
101 | ); 102 | const Svg = p => ( 103 | 111 | ); 112 | const DropdownIndicator = () => ( 113 |
114 | 115 | 120 | 121 |
122 | ); 123 | const ChevronDown = () => ( 124 | 125 | 130 | 131 | ); 132 | -------------------------------------------------------------------------------- /docs/examples/StyleCompositionExample.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { css } from 'emotion'; 3 | import Select from 'react-select-reborn'; 4 | import { colourOptions } from '../data'; 5 | 6 | const Option = (props: OptionProps) => { 7 | const { 8 | children, 9 | className, 10 | cx, 11 | getStyles, 12 | isDisabled, 13 | isFocused, 14 | isSelected, 15 | innerRef, 16 | innerProps, 17 | } = props; 18 | return ( 19 |
33 | {children} 34 |
35 | ); 36 | }; 37 | 38 | export default () => ( 39 | 64 | ); 65 | -------------------------------------------------------------------------------- /docs/examples/StyledSingle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import chroma from 'chroma-js'; 3 | 4 | import { colourOptions } from '../data'; 5 | import Select from 'react-select-reborn'; 6 | 7 | const dot = (color = '#ccc') => ({ 8 | alignItems: 'center', 9 | display: 'flex', 10 | 11 | ':before': { 12 | backgroundColor: color, 13 | borderRadius: 10, 14 | content: '" "', 15 | display: 'block', 16 | marginRight: 8, 17 | height: 10, 18 | width: 10, 19 | }, 20 | }); 21 | 22 | const colourStyles = { 23 | control: styles => ({ ...styles, backgroundColor: 'white' }), 24 | option: (styles, { data, isDisabled, isFocused, isSelected }) => { 25 | const color = chroma(data.color); 26 | return { 27 | ...styles, 28 | backgroundColor: isDisabled 29 | ? null 30 | : isSelected 31 | ? data.color 32 | : isFocused 33 | ? color.alpha(0.1).css() 34 | : null, 35 | color: isDisabled 36 | ? '#ccc' 37 | : isSelected 38 | ? chroma.contrast(color, 'white') > 2 39 | ? 'white' 40 | : 'black' 41 | : data.color, 42 | cursor: isDisabled ? 'not-allowed' : 'default', 43 | 44 | ':active': { 45 | ...styles[':active'], 46 | backgroundColor: !isDisabled && (isSelected ? data.color : color.alpha(0.3).css()), 47 | }, 48 | }; 49 | }, 50 | input: styles => ({ ...styles, ...dot() }), 51 | placeholder: styles => ({ ...styles, ...dot() }), 52 | singleValue: (styles, { data }) => ({ ...styles, ...dot(data.color) }), 53 | }; 54 | 55 | export default () => ( 56 | ({ 12 | ...theme, 13 | borderRadius: 0, 14 | colors: { 15 | ...theme.colors, 16 | primary25: 'hotpink', 17 | primary: 'black', 18 | }, 19 | })} 20 | /> 21 | ); 22 | -------------------------------------------------------------------------------- /docs/examples/index.js: -------------------------------------------------------------------------------- 1 | export { default as AccessingInternals } from './AccessingInternals'; 2 | export { default as ControlledMenu } from './ControlledMenu'; 3 | export { default as AnimatedMulti } from './AnimatedMulti'; 4 | export { default as AsyncCallbacks } from './AsyncCallbacks'; 5 | export { default as AsyncCreatable } from './AsyncCreatable'; 6 | export { default as AsyncPromises } from './AsyncPromises'; 7 | export { default as BasicGrouped } from './BasicGrouped'; 8 | export { default as BasicMulti } from './BasicMulti'; 9 | export { default as BasicSingle } from './BasicSingle'; 10 | export { default as CustomControl } from './CustomControl'; 11 | export { default as CreatableAdvanced } from './CreatableAdvanced'; 12 | export { default as CreatableInputOnly } from './CreatableInputOnly'; 13 | export { default as CreateFilter } from './CreateFilter'; 14 | export { default as CreatableMulti } from './CreatableMulti'; 15 | export { default as CreatableSingle } from './CreatableSingle'; 16 | export { default as CustomClearIndicator } from './CustomClearIndicator'; 17 | export { default as CustomDropdownIndicator } from './CustomDropdownIndicator'; 18 | export { default as CustomLoadingIndicator } from './CustomLoadingIndicator'; 19 | export { default as CustomLoadingMessage } from './CustomLoadingMessage'; 20 | export { default as CustomGroup } from './CustomGroup'; 21 | export { default as CustomMenu } from './CustomMenu'; 22 | export { default as CustomMenuList } from './CustomMenuList'; 23 | export { default as CustomIndicatorsContainer } from './CustomIndicatorsContainer'; 24 | export { default as CustomIndicatorSeparator } from './CustomIndicatorSeparator'; 25 | export { default as CustomNoOptionsMessage } from './CustomNoOptionsMessage'; 26 | export { default as CustomMultiValueContainer } from './CustomMultiValueContainer'; 27 | export { default as CustomOption } from './CustomOption'; 28 | export { default as CustomMultiValueLabel } from './CustomMultiValueLabel'; 29 | export { default as CustomMultiValueRemove } from './CustomMultiValueRemove'; 30 | export { default as CustomInput } from './CustomInput'; 31 | export { default as CustomGroupHeading } from './CustomGroupHeading'; 32 | export { default as CustomPlaceholder } from './CustomPlaceholder'; 33 | export { default as CustomSelectContainer } from './CustomSelectContainer'; 34 | export { default as CustomSingleValue } from './CustomSingleValue'; 35 | export { default as CustomValueContainer } from './CustomValueContainer'; 36 | export { default as CustomGetOptionLabel } from './CustomGetOptionLabel'; 37 | export { default as CustomGetOptionValue } from './CustomGetOptionValue'; 38 | export { default as CustomFilterOptions } from './CustomFilterOptions'; 39 | export { default as CustomIsOptionDisabled } from './CustomIsOptionDisabled'; 40 | export { default as Experimental } from './Experimental'; 41 | export { default as FixedOptions } from './FixedOptions'; 42 | export { default as MultiSelectSort } from './MultiSelectSort'; 43 | export { default as Popout } from './Popout'; 44 | export { default as StyledMulti } from './StyledMulti'; 45 | export { default as StyledSingle } from './StyledSingle'; 46 | export { default as OnSelectResetsInput } from './OnSelectResetsInput'; 47 | export { default as AsyncMulti } from './AsyncMulti'; 48 | export { default as MenuBuffer } from './MenuBuffer'; 49 | export { default as MenuPortal } from './MenuPortal'; 50 | export { default as Theme } from './Theme'; 51 | export { default as StyleCompositionExample } from './StyleCompositionExample'; 52 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marcelltoth/react-select-reborn/b2e64d5253126fa3ebea261fe73efc4fac197f45/docs/favicon.ico -------------------------------------------------------------------------------- /docs/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Roboto:400,500,700'); 2 | 3 | body { 4 | -moz-font-feature-settings: 'liga' on; 5 | -moz-osx-font-smoothing: grayscale; 6 | -webkit-font-smoothing: antialiased; 7 | color: #253858; 8 | font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 9 | Helvetica, sans-serif; 10 | font-style: normal; 11 | font-weight: 400; 12 | margin: 0; 13 | padding: 0; 14 | text-rendering: optimizeLegibility; 15 | } 16 | p > a, 17 | p > a:hover, 18 | p > a:visited { 19 | color: #2684ff; 20 | } 21 | code { 22 | font-family: Roboto Mono, Monaco, monospace; 23 | } 24 | p > code { 25 | white-space: nowrap; 26 | } 27 | p, 28 | ul, 29 | ol { 30 | line-height: 1.5; 31 | } 32 | td p { 33 | margin: 0; 34 | } 35 | h1, 36 | h2, 37 | h3, 38 | h4, 39 | h5 { 40 | color: #091e42; 41 | } 42 | h6 { 43 | color: #777; 44 | margin-bottom: 0.25em; 45 | text-transform: uppercase; 46 | } 47 | @keyframes dropIn { 48 | from, 49 | 60%, 50 | 75%, 51 | 90%, 52 | to { 53 | animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); 54 | } 55 | 0% { 56 | opacity: 0; 57 | transform: translate3d(0, -1666px, 0); 58 | } 59 | 60% { 60 | opacity: 1; 61 | transform: translate3d(0, 26px, 0); 62 | } 63 | 75% { 64 | transform: translate3d(0, -10px, 0); 65 | } 66 | 90% { 67 | transform: translate3d(0, 6px, 0); 68 | } 69 | to { 70 | transform: translate3d(0, 0, 0); 71 | } 72 | } 73 | .animate-dropin { 74 | animation: dropIn 0.66s; 75 | } 76 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | React-Select 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 25 | 29 | 30 | 31 |
32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/index.js: -------------------------------------------------------------------------------- 1 | import '@babel/polyfill'; 2 | import React from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import App from './App'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /docs/markdown/store.js: -------------------------------------------------------------------------------- 1 | class HeadingStore { 2 | store = {}; 3 | headings = {}; 4 | 5 | add(key, data) { 6 | if (!this.headings[location.pathname]) { 7 | this.headings[location.pathname] = []; 8 | } 9 | 10 | if (!this.store[key]) { 11 | this.store[key] = data; 12 | this.headings[location.pathname].push(data); 13 | } 14 | } 15 | getStore() { 16 | return this.store; 17 | } 18 | getPageHeadings(page) { 19 | return this.headings[page]; 20 | } 21 | getAllHeadings() { 22 | return this.headings; 23 | } 24 | getHeadingByKey(key) { 25 | return this.store[key]; 26 | } 27 | } 28 | 29 | // global heading store 30 | const store = new HeadingStore(); 31 | 32 | export default store; 33 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@react-select-reborn/docs", 3 | "private": true, 4 | "version": "2.4.5", 5 | "author": "Marcell Toth", 6 | "license": "MIT", 7 | "dependencies": { 8 | "@atlaskit/button": "^7.0.2", 9 | "@atlaskit/icon": "^11.0.1", 10 | "@atlaskit/modal-dialog": "^4.0.3", 11 | "@atlaskit/spinner": "^5.0.0", 12 | "@atlaskit/tooltip": "^9.1.4", 13 | "@babel/core": "^7.2.2", 14 | "@babel/plugin-proposal-class-properties": "^7.2.3", 15 | "@babel/polyfill": "^7.0.0", 16 | "@babel/preset-env": "^7.0.0", 17 | "@babel/preset-flow": "^7.0.0", 18 | "@babel/preset-react": "^7.0.0", 19 | "@babel/runtime": "^7.4.4", 20 | "@emotion/core": "^10.0.9", 21 | "babel-loader": "^8.0.0", 22 | "babel-plugin-emotion": "^10.0.9", 23 | "chroma-js": "^1.3.6", 24 | "chrono-node": "^1.3.5", 25 | "codesandboxer": "^0.1.1", 26 | "copy-webpack-plugin": "^5.0.3", 27 | "cross-env": "^5.1.3", 28 | "css-loader": "^0.28.7", 29 | "dotenv": "^7.0.0", 30 | "extract-react-types-loader": "^0.3.0", 31 | "flow-bin": "^0.91.0", 32 | "html-webpack-plugin": "^3.2.0", 33 | "moment": "^2.20.1", 34 | "pretty-proptypes": "^0.5.0", 35 | "raf-schd": "^2.1.0", 36 | "raw-loader": "^2.0.0", 37 | "react": "^16.8.0", 38 | "react-codesandboxer": "^2.0.1", 39 | "react-dom": "^16.8.0", 40 | "react-helmet": "^5.2.0", 41 | "react-markings": "^1.3.0", 42 | "react-router-dom": "^4.2.2", 43 | "react-select-reborn": "^3.0.0", 44 | "react-sortable-hoc": "^1.9.1", 45 | "react-syntax-highlighter": "^7.0.1", 46 | "style-loader": "^0.23.1", 47 | "unfetch": "^3.0.0", 48 | "webpack": "^4.30.0", 49 | "webpack-cli": "^3.3.1", 50 | "webpack-dev-server": "^3.3.1" 51 | }, 52 | "scripts": { 53 | "start": "cross-env FORCE_EXTRACT_REACT_TYPES=true webpack-dev-server --progress", 54 | "build:docs": "rimraf docs/dist && cross-env FORCE_EXTRACT_REACT_TYPES=true webpack --progress -p" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /docs/pages/async/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React, { Fragment } from 'react'; 4 | import Helmet from 'react-helmet'; 5 | import ExampleWrapper from '../../ExampleWrapper'; 6 | import md from '../../markdown/renderer'; 7 | import { 8 | AsyncCallbacks, 9 | AsyncMulti, 10 | AsyncPromises, 11 | } from '../../examples'; 12 | 13 | 14 | export default function Async() { 15 | return ( 16 | 17 | 18 | Async - React Select 19 | 23 | 24 | {md` 25 | # Async 26 | Use the Async component to load options from a remote source as the user types. 27 | 28 | ~~~jsx 29 | import Async, { makeAsyncSelect } from 'react-select-reborn/async'; 30 | ~~~ 31 | 32 | ## Loading Asynchronously 33 | 34 | The loadOptions prop allows users to either resolve from a callback... 35 | 36 | ${( 37 | 42 | 43 | 44 | )} 45 | 46 | or resolve from a returned promise.... 47 | 48 | ${( 49 | 54 | 55 | 56 | )} 57 | 58 | ${( 59 | 64 | 65 | 66 | )} 67 | 68 | ## defaultOptions 69 | 70 | The defaultOptions prop determines "when" your remote request is initially fired. There are two valid values for this property. Providing an option array to this prop will populate the initial set of options used when opening the select, at which point the remote load only occurs when filtering the options (typing in the control). Providing the prop by itself (or with 'true') tells the control to immediately fire the remote request, described by your loadOptions, to get those initial values for the Select. 71 | 72 | ${( 73 | 78 | 79 | 80 | )} 81 | 82 | ${( 83 | 88 | 89 | 90 | )} 91 | `} 92 | ); 93 | }; 94 | -------------------------------------------------------------------------------- /docs/pages/creatable/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React, { Fragment } from 'react'; 4 | import Helmet from 'react-helmet'; 5 | import md from '../../markdown/renderer'; 6 | import ExampleWrapper from '../../ExampleWrapper'; 7 | 8 | import { 9 | AsyncCreatable, 10 | CreatableAdvanced, 11 | CreatableInputOnly, 12 | CreatableMulti, 13 | CreatableSingle, 14 | } from '../../examples'; 15 | 16 | export default function Creatable() { 17 | return ( 18 | 19 | 20 | Creatable - React Select 21 | 25 | 26 | {md` 27 | # Creatable 28 | 29 | ~~~jsx 30 | import Creatable, { makeCreatableSelect } from 'react-select-reborn/creatable'; 31 | ~~~ 32 | 33 | For the prop definition, please see the API docs [here](/props) 34 | 35 | ${( 36 | 41 | 42 | 43 | )} 44 | 45 | ${( 46 | 51 | 52 | 53 | )} 54 | 55 | ${( 56 | 61 | 62 | 63 | )} 64 | 65 | > This example uses the \`onCreateOption\` prop to handle new options. 66 | 67 | > To simulate waiting for a back-end service to create a new option, the input is disabled for a second before the new option is added to the list and the value is updated. 68 | 69 | ${( 70 | 75 | 76 | 77 | )} 78 | 79 | > This example uses the combined async + creatable variant, imported from \`react-select/async-creatable\` 80 | 81 | ${( 82 | 87 | 88 | 89 | )} 90 | `} 91 | 92 | ); 93 | } 94 | -------------------------------------------------------------------------------- /docs/styled-components.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /** @jsx emotionJSX */ 3 | import { jsx as emotionJSX } from '@emotion/core'; 4 | 5 | import SyntaxHighlighter, { 6 | registerLanguage, 7 | } from 'react-syntax-highlighter/prism-light'; 8 | import jsx from 'react-syntax-highlighter/languages/prism/jsx'; 9 | import { tomorrow } from 'react-syntax-highlighter/styles/prism'; 10 | 11 | const customTomorrow = { 12 | ...tomorrow, 13 | 'code[class*="language-"]': { 14 | ...tomorrow['code[class*="language-"]'], 15 | fontFamily: null, // inherit from css 16 | }, 17 | 'pre[class*="language-"]': { 18 | ...tomorrow['pre[class*="language-"]'], 19 | fontFamily: null, // inherit from css 20 | }, 21 | }; 22 | 23 | registerLanguage('jsx', jsx); 24 | 25 | export const Hr = () => ( 26 |
34 | ); 35 | 36 | export const Note = ({ Tag = 'div', ...props }: { Tag?: string }) => ( 37 | 47 | ); 48 | 49 | export const H1 = (props: any) =>

; 50 | export const H2 = (props: any) =>

; 51 | 52 | export const ColorSample = ({ name, color }: { color: string, name: string }) => ( 53 |
61 | 72 | {name} 73 |
74 | ); 75 | 76 | // ============================== 77 | // Code 78 | // ============================== 79 | 80 | export const Code = (props: {}) => ( 81 | 91 | ); 92 | 93 | type PreProps = { children: string, language: string }; 94 | 95 | export const CodeBlock = ({ children, language, ...props }: PreProps) => { 96 | return ( 97 | 110 | {children} 111 | 112 | ); 113 | }; 114 | CodeBlock.defaultProps = { language: 'jsx' }; 115 | -------------------------------------------------------------------------------- /docs/types.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import type { Location, Match, RouterHistory } from 'react-router-dom'; 4 | 5 | export type RouterProps = { 6 | history: RouterHistory, 7 | location: Location, 8 | match: Match, 9 | }; 10 | -------------------------------------------------------------------------------- /docs/webpack.config.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | const path = require('path'); 4 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | 7 | // const webpack = require('webpack'); 8 | require('dotenv').config(); 9 | 10 | module.exports = { 11 | context: __dirname, 12 | entry: { 13 | index: './index.js', 14 | }, 15 | output: { 16 | path: path.resolve(__dirname, 'dist'), 17 | filename: '[name].js', 18 | publicPath: '/', 19 | }, 20 | devServer: { 21 | port: 8000, 22 | historyApiFallback: true, 23 | }, 24 | // devtool: 'source-map', 25 | devtool: 'cheap-module-eval-source-map', 26 | module: { 27 | rules: [ 28 | { 29 | test: /\.js$/, 30 | exclude: [/node_modules/], 31 | use: [ 32 | { 33 | loader: 'babel-loader', 34 | options: { 35 | root: path.join(__dirname, '..'), 36 | }, 37 | }, 38 | ], 39 | }, 40 | { 41 | test: /\.css$/, 42 | use: [{ loader: 'style-loader' }, { loader: 'css-loader' }], 43 | }, 44 | ], 45 | }, 46 | plugins: [ 47 | // new webpack.DefinePlugin({ 48 | // // $FlowFixMe: This definitely exists here. 49 | // 'process.env.CLIENT_ID': `'${process.env.CLIENT_ID}'`, 50 | // // $FlowFixMe: This definitely exists here. 51 | // 'process.env.CLIENT_SECRET': `'${process.env.CLIENT_SECRET}'`, 52 | // }), 53 | new HtmlWebpackPlugin({ 54 | filename: 'index.html', 55 | inject: false, 56 | template: path.resolve(__dirname, 'index.html'), 57 | }), 58 | new CopyWebpackPlugin(['_redirects', 'favicon.ico', 'index.css']), 59 | ], 60 | }; 61 | -------------------------------------------------------------------------------- /enzymeAdapter.setup.js: -------------------------------------------------------------------------------- 1 | import Enzyme from 'enzyme'; 2 | import Adapter from 'enzyme-adapter-react-16'; 3 | 4 | Enzyme.configure({ adapter: new Adapter() }); 5 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "yarn build:docs" 3 | publish = "docs/dist" 4 | -------------------------------------------------------------------------------- /packages/react-select/animated/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "dist/react-select-reborn.cjs.js", 3 | "module": "dist/react-select-reborn.esm.js", 4 | "browser": { 5 | "./dist/react-select-reborn.cjs.js": "./dist/react-select-reborn.browser.cjs.js", 6 | "./dist/react-select-reborn.esm.js": "./dist/react-select-reborn.browser.esm.js" 7 | }, 8 | "preconstruct": { 9 | "source": "../src/animated" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/react-select/async-creatable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "dist/react-select-reborn.cjs.js", 3 | "module": "dist/react-select-reborn.esm.js", 4 | "browser": { 5 | "./dist/react-select-reborn.cjs.js": "./dist/react-select-reborn.browser.cjs.js", 6 | "./dist/react-select-reborn.esm.js": "./dist/react-select-reborn.browser.esm.js" 7 | }, 8 | "preconstruct": { 9 | "source": "../src/AsyncCreatable" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/react-select/async/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "dist/react-select-reborn.cjs.js", 3 | "module": "dist/react-select-reborn.esm.js", 4 | "browser": { 5 | "./dist/react-select-reborn.cjs.js": "./dist/react-select-reborn.browser.cjs.js", 6 | "./dist/react-select-reborn.esm.js": "./dist/react-select-reborn.browser.esm.js" 7 | }, 8 | "preconstruct": { 9 | "source": "../src/Async" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/react-select/base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "dist/react-select-reborn.cjs.js", 3 | "module": "dist/react-select-reborn.esm.js", 4 | "browser": { 5 | "./dist/react-select-reborn.cjs.js": "./dist/react-select-reborn.browser.cjs.js", 6 | "./dist/react-select-reborn.esm.js": "./dist/react-select-reborn.browser.esm.js" 7 | }, 8 | "preconstruct": { 9 | "source": "../src/Select" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/react-select/creatable/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "main": "dist/react-select-reborn.cjs.js", 3 | "module": "dist/react-select-reborn.esm.js", 4 | "browser": { 5 | "./dist/react-select-reborn.cjs.js": "./dist/react-select-reborn.browser.cjs.js", 6 | "./dist/react-select-reborn.esm.js": "./dist/react-select-reborn.browser.esm.js" 7 | }, 8 | "preconstruct": { 9 | "source": "../src/Creatable" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/react-select/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-select-reborn", 3 | "version": "3.2.0", 4 | "description": "A Select control built with and for ReactJS", 5 | "main": "dist/react-select-reborn.cjs.js", 6 | "module": "dist/react-select-reborn.esm.js", 7 | "sideEffects": false, 8 | "author": "Marcell Toth", 9 | "license": "MIT", 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/JedWatson/react-select.git" 13 | }, 14 | "dependencies": { 15 | "@babel/runtime": "^7.4.4", 16 | "@emotion/cache": "^10.0.9", 17 | "@emotion/core": "^10.0.9", 18 | "@emotion/css": "^10.0.9", 19 | "memoize-one": "^5.0.0", 20 | "prop-types": "^15.6.0", 21 | "react-input-autosize": "^2.2.2", 22 | "react-transition-group": "^4.3.0" 23 | }, 24 | "devDependencies": { 25 | "cypress": "^1.4.1", 26 | "enzyme": "^3.8.0", 27 | "enzyme-to-json": "^3.3.0", 28 | "jest-in-case": "^1.0.2", 29 | "react": "^16.8.0", 30 | "react-dom": "^16.8.0" 31 | }, 32 | "peerDependencies": { 33 | "react": "^16.8.0", 34 | "react-dom": "^16.8.0" 35 | }, 36 | "files": [ 37 | "dist", 38 | "src", 39 | "base", 40 | "animated", 41 | "async", 42 | "creatable", 43 | "async-creatable" 44 | ], 45 | "keywords": [ 46 | "combobox", 47 | "form", 48 | "input", 49 | "multiselect", 50 | "react", 51 | "react-component", 52 | "select", 53 | "ui" 54 | ], 55 | "preconstruct": { 56 | "entrypoints": [ 57 | ".", 58 | "base", 59 | "animated", 60 | "async", 61 | "creatable", 62 | "async-creatable" 63 | ] 64 | }, 65 | "browser": { 66 | "./dist/react-select-reborn.cjs.js": "./dist/react-select-reborn.browser.cjs.js", 67 | "./dist/react-select-reborn.esm.js": "./dist/react-select-reborn.browser.esm.js" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/react-select/src/AsyncCreatable.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import { type ElementConfig } from 'react'; 4 | import { makeAsyncSelect } from './Async'; 5 | import { makeCreatableSelect } from './Creatable'; 6 | import manageState from './stateManager'; 7 | import Select from './Select'; 8 | 9 | const SelectCreatable = makeCreatableSelect>( 10 | Select 11 | ); 12 | const SelectCreatableState = manageState>( 13 | SelectCreatable 14 | ); 15 | 16 | export default makeAsyncSelect>( 17 | SelectCreatableState 18 | ); 19 | -------------------------------------------------------------------------------- /packages/react-select/src/NonceProvider.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { Component, type Node } from 'react'; 3 | import { CacheProvider } from '@emotion/core'; 4 | import createCache from '@emotion/cache'; 5 | import memoizeOne from 'memoize-one'; 6 | 7 | type NonceProviderProps = { 8 | nonce: string, 9 | children: Node, 10 | }; 11 | 12 | export default class NonceProvider extends Component { 13 | constructor(props: NonceProviderProps) { 14 | super(props); 15 | this.createEmotionCache = memoizeOne(this.createEmotionCache); 16 | } 17 | createEmotionCache = (nonce: string) => { 18 | return createCache({ nonce }); 19 | }; 20 | render() { 21 | const emotionCache = this.createEmotionCache(this.props.nonce); 22 | return ( 23 | {this.props.children} 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/react-select/src/__tests__/AsyncCreatable.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { mount } from 'enzyme'; 3 | import toJson from 'enzyme-to-json'; 4 | 5 | import AsyncCreatable from '../AsyncCreatable'; 6 | import Select from '../Select'; 7 | import { components } from '../components'; 8 | import { OPTIONS } from './constants'; 9 | const { Menu, Option } = components; 10 | 11 | test('defaults - snapshot', () => { 12 | const tree = mount(); 13 | expect(toJson(tree)).toMatchSnapshot(); 14 | }); 15 | 16 | test('creates an inner Select', () => { 17 | const asyncCreatableWrapper = mount( 18 | 19 | ); 20 | expect(asyncCreatableWrapper.find(Select).exists()).toBeTruthy(); 21 | }); 22 | 23 | test('render decorated select with props passed', () => { 24 | const asyncCreatableWrapper = mount(); 25 | expect(asyncCreatableWrapper.find(Select).props().className).toBe('foo'); 26 | }); 27 | 28 | test('to show the create option in menu', () => { 29 | let asyncCreatableWrapper = mount( 30 | 31 | ); 32 | let inputValueWrapper = asyncCreatableWrapper.find( 33 | 'div.react-select__input input' 34 | ); 35 | asyncCreatableWrapper.setProps({ inputValue: 'a' }); 36 | inputValueWrapper.simulate('change', { currentTarget: { value: 'a' } }); 37 | expect( 38 | asyncCreatableWrapper 39 | .find(Option) 40 | .last() 41 | .text() 42 | ).toBe('Create "a"'); 43 | }); 44 | 45 | test('to show loading and then create option in menu', () => { 46 | jest.useFakeTimers(); 47 | let loadOptionsSpy = jest.fn((inputValue, callback) => 48 | setTimeout(() => callback(OPTIONS), 200) 49 | ); 50 | let asyncCreatableWrapper = mount( 51 | 52 | ); 53 | let inputValueWrapper = asyncCreatableWrapper.find( 54 | 'div.react-select__input input' 55 | ); 56 | asyncCreatableWrapper.setProps({ inputValue: 'a' }); 57 | inputValueWrapper.simulate('change', { currentTarget: { value: 'a' } }); 58 | 59 | // to show a loading message while loading options 60 | expect(asyncCreatableWrapper.find(Menu).text()).toBe('Loading...'); 61 | jest.runAllTimers(); 62 | asyncCreatableWrapper.update(); 63 | 64 | // show create options once options are loaded 65 | expect( 66 | asyncCreatableWrapper 67 | .find(Option) 68 | .last() 69 | .text() 70 | ).toBe('Create "a"'); 71 | }); 72 | -------------------------------------------------------------------------------- /packages/react-select/src/__tests__/__snapshots__/Creatable.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`defaults - snapshot 1`] = ` 4 | 18 | `; 19 | -------------------------------------------------------------------------------- /packages/react-select/src/__tests__/__snapshots__/StateManaged.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`defaults > snapshot 1`] = ` 4 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /packages/react-select/src/internal/NodeResolver.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import { Component, type Element, type ElementRef } from 'react'; 4 | import { findDOMNode } from 'react-dom'; 5 | 6 | type Props = { 7 | children: Element<*>, 8 | innerRef: ElementRef<*>, 9 | }; 10 | 11 | export default class NodeResolver extends Component { 12 | componentDidMount() { 13 | this.props.innerRef(findDOMNode(this)); 14 | } 15 | componentWillUnmount() { 16 | this.props.innerRef(null); 17 | } 18 | render() { 19 | return this.props.children; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/react-select/src/internal/ScrollBlock.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | /** @jsx jsx */ 3 | import { PureComponent, type Element } from 'react'; 4 | import { jsx } from '@emotion/core'; 5 | import NodeResolver from './NodeResolver'; 6 | import ScrollLock from './ScrollLock/index'; 7 | 8 | type Props = { 9 | children: Element<*>, 10 | isEnabled: boolean, 11 | }; 12 | type State = { 13 | touchScrollTarget: HTMLElement | null, 14 | }; 15 | 16 | // NOTE: 17 | // We shouldn't need this after updating to React v16.3.0, which introduces: 18 | // - createRef() https://reactjs.org/docs/react-api.html#reactcreateref 19 | // - forwardRef() https://reactjs.org/docs/react-api.html#reactforwardref 20 | 21 | export default class ScrollBlock extends PureComponent { 22 | state = { touchScrollTarget: null }; 23 | 24 | // must be in state to trigger a re-render, only runs once per instance 25 | getScrollTarget = (ref: HTMLElement) => { 26 | if (ref === this.state.touchScrollTarget) return; 27 | this.setState({ touchScrollTarget: ref }); 28 | }; 29 | 30 | // this will close the menu when a user clicks outside 31 | blurSelectInput = () => { 32 | if (document.activeElement) { 33 | document.activeElement.blur(); 34 | } 35 | }; 36 | 37 | render() { 38 | const { children, isEnabled } = this.props; 39 | const { touchScrollTarget } = this.state; 40 | 41 | // bail early if not enabled 42 | if (!isEnabled) return children; 43 | 44 | /* 45 | * Div 46 | * ------------------------------ 47 | * blocks scrolling on non-body elements behind the menu 48 | 49 | * NodeResolver 50 | * ------------------------------ 51 | * we need a reference to the scrollable element to "unlock" scroll on 52 | * mobile devices 53 | 54 | * ScrollLock 55 | * ------------------------------ 56 | * actually does the scroll locking 57 | */ 58 | return ( 59 |
60 |
64 | {children} 65 | {touchScrollTarget ? ( 66 | 67 | ) : null} 68 |
69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /packages/react-select/src/internal/ScrollLock/constants.js: -------------------------------------------------------------------------------- 1 | export const STYLE_KEYS = [ 2 | 'boxSizing', 3 | 'height', 4 | 'overflow', 5 | 'paddingRight', 6 | 'position' 7 | ]; 8 | 9 | export const LOCK_STYLES = { 10 | boxSizing: 'border-box', // account for possible declaration `width: 100%;` on body 11 | overflow: 'hidden', 12 | position: 'relative', 13 | height: '100%' 14 | }; 15 | -------------------------------------------------------------------------------- /packages/react-select/src/internal/ScrollLock/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import { Component } from 'react'; 3 | 4 | import { LOCK_STYLES, STYLE_KEYS } from './constants'; 5 | import { 6 | allowTouchMove, 7 | isTouchDevice, 8 | preventInertiaScroll, 9 | preventTouchMove, 10 | } from './utils'; 11 | 12 | const canUseDOM = !!( 13 | typeof window !== 'undefined' && 14 | window.document && 15 | window.document.createElement 16 | ); 17 | 18 | let activeScrollLocks = 0; 19 | 20 | type Props = { 21 | accountForScrollbars: boolean, 22 | touchScrollTarget?: HTMLElement, 23 | }; 24 | type TargetStyle = { 25 | [key: string]: string | null, 26 | }; 27 | 28 | export default class ScrollLock extends Component { 29 | originalStyles = {}; 30 | listenerOptions = { 31 | capture: false, 32 | passive: false, 33 | }; 34 | static defaultProps = { 35 | accountForScrollbars: true, 36 | }; 37 | componentDidMount() { 38 | if (!canUseDOM) return; 39 | 40 | const { accountForScrollbars, touchScrollTarget } = this.props; 41 | const target = document.body; 42 | const targetStyle = target && (target.style: TargetStyle); 43 | 44 | if (accountForScrollbars) { 45 | // store any styles already applied to the body 46 | STYLE_KEYS.forEach(key => { 47 | const val = targetStyle && targetStyle[key]; 48 | this.originalStyles[key] = val; 49 | }); 50 | } 51 | 52 | // apply the lock styles and padding if this is the first scroll lock 53 | if (accountForScrollbars && activeScrollLocks < 1) { 54 | const currentPadding = 55 | parseInt(this.originalStyles.paddingRight, 10) || 0; 56 | const clientWidth = document.body ? document.body.clientWidth : 0; 57 | const adjustedPadding = 58 | window.innerWidth - clientWidth + currentPadding || 0; 59 | 60 | Object.keys(LOCK_STYLES).forEach(key => { 61 | const val = LOCK_STYLES[key]; 62 | if (targetStyle) { 63 | targetStyle[key] = val; 64 | } 65 | }); 66 | 67 | if (targetStyle) { 68 | targetStyle.paddingRight = `${adjustedPadding}px`; 69 | } 70 | } 71 | 72 | // account for touch devices 73 | if (target && isTouchDevice()) { 74 | // Mobile Safari ignores { overflow: hidden } declaration on the body. 75 | target.addEventListener( 76 | 'touchmove', 77 | preventTouchMove, 78 | this.listenerOptions 79 | ); 80 | 81 | // Allow scroll on provided target 82 | if (touchScrollTarget) { 83 | touchScrollTarget.addEventListener( 84 | 'touchstart', 85 | preventInertiaScroll, 86 | this.listenerOptions 87 | ); 88 | touchScrollTarget.addEventListener( 89 | 'touchmove', 90 | allowTouchMove, 91 | this.listenerOptions 92 | ); 93 | } 94 | } 95 | 96 | // increment active scroll locks 97 | activeScrollLocks += 1; 98 | } 99 | componentWillUnmount() { 100 | if (!canUseDOM) return; 101 | 102 | const { accountForScrollbars, touchScrollTarget } = this.props; 103 | const target = document.body; 104 | const targetStyle = target && (target.style: TargetStyle); 105 | 106 | // safely decrement active scroll locks 107 | activeScrollLocks = Math.max(activeScrollLocks - 1, 0); 108 | 109 | // reapply original body styles, if any 110 | if (accountForScrollbars && activeScrollLocks < 1) { 111 | STYLE_KEYS.forEach(key => { 112 | const val = this.originalStyles[key]; 113 | if (targetStyle) { 114 | targetStyle[key] = val; 115 | } 116 | }); 117 | } 118 | 119 | // remove touch listeners 120 | if (target && isTouchDevice()) { 121 | target.removeEventListener( 122 | 'touchmove', 123 | preventTouchMove, 124 | this.listenerOptions 125 | ); 126 | 127 | if (touchScrollTarget) { 128 | touchScrollTarget.removeEventListener( 129 | 'touchstart', 130 | preventInertiaScroll, 131 | this.listenerOptions 132 | ); 133 | touchScrollTarget.removeEventListener( 134 | 'touchmove', 135 | allowTouchMove, 136 | this.listenerOptions 137 | ); 138 | } 139 | } 140 | } 141 | render() { 142 | return null; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /packages/react-select/src/internal/ScrollLock/utils.js: -------------------------------------------------------------------------------- 1 | export function preventTouchMove(e) { 2 | e.preventDefault(); 3 | } 4 | 5 | export function allowTouchMove(e) { 6 | e.stopPropagation(); 7 | } 8 | 9 | export function preventInertiaScroll() { 10 | const top = this.scrollTop; 11 | const totalScroll = this.scrollHeight; 12 | const currentScroll = top + this.offsetHeight; 13 | 14 | if (top === 0) { 15 | this.scrollTop = 1; 16 | } else if (currentScroll === totalScroll) { 17 | this.scrollTop = top - 1; 18 | } 19 | } 20 | 21 | // `ontouchstart` check works on most browsers 22 | // `maxTouchPoints` works on IE10/11 and Surface 23 | export function isTouchDevice() { 24 | return 'ontouchstart' in window || navigator.maxTouchPoints; 25 | } 26 | -------------------------------------------------------------------------------- /packages/react-select/src/internal/index.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | export { default as A11yText } from './A11yText'; 4 | export { default as DummyInput } from './DummyInput'; 5 | export { default as NodeResolver } from './NodeResolver'; 6 | export { default as ScrollBlock } from './ScrollBlock'; 7 | export { default as ScrollCaptor } from './ScrollCaptor'; 8 | -------------------------------------------------------------------------------- /packages/react-select/src/internal/react-fast-compare.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var isArray = Array.isArray; 4 | var keyList = Object.keys; 5 | var hasProp = Object.prototype.hasOwnProperty; 6 | 7 | function equal(a, b) { 8 | // fast-deep-equal index.js 2.0.1 9 | if (a === b) return true; 10 | 11 | if (a && b && typeof a == 'object' && typeof b == 'object') { 12 | var arrA = isArray(a) 13 | , arrB = isArray(b) 14 | , i 15 | , length 16 | , key; 17 | 18 | if (arrA && arrB) { 19 | length = a.length; 20 | if (length != b.length) return false; 21 | for (i = length; i-- !== 0;) { 22 | if (!equal(a[i], b[i])) return false; 23 | } 24 | return true; 25 | } 26 | 27 | if (arrA != arrB) return false; 28 | 29 | var dateA = a instanceof Date 30 | , dateB = b instanceof Date; 31 | if (dateA != dateB) return false; 32 | if (dateA && dateB) return a.getTime() == b.getTime(); 33 | 34 | var regexpA = a instanceof RegExp 35 | , regexpB = b instanceof RegExp; 36 | if (regexpA != regexpB) return false; 37 | if (regexpA && regexpB) return a.toString() == b.toString(); 38 | 39 | var keys = keyList(a); 40 | length = keys.length; 41 | 42 | if (length !== keyList(b).length) { 43 | return false; 44 | } 45 | 46 | for (i = length; i-- !== 0;) { 47 | if (!hasProp.call(b, keys[i])) return false; 48 | } 49 | // end fast-deep-equal 50 | 51 | // Custom handling for React 52 | for (i = length; i-- !== 0;) { 53 | key = keys[i]; 54 | if (key === '_owner' && a.$$typeof) { 55 | // React-specific: avoid traversing React elements' _owner. 56 | // _owner contains circular references 57 | // and is not needed when comparing the actual elements (and not their owners) 58 | // .$$typeof and ._store on just reasonable markers of a react element 59 | continue; 60 | } else { 61 | // all other properties should be traversed as usual 62 | if (!equal(a[key], b[key])) return false; 63 | } 64 | } 65 | 66 | // fast-deep-equal index.js 2.0.1 67 | return true; 68 | } 69 | 70 | return a!==a && b!==b; 71 | } 72 | // end fast-deep-equal 73 | 74 | export default function exportedEqual(a, b) { 75 | try { 76 | return equal(a, b); 77 | } catch (error) { 78 | if (error.message && error.message.match(/stack|recursion/i)) { 79 | // warn on circular references, don't crash 80 | // browsers give this different errors name and messages: 81 | // chrome/safari: "RangeError", "Maximum call stack size exceeded" 82 | // firefox: "InternalError", too much recursion" 83 | // edge: "Error", "Out of stack space" 84 | console.warn('Warning: react-fast-compare does not handle circular references.', error.name, error.message); 85 | return false; 86 | } 87 | // some other error. we should definitely know about these 88 | throw error; 89 | } 90 | }; 91 | -------------------------------------------------------------------------------- /packages/react-select/src/stateManager.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import React, { 4 | Component, 5 | type ElementRef, 6 | type AbstractComponent, 7 | type Config, 8 | } from 'react'; 9 | 10 | import type { ActionMeta, InputActionMeta, ValueType } from './types'; 11 | 12 | export type DefaultProps = {| 13 | defaultInputValue: string, 14 | defaultMenuIsOpen: boolean, 15 | defaultValue: ValueType, 16 | |}; 17 | export type Props = { 18 | ...DefaultProps, 19 | inputValue?: string, 20 | menuIsOpen?: boolean, 21 | value?: ValueType, 22 | onChange?: (ValueType, ActionMeta) => void, 23 | }; 24 | 25 | type StateProps

= $Diff< 26 | P, 27 | { 28 | inputValue: any, 29 | value: any, 30 | menuIsOpen: any, 31 | onChange: any, 32 | onInputChange: any, 33 | onMenuClose: any, 34 | onMenuOpen: any, 35 | } 36 | >; 37 | 38 | type State = { 39 | inputValue: string, 40 | menuIsOpen: boolean, 41 | value: ValueType, 42 | }; 43 | 44 | export const defaultProps = { 45 | defaultInputValue: '', 46 | defaultMenuIsOpen: false, 47 | defaultValue: null, 48 | }; 49 | 50 | const manageState = ( 51 | SelectComponent: AbstractComponent 52 | ): AbstractComponent & Config> => 53 | class StateManager extends Component & Props, State> { 54 | static defaultProps: DefaultProps = defaultProps; 55 | 56 | select: ElementRef<*>; 57 | 58 | state = { 59 | inputValue: 60 | this.props.inputValue !== undefined 61 | ? this.props.inputValue 62 | : this.props.defaultInputValue, 63 | menuIsOpen: 64 | this.props.menuIsOpen !== undefined 65 | ? this.props.menuIsOpen 66 | : this.props.defaultMenuIsOpen, 67 | value: 68 | this.props.value !== undefined 69 | ? this.props.value 70 | : this.props.defaultValue, 71 | }; 72 | focus() { 73 | this.select.focus(); 74 | } 75 | blur() { 76 | this.select.blur(); 77 | } 78 | // FIXME: untyped flow code, return any 79 | getProp(key: string) { 80 | return this.props[key] !== undefined ? this.props[key] : this.state[key]; 81 | } 82 | // FIXME: untyped flow code, return any 83 | callProp(name: string, ...args: any) { 84 | if (typeof this.props[name] === 'function') { 85 | return this.props[name](...args); 86 | } 87 | } 88 | onChange = (value: any, actionMeta: ActionMeta) => { 89 | this.callProp('onChange', value, actionMeta); 90 | this.setState({ value }); 91 | }; 92 | onInputChange = (value: any, actionMeta: InputActionMeta) => { 93 | // TODO: for backwards compatibility, we allow the prop to return a new 94 | // value, but now inputValue is a controllable prop we probably shouldn't 95 | const newValue = this.callProp('onInputChange', value, actionMeta); 96 | this.setState({ 97 | inputValue: newValue !== undefined ? newValue : value, 98 | }); 99 | }; 100 | onMenuOpen = () => { 101 | this.callProp('onMenuOpen'); 102 | this.setState({ menuIsOpen: true }); 103 | }; 104 | onMenuClose = () => { 105 | this.callProp('onMenuClose'); 106 | this.setState({ menuIsOpen: false }); 107 | }; 108 | render() { 109 | const { 110 | defaultInputValue, 111 | defaultMenuIsOpen, 112 | defaultValue, 113 | ...props 114 | } = this.props; 115 | return ( 116 | { 119 | this.select = ref; 120 | }} 121 | inputValue={this.getProp('inputValue')} 122 | menuIsOpen={this.getProp('menuIsOpen')} 123 | onChange={this.onChange} 124 | onInputChange={this.onInputChange} 125 | onMenuClose={this.onMenuClose} 126 | onMenuOpen={this.onMenuOpen} 127 | value={this.getProp('value')} 128 | /> 129 | ); 130 | } 131 | }; 132 | 133 | export default manageState; 134 | -------------------------------------------------------------------------------- /packages/react-select/src/styles.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import { 4 | containerCSS, 5 | indicatorsContainerCSS, 6 | valueContainerCSS, 7 | } from './components/containers'; 8 | import { css as controlCSS } from './components/Control'; 9 | import { groupCSS, groupHeadingCSS } from './components/Group'; 10 | import { 11 | clearIndicatorCSS, 12 | dropdownIndicatorCSS, 13 | loadingIndicatorCSS, 14 | indicatorSeparatorCSS, 15 | } from './components/indicators'; 16 | import { inputCSS } from './components/Input'; 17 | import { placeholderCSS } from './components/Placeholder'; 18 | import { optionCSS } from './components/Option'; 19 | import { 20 | menuCSS, 21 | menuListCSS, 22 | menuPortalCSS, 23 | noOptionsMessageCSS, 24 | loadingMessageCSS, 25 | } from './components/Menu'; 26 | import { css as singleValueCSS } from './components/SingleValue'; 27 | import { 28 | multiValueCSS, 29 | multiValueLabelCSS, 30 | multiValueRemoveCSS, 31 | } from './components/MultiValue'; 32 | 33 | type Props = { [key: string]: any }; 34 | 35 | // TODO: flow for state 36 | type StyleFn = (props: Props, state: { [key: string]: any }) => {}; 37 | 38 | export type Styles = { 39 | clearIndicator?: StyleFn, 40 | container?: StyleFn, 41 | control?: StyleFn, 42 | dropdownIndicator?: StyleFn, 43 | group?: StyleFn, 44 | groupHeading?: StyleFn, 45 | indicatorsContainer?: StyleFn, 46 | indicatorSeparator?: StyleFn, 47 | input?: StyleFn, 48 | loadingIndicator?: StyleFn, 49 | loadingMessage?: StyleFn, 50 | menu?: StyleFn, 51 | menuList?: StyleFn, 52 | menuPortal?: StyleFn, 53 | multiValue?: StyleFn, 54 | multiValueLabel?: StyleFn, 55 | multiValueRemove?: StyleFn, 56 | noOptionsMessage?: StyleFn, 57 | option?: StyleFn, 58 | placeholder?: StyleFn, 59 | singleValue?: StyleFn, 60 | valueContainer: StyleFn, 61 | }; 62 | export type StylesConfig = $Shape; 63 | export type GetStyles = (string, Props) => {}; 64 | 65 | export const defaultStyles: Styles = { 66 | clearIndicator: clearIndicatorCSS, 67 | container: containerCSS, 68 | control: controlCSS, 69 | dropdownIndicator: dropdownIndicatorCSS, 70 | group: groupCSS, 71 | groupHeading: groupHeadingCSS, 72 | indicatorsContainer: indicatorsContainerCSS, 73 | indicatorSeparator: indicatorSeparatorCSS, 74 | input: inputCSS, 75 | loadingIndicator: loadingIndicatorCSS, 76 | loadingMessage: loadingMessageCSS, 77 | menu: menuCSS, 78 | menuList: menuListCSS, 79 | menuPortal: menuPortalCSS, 80 | multiValue: multiValueCSS, 81 | multiValueLabel: multiValueLabelCSS, 82 | multiValueRemove: multiValueRemoveCSS, 83 | noOptionsMessage: noOptionsMessageCSS, 84 | option: optionCSS, 85 | placeholder: placeholderCSS, 86 | singleValue: singleValueCSS, 87 | valueContainer: valueContainerCSS, 88 | }; 89 | 90 | // Merge Utility 91 | // Allows consumers to extend a base Select with additional styles 92 | 93 | export function mergeStyles(source: Object, target: Object = {}) { 94 | // initialize with source styles 95 | const styles = { ...source }; 96 | 97 | // massage in target styles 98 | Object.keys(target).forEach(key => { 99 | if (source[key]) { 100 | styles[key] = (rsCss, props) => { 101 | return target[key](source[key](rsCss, props), props); 102 | }; 103 | } else { 104 | styles[key] = target[key]; 105 | } 106 | }); 107 | 108 | return styles; 109 | } 110 | -------------------------------------------------------------------------------- /packages/react-select/src/theme.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | 3 | import type { Theme } from './types'; 4 | 5 | export const colors = { 6 | primary: '#2684FF', 7 | primary75: '#4C9AFF', 8 | primary50: '#B2D4FF', 9 | primary25: '#DEEBFF', 10 | 11 | danger: '#DE350B', 12 | dangerLight: '#FFBDAD', 13 | 14 | neutral0: 'hsl(0, 0%, 100%)', 15 | neutral5: 'hsl(0, 0%, 95%)', 16 | neutral10: 'hsl(0, 0%, 90%)', 17 | neutral20: 'hsl(0, 0%, 80%)', 18 | neutral30: 'hsl(0, 0%, 70%)', 19 | neutral40: 'hsl(0, 0%, 60%)', 20 | neutral50: 'hsl(0, 0%, 50%)', 21 | neutral60: 'hsl(0, 0%, 40%)', 22 | neutral70: 'hsl(0, 0%, 30%)', 23 | neutral80: 'hsl(0, 0%, 20%)', 24 | neutral90: 'hsl(0, 0%, 10%)', 25 | }; 26 | 27 | const borderRadius = 4; 28 | // Used to calculate consistent margin/padding on elements 29 | const baseUnit = 4; 30 | // The minimum height of the control 31 | const controlHeight = 38; 32 | // The amount of space between the control and menu */ 33 | const menuGutter = baseUnit * 2; 34 | 35 | export const spacing = { 36 | baseUnit, 37 | controlHeight, 38 | menuGutter, 39 | }; 40 | 41 | export const defaultTheme: Theme = { 42 | borderRadius, 43 | colors, 44 | spacing, 45 | }; 46 | 47 | export type ThemeConfig = Theme | ((theme: Theme) => Theme); 48 | -------------------------------------------------------------------------------- /packages/react-select/src/types.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import type { Ref } from 'react'; 3 | 4 | export type OptionType = { 5 | [string]: any, 6 | }; 7 | 8 | export type OptionsType = Array; 9 | 10 | export type GroupType = { 11 | options: OptionsType, 12 | [string]: any, 13 | }; 14 | 15 | export type ValueType = OptionType | OptionsType | null | void; 16 | 17 | export type FocusEventHandler = (SyntheticFocusEvent) => void; 18 | export type MouseEventHandler = (SyntheticMouseEvent) => void; 19 | export type KeyboardEventHandler = ( 20 | SyntheticKeyboardEvent 21 | ) => void; 22 | 23 | export type InnerRef = Ref<*>; 24 | export type PropsWithInnerRef = { 25 | /** The inner reference. */ 26 | innerRef: Ref<*>, 27 | }; 28 | 29 | type ThemeSpacing = { 30 | baseUnit: number, 31 | controlHeight: number, 32 | menuGutter: number, 33 | }; 34 | 35 | export type Theme = { 36 | borderRadius: number, 37 | colors: { [key: string]: string }, 38 | spacing: ThemeSpacing, 39 | }; 40 | 41 | export type PropsWithStyles = { 42 | /** 43 | Get the styles of a particular part of the select. Pass in the name of the 44 | property as the first argument, and the current props as the second argument. 45 | See the `styles` object for the properties available. 46 | */ 47 | getStyles: (string, any) => {}, 48 | theme: Theme, 49 | }; 50 | 51 | export type ClassNameList = Array; 52 | export type ClassNamesState = { [string]: boolean } | void; 53 | 54 | export type CommonProps = { 55 | clearValue: () => void, 56 | className?: string, 57 | cx: ( 58 | state: ClassNamesState | void, 59 | className: string | void 60 | ) => string | void, 61 | /** 62 | Get the styles of a particular part of the select. Pass in the name of the 63 | property as the first argument, and the current props as the second argument. 64 | See the `styles` object for the properties available. 65 | */ 66 | getStyles: (string, any) => {}, 67 | theme: Theme, 68 | getValue: () => ValueType, 69 | hasValue: boolean, 70 | isMulti: boolean, 71 | options: OptionsType, 72 | selectOption: OptionType => void, 73 | selectProps: any, 74 | setValue: (ValueType, ActionTypes) => void, 75 | }; 76 | 77 | export type ActionTypes = 78 | | 'select-option' 79 | | 'deselect-option' 80 | | 'remove-value' 81 | | 'pop-value' 82 | | 'set-value' 83 | | 'clear' 84 | | 'create-option'; 85 | 86 | export type ActionMeta = { 87 | action: ActionTypes, 88 | }; 89 | 90 | export type InputActionTypes = 91 | | 'set-value' 92 | | 'input-change' 93 | | 'input-blur' 94 | | 'menu-close'; 95 | 96 | export type InputActionMeta = {| 97 | action: InputActionTypes, 98 | |}; 99 | 100 | export type MenuPlacement = 'auto' | 'bottom' | 'top'; 101 | export type MenuPosition = 'absolute' | 'fixed'; 102 | 103 | export type FocusDirection = 104 | | 'up' 105 | | 'down' 106 | | 'pageup' 107 | | 'pagedown' 108 | | 'first' 109 | | 'last'; 110 | 111 | export type OptionProps = PropsWithInnerRef & { 112 | data: any, 113 | id: number, 114 | index: number, 115 | isDisabled: boolean, 116 | isFocused: boolean, 117 | isSelected: boolean, 118 | label: string, 119 | onClick: MouseEventHandler, 120 | onMouseOver: MouseEventHandler, 121 | value: any, 122 | }; 123 | -------------------------------------------------------------------------------- /typings/extract-react-types-loader.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | declare module.exports: Object; 3 | -------------------------------------------------------------------------------- /typings/raw-loader.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | declare module.exports: string; 3 | --------------------------------------------------------------------------------