@softwareone/spi-sv5-library 0.1.3 → 1.1.0
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/README.md +75 -19
- package/dist/Avatar/Avatar.svelte +33 -0
- package/dist/Avatar/Avatar.svelte.d.ts +10 -0
- package/dist/Breadcrumbs/Breadcrumbs.svelte +10 -20
- package/dist/Button/Button.svelte +66 -115
- package/dist/Button/Button.svelte.d.ts +8 -6
- package/dist/Card/Card.svelte +18 -44
- package/dist/Card/Card.svelte.d.ts +1 -1
- package/dist/Chips/Chips.svelte +40 -46
- package/dist/Chips/Chips.svelte.d.ts +2 -1
- package/dist/Chips/chipsState.svelte.d.ts +7 -0
- package/dist/Chips/chipsState.svelte.js +8 -0
- package/dist/ErrorPage/ErrorPage.svelte +96 -0
- package/dist/ErrorPage/ErrorPage.svelte.d.ts +7 -0
- package/dist/Footer/Footer.svelte +29 -135
- package/dist/Footer/Footer.svelte.d.ts +1 -1
- package/dist/Form/Input/Input.svelte +393 -0
- package/dist/Form/Input/Input.svelte.d.ts +14 -0
- package/dist/Form/Input/InputIcon.svelte +97 -0
- package/dist/Form/Input/InputIcon.svelte.d.ts +9 -0
- package/dist/Form/TextArea/TextArea.svelte +260 -0
- package/dist/Form/TextArea/TextArea.svelte.d.ts +13 -0
- package/dist/Form/Toggle/Toggle.svelte +120 -0
- package/dist/{Toggle → Form/Toggle}/Toggle.svelte.d.ts +4 -3
- package/dist/Header/Header.svelte +54 -136
- package/dist/Header/Header.svelte.d.ts +2 -2
- package/dist/Header/HeaderAccount.svelte +14 -35
- package/dist/Header/HeaderLoader.svelte +2 -2
- package/dist/Header/HeaderLogo.svelte +7 -4
- package/dist/Header/HeaderLogo.svelte.d.ts +14 -6
- package/dist/HighlightPanel/HighlightPanel.svelte +125 -0
- package/dist/HighlightPanel/HighlightPanel.svelte.d.ts +10 -0
- package/dist/HighlightPanel/highlightPanelState.svelte.d.ts +35 -0
- package/dist/HighlightPanel/highlightPanelState.svelte.js +13 -0
- package/dist/Menu/Menu.svelte +158 -0
- package/dist/Menu/Menu.svelte.d.ts +8 -0
- package/dist/Menu/MenuItem.svelte +149 -0
- package/dist/Menu/MenuItem.svelte.d.ts +11 -0
- package/dist/Menu/Sidebar.svelte +228 -0
- package/dist/Menu/Sidebar.svelte.d.ts +11 -0
- package/dist/Menu/SidebarState.svelte.d.ts +6 -0
- package/dist/Menu/SidebarState.svelte.js +1 -0
- package/dist/Modal/Modal.svelte +81 -29
- package/dist/Modal/Modal.svelte.d.ts +2 -9
- package/dist/Modal/ModalContent.svelte +8 -88
- package/dist/Modal/ModalContent.svelte.d.ts +2 -3
- package/dist/Modal/ModalFooter.svelte +21 -66
- package/dist/Modal/ModalFooter.svelte.d.ts +5 -5
- package/dist/Modal/ModalHeader.svelte +50 -34
- package/dist/Modal/ModalHeader.svelte.d.ts +5 -4
- package/dist/Modal/modalState.svelte.d.ts +15 -0
- package/dist/Modal/modalState.svelte.js +1 -0
- package/dist/ProgressWizard/ProgressWizard.svelte +273 -294
- package/dist/ProgressWizard/ProgressWizard.svelte.d.ts +11 -13
- package/dist/ProgressWizard/progressWizardState.svelte.d.ts +6 -0
- package/dist/ProgressWizard/progressWizardState.svelte.js +1 -0
- package/dist/Search/Search.svelte +154 -0
- package/dist/Search/Search.svelte.d.ts +10 -0
- package/dist/Tabs/Tabs.svelte +111 -0
- package/dist/Tabs/Tabs.svelte.d.ts +8 -0
- package/dist/Tabs/tabsState.svelte.d.ts +7 -0
- package/dist/Tabs/tabsState.svelte.js +1 -0
- package/dist/Toast/Toast.svelte +116 -49
- package/dist/Toast/toastState.svelte.d.ts +7 -3
- package/dist/Toast/toastState.svelte.js +13 -10
- package/dist/Tooltip/Tooltip.svelte +168 -0
- package/dist/Tooltip/Tooltip.svelte.d.ts +13 -0
- package/dist/assets/icons/feedback.svg +5 -0
- package/dist/index.d.ts +28 -8
- package/dist/index.js +24 -9
- package/package.json +4 -5
- package/dist/Toggle/Toggle.svelte +0 -170
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
3
|
+
|
|
4
|
+
type Props = {
|
|
5
|
+
value?: string;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
onclear?: () => void;
|
|
9
|
+
} & Omit<HTMLInputAttributes, 'value' | 'type'>;
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
value = $bindable(''),
|
|
13
|
+
placeholder = 'Search',
|
|
14
|
+
disabled = false,
|
|
15
|
+
onclear,
|
|
16
|
+
...props
|
|
17
|
+
}: Props = $props();
|
|
18
|
+
|
|
19
|
+
const hasValue = $derived(!!value);
|
|
20
|
+
|
|
21
|
+
const handleClear = () => {
|
|
22
|
+
value = '';
|
|
23
|
+
onclear?.();
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const handleKeydown = (event: KeyboardEvent) => {
|
|
27
|
+
if (event.key === 'Escape' && hasValue) {
|
|
28
|
+
handleClear();
|
|
29
|
+
event.preventDefault();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<div class="search-container" class:disabled>
|
|
35
|
+
<div class="search-wrapper">
|
|
36
|
+
<span class="material-icons-outlined search-icon" aria-hidden="true">search</span>
|
|
37
|
+
<input
|
|
38
|
+
type="search"
|
|
39
|
+
class="search-input"
|
|
40
|
+
bind:value
|
|
41
|
+
{placeholder}
|
|
42
|
+
{disabled}
|
|
43
|
+
onkeydown={handleKeydown}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
|
|
47
|
+
{#if hasValue && !disabled}
|
|
48
|
+
<button type="button" class="clear-button" onclick={handleClear} aria-label="Clear search">
|
|
49
|
+
<span class="material-icons-outlined" aria-hidden="true">close</span>
|
|
50
|
+
</button>
|
|
51
|
+
{/if}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<style>
|
|
56
|
+
.search-container {
|
|
57
|
+
position: relative;
|
|
58
|
+
font-size: 14px;
|
|
59
|
+
line-height: 20px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.search-wrapper {
|
|
63
|
+
position: relative;
|
|
64
|
+
display: flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
width: 100%;
|
|
67
|
+
border-radius: 8px;
|
|
68
|
+
border: 1px solid #6b7180;
|
|
69
|
+
background: #fff;
|
|
70
|
+
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.search-wrapper:hover:not(:has(.search-input:disabled)),
|
|
74
|
+
.search-wrapper:focus-within {
|
|
75
|
+
border-color: #472aff;
|
|
76
|
+
box-shadow: 0 0 0 3px rgba(149, 155, 255, 0.3);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.search-input {
|
|
80
|
+
width: 100%;
|
|
81
|
+
padding: 8px 40px 8px 40px;
|
|
82
|
+
border: none;
|
|
83
|
+
background: transparent;
|
|
84
|
+
font-size: 14px;
|
|
85
|
+
color: #000;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.search-input:focus {
|
|
89
|
+
outline: none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.search-input::placeholder {
|
|
93
|
+
color: #6b7180;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.search-input::-webkit-search-cancel-button,
|
|
97
|
+
.search-input::-webkit-search-decoration {
|
|
98
|
+
-webkit-appearance: none;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.search-icon,
|
|
102
|
+
.clear-button {
|
|
103
|
+
position: absolute;
|
|
104
|
+
top: 50%;
|
|
105
|
+
transform: translateY(-50%);
|
|
106
|
+
color: #6b7180;
|
|
107
|
+
font-size: 18px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.search-icon {
|
|
111
|
+
left: 12px;
|
|
112
|
+
pointer-events: none;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.clear-button {
|
|
116
|
+
right: 12px;
|
|
117
|
+
background: none;
|
|
118
|
+
border: none;
|
|
119
|
+
padding: 4px;
|
|
120
|
+
cursor: pointer;
|
|
121
|
+
border-radius: 4px;
|
|
122
|
+
transition: color 0.2s ease-in-out, background-color 0.2s ease-in-out;
|
|
123
|
+
display: flex;
|
|
124
|
+
align-items: center;
|
|
125
|
+
justify-content: center;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.clear-button:hover,
|
|
129
|
+
.clear-button:focus {
|
|
130
|
+
color: #000;
|
|
131
|
+
background-color: #f3f4f6;
|
|
132
|
+
outline: none;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.clear-button span {
|
|
136
|
+
font-size: 16px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.disabled .search-wrapper {
|
|
140
|
+
border-color: #d1d5db;
|
|
141
|
+
background-color: #f3f4f6;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.disabled .search-input {
|
|
145
|
+
color: #6b7180;
|
|
146
|
+
cursor: not-allowed;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@media (max-width: 640px) {
|
|
150
|
+
.search-input {
|
|
151
|
+
font-size: 16px;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HTMLInputAttributes } from 'svelte/elements';
|
|
2
|
+
type Props = {
|
|
3
|
+
value?: string;
|
|
4
|
+
placeholder?: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
onclear?: () => void;
|
|
7
|
+
} & Omit<HTMLInputAttributes, 'value' | 'type'>;
|
|
8
|
+
declare const Search: import("svelte").Component<Props, {}, "value">;
|
|
9
|
+
type Search = ReturnType<typeof Search>;
|
|
10
|
+
export default Search;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Tab } from '../index.js';
|
|
3
|
+
|
|
4
|
+
interface TabsProps {
|
|
5
|
+
tabs: Tab[];
|
|
6
|
+
activeTab?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { tabs = [], activeTab = 0 }: TabsProps = $props();
|
|
10
|
+
|
|
11
|
+
const handleClick = (index: number) => (): void => {
|
|
12
|
+
activeTab = index;
|
|
13
|
+
};
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class="tabs-container">
|
|
17
|
+
<div class="tabs-list" role="tablist" aria-label="tabs">
|
|
18
|
+
{#each tabs as tab}
|
|
19
|
+
{#if !tab.hidden}
|
|
20
|
+
{@const isActiveTab = activeTab === tab.index}
|
|
21
|
+
<button
|
|
22
|
+
id="tab-{tab.index}"
|
|
23
|
+
role="tab"
|
|
24
|
+
aria-selected={isActiveTab}
|
|
25
|
+
aria-controls="panel-{tab.index}"
|
|
26
|
+
tabindex={isActiveTab ? 0 : -1}
|
|
27
|
+
type="button"
|
|
28
|
+
class:active={isActiveTab}
|
|
29
|
+
onclick={handleClick(tab.index)}
|
|
30
|
+
>
|
|
31
|
+
{tab.label}
|
|
32
|
+
</button>
|
|
33
|
+
{/if}
|
|
34
|
+
{/each}
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
{#each tabs as tab}
|
|
38
|
+
{#if activeTab === tab.index}
|
|
39
|
+
<div
|
|
40
|
+
class="tabs-content"
|
|
41
|
+
id="panel-{tab.index}"
|
|
42
|
+
role="tabpanel"
|
|
43
|
+
aria-labelledby="tab-{tab.index}"
|
|
44
|
+
>
|
|
45
|
+
{@render tab.component?.()}
|
|
46
|
+
</div>
|
|
47
|
+
{/if}
|
|
48
|
+
{/each}
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<style>
|
|
52
|
+
.tabs-container {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-direction: column;
|
|
55
|
+
width: 100%;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.tabs-list {
|
|
59
|
+
display: flex;
|
|
60
|
+
gap: 16px;
|
|
61
|
+
border-bottom: 1px solid #e0e5e8;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.tabs-list button {
|
|
65
|
+
border-radius: 8px;
|
|
66
|
+
background-color: #fff;
|
|
67
|
+
padding: 20px 16px 20px;
|
|
68
|
+
position: relative;
|
|
69
|
+
border: none;
|
|
70
|
+
font-size: 16px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.tabs-list button:hover {
|
|
74
|
+
background-color: #f4f6f8;
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.tabs-list button.active {
|
|
79
|
+
color: #472aff;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.tabs-list button::after {
|
|
83
|
+
content: '';
|
|
84
|
+
position: absolute;
|
|
85
|
+
left: 50%;
|
|
86
|
+
bottom: -2px;
|
|
87
|
+
width: 0;
|
|
88
|
+
height: 4px;
|
|
89
|
+
background-color: #472aff;
|
|
90
|
+
border-radius: 8px;
|
|
91
|
+
transform: translateX(-50%);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.tabs-list button:hover::after,
|
|
95
|
+
.tabs-list button.active::after {
|
|
96
|
+
width: 90%;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.tabs-content {
|
|
100
|
+
width: 100%;
|
|
101
|
+
height: 100%;
|
|
102
|
+
position: relative;
|
|
103
|
+
border-radius: 0px 0px 16px 16px;
|
|
104
|
+
overflow: hidden;
|
|
105
|
+
padding: 24px;
|
|
106
|
+
box-sizing: border-box;
|
|
107
|
+
min-height: 300px;
|
|
108
|
+
text-align: left;
|
|
109
|
+
font-size: 18px;
|
|
110
|
+
}
|
|
111
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/Toast/Toast.svelte
CHANGED
|
@@ -1,47 +1,47 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { fly } from 'svelte/transition';
|
|
3
2
|
import { linear } from 'svelte/easing';
|
|
4
|
-
import {
|
|
3
|
+
import { fly, type FlyParams } from 'svelte/transition';
|
|
4
|
+
|
|
5
|
+
import { deleteToastById, getToast } from './toastState.svelte.js';
|
|
5
6
|
|
|
6
7
|
interface ToastProps {
|
|
7
8
|
duration?: number;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
let { duration }:ToastProps = $props();
|
|
11
|
+
let { duration }: ToastProps = $props();
|
|
11
12
|
|
|
12
|
-
const
|
|
13
|
+
const TRANSITION_DURATION = 100;
|
|
14
|
+
const VERTICAL_DISTANCE = 8;
|
|
13
15
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
danger: '#DC182C',
|
|
19
|
-
neutral: '#6B7180',
|
|
20
|
-
success: '#008556'
|
|
21
|
-
};
|
|
22
|
-
return colors[type] || '#6B7180'; // Default to neutral if type is unknown
|
|
16
|
+
const transitionConfig: FlyParams = {
|
|
17
|
+
duration: TRANSITION_DURATION,
|
|
18
|
+
easing: linear,
|
|
19
|
+
y: VERTICAL_DISTANCE
|
|
23
20
|
};
|
|
24
21
|
|
|
22
|
+
const toastNotifications = getToast(duration);
|
|
25
23
|
</script>
|
|
26
24
|
|
|
27
|
-
{#if
|
|
28
|
-
<div class="toast-container" in:fly={
|
|
29
|
-
{#each
|
|
30
|
-
<div class="toast" in:fly={
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
>
|
|
39
|
-
<rect width="8" height="36" rx="4" fill={getToastColor(msg.type)} />
|
|
40
|
-
</svg>
|
|
25
|
+
{#if toastNotifications.toasts.length > 0}
|
|
26
|
+
<div class="toast-container" in:fly={transitionConfig} out:fly={transitionConfig}>
|
|
27
|
+
{#each toastNotifications.toasts as toast}
|
|
28
|
+
<div class="toast {toast.width ?? 'sm'}" in:fly={transitionConfig} out:fly={transitionConfig}>
|
|
29
|
+
<span class="status-indicator {toast.type}"></span>
|
|
30
|
+
<div class="toast-content-container">
|
|
31
|
+
<div class="toast-content">
|
|
32
|
+
<span>{toast.message}</span>
|
|
33
|
+
{#if toast.link}
|
|
34
|
+
<a class="toast-content-link" href={toast.link} title="View details">View details</a>
|
|
35
|
+
{/if}
|
|
36
|
+
</div>
|
|
41
37
|
</div>
|
|
42
|
-
<div class="toast-
|
|
43
|
-
<
|
|
44
|
-
|
|
38
|
+
<div class="toast-close-container">
|
|
39
|
+
<button
|
|
40
|
+
type="button"
|
|
41
|
+
class="toast-close-button material-icons"
|
|
42
|
+
aria-label="Close toast"
|
|
43
|
+
onclick={() => deleteToastById(toast.id)}>close</button
|
|
44
|
+
>
|
|
45
45
|
</div>
|
|
46
46
|
</div>
|
|
47
47
|
{/each}
|
|
@@ -50,55 +50,122 @@
|
|
|
50
50
|
|
|
51
51
|
<style>
|
|
52
52
|
.toast-container {
|
|
53
|
-
position: fixed;
|
|
53
|
+
position: fixed;
|
|
54
54
|
top: 96px;
|
|
55
55
|
right: 16px;
|
|
56
56
|
z-index: 9999;
|
|
57
57
|
display: flex;
|
|
58
58
|
flex-direction: column;
|
|
59
59
|
gap: 16px;
|
|
60
|
+
align-items: flex-end;
|
|
60
61
|
}
|
|
62
|
+
|
|
61
63
|
.toast {
|
|
64
|
+
width: var(--toast-width);
|
|
65
|
+
height: var(--toast-height);
|
|
62
66
|
display: inline-flex;
|
|
63
67
|
padding: 8px;
|
|
64
|
-
justify-content: flex-start;
|
|
65
|
-
align-items: center;
|
|
66
68
|
gap: 16px;
|
|
67
69
|
border-radius: 8px;
|
|
68
|
-
border: 1px solid
|
|
69
|
-
background:
|
|
70
|
-
/* shadow/dropdown */
|
|
70
|
+
border: 1px solid #e0e5e8;
|
|
71
|
+
background: #fff;
|
|
71
72
|
box-shadow:
|
|
72
73
|
0px 4px 5px 0px rgba(51, 56, 64, 0.15),
|
|
73
74
|
0px 1px 3px 0px rgba(51, 56, 64, 0.2),
|
|
74
75
|
0px 1px 16px 0px rgba(51, 56, 64, 0.1);
|
|
75
76
|
}
|
|
77
|
+
|
|
78
|
+
.toast.sm {
|
|
79
|
+
--toast-width: 400px;
|
|
80
|
+
--toast-height: 52px;
|
|
81
|
+
--toast-flex-direction: row;
|
|
82
|
+
--toast-gap: 8px;
|
|
83
|
+
--toast-close-button-align: center;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.toast.md {
|
|
87
|
+
--toast-width: 600px;
|
|
88
|
+
--toast-height: 88px;
|
|
89
|
+
--toast-flex-direction: column;
|
|
90
|
+
--toast-gap: 4px;
|
|
91
|
+
--toast-close-button-align: flex-start;
|
|
92
|
+
}
|
|
93
|
+
|
|
76
94
|
.toast-content {
|
|
77
95
|
display: flex;
|
|
96
|
+
justify-content: space-between;
|
|
97
|
+
flex-direction: var(--toast-flex-direction);
|
|
98
|
+
gap: var(--toast-gap);
|
|
78
99
|
padding: 8px 0px;
|
|
79
|
-
|
|
80
|
-
gap: 8px;
|
|
81
|
-
color: var(--brand-type, #000);
|
|
82
|
-
|
|
83
|
-
/* regular/2 */
|
|
84
|
-
font-family: 'Haas Grotesk Display Pro', sans-serif;
|
|
100
|
+
color: #000;
|
|
85
101
|
font-size: 14px;
|
|
86
102
|
font-style: normal;
|
|
87
103
|
font-weight: 400;
|
|
88
|
-
line-height: 20px;
|
|
104
|
+
line-height: 20px;
|
|
89
105
|
}
|
|
106
|
+
|
|
107
|
+
.toast-content-container {
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
gap: 16px;
|
|
111
|
+
flex-grow: 1;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.status-indicator {
|
|
115
|
+
width: 8px;
|
|
116
|
+
height: calc(var(--toast-height) - 20px);
|
|
117
|
+
flex-shrink: 0;
|
|
118
|
+
border-radius: 4px;
|
|
119
|
+
background-color: var(--toast-bg);
|
|
120
|
+
}
|
|
121
|
+
|
|
90
122
|
.toast-content-link {
|
|
91
123
|
display: flex;
|
|
92
|
-
align-items:
|
|
93
|
-
color:
|
|
94
|
-
font-family: 'Haas Grotesk Display Pro', sans-serif;
|
|
124
|
+
align-items: center;
|
|
125
|
+
color: #2b1999;
|
|
95
126
|
font-size: 14px;
|
|
96
|
-
font-style: normal;
|
|
97
127
|
font-weight: 400;
|
|
98
|
-
line-height: 20px;
|
|
128
|
+
line-height: 20px;
|
|
99
129
|
}
|
|
130
|
+
|
|
100
131
|
.toast-content-link:hover {
|
|
101
|
-
color:
|
|
132
|
+
color: #472aff;
|
|
102
133
|
text-decoration: underline;
|
|
103
134
|
}
|
|
135
|
+
|
|
136
|
+
.status-indicator.info {
|
|
137
|
+
--toast-bg: #472aff;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.status-indicator.warning {
|
|
141
|
+
--toast-bg: #e87d1e;
|
|
142
|
+
}
|
|
143
|
+
.status-indicator.danger {
|
|
144
|
+
--toast-bg: #dc182c;
|
|
145
|
+
}
|
|
146
|
+
.status-indicator.neutral {
|
|
147
|
+
--toast-bg: #6b7180;
|
|
148
|
+
}
|
|
149
|
+
.status-indicator.success {
|
|
150
|
+
--toast-bg: #008556;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.toast-close-container {
|
|
154
|
+
display: flex;
|
|
155
|
+
align-items: var(--toast-close-button-align);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.toast-close-button {
|
|
159
|
+
background: none;
|
|
160
|
+
border: none;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.toast-close-button:hover {
|
|
164
|
+
cursor: pointer;
|
|
165
|
+
color: #434952;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.toast-close-button:focus {
|
|
169
|
+
outline: none;
|
|
170
|
+
}
|
|
104
171
|
</style>
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
type ToastType = 'info' | 'success' | 'warning' | 'danger' | 'neutral';
|
|
2
|
+
type ToastWidth = 'sm' | 'md';
|
|
2
3
|
export interface Toast {
|
|
3
4
|
type: ToastType;
|
|
4
5
|
message: string;
|
|
6
|
+
width?: ToastWidth;
|
|
7
|
+
link?: string;
|
|
5
8
|
}
|
|
6
9
|
interface ToastState extends Toast {
|
|
7
10
|
id: string;
|
|
8
11
|
}
|
|
9
|
-
export declare
|
|
10
|
-
|
|
12
|
+
export declare const getToast: (duration?: number) => {
|
|
13
|
+
toasts: ToastState[];
|
|
11
14
|
duration: number;
|
|
12
15
|
};
|
|
13
|
-
export declare
|
|
16
|
+
export declare const addToast: (toast: Toast) => void;
|
|
17
|
+
export declare const deleteToastById: (id: string) => void;
|
|
14
18
|
export {};
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
const toastState = $state({
|
|
2
|
-
|
|
3
|
-
duration: 5000
|
|
2
|
+
toasts: [],
|
|
3
|
+
duration: 5000
|
|
4
4
|
});
|
|
5
|
-
export
|
|
5
|
+
export const getToast = (duration) => {
|
|
6
6
|
if (duration) {
|
|
7
7
|
toastState.duration = duration;
|
|
8
8
|
}
|
|
9
9
|
return toastState;
|
|
10
|
-
}
|
|
11
|
-
export
|
|
10
|
+
};
|
|
11
|
+
export const addToast = (toast) => {
|
|
12
12
|
const newToast = { ...toast, id: crypto.randomUUID() };
|
|
13
|
-
toastState.
|
|
13
|
+
toastState.toasts.push(newToast);
|
|
14
14
|
scheduleToastRemoval(newToast.id);
|
|
15
|
-
}
|
|
16
|
-
|
|
15
|
+
};
|
|
16
|
+
const scheduleToastRemoval = (id) => {
|
|
17
17
|
setTimeout(() => {
|
|
18
|
-
|
|
18
|
+
deleteToastById(id);
|
|
19
19
|
}, toastState.duration);
|
|
20
|
-
}
|
|
20
|
+
};
|
|
21
|
+
export const deleteToastById = (id) => {
|
|
22
|
+
toastState.toasts = toastState.toasts.filter((toast) => toast.id !== id);
|
|
23
|
+
};
|