@fluixi-ui/toast 0.2.0-alpha.18 → 0.2.0-alpha.20
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/dist/index.js +2 -11
- package/dist/toast.js +508 -366
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +5 -5
package/dist/toast.js
CHANGED
|
@@ -1,390 +1,532 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createComponent, createNativeElement, delegateEvents, handleRef, holeContent, holeEnd, holeScope, insert, mergeProps, splitProps, spread, templateNode } from "@fluixi/dom";
|
|
2
|
+
import { createEffect, createMemo, createSignal, onCleanup } from "@fluixi/reactive/signal";
|
|
3
3
|
import { fxProps } from "@fluixi-ui/fx";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { For, Show, onMount, useRef } from "@fluixi/core";
|
|
5
|
+
import { composeEventHandlers, createId, createSafeContext } from "@fluixi-ui/kit";
|
|
6
6
|
import { Portal } from "@fluixi-ui/primitives";
|
|
7
|
-
|
|
7
|
+
//#region src/toast.tsx
|
|
8
|
+
var _fxTmpl$0 = "<div data-toast-content=\"\"><!--fx--><!--fx/--><!--fx--><!--fx/--></div>";
|
|
8
9
|
delegateEvents(["click", "keydown"]);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
var PLACEMENTS = [
|
|
11
|
+
"top-left",
|
|
12
|
+
"top-center",
|
|
13
|
+
"top-right",
|
|
14
|
+
"bottom-left",
|
|
15
|
+
"bottom-center",
|
|
16
|
+
"bottom-right"
|
|
16
17
|
];
|
|
18
|
+
/**
|
|
19
|
+
* Create an isolated toast store: the reactive engine behind a region. Owns the
|
|
20
|
+
* toast list and per-toast auto-dismiss timers (pausable for hover). Most apps
|
|
21
|
+
* use the default {@link toast} singleton; create a store for scoped or testable
|
|
22
|
+
* setups.
|
|
23
|
+
*/
|
|
17
24
|
function createToastStore(config = {}) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
25
|
+
const [toasts, setToasts] = createSignal([]);
|
|
26
|
+
const timers = /* @__PURE__ */ new Map();
|
|
27
|
+
const defaultDuration = config.duration ?? 4e3;
|
|
28
|
+
const defaultPlacement = config.defaultPlacement ?? "bottom-right";
|
|
29
|
+
const maxVisible = config.maxVisible ?? 3;
|
|
30
|
+
const clearTimer = (id) => {
|
|
31
|
+
const timer = timers.get(id);
|
|
32
|
+
if (timer?.handle) clearTimeout(timer.handle);
|
|
33
|
+
};
|
|
34
|
+
const schedule = (id, ms) => {
|
|
35
|
+
if (!Number.isFinite(ms) || ms <= 0) return;
|
|
36
|
+
const timer = {
|
|
37
|
+
handle: void 0,
|
|
38
|
+
remaining: ms,
|
|
39
|
+
startedAt: Date.now()
|
|
40
|
+
};
|
|
41
|
+
timer.handle = setTimeout(() => dismiss(id), ms);
|
|
42
|
+
timers.set(id, timer);
|
|
43
|
+
};
|
|
44
|
+
const dismiss = (id) => {
|
|
45
|
+
clearTimer(id);
|
|
46
|
+
timers.delete(id);
|
|
47
|
+
const record = toasts().find((toast) => toast.id === id);
|
|
48
|
+
setToasts((list) => list.filter((toast) => toast.id !== id));
|
|
49
|
+
record?.onDismiss?.(record);
|
|
50
|
+
};
|
|
51
|
+
const add = (options) => {
|
|
52
|
+
const id = createId("toast");
|
|
53
|
+
const type = options.type ?? "default";
|
|
54
|
+
const duration = options.duration ?? (type === "loading" ? 0 : defaultDuration);
|
|
55
|
+
const record = {
|
|
56
|
+
...options,
|
|
57
|
+
id,
|
|
58
|
+
type,
|
|
59
|
+
placement: options.placement ?? defaultPlacement,
|
|
60
|
+
duration,
|
|
61
|
+
dismissible: options.dismissible ?? true,
|
|
62
|
+
createdAt: Date.now()
|
|
63
|
+
};
|
|
64
|
+
setToasts((list) => [...list, record]);
|
|
65
|
+
schedule(id, duration);
|
|
66
|
+
return id;
|
|
67
|
+
};
|
|
68
|
+
const update = (id, options) => {
|
|
69
|
+
let next;
|
|
70
|
+
setToasts((list) => list.map((toast) => {
|
|
71
|
+
if (toast.id !== id) return toast;
|
|
72
|
+
next = {
|
|
73
|
+
...toast,
|
|
74
|
+
...options,
|
|
75
|
+
id: toast.id,
|
|
76
|
+
createdAt: toast.createdAt
|
|
77
|
+
};
|
|
78
|
+
return next;
|
|
79
|
+
}));
|
|
80
|
+
if (!next) return;
|
|
81
|
+
clearTimer(id);
|
|
82
|
+
timers.delete(id);
|
|
83
|
+
schedule(id, next.duration);
|
|
84
|
+
};
|
|
85
|
+
const pause = () => {
|
|
86
|
+
const now = Date.now();
|
|
87
|
+
for (const timer of timers.values()) {
|
|
88
|
+
if (!timer.handle) continue;
|
|
89
|
+
clearTimeout(timer.handle);
|
|
90
|
+
timer.remaining -= now - timer.startedAt;
|
|
91
|
+
timer.handle = void 0;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const resume = () => {
|
|
95
|
+
const now = Date.now();
|
|
96
|
+
for (const [id, timer] of timers) {
|
|
97
|
+
if (timer.handle) continue;
|
|
98
|
+
timer.startedAt = now;
|
|
99
|
+
timer.handle = setTimeout(() => dismiss(id), Math.max(0, timer.remaining));
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const clear = () => {
|
|
103
|
+
for (const id of timers.keys()) clearTimer(id);
|
|
104
|
+
timers.clear();
|
|
105
|
+
setToasts([]);
|
|
106
|
+
};
|
|
107
|
+
const promise = (p, messages, options = {}) => {
|
|
108
|
+
const id = add({
|
|
109
|
+
...options,
|
|
110
|
+
type: "loading",
|
|
111
|
+
title: messages.loading,
|
|
112
|
+
duration: 0
|
|
113
|
+
});
|
|
114
|
+
const resolveMessage = (message, value) => typeof message === "function" ? message(value) : message;
|
|
115
|
+
p.then((value) => update(id, {
|
|
116
|
+
type: "success",
|
|
117
|
+
title: resolveMessage(messages.success, value),
|
|
118
|
+
duration: options.duration ?? defaultDuration
|
|
119
|
+
}), (reason) => update(id, {
|
|
120
|
+
type: "error",
|
|
121
|
+
title: resolveMessage(messages.error, reason),
|
|
122
|
+
duration: options.duration ?? defaultDuration
|
|
123
|
+
}));
|
|
124
|
+
return p;
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
toasts,
|
|
128
|
+
add,
|
|
129
|
+
update,
|
|
130
|
+
dismiss,
|
|
131
|
+
clear,
|
|
132
|
+
promise,
|
|
133
|
+
pause,
|
|
134
|
+
resume,
|
|
135
|
+
maxVisible
|
|
136
|
+
};
|
|
111
137
|
}
|
|
112
|
-
|
|
138
|
+
var defaultStore = createToastStore();
|
|
113
139
|
function shortcut(type) {
|
|
114
|
-
|
|
140
|
+
return (message, options = {}) => defaultStore.add({
|
|
141
|
+
...options,
|
|
142
|
+
title: message,
|
|
143
|
+
type
|
|
144
|
+
});
|
|
115
145
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
);
|
|
131
|
-
|
|
146
|
+
/**
|
|
147
|
+
* The default toast API — fire a notification from anywhere.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```tsx
|
|
151
|
+
* import { toast, Toaster } from '@fluixi-ui/toast';
|
|
152
|
+
*
|
|
153
|
+
* // once, near the app root:
|
|
154
|
+
* <Toaster />
|
|
155
|
+
*
|
|
156
|
+
* // anywhere:
|
|
157
|
+
* toast.success('Saved');
|
|
158
|
+
* toast.error('Upload failed', { placement: 'top-center' });
|
|
159
|
+
* const id = toast.loading('Uploading…');
|
|
160
|
+
* toast.update(id, { type: 'success', title: 'Uploaded', duration: 4000 });
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
var toast = Object.assign((options) => defaultStore.add(options), {
|
|
164
|
+
success: shortcut("success"),
|
|
165
|
+
error: shortcut("error"),
|
|
166
|
+
warning: shortcut("warning"),
|
|
167
|
+
info: shortcut("info"),
|
|
168
|
+
loading: shortcut("loading"),
|
|
169
|
+
promise: defaultStore.promise,
|
|
170
|
+
update: defaultStore.update,
|
|
171
|
+
dismiss: defaultStore.dismiss,
|
|
172
|
+
clear: defaultStore.clear,
|
|
173
|
+
store: defaultStore
|
|
174
|
+
});
|
|
175
|
+
var [ToastProvider, useToastContext] = createSafeContext("Toast");
|
|
176
|
+
/**
|
|
177
|
+
* Renders a store's toasts into fixed corner stacks (one per placement in use).
|
|
178
|
+
* Mount once near the app root. Hovering a stack pauses its auto-dismiss timers.
|
|
179
|
+
*/
|
|
132
180
|
function Toaster(props) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
181
|
+
const [local, others] = splitProps(props, [
|
|
182
|
+
"store",
|
|
183
|
+
"label",
|
|
184
|
+
"fx",
|
|
185
|
+
"style"
|
|
186
|
+
]);
|
|
187
|
+
const store = local.store ?? defaultStore;
|
|
188
|
+
const byPlacement = (placement) => store.toasts().filter((toast) => toast.placement === placement).slice(-store.maxVisible);
|
|
189
|
+
onMount(() => {
|
|
190
|
+
const onKeyDown = (event) => {
|
|
191
|
+
if (event.key !== "F6") return;
|
|
192
|
+
const first = document.querySelector("[data-toast]");
|
|
193
|
+
if (first) {
|
|
194
|
+
event.preventDefault();
|
|
195
|
+
first.focus();
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
document.addEventListener("keydown", onKeyDown);
|
|
199
|
+
onCleanup(() => document.removeEventListener("keydown", onKeyDown));
|
|
200
|
+
});
|
|
201
|
+
const onRegionKeyDown = (event) => {
|
|
202
|
+
const active = document.activeElement;
|
|
203
|
+
const region = active?.closest("[data-toast-viewport]");
|
|
204
|
+
if (!region) return;
|
|
205
|
+
const items = [...region.querySelectorAll("[data-toast]")];
|
|
206
|
+
const index = items.indexOf(active);
|
|
207
|
+
if (index === -1) return;
|
|
208
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
209
|
+
event.preventDefault();
|
|
210
|
+
const step = event.key === "ArrowDown" ? 1 : -1;
|
|
211
|
+
items[Math.min(Math.max(index + step, 0), items.length - 1)]?.focus();
|
|
212
|
+
} else if (event.key === "Escape") {
|
|
213
|
+
event.preventDefault();
|
|
214
|
+
const record = byPlacement(region.dataset.placement)[index];
|
|
215
|
+
if (record) store.dismiss(record.id);
|
|
216
|
+
const remaining = region.querySelectorAll("[data-toast]");
|
|
217
|
+
remaining[Math.min(index, remaining.length - 1)]?.focus();
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
const ref = useRef(null);
|
|
221
|
+
createEffect(() => {
|
|
222
|
+
if (store.toasts().length === 0 && ref.current) ref.current.remove();
|
|
223
|
+
});
|
|
224
|
+
return createMemo(() => createComponent(Show, {
|
|
225
|
+
get when() {
|
|
226
|
+
return store.toasts().length > 0;
|
|
227
|
+
},
|
|
228
|
+
get fallback() {
|
|
229
|
+
return null;
|
|
230
|
+
},
|
|
231
|
+
get children() {
|
|
232
|
+
return createMemo(() => createComponent(Portal, {
|
|
233
|
+
get ref() {
|
|
234
|
+
return ref;
|
|
235
|
+
},
|
|
236
|
+
get children() {
|
|
237
|
+
return createMemo(() => createComponent(For, {
|
|
238
|
+
get each() {
|
|
239
|
+
return () => PLACEMENTS;
|
|
240
|
+
},
|
|
241
|
+
get children() {
|
|
242
|
+
return (placement) => createMemo(() => createComponent(Show, {
|
|
243
|
+
get when() {
|
|
244
|
+
return () => byPlacement(placement).length > 0;
|
|
245
|
+
},
|
|
246
|
+
get children() {
|
|
247
|
+
return (() => {
|
|
248
|
+
const _el$ = createNativeElement("ol");
|
|
249
|
+
spread({
|
|
250
|
+
element: _el$,
|
|
251
|
+
props: mergeProps(fxProps(() => local.fx, () => local.style), others, {
|
|
252
|
+
"data-toast-viewport": "",
|
|
253
|
+
"data-placement": placement,
|
|
254
|
+
role: "region",
|
|
255
|
+
"aria-label": () => local.label ?? "Notifications",
|
|
256
|
+
tabindex: -1,
|
|
257
|
+
onPointerEnter: () => store.pause(),
|
|
258
|
+
onPointerLeave: () => store.resume(),
|
|
259
|
+
onKeyDown: onRegionKeyDown
|
|
260
|
+
})
|
|
261
|
+
});
|
|
262
|
+
insert(_el$, createMemo(() => createComponent(For, {
|
|
263
|
+
get each() {
|
|
264
|
+
return () => byPlacement(placement);
|
|
265
|
+
},
|
|
266
|
+
get by() {
|
|
267
|
+
return (record) => record.id;
|
|
268
|
+
},
|
|
269
|
+
get children() {
|
|
270
|
+
return (record) => createMemo(() => createComponent(ToastItem, {
|
|
271
|
+
get record() {
|
|
272
|
+
return record;
|
|
273
|
+
},
|
|
274
|
+
get store() {
|
|
275
|
+
return store;
|
|
276
|
+
}
|
|
277
|
+
}));
|
|
278
|
+
}
|
|
279
|
+
})), null);
|
|
280
|
+
return _el$;
|
|
281
|
+
})();
|
|
282
|
+
}
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
}));
|
|
288
|
+
}
|
|
289
|
+
}));
|
|
213
290
|
}
|
|
291
|
+
/** One rendered toast: establishes context, then renders {@link Toast}. */
|
|
214
292
|
function ToastItem(props) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
293
|
+
return createMemo(() => createComponent(ToastProvider, {
|
|
294
|
+
get value() {
|
|
295
|
+
return {
|
|
296
|
+
record: props.record,
|
|
297
|
+
dismiss: () => props.store.dismiss(props.record().id)
|
|
298
|
+
};
|
|
299
|
+
},
|
|
300
|
+
get children() {
|
|
301
|
+
return createMemo(() => createComponent(Toast, {}));
|
|
302
|
+
}
|
|
303
|
+
}));
|
|
220
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* A single toast. Body resolution: explicit `children`, else the record's custom
|
|
307
|
+
* `render`, else the default title/description/close.
|
|
308
|
+
*/
|
|
221
309
|
function Toast(props) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
310
|
+
const ctx = useToastContext();
|
|
311
|
+
const [local, others] = splitProps(props, [
|
|
312
|
+
"children",
|
|
313
|
+
"ref",
|
|
314
|
+
"fx",
|
|
315
|
+
"style"
|
|
316
|
+
]);
|
|
317
|
+
const record = ctx.record;
|
|
318
|
+
const placement = record().placement;
|
|
319
|
+
const dir = placement.endsWith("left") ? -1 : placement.endsWith("right") ? 1 : 0;
|
|
320
|
+
const THRESHOLD = 60;
|
|
321
|
+
let el;
|
|
322
|
+
let startX = 0;
|
|
323
|
+
let dragging = false;
|
|
324
|
+
const onPointerDown = (event) => {
|
|
325
|
+
if (event.button !== 0 || !el) return;
|
|
326
|
+
if (event.target.closest("button,a,input,textarea,select")) return;
|
|
327
|
+
dragging = true;
|
|
328
|
+
startX = event.clientX;
|
|
329
|
+
el.setPointerCapture?.(event.pointerId);
|
|
330
|
+
el.setAttribute("data-swiping", "");
|
|
331
|
+
};
|
|
332
|
+
const constrain = (dx) => dir > 0 ? Math.max(0, dx) : dir < 0 ? Math.min(0, dx) : dx;
|
|
333
|
+
const onPointerMove = (event) => {
|
|
334
|
+
if (!dragging || !el) return;
|
|
335
|
+
const dx = constrain(event.clientX - startX);
|
|
336
|
+
el.style.setProperty("--flx-ui-toast-swipe", `${dx}px`);
|
|
337
|
+
el.style.opacity = `${Math.max(.35, 1 - Math.abs(dx) / 200)}`;
|
|
338
|
+
};
|
|
339
|
+
const onPointerUp = (event) => {
|
|
340
|
+
if (!dragging || !el) return;
|
|
341
|
+
dragging = false;
|
|
342
|
+
el.removeAttribute("data-swiping");
|
|
343
|
+
const dx = constrain(event.clientX - startX);
|
|
344
|
+
if (Math.abs(dx) >= THRESHOLD) {
|
|
345
|
+
el.setAttribute("data-swiped-out", "");
|
|
346
|
+
el.style.setProperty("--flx-ui-toast-swipe", `${(dx < 0 ? -1 : 1) * 480}px`);
|
|
347
|
+
el.style.opacity = "0";
|
|
348
|
+
setTimeout(() => ctx.dismiss(), 150);
|
|
349
|
+
} else {
|
|
350
|
+
el.style.removeProperty("--flx-ui-toast-swipe");
|
|
351
|
+
el.style.removeProperty("opacity");
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
const setRef = (node) => {
|
|
355
|
+
el = node;
|
|
356
|
+
const onEntered = () => {
|
|
357
|
+
node.setAttribute("data-entered", "");
|
|
358
|
+
node.removeEventListener("animationend", onEntered);
|
|
359
|
+
};
|
|
360
|
+
node.addEventListener("animationend", onEntered);
|
|
361
|
+
onCleanup(() => node.removeEventListener("animationend", onEntered));
|
|
362
|
+
handleRef(local.ref, node);
|
|
363
|
+
};
|
|
364
|
+
return (() => {
|
|
365
|
+
const _el$ = createNativeElement("li");
|
|
366
|
+
spread({
|
|
367
|
+
element: _el$,
|
|
368
|
+
props: mergeProps(fxProps(() => local.fx, () => local.style), others, {
|
|
369
|
+
ref: setRef,
|
|
370
|
+
"data-toast": "",
|
|
371
|
+
"data-type": () => record().type,
|
|
372
|
+
role: () => record().type === "error" ? "alert" : "status",
|
|
373
|
+
"aria-live": () => record().type === "error" ? "assertive" : "polite",
|
|
374
|
+
"aria-atomic": "true",
|
|
375
|
+
tabindex: -1,
|
|
376
|
+
onPointerDown,
|
|
377
|
+
onPointerMove,
|
|
378
|
+
onPointerUp
|
|
379
|
+
})
|
|
380
|
+
});
|
|
381
|
+
insert(_el$, createMemo(() => createComponent(Show, {
|
|
382
|
+
get when() {
|
|
383
|
+
return () => local.children ?? record().render;
|
|
384
|
+
},
|
|
385
|
+
get fallback() {
|
|
386
|
+
return createMemo(() => createComponent(ToastDefaultBody, {}));
|
|
387
|
+
},
|
|
388
|
+
get children() {
|
|
389
|
+
return () => local.children ?? record().render(record());
|
|
390
|
+
}
|
|
391
|
+
})), null);
|
|
392
|
+
return _el$;
|
|
393
|
+
})();
|
|
286
394
|
}
|
|
287
395
|
function ToastDefaultBody() {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
396
|
+
const record = useToastContext().record;
|
|
397
|
+
return [(() => {
|
|
398
|
+
const _el$ = templateNode(_fxTmpl$0, "div", true);
|
|
399
|
+
const _n$0 = _el$.firstChild;
|
|
400
|
+
const _n$1 = holeEnd(_n$0);
|
|
401
|
+
const _n$2 = _n$1.nextSibling;
|
|
402
|
+
const _n$3 = holeEnd(_n$2);
|
|
403
|
+
insert(_el$, holeScope(_n$0, () => createMemo(() => createComponent(Show, {
|
|
404
|
+
get when() {
|
|
405
|
+
return () => record().title;
|
|
406
|
+
},
|
|
407
|
+
get children() {
|
|
408
|
+
return createMemo(() => createComponent(ToastTitle, { get children() {
|
|
409
|
+
return () => record().title;
|
|
410
|
+
} }));
|
|
411
|
+
}
|
|
412
|
+
}))), _n$1, holeContent(_n$0, _n$1));
|
|
413
|
+
insert(_el$, holeScope(_n$2, () => createMemo(() => createComponent(Show, {
|
|
414
|
+
get when() {
|
|
415
|
+
return () => record().description;
|
|
416
|
+
},
|
|
417
|
+
get children() {
|
|
418
|
+
return createMemo(() => createComponent(ToastDescription, { get children() {
|
|
419
|
+
return () => record().description;
|
|
420
|
+
} }));
|
|
421
|
+
}
|
|
422
|
+
}))), _n$3, holeContent(_n$2, _n$3));
|
|
423
|
+
return _el$;
|
|
424
|
+
})(), createMemo(() => createComponent(Show, {
|
|
425
|
+
get when() {
|
|
426
|
+
return () => record().dismissible;
|
|
427
|
+
},
|
|
428
|
+
get children() {
|
|
429
|
+
return createMemo(() => createComponent(ToastClose, {}));
|
|
430
|
+
}
|
|
431
|
+
}))];
|
|
316
432
|
}
|
|
433
|
+
/** The toast's headline. */
|
|
317
434
|
function ToastTitle(props) {
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
435
|
+
const [local, others] = splitProps(props, [
|
|
436
|
+
"children",
|
|
437
|
+
"fx",
|
|
438
|
+
"style"
|
|
439
|
+
]);
|
|
440
|
+
return (() => {
|
|
441
|
+
const _el$ = createNativeElement("div");
|
|
442
|
+
spread({
|
|
443
|
+
element: _el$,
|
|
444
|
+
props: mergeProps(fxProps(() => local.fx, () => local.style), others, { "data-toast-title": "" })
|
|
445
|
+
});
|
|
446
|
+
insert(_el$, local.children, null);
|
|
447
|
+
return _el$;
|
|
448
|
+
})();
|
|
328
449
|
}
|
|
450
|
+
/** Supporting detail under the title. */
|
|
329
451
|
function ToastDescription(props) {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
452
|
+
const [local, others] = splitProps(props, [
|
|
453
|
+
"children",
|
|
454
|
+
"fx",
|
|
455
|
+
"style"
|
|
456
|
+
]);
|
|
457
|
+
return (() => {
|
|
458
|
+
const _el$ = createNativeElement("div");
|
|
459
|
+
spread({
|
|
460
|
+
element: _el$,
|
|
461
|
+
props: mergeProps(fxProps(() => local.fx, () => local.style), others, { "data-toast-description": "" })
|
|
462
|
+
});
|
|
463
|
+
insert(_el$, local.children, null);
|
|
464
|
+
return _el$;
|
|
465
|
+
})();
|
|
340
466
|
}
|
|
467
|
+
/** Dismisses the toast. */
|
|
341
468
|
function ToastClose(props) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
469
|
+
const ctx = useToastContext();
|
|
470
|
+
const [local, others] = splitProps(props, [
|
|
471
|
+
"onClick",
|
|
472
|
+
"children",
|
|
473
|
+
"ref",
|
|
474
|
+
"fx",
|
|
475
|
+
"style"
|
|
476
|
+
]);
|
|
477
|
+
return (() => {
|
|
478
|
+
const _el$ = createNativeElement("button");
|
|
479
|
+
spread({
|
|
480
|
+
element: _el$,
|
|
481
|
+
props: mergeProps(fxProps(() => local.fx, () => local.style), others, {
|
|
482
|
+
ref: (node) => handleRef(local.ref, node),
|
|
483
|
+
type: "button",
|
|
484
|
+
"data-toast-close": "",
|
|
485
|
+
"aria-label": "Dismiss",
|
|
486
|
+
onClick: composeEventHandlers([local.onClick, () => ctx.dismiss()])
|
|
487
|
+
})
|
|
488
|
+
});
|
|
489
|
+
insert(_el$, createMemo(() => createComponent(Show, {
|
|
490
|
+
get when() {
|
|
491
|
+
return () => local.children;
|
|
492
|
+
},
|
|
493
|
+
get fallback() {
|
|
494
|
+
return "✕";
|
|
495
|
+
},
|
|
496
|
+
get children() {
|
|
497
|
+
return local.children;
|
|
498
|
+
}
|
|
499
|
+
})), null);
|
|
500
|
+
return _el$;
|
|
501
|
+
})();
|
|
362
502
|
}
|
|
503
|
+
/** An action button inside a toast (e.g. "Undo"). */
|
|
363
504
|
function ToastAction(props) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
505
|
+
const ctx = useToastContext();
|
|
506
|
+
const [local, others] = splitProps(props, [
|
|
507
|
+
"onClick",
|
|
508
|
+
"dismissOnClick",
|
|
509
|
+
"children",
|
|
510
|
+
"ref",
|
|
511
|
+
"fx",
|
|
512
|
+
"style"
|
|
513
|
+
]);
|
|
514
|
+
return (() => {
|
|
515
|
+
const _el$ = createNativeElement("button");
|
|
516
|
+
spread({
|
|
517
|
+
element: _el$,
|
|
518
|
+
props: mergeProps(fxProps(() => local.fx, () => local.style), others, {
|
|
519
|
+
ref: (node) => handleRef(local.ref, node),
|
|
520
|
+
type: "button",
|
|
521
|
+
"data-toast-action": "",
|
|
522
|
+
onClick: composeEventHandlers([local.onClick, () => {
|
|
523
|
+
if (local.dismissOnClick !== false) ctx.dismiss();
|
|
524
|
+
}])
|
|
525
|
+
})
|
|
526
|
+
});
|
|
527
|
+
insert(_el$, local.children, null);
|
|
528
|
+
return _el$;
|
|
529
|
+
})();
|
|
380
530
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
ToastAction,
|
|
384
|
-
ToastClose,
|
|
385
|
-
ToastDescription,
|
|
386
|
-
ToastTitle,
|
|
387
|
-
Toaster,
|
|
388
|
-
createToastStore,
|
|
389
|
-
toast
|
|
390
|
-
};
|
|
531
|
+
//#endregion
|
|
532
|
+
export { Toast, ToastAction, ToastClose, ToastDescription, ToastTitle, Toaster, createToastStore, toast };
|