mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-22 10:30:34 +03:00
wip
This commit is contained in:
+2
-2
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import vSelect from "../src/components/Select";
|
import vSelect from "../src/components/Select";
|
||||||
import countries from "../docs/data/countryCodes";
|
import countries from "../docs/assets/data/countryCodes";
|
||||||
import books from "../docs/data/books";
|
import books from "../docs/assets/data/books";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { vSelect },
|
components: { vSelect },
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path d="M11 3a1 1 0 100 2h2.586l-6.293 6.293a1 1 0 101.414 1.414L15 6.414V9a1 1 0 102 0V4a1 1 0 00-1-1h-5z" />
|
||||||
|
<path d="M5 5a2 2 0 00-2 2v8a2 2 0 002 2h8a2 2 0 002-2v-3a1 1 0 10-2 0v3H5V7h3a1 1 0 000-2H5z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 306 B |
@@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<label for="search" class="block text-sm font-medium text-gray-700 sr-only">
|
||||||
|
Quick search
|
||||||
|
</label>
|
||||||
|
<div class="mt-1 relative flex items-center">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="search"
|
||||||
|
id="search"
|
||||||
|
class="
|
||||||
|
shadow-sm
|
||||||
|
focus:ring-indigo-500 focus:border-indigo-500
|
||||||
|
block
|
||||||
|
w-full
|
||||||
|
pr-12
|
||||||
|
sm:text-sm
|
||||||
|
border-gray-300
|
||||||
|
rounded-md
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<div class="absolute inset-y-0 right-0 flex py-1.5 pr-1.5">
|
||||||
|
<kbd
|
||||||
|
class="
|
||||||
|
inline-flex
|
||||||
|
items-center
|
||||||
|
border border-gray-200
|
||||||
|
rounded
|
||||||
|
px-2
|
||||||
|
text-sm
|
||||||
|
font-sans font-medium
|
||||||
|
text-gray-400
|
||||||
|
"
|
||||||
|
>
|
||||||
|
⌘K
|
||||||
|
</kbd>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "ContentSearch",
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -3,16 +3,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countryCodes from '../data/countryCodes.js';
|
import countryCodes from "../assets/data/countryCodes.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CountrySelect',
|
name: "CountrySelect",
|
||||||
data: () => ({
|
data: () => ({
|
||||||
options: countryCodes,
|
options: countryCodes,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select :filter="fuseSearch" :options="books" :getOptionLabel="option => option.title">
|
<v-select
|
||||||
|
:filter="fuseSearch"
|
||||||
|
:options="books"
|
||||||
|
:getOptionLabel="(option) => option.title"
|
||||||
|
>
|
||||||
<template #option="{ author, title }">
|
<template #option="{ author, title }">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
<br />
|
<br />
|
||||||
@@ -10,22 +14,22 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Fuse from "fuse.js";
|
import Fuse from "fuse.js";
|
||||||
import books from "../data/books.js";
|
import books from "../assets/data/books.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
books: () => books
|
books: () => books,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fuseSearch(options, search) {
|
fuseSearch(options, search) {
|
||||||
const fuse = new Fuse(options, {
|
const fuse = new Fuse(options, {
|
||||||
keys: ["title", "author.firstName", "author.lastName"],
|
keys: ["title", "author.firstName", "author.lastName"],
|
||||||
shouldSort: true
|
shouldSort: true,
|
||||||
});
|
});
|
||||||
return search.length
|
return search.length
|
||||||
? fuse.search(search).map(({ item }) => item)
|
? fuse.search(search).map(({ item }) => item)
|
||||||
: fuse.list;
|
: fuse.list;
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
:filterable="false"
|
:filterable="false"
|
||||||
@open="onOpen"
|
@open="onOpen"
|
||||||
@close="onClose"
|
@close="onClose"
|
||||||
@search="query => search = query"
|
@search="(query) => (search = query)"
|
||||||
>
|
>
|
||||||
<template #list-footer>
|
<template #list-footer>
|
||||||
<li ref="load" class="loader" v-show="hasNextPage">
|
<li ref="load" class="loader" v-show="hasNextPage">
|
||||||
@@ -15,16 +15,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countries from '../data/countries.js';
|
import countries from "../assets/data/countries.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "InfiniteScroll",
|
name: "InfiniteScroll",
|
||||||
data: () => ({
|
data: () => ({
|
||||||
observer: null,
|
observer: null,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
search: ''
|
search: "",
|
||||||
}),
|
}),
|
||||||
mounted () {
|
mounted() {
|
||||||
/**
|
/**
|
||||||
* You could do this directly in data(), but since these docs
|
* You could do this directly in data(), but since these docs
|
||||||
* are server side rendered, IntersectionObserver doesn't exist
|
* are server side rendered, IntersectionObserver doesn't exist
|
||||||
@@ -33,27 +33,27 @@ export default {
|
|||||||
this.observer = new IntersectionObserver(this.infiniteScroll);
|
this.observer = new IntersectionObserver(this.infiniteScroll);
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
filtered () {
|
filtered() {
|
||||||
return countries.filter(country => country.includes(this.search));
|
return countries.filter((country) => country.includes(this.search));
|
||||||
},
|
},
|
||||||
paginated () {
|
paginated() {
|
||||||
return this.filtered.slice(0, this.limit);
|
return this.filtered.slice(0, this.limit);
|
||||||
},
|
},
|
||||||
hasNextPage () {
|
hasNextPage() {
|
||||||
return this.paginated.length < this.filtered.length;
|
return this.paginated.length < this.filtered.length;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onOpen () {
|
async onOpen() {
|
||||||
if (this.hasNextPage) {
|
if (this.hasNextPage) {
|
||||||
await this.$nextTick();
|
await this.$nextTick();
|
||||||
this.observer.observe(this.$refs.load)
|
this.observer.observe(this.$refs.load);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClose () {
|
onClose() {
|
||||||
this.observer.disconnect();
|
this.observer.disconnect();
|
||||||
},
|
},
|
||||||
async infiniteScroll ([{isIntersecting, target}]) {
|
async infiniteScroll([{ isIntersecting, target }]) {
|
||||||
if (isIntersecting) {
|
if (isIntersecting) {
|
||||||
const ul = target.offsetParent;
|
const ul = target.offsetParent;
|
||||||
const scrollTop = target.offsetParent.scrollTop;
|
const scrollTop = target.offsetParent.scrollTop;
|
||||||
@@ -61,14 +61,14 @@ export default {
|
|||||||
await this.$nextTick();
|
await this.$nextTick();
|
||||||
ul.scrollTop = scrollTop;
|
ul.scrollTop = scrollTop;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.loader {
|
.loader {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #bbbbbb;
|
color: #bbbbbb;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import books from '../data/books.js';
|
import books from "../assets/data/books.js";
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return { selected: [] }
|
return { selected: [] };
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
books: () => books,
|
books: () => books,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<v-select
|
<v-select
|
||||||
:options="options"
|
:options="options"
|
||||||
:value="person.country"
|
:value="person.country"
|
||||||
@input="country => updateCountry(person, country)"
|
@input="(country) => updateCountry(person, country)"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -18,14 +18,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countries from '../data/countries.js';
|
import countries from "../assets/data/countries.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
people: [{name: 'John', country: ''}, {name: 'Jane', country: ''}],
|
people: [
|
||||||
|
{ name: "John", country: "" },
|
||||||
|
{ name: "Jane", country: "" },
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
methods: {
|
methods: {
|
||||||
updateCountry (person, country) {
|
updateCountry(person, country) {
|
||||||
person.country = country;
|
person.country = country;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -36,8 +39,8 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
table {
|
table {
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select :options="paginated" @search="query => search = query" :filterable="false">
|
<v-select
|
||||||
|
:options="paginated"
|
||||||
|
@search="(query) => (search = query)"
|
||||||
|
:filterable="false"
|
||||||
|
>
|
||||||
<li slot="list-footer" class="pagination">
|
<li slot="list-footer" class="pagination">
|
||||||
<button @click="offset -= 10" :disabled="!hasPrevPage">Prev</button>
|
<button @click="offset -= 10" :disabled="!hasPrevPage">Prev</button>
|
||||||
<button @click="offset += 10" :disabled="!hasNextPage">Next</button>
|
<button @click="offset += 10" :disabled="!hasNextPage">Next</button>
|
||||||
@@ -8,42 +12,46 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countries from '../data/countries.js';
|
import countries from "../assets/data/countries.js";
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
countries,
|
countries,
|
||||||
search: '',
|
search: "",
|
||||||
offset: 0,
|
offset: 0,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
filtered () {
|
filtered() {
|
||||||
return this.countries.filter(country => country.includes(this.search));
|
return this.countries.filter((country) => country.includes(this.search));
|
||||||
},
|
},
|
||||||
paginated () {
|
paginated() {
|
||||||
return this.filtered.slice(this.offset, this.limit + this.offset);
|
return this.filtered.slice(this.offset, this.limit + this.offset);
|
||||||
},
|
},
|
||||||
hasNextPage () {
|
hasNextPage() {
|
||||||
const nextOffset = this.offset + 10;
|
const nextOffset = this.offset + 10;
|
||||||
return Boolean(this.filtered.slice(nextOffset, this.limit + nextOffset).length);
|
return Boolean(
|
||||||
|
this.filtered.slice(nextOffset, this.limit + nextOffset).length
|
||||||
|
);
|
||||||
},
|
},
|
||||||
hasPrevPage () {
|
hasPrevPage() {
|
||||||
const prevOffset = this.offset - 10;
|
const prevOffset = this.offset - 10;
|
||||||
return Boolean(this.filtered.slice(prevOffset, this.limit + prevOffset).length);
|
return Boolean(
|
||||||
}
|
this.filtered.slice(prevOffset, this.limit + prevOffset).length
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.pagination {
|
.pagination {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: .25rem .25rem 0;
|
margin: 0.25rem 0.25rem 0;
|
||||||
}
|
}
|
||||||
.pagination button {
|
.pagination button {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
.pagination button:hover {
|
.pagination button:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,28 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-select :options="countries" append-to-body :calculate-position="withPopper" />
|
<v-select
|
||||||
|
:options="countries"
|
||||||
|
append-to-body
|
||||||
|
:calculate-position="withPopper"
|
||||||
|
/>
|
||||||
|
|
||||||
<label for="position" style="display: block; margin: 1rem 0;">
|
<label for="position" style="display: block; margin: 1rem 0">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="position"
|
id="position"
|
||||||
v-model="placement"
|
v-model="placement"
|
||||||
true-value="top"
|
true-value="top"
|
||||||
false-value="bottom"
|
false-value="bottom"
|
||||||
>
|
/>
|
||||||
Position dropdown above
|
Position dropdown above
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countries from '../data/countries.js'
|
import countries from "../assets/data/countries.js";
|
||||||
import { createPopper } from '@popperjs/core';
|
import { createPopper } from "@popperjs/core";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data: () => ({countries, placement: 'top'}),
|
data: () => ({ countries, placement: "top" }),
|
||||||
methods: {
|
methods: {
|
||||||
withPopper (dropdownList, component, {width}) {
|
withPopper(dropdownList, component, { width }) {
|
||||||
/**
|
/**
|
||||||
* We need to explicitly define the dropdown width since
|
* We need to explicitly define the dropdown width since
|
||||||
* it is usually inherited from the parent with CSS.
|
* it is usually inherited from the parent with CSS.
|
||||||
@@ -43,18 +47,23 @@ export default {
|
|||||||
placement: this.placement,
|
placement: this.placement,
|
||||||
modifiers: [
|
modifiers: [
|
||||||
{
|
{
|
||||||
name: 'offset', options: {
|
name: "offset",
|
||||||
offset: [0, -1]
|
options: {
|
||||||
}
|
offset: [0, -1],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'toggleClass',
|
name: "toggleClass",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
phase: 'write',
|
phase: "write",
|
||||||
fn ({state}) {
|
fn({ state }) {
|
||||||
component.$el.classList.toggle('drop-up', state.placement === 'top')
|
component.$el.classList.toggle(
|
||||||
|
"drop-up",
|
||||||
|
state.placement === "top"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
}]
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,22 +71,22 @@ export default {
|
|||||||
* If you return function, it will be called just before dropdown is removed from DOM.
|
* If you return function, it will be called just before dropdown is removed from DOM.
|
||||||
*/
|
*/
|
||||||
return () => popper.destroy();
|
return () => popper.destroy();
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.v-select.drop-up.vs--open .vs__dropdown-toggle {
|
.v-select.drop-up.vs--open .vs__dropdown-toggle {
|
||||||
border-radius: 0 0 4px 4px;
|
border-radius: 0 0 4px 4px;
|
||||||
border-top-color: transparent;
|
border-top-color: transparent;
|
||||||
border-bottom-color: rgba(60, 60, 60, 0.26);
|
border-bottom-color: rgba(60, 60, 60, 0.26);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-popper-placement='top'] {
|
[data-popper-placement="top"] {
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: 4px 4px 0 0;
|
||||||
border-top-style: solid;
|
border-top-style: solid;
|
||||||
border-bottom-style: none;
|
border-bottom-style: none;
|
||||||
box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.15)
|
box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
+191
-92
@@ -1,49 +1,85 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="sandbox-wrap">
|
<div id="sandbox-wrap">
|
||||||
<div id="config">
|
<div id="config">
|
||||||
|
|
||||||
<div class="list-item" v-if="!hideHelp">
|
<div class="list-item" v-if="!hideHelp">
|
||||||
<p>Use the controls below to adjust the props used
|
<p>
|
||||||
by the vue-select components.</p>
|
Use the controls below to adjust the props used by the vue-select
|
||||||
<p>The API provides
|
components.
|
||||||
more props than are shown here, these are some
|
</p>
|
||||||
commonly adjusted settings.</p>
|
<p>
|
||||||
|
The API provides more props than are shown here, these are some
|
||||||
|
commonly adjusted settings.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h5 class="list-item">Basic Features</h5>
|
<h5 class="list-item">Basic Features</h5>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="multiple">
|
<label for="multiple">
|
||||||
<input id="multiple" type="checkbox" v-model="configuration.multiple">
|
<input
|
||||||
<code>:multiple="{{ configuration.multiple ? 'true' : 'false' }}"</code>
|
id="multiple"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.multiple"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:multiple="{{ configuration.multiple ? "true" : "false" }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="disabled">
|
<label for="disabled">
|
||||||
<input id="disabled" type="checkbox" v-model="configuration.disabled">
|
<input
|
||||||
<code>:disabled="{{ configuration.disabled ? 'true' : 'false' }}"</code>
|
id="disabled"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.disabled"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:disabled="{{ configuration.disabled ? "true" : "false" }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="clearable">
|
<label for="clearable">
|
||||||
<input id="clearable" type="checkbox" v-model="configuration.clearable">
|
<input
|
||||||
<code>:clearable="{{ configuration.clearable ? 'true' : 'false' }}"</code>
|
id="clearable"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.clearable"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:clearable="{{ configuration.clearable ? "true" : "false" }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="searchable">
|
<label for="searchable">
|
||||||
<input id="searchable" type="checkbox" v-model="configuration.searchable">
|
<input
|
||||||
<code>:searchable="{{ configuration.searchable ? 'true' : 'false' }}"</code>
|
id="searchable"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.searchable"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:searchable="{{
|
||||||
|
configuration.searchable ? "true" : "false"
|
||||||
|
}}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="filterable">
|
<label for="filterable">
|
||||||
<input id="filterable" type="checkbox" v-model="configuration.filterable">
|
<input
|
||||||
<code>:filterable="{{ configuration.searchable ? 'true' : 'false' }}"</code>
|
id="filterable"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.filterable"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:filterable="{{
|
||||||
|
configuration.searchable ? "true" : "false"
|
||||||
|
}}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -51,22 +87,34 @@
|
|||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="taggable">
|
<label for="taggable">
|
||||||
<input id="taggable" type="checkbox" v-model="configuration.taggable">
|
<input
|
||||||
<code>:taggable="{{ configuration.taggable ? 'true' : 'false' }}"</code>
|
id="taggable"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.taggable"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:taggable="{{ configuration.taggable ? "true" : "false" }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="noDrop">
|
<label for="noDrop">
|
||||||
<input id="noDrop" type="checkbox" v-model="configuration.noDrop">
|
<input id="noDrop" type="checkbox" v-model="configuration.noDrop" />
|
||||||
<code>:no-drop="{{ configuration.noDrop ? 'true' : 'false' }}"</code>
|
<code>:no-drop="{{ configuration.noDrop ? "true" : "false" }}"</code>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="pushTags">
|
<label for="pushTags">
|
||||||
<input id="pushTags" type="checkbox" v-model="configuration.pushTags">
|
<input
|
||||||
<code>:push-tags="{{ configuration.pushTags ? 'true' : 'false' }}"</code>
|
id="pushTags"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.pushTags"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:push-tags="{{ configuration.pushTags ? "true" : "false" }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -74,15 +122,31 @@
|
|||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="selectOnTab">
|
<label for="selectOnTab">
|
||||||
<input id="selectOnTab" type="checkbox" v-model="configuration.selectOnTab">
|
<input
|
||||||
<code>:select-on-tab="{{ configuration.selectOnTab ? 'true' : 'false' }}"</code>
|
id="selectOnTab"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.selectOnTab"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:select-on-tab="{{
|
||||||
|
configuration.selectOnTab ? "true" : "false"
|
||||||
|
}}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="closeOnSelect">
|
<label for="closeOnSelect">
|
||||||
<input id="closeOnSelect" type="checkbox" v-model="configuration.closeOnSelect">
|
<input
|
||||||
<code>:close-on-select="{{ configuration.closeOnSelect ? 'true' : 'false' }}"</code>
|
id="closeOnSelect"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="configuration.closeOnSelect"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:close-on-select="{{
|
||||||
|
configuration.closeOnSelect ? "true" : "false"
|
||||||
|
}}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -90,11 +154,21 @@
|
|||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="rtl">
|
<label for="rtl">
|
||||||
<input id="rtl" type="radio" v-model="configuration.dir" value="rtl">
|
<input
|
||||||
|
id="rtl"
|
||||||
|
type="radio"
|
||||||
|
v-model="configuration.dir"
|
||||||
|
value="rtl"
|
||||||
|
/>
|
||||||
<code>dir="rtl"</code>
|
<code>dir="rtl"</code>
|
||||||
</label>
|
</label>
|
||||||
<label for="ltr">
|
<label for="ltr">
|
||||||
<input id="ltr" type="radio" v-model="configuration.dir" value="ltr">
|
<input
|
||||||
|
id="ltr"
|
||||||
|
type="radio"
|
||||||
|
v-model="configuration.dir"
|
||||||
|
value="ltr"
|
||||||
|
/>
|
||||||
<code>dir="ltr"</code>
|
<code>dir="ltr"</code>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,11 +177,17 @@
|
|||||||
<div id="sandbox">
|
<div id="sandbox">
|
||||||
<slot v-bind="configuration">
|
<slot v-bind="configuration">
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" placeholder="country objects"></v-select>
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
placeholder="country objects"
|
||||||
|
></v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" placeholder="country objects, using option scoped slots">
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
placeholder="country objects, using option scoped slots"
|
||||||
|
>
|
||||||
<template slot="selected-option" slot-scope="{ label, value }">
|
<template slot="selected-option" slot-scope="{ label, value }">
|
||||||
{{ label }} -- {{ value }}
|
{{ label }} -- {{ value }}
|
||||||
</template>
|
</template>
|
||||||
@@ -118,7 +198,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" :options="['cat', 'dog', 'bear']" placeholder="string options, option slots">
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
:options="['cat', 'dog', 'bear']"
|
||||||
|
placeholder="string options, option slots"
|
||||||
|
>
|
||||||
<template slot="selected-option" slot-scope="{ label }">
|
<template slot="selected-option" slot-scope="{ label }">
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</template>
|
</template>
|
||||||
@@ -129,32 +213,48 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" :options="[1,5,10]" placeholder="options=[1,5,10]"></v-select>
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
:options="[1, 5, 10]"
|
||||||
|
placeholder="options=[1,5,10]"
|
||||||
|
></v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" label="title" :options="optionDataSets.books" :filter="fuseSearch"
|
<v-select
|
||||||
placeholder="advanced filtering w/ fuse.js + scoped slots">
|
v-bind="configuration"
|
||||||
|
label="title"
|
||||||
|
:options="optionDataSets.books"
|
||||||
|
:filter="fuseSearch"
|
||||||
|
placeholder="advanced filtering w/ fuse.js + scoped slots"
|
||||||
|
>
|
||||||
<template slot="option" slot-scope="option">
|
<template slot="option" slot-scope="option">
|
||||||
<strong>{{ option.title }}</strong><br>
|
<strong>{{ option.title }}</strong
|
||||||
<em>{{ `${option.author.firstName} ${option.author.lastName}` }}</em>
|
><br />
|
||||||
|
<em>{{
|
||||||
|
`${option.author.firstName} ${option.author.lastName}`
|
||||||
|
}}</em>
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select
|
<v-select
|
||||||
v-bind="configuration"
|
v-bind="configuration"
|
||||||
placeholder="search github repositories.."
|
placeholder="search github repositories.."
|
||||||
label="full_name"
|
label="full_name"
|
||||||
@search="search"
|
@search="search"
|
||||||
:options="ajaxRes"
|
:options="ajaxRes"
|
||||||
>
|
>
|
||||||
</v-select>
|
</v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" :options="[]" placeholder="options=[]"></v-select>
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
:options="[]"
|
||||||
|
placeholder="options=[]"
|
||||||
|
></v-select>
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -162,16 +262,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Fuse from 'fuse.js';
|
import Fuse from "fuse.js";
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from "lodash/debounce";
|
||||||
import vSelect from '../../src/components/Select.vue';
|
import vSelect from "../../src/components/Select.vue";
|
||||||
import countries from '../data/countryCodes.js';
|
import countries from "../assets/data/countryCodes.js";
|
||||||
import books from '../data/books.js';
|
import books from "../assets/data/books.js";
|
||||||
|
|
||||||
const defaultConfig = () => ({
|
const defaultConfig = () => ({
|
||||||
options: countries,
|
options: countries,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
dir: 'ltr',
|
dir: "ltr",
|
||||||
clearable: true,
|
clearable: true,
|
||||||
searchable: true,
|
searchable: true,
|
||||||
filterable: true,
|
filterable: true,
|
||||||
@@ -179,7 +279,7 @@ const defaultConfig = () => ({
|
|||||||
closeOnSelect: true,
|
closeOnSelect: true,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
selectOntab: false,
|
selectOntab: false,
|
||||||
placeholder: 'Select a Country...',
|
placeholder: "Select a Country...",
|
||||||
});
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -189,14 +289,14 @@ export default {
|
|||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {vSelect},
|
components: { vSelect },
|
||||||
data () {
|
data() {
|
||||||
return {
|
return {
|
||||||
configuration: defaultConfig(),
|
configuration: defaultConfig(),
|
||||||
value: null,
|
value: null,
|
||||||
ajaxRes: [],
|
ajaxRes: [],
|
||||||
people: [],
|
people: [],
|
||||||
optionDataSet: 'countries',
|
optionDataSet: "countries",
|
||||||
optionDataSets: {
|
optionDataSets: {
|
||||||
countries,
|
countries,
|
||||||
books,
|
books,
|
||||||
@@ -204,16 +304,16 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
search (search, loading) {
|
search(search, loading) {
|
||||||
loading(true);
|
loading(true);
|
||||||
this.getRepositories(search, loading, this);
|
this.getRepositories(search, loading, this);
|
||||||
},
|
},
|
||||||
searchPeople (search, loading) {
|
searchPeople(search, loading) {
|
||||||
loading(true);
|
loading(true);
|
||||||
this.getPeople(loading, this);
|
this.getPeople(loading, this);
|
||||||
},
|
},
|
||||||
getPeople: debounce((loading, vm) => {
|
getPeople: debounce((loading, vm) => {
|
||||||
vm.$http.get(`https://reqres.in/api/users?per_page=10`).then(res => {
|
vm.$http.get(`https://reqres.in/api/users?per_page=10`).then((res) => {
|
||||||
vm.people = res.data.data;
|
vm.people = res.data.data;
|
||||||
loading(false);
|
loading(false);
|
||||||
});
|
});
|
||||||
@@ -221,7 +321,7 @@ export default {
|
|||||||
getRepositories: debounce((search, loading, vm) => {
|
getRepositories: debounce((search, loading, vm) => {
|
||||||
vm.$http
|
vm.$http
|
||||||
.get(`https://api.github.com/search/repositories?q=${search}`)
|
.get(`https://api.github.com/search/repositories?q=${search}`)
|
||||||
.then(res => {
|
.then((res) => {
|
||||||
vm.ajaxRes = res.data.items;
|
vm.ajaxRes = res.data.items;
|
||||||
loading(false);
|
loading(false);
|
||||||
});
|
});
|
||||||
@@ -231,46 +331,45 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#sandbox-wrap {
|
#sandbox-wrap {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto 75%;
|
grid-template-columns: auto 75%;
|
||||||
grid-template-rows: auto;
|
grid-template-rows: auto;
|
||||||
grid-template-areas:
|
grid-template-areas: "sidebar component";
|
||||||
"sidebar component"
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#config {
|
#config {
|
||||||
grid-area: sidebar;
|
grid-area: sidebar;
|
||||||
border-right: 1px solid #eaecef;
|
border-right: 1px solid #eaecef;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sandbox {
|
#sandbox {
|
||||||
grid-area: component;
|
grid-area: component;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item {
|
.list-item {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding: 1rem 1rem 0;
|
padding: 1rem 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item:not(:first-child) {
|
.list-item:not(:first-child) {
|
||||||
border-top: 1px solid #eaecef;
|
border-top: 1px solid #eaecef;
|
||||||
}
|
}
|
||||||
|
|
||||||
.example {
|
.example {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-select {
|
.v-select {
|
||||||
width: 25em;
|
width: 25em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
placeholder="Choose a book to read"
|
placeholder="Choose a book to read"
|
||||||
label="title"
|
label="title"
|
||||||
:options="books"
|
:options="books"
|
||||||
:selectable="option => ! option.author.lastName.includes('Woodhouse')"
|
:selectable="(option) => !option.author.lastName.includes('Woodhouse')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import books from '../data/books.js';
|
import books from "../assets/data/books.js";
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
books: () => books,
|
books: () => books,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.stop="onSubmit">
|
<form @submit.stop="onSubmit">
|
||||||
<v-select :options="books" label="title" v-model="selected">
|
<v-select :options="books" label="title" v-model="selected">
|
||||||
<template #search="{attributes, events}">
|
<template #search="{ attributes, events }">
|
||||||
<input
|
<input
|
||||||
:required="!selected"
|
:required="!selected"
|
||||||
class="vs__search"
|
class="vs__search"
|
||||||
@@ -11,12 +11,12 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
|
|
||||||
<input type="submit">
|
<input type="submit" />
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import books from '../data/books.js'
|
import books from "../assets/data/books.js";
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
books,
|
books,
|
||||||
@@ -24,28 +24,28 @@ export default {
|
|||||||
}),
|
}),
|
||||||
methods: {
|
methods: {
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
alert('Submitted!');
|
alert("Submitted!");
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
form {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-select {
|
.v-select {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="submit"] {
|
input[type="submit"] {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
background: #44ae7d;
|
background: #44ae7d;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<a :href="href" class="flex items-center">
|
||||||
|
<slot></slot>
|
||||||
|
<img
|
||||||
|
src="~assets/svg/ExternalLink.svg?data"
|
||||||
|
aria-hidden="true"
|
||||||
|
class="w-5 h-5 opacity-50"
|
||||||
|
alt="External Link Icon"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "ExternalLink",
|
||||||
|
props: {
|
||||||
|
href: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -1 +1,35 @@
|
|||||||
<template></template>
|
<template>
|
||||||
|
<div>
|
||||||
|
<header>
|
||||||
|
<nav class="flex justify-between items-center px-5">
|
||||||
|
<h1 class="font-bold text-xl text-gray-800">Vue Select</h1>
|
||||||
|
|
||||||
|
<ContentSearch />
|
||||||
|
|
||||||
|
<ul class="flex items-center space-x-4">
|
||||||
|
<li>
|
||||||
|
<NuxtLink to="/sandbox">Sandbox</NuxtLink>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<ExternalLink href="https://github.com/sagalbot/vue-select">
|
||||||
|
GitHub
|
||||||
|
</ExternalLink>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<nav></nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ContentSearch from "~/components/ContentSearch.vue";
|
||||||
|
import ExternalLink from "~/layouts/ExternalLink.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { ExternalLink, ContentSearch },
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|||||||
+8
-2
@@ -1,4 +1,10 @@
|
|||||||
export default {
|
import { resolve } from "path";
|
||||||
|
import theme from "@nuxt/content-theme-docs";
|
||||||
|
|
||||||
|
export default theme({
|
||||||
env: {},
|
env: {},
|
||||||
|
alias: {
|
||||||
|
svg: resolve(__dirname, "./assets/svg"),
|
||||||
|
},
|
||||||
buildModules: ["@nuxtjs/tailwindcss"],
|
buildModules: ["@nuxtjs/tailwindcss"],
|
||||||
};
|
});
|
||||||
|
|||||||
+3
-1
@@ -10,9 +10,12 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/content": "^1.14.0",
|
"@nuxt/content": "^1.14.0",
|
||||||
|
"@nuxt/content-theme-docs": "^0.10.2",
|
||||||
|
"@nuxtjs/svg": "^0.1.12",
|
||||||
"@nuxtjs/tailwindcss": "^4.2.1",
|
"@nuxtjs/tailwindcss": "^4.2.1",
|
||||||
"@octokit/graphql": "^4.6.4",
|
"@octokit/graphql": "^4.6.4",
|
||||||
"@popperjs/core": "^2.9.2",
|
"@popperjs/core": "^2.9.2",
|
||||||
|
"@tailwindcss/forms": "^0.3.3",
|
||||||
"autoprefixer": "^10.3.1",
|
"autoprefixer": "^10.3.1",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"date-fns": "^2.23.0",
|
"date-fns": "^2.23.0",
|
||||||
@@ -21,7 +24,6 @@
|
|||||||
"octonode": "^0.10.2",
|
"octonode": "^0.10.2",
|
||||||
"postcss": "^8.3.6",
|
"postcss": "^8.3.6",
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
"tailwindcss": "^2.2.7",
|
|
||||||
"vuex": "^3.6.2"
|
"vuex": "^3.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ module.exports = {
|
|||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [require("@tailwindcss/forms")],
|
||||||
};
|
};
|
||||||
|
|||||||
+746
-19
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user