react-snackbar-glass 1.1.0 → 1.3.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/CHANGELOG.md +33 -0
- package/README.md +79 -1
- package/dist/index.cjs +138 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +278 -2
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +111 -3
- package/dist/index.d.ts +111 -3
- package/dist/index.js +138 -32
- package/dist/index.js.map +1 -1
- package/dist/styles.css +278 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,26 @@ type SnackbarTone = 'glass' | 'solid';
|
|
|
13
13
|
* mini style, `lg` is an editorial width for richer content.
|
|
14
14
|
*/
|
|
15
15
|
type SnackbarSize = 'xs' | 'sm' | 'md' | 'lg';
|
|
16
|
+
/**
|
|
17
|
+
* How much room a snackbar takes.
|
|
18
|
+
*
|
|
19
|
+
* - `card` — full card: title, message, action, countdown hairline.
|
|
20
|
+
* - `compact` — fully rounded single-line pill.
|
|
21
|
+
* - `inline` — message-only status line: content width, ~38px tall, never
|
|
22
|
+
* wraps and never shows a title or countdown.
|
|
23
|
+
*/
|
|
24
|
+
type SnackbarLayout = 'card' | 'compact' | 'inline';
|
|
25
|
+
/**
|
|
26
|
+
* Enter/exit animation preset.
|
|
27
|
+
*
|
|
28
|
+
* - `slide` — spring slide from the edge with a soft blur (default).
|
|
29
|
+
* - `fade` — pure opacity cross-fade.
|
|
30
|
+
* - `scale` — zoom in/out from the center.
|
|
31
|
+
* - `pop` — bouncy overshoot.
|
|
32
|
+
* - `flip` — 3D flip on the X axis.
|
|
33
|
+
* - `none` — appears and disappears instantly.
|
|
34
|
+
*/
|
|
35
|
+
type SnackbarAnimation = 'slide' | 'fade' | 'scale' | 'pop' | 'flip' | 'none';
|
|
16
36
|
type SnackbarPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
|
|
17
37
|
type SnackbarTheme = 'light' | 'dark' | 'auto';
|
|
18
38
|
type SnackbarPhase = 'visible' | 'exiting';
|
|
@@ -59,6 +79,30 @@ interface SnackbarOptions {
|
|
|
59
79
|
dismissible?: boolean;
|
|
60
80
|
/** Show the countdown hairline. @default true */
|
|
61
81
|
progress?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Single-line pill: no title, no countdown hairline and tighter padding.
|
|
84
|
+
* Ideal for high-frequency, low-stakes messages.
|
|
85
|
+
*
|
|
86
|
+
* Sugar for `layout: 'compact'`.
|
|
87
|
+
* @default false
|
|
88
|
+
*/
|
|
89
|
+
compact?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* How much room the snackbar takes. `compact: true` is sugar for
|
|
92
|
+
* `layout: 'compact'`; `toast.single()` uses `'inline'`.
|
|
93
|
+
* @default 'card'
|
|
94
|
+
*/
|
|
95
|
+
layout?: SnackbarLayout;
|
|
96
|
+
/**
|
|
97
|
+
* Enter/exit animation preset. Applies to both phases unless
|
|
98
|
+
* `enterAnimation` / `exitAnimation` override it.
|
|
99
|
+
* @default 'slide'
|
|
100
|
+
*/
|
|
101
|
+
animation?: SnackbarAnimation;
|
|
102
|
+
/** Enter animation for this snackbar only. */
|
|
103
|
+
enterAnimation?: SnackbarAnimation;
|
|
104
|
+
/** Exit animation for this snackbar only. */
|
|
105
|
+
exitAnimation?: SnackbarAnimation;
|
|
62
106
|
/** @default 'glass' */
|
|
63
107
|
tone?: SnackbarTone;
|
|
64
108
|
/** @default 'md' */
|
|
@@ -84,6 +128,11 @@ interface SnackbarRecord {
|
|
|
84
128
|
readonly action: SnackbarAction | null;
|
|
85
129
|
readonly dismissible: boolean;
|
|
86
130
|
readonly progress: boolean;
|
|
131
|
+
readonly compact: boolean;
|
|
132
|
+
readonly layout: SnackbarLayout;
|
|
133
|
+
readonly animation: SnackbarAnimation;
|
|
134
|
+
readonly enterAnimation: SnackbarAnimation;
|
|
135
|
+
readonly exitAnimation: SnackbarAnimation;
|
|
87
136
|
readonly className: string | undefined;
|
|
88
137
|
readonly style: CSSProperties | undefined;
|
|
89
138
|
readonly createdAt: number;
|
|
@@ -102,6 +151,16 @@ interface SnackbarStoreConfig {
|
|
|
102
151
|
dismissible?: boolean;
|
|
103
152
|
/** @default true */
|
|
104
153
|
progress?: boolean;
|
|
154
|
+
/** Default `compact` value for new snackbars. @default false */
|
|
155
|
+
compact?: boolean;
|
|
156
|
+
/** Default layout for new snackbars. @default 'card' */
|
|
157
|
+
layout?: SnackbarLayout;
|
|
158
|
+
/** Default enter/exit animation. @default 'slide' */
|
|
159
|
+
animation?: SnackbarAnimation;
|
|
160
|
+
/** Default enter animation; falls back to `animation`. */
|
|
161
|
+
enterAnimation?: SnackbarAnimation;
|
|
162
|
+
/** Default exit animation; falls back to `animation`. */
|
|
163
|
+
exitAnimation?: SnackbarAnimation;
|
|
105
164
|
/** @default 'glass' */
|
|
106
165
|
tone?: SnackbarTone;
|
|
107
166
|
/** Default size for new snackbars. @default 'md' */
|
|
@@ -114,6 +173,11 @@ interface ResolvedSnackbarStoreConfig {
|
|
|
114
173
|
duration: number;
|
|
115
174
|
dismissible: boolean;
|
|
116
175
|
progress: boolean;
|
|
176
|
+
compact: boolean;
|
|
177
|
+
layout: SnackbarLayout;
|
|
178
|
+
animation: SnackbarAnimation;
|
|
179
|
+
enterAnimation: SnackbarAnimation;
|
|
180
|
+
exitAnimation: SnackbarAnimation;
|
|
117
181
|
tone: SnackbarTone;
|
|
118
182
|
size: SnackbarSize;
|
|
119
183
|
maxVisible: number;
|
|
@@ -145,8 +209,15 @@ interface SnackbarStore {
|
|
|
145
209
|
/** Internal-ish lifecycle hook, called by the viewport after the exit animation. */
|
|
146
210
|
notifyExited(id: string): void;
|
|
147
211
|
setPageHidden(hidden: boolean): void;
|
|
212
|
+
/** Whether the stack is collapsed into a single summary pill. */
|
|
213
|
+
getMinimized(): boolean;
|
|
214
|
+
getServerMinimized(): boolean;
|
|
215
|
+
/** Collapse (`true`) or expand (`false`) the visible stack. */
|
|
216
|
+
setMinimized(minimized: boolean): void;
|
|
148
217
|
}
|
|
149
218
|
type SnackbarPresetOptions = Omit<SnackbarOptions, 'message' | 'variant'>;
|
|
219
|
+
/** `toast.single()` options: everything except the forced inline layout. */
|
|
220
|
+
type ToastSingleOptions = Omit<SnackbarOptions, 'message' | 'layout'>;
|
|
150
221
|
interface SnackbarApi {
|
|
151
222
|
/** Queue a fully customised snackbar and return its id. */
|
|
152
223
|
show(options: SnackbarOptions): string;
|
|
@@ -160,7 +231,18 @@ interface SnackbarApi {
|
|
|
160
231
|
neutral(message: ReactNode, options?: SnackbarPresetOptions): string;
|
|
161
232
|
loading(message: ReactNode, options?: SnackbarPresetOptions): string;
|
|
162
233
|
custom(message: ReactNode, options?: SnackbarPresetOptions): string;
|
|
234
|
+
/**
|
|
235
|
+
* Message-only status line (`layout: 'inline'`): content width, one line,
|
|
236
|
+
* no title and no countdown. Ideal for instant feedback such as
|
|
237
|
+
* “Position set to top-center”.
|
|
238
|
+
*/
|
|
239
|
+
single(message: ReactNode, options?: ToastSingleOptions): string;
|
|
163
240
|
promise<T>(promise: Promise<T>, messages: SnackbarPromiseOptions<T>, options?: SnackbarOptions): Promise<T>;
|
|
241
|
+
/** Collapse the visible stack into one summary pill. */
|
|
242
|
+
minimize(): void;
|
|
243
|
+
/** Restore the full stack after `minimize()`. */
|
|
244
|
+
expand(): void;
|
|
245
|
+
isMinimized(): boolean;
|
|
164
246
|
/** Escape hatch for scheduling, subscribing or advanced updates. */
|
|
165
247
|
store: SnackbarStore;
|
|
166
248
|
}
|
|
@@ -187,7 +269,18 @@ interface ToastApi {
|
|
|
187
269
|
neutral(message: ReactNode, options?: ToastPresetOptions): string;
|
|
188
270
|
loading(message: ReactNode, options?: ToastPresetOptions): string;
|
|
189
271
|
custom(message: ReactNode, options?: ToastPresetOptions): string;
|
|
272
|
+
/**
|
|
273
|
+
* Message-only status line (`layout: 'inline'`): content width, one line,
|
|
274
|
+
* no title and no countdown. Ideal for instant feedback such as
|
|
275
|
+
* “Position set to top-center”.
|
|
276
|
+
*/
|
|
277
|
+
single(message: ReactNode, options?: ToastSingleOptions): string;
|
|
190
278
|
promise<T>(promise: Promise<T>, messages: SnackbarPromiseOptions<T>, options?: SnackbarOptions): Promise<T>;
|
|
279
|
+
/** Collapse the visible stack into one summary pill. */
|
|
280
|
+
minimize(): void;
|
|
281
|
+
/** Restore the full stack after `minimize()`. */
|
|
282
|
+
expand(): void;
|
|
283
|
+
isMinimized(): boolean;
|
|
191
284
|
/** The store behind the global API (same instance the provider renders). */
|
|
192
285
|
readonly store: SnackbarStore;
|
|
193
286
|
}
|
|
@@ -218,6 +311,11 @@ interface SnackbarHostProps {
|
|
|
218
311
|
closeLabel?: string;
|
|
219
312
|
/** Accessible label for each notification region. @default 'Notifications' */
|
|
220
313
|
regionLabel?: string;
|
|
314
|
+
/**
|
|
315
|
+
* Text shown on the collapsed pill. Defaults to
|
|
316
|
+
* `"1 notification"` / `"3 notifications"`.
|
|
317
|
+
*/
|
|
318
|
+
minimizedLabel?: (count: number) => ReactNode;
|
|
221
319
|
className?: string;
|
|
222
320
|
style?: CSSProperties;
|
|
223
321
|
/** @default 2147483000 */
|
|
@@ -237,6 +335,16 @@ interface SnackbarProviderProps extends Omit<SnackbarHostProps, 'store'> {
|
|
|
237
335
|
dismissible?: boolean;
|
|
238
336
|
/** @default true */
|
|
239
337
|
progress?: boolean;
|
|
338
|
+
/** Render every snackbar as a single-line pill. @default false */
|
|
339
|
+
compact?: boolean;
|
|
340
|
+
/** Default layout for new snackbars. @default 'card' */
|
|
341
|
+
layout?: SnackbarLayout;
|
|
342
|
+
/** Default enter/exit animation. @default 'slide' */
|
|
343
|
+
animation?: SnackbarAnimation;
|
|
344
|
+
/** Default enter animation; falls back to `animation`. */
|
|
345
|
+
enterAnimation?: SnackbarAnimation;
|
|
346
|
+
/** Default exit animation; falls back to `animation`. */
|
|
347
|
+
exitAnimation?: SnackbarAnimation;
|
|
240
348
|
/** @default 'glass' */
|
|
241
349
|
tone?: SnackbarTone;
|
|
242
350
|
/** Default size for new snackbars. @default 'md' */
|
|
@@ -259,9 +367,9 @@ declare function getDefaultStore(): SnackbarStore;
|
|
|
259
367
|
*/
|
|
260
368
|
declare function setDefaultStore(store: SnackbarStore | null): void;
|
|
261
369
|
|
|
262
|
-
declare function SnackbarHost({ store, maxVisible, offset, gap, width, theme, container, pauseOnHover, pauseOnFocus, pauseOnDocumentHidden, swipeToDismiss, swipeThreshold, icons, closeIcon, closeLabel, regionLabel, className, style, zIndex, dir, }: SnackbarHostProps): react.ReactPortal | null;
|
|
370
|
+
declare function SnackbarHost({ store, maxVisible, offset, gap, width, theme, container, pauseOnHover, pauseOnFocus, pauseOnDocumentHidden, swipeToDismiss, swipeThreshold, icons, closeIcon, closeLabel, regionLabel, minimizedLabel, className, style, zIndex, dir, }: SnackbarHostProps): react.ReactPortal | null;
|
|
263
371
|
|
|
264
|
-
declare function SnackbarProvider({ children, store: providedStore, position, duration, dismissible, progress, tone, size, maxVisible, ...hostProps }: SnackbarProviderProps): react.JSX.Element;
|
|
372
|
+
declare function SnackbarProvider({ children, store: providedStore, position, duration, dismissible, progress, compact, layout, animation, enterAnimation, exitAnimation, tone, size, maxVisible, ...hostProps }: SnackbarProviderProps): react.JSX.Element;
|
|
265
373
|
/** Imperative API for showing and managing snackbars. */
|
|
266
374
|
declare function useSnackbar(): SnackbarApi;
|
|
267
375
|
/** Low-level store access for subscriptions and advanced integrations. */
|
|
@@ -281,4 +389,4 @@ declare function useSnackbarStore(): SnackbarStore;
|
|
|
281
389
|
*/
|
|
282
390
|
declare const toast: ToastApi;
|
|
283
391
|
|
|
284
|
-
export { type ResolvedSnackbarStoreConfig, type SnackbarAction, type SnackbarApi, type SnackbarCloseReason, SnackbarHost, type SnackbarHostProps, type SnackbarOptions, type SnackbarPhase, type SnackbarPosition, type SnackbarPromiseContent, type SnackbarPromiseOptions, SnackbarProvider, type SnackbarProviderProps, type SnackbarRecord, type SnackbarSize, type SnackbarStore, type SnackbarStoreConfig, type SnackbarTheme, type SnackbarTone, type SnackbarVariant, type ToastApi, type ToastPresetOptions, createSnackbarStore, getDefaultStore, setDefaultStore, toast, useSnackbar, useSnackbarStore };
|
|
392
|
+
export { type ResolvedSnackbarStoreConfig, type SnackbarAction, type SnackbarAnimation, type SnackbarApi, type SnackbarCloseReason, SnackbarHost, type SnackbarHostProps, type SnackbarLayout, type SnackbarOptions, type SnackbarPhase, type SnackbarPosition, type SnackbarPromiseContent, type SnackbarPromiseOptions, SnackbarProvider, type SnackbarProviderProps, type SnackbarRecord, type SnackbarSize, type SnackbarStore, type SnackbarStoreConfig, type SnackbarTheme, type SnackbarTone, type SnackbarVariant, type ToastApi, type ToastPresetOptions, type ToastSingleOptions, createSnackbarStore, getDefaultStore, setDefaultStore, toast, useSnackbar, useSnackbarStore };
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,10 @@ var DEFAULT_CONFIG = {
|
|
|
9
9
|
duration: 5e3,
|
|
10
10
|
dismissible: true,
|
|
11
11
|
progress: true,
|
|
12
|
+
layout: "card",
|
|
13
|
+
animation: "slide",
|
|
14
|
+
enterAnimation: "slide",
|
|
15
|
+
exitAnimation: "slide",
|
|
12
16
|
tone: "glass",
|
|
13
17
|
size: "md",
|
|
14
18
|
maxVisible: 3
|
|
@@ -36,28 +40,45 @@ function resolveContent(content, value) {
|
|
|
36
40
|
const resolved = typeof content === "function" ? content(value) : content;
|
|
37
41
|
return contentToOptions(resolved);
|
|
38
42
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
function resolveLayout(layout, compact, fallback) {
|
|
44
|
+
if (layout !== void 0) return layout;
|
|
45
|
+
if (compact !== void 0) return compact ? "compact" : "card";
|
|
46
|
+
return fallback;
|
|
47
|
+
}
|
|
48
|
+
function resolveLayoutPatch(record, options) {
|
|
49
|
+
if (options.layout === void 0 && options.compact === void 0) return {};
|
|
50
|
+
const layout = resolveLayout(options.layout, options.compact, record.layout);
|
|
51
|
+
return { layout, compact: layout === "compact" };
|
|
52
|
+
}
|
|
53
|
+
function mergeConfig(previous, patch) {
|
|
54
|
+
const layout = resolveLayout(patch.layout, patch.compact, previous.layout);
|
|
55
|
+
return {
|
|
56
|
+
position: patch.position ?? previous.position,
|
|
57
|
+
duration: patch.duration !== void 0 ? normalizeDuration(patch.duration, previous.duration) : previous.duration,
|
|
58
|
+
dismissible: patch.dismissible ?? previous.dismissible,
|
|
59
|
+
progress: patch.progress ?? previous.progress,
|
|
60
|
+
compact: layout === "compact",
|
|
61
|
+
layout,
|
|
62
|
+
animation: patch.animation ?? previous.animation,
|
|
63
|
+
enterAnimation: patch.enterAnimation ?? patch.animation ?? previous.enterAnimation,
|
|
64
|
+
exitAnimation: patch.exitAnimation ?? patch.animation ?? previous.exitAnimation,
|
|
65
|
+
tone: patch.tone ?? previous.tone,
|
|
66
|
+
size: patch.size ?? previous.size,
|
|
67
|
+
maxVisible: patch.maxVisible !== void 0 ? Math.max(1, Math.floor(patch.maxVisible)) : previous.maxVisible
|
|
54
68
|
};
|
|
69
|
+
}
|
|
70
|
+
function createSnackbarStore(initialConfig = {}) {
|
|
71
|
+
let config = mergeConfig(
|
|
72
|
+
DEFAULT_CONFIG,
|
|
73
|
+
initialConfig
|
|
74
|
+
);
|
|
55
75
|
let records = EMPTY;
|
|
56
76
|
const listeners = /* @__PURE__ */ new Set();
|
|
57
77
|
const timers = /* @__PURE__ */ new Map();
|
|
58
78
|
const shown = /* @__PURE__ */ new Set();
|
|
59
79
|
const pauseReasons = /* @__PURE__ */ new Map();
|
|
60
80
|
let pageHidden = false;
|
|
81
|
+
let minimized = false;
|
|
61
82
|
const emit = () => {
|
|
62
83
|
for (const listener of listeners) listener();
|
|
63
84
|
};
|
|
@@ -218,6 +239,7 @@ function createSnackbarStore(initialConfig = {}) {
|
|
|
218
239
|
}
|
|
219
240
|
return id;
|
|
220
241
|
}
|
|
242
|
+
const layout = resolveLayout(options.layout, options.compact, config.layout);
|
|
221
243
|
const record = {
|
|
222
244
|
id,
|
|
223
245
|
title: options.title,
|
|
@@ -231,6 +253,11 @@ function createSnackbarStore(initialConfig = {}) {
|
|
|
231
253
|
action: options.action ?? null,
|
|
232
254
|
dismissible: options.dismissible ?? config.dismissible,
|
|
233
255
|
progress: options.progress ?? config.progress,
|
|
256
|
+
compact: layout === "compact",
|
|
257
|
+
layout,
|
|
258
|
+
animation: options.animation ?? config.animation,
|
|
259
|
+
enterAnimation: options.enterAnimation ?? options.animation ?? config.enterAnimation,
|
|
260
|
+
exitAnimation: options.exitAnimation ?? options.animation ?? config.exitAnimation,
|
|
234
261
|
className: options.className,
|
|
235
262
|
style: options.style,
|
|
236
263
|
createdAt: Date.now(),
|
|
@@ -259,6 +286,14 @@ function createSnackbarStore(initialConfig = {}) {
|
|
|
259
286
|
...options.action !== void 0 ? { action: options.action } : null,
|
|
260
287
|
...options.dismissible !== void 0 ? { dismissible: options.dismissible } : null,
|
|
261
288
|
...options.progress !== void 0 ? { progress: options.progress } : null,
|
|
289
|
+
...resolveLayoutPatch(record, options),
|
|
290
|
+
...options.animation !== void 0 ? {
|
|
291
|
+
animation: options.animation,
|
|
292
|
+
enterAnimation: options.animation,
|
|
293
|
+
exitAnimation: options.animation
|
|
294
|
+
} : null,
|
|
295
|
+
...options.enterAnimation !== void 0 ? { enterAnimation: options.enterAnimation } : null,
|
|
296
|
+
...options.exitAnimation !== void 0 ? { exitAnimation: options.exitAnimation } : null,
|
|
262
297
|
...options.className !== void 0 ? { className: options.className } : null,
|
|
263
298
|
...options.style !== void 0 ? { style: options.style } : null,
|
|
264
299
|
...options.onOpen !== void 0 ? { onOpen: options.onOpen } : null,
|
|
@@ -308,18 +343,7 @@ function createSnackbarStore(initialConfig = {}) {
|
|
|
308
343
|
}
|
|
309
344
|
};
|
|
310
345
|
const setConfig = (patch) => {
|
|
311
|
-
config =
|
|
312
|
-
...config,
|
|
313
|
-
...patch.position !== void 0 ? { position: patch.position } : null,
|
|
314
|
-
...patch.duration !== void 0 ? {
|
|
315
|
-
duration: normalizeDuration(patch.duration, config.duration)
|
|
316
|
-
} : null,
|
|
317
|
-
...patch.dismissible !== void 0 ? { dismissible: patch.dismissible } : null,
|
|
318
|
-
...patch.progress !== void 0 ? { progress: patch.progress } : null,
|
|
319
|
-
...patch.tone !== void 0 ? { tone: patch.tone } : null,
|
|
320
|
-
...patch.size !== void 0 ? { size: patch.size } : null,
|
|
321
|
-
...patch.maxVisible !== void 0 ? { maxVisible: Math.max(1, Math.floor(patch.maxVisible)) } : null
|
|
322
|
-
};
|
|
346
|
+
config = mergeConfig(config, patch);
|
|
323
347
|
};
|
|
324
348
|
const promise = (input, messages, options = {}) => {
|
|
325
349
|
const loadingOptions = contentToOptions(messages.loading ?? "Loading\u2026");
|
|
@@ -370,7 +394,14 @@ function createSnackbarStore(initialConfig = {}) {
|
|
|
370
394
|
resume,
|
|
371
395
|
notifyShown,
|
|
372
396
|
notifyExited,
|
|
373
|
-
setPageHidden
|
|
397
|
+
setPageHidden,
|
|
398
|
+
getMinimized: () => minimized,
|
|
399
|
+
getServerMinimized: () => false,
|
|
400
|
+
setMinimized(next) {
|
|
401
|
+
if (minimized === next) return;
|
|
402
|
+
minimized = next;
|
|
403
|
+
emit();
|
|
404
|
+
}
|
|
374
405
|
};
|
|
375
406
|
}
|
|
376
407
|
|
|
@@ -615,7 +646,10 @@ function SnackbarItem({
|
|
|
615
646
|
};
|
|
616
647
|
const resolvedIcon = record.icon === void 0 ? icons?.[variant] ?? defaultIcons[variant] : record.icon;
|
|
617
648
|
const showIcon = record.icon !== false;
|
|
618
|
-
const
|
|
649
|
+
const isInline = record.layout === "inline";
|
|
650
|
+
const isTimed = Number.isFinite(duration) && duration > 0;
|
|
651
|
+
const showProgress = record.layout === "card" && record.progress && isTimed;
|
|
652
|
+
const showClose = record.dismissible && (!isInline || !isTimed);
|
|
619
653
|
const style = {
|
|
620
654
|
...record.style,
|
|
621
655
|
"--prs-drag-x": `${dragX}px`,
|
|
@@ -635,6 +669,10 @@ function SnackbarItem({
|
|
|
635
669
|
"data-dragging": dragging ? "true" : "false",
|
|
636
670
|
"data-has-icon": showIcon ? "true" : "false",
|
|
637
671
|
"data-dismissible": record.dismissible ? "true" : "false",
|
|
672
|
+
"data-compact": record.compact ? "true" : "false",
|
|
673
|
+
"data-layout": record.layout,
|
|
674
|
+
"data-enter": record.enterAnimation,
|
|
675
|
+
"data-exit": record.exitAnimation,
|
|
638
676
|
"data-prs-id": record.id,
|
|
639
677
|
"data-position": record.position,
|
|
640
678
|
style,
|
|
@@ -683,7 +721,7 @@ function SnackbarItem({
|
|
|
683
721
|
className: "prs-item__content",
|
|
684
722
|
"data-has-title": title !== void 0 && title !== null ? "true" : "false",
|
|
685
723
|
children: [
|
|
686
|
-
title !== void 0 && title !== null ? /* @__PURE__ */ jsx("div", { className: "prs-item__title", children: title }) : null,
|
|
724
|
+
title !== void 0 && title !== null && !isInline ? /* @__PURE__ */ jsx("div", { className: "prs-item__title", children: title }) : null,
|
|
687
725
|
message !== void 0 && message !== null ? /* @__PURE__ */ jsx("div", { className: "prs-item__message", children: message }) : null,
|
|
688
726
|
action ? /* @__PURE__ */ jsx("div", { className: "prs-item__actions", children: /* @__PURE__ */ jsxs(
|
|
689
727
|
"button",
|
|
@@ -702,7 +740,7 @@ function SnackbarItem({
|
|
|
702
740
|
]
|
|
703
741
|
}
|
|
704
742
|
),
|
|
705
|
-
|
|
743
|
+
showClose ? /* @__PURE__ */ jsx(
|
|
706
744
|
"button",
|
|
707
745
|
{
|
|
708
746
|
type: "button",
|
|
@@ -734,6 +772,9 @@ var POSITIONS = [
|
|
|
734
772
|
"bottom-center",
|
|
735
773
|
"bottom-right"
|
|
736
774
|
];
|
|
775
|
+
function defaultMinimizedLabel(count) {
|
|
776
|
+
return `${count} notification${count === 1 ? "" : "s"}`;
|
|
777
|
+
}
|
|
737
778
|
function SnackbarHost({
|
|
738
779
|
store,
|
|
739
780
|
maxVisible = 3,
|
|
@@ -751,6 +792,7 @@ function SnackbarHost({
|
|
|
751
792
|
closeIcon,
|
|
752
793
|
closeLabel = "Dismiss notification",
|
|
753
794
|
regionLabel = "Notifications",
|
|
795
|
+
minimizedLabel = defaultMinimizedLabel,
|
|
754
796
|
className,
|
|
755
797
|
style,
|
|
756
798
|
zIndex = 2147483e3,
|
|
@@ -761,6 +803,11 @@ function SnackbarHost({
|
|
|
761
803
|
store.getSnapshot,
|
|
762
804
|
store.getServerSnapshot
|
|
763
805
|
);
|
|
806
|
+
const minimized = useSyncExternalStore(
|
|
807
|
+
store.subscribe,
|
|
808
|
+
store.getMinimized,
|
|
809
|
+
store.getServerMinimized
|
|
810
|
+
);
|
|
764
811
|
const [portalNode, setPortalNode] = useState(null);
|
|
765
812
|
const regionRefs = useRef(/* @__PURE__ */ new Map());
|
|
766
813
|
const topsRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -824,6 +871,7 @@ function SnackbarHost({
|
|
|
824
871
|
else byPosition.set(record.position, [record]);
|
|
825
872
|
}
|
|
826
873
|
const limit = Math.max(1, Math.floor(maxVisible));
|
|
874
|
+
const minimizedPosition = records[0]?.position ?? null;
|
|
827
875
|
const rootStyle = {
|
|
828
876
|
"--prs-width": `${width}px`,
|
|
829
877
|
"--prs-offset": `${offset}px`,
|
|
@@ -842,6 +890,32 @@ function SnackbarHost({
|
|
|
842
890
|
children: POSITIONS.map((position) => {
|
|
843
891
|
const items = byPosition.get(position);
|
|
844
892
|
if (!items || items.length === 0) return null;
|
|
893
|
+
if (minimized) {
|
|
894
|
+
if (position !== minimizedPosition) return null;
|
|
895
|
+
return /* @__PURE__ */ jsx(
|
|
896
|
+
"section",
|
|
897
|
+
{
|
|
898
|
+
className: "prs-region prs-region--minimized",
|
|
899
|
+
"data-position": position,
|
|
900
|
+
"aria-label": regionLabel,
|
|
901
|
+
children: /* @__PURE__ */ jsxs(
|
|
902
|
+
"button",
|
|
903
|
+
{
|
|
904
|
+
type: "button",
|
|
905
|
+
className: "prs-minimized",
|
|
906
|
+
"data-count": items.length,
|
|
907
|
+
onClick: () => store.setMinimized(false),
|
|
908
|
+
title: "Expand notifications",
|
|
909
|
+
children: [
|
|
910
|
+
/* @__PURE__ */ jsx("span", { className: "prs-minimized__dot", "aria-hidden": "true" }),
|
|
911
|
+
/* @__PURE__ */ jsx("span", { className: "prs-minimized__count", children: minimizedLabel(items.length) })
|
|
912
|
+
]
|
|
913
|
+
}
|
|
914
|
+
)
|
|
915
|
+
},
|
|
916
|
+
position
|
|
917
|
+
);
|
|
918
|
+
}
|
|
845
919
|
const visible = items.slice(0, limit);
|
|
846
920
|
return /* @__PURE__ */ jsx(
|
|
847
921
|
"section",
|
|
@@ -885,6 +959,11 @@ function SnackbarProvider({
|
|
|
885
959
|
duration,
|
|
886
960
|
dismissible,
|
|
887
961
|
progress,
|
|
962
|
+
compact,
|
|
963
|
+
layout,
|
|
964
|
+
animation,
|
|
965
|
+
enterAnimation,
|
|
966
|
+
exitAnimation,
|
|
888
967
|
tone,
|
|
889
968
|
size,
|
|
890
969
|
maxVisible,
|
|
@@ -906,11 +985,30 @@ function SnackbarProvider({
|
|
|
906
985
|
duration,
|
|
907
986
|
dismissible,
|
|
908
987
|
progress,
|
|
988
|
+
compact,
|
|
989
|
+
layout,
|
|
990
|
+
animation,
|
|
991
|
+
enterAnimation,
|
|
992
|
+
exitAnimation,
|
|
909
993
|
tone,
|
|
910
994
|
size,
|
|
911
995
|
maxVisible
|
|
912
996
|
});
|
|
913
|
-
}, [
|
|
997
|
+
}, [
|
|
998
|
+
store,
|
|
999
|
+
position,
|
|
1000
|
+
duration,
|
|
1001
|
+
dismissible,
|
|
1002
|
+
progress,
|
|
1003
|
+
compact,
|
|
1004
|
+
layout,
|
|
1005
|
+
animation,
|
|
1006
|
+
enterAnimation,
|
|
1007
|
+
exitAnimation,
|
|
1008
|
+
tone,
|
|
1009
|
+
size,
|
|
1010
|
+
maxVisible
|
|
1011
|
+
]);
|
|
914
1012
|
const api = useMemo(() => {
|
|
915
1013
|
const preset2 = (variant) => (message, options = {}) => store.show({ ...options, message, variant });
|
|
916
1014
|
return {
|
|
@@ -925,12 +1023,16 @@ function SnackbarProvider({
|
|
|
925
1023
|
info: preset2("info"),
|
|
926
1024
|
neutral: preset2("neutral"),
|
|
927
1025
|
custom: preset2("custom"),
|
|
1026
|
+
single: (message, options = {}) => store.show({ ...options, message, layout: "inline" }),
|
|
928
1027
|
loading: (message, options = {}) => store.show({
|
|
929
1028
|
...options,
|
|
930
1029
|
message,
|
|
931
1030
|
variant: "loading",
|
|
932
1031
|
duration: options.duration !== void 0 ? options.duration : null
|
|
933
1032
|
}),
|
|
1033
|
+
minimize: () => store.setMinimized(true),
|
|
1034
|
+
expand: () => store.setMinimized(false),
|
|
1035
|
+
isMinimized: () => store.getMinimized(),
|
|
934
1036
|
store
|
|
935
1037
|
};
|
|
936
1038
|
}, [store]);
|
|
@@ -988,6 +1090,7 @@ function createToast() {
|
|
|
988
1090
|
toast2.info = preset("info");
|
|
989
1091
|
toast2.neutral = preset("neutral");
|
|
990
1092
|
toast2.custom = preset("custom");
|
|
1093
|
+
toast2.single = (message, options = {}) => getDefaultStore().show({ ...options, message, layout: "inline" });
|
|
991
1094
|
toast2.loading = (message, options = {}) => getDefaultStore().show({
|
|
992
1095
|
...options,
|
|
993
1096
|
message,
|
|
@@ -995,6 +1098,9 @@ function createToast() {
|
|
|
995
1098
|
duration: options.duration !== void 0 ? options.duration : null
|
|
996
1099
|
});
|
|
997
1100
|
toast2.promise = (input, messages, options) => getDefaultStore().promise(input, messages, options);
|
|
1101
|
+
toast2.minimize = () => getDefaultStore().setMinimized(true);
|
|
1102
|
+
toast2.expand = () => getDefaultStore().setMinimized(false);
|
|
1103
|
+
toast2.isMinimized = () => getDefaultStore().getMinimized();
|
|
998
1104
|
Object.defineProperty(toast2, "store", {
|
|
999
1105
|
get: getDefaultStore,
|
|
1000
1106
|
enumerable: true
|