97 lines
No EOL
3.1 KiB
Svelte
97 lines
No EOL
3.1 KiB
Svelte
<script context="module">
|
|
import { writable } from 'svelte/store';
|
|
|
|
/**
|
|
* @typedef {'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'light' | 'dark'} ToastColor
|
|
* @typedef {object} ToastMessage
|
|
* @property {string} id - Unique identifier
|
|
* @property {string} header - Toast title
|
|
* @property {string} body - Toast message content
|
|
* @property {ToastColor} [color='info'] - The color of the toast header icon
|
|
* @property {boolean} [persistent=false] - If true, toast will not auto-close
|
|
* @property {function} [onRemoveCallback=null] - Callback function to be called when the toast is removed
|
|
*/
|
|
|
|
/** @type {import('svelte/store').Writable<ToastMessage[]>} */
|
|
export const toasts = writable([]);
|
|
|
|
/**
|
|
* Adds a new toast to the list.
|
|
* @param {Omit<ToastMessage, 'id'>} toast
|
|
* @returns {string} The ID of the new toast.
|
|
*/
|
|
export function addToast(toast) {
|
|
const id = crypto.randomUUID();
|
|
toasts.update((all) => [...all, { id, ...toast }]);
|
|
return id;
|
|
}
|
|
|
|
/**
|
|
* Removes a toast by its ID.
|
|
* @param {string} id
|
|
*/
|
|
export function removeToast(id) {
|
|
// call the onRemoveCallback if it exists
|
|
toasts.update((all) => {
|
|
const toast = all.find((t) => t.id === id);
|
|
if (toast && toast.onRemoveCallback) {
|
|
toast.onRemoveCallback(id);
|
|
}
|
|
return all.filter((t) => t.id !== id);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Callback function to be called when a toast is removed.
|
|
* @param {string} id - The ID of the removed toast.
|
|
*/
|
|
</script>
|
|
|
|
<script>
|
|
import { Toast, ToastBody, ToastHeader } from '@sveltestrap/sveltestrap';
|
|
|
|
/**
|
|
* Removes a toast from the list by its ID.
|
|
* @param {string} id
|
|
*/
|
|
|
|
</script>
|
|
|
|
<!--
|
|
This container holds all the toasts.
|
|
To use this component:
|
|
1. Import it into your layout or page: `import ToastContainer from './Toast.svelte';`
|
|
2. Place `<ToastContainer />` in your markup.
|
|
3. To show a toast from any other component:
|
|
import { addToast } from './Toast.svelte';
|
|
|
|
// For an auto-closing error message
|
|
addToast({ header: 'Error', body: 'Something went wrong.', color: 'danger' });
|
|
|
|
// For a persistent "map mode" indication
|
|
addToast({ header: 'Map Mode', body: 'You are in satellite view.', color: 'info', persistent: true });
|
|
-->
|
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
|
{#each $toasts as toast (toast.id)}
|
|
<Toast
|
|
isOpen={true}
|
|
autohide={!toast.persistent}
|
|
delay={5000}
|
|
color={toast.color || 'info'}
|
|
on:close={() => removeToast(toast.id)}
|
|
>
|
|
<ToastHeader toggle={() => removeToast(toast.id)}>
|
|
{toast.header}
|
|
</ToastHeader>
|
|
<ToastBody>
|
|
{toast.body}
|
|
</ToastBody>
|
|
</Toast>
|
|
{/each}
|
|
</div>
|
|
|
|
<style>
|
|
.toast-container {
|
|
z-index: 1090; /* High z-index to appear above other elements */
|
|
}
|
|
</style> |