Skip to content

Commit 28353ff

Browse files
committed
Make package public
1 parent 97fa550 commit 28353ff

File tree

14 files changed

+611
-2
lines changed

14 files changed

+611
-2
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
.DS_Store
22
node_modules
3-
/.svelte-kit
4-
/package
3+
/.svelte-kit

package/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.DS_Store
2+
node_modules
3+
/.svelte-kit
4+
/package

package/Notifications.svelte

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
<ul class="toasts" use:toaster={sessionKey} on:notify={createToast}>
2+
{#each toasts as toast (toast.id)}
3+
<li class="toast" style="background: {toast.background};" out:animateOut>
4+
{#if toast.persist}
5+
<button class="close" on:click={() => purge(toast.id)}>
6+
7+
</button>
8+
{/if}
9+
<div class="content">
10+
{toast.message}
11+
</div>
12+
<div
13+
class="progress"
14+
style="animation-duration: {toast.timeout}ms;"
15+
on:animationend={() => maybePurge(toast) }>
16+
</div>
17+
</li>
18+
{/each}
19+
</ul>
20+
21+
<style>
22+
.toasts {
23+
list-style: none;
24+
position: fixed;
25+
top: 0;
26+
right: 0;
27+
padding: 0;
28+
margin: 0;
29+
z-index: 9999;
30+
}
31+
32+
.toasts > .toast {
33+
display: flex;
34+
align-items: center;
35+
position: relative;
36+
margin: 1vh 1vw;
37+
min-width: 98vw;
38+
position: relative;
39+
animation: animate-in 600ms forwards;
40+
color: #fff;
41+
min-height: 8vh;
42+
}
43+
44+
.toasts > .toast > button {
45+
position: absolute;
46+
font-size: 18px;
47+
right: 0;
48+
margin: 6px;
49+
color: #fff;
50+
outline: none;
51+
border: 0;
52+
background-color: transparent;
53+
}
54+
55+
.toasts > .toast > .content {
56+
padding: 1vw;
57+
display: flex;
58+
font-weight: 500;
59+
margin-right: 20px;
60+
}
61+
62+
.toasts > .toast > .progress {
63+
position: absolute;
64+
bottom: 0;
65+
background-color: rgb(0, 0, 0, 0.3);
66+
height: 6px;
67+
width: 100%;
68+
animation-name: shrink;
69+
animation-timing-function: linear;
70+
animation-fill-mode: forwards;
71+
}
72+
73+
.toasts > .toast:before,
74+
.toasts > .toast:after {
75+
content:"";
76+
position: absolute;
77+
z-index:-1;
78+
top:50%;
79+
bottom:0;
80+
left:1vw;
81+
right:1vw;
82+
border-radius:100px / 10px;
83+
}
84+
85+
.toasts > .toast:after {
86+
right: 1vw;
87+
left: auto;
88+
transform:skew(8deg) rotate(3deg);
89+
}
90+
91+
@keyframes animate-in {
92+
0%,
93+
60%,
94+
75%,
95+
90%,
96+
to {
97+
-webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1);
98+
animation-timing-function: cubic-bezier(.215, .61, .355, 1);
99+
}
100+
101+
0% {
102+
opacity: 0;
103+
transform: translate3d(3000px, 0, 0);
104+
}
105+
106+
60% {
107+
opacity: 1;
108+
transform: translate3d(-25px, 0, 0);
109+
}
110+
111+
75% {
112+
transform: translate3d(10px, 0, 0);
113+
}
114+
115+
90% {
116+
transform: translate3d(-5px, 0, 0);
117+
}
118+
119+
to {
120+
transform: none;
121+
}
122+
}
123+
124+
@keyframes shrink {
125+
0% {
126+
width: 98vw;
127+
}
128+
100% {
129+
width: 0;
130+
}
131+
}
132+
133+
@media (min-width: 480px) {
134+
@keyframes animate-in {
135+
0%,
136+
60%,
137+
75%,
138+
90%,
139+
to {
140+
-webkit-animation-timing-function: cubic-bezier(.215, .61, .355, 1);
141+
animation-timing-function: cubic-bezier(.215, .61, .355, 1);
142+
}
143+
144+
0% {
145+
opacity: 0;
146+
transform: translate3d(3000px, 0, 0);
147+
}
148+
149+
60% {
150+
opacity: 1;
151+
transform: translate3d(-25px, 0, 0);
152+
}
153+
154+
75% {
155+
transform: translate3d(10px, 0, 0);
156+
}
157+
158+
90% {
159+
transform: translate3d(-5px, 0, 0);
160+
}
161+
162+
to {
163+
transform: none;
164+
}
165+
}
166+
167+
@keyframes shrink {
168+
0% {
169+
width: 40vw;
170+
}
171+
100% {
172+
width: 0;
173+
}
174+
}
175+
}
176+
177+
@media screen and (min-width: 600px) {
178+
.toasts > .toast {
179+
min-width: 40vw;
180+
min-height: auto;
181+
}
182+
183+
.toasts > .toast > .content {
184+
justify-content: flex-start;
185+
}
186+
}
187+
</style>
188+
189+
<script>
190+
import { toaster } from './toaster.js'
191+
192+
export let themes = {
193+
danger: '#bb2124',
194+
success: '#22bb33',
195+
warning: '#f0ad4e',
196+
info: '#5bc0de',
197+
default: '#aaaaaa'
198+
}
199+
200+
export let timeout = 3000
201+
export let sessionKey = 'byk-toasts'
202+
203+
let toasts = []
204+
205+
function animateOut (node, { delay = 0, duration = 1000 }) {
206+
return {
207+
delay,
208+
duration,
209+
css: t => `opacity: ${(t - 0.7) * 1}; transform-origin: top right;`
210+
}
211+
}
212+
213+
function createToast ({ detail }) {
214+
const { message, type, options = {} } = detail
215+
const background = themes[type] || themes.default
216+
const persist = options.persist
217+
const computedTimeout = options.persist ? 0 : (options.timeout || timeout)
218+
const id = Math.random().toString(36).replace(/[^a-z]+/g, '')
219+
220+
try {
221+
sessionStorage.setItem(
222+
sessionKey,
223+
JSON.stringify([
224+
...JSON.parse(sessionStorage.getItem(sessionKey) || '[]'),
225+
{ ...detail, id }
226+
])
227+
)
228+
} catch (e) {}
229+
230+
toasts = [ {
231+
id,
232+
message,
233+
background,
234+
persist,
235+
timeout: computedTimeout,
236+
width: '100%'
237+
}, ...toasts ]
238+
}
239+
240+
function maybePurge (toast) {
241+
!toast.persist && purge(toast.id)
242+
}
243+
244+
function purge (id) {
245+
const filter = t => t.id !== id
246+
toasts = toasts.filter(filter)
247+
try {
248+
sessionStorage.setItem(
249+
sessionKey,
250+
JSON.stringify(
251+
JSON.parse(sessionStorage.getItem(sessionKey) || '[]').filter(filter)
252+
)
253+
)
254+
} catch (e) {
255+
256+
}
257+
}
258+
</script>

package/Notifications.svelte.d.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/** @typedef {typeof __propDef.props} NotificationsProps */
2+
/** @typedef {typeof __propDef.events} NotificationsEvents */
3+
/** @typedef {typeof __propDef.slots} NotificationsSlots */
4+
export default class Notifications extends SvelteComponentTyped<{
5+
themes?: {
6+
danger: string;
7+
success: string;
8+
warning: string;
9+
info: string;
10+
default: string;
11+
};
12+
timeout?: number;
13+
sessionKey?: string;
14+
}, {
15+
[evt: string]: CustomEvent<any>;
16+
}, {}> {
17+
}
18+
export type NotificationsProps = typeof __propDef.props;
19+
export type NotificationsEvents = typeof __propDef.events;
20+
export type NotificationsSlots = typeof __propDef.slots;
21+
import { SvelteComponentTyped } from "svelte";
22+
declare const __propDef: {
23+
props: {
24+
themes?: {
25+
danger: string;
26+
success: string;
27+
warning: string;
28+
info: string;
29+
default: string;
30+
};
31+
timeout?: number;
32+
sessionKey?: string;
33+
};
34+
events: {
35+
[evt: string]: CustomEvent<any>;
36+
};
37+
slots: {};
38+
};
39+
export {};

0 commit comments

Comments
 (0)