diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..17bf4c2 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,12 @@ +## Pull Requests + +Looks like you want to help out on vue-select.. awesome! Here's a few things to keep in mind when contributing. + +- Vue Select uses semantic release to automate the release process. This means that good commit + messages are critical. If you're unfamiliar with [conventional changelog](https://github.com/ajoslin/conventional-changelog) you can run `yarn commit` to generate a commit message. +- It's almost always better to ask before you jump into a PR if you want to add new functionality +. It's not fun for anyone when you spend time on something that doesn't end up in the component. +- If your PR fixes or references an open issue, be sure to reference it in your message. +- If you're adding new functionality, make sure your code has good test coverage. + +:tada: Thanks for contributing, and an even bigger thanks for reading these guidelines! diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b7a1ebc --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,28 @@ +name: Release +on: + push: + branches: + - master +jobs: + release: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 12 + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Test with Coverage + run: yarn test + + - name: Build + run: yarn build + + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..874868b --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,38 @@ +name: Test & Build +on: [pull_request] +jobs: + test: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 12 + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Test with Coverage + run: yarn test --coverage --coverageReporters=lcov + + - name: Report Coverage + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + build: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: 12 + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Build + run: yarn build + + - name: Bundlewatch + run: npx bundlewatch diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 690e9ff..0000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: node_js -cache: yarn - -node_js: - - "8" - -script: - - yarn test --coverage --coverageReporters=text-lcov | coveralls - - yarn build && bundlewatch --max-size 20kb ./dist/!(*.map) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index e705d1f..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,10 +0,0 @@ -## Pull Requests - -Looks like you want to help out on vue-select.. awesome! Here's a few things to keep in mind when contributing. - -1. If your PR contains multiple commits, try to keep those commits succinct, with descriptive messages. This makes it easier to understand your thought process. -2. **Don't run the build** before submitting. The build is only run and committed immediately before a new release. -3. If your PR fixes or references an open issue, be sure to reference it in your message. -4. If you're adding new functionality, make sure your code has good test coverage. - -:tada: Thanks for contributing, and an even bigger thanks for reading these guidelines! diff --git a/docs/.vuepress/components/BetterNoOptions.vue b/docs/.vuepress/components/BetterNoOptions.vue new file mode 100644 index 0000000..e1d429b --- /dev/null +++ b/docs/.vuepress/components/BetterNoOptions.vue @@ -0,0 +1,16 @@ + + + diff --git a/docs/.vuepress/components/PositionedWithPopper.vue b/docs/.vuepress/components/PositionedWithPopper.vue new file mode 100644 index 0000000..d7580bf --- /dev/null +++ b/docs/.vuepress/components/PositionedWithPopper.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 2bed2c8..2ee84ca 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -129,6 +129,7 @@ module.exports = { collapsable: false, children: [ ['guide/keydown', 'Keydown Events'], + ['guide/positioning', 'Dropdown Position'] ], }, { diff --git a/docs/api/props.md b/docs/api/props.md index 2ae8284..d4d200d 100644 --- a/docs/api/props.md +++ b/docs/api/props.md @@ -1,3 +1,18 @@ +## appendToBody + +Append the dropdown element to the end of the body +and size/position it dynamically. Use it if you have +overflow or z-index issues. + +See [Dropdown Position](../guide/positioning.md) for more details. + +```js +appendToBody: { + type: Boolean, + default: false +}, +``` + ## value Contains the currently selected value. Very similar to a @@ -109,6 +124,30 @@ transition: { }, ``` +## calculatePosition + +When `appendToBody` is true, this function is responsible for positioning the drop down list. + +See [Dropdown Position](../guide/positioning.md) for more details. + +```js +calculatePosition: { + type: Function, + /** + * @param dropdownList {HTMLUListElement} + * @param component {Vue} current instance of vue select + * @param width {string} calculated width in pixels of the dropdown menu + * @param top {string} absolute position top value in pixels relative to the document + * @param left {string} absolute position left value in pixels relative to the document + */ + default(dropdownList, component, {width, top, left}) { + dropdownList.style.top = top; + dropdownList.style.left = left; + dropdownList.style.width = width; + } +} +``` + ## clearSearchOnSelect Enables/disables clearing the search text when an option is selected. @@ -120,6 +159,19 @@ clearSearchOnSelect: { }, ``` +## clearSearchOnBlur + +Enables/disables clearing the search text when the search input is blurred. + +```js +clearSearchOnBlur: { + type: Function, + default: function ({ clearSearchOnSelect, multiple }) { + return clearSearchOnSelect && !multiple + } +}, +``` + ## closeOnSelect Close a dropdown when an option is chosen. Set to false to keep the dropdown @@ -340,10 +392,10 @@ createOption: { ## resetOnOptionsChange When false, updating the options will not reset the selected value. - -Since `v3.4+` the prop accepts either a `boolean` or `function` that returns a `boolean`. -If defined as a function, it will receive the params listed below. +Since `v3.4+` the prop accepts either a `boolean` or `function` that returns a `boolean`. + +If defined as a function, it will receive the params listed below. ```js /** @@ -399,3 +451,4 @@ selectOnTab: { type: Boolean, default: false } +``` diff --git a/docs/api/slots.md b/docs/api/slots.md index 1f3a94f..68e74a2 100644 --- a/docs/api/slots.md +++ b/docs/api/slots.md @@ -7,13 +7,16 @@ Slots can be used to change the look and feel of the UI, or to simply swap out t ### `selected-option` -#### Scope: +#### Scope: - `option {Object}` - A selected option ```html - - {{ getOptionLabel(option) }} + + {{ getOptionLabel(option) }} ``` @@ -27,16 +30,32 @@ Slots can be used to change the look and feel of the UI, or to simply swap out t - `multiple {Boolean}` - If the component supports the selection of multiple values ```html - - - - {{ getOptionLabel(option) }} - - - + + + + {{ getOptionLabel(option) }} + + + ``` @@ -44,9 +63,29 @@ Slots can be used to change the look and feel of the UI, or to simply swap out t ### `spinner` +#### Scope: + +- `loading {Boolean}` - if the component is in a loading state + ```html - -
Loading...
+ +
Loading...
+
+``` + +### `open-indicator` + +```js +attributes : { + 'ref': 'openIndicator', + 'role': 'presentation', + 'class': 'vs__open-indicator', +} +``` + +```vue + + ``` @@ -54,12 +93,26 @@ Slots can be used to change the look and feel of the UI, or to simply swap out t ### `option` -#### Scope: - - `option {Object}` - The currently iterated option from `filteredOptions` ```html - - {{ getOptionLabel(option) }} + + {{ getOptionLabel(option) }} + +``` + +### `no-options` + +The no options slot is displayed in the dropdown when `filteredOptions.length === 0`. + +- `search {String}` - the current search text +- `searching {Boolean}` - if the component has search text + +```vue + + Sorry, no matching options. ``` diff --git a/docs/guide/positioning.md b/docs/guide/positioning.md new file mode 100644 index 0000000..ad5a4b9 --- /dev/null +++ b/docs/guide/positioning.md @@ -0,0 +1,33 @@ +## Default + +With the default CSS, Vue Select uses absolute positioning to render the dropdown menu. The root +`.v-select` container (the components `$el`) is used as the `relative` parent for the dropdown. The +dropdown will be displayed below the `$el` regardless of the available space. + +This works for most cases, but you might run into issues placing into a modal or near the bottom of +the viewport. If you need more fine grain control, you can use calculated positioning. + +## Calculated + +If you want more control over how the dropdown is rendered, or if you're running into z-index issues, +you may use the `appendToBody` boolean prop. When enabled, Vue Select will append the dropdown to +the document, outside of the `.v-select` container, and position it with Javscript. + +When `appendToBody` is true, the positioning will be handled by the `calculatePosition` prop. This +function is responsible for setting top/left absolute positioning values for the dropdown. The +default implementation places the dropdown in the same position that it would normally appear. + +## Popper.js Integration + +[Popper.js](https://popper.js.org/) is an awesome, 3kb utility for calculating positions of just +about any DOM element relative to another. + +By using the `appendToBody` and `calculatePosition` props, we're able to integrate directly with +popper to calculate positioning for us. + + + +Check out the [Popper Docs](https://popper.js.org/docs/v2/modifiers/) to see the full `modifiers` +API being used below. + +<<< @/.vuepress/components/PositionedWithPopper.vue{25-59} diff --git a/docs/guide/slots.md b/docs/guide/slots.md index 7bfe9b1..62d7392 100644 --- a/docs/guide/slots.md +++ b/docs/guide/slots.md @@ -1,22 +1,32 @@ ::: tip 🚧 This section of the guide is a work in progress! Check back soon for an update. -Vue Select currently offers quite a few scoped slots, and you can check out the +Vue Select currently offers quite a few scoped slots, and you can check out the [API Docs for Slots](../api/slots.md) in the meantime while a good guide is put together. ::: -#### Scoped Slot `option` +### Scoped Slot `option` vue-select provides the scoped `option` slot in order to create custom dropdown templates. ```html - - -``` + + +``` Using the `option` slot with props `"option"` provides the current option variable to the template. + +### Improving the default `no-options` text + +The `no-options` slot is displayed in the dropdown when `filteredOptions === 0`. By default, it +displays _Sorry, no matching options_. You can add more contextual information by using the slot +in your own apps. + + + +<<< @/.vuepress/components/BetterNoOptions.vue diff --git a/docs/package.json b/docs/package.json index 1fcd52b..79ca247 100644 --- a/docs/package.json +++ b/docs/package.json @@ -8,6 +8,7 @@ "build:preview": "cross-env DEPLOY_PREVIEW=true vuepress build" }, "devDependencies": { + "@popperjs/core": "^2.1.0", "@vuepress/plugin-active-header-links": "^1.0.0-alpha.47", "@vuepress/plugin-google-analytics": "^1.0.0-alpha.47", "@vuepress/plugin-nprogress": "^1.0.0-alpha.47", diff --git a/docs/yarn.lock b/docs/yarn.lock index 8548f5b..ce6091c 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -715,6 +715,11 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@popperjs/core@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.1.0.tgz#09a7a352a40508156e1256efdc015593feca28e0" + integrity sha512-ntN5t5spqhQv28cLfmmt1dYabsudzR5A7PU15gr/gzcT/gzqAOnYFQPaLPFraDa7ZCJG2eJ1JsO7pgXbYXGIrw== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" diff --git a/package.json b/package.json index f8218bc..becf537 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-select", - "version": "3.4.0", + "version": "3.7.0", "description": "Everything you wish the HTML