@riverflowpkg/riverflow 1.0.3 → 1.0.7

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/toast/toast.js ADDED
@@ -0,0 +1,302 @@
1
+ // RiverFlow Toast
2
+ (function() {
3
+ 'use strict';
4
+
5
+ const STYLES = `
6
+ .rf-toast-container {
7
+ position: fixed;
8
+ z-index: 999999;
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: 12px;
12
+ max-width: 400px;
13
+ width: 100%;
14
+ pointer-events: none;
15
+ padding: 16px;
16
+ }
17
+ .rf-toast-container.bottom-right { bottom: 0; right: 0; }
18
+ .rf-toast-container.bottom-left { bottom: 0; left: 0; }
19
+ .rf-toast-container.top-right { top: 0; right: 0; }
20
+ .rf-toast-container.top-left { top: 0; left: 0; }
21
+ .rf-toast-container.top-center { top: 0; left: 50%; transform: translateX(-50%); }
22
+ .rf-toast-container.bottom-center { bottom: 0; left: 50%; transform: translateX(-50%); }
23
+
24
+ .rf-toast-container .rf-toast {
25
+ pointer-events: auto;
26
+ padding: 16px 20px;
27
+ border-radius: 16px;
28
+ font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
29
+ font-size: 0.95rem;
30
+ line-height: 1.5;
31
+ display: flex;
32
+ align-items: center;
33
+ gap: 14px;
34
+ transition: opacity 0.35s ease, transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
35
+ will-change: transform, opacity;
36
+ opacity: 0;
37
+ transform: var(--rf-out, translateX(120%)) scale(0.95);
38
+ border: 1px solid rgba(255,255,255,0.06);
39
+ }
40
+ .rf-toast-container .rf-toast.show {
41
+ opacity: 1;
42
+ transform: var(--rf-in, translateX(0)) scale(1);
43
+ }
44
+ .rf-toast-container .rf-toast.hide {
45
+ opacity: 0;
46
+ transform: var(--rf-out, translateX(120%)) scale(0.95);
47
+ }
48
+ .rf-toast-container .rf-toast .rf-toast-msg { flex: 1; font-weight: 450; }
49
+ .rf-toast-container .rf-toast .rf-toast-close {
50
+ background: none;
51
+ border: none;
52
+ font-size: 1.2rem;
53
+ cursor: pointer;
54
+ padding: 0 0 0 8px;
55
+ line-height: 1;
56
+ opacity: 0.5;
57
+ transition: opacity 0.2s, transform 0.2s;
58
+ color: inherit;
59
+ }
60
+ .rf-toast-container .rf-toast .rf-toast-close:hover {
61
+ opacity: 1;
62
+ transform: rotate(90deg);
63
+ }
64
+
65
+ .rf-toast.dark { background: rgba(26,26,46,0.92); color: #eee; box-shadow: 0 12px 40px rgba(0,0,0,0.35); border-color: rgba(255,255,255,0.06); }
66
+ .rf-toast.dark.success { background: rgba(0,200,81,0.15); }
67
+ .rf-toast.dark.warning { background: rgba(255,187,51,0.15); }
68
+ .rf-toast.dark.error { background: rgba(255,68,68,0.15); }
69
+ .rf-toast.dark.info { background: rgba(51,181,229,0.15); }
70
+
71
+ .rf-toast.light { background: rgba(255,255,255,0.92); color: #1a1a2e; box-shadow: 0 12px 40px rgba(0,0,0,0.08); border-color: rgba(0,0,0,0.05); }
72
+ .rf-toast.light.success { background: rgba(0,200,81,0.10); }
73
+ .rf-toast.light.warning { background: rgba(255,187,51,0.10); }
74
+ .rf-toast.light.error { background: rgba(255,68,68,0.10); }
75
+ .rf-toast.light.info { background: rgba(51,181,229,0.10); }
76
+
77
+ .rf-toast.neon { background: rgba(10,10,30,0.92); color: #00f5ff; border-color: #00f5ff44; box-shadow: 0 0 30px rgba(0,245,255,0.15), inset 0 0 30px rgba(0,245,255,0.03); text-shadow: 0 0 20px rgba(0,245,255,0.2); }
78
+
79
+ .rf-toast.glass { background: rgba(255,255,255,0.08); color: #fff; border-color: rgba(255,255,255,0.15); box-shadow: 0 12px 40px rgba(0,0,0,0.2), inset 0 1px 0 rgba(255,255,255,0.1); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); }
80
+
81
+ .rf-toast.gradient { background: linear-gradient(135deg, #667eea, #764ba2); color: #fff; border-color: rgba(255,255,255,0.15); box-shadow: 0 12px 40px rgba(118,75,162,0.3); }
82
+ .rf-toast.gradient.success { background: linear-gradient(135deg, #11998e, #38ef7d); }
83
+ .rf-toast.gradient.warning { background: linear-gradient(135deg, #f093fb, #f5576c); }
84
+ .rf-toast.gradient.error { background: linear-gradient(135deg, #eb3349, #f45c43); }
85
+ .rf-toast.gradient.info { background: linear-gradient(135deg, #4facfe, #00f2fe); }
86
+
87
+ .rf-toast.minimal { background: rgba(255,255,255,0.05); color: #ccc; border-color: rgba(255,255,255,0.04); box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; border-radius: 8px; padding: 12px 16px; }
88
+
89
+ .rf-toast.up-down { --rf-out: translateY(80px) scale(0.95); --rf-in: translateY(0) scale(1); }
90
+ .rf-toast.down-up { --rf-out: translateY(-80px) scale(0.95); --rf-in: translateY(0) scale(1); }
91
+ .rf-toast.left-right { --rf-out: translateX(-120%) scale(0.95); --rf-in: translateX(0) scale(1); }
92
+ .rf-toast.right-left { --rf-out: translateX(120%) scale(0.95); --rf-in: translateX(0) scale(1); }
93
+ .rf-toast.zoom { --rf-out: scale(0.6) translateY(40px); --rf-in: scale(1) translateY(0); }
94
+ .rf-toast.bounce { --rf-out: translateX(120%) scale(0.8); --rf-in: translateX(0) scale(1); transition: opacity 0.35s ease, transform 0.6s cubic-bezier(0.34, 1.7, 0.64, 1); }
95
+ `;
96
+
97
+ let stylesInjected = false;
98
+ let toastCount = 0;
99
+ let clickBindings = [];
100
+
101
+ const DEFAULTS = {
102
+ duration: 4000,
103
+ position: 'bottom-right',
104
+ containerId: 'rf-toast-container',
105
+ mode: 'dark',
106
+ animation: 'right-left',
107
+ closeable: true
108
+ };
109
+
110
+ let currentMode = DEFAULTS.mode;
111
+ let currentAnim = DEFAULTS.animation;
112
+ let currentPosition = DEFAULTS.position;
113
+
114
+ function getContainer() {
115
+ let el = document.getElementById(DEFAULTS.containerId);
116
+ if (!el) {
117
+ el = document.createElement('div');
118
+ el.id = DEFAULTS.containerId;
119
+ el.className = 'rf-toast-container ' + currentPosition;
120
+ document.body.appendChild(el);
121
+ }
122
+ return el;
123
+ }
124
+
125
+ const container = getContainer();
126
+
127
+ function injectStyles() {
128
+ if (stylesInjected) return;
129
+ const style = document.createElement('style');
130
+ style.textContent = STYLES;
131
+ document.head.appendChild(style);
132
+ stylesInjected = true;
133
+ }
134
+
135
+ window.RiverFlow = window.RiverFlow || {};
136
+
137
+ window.RiverFlow.toast = function toast(message, options) {
138
+ if (!message) return;
139
+
140
+ injectStyles();
141
+
142
+ const opts = Object.assign({}, DEFAULTS, options || {});
143
+ const type = opts.type || 'default';
144
+ const duration = opts.duration || DEFAULTS.duration;
145
+ const closeable = opts.closeable !== false;
146
+ const mode = opts.mode || currentMode;
147
+ const anim = opts.animation || currentAnim;
148
+
149
+ const toast = document.createElement('div');
150
+ toast.className = 'rf-toast ' + mode + ' ' + anim + ' ' + type;
151
+ toast.id = 'rf-toast-' + (++toastCount);
152
+ toast.setAttribute('role', 'alert');
153
+
154
+ let html = '<span class="rf-toast-msg">' + message + '</span>';
155
+ if (closeable) {
156
+ html += '<button class="rf-toast-close" aria-label="Close toast">&times;</button>';
157
+ }
158
+ toast.innerHTML = html;
159
+
160
+ container.appendChild(toast);
161
+
162
+ requestAnimationFrame(function() {
163
+ toast.classList.add('show');
164
+ });
165
+
166
+ let hideTimer = null;
167
+
168
+ function hideToast() {
169
+ if (hideTimer) clearTimeout(hideTimer);
170
+ toast.classList.remove('show');
171
+ toast.classList.add('hide');
172
+ setTimeout(function() {
173
+ if (toast.parentNode) toast.remove();
174
+ }, 500);
175
+ }
176
+
177
+ if (duration > 0) {
178
+ hideTimer = setTimeout(hideToast, duration);
179
+ }
180
+
181
+ const closeBtn = toast.querySelector('.rf-toast-close');
182
+ if (closeBtn) {
183
+ closeBtn.addEventListener('click', hideToast);
184
+ }
185
+
186
+ toast.addEventListener('mouseenter', function() {
187
+ if (hideTimer) clearTimeout(hideTimer);
188
+ });
189
+ toast.addEventListener('mouseleave', function() {
190
+ if (duration > 0) {
191
+ hideTimer = setTimeout(hideToast, duration);
192
+ }
193
+ });
194
+
195
+ return {
196
+ hide: hideToast,
197
+ element: toast
198
+ };
199
+ };
200
+
201
+ window.RiverFlow.toastSuccess = function(msg, opts) {
202
+ return window.RiverFlow.toast(msg, Object.assign({ type: 'success' }, opts));
203
+ };
204
+
205
+ window.RiverFlow.toastWarning = function(msg, opts) {
206
+ return window.RiverFlow.toast(msg, Object.assign({ type: 'warning' }, opts));
207
+ };
208
+
209
+ window.RiverFlow.toastError = function(msg, opts) {
210
+ return window.RiverFlow.toast(msg, Object.assign({ type: 'error' }, opts));
211
+ };
212
+
213
+ window.RiverFlow.toastInfo = function(msg, opts) {
214
+ return window.RiverFlow.toast(msg, Object.assign({ type: 'info' }, opts));
215
+ };
216
+
217
+ window.RiverFlow.setToastMode = function(mode) {
218
+ var modes = ['light', 'dark', 'neon', 'glass', 'gradient', 'minimal'];
219
+ if (modes.indexOf(mode) !== -1) {
220
+ currentMode = mode;
221
+ }
222
+ };
223
+
224
+ window.RiverFlow.setToastAnimation = function(anim) {
225
+ var anims = ['up-down', 'down-up', 'left-right', 'right-left', 'zoom', 'bounce'];
226
+ if (anims.indexOf(anim) !== -1) {
227
+ currentAnim = anim;
228
+ }
229
+ };
230
+
231
+ window.RiverFlow.setToastPosition = function(pos) {
232
+ var positions = ['bottom-right', 'bottom-left', 'top-right', 'top-left', 'top-center', 'bottom-center'];
233
+ if (positions.indexOf(pos) !== -1) {
234
+ currentPosition = pos;
235
+ container.className = 'rf-toast-container ' + pos;
236
+ }
237
+ };
238
+
239
+ window.RiverFlow.setToastDuration = function(ms) {
240
+ if (typeof ms === 'number' && ms >= 0) {
241
+ DEFAULTS.duration = ms;
242
+ }
243
+ };
244
+
245
+ window.RiverFlow.bindToast = function(config) {
246
+ if (!config || !config.id || !config.message) return;
247
+
248
+ var element = document.getElementById(config.id);
249
+ if (!element) return;
250
+
251
+ var options = {
252
+ type: config.type || 'default',
253
+ mode: config.mode || currentMode,
254
+ animation: config.animation || currentAnim,
255
+ duration: config.duration || DEFAULTS.duration,
256
+ closeable: config.closeable !== undefined ? config.closeable : DEFAULTS.closeable
257
+ };
258
+
259
+ var handler = function(e) {
260
+ window.RiverFlow.toast(config.message, options);
261
+ };
262
+
263
+ element.addEventListener('click', handler);
264
+
265
+ clickBindings.push({
266
+ id: config.id,
267
+ element: element,
268
+ handler: handler,
269
+ config: config
270
+ });
271
+ };
272
+
273
+ window.RiverFlow.unbindToast = function(id) {
274
+ for (var i = clickBindings.length - 1; i >= 0; i--) {
275
+ if (clickBindings[i].id === id) {
276
+ clickBindings[i].element.removeEventListener('click', clickBindings[i].handler);
277
+ clickBindings.splice(i, 1);
278
+ }
279
+ }
280
+ };
281
+
282
+ window.RiverFlow.unbindAllToasts = function() {
283
+ for (var i = clickBindings.length - 1; i >= 0; i--) {
284
+ clickBindings[i].element.removeEventListener('click', clickBindings[i].handler);
285
+ }
286
+ clickBindings = [];
287
+ };
288
+
289
+ window.toast = window.RiverFlow.toast;
290
+ window.toastSuccess = window.RiverFlow.toastSuccess;
291
+ window.toastWarning = window.RiverFlow.toastWarning;
292
+ window.toastError = window.RiverFlow.toastError;
293
+ window.toastInfo = window.RiverFlow.toastInfo;
294
+ window.setToastMode = window.RiverFlow.setToastMode;
295
+ window.setToastAnimation = window.RiverFlow.setToastAnimation;
296
+ window.setToastPosition = window.RiverFlow.setToastPosition;
297
+ window.setToastDuration = window.RiverFlow.setToastDuration;
298
+ window.bindToast = window.RiverFlow.bindToast;
299
+ window.unbindToast = window.RiverFlow.unbindToast;
300
+ window.unbindAllToasts = window.RiverFlow.unbindAllToasts;
301
+
302
+ })();