2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-16 09:10:33 +03:00

nuxt setup, tailwind

This commit is contained in:
Jeff Sagal
2021-07-28 09:46:15 -07:00
parent 335920b586
commit 3399ecbd9a
86 changed files with 5656 additions and 4359 deletions
+16
View File
@@ -0,0 +1,16 @@
<template>
<v-select>
<template v-slot:no-options="{ search, searching }">
<template v-if="searching">
No results found for <em>{{ search }}</em>.
</template>
<em style="opacity: 0.5;" v-else>Start typing to search for a country.</em>
</template>
</v-select>
</template>
<script>
export default {
name: 'BetterNoOptions',
};
</script>
+21
View File
@@ -0,0 +1,21 @@
<template>
<div>
<v-select
placeholder="choose a country"
v-model="selected"
:components="{Deselect}"
:options="['Canada', 'United States']"
/>
</div>
</template>
<script>
export default {
data: () => ({
selected: 'Canada',
Deselect: {
render: createElement => createElement('span', '❌'),
},
}),
};
</script>
+28
View File
@@ -0,0 +1,28 @@
<template>
<p :data-height="height"
data-theme-id="32252"
:data-slug-hash="url"
data-default-tab="result"
data-user="sagalbot"
class="codepen">
</p>
</template>
<script>
import mountCodePen from '../utils/codePen.js';
export default {
props: {
url: {
type: String,
required: true,
},
height: {
default: 250
}
},
mounted () {
mountCodePen();
},
};
</script>
+63
View File
@@ -0,0 +1,63 @@
<template>
<ul>
<li v-for="{ login, avatar_url, html_url, contributions } in contributors">
<img :src="`${avatar_url}&s=75`" :alt="`${login}'s Avatar`" />
<div>
<a :href="html_url">@{{ login }}</a>
<br /><a
class="contributions-link"
:href="
`https://github.com/sagalbot/vue-select/commits?author=${login}`
"
>{{ contributions }} contributions</a
>
</div>
</li>
</ul>
</template>
<script>
import { CONTRIBUTORS } from "@dynamic/constants";
export default {
data: () => ({
contributors: CONTRIBUTORS.filter(
({ login }) => login !== "semantic-release-bot"
)
})
};
</script>
<style scoped>
ul {
list-style: none;
padding: 0;
max-width: 100%;
margin-top: 2rem;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
img {
width: 75px;
height: 75px;
margin-right: 1rem;
border-radius: 100%;
}
li {
display: inline-flex;
align-items: center;
margin-bottom: 2rem;
margin-right: 1rem;
}
a {
display: inline-block;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.contributions-link {
color: #2c5282;
}
</style>
+18
View File
@@ -0,0 +1,18 @@
<template>
<v-select :options="options"></v-select>
</template>
<script>
import countryCodes from '../data/countryCodes.js';
export default {
name: 'CountrySelect',
data: () => ({
options: countryCodes,
}),
};
</script>
<style scoped>
</style>
+26
View File
@@ -0,0 +1,26 @@
<template>
<div>
<v-select
class="style-chooser"
placeholder="Choose a Styling Option"
:options="['Components', 'CSS / Variables', 'Slots']"
/>
</div>
</template>
<style>
.style-chooser .vs__search::placeholder,
.style-chooser .vs__dropdown-toggle,
.style-chooser .vs__dropdown-menu {
background: #dfe5fb;
border: none;
color: #394066;
text-transform: lowercase;
font-variant: small-caps;
}
.style-chooser .vs__clear,
.style-chooser .vs__open-indicator {
fill: #394066;
}
</style>
@@ -0,0 +1,19 @@
<template>
<v-select
:options="['Vue.js', 'React', 'Angular']"
:components="{Deselect, OpenIndicator}"
/>
</template>
<script>
export default {
data: () => ({
Deselect: {
render: createElement => createElement('span', '❌'),
},
OpenIndicator: {
render: createElement => createElement('span', '🔽'),
},
}),
};
</script>
+25
View File
@@ -0,0 +1,25 @@
<template>
<v-select
taggable
multiple
no-drop
:map-keydown="handlers"
placeholder="enter an email"
/>
</template>
<script>
export default {
name: 'CustomHandlers',
methods: {
handlers: (map, vm) => ({
...map, 50: e => {
e.preventDefault();
if( e.key === '@' && vm.search.length > 0 ) {
vm.search = `${vm.search}@gmail.com`;
}
},
}),
},
};
</script>
+31
View File
@@ -0,0 +1,31 @@
<template>
<v-select :filter="fuseSearch" :options="books" :getOptionLabel="option => option.title">
<template #option="{ author, title }">
{{ title }}
<br />
<cite>{{ author.firstName }} {{ author.lastName }}</cite>
</template>
</v-select>
</template>
<script>
import Fuse from "fuse.js";
import books from "../data/books.js";
export default {
computed: {
books: () => books
},
methods: {
fuseSearch(options, search) {
const fuse = new Fuse(options, {
keys: ["title", "author.firstName", "author.lastName"],
shouldSort: true
});
return search.length
? fuse.search(search).map(({ item }) => item)
: fuse.list;
}
}
};
</script>
+74
View File
@@ -0,0 +1,74 @@
<template>
<v-select
:options="paginated"
:filterable="false"
@open="onOpen"
@close="onClose"
@search="query => search = query"
>
<template #list-footer>
<li ref="load" class="loader" v-show="hasNextPage">
Loading more options...
</li>
</template>
</v-select>
</template>
<script>
import countries from '../data/countries.js';
export default {
name: "InfiniteScroll",
data: () => ({
observer: null,
limit: 10,
search: ''
}),
mounted () {
/**
* You could do this directly in data(), but since these docs
* are server side rendered, IntersectionObserver doesn't exist
* in that environment, so we need to do it in mounted() instead.
*/
this.observer = new IntersectionObserver(this.infiniteScroll);
},
computed: {
filtered () {
return countries.filter(country => country.includes(this.search));
},
paginated () {
return this.filtered.slice(0, this.limit);
},
hasNextPage () {
return this.paginated.length < this.filtered.length;
},
},
methods: {
async onOpen () {
if (this.hasNextPage) {
await this.$nextTick();
this.observer.observe(this.$refs.load)
}
},
onClose () {
this.observer.disconnect();
},
async infiniteScroll ([{isIntersecting, target}]) {
if (isIntersecting) {
const ul = target.offsetParent;
const scrollTop = target.offsetParent.scrollTop;
this.limit += 10;
await this.$nextTick();
ul.scrollTop = scrollTop;
}
}
}
}
</script>
<style scoped>
.loader {
text-align: center;
color: #bbbbbb;
}
</style>
@@ -0,0 +1,21 @@
<template>
<v-select
multiple
placeholder="Choose up to 3 books!"
label="title"
v-model="selected"
:options="books"
:selectable="() => selected.length < 3"
/>
</template>
<script>
import books from '../data/books.js';
export default {
data() {
return { selected: [] }
},
computed: {
books: () => books,
}
}
</script>
+43
View File
@@ -0,0 +1,43 @@
<template>
<table>
<tr>
<th>Name</th>
<th>Country</th>
</tr>
<tr v-for="person in people">
<td>{{ person.name }}</td>
<td>
<v-select
:options="options"
:value="person.country"
@input="country => updateCountry(person, country)"
/>
</td>
</tr>
</table>
</template>
<script>
import countries from '../data/countries.js';
export default {
data: () => ({
people: [{name: 'John', country: ''}, {name: 'Jane', country: ''}],
}),
methods: {
updateCountry (person, country) {
person.country = country;
},
},
computed: {
options: () => countries,
},
};
</script>
<style scoped>
table {
display: table;
width: 100%;
}
</style>
@@ -0,0 +1,21 @@
<template>
<div>
<v-select
multiple
v-model="selected"
:options="['Canada', 'United States']"
:components="{Deselect}"
/>
</div>
</template>
<script>
export default {
data: () => ({
selected: ['Canada'],
Deselect: {
render: createElement => createElement('span', '❌'),
},
}),
};
</script>
+18
View File
@@ -0,0 +1,18 @@
<template>
<div>
<v-select
:options="['Canada', 'United States']"
:components="{OpenIndicator}"
/>
</div>
</template>
<script>
export default {
data: () => ({
OpenIndicator: {
render: createElement => createElement('span', '🔽'),
},
}),
};
</script>
+49
View File
@@ -0,0 +1,49 @@
<template>
<v-select :options="paginated" @search="query => search = query" :filterable="false">
<li slot="list-footer" class="pagination">
<button @click="offset -= 10" :disabled="!hasPrevPage">Prev</button>
<button @click="offset += 10" :disabled="!hasNextPage">Next</button>
</li>
</v-select>
</template>
<script>
import countries from '../data/countries.js';
export default {
data: () => ({
countries,
search: '',
offset: 0,
limit: 10,
}),
computed: {
filtered () {
return this.countries.filter(country => country.includes(this.search));
},
paginated () {
return this.filtered.slice(this.offset, this.limit + this.offset);
},
hasNextPage () {
const nextOffset = this.offset + 10;
return Boolean(this.filtered.slice(nextOffset, this.limit + nextOffset).length);
},
hasPrevPage () {
const prevOffset = this.offset - 10;
return Boolean(this.filtered.slice(prevOffset, this.limit + prevOffset).length);
}
},
};
</script>
<style scoped>
.pagination {
display: flex;
margin: .25rem .25rem 0;
}
.pagination button {
flex-grow: 1;
}
.pagination button:hover {
cursor: pointer;
}
</style>
+83
View File
@@ -0,0 +1,83 @@
<template>
<div>
<v-select :options="countries" append-to-body :calculate-position="withPopper" />
<label for="position" style="display: block; margin: 1rem 0;">
<input
type="checkbox"
id="position"
v-model="placement"
true-value="top"
false-value="bottom"
>
Position dropdown above
</label>
</div>
</template>
<script>
import countries from '../data/countries.js'
import { createPopper } from '@popperjs/core';
export default {
data: () => ({countries, placement: 'top'}),
methods: {
withPopper (dropdownList, component, {width}) {
/**
* We need to explicitly define the dropdown width since
* it is usually inherited from the parent with CSS.
*/
dropdownList.style.width = width;
/**
* Here we position the dropdownList relative to the $refs.toggle Element.
*
* The 'offset' modifier aligns the dropdown so that the $refs.toggle and
* the dropdownList overlap by 1 pixel.
*
* The 'toggleClass' modifier adds a 'drop-up' class to the Vue Select
* wrapper so that we can set some styles for when the dropdown is placed
* above.
*/
const popper = createPopper(component.$refs.toggle, dropdownList, {
placement: this.placement,
modifiers: [
{
name: 'offset', options: {
offset: [0, -1]
}
},
{
name: 'toggleClass',
enabled: true,
phase: 'write',
fn ({state}) {
component.$el.classList.toggle('drop-up', state.placement === 'top')
},
}]
});
/**
* To prevent memory leaks Popper needs to be destroyed.
* If you return function, it will be called just before dropdown is removed from DOM.
*/
return () => popper.destroy();
}
}
};
</script>
<style>
.v-select.drop-up.vs--open .vs__dropdown-toggle {
border-radius: 0 0 4px 4px;
border-top-color: transparent;
border-bottom-color: rgba(60, 60, 60, 0.26);
}
[data-popper-placement='top'] {
border-radius: 4px 4px 0 0;
border-top-style: solid;
border-bottom-style: none;
box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.15)
}
</style>
+60
View File
@@ -0,0 +1,60 @@
<template>
<div class="flex">
<div>
<v-select
label="country"
v-model="selected"
:reduce="opt => opt.meta.id"
:options="options"
/>
</div>
<div>
<pre><code>v-model value: {{ selected || 'null' }}</code></pre>
</div>
</div>
</template>
<script>
export default {
name: 'ReducerNestedValue',
data: () => ({
selected: null,
options: [
{
country: 'canada',
meta: {
id: '1',
code: 'ca',
},
}],
}),
};
</script>
<style scoped>
.flex {
margin-bottom: 2rem;
border: 1px solid #eaecef;
/*padding: 1rem;*/
display: flex;
justify-content: center;
align-items: center;
}
.flex > div {
flex-grow: 1;
width: 50%;
padding: 0 1rem;
}
pre {
margin: 0;
background: #fff;
}
code {
color: #635762 !important;
color: #5b2d2d !important;
/*color: #7ec699 !important;*/
}
</style>
+276
View File
@@ -0,0 +1,276 @@
<template>
<div id="sandbox-wrap">
<div id="config">
<div class="list-item" v-if="!hideHelp">
<p>Use the controls below to adjust the props used
by the vue-select components.</p>
<p>The API provides
more props than are shown here, these are some
commonly adjusted settings.</p>
</div>
<h5 class="list-item">Basic Features</h5>
<div class="list-item">
<label for="multiple">
<input id="multiple" type="checkbox" v-model="configuration.multiple">
<code>:multiple="{{ configuration.multiple ? 'true' : 'false' }}"</code>
</label>
</div>
<div class="list-item">
<label for="disabled">
<input id="disabled" type="checkbox" v-model="configuration.disabled">
<code>:disabled="{{ configuration.disabled ? 'true' : 'false' }}"</code>
</label>
</div>
<div class="list-item">
<label for="clearable">
<input id="clearable" type="checkbox" v-model="configuration.clearable">
<code>:clearable="{{ configuration.clearable ? 'true' : 'false' }}"</code>
</label>
</div>
<div class="list-item">
<label for="searchable">
<input id="searchable" type="checkbox" v-model="configuration.searchable">
<code>:searchable="{{ configuration.searchable ? 'true' : 'false' }}"</code>
</label>
</div>
<div class="list-item">
<label for="filterable">
<input id="filterable" type="checkbox" v-model="configuration.filterable">
<code>:filterable="{{ configuration.searchable ? 'true' : 'false' }}"</code>
</label>
</div>
<h5 class="list-item">Tagging</h5>
<div class="list-item">
<label for="taggable">
<input id="taggable" type="checkbox" v-model="configuration.taggable">
<code>:taggable="{{ configuration.taggable ? 'true' : 'false' }}"</code>
</label>
</div>
<div class="list-item">
<label for="noDrop">
<input id="noDrop" type="checkbox" v-model="configuration.noDrop">
<code>:no-drop="{{ configuration.noDrop ? 'true' : 'false' }}"</code>
</label>
</div>
<div class="list-item">
<label for="pushTags">
<input id="pushTags" type="checkbox" v-model="configuration.pushTags">
<code>:push-tags="{{ configuration.pushTags ? 'true' : 'false' }}"</code>
</label>
</div>
<h5 class="list-item">UX</h5>
<div class="list-item">
<label for="selectOnTab">
<input id="selectOnTab" type="checkbox" v-model="configuration.selectOnTab">
<code>:select-on-tab="{{ configuration.selectOnTab ? 'true' : 'false' }}"</code>
</label>
</div>
<div class="list-item">
<label for="closeOnSelect">
<input id="closeOnSelect" type="checkbox" v-model="configuration.closeOnSelect">
<code>:close-on-select="{{ configuration.closeOnSelect ? 'true' : 'false' }}"</code>
</label>
</div>
<h5 class="list-item">Localization / i18n</h5>
<div class="list-item">
<label for="rtl">
<input id="rtl" type="radio" v-model="configuration.dir" value="rtl">
<code>dir="rtl"</code>
</label>
<label for="ltr">
<input id="ltr" type="radio" v-model="configuration.dir" value="ltr">
<code>dir="ltr"</code>
</label>
</div>
</div>
<div id="sandbox">
<slot v-bind="configuration">
<div class="example">
<v-select v-bind="configuration" placeholder="country objects"></v-select>
</div>
<div class="example">
<v-select v-bind="configuration" placeholder="country objects, using option scoped slots">
<template slot="selected-option" slot-scope="{ label, value }">
{{ label }} -- {{ value }}
</template>
<template slot="option" slot-scope="{ label, value }">
{{ label }} ({{ value }})
</template>
</v-select>
</div>
<div class="example">
<v-select v-bind="configuration" :options="['cat', 'dog', 'bear']" placeholder="string options, option slots">
<template slot="selected-option" slot-scope="{ label }">
{{ label }}
</template>
<template slot="option" slot-scope="{ label }">
{{ label }}
</template>
</v-select>
</div>
<div class="example">
<v-select v-bind="configuration" :options="[1,5,10]" placeholder="options=[1,5,10]"></v-select>
</div>
<div class="example">
<v-select v-bind="configuration" label="title" :options="optionDataSets.books" :filter="fuseSearch"
placeholder="advanced filtering w/ fuse.js + scoped slots">
<template slot="option" slot-scope="option">
<strong>{{ option.title }}</strong><br>
<em>{{ `${option.author.firstName} ${option.author.lastName}` }}</em>
</template>
</v-select>
</div>
<div class="example">
<v-select
v-bind="configuration"
placeholder="search github repositories.."
label="full_name"
@search="search"
:options="ajaxRes"
>
</v-select>
</div>
<div class="example">
<v-select v-bind="configuration" :options="[]" placeholder="options=[]"></v-select>
</div>
</slot>
</div>
</div>
</template>
<script>
import Fuse from 'fuse.js';
import debounce from 'lodash/debounce';
import vSelect from '../../src/components/Select.vue';
import countries from '../data/countryCodes.js';
import books from '../data/books.js';
const defaultConfig = () => ({
options: countries,
multiple: false,
dir: 'ltr',
clearable: true,
searchable: true,
filterable: true,
noDrop: false,
closeOnSelect: true,
disabled: false,
selectOntab: false,
placeholder: 'Select a Country...',
});
export default {
props: {
hideHelp: {
type: Boolean,
default: false,
},
},
components: {vSelect},
data () {
return {
configuration: defaultConfig(),
value: null,
ajaxRes: [],
people: [],
optionDataSet: 'countries',
optionDataSets: {
countries,
books,
},
};
},
methods: {
search (search, loading) {
loading(true);
this.getRepositories(search, loading, this);
},
searchPeople (search, loading) {
loading(true);
this.getPeople(loading, this);
},
getPeople: debounce((loading, vm) => {
vm.$http.get(`https://reqres.in/api/users?per_page=10`).then(res => {
vm.people = res.data.data;
loading(false);
});
}, 250),
getRepositories: debounce((search, loading, vm) => {
vm.$http
.get(`https://api.github.com/search/repositories?q=${search}`)
.then(res => {
vm.ajaxRes = res.data.items;
loading(false);
});
}, 250),
},
};
</script>
<style scoped>
#sandbox-wrap {
min-height: 100%;
display: grid;
grid-template-columns: auto 75%;
grid-template-rows: auto;
grid-template-areas:
"sidebar component"
}
#config {
grid-area: sidebar;
border-right: 1px solid #eaecef;
display: flex;
flex-direction: column;
justify-content: center;
}
#sandbox {
grid-area: component;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.list-item {
margin-top: 0;
margin-bottom: 1rem;
padding: 1rem 1rem 0;
}
.list-item:not(:first-child) {
border-top: 1px solid #eaecef;
}
.example {
margin-bottom: 2rem;
}
.v-select {
width: 25em;
}
</style>
+7
View File
@@ -0,0 +1,7 @@
<template>
<v-select append-to-body>
<template #footer>
<div style="opacity: .8">Bottom of the component, in the footer slot!</div>
</template>
</v-select>
</template>
+7
View File
@@ -0,0 +1,7 @@
<template>
<v-select>
<template #header>
<div style="opacity: .8">Top of the component, in the header slot!</div>
</template>
</v-select>
</template>
+7
View File
@@ -0,0 +1,7 @@
<template>
<v-select>
<template #list-footer>
<li style="text-align: center">Bottom of the list!</li>
</template>
</v-select>
</template>
+7
View File
@@ -0,0 +1,7 @@
<template>
<v-select>
<template #list-header>
<li style="text-align: center">Top of the list!</li>
</template>
</v-select>
</template>
+7
View File
@@ -0,0 +1,7 @@
<template>
<v-select>
<template #no-options="{ search, searching, loading }">
This is the no options slot.
</template>
</v-select>
</template>
+7
View File
@@ -0,0 +1,7 @@
<template>
<v-select>
<template #open-indicator="{ attributes }">
<span v-bind="attributes">🔽</span>
</template>
</v-select>
</template>
+24
View File
@@ -0,0 +1,24 @@
<template>
<v-select :options="books" label="title">
<template #option="{ title, author }">
<h3 style="margin: 0">{{ title }}</h3>
<em>{{ author.firstName }} {{ author.lastName }}</em>
</template>
</v-select>
</template>
<script>
export default {
data: () => ({
books: [
{
title: "Old Man's War",
author: {
firstName: "John",
lastName: "Scalzi"
}
}
]
})
}
</script>
+12
View File
@@ -0,0 +1,12 @@
<template>
<v-select>
<template #search="{ attributes, events }">
<input
maxlength="1"
class="vs__search"
v-bind="attributes"
v-on="events"
>
</template>
</v-select>
</template>
+26
View File
@@ -0,0 +1,26 @@
<template>
<v-select v-model="selected" :options="books" label="title">
<template #selected-option="{ title, author }">
<div style="display: flex; align-items: baseline;">
<strong>{{ title }}</strong>
<em style="margin-left: .5rem;">by {{ author.firstName }} {{ author.lastName }}</em>
</div>
</template>
</v-select>
</template>
<script>
const book = {
title: "Old Man's War",
author: {
firstName: "John",
lastName: "Scalzi"
}
};
export default {
data: () => ({
books: [book],
selected: book
})
}
</script>
@@ -0,0 +1,23 @@
<template>
<v-select :options="books" label="title">
<template #selected-option-container="{ option, deselect, multiple, disabled }">
<div class="vs__selected">{{ option.title }}</div>
</template>
</v-select>
</template>
<script>
export default {
data: () => ({
books: [
{
title: "Old Man's War",
author: {
firstName: "John",
lastName: "Scalzi"
}
}
]
})
}
</script>
+9
View File
@@ -0,0 +1,9 @@
<template>
<v-select :loading="true">
<template #spinner="{ loading }">
<div v-if="loading" style="border-left-color: rgba(88,151,251,0.71)" class="vs__spinner">
The .vs__spinner class will hide the text for me.
</div>
</template>
</v-select>
</template>
+25
View File
@@ -0,0 +1,25 @@
<template>
<p class="sponsor">
Are you using Vue Select on a lot of projects? Please consider
<a href="https://github.com/sponsors/sagalbot" target="_blank">
sponsoring @sagalbot!
</a>
</p>
</template>
<style scoped>
.sponsor {
display: block;
border: 2px solid #e2e8f0;
background: #f7fafc;
border-radius: 10px;
padding: 0.25rem;
font-weight: 600;
text-align: center;
margin: 0 auto;
color: #8492a4;
}
p a {
color: #48BB78;
}
</style>
+146
View File
@@ -0,0 +1,146 @@
<template>
<div class="sponsor-me">
<div class="avatar">
<a href="https://github.com/sponsors/sagalbot">
<img
src="https://avatars2.githubusercontent.com/u/692538?s=400&u=a5ab0d164266bd2d59ce1a514835627b4cc4f24f&v=4"
alt="Jeff Sagal's Avatar"
/>
</a>
</div>
<div class="cta">
<p style="font-size: 1.2rem; font-weight: 600;">
Hi! I'm Jeff Sagal, the author of Vue Select.
</p>
<p>
I've spent hundreds of hours working alongside contributors to make Vue
Select the best it can be. I've researched UX and accessibility
patterns, squashed bugs, reviewed code, tested-cross browser, and spent
many evenings and weekends working on these docs.
</p>
<p>
If it's saved you time on your projects, please consider supporting me
on GitHub sponsors.
</p>
<div class="links">
<a
href="https://github.com/sponsors/sagalbot"
class="button"
target="_blank"
>
<svg viewBox="0 0 20 20">
<path
d="M10 0a10 10 0 00-3.16 19.49c.5.1.68-.22.68-.48l-.01-1.7c-2.78.6-3.37-1.34-3.37-1.34-.46-1.16-1.11-1.47-1.11-1.47-.9-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.9 1.52 2.34 1.08 2.91.83.1-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.94 0-1.1.39-1.99 1.03-2.69a3.6 3.6 0 01.1-2.64s.84-.27 2.75 1.02a9.58 9.58 0 015 0c1.91-1.3 2.75-1.02 2.75-1.02.55 1.37.2 2.4.1 2.64.64.7 1.03 1.6 1.03 2.69 0 3.84-2.34 4.68-4.57 4.93.36.31.68.92.68 1.85l-.01 2.75c0 .26.18.58.69.48A10 10 0 0010 0"
/>
</svg>
Sponsor Vue Select!
</a>
<a href="https://twitter.com/sagalbot" target="_blank" class="social-link">
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path
d="M23.954 4.569a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.691 8.094 4.066 6.13 1.64 3.161a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.061a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.937 4.937 0 004.604 3.417 9.868 9.868 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.054 0 13.999-7.496 13.999-13.986 0-.209 0-.42-.015-.63a9.936 9.936 0 002.46-2.548l-.047-.02z"
/>
</svg>
Follow @sagalbot
</a>
</div>
</div>
</div>
</template>
<style scoped>
.sponsor-me {
display: flex;
border: 2px solid #c3dafe;
background: #ebf4ff;
border-radius: 10px;
/*align-items: top;*/
padding: 2rem 1rem;
margin: 3rem 0;
flex-direction: column;
}
.avatar {
display: flex;
align-items: center;
justify-content: space-evenly;
padding: 1rem;
}
.cta {
/*text-align: center;*/
}
@media (min-width: 1150px) {
.sponsor-me {
flex-direction: row;
}
.avatar {
display: flex;
justify-content: flex-start;
flex-direction: column;
margin: 0 2rem;
}
.cta {
text-align: left;
}
}
p {
margin-top: 0;
}
.avatar img {
max-width: 150px;
border-radius: 100%;
}
.button {
display: inline-flex;
text-align: center;
align-items: center;
padding: 0.75rem 1rem;
background: #63b3ed;
color: #fff;
font-weight: 600;
border-radius: 5px;
margin-top: 0.5rem;
transition: background-color 0.25s, box-shadow 0.25s;
}
.button svg {
max-width: 25px;
fill: currentColor;
margin-right: 0.5rem;
}
a.button:hover {
box-shadow: inset 0px 0px 3px #3182ce;
background: #90cdf4;
text-decoration: none;
text-shadow: 0 1px 1px #63b3ed;
}
.links {
display: flex;
flex-direction: column;
align-items: center;
}
.links a {
margin: 1rem;
}
@media (min-width: 1150px) {
.links {
flex-direction: row;
justify-content: flex-start;
}
.links a {
margin: 0 2rem 0 0;
}
}
.social-link {
display: flex;
align-items: center;
color: #3182ce;
}
.social-link svg {
fill: currentColor;
width: 20px;
margin-right: 0.5rem;
}
.social-link:hover {
color: #2c5282;
text-decoration: none;
}
</style>
+56
View File
@@ -0,0 +1,56 @@
<template>
<ul>
<li v-for="{ createdAt, login, avatarUrl } in sponsors">
<img :src="avatarUrl + '&s=150'" :alt="`@${login}'s avatar`" />
<p>
<a :href="`https://github.com/${login}`">@{{ login }}</a> <br />
Sponsor since {{ createdAt }}
</p>
</li>
</ul>
</template>
<script>
import { SPONSORS } from "@dynamic/constants";
import { format } from "date-fns";
export default {
data: () => ({
sponsors: SPONSORS.map(({ createdAt, sponsorEntity }) => ({
createdAt: format(new Date(createdAt), "LLL yyyy"),
...sponsorEntity
}))
}),
};
</script>
<style scoped>
ul {
list-style: none;
padding: 0;
max-width: 100%;
margin-top: 2rem;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
img {
width: 75px;
height: 75px;
margin-right: 1rem;
border-radius: 100%;
}
li {
display: inline-flex;
align-items: center;
margin-bottom: 2rem;
/*max-width: 220px;*/
}
a {
display: inline-block;
max-width: 150px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
+4
View File
@@ -0,0 +1,4 @@
<template>
<!-- tag on 188/comma & 13/return -->
<v-select no-drop taggable multiple :select-on-key-codes="[188, 13]" />
</template>
+16
View File
@@ -0,0 +1,16 @@
<template>
<v-select
placeholder="Choose a book to read"
label="title"
:options="books"
:selectable="option => ! option.author.lastName.includes('Woodhouse')"
/>
</template>
<script>
import books from '../data/books.js';
export default {
computed: {
books: () => books,
}
}
</script>
+51
View File
@@ -0,0 +1,51 @@
<template>
<form @submit.stop="onSubmit">
<v-select :options="books" label="title" v-model="selected">
<template #search="{attributes, events}">
<input
:required="!selected"
class="vs__search"
v-bind="attributes"
v-on="events"
/>
</template>
</v-select>
<input type="submit">
</form>
</template>
<script>
import books from '../data/books.js'
export default {
data: () => ({
books,
selected: null,
}),
methods: {
onSubmit() {
alert('Submitted!');
}
}
};
</script>
<style scoped>
form {
display: flex;
align-items: stretch;
}
.v-select {
width: 75%;
}
input[type="submit"] {
margin-left: 1rem;
background: #44ae7d;
border: none;
border-radius: 3px;
color: #fff;
width: 20%;
}
</style>