Merge pull request #42 from themesberg/chank1e/develop
feat: toast-provider and useToast initial
This commit is contained in:
@@ -58,6 +58,7 @@ function getComponents() {
|
|||||||
function getUtils() {
|
function getUtils() {
|
||||||
return [
|
return [
|
||||||
{ text: 'Flowbite Themable', link: '/components/flowbiteThemable/flowbiteThemable.md' },
|
{ text: 'Flowbite Themable', link: '/components/flowbiteThemable/flowbiteThemable.md' },
|
||||||
|
{ text: 'ToastProvider', link: '/components/toastProvider/toastProvider.md' },
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,4 +4,12 @@ import DefaultTheme from 'vitepress/theme'
|
|||||||
|
|
||||||
import './clear.css'
|
import './clear.css'
|
||||||
|
|
||||||
export default DefaultTheme
|
import { TransitionGroup } from "vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
...DefaultTheme,
|
||||||
|
enhanceApp({ app, router, siteData }) {
|
||||||
|
// strange thing, but there is no global transition-group component inside vitepress app
|
||||||
|
app.component('TransitionGroup', TransitionGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ToastClosableExample from './examples/ToastClosableExample.vue';
|
|||||||
import ToastIconExample from './examples/ToastIconExample.vue';
|
import ToastIconExample from './examples/ToastIconExample.vue';
|
||||||
import ToastDivideExample from './examples/ToastDivideExample.vue';
|
import ToastDivideExample from './examples/ToastDivideExample.vue';
|
||||||
import ToastMessageExample from './examples/ToastMessageExample.vue';
|
import ToastMessageExample from './examples/ToastMessageExample.vue';
|
||||||
|
import ToastProviderExample from './examples/ToastProviderExample.vue';
|
||||||
import ToastInteractiveExample from './examples/ToastInteractiveExample.vue'
|
import ToastInteractiveExample from './examples/ToastInteractiveExample.vue'
|
||||||
</script>
|
</script>
|
||||||
# Toast
|
# Toast
|
||||||
@@ -176,3 +177,6 @@ import { Toast } from 'flowbite-vue'
|
|||||||
```
|
```
|
||||||
|
|
||||||
<ToastIconExample />
|
<ToastIconExample />
|
||||||
|
|
||||||
|
---
|
||||||
|
<ToastProviderExample />
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<toast-provider>
|
||||||
|
<div class="vp-raw flex align-center gap-2 flex-wrap flex-col">
|
||||||
|
<toast-provider-example-child />
|
||||||
|
</div>
|
||||||
|
</toast-provider>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { ToastProvider } from '../../../../src/index'
|
||||||
|
import ToastProviderExampleChild from './ToastProviderExampleChild.vue'
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
<input class="text-black" type="number" v-model="ms">
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<Button @click="() => add('success')" color="green">success</Button>
|
||||||
|
<Button @click="() => add('warning')" color="yellow">warning</Button>
|
||||||
|
<Button @click="() => add('danger')" color="red">danger</Button>
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<Button @click="remove" color="alternative">remove</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { FLOWBITE_TOAST_INJECTION_KEY } from '../../../../src/components/Toast/components/ToastProvider/injection/config'
|
||||||
|
import { inject, ref } from 'vue'
|
||||||
|
import { Button } from '../../../../src/index'
|
||||||
|
|
||||||
|
const ms = ref('5000')
|
||||||
|
|
||||||
|
const injected = inject(FLOWBITE_TOAST_INJECTION_KEY)
|
||||||
|
const add = (type) => {
|
||||||
|
injected.add({
|
||||||
|
time: parseInt(ms.value) || 0,
|
||||||
|
type: type,
|
||||||
|
text: `${type} alert! Hello world!`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const remove = () => {
|
||||||
|
injected.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
6
docs/components/toastProvider/toastProvider.md
Normal file
6
docs/components/toastProvider/toastProvider.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<script setup>
|
||||||
|
import ToastProviderExample from './examples/ToastProviderExample.vue';
|
||||||
|
</script>
|
||||||
|
# Toast provider
|
||||||
|
|
||||||
|
<ToastProviderExample />
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "flowbite-vue",
|
"name": "flowbite-vue",
|
||||||
"version": "0.0.3",
|
"version": "0.0.4",
|
||||||
"repository": "https://github.com/themesberg/flowbite-vue.git",
|
"repository": "https://github.com/themesberg/flowbite-vue.git",
|
||||||
"author": "themesberg",
|
"author": "themesberg",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ToastAlign, ToastPreset } from '@/components/Toast/types'
|
import type { ToastAlign, ToastType } from '@/components/Toast/types'
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import { useToastClasses } from './composables/useToastClasses'
|
import { useToastClasses } from './composables/useToastClasses'
|
||||||
import { ref, toRefs } from 'vue'
|
import { ref, toRefs } from 'vue'
|
||||||
@@ -32,7 +32,7 @@ import FlowbiteThemableChild
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
type: {
|
type: {
|
||||||
type: String as PropType<ToastPreset>,
|
type: String as PropType<ToastType>,
|
||||||
default: 'empty',
|
default: 'empty',
|
||||||
},
|
},
|
||||||
alignment: {
|
alignment: {
|
||||||
@@ -59,5 +59,4 @@ const onClose = () => {
|
|||||||
emit('close')
|
emit('close')
|
||||||
visible.value = false
|
visible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
.list-enter-active,
|
||||||
|
.list-leave-active {
|
||||||
|
transition: all 0.5s ease;
|
||||||
|
}
|
||||||
|
.list-enter-from,
|
||||||
|
.list-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(30px);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, h, provide, ref, resolveComponent } from 'vue'
|
||||||
|
import { FLOWBITE_TOAST_INJECTION_KEY } from '@/components/Toast/components/ToastProvider/injection/config'
|
||||||
|
import type { ToastItem, ToastItemWithId } from '@/components/Toast/components/ToastProvider/types'
|
||||||
|
import { Toast } from '@/index'
|
||||||
|
import { useTimeoutFn } from '@vueuse/core'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
Toast: Toast as any,
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const toasts = ref<ToastItemWithId[]>([])
|
||||||
|
|
||||||
|
const runRemoveTimeout = (id: string, ms: number) => {
|
||||||
|
useTimeoutFn(() => removeToast(id), ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
const addToast = (toast: ToastItem) => {
|
||||||
|
const id = ((new Date()).getTime() * Math.random()).toString()
|
||||||
|
toasts.value.push({
|
||||||
|
id,
|
||||||
|
...toast,
|
||||||
|
})
|
||||||
|
if(toast.time > 0)
|
||||||
|
runRemoveTimeout(id, toast.time)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeToast = (id: string) => {
|
||||||
|
const index = toasts.value.findIndex(_ => _.id === id)
|
||||||
|
toasts.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const popToast = () => {
|
||||||
|
if(toasts.value.length === 0) return
|
||||||
|
toasts.value.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
provide(FLOWBITE_TOAST_INJECTION_KEY, {
|
||||||
|
add: addToast,
|
||||||
|
remove: removeToast,
|
||||||
|
pop: popToast,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
toasts,
|
||||||
|
removeToast,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
$slots,
|
||||||
|
toasts,
|
||||||
|
removeToast,
|
||||||
|
} = this
|
||||||
|
|
||||||
|
return h('div', {}, [
|
||||||
|
$slots.default ? $slots.default() : null, // rendering default slot
|
||||||
|
h(resolveComponent('TransitionGroup'), {
|
||||||
|
name: 'list',
|
||||||
|
tag: 'div',
|
||||||
|
class: 'xl:w-1/6 md:w-1/4 sm:w-1/4 fixed top-3 right-3 flex flex-col gap-2 z-50',
|
||||||
|
},
|
||||||
|
toasts.map(_toast => // rendering every toast
|
||||||
|
h(resolveComponent('Toast'), {
|
||||||
|
closable: true,
|
||||||
|
type: _toast.type,
|
||||||
|
key: _toast.id,
|
||||||
|
onClose: () => removeToast(_toast.id),
|
||||||
|
}, _toast.text),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped src="./ToastProvider.css"></style>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export function useToast() {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const FLOWBITE_TOAST_INJECTION_KEY = 'flowbite-toast-injection-key'
|
||||||
14
src/components/Toast/components/ToastProvider/types.ts
Normal file
14
src/components/Toast/components/ToastProvider/types.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import type { ToastType } from '@/components/Toast/types'
|
||||||
|
|
||||||
|
export type ToastItem = {
|
||||||
|
time: number // ms
|
||||||
|
type: ToastType
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ToastItemWithId = ToastItem & {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ToastInjection = {
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import type { ToastPreset } from '@/components/Toast/types'
|
import type { ToastType } from '@/components/Toast/types'
|
||||||
import { simplifyTailwindClasses } from '@/utils/simplifyTailwindClasses'
|
import { simplifyTailwindClasses } from '@/utils/simplifyTailwindClasses'
|
||||||
import type { ToastAlign } from '@/components/Toast/types'
|
import type { ToastAlign } from '@/components/Toast/types'
|
||||||
|
|
||||||
@@ -11,12 +11,12 @@ type UseToastClassesReturns = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UseToastClassesProps = {
|
type UseToastClassesProps = {
|
||||||
type: Ref<ToastPreset>
|
type: Ref<ToastType>
|
||||||
divide: Ref<boolean>
|
divide: Ref<boolean>
|
||||||
alignment: Ref<ToastAlign>
|
alignment: Ref<ToastAlign>
|
||||||
}
|
}
|
||||||
|
|
||||||
const typeClassesMap: Record<ToastPreset, string> = {
|
const typeClassesMap: Record<ToastType, string> = {
|
||||||
danger: 'text-red-500 bg-red-100 dark:bg-red-800 dark:text-red-200',
|
danger: 'text-red-500 bg-red-100 dark:bg-red-800 dark:text-red-200',
|
||||||
empty: '',
|
empty: '',
|
||||||
success: 'text-green-500 bg-green-100 dark:bg-green-800 dark:text-green-200',
|
success: 'text-green-500 bg-green-100 dark:bg-green-800 dark:text-green-200',
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export type ToastPreset = 'success' | 'warning' | 'danger' | 'empty'
|
export type ToastType = 'success' | 'warning' | 'danger' | 'empty'
|
||||||
export type ToastAlign = 'start' | 'center' | 'end'
|
export type ToastAlign = 'start' | 'center' | 'end'
|
||||||
|
|||||||
5
src/composables.ts
Normal file
5
src/composables.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { useToast } from '@/components/Toast/components/ToastProvider/composables/useToast'
|
||||||
|
|
||||||
|
export {
|
||||||
|
useToast,
|
||||||
|
}
|
||||||
@@ -26,4 +26,7 @@ export { default as Sidebar } from './components/Sidebar/Sidebar.vue'
|
|||||||
export { default as Table } from './components/Table/Table.vue'
|
export { default as Table } from './components/Table/Table.vue'
|
||||||
export { default as Timeline } from './components/Timeline/Timeline.vue'
|
export { default as Timeline } from './components/Timeline/Timeline.vue'
|
||||||
export { default as Toast } from './components/Toast/Toast.vue'
|
export { default as Toast } from './components/Toast/Toast.vue'
|
||||||
|
export { default as ToastProvider } from './components/Toast/components/ToastProvider/ToastProvider.vue'
|
||||||
export { default as Tooltip } from './components/Tooltip/Tooltip.vue'
|
export { default as Tooltip } from './components/Tooltip/Tooltip.vue'
|
||||||
|
|
||||||
|
export * from './composables'
|
||||||
|
|||||||
Reference in New Issue
Block a user