diff --git a/packages/ui/src/lib/Toast.svelte b/packages/ui/src/lib/Toast.svelte
new file mode 100644
index 0000000..ab3f6f9
--- /dev/null
+++ b/packages/ui/src/lib/Toast.svelte
@@ -0,0 +1,36 @@
+
+
+
+ {#each toasts.value as item (item.id)}
+
+ {item.message}
+
+ {/each}
+
+
+
diff --git a/packages/ui/src/lib/index.ts b/packages/ui/src/lib/index.ts
index 03670f9..499b98c 100644
--- a/packages/ui/src/lib/index.ts
+++ b/packages/ui/src/lib/index.ts
@@ -2,14 +2,20 @@ export { default as Input } from './Input.svelte';
export { default as InputCheckbox } from './inputs/InputCheckbox.svelte';
export { default as InputColor } from './inputs/InputColor.svelte';
export { default as InputNumber } from './inputs/InputNumber.svelte';
+export { default as InputSearch } from './inputs/InputSearch.svelte';
export { default as InputSelect } from './inputs/InputSelect.svelte';
export { default as InputShape } from './inputs/InputShape.svelte';
export { default as InputVec3 } from './inputs/InputVec3.svelte';
export { default as SocketTable } from './inputs/SocketTable.svelte';
+export { default as Button } from './Button.svelte';
export { default as Details } from './Details.svelte';
export { default as JsonViewer } from './JsonViewer.svelte';
export { default as ShortCut } from './ShortCut.svelte';
+export { default as Spinner } from './Spinner.svelte';
+export { default as Toast } from './Toast.svelte';
+export { toast } from './toast.svelte';
+export { default as ConfirmDialog } from './ConfirmDialog.svelte';
import Input from './Input.svelte';
export default Input;
diff --git a/packages/ui/src/lib/toast.svelte.ts b/packages/ui/src/lib/toast.svelte.ts
new file mode 100644
index 0000000..25b951d
--- /dev/null
+++ b/packages/ui/src/lib/toast.svelte.ts
@@ -0,0 +1,24 @@
+export type ToastType = 'info' | 'success' | 'error';
+
+export type ToastItem = {
+ id: number;
+ message: string;
+ type: ToastType;
+};
+
+let _toasts = $state([]);
+let _nextId = 0;
+
+export const toasts = {
+ get value() {
+ return _toasts;
+ }
+};
+
+export function toast(message: string, type: ToastType = 'info', duration = 3000) {
+ const id = _nextId++;
+ _toasts.push({ id, message, type });
+ setTimeout(() => {
+ _toasts = _toasts.filter((t) => t.id !== id);
+ }, duration);
+}
diff --git a/packages/ui/src/routes/+page.svelte b/packages/ui/src/routes/+page.svelte
index 32515cf..2f2542b 100644
--- a/packages/ui/src/routes/+page.svelte
+++ b/packages/ui/src/routes/+page.svelte
@@ -2,15 +2,21 @@
import type { NodeInput } from '@nodarium/types';
import '$lib/app.css';
import {
+ Button,
+ ConfirmDialog,
Details,
InputCheckbox,
InputColor,
InputNumber,
+ InputSearch,
InputSelect,
InputShape,
InputVec3,
JsonViewer,
- ShortCut
+ ShortCut,
+ Spinner,
+ Toast,
+ toast
} from '$lib';
import SocketTable from '$lib/inputs/SocketTable.svelte';
import Section from './Section.svelte';
@@ -68,6 +74,7 @@
let points = $state([]);
let theme = $state('dark');
+ let confirmOpen = $state(false);
@@ -76,6 +83,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -95,6 +113,13 @@
+
+
+
Searchable select — type to filter
+
+
+
+
Select with simple values
@@ -148,12 +173,12 @@
{#snippet header()}
-
+
{/snippet}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ toast('Project deleted', 'error')}
+ />
+
+
+