2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-19 09:50:33 +03:00
This commit is contained in:
Jeff Sagal
2021-07-28 15:56:54 -07:00
parent 3399ecbd9a
commit ae2eb99f86
22 changed files with 1196 additions and 234 deletions
+2 -2
View File
@@ -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 },
+4
View File
@@ -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

+45
View File
@@ -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 -5
View File
@@ -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>
+10 -6
View File
@@ -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>
+19 -19
View File
@@ -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>
+4 -4
View File
@@ -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>
+11 -8
View File
@@ -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>
+29 -21
View File
@@ -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>
+37 -28
View File
@@ -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
View File
@@ -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>
+4 -4
View File
@@ -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>
+21 -21
View File
@@ -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>
+23
View File
@@ -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>
+35 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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"
} }
} }
+1 -1
View File
@@ -11,5 +11,5 @@ module.exports = {
theme: { theme: {
extend: {}, extend: {},
}, },
plugins: [], plugins: [require("@tailwindcss/forms")],
}; };
+746 -19
View File
File diff suppressed because it is too large Load Diff