twintrinsic 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +150 -0
- package/dist/App/App.svelte +54 -0
- package/dist/App/App.svelte.d.ts +65 -0
- package/dist/Section.svelte +25 -0
- package/dist/Section.svelte.d.ts +34 -0
- package/dist/actions/clickOutside.d.ts +9 -0
- package/dist/actions/clickOutside.js +19 -0
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/components/Accordion/Accordion.svelte +75 -0
- package/dist/components/Accordion/Accordion.svelte.d.ts +39 -0
- package/dist/components/Accordion/AccordionItem.svelte +150 -0
- package/dist/components/Accordion/AccordionItem.svelte.d.ts +30 -0
- package/dist/components/App/App.story.md +8 -0
- package/dist/components/App/App.story.svelte +170 -0
- package/dist/components/App/App.story.svelte.d.ts +22 -0
- package/dist/components/App/App.svelte +77 -0
- package/dist/components/App/App.svelte.d.ts +66 -0
- package/dist/components/App/Split.svelte +346 -0
- package/dist/components/App/Split.svelte.d.ts +54 -0
- package/dist/components/App/index.d.ts +2 -0
- package/dist/components/App/index.js +3 -0
- package/dist/components/AppHeader/AppHeader.svelte +439 -0
- package/dist/components/AppHeader/AppHeader.svelte.d.ts +24 -0
- package/dist/components/Avatar/Avatar.svelte +300 -0
- package/dist/components/Avatar/Avatar.svelte.d.ts +48 -0
- package/dist/components/Avatar/AvatarGroup.svelte +185 -0
- package/dist/components/Avatar/AvatarGroup.svelte.d.ts +46 -0
- package/dist/components/Badge/Badge.svelte +186 -0
- package/dist/components/Badge/Badge.svelte.d.ts +51 -0
- package/dist/components/BottomBar/BottomBar.svelte +146 -0
- package/dist/components/BottomBar/BottomBar.svelte.d.ts +38 -0
- package/dist/components/Breadcrumb/Breadcrumb.svelte +77 -0
- package/dist/components/Breadcrumb/Breadcrumb.svelte.d.ts +42 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.svelte +171 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.svelte.d.ts +38 -0
- package/dist/components/Button/Button.svelte +252 -0
- package/dist/components/Button/Button.svelte.d.ts +80 -0
- package/dist/components/Button/ButtonGroup.svelte +127 -0
- package/dist/components/Button/ButtonGroup.svelte.d.ts +44 -0
- package/dist/components/Card/Card.svelte +152 -0
- package/dist/components/Card/Card.svelte.d.ts +55 -0
- package/dist/components/Carousel/Carousel.svelte +461 -0
- package/dist/components/Carousel/Carousel.svelte.d.ts +79 -0
- package/dist/components/Carousel/CarouselItem.svelte +149 -0
- package/dist/components/Carousel/CarouselItem.svelte.d.ts +35 -0
- package/dist/components/Chip/Chip.svelte +288 -0
- package/dist/components/Chip/Chip.svelte.d.ts +71 -0
- package/dist/components/Chip/ChipGroup.svelte +190 -0
- package/dist/components/Chip/ChipGroup.svelte.d.ts +71 -0
- package/dist/components/CodeBlock/CodeBlock.svelte +356 -0
- package/dist/components/CodeBlock/CodeBlock.svelte.d.ts +44 -0
- package/dist/components/CodeBlock/index.d.ts +1 -0
- package/dist/components/CodeBlock/index.js +1 -0
- package/dist/components/CodeBlockSpeed/CodeBlockSpeed.svelte +145 -0
- package/dist/components/CodeBlockSpeed/CodeBlockSpeed.svelte.d.ts +44 -0
- package/dist/components/CodeEditor/CodeEditor.svelte +229 -0
- package/dist/components/CodeEditor/CodeEditor.svelte.d.ts +23 -0
- package/dist/components/Combobox/Combobox.svelte +279 -0
- package/dist/components/Combobox/Combobox.svelte.d.ts +34 -0
- package/dist/components/Container/Container.svelte +45 -0
- package/dist/components/Container/Container.svelte.d.ts +36 -0
- package/dist/components/DataTable/DataTable.svelte +879 -0
- package/dist/components/DataTable/DataTable.svelte.d.ts +102 -0
- package/dist/components/Form/AutoComplete.svelte +357 -0
- package/dist/components/Form/AutoComplete.svelte.d.ts +73 -0
- package/dist/components/Form/Calendar.svelte +429 -0
- package/dist/components/Form/Calendar.svelte.d.ts +53 -0
- package/dist/components/Form/Checkbox.svelte +196 -0
- package/dist/components/Form/Checkbox.svelte.d.ts +50 -0
- package/dist/components/Form/ColorPicker.svelte +396 -0
- package/dist/components/Form/ColorPicker.svelte.d.ts +43 -0
- package/dist/components/Form/Combobox.svelte +645 -0
- package/dist/components/Form/Combobox.svelte.d.ts +93 -0
- package/dist/components/Form/Dropdown.svelte +773 -0
- package/dist/components/Form/Dropdown.svelte.d.ts +81 -0
- package/dist/components/Form/FileUpload.svelte +796 -0
- package/dist/components/Form/FileUpload.svelte.d.ts +78 -0
- package/dist/components/Form/FloatLabel.svelte +245 -0
- package/dist/components/Form/FloatLabel.svelte.d.ts +44 -0
- package/dist/components/Form/Form.svelte +281 -0
- package/dist/components/Form/Form.svelte.d.ts +54 -0
- package/dist/components/Form/FormField.svelte +218 -0
- package/dist/components/Form/FormField.svelte.d.ts +47 -0
- package/dist/components/Form/Input.svelte +340 -0
- package/dist/components/Form/Input.svelte.d.ts +79 -0
- package/dist/components/Form/InputSwitch.svelte +189 -0
- package/dist/components/Form/InputSwitch.svelte.d.ts +46 -0
- package/dist/components/Form/InvalidState.svelte +97 -0
- package/dist/components/Form/InvalidState.svelte.d.ts +37 -0
- package/dist/components/Form/Knob.svelte +537 -0
- package/dist/components/Form/Knob.svelte.d.ts +78 -0
- package/dist/components/Form/ListInput.svelte +469 -0
- package/dist/components/Form/ListInput.svelte.d.ts +70 -0
- package/dist/components/Form/Listbox.svelte +513 -0
- package/dist/components/Form/Listbox.svelte.d.ts +74 -0
- package/dist/components/Form/NumberInput.svelte +452 -0
- package/dist/components/Form/NumberInput.svelte.d.ts +82 -0
- package/dist/components/Form/Radio.svelte +192 -0
- package/dist/components/Form/Radio.svelte.d.ts +53 -0
- package/dist/components/Form/RadioGroup.svelte +155 -0
- package/dist/components/Form/RadioGroup.svelte.d.ts +48 -0
- package/dist/components/Form/Rating.svelte +380 -0
- package/dist/components/Form/Rating.svelte.d.ts +64 -0
- package/dist/components/Form/Select.svelte +436 -0
- package/dist/components/Form/Select.svelte.d.ts +49 -0
- package/dist/components/Form/SelectGroup.svelte +34 -0
- package/dist/components/Form/SelectGroup.svelte.d.ts +33 -0
- package/dist/components/Form/Slider.svelte +622 -0
- package/dist/components/Form/Slider.svelte.d.ts +73 -0
- package/dist/components/Form/Switch.svelte +192 -0
- package/dist/components/Form/Switch.svelte.d.ts +46 -0
- package/dist/components/Form/TextInput.svelte +274 -0
- package/dist/components/Form/TextInput.svelte.d.ts +74 -0
- package/dist/components/Form/Textarea.svelte +207 -0
- package/dist/components/Form/Textarea.svelte.d.ts +62 -0
- package/dist/components/Icon/Icon.svelte +140 -0
- package/dist/components/Icon/Icon.svelte.d.ts +25 -0
- package/dist/components/Icon/index.d.ts +1 -0
- package/dist/components/Icon/index.js +1 -0
- package/dist/components/Lazy/Lazy.svelte +158 -0
- package/dist/components/Lazy/Lazy.svelte.d.ts +42 -0
- package/dist/components/Masonry/Masonry.svelte +299 -0
- package/dist/components/Masonry/Masonry.svelte.d.ts +55 -0
- package/dist/components/Menu/Menu/Menu.svelte +65 -0
- package/dist/components/Menu/Menu/Menu.svelte.d.ts +17 -0
- package/dist/components/Menu/Menu/MenuItem.svelte +90 -0
- package/dist/components/Menu/Menu/MenuItem.svelte.d.ts +27 -0
- package/dist/components/Modal/Modal.svelte +334 -0
- package/dist/components/Modal/Modal.svelte.d.ts +55 -0
- package/dist/components/Panel/Card.svelte +141 -0
- package/dist/components/Panel/Card.svelte.d.ts +52 -0
- package/dist/components/Panel/Hero/Hero.story.md +9 -0
- package/dist/components/Panel/Hero/Hero.story.svelte +49 -0
- package/dist/components/Panel/Hero/Hero.story.svelte.d.ts +21 -0
- package/dist/components/Panel/Hero/Hero.svelte +24 -0
- package/dist/components/Panel/Hero/Hero.svelte.d.ts +32 -0
- package/dist/components/Panel/LazyPanel.svelte +110 -0
- package/dist/components/Panel/LazyPanel.svelte.d.ts +46 -0
- package/dist/components/Panel/Panel.svelte +205 -0
- package/dist/components/Panel/Panel.svelte.d.ts +23 -0
- package/dist/components/Progress/Progress.svelte +220 -0
- package/dist/components/Progress/Progress.svelte.d.ts +61 -0
- package/dist/components/Separator/Separator.svelte +109 -0
- package/dist/components/Separator/Separator.svelte.d.ts +35 -0
- package/dist/components/Sidebar/Sidebar.svelte +213 -0
- package/dist/components/Sidebar/Sidebar.svelte.d.ts +60 -0
- package/dist/components/Skeleton/Skeleton.svelte +170 -0
- package/dist/components/Skeleton/Skeleton.svelte.d.ts +48 -0
- package/dist/components/Stepper/Stepper.svelte +111 -0
- package/dist/components/Stepper/Stepper.svelte.d.ts +54 -0
- package/dist/components/Stepper/StepperStep.svelte +369 -0
- package/dist/components/Stepper/StepperStep.svelte.d.ts +63 -0
- package/dist/components/Table/Table.svelte +167 -0
- package/dist/components/Table/Table.svelte.d.ts +56 -0
- package/dist/components/Table/TableBody.svelte +41 -0
- package/dist/components/Table/TableBody.svelte.d.ts +33 -0
- package/dist/components/Table/TableCell.svelte +76 -0
- package/dist/components/Table/TableCell.svelte.d.ts +36 -0
- package/dist/components/Table/TableHead.svelte +41 -0
- package/dist/components/Table/TableHead.svelte.d.ts +32 -0
- package/dist/components/Table/TableHeader.svelte +148 -0
- package/dist/components/Table/TableHeader.svelte.d.ts +42 -0
- package/dist/components/Table/TableRow.svelte +99 -0
- package/dist/components/Table/TableRow.svelte.d.ts +40 -0
- package/dist/components/Tabs/Tab.svelte +145 -0
- package/dist/components/Tabs/Tab.svelte.d.ts +36 -0
- package/dist/components/Tabs/TabList.svelte +60 -0
- package/dist/components/Tabs/TabList.svelte.d.ts +32 -0
- package/dist/components/Tabs/TabPanel.svelte +118 -0
- package/dist/components/Tabs/TabPanel.svelte.d.ts +38 -0
- package/dist/components/Tabs/Tabs.svelte +287 -0
- package/dist/components/Tabs/Tabs.svelte.d.ts +50 -0
- package/dist/components/Tag/Tag.svelte +260 -0
- package/dist/components/Tag/Tag.svelte.d.ts +54 -0
- package/dist/components/Tag/TagGroup.svelte +147 -0
- package/dist/components/Tag/TagGroup.svelte.d.ts +62 -0
- package/dist/components/ThemeToggle/ThemeToggle.svelte +93 -0
- package/dist/components/ThemeToggle/ThemeToggle.svelte.d.ts +12 -0
- package/dist/components/Timeline/Timeline.svelte +144 -0
- package/dist/components/Timeline/Timeline.svelte.d.ts +48 -0
- package/dist/components/Timeline/TimelineItem.svelte +391 -0
- package/dist/components/Timeline/TimelineItem.svelte.d.ts +63 -0
- package/dist/components/Toast/Toast.svelte +313 -0
- package/dist/components/Toast/Toast.svelte.d.ts +44 -0
- package/dist/components/Toast/toastStore.d.ts +40 -0
- package/dist/components/Toast/toastStore.js +293 -0
- package/dist/components/Tooltip/Tooltip.svelte +282 -0
- package/dist/components/Tooltip/Tooltip.svelte.d.ts +55 -0
- package/dist/components/Tree/Tree.svelte +129 -0
- package/dist/components/Tree/Tree.svelte.d.ts +61 -0
- package/dist/components/Tree/TreeNode.svelte +332 -0
- package/dist/components/Tree/TreeNode.svelte.d.ts +55 -0
- package/dist/components/icons/TwintrinsicLogo.svelte +73 -0
- package/dist/components/icons/TwintrinsicLogo.svelte.d.ts +17 -0
- package/dist/components/icons/twintrinsic-source.svg +73 -0
- package/dist/components/icons/twintrinsic.svg +38 -0
- package/dist/docs/EventsTable.svelte +86 -0
- package/dist/docs/EventsTable.svelte.d.ts +27 -0
- package/dist/docs/PropsTable.svelte +103 -0
- package/dist/docs/PropsTable.svelte.d.ts +28 -0
- package/dist/docs/index.d.ts +2 -0
- package/dist/docs/index.js +2 -0
- package/dist/helpers/detectLanguage.d.ts +6 -0
- package/dist/helpers/detectLanguage.js +60 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +94 -0
- package/dist/twintrinsic.css +347 -0
- package/package.json +98 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Toast - A component for displaying temporary notifications.
|
|
4
|
+
Provides consistent styling, accessibility features, and various display options.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
```svelte
|
|
8
|
+
<script>
|
|
9
|
+
import { showToast } from "./toastStore"
|
|
10
|
+
|
|
11
|
+
function notify() {
|
|
12
|
+
showToast({
|
|
13
|
+
message: "Operation completed successfully",
|
|
14
|
+
variant: "success",
|
|
15
|
+
duration: 3000,
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<button onclick={notify}>Show Toast</button>
|
|
21
|
+
|
|
22
|
+
<Toast />
|
|
23
|
+
```
|
|
24
|
+
-->
|
|
25
|
+
<script>
|
|
26
|
+
import { onMount, onDestroy } from 'svelte';
|
|
27
|
+
import { toastStore } from './toastStore';
|
|
28
|
+
import { fly, fade } from 'svelte/transition';
|
|
29
|
+
|
|
30
|
+
const {
|
|
31
|
+
/** @type {string} - Additional CSS classes */
|
|
32
|
+
class: className = '',
|
|
33
|
+
|
|
34
|
+
/** @type {string} - Position of toasts (top-right, top-left, bottom-right, bottom-left, top-center, bottom-center) */
|
|
35
|
+
position = 'bottom-right',
|
|
36
|
+
|
|
37
|
+
/** @type {number} - Maximum number of toasts to show at once */
|
|
38
|
+
maxToasts = 5,
|
|
39
|
+
|
|
40
|
+
/** @type {number} - Default duration in milliseconds */
|
|
41
|
+
duration = 5000,
|
|
42
|
+
|
|
43
|
+
/** @type {boolean} - Whether toasts can be dismissed by clicking */
|
|
44
|
+
dismissible = true,
|
|
45
|
+
|
|
46
|
+
/** @type {boolean} - Whether to pause toast timers on hover */
|
|
47
|
+
pauseOnHover = true
|
|
48
|
+
} = $props();
|
|
49
|
+
|
|
50
|
+
// Component state
|
|
51
|
+
let toasts = $state([]);
|
|
52
|
+
let container;
|
|
53
|
+
|
|
54
|
+
// Determine position classes
|
|
55
|
+
const positionClasses = $derived({
|
|
56
|
+
'top-right': 'toast-top-right',
|
|
57
|
+
'top-left': 'toast-top-left',
|
|
58
|
+
'bottom-right': 'toast-bottom-right',
|
|
59
|
+
'bottom-left': 'toast-bottom-left',
|
|
60
|
+
'top-center': 'toast-top-center',
|
|
61
|
+
'bottom-center': 'toast-bottom-center'
|
|
62
|
+
}[position] || 'toast-bottom-right');
|
|
63
|
+
|
|
64
|
+
// Subscribe to toast store
|
|
65
|
+
onMount(() => {
|
|
66
|
+
const unsubscribe = toastStore.subscribe(($toasts) => {
|
|
67
|
+
// Limit to maxToasts
|
|
68
|
+
toasts = $toasts.slice(0, maxToasts);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return unsubscribe;
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Removes a toast by id
|
|
76
|
+
* @param {string} id - Toast id
|
|
77
|
+
*/
|
|
78
|
+
function removeToast(id) {
|
|
79
|
+
toastStore.remove(id);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Pauses a toast's timer
|
|
84
|
+
* @param {string} id - Toast id
|
|
85
|
+
*/
|
|
86
|
+
function pauseToast(id) {
|
|
87
|
+
if (pauseOnHover) {
|
|
88
|
+
toastStore.pause(id);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Resumes a toast's timer
|
|
94
|
+
* @param {string} id - Toast id
|
|
95
|
+
*/
|
|
96
|
+
function resumeToast(id) {
|
|
97
|
+
if (pauseOnHover) {
|
|
98
|
+
toastStore.resume(id);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Clean up on component destroy
|
|
103
|
+
onDestroy(() => {
|
|
104
|
+
toastStore.clear();
|
|
105
|
+
});
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<div
|
|
109
|
+
class="
|
|
110
|
+
toast-container
|
|
111
|
+
{positionClasses}
|
|
112
|
+
{className}
|
|
113
|
+
"
|
|
114
|
+
aria-live="polite"
|
|
115
|
+
aria-atomic="true"
|
|
116
|
+
bind:this={container}
|
|
117
|
+
>
|
|
118
|
+
{#each toasts as toast (toast.id)}
|
|
119
|
+
<div
|
|
120
|
+
class="
|
|
121
|
+
toast
|
|
122
|
+
toast-{toast.variant || 'default'}
|
|
123
|
+
"
|
|
124
|
+
role="alert"
|
|
125
|
+
aria-live={toast.variant === 'error' ? 'assertive' : 'polite'}
|
|
126
|
+
onclick={() => dismissible && removeToast(toast.id)}
|
|
127
|
+
onmouseenter={() => pauseToast(toast.id)}
|
|
128
|
+
onmouseleave={() => resumeToast(toast.id)}
|
|
129
|
+
in:fly={{ y: 20, duration: 200 }}
|
|
130
|
+
out:fly={{ x: 20, duration: 200 }}
|
|
131
|
+
>
|
|
132
|
+
<div class="toast-content">
|
|
133
|
+
{#if toast.icon}
|
|
134
|
+
<div class="toast-icon">
|
|
135
|
+
{@html toast.icon}
|
|
136
|
+
</div>
|
|
137
|
+
{:else}
|
|
138
|
+
<div class="toast-icon">
|
|
139
|
+
{#if toast.variant === 'success'}
|
|
140
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
141
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
|
142
|
+
</svg>
|
|
143
|
+
{:else if toast.variant === 'error'}
|
|
144
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
145
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
146
|
+
</svg>
|
|
147
|
+
{:else if toast.variant === 'warning'}
|
|
148
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
149
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
|
|
150
|
+
</svg>
|
|
151
|
+
{:else if toast.variant === 'info'}
|
|
152
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
153
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
154
|
+
</svg>
|
|
155
|
+
{/if}
|
|
156
|
+
</div>
|
|
157
|
+
{/if}
|
|
158
|
+
|
|
159
|
+
<div class="toast-message">
|
|
160
|
+
{#if toast.title}
|
|
161
|
+
<div class="toast-title">{toast.title}</div>
|
|
162
|
+
{/if}
|
|
163
|
+
<div>{toast.message}</div>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
{#if dismissible}
|
|
167
|
+
<button
|
|
168
|
+
type="button"
|
|
169
|
+
class="toast-close"
|
|
170
|
+
aria-label="Close notification"
|
|
171
|
+
onclick={(e) => { e.stopPropagation(); removeToast(toast.id) }}
|
|
172
|
+
>
|
|
173
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
174
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
175
|
+
</svg>
|
|
176
|
+
</button>
|
|
177
|
+
{/if}
|
|
178
|
+
</div>
|
|
179
|
+
|
|
180
|
+
{#if toast.progress !== false}
|
|
181
|
+
<div class="toast-progress-container">
|
|
182
|
+
<div
|
|
183
|
+
class="toast-progress"
|
|
184
|
+
style="width: {toast.progress || 100}%"
|
|
185
|
+
></div>
|
|
186
|
+
</div>
|
|
187
|
+
{/if}
|
|
188
|
+
</div>
|
|
189
|
+
{/each}
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<style>
|
|
193
|
+
@reference "../../twintrinsic.css";
|
|
194
|
+
|
|
195
|
+
.toast-container {
|
|
196
|
+
@apply fixed z-50;
|
|
197
|
+
@apply flex flex-col gap-2;
|
|
198
|
+
@apply max-w-sm w-full;
|
|
199
|
+
@apply pointer-events-none;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.toast-top-right {
|
|
203
|
+
@apply top-4 right-4;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.toast-top-left {
|
|
207
|
+
@apply top-4 left-4;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.toast-bottom-right {
|
|
211
|
+
@apply bottom-4 right-4;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.toast-bottom-left {
|
|
215
|
+
@apply bottom-4 left-4;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.toast-top-center {
|
|
219
|
+
@apply top-4 left-1/2 -translate-x-1/2;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.toast-bottom-center {
|
|
223
|
+
@apply bottom-4 left-1/2 -translate-x-1/2;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.toast {
|
|
227
|
+
@apply bg-surface dark:bg-surface;
|
|
228
|
+
@apply text-text dark:text-text;
|
|
229
|
+
@apply rounded-lg shadow-lg;
|
|
230
|
+
@apply overflow-hidden;
|
|
231
|
+
@apply pointer-events-auto;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.toast-content {
|
|
235
|
+
@apply flex items-start p-4;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.toast-icon {
|
|
239
|
+
@apply flex-shrink-0 mr-3 mt-0.5;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.toast-message {
|
|
243
|
+
@apply flex-grow;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.toast-title {
|
|
247
|
+
@apply font-medium mb-0.5;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.toast-close {
|
|
251
|
+
@apply flex-shrink-0 ml-3 -mr-1 p-1;
|
|
252
|
+
@apply text-muted dark:text-muted;
|
|
253
|
+
@apply hover:text-text dark:hover:text-text;
|
|
254
|
+
@apply rounded-full;
|
|
255
|
+
@apply focus:outline-none focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400;
|
|
256
|
+
@apply transition-colors duration-150;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.toast-progress-container {
|
|
260
|
+
@apply h-1 w-full bg-muted/10 dark:bg-muted/10;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.toast-progress {
|
|
264
|
+
@apply h-full transition-all duration-150 ease-linear;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Variant styles */
|
|
268
|
+
.toast-default .toast-progress {
|
|
269
|
+
@apply bg-muted dark:bg-muted;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.toast-primary .toast-icon {
|
|
273
|
+
@apply text-primary-500 dark:text-primary-500;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.toast-primary .toast-progress {
|
|
277
|
+
@apply bg-primary-500 dark:bg-primary-500;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.toast-success .toast-icon {
|
|
281
|
+
@apply text-success-500 dark:text-success-500;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.toast-success .toast-progress {
|
|
285
|
+
@apply bg-success-500 dark:bg-success-500;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.toast-warning .toast-icon {
|
|
289
|
+
@apply text-warning-500 dark:text-warning-500;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.toast-warning .toast-progress {
|
|
293
|
+
@apply bg-warning-500 dark:bg-warning-500;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.toast-error .toast-icon {
|
|
297
|
+
@apply text-error-500 dark:text-error-500;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.toast-error .toast-progress {
|
|
301
|
+
@apply bg-error-500 dark:bg-error-500;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.toast-info .toast-icon {
|
|
305
|
+
@apply text-info-500 dark:text-info-500;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.toast-info .toast-progress {
|
|
309
|
+
@apply bg-info-500 dark:bg-info-500;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/* No custom animations needed - using Svelte transitions */
|
|
313
|
+
</style>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export default Toast;
|
|
2
|
+
type Toast = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Toast - A component for displaying temporary notifications.
|
|
8
|
+
* Provides consistent styling, accessibility features, and various display options.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <script>
|
|
13
|
+
* import { showToast } from "./toastStore"
|
|
14
|
+
*
|
|
15
|
+
* function notify() {
|
|
16
|
+
* showToast({
|
|
17
|
+
* message: "Operation completed successfully",
|
|
18
|
+
* variant: "success",
|
|
19
|
+
* duration: 3000,
|
|
20
|
+
* })
|
|
21
|
+
* }
|
|
22
|
+
* </script>
|
|
23
|
+
*
|
|
24
|
+
* <button onclick={notify}>Show Toast</button>
|
|
25
|
+
*
|
|
26
|
+
* <Toast />
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
declare const Toast: import("svelte").Component<{
|
|
30
|
+
class?: string;
|
|
31
|
+
position?: string;
|
|
32
|
+
maxToasts?: number;
|
|
33
|
+
duration?: number;
|
|
34
|
+
dismissible?: boolean;
|
|
35
|
+
pauseOnHover?: boolean;
|
|
36
|
+
}, {}, "">;
|
|
37
|
+
type $$ComponentProps = {
|
|
38
|
+
class?: string;
|
|
39
|
+
position?: string;
|
|
40
|
+
maxToasts?: number;
|
|
41
|
+
duration?: number;
|
|
42
|
+
dismissible?: boolean;
|
|
43
|
+
pauseOnHover?: boolean;
|
|
44
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export const toastStore: Object;
|
|
2
|
+
export const showToast: any;
|
|
3
|
+
export type Toast = {
|
|
4
|
+
/**
|
|
5
|
+
* - Unique identifier
|
|
6
|
+
*/
|
|
7
|
+
id: string;
|
|
8
|
+
/**
|
|
9
|
+
* - Toast message content
|
|
10
|
+
*/
|
|
11
|
+
message: string;
|
|
12
|
+
/**
|
|
13
|
+
* - Optional toast title
|
|
14
|
+
*/
|
|
15
|
+
title?: string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* - Visual style variant (default, primary, success, warning, error, info)
|
|
18
|
+
*/
|
|
19
|
+
variant?: string | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* - Duration in milliseconds
|
|
22
|
+
*/
|
|
23
|
+
duration?: number | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* - Custom icon or false to hide icon
|
|
26
|
+
*/
|
|
27
|
+
icon?: string | boolean | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* - Whether toast can be dismissed by clicking
|
|
30
|
+
*/
|
|
31
|
+
dismissible?: boolean | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* - Progress percentage (0-100) or false to hide progress
|
|
34
|
+
*/
|
|
35
|
+
progress?: number | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* - Whether toast is in closing animation
|
|
38
|
+
*/
|
|
39
|
+
closing?: boolean | undefined;
|
|
40
|
+
};
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast notification store
|
|
3
|
+
* Manages toast notifications for the application
|
|
4
|
+
*
|
|
5
|
+
* @module toastStore
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { writable } from "svelte/store"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} Toast
|
|
12
|
+
* @property {string} id - Unique identifier
|
|
13
|
+
* @property {string} message - Toast message content
|
|
14
|
+
* @property {string} [title] - Optional toast title
|
|
15
|
+
* @property {string} [variant] - Visual style variant (default, primary, success, warning, error, info)
|
|
16
|
+
* @property {number} [duration] - Duration in milliseconds
|
|
17
|
+
* @property {string|boolean} [icon] - Custom icon or false to hide icon
|
|
18
|
+
* @property {boolean} [dismissible] - Whether toast can be dismissed by clicking
|
|
19
|
+
* @property {number} [progress] - Progress percentage (0-100) or false to hide progress
|
|
20
|
+
* @property {boolean} [closing] - Whether toast is in closing animation
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Create a toast store
|
|
25
|
+
* @returns {Object} Toast store with methods
|
|
26
|
+
*/
|
|
27
|
+
function createToastStore() {
|
|
28
|
+
// Create writable store
|
|
29
|
+
const { subscribe, update } = writable(/** @type {Toast[]} */ ([]))
|
|
30
|
+
|
|
31
|
+
// Timer map to track toast timeouts
|
|
32
|
+
const timers = new Map()
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Add a new toast
|
|
36
|
+
* @param {Object} toast - Toast configuration
|
|
37
|
+
* @param {string} toast.message - Toast message
|
|
38
|
+
* @param {string} [toast.title] - Toast title
|
|
39
|
+
* @param {string} [toast.variant] - Toast variant (default, primary, success, warning, error, info)
|
|
40
|
+
* @param {number} [toast.duration] - Duration in milliseconds
|
|
41
|
+
* @param {string|boolean} [toast.icon] - Custom icon or false to hide icon
|
|
42
|
+
* @param {boolean} [toast.dismissible] - Whether toast can be dismissed
|
|
43
|
+
* @param {boolean} [toast.progress] - Whether to show progress
|
|
44
|
+
* @returns {string} Toast ID
|
|
45
|
+
*/
|
|
46
|
+
function add(toast) {
|
|
47
|
+
const id = crypto.randomUUID()
|
|
48
|
+
const duration = toast.duration || 5000
|
|
49
|
+
|
|
50
|
+
// Create toast object
|
|
51
|
+
const newToast = {
|
|
52
|
+
id,
|
|
53
|
+
message: toast.message,
|
|
54
|
+
title: toast.title,
|
|
55
|
+
variant: toast.variant || "default",
|
|
56
|
+
duration,
|
|
57
|
+
icon: toast.icon,
|
|
58
|
+
dismissible: toast.dismissible !== false,
|
|
59
|
+
progress: toast.progress !== false ? 100 : false,
|
|
60
|
+
closing: false,
|
|
61
|
+
createdAt: Date.now(),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Add toast to store
|
|
65
|
+
update((toasts) => [newToast, ...toasts])
|
|
66
|
+
|
|
67
|
+
// Start timer for auto-removal
|
|
68
|
+
if (duration > 0) {
|
|
69
|
+
const timer = startTimer(id, duration)
|
|
70
|
+
timers.set(id, timer)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return id
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Start a timer for toast removal
|
|
78
|
+
* @param {string} id - Toast ID
|
|
79
|
+
* @param {number} duration - Duration in milliseconds
|
|
80
|
+
* @returns {Object} Timer object with interval and timeout
|
|
81
|
+
*/
|
|
82
|
+
function startTimer(id, duration) {
|
|
83
|
+
// Progress update interval (update every 100ms)
|
|
84
|
+
const interval = setInterval(() => {
|
|
85
|
+
update((toasts) => {
|
|
86
|
+
return toasts.map((toast) => {
|
|
87
|
+
if (toast.id === id && toast.progress !== false) {
|
|
88
|
+
const elapsed = Date.now() - toast.createdAt
|
|
89
|
+
const remaining = Math.max(0, duration - elapsed)
|
|
90
|
+
const progress = (remaining / duration) * 100
|
|
91
|
+
|
|
92
|
+
return { ...toast, progress }
|
|
93
|
+
}
|
|
94
|
+
return toast
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
}, 100)
|
|
98
|
+
|
|
99
|
+
// Timeout for removal
|
|
100
|
+
const timeout = setTimeout(() => {
|
|
101
|
+
// Start closing animation
|
|
102
|
+
update((toasts) => {
|
|
103
|
+
return toasts.map((toast) => {
|
|
104
|
+
if (toast.id === id) {
|
|
105
|
+
return { ...toast, closing: true }
|
|
106
|
+
}
|
|
107
|
+
return toast
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// Remove after animation completes
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
remove(id)
|
|
114
|
+
}, 200) // Match animation duration
|
|
115
|
+
}, duration)
|
|
116
|
+
|
|
117
|
+
return { interval, timeout }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Remove a toast by ID
|
|
122
|
+
* @param {string} id - Toast ID
|
|
123
|
+
*/
|
|
124
|
+
function remove(id) {
|
|
125
|
+
// Clear timers
|
|
126
|
+
if (timers.has(id)) {
|
|
127
|
+
const timer = timers.get(id)
|
|
128
|
+
clearInterval(timer.interval)
|
|
129
|
+
clearTimeout(timer.timeout)
|
|
130
|
+
timers.delete(id)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Remove from store
|
|
134
|
+
update((toasts) => toasts.filter((toast) => toast.id !== id))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Pause a toast's timer
|
|
139
|
+
* @param {string} id - Toast ID
|
|
140
|
+
*/
|
|
141
|
+
function pause(id) {
|
|
142
|
+
if (timers.has(id)) {
|
|
143
|
+
const timer = timers.get(id)
|
|
144
|
+
clearInterval(timer.interval)
|
|
145
|
+
clearTimeout(timer.timeout)
|
|
146
|
+
|
|
147
|
+
// Store remaining time
|
|
148
|
+
update((toasts) => {
|
|
149
|
+
return toasts.map((toast) => {
|
|
150
|
+
if (toast.id === id) {
|
|
151
|
+
const elapsed = Date.now() - toast.createdAt
|
|
152
|
+
const remaining = Math.max(0, toast.duration - elapsed)
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
...toast,
|
|
156
|
+
remaining,
|
|
157
|
+
paused: true,
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return toast
|
|
161
|
+
})
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Resume a toast's timer
|
|
168
|
+
* @param {string} id - Toast ID
|
|
169
|
+
*/
|
|
170
|
+
function resume(id) {
|
|
171
|
+
update((toasts) => {
|
|
172
|
+
const toastToResume = toasts.find((toast) => toast.id === id && toast.paused)
|
|
173
|
+
|
|
174
|
+
if (toastToResume) {
|
|
175
|
+
// Update creation time to account for pause
|
|
176
|
+
const newCreatedAt = Date.now() - (toastToResume.duration - toastToResume.remaining)
|
|
177
|
+
|
|
178
|
+
// Restart timer
|
|
179
|
+
const timer = startTimer(id, toastToResume.remaining)
|
|
180
|
+
timers.set(id, timer)
|
|
181
|
+
|
|
182
|
+
// Update toast
|
|
183
|
+
return toasts.map((toast) => {
|
|
184
|
+
if (toast.id === id) {
|
|
185
|
+
return {
|
|
186
|
+
...toast,
|
|
187
|
+
createdAt: newCreatedAt,
|
|
188
|
+
paused: false,
|
|
189
|
+
remaining: undefined,
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return toast
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return toasts
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Clear all toasts
|
|
202
|
+
*/
|
|
203
|
+
function clear() {
|
|
204
|
+
// Clear all timers
|
|
205
|
+
timers.forEach((timer) => {
|
|
206
|
+
clearInterval(timer.interval)
|
|
207
|
+
clearTimeout(timer.timeout)
|
|
208
|
+
})
|
|
209
|
+
timers.clear()
|
|
210
|
+
|
|
211
|
+
// Clear store
|
|
212
|
+
update(() => [])
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Show a success toast
|
|
217
|
+
* @param {string|Object} message - Message or toast config
|
|
218
|
+
* @param {string} [title] - Toast title
|
|
219
|
+
* @param {number} [duration] - Duration in milliseconds
|
|
220
|
+
* @returns {string} Toast ID
|
|
221
|
+
*/
|
|
222
|
+
function success(message, title, duration) {
|
|
223
|
+
const config =
|
|
224
|
+
typeof message === "string"
|
|
225
|
+
? { message, title, duration }
|
|
226
|
+
: { ...message, variant: "success" }
|
|
227
|
+
|
|
228
|
+
return add({ ...config, variant: "success" })
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Show an error toast
|
|
233
|
+
* @param {string|Object} message - Message or toast config
|
|
234
|
+
* @param {string} [title] - Toast title
|
|
235
|
+
* @param {number} [duration] - Duration in milliseconds
|
|
236
|
+
* @returns {string} Toast ID
|
|
237
|
+
*/
|
|
238
|
+
function error(message, title, duration) {
|
|
239
|
+
const config =
|
|
240
|
+
typeof message === "string" ? { message, title, duration } : { ...message, variant: "error" }
|
|
241
|
+
|
|
242
|
+
return add({ ...config, variant: "error" })
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Show a warning toast
|
|
247
|
+
* @param {string|Object} message - Message or toast config
|
|
248
|
+
* @param {string} [title] - Toast title
|
|
249
|
+
* @param {number} [duration] - Duration in milliseconds
|
|
250
|
+
* @returns {string} Toast ID
|
|
251
|
+
*/
|
|
252
|
+
function warning(message, title, duration) {
|
|
253
|
+
const config =
|
|
254
|
+
typeof message === "string"
|
|
255
|
+
? { message, title, duration }
|
|
256
|
+
: { ...message, variant: "warning" }
|
|
257
|
+
|
|
258
|
+
return add({ ...config, variant: "warning" })
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Show an info toast
|
|
263
|
+
* @param {string|Object} message - Message or toast config
|
|
264
|
+
* @param {string} [title] - Toast title
|
|
265
|
+
* @param {number} [duration] - Duration in milliseconds
|
|
266
|
+
* @returns {string} Toast ID
|
|
267
|
+
*/
|
|
268
|
+
function info(message, title, duration) {
|
|
269
|
+
const config =
|
|
270
|
+
typeof message === "string" ? { message, title, duration } : { ...message, variant: "info" }
|
|
271
|
+
|
|
272
|
+
return add({ ...config, variant: "info" })
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return {
|
|
276
|
+
subscribe,
|
|
277
|
+
add,
|
|
278
|
+
remove,
|
|
279
|
+
pause,
|
|
280
|
+
resume,
|
|
281
|
+
clear,
|
|
282
|
+
success,
|
|
283
|
+
error,
|
|
284
|
+
warning,
|
|
285
|
+
info,
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Create and export toast store
|
|
290
|
+
export const toastStore = createToastStore()
|
|
291
|
+
|
|
292
|
+
// Alias for add method
|
|
293
|
+
export const showToast = toastStore.add
|