mirror of
https://github.com/bitinflow/ui.git
synced 2026-03-13 13:45:59 +00:00
New elements and updates
This commit is contained in:
@@ -4,6 +4,10 @@
|
||||
:class="computedClass"
|
||||
@click="click"
|
||||
>
|
||||
<i
|
||||
v-if="icon"
|
||||
:class="['fal mr-1', icon]"
|
||||
/>
|
||||
<slot v-if="!loading" />
|
||||
<template v-else>
|
||||
<i class="fas fa-spinner fa-spin" />
|
||||
@@ -16,6 +20,10 @@ export default {
|
||||
name: "BitinflowButton",
|
||||
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'md'
|
||||
@@ -59,9 +67,11 @@ export default {
|
||||
.disabled {
|
||||
@apply opacity-50 cursor-not-allowed;
|
||||
}
|
||||
|
||||
.loading {
|
||||
@apply opacity-50 cursor-not-allowed;
|
||||
}
|
||||
|
||||
.button-text-sm {
|
||||
@apply text-sm;
|
||||
}
|
||||
@@ -97,6 +107,7 @@ export default {
|
||||
.primary-solid {
|
||||
@apply bg-primary-500 hover:bg-primary-600 dark:bg-primary-500 dark:hover:bg-primary-400 text-white;
|
||||
}
|
||||
|
||||
.primary-outline {
|
||||
@apply border-primary-500 hover:bg-primary-500 dark:hover:bg-primary-500 dark:border-primary-500 dark:hover:border-primary-500 text-primary-500 hover:text-white;
|
||||
}
|
||||
@@ -104,6 +115,7 @@ export default {
|
||||
.danger-solid {
|
||||
@apply bg-rose-500 hover:bg-rose-600 dark:bg-rose-500 dark:hover:bg-rose-400 text-white;
|
||||
}
|
||||
|
||||
.danger-outline {
|
||||
@apply border-rose-500 hover:bg-rose-500 dark:hover:bg-rose-500 dark:border-rose-500 dark:hover:border-rose-500 text-rose-500 hover:text-white;
|
||||
}
|
||||
@@ -111,6 +123,7 @@ export default {
|
||||
.warning-solid {
|
||||
@apply bg-amber-500 hover:bg-amber-600 dark:bg-amber-500 dark:hover:bg-amber-400 text-white;
|
||||
}
|
||||
|
||||
.warning-outline {
|
||||
@apply border-amber-500 hover:bg-amber-500 dark:hover:bg-amber-500 dark:border-amber-500 dark:hover:border-amber-500 text-amber-500 hover:text-white;
|
||||
}
|
||||
@@ -118,6 +131,7 @@ export default {
|
||||
.base-solid {
|
||||
@apply bg-white hover:bg-zinc-100 dark:bg-base-700 dark:hover:bg-base-600 text-black dark:text-white;
|
||||
}
|
||||
|
||||
.base-outline {
|
||||
@apply border-zinc-100 hover:bg-zinc-100 dark:hover:bg-base-700 dark:border-base-600 dark:hover:border-base-600 text-black dark:text-white;
|
||||
}
|
||||
@@ -125,6 +139,7 @@ export default {
|
||||
.light-solid {
|
||||
@apply bg-zinc-200 hover:bg-zinc-300 dark:bg-base-600 dark:hover:bg-base-500 text-black dark:text-white;
|
||||
}
|
||||
|
||||
.light-outline {
|
||||
@apply border-zinc-200 hover:bg-zinc-200 hover:border-zinc-200 dark:hover:bg-base-500 dark:border-base-500 dark:hover:border-base-500 text-black dark:text-white;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<nuxt-link
|
||||
class="hover:bg-primary-500 rounded-lg text-center text-xs py-4 flex flex-col space-y-2"
|
||||
href="#"
|
||||
:class="calculateClasses"
|
||||
:to="to"
|
||||
>
|
||||
<i :class="['fal text-xl', icon]" />
|
||||
<span>
|
||||
@@ -17,7 +18,29 @@ export default {
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'fa-arrow-up-right-from-square'
|
||||
},
|
||||
to: {
|
||||
type: String,
|
||||
default: '/'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
calculateClasses: function () {
|
||||
return {
|
||||
'router-link-active': this.$route.path.includes(this.to) && this.to !== '/',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.router-link-active {
|
||||
@apply bg-primary-500 dark:bg-primary-500;
|
||||
}
|
||||
/*
|
||||
.router-link-active:hover {
|
||||
@apply bg-primary-600 dark:bg-primary-400;
|
||||
}
|
||||
*/
|
||||
</style>
|
||||
|
||||
@@ -96,19 +96,19 @@
|
||||
<div class="flex-auto flex flex-col overflow-y-auto py-6 space-y-6">
|
||||
<!-- nav -->
|
||||
<nav class="primary flex flex-grow flex-col space-y-4 px-6">
|
||||
<slot name="top" />
|
||||
<slot name="top"/>
|
||||
</nav>
|
||||
|
||||
<nav class="flex flex-initial flex-col space-y-4 px-6">
|
||||
<slot name="bottom" />
|
||||
<slot name="bottom"/>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="flex-none" />
|
||||
<div class="flex-none"/>
|
||||
</nav>
|
||||
|
||||
<!-- Content -->
|
||||
<main class="flex flex-1">
|
||||
<slot />
|
||||
<slot/>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
@@ -139,6 +139,12 @@ export default {
|
||||
],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
// restore dark mode from local storage
|
||||
if (localStorage.getItem('darkMode') === 'true') {
|
||||
document.body.classList.add('dark');
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleMenu() {
|
||||
this.$refs.overlay.classList.toggle('hidden');
|
||||
@@ -166,7 +172,8 @@ export default {
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
document.body.classList.toggle('dark')
|
||||
const result = document.body.classList.toggle('dark')
|
||||
localStorage.setItem('darkMode', result ? 'true' : 'false');
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
15
src/runtime/components/BitinflowFlex1.vue
Normal file
15
src/runtime/components/BitinflowFlex1.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div class="flex-1">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "BitinflowFlex1"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div class="flex-auto">
|
||||
<slot/>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "BitinflowFlex"
|
||||
name: "BitinflowFlexAuto"
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<bitinflow-button
|
||||
class="flex items-center gap-2 w-full"
|
||||
icon="fa-plus"
|
||||
@click="$emit('click')"
|
||||
>
|
||||
<i :class="['fal', icon]" />
|
||||
<slot />
|
||||
</bitinflow-button>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<bitinflow-button-link
|
||||
class="flex items-center gap-2"
|
||||
:class="calculateClasses"
|
||||
:to="to"
|
||||
>
|
||||
<i :class="['fal', icon]" />
|
||||
@@ -23,6 +24,25 @@ export default {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
calculateClasses: function () {
|
||||
return {
|
||||
'router-link-active': this.$route.path.includes(this.to),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.router-link-active, .router-link-exact-active {
|
||||
@apply bg-primary-500 dark:bg-primary-500;
|
||||
}
|
||||
/*
|
||||
.router-link-active:hover, .router-link-exact-active:hover {
|
||||
@apply bg-primary-600 dark:bg-primary-400;
|
||||
}
|
||||
*/
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- eslint-disable vue/require-explicit-emits -->
|
||||
<template>
|
||||
<nav
|
||||
class="w-64 bg-white text-black shadow dark:bg-base-700 dark:text-white dark:border-base-900 dark:border-l flex flex-col overflow-y-auto h-screen absolute sm:relative transform -translate-x-full sm:translate-x-0 pt-10 pb-4 px-4 space-y-2"
|
||||
class="w bg-white text-black shadow dark:bg-base-700 dark:text-white dark:border-base-900 dark:border-l flex flex-col overflow-y-auto h-screen absolute sm:relative transform -translate-x-full sm:translate-x-0 pt-10 pb-4 px-4 space-y-2"
|
||||
>
|
||||
<span class="font-semibold px-4">
|
||||
<slot name="title" />
|
||||
@@ -14,11 +14,23 @@
|
||||
<div
|
||||
v-for="i in 3"
|
||||
:key="i"
|
||||
class="bg-zinc-100 dark:bg-base-600 rounded-lg px-4 py-2"
|
||||
>
|
||||
|
||||
</div>
|
||||
class="bg-zinc-100 dark:bg-base-600 rounded-lg px-4 py-2 h-10 animate-pulse"
|
||||
/>
|
||||
</template>
|
||||
<div v-else-if="empty" class="bg-zinc-100 dark:bg-base-600 rounded-lg px-4 py-16 text-xl opacity-50 text-center">
|
||||
<i class="fas fa-ghost mr-2 text-5xl opacity-70" />
|
||||
<div>
|
||||
No resources found
|
||||
</div>
|
||||
<div class="text-xs mt-2 opacity-70">
|
||||
<template v-if="hasCreateListener">
|
||||
Click on the <span class="font-bold"><i class="far fa-plus" /> Create Resource</span> button below to create your first resource.
|
||||
</template>
|
||||
<template v-else>
|
||||
You don't have any resources yet.
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="hasCreateListener">
|
||||
<bitinflow-second-level-button
|
||||
@@ -51,6 +63,10 @@ export default {
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
empty: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
135
src/runtime/components/BitinflowTable.vue
Normal file
135
src/runtime/components/BitinflowTable.vue
Normal file
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<template v-if="loading">
|
||||
<div
|
||||
v-for="i in 3"
|
||||
:key="i"
|
||||
class="bg-white text-black dark:bg-base-700 rounded-lg h-16 animate-pulse"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<div
|
||||
v-else-if="items.length === 0"
|
||||
class="bg-white dark:bg-base-700 rounded-lg px-4 py-16 text-xl text-center text-black dark:text-white"
|
||||
>
|
||||
<i class="fas fa-ghost mr-2 text-5xl opacity-70" />
|
||||
<div>
|
||||
No resources found
|
||||
</div>
|
||||
<div class="text-xs mt-2 opacity-70">
|
||||
<template v-if="hasCreateListener">
|
||||
Click on the
|
||||
<span class="font-bold"><i class="far fa-plus" /> Create Resource</span>
|
||||
button below to create your first resource.
|
||||
</template>
|
||||
<template v-else>
|
||||
You don't have any resources yet.
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-if="hasCreateListener">
|
||||
<bitinflow-button
|
||||
color="light"
|
||||
variant="outline"
|
||||
class="mt-8"
|
||||
size="sm"
|
||||
icon="fa-plus"
|
||||
@click="$emit('create')"
|
||||
>
|
||||
Create Resource
|
||||
</bitinflow-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else
|
||||
class="text-black dark:text-white"
|
||||
>
|
||||
<div class="flex gap-4 py-2">
|
||||
<div>
|
||||
<bitinflow-table-checkbox
|
||||
v-model="checkedAll"
|
||||
@update:model-value="toggleAll"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="flex-auto px-6"
|
||||
:class="gridClass"
|
||||
>
|
||||
<template
|
||||
v-for="key in keys"
|
||||
:key="key"
|
||||
>
|
||||
<div class="opacity-80">{{ columns[key].label }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid gap-4">
|
||||
<bitinflow-table-row
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
:grid-class="gridClass"
|
||||
@click="click(item)"
|
||||
>
|
||||
<slot
|
||||
name="row"
|
||||
:item="item"
|
||||
:keys="keys"
|
||||
/>
|
||||
</bitinflow-table-row>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BitinflowTableRow from "../../../dist/runtime/components/BitinflowTableRow.vue";
|
||||
import BitinflowTableCheckbox from "./BitinflowTableCheckbox.vue";
|
||||
|
||||
export default {
|
||||
name: "BitinflowTable",
|
||||
components: {BitinflowTableCheckbox, BitinflowTableRow},
|
||||
|
||||
props: {
|
||||
columns: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
keys: Object.keys(this.columns),
|
||||
checkedAll: false,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
gridClass() {
|
||||
return `grid grid-cols-${this.keys.length} gap-4`;
|
||||
},
|
||||
hasCreateListener() {
|
||||
return this.$attrs && this.$attrs.onCreate;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
title(value) {
|
||||
// "humanized" by converting kebab-case, snake_case, and camelCase to individual words and capitalizes each word.
|
||||
return value.replace(/([A-Z])/g, ' $1').replace(/[-_]/g, ' ').toLowerCase().replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); });
|
||||
},
|
||||
toggleAll(checked) {
|
||||
console.log('toggleAll', checked)
|
||||
},
|
||||
click(item) {
|
||||
this.$emit('click', item);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
37
src/runtime/components/BitinflowTableCheckbox.vue
Normal file
37
src/runtime/components/BitinflowTableCheckbox.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<a
|
||||
class="w-4 h-4 flex justify-center rounded p-2 text-black dark:text-white border-2 border-zinc-200 dark:border-base-600 dark:bg-base-700 dark:text-white"
|
||||
href="#"
|
||||
@click.prevent="toggle"
|
||||
>
|
||||
<i
|
||||
v-if="modelValue"
|
||||
class="fas fa-check text-xs text-primary-500 self-center"
|
||||
/>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "BitinflowTableCheckbox",
|
||||
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
emits: ['update:modelValue'],
|
||||
|
||||
methods: {
|
||||
toggle() {
|
||||
this.$emit('update:modelValue', !this.modelValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
52
src/runtime/components/BitinflowTableRow.vue
Normal file
52
src/runtime/components/BitinflowTableRow.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="flex gap-4">
|
||||
<div class="self-center">
|
||||
<bitinflow-table-checkbox v-model="checked" />
|
||||
</div>
|
||||
<div class="flex-auto relative">
|
||||
<a
|
||||
class="after:absolute after:inset-0"
|
||||
href="#"
|
||||
@click.prevent="click"
|
||||
/>
|
||||
<div
|
||||
class="bg-white border-2 text-black dark:bg-base-700 dark:text-white rounded shadow py-4 px-6"
|
||||
:class="checked ? 'border-primary-500' : 'border-transparent'"
|
||||
>
|
||||
<div :class="gridClass" class="items-center">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BitinflowTableCheckbox from "./BitinflowTableCheckbox.vue";
|
||||
|
||||
export default {
|
||||
name: "BitinflowTableRow",
|
||||
components: {BitinflowTableCheckbox},
|
||||
|
||||
props: {
|
||||
gridClass: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
emits: ['click'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
checked: false
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
click() {
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user