mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-05 10:35:42 +02:00
init
This commit is contained in:
commit
495af35043
106 changed files with 18798 additions and 0 deletions
78
components/ui/Btn.vue
Normal file
78
components/ui/Btn.vue
Normal file
|
@ -0,0 +1,78 @@
|
|||
<template>
|
||||
<button class="btn outline-none rounded-md shadow-md relative border border-gray-600" :disabled="loading" :type="type" :class="classList" @click="click">
|
||||
<slot />
|
||||
<div v-if="loading" class="text-white absolute top-0 left-0 w-full h-full flex items-center justify-center text-opacity-100">
|
||||
<!-- <span class="material-icons animate-spin">refresh</span> -->
|
||||
<svg class="animate-spin" style="width: 24px; height: 24px" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z" />
|
||||
</svg>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: 'primary'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
paddingX: Number,
|
||||
small: Boolean,
|
||||
loading: Boolean
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
classList() {
|
||||
var list = []
|
||||
if (this.loading) list.push('text-opacity-0')
|
||||
list.push('text-white')
|
||||
list.push(`bg-${this.color}`)
|
||||
if (this.small) {
|
||||
list.push('text-sm')
|
||||
if (this.paddingX === undefined) list.push('px-4')
|
||||
list.push('py-1')
|
||||
} else {
|
||||
if (this.paddingX === undefined) list.push('px-8')
|
||||
list.push('py-2')
|
||||
}
|
||||
if (this.paddingX !== undefined) {
|
||||
list.push(`px-${this.paddingX}`)
|
||||
}
|
||||
return list
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
click(e) {
|
||||
this.$emit('click', e)
|
||||
}
|
||||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
button.btn::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
border-radius: 6px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
transition: all 0.1s ease-in-out;
|
||||
}
|
||||
button.btn:hover:not(:disabled)::before {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
button:disabled::before {
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
</style>
|
61
components/ui/Menu.vue
Normal file
61
components/ui/Menu.vue
Normal file
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<div class="relative" v-click-outside="clickOutside">
|
||||
<button type="button" class="relative w-full bg-fg border border-gray-500 rounded shadow-sm pl-3 pr-10 py-2 text-left focus:outline-none sm:text-sm cursor-pointer" aria-haspopup="listbox" aria-expanded="true" @click.stop.prevent="showMenu = !showMenu">
|
||||
<span class="flex items-center">
|
||||
<span class="block truncate">{{ label }}</span>
|
||||
</span>
|
||||
<span class="ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||
<span class="material-icons text-gray-100">person</span>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<transition name="menu">
|
||||
<ul v-show="showMenu" class="absolute z-10 -mt-px w-full bg-primary border border-gray-600 shadow-lg max-h-56 rounded-b-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm" tabindex="-1" role="listbox" aria-activedescendant="listbox-option-3">
|
||||
<template v-for="item in items">
|
||||
<nuxt-link :key="item.value" v-if="item.to" :to="item.to">
|
||||
<li :key="item.value" class="text-gray-100 select-none relative py-2 cursor-pointer hover:bg-black-400" id="listbox-option-0" role="option" @click="clickedOption(item.value)">
|
||||
<div class="flex items-center">
|
||||
<span class="font-normal ml-3 block truncate font-sans">{{ item.text }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</nuxt-link>
|
||||
<li v-else :key="item.value" class="text-gray-100 select-none relative py-2 cursor-pointer hover:bg-black-400" id="listbox-option-0" role="option" @click="clickedOption(item.value)">
|
||||
<div class="flex items-center">
|
||||
<span class="font-normal ml-3 block truncate font-sans">{{ item.text }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Menu'
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showMenu: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickOutside() {
|
||||
this.showMenu = false
|
||||
},
|
||||
clickedOption(itemValue) {
|
||||
this.$emit('action', itemValue)
|
||||
this.showMenu = false
|
||||
}
|
||||
},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
29
components/ui/TextInput.vue
Normal file
29
components/ui/TextInput.vue
Normal file
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<input v-model="input" :type="type" :disabled="disabled" :placeholder="placeholder" class="px-2 py-1 bg-bg border border-gray-600 outline-none rounded-sm" :class="disabled ? 'text-gray-300' : 'text-white'" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: [String, Number],
|
||||
placeholder: String,
|
||||
type: String,
|
||||
disabled: Boolean
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
input: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
35
components/ui/TextInputWithLabel.vue
Normal file
35
components/ui/TextInputWithLabel.vue
Normal file
|
@ -0,0 +1,35 @@
|
|||
<template>
|
||||
<div class="w-full">
|
||||
<p class="px-1 pb-1 text-sm font-semibold">{{ label }}</p>
|
||||
<ui-text-input v-model="inputValue" :disabled="disabled" :type="type" class="w-full px-4 py-2" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: [String, Number],
|
||||
label: String,
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
disabled: Boolean
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
inputValue: {
|
||||
get() {
|
||||
return this.value
|
||||
},
|
||||
set(val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {},
|
||||
mounted() {}
|
||||
}
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue