@react-stately/toast 3.0.0-nightly.5042 → 3.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/dist/types.d.ts CHANGED
@@ -1,20 +1,15 @@
1
+ type ToastAction = 'add' | 'remove' | 'clear';
1
2
  export interface ToastStateProps {
2
3
  /** The maximum number of toasts to display at a time. */
3
4
  maxVisibleToasts?: number;
4
- /**
5
- * Whether toasts have an exit animation. If true, toasts are not
6
- * removed immediately but transition into an "exiting" state instead.
7
- * Once the animation is complete, call the `remove` function.
8
- */
9
- hasExitAnimation?: boolean;
5
+ /** Function to wrap updates in (i.e. document.startViewTransition()). */
6
+ wrapUpdate?: (fn: () => void, action: ToastAction) => void;
10
7
  }
11
8
  export interface ToastOptions {
12
9
  /** Handler that is called when the toast is closed, either by the user or after a timeout. */
13
10
  onClose?: () => void;
14
11
  /** A timeout to automatically close the toast after, in milliseconds. */
15
12
  timeout?: number;
16
- /** The priority of the toast relative to other toasts. Larger numbers indicate higher priority. */
17
- priority?: number;
18
13
  }
19
14
  export interface QueuedToast<T> extends ToastOptions {
20
15
  /** The content of the toast. */
@@ -23,19 +18,14 @@ export interface QueuedToast<T> extends ToastOptions {
23
18
  key: string;
24
19
  /** A timer for the toast, if a timeout was set. */
25
20
  timer?: Timer;
26
- /** The current animation state for the toast. */
27
- animation?: 'entering' | 'queued' | 'exiting';
28
21
  }
29
22
  export interface ToastState<T> {
30
23
  /** Adds a new toast to the queue. */
31
24
  add(content: T, options?: ToastOptions): string;
32
25
  /**
33
- * Closes a toast. If `hasExitAnimation` is true, the toast
34
- * transitions to an "exiting" state instead of being removed immediately.
26
+ * Closes a toast.
35
27
  */
36
28
  close(key: string): void;
37
- /** Removes a toast from the visible toasts after an exiting animation. */
38
- remove(key: string): void;
39
29
  /** Pauses the timers for all visible toasts. */
40
30
  pauseAll(): void;
41
31
  /** Resumes the timers for all visible toasts. */
@@ -53,27 +43,25 @@ export function useToastState<T>(props?: ToastStateProps): ToastState<T>;
53
43
  */
54
44
  export function useToastQueue<T>(queue: ToastQueue<T>): ToastState<T>;
55
45
  /**
56
- * A ToastQueue is a priority queue of toasts.
46
+ * A ToastQueue manages the order of toasts.
57
47
  */
58
48
  export class ToastQueue<T> {
59
49
  /** The currently visible toasts. */
60
50
  visibleToasts: QueuedToast<T>[];
61
51
  constructor(options?: ToastStateProps);
62
52
  /** Subscribes to updates to the visible toasts. */
63
- subscribe(fn: () => void): () => boolean;
53
+ subscribe(fn: () => void): () => void;
64
54
  /** Adds a new toast to the queue. */
65
55
  add(content: T, options?: ToastOptions): string;
66
56
  /**
67
- * Closes a toast. If `hasExitAnimation` is true, the toast
68
- * transitions to an "exiting" state instead of being removed immediately.
57
+ * Closes a toast.
69
58
  */
70
59
  close(key: string): void;
71
- /** Removes a toast from the visible toasts after an exiting animation. */
72
- remove(key: string): void;
73
60
  /** Pauses the timers for all visible toasts. */
74
61
  pauseAll(): void;
75
62
  /** Resumes the timers for all visible toasts. */
76
63
  resumeAll(): void;
64
+ clear(): void;
77
65
  }
78
66
  declare class Timer {
79
67
  constructor(callback: () => void, delay: number);
@@ -1 +1 @@
1
- {"mappings":"AAgBA;IACE,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED;IACE,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mGAAmG;IACnG,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,6BAA6B,CAAC,CAAE,SAAQ,YAAY;IAClD,gCAAgC;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,iDAAiD;IACjD,SAAS,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAA;CAC9C;AAED,4BAA4B,CAAC;IAC3B,qCAAqC;IACrC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAChD;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,0EAA0E;IAC1E,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gDAAgD;IAChD,QAAQ,IAAI,IAAI,CAAC;IACjB,iDAAiD;IACjD,SAAS,IAAI,IAAI,CAAC;IAClB,0BAA0B;IAC1B,aAAa,EAAE,YAAY,CAAC,CAAC,EAAE,CAAA;CAChC;AAED;;;GAGG;AACH,8BAA8B,CAAC,EAAE,KAAK,GAAE,eAAoB,GAAG,WAAW,CAAC,CAAC,CAI3E;AAED;;GAEG;AACH,8BAA8B,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAapE;AAED;;GAEG;AACH,wBAAwB,CAAC;IAKvB,oCAAoC;IACpC,aAAa,EAAE,YAAY,CAAC,CAAC,EAAE,CAAM;gBAEzB,OAAO,CAAC,EAAE,eAAe;IAKrC,mDAAmD;IACnD,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI;IAKxB,qCAAqC;IACrC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,GAAE,YAAiB;IAgC1C;;;OAGG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM;IAUjB,0EAA0E;IAC1E,MAAM,CAAC,GAAG,EAAE,MAAM;IA+BlB,gDAAgD;IAChD,QAAQ;IAQR,iDAAiD;IACjD,SAAS;CAOV;AAED;gBAMc,QAAQ,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM;IAK/C,KAAK,CAAC,KAAK,EAAE,MAAM;IAKnB,KAAK;IAUL,MAAM;CAYP","sources":["packages/@react-stately/toast/src/packages/@react-stately/toast/src/useToastState.ts","packages/@react-stately/toast/src/packages/@react-stately/toast/src/index.ts","packages/@react-stately/toast/src/index.ts"],"sourcesContent":[null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useToastState, ToastQueue, useToastQueue} from './useToastState';\n\nexport type {ToastState, QueuedToast, ToastStateProps, ToastOptions} from './useToastState';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
1
+ {"mappings":"AAgBA,mBAAmB,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC9C;IACE,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;CAC3D;AAED;IACE,8FAA8F;IAC9F,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,6BAA6B,CAAC,CAAE,SAAQ,YAAY;IAClD,gCAAgC;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAA;CACd;AAED,4BAA4B,CAAC;IAC3B,qCAAqC;IACrC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;IAChD;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,gDAAgD;IAChD,QAAQ,IAAI,IAAI,CAAC;IACjB,iDAAiD;IACjD,SAAS,IAAI,IAAI,CAAC;IAClB,0BAA0B;IAC1B,aAAa,EAAE,YAAY,CAAC,CAAC,EAAE,CAAA;CAChC;AAED;;;GAGG;AACH,8BAA8B,CAAC,EAAE,KAAK,GAAE,eAAoB,GAAG,WAAW,CAAC,CAAC,CAI3E;AAED;;GAEG;AACH,8BAA8B,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAYpE;AAED;;GAEG;AACH,wBAAwB,CAAC;IAKvB,oCAAoC;IACpC,aAAa,EAAE,YAAY,CAAC,CAAC,EAAE,CAAM;gBAEzB,OAAO,CAAC,EAAE,eAAe;IAarC,mDAAmD;IACnD,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKrC,qCAAqC;IACrC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM;IAenD;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAoBxB,gDAAgD;IAChD,QAAQ,IAAI,IAAI;IAQhB,iDAAiD;IACjD,SAAS,IAAI,IAAI;IAQjB,KAAK,IAAI,IAAI;CAId;AAED;gBAMc,QAAQ,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,MAAM;IAK/C,KAAK,CAAC,KAAK,EAAE,MAAM;IAKnB,KAAK;IAUL,MAAM;CAYP","sources":["packages/@react-stately/toast/src/packages/@react-stately/toast/src/useToastState.ts","packages/@react-stately/toast/src/packages/@react-stately/toast/src/index.ts","packages/@react-stately/toast/src/index.ts"],"sourcesContent":[null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useToastState, ToastQueue, useToastQueue} from './useToastState';\n\nexport type {ToastState, QueuedToast, ToastStateProps, ToastOptions} from './useToastState';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
@@ -22,13 +22,13 @@ $parcel$export(module.exports, "useToastQueue", () => $c995945a643dde76$export$8
22
22
  */
23
23
 
24
24
  function $c995945a643dde76$export$c7b26b20d3ced9c5(props = {}) {
25
- let { maxVisibleToasts: maxVisibleToasts = 1, hasExitAnimation: hasExitAnimation = false } = props;
25
+ let { maxVisibleToasts: maxVisibleToasts = 1, wrapUpdate: wrapUpdate } = props;
26
26
  let queue = (0, $pwpJQ$react.useMemo)(()=>new $c995945a643dde76$export$f1f8569633bbbec4({
27
27
  maxVisibleToasts: maxVisibleToasts,
28
- hasExitAnimation: hasExitAnimation
28
+ wrapUpdate: wrapUpdate
29
29
  }), [
30
30
  maxVisibleToasts,
31
- hasExitAnimation
31
+ wrapUpdate
32
32
  ]);
33
33
  return $c995945a643dde76$export$84726ef35ca2129a(queue);
34
34
  }
@@ -44,43 +44,33 @@ function $c995945a643dde76$export$84726ef35ca2129a(queue) {
44
44
  visibleToasts: visibleToasts,
45
45
  add: (content, options)=>queue.add(content, options),
46
46
  close: (key)=>queue.close(key),
47
- remove: (key)=>queue.remove(key),
48
47
  pauseAll: ()=>queue.pauseAll(),
49
48
  resumeAll: ()=>queue.resumeAll()
50
49
  };
51
50
  }
52
51
  class $c995945a643dde76$export$f1f8569633bbbec4 {
52
+ runWithWrapUpdate(fn, action) {
53
+ if (this.wrapUpdate) this.wrapUpdate(fn, action);
54
+ else fn();
55
+ }
53
56
  /** Subscribes to updates to the visible toasts. */ subscribe(fn) {
54
57
  this.subscriptions.add(fn);
55
58
  return ()=>this.subscriptions.delete(fn);
56
59
  }
57
60
  /** Adds a new toast to the queue. */ add(content, options = {}) {
58
- let toastKey = Math.random().toString(36);
61
+ let toastKey = '_' + Math.random().toString(36).slice(2);
59
62
  let toast = {
60
63
  ...options,
61
64
  content: content,
62
65
  key: toastKey,
63
- timer: options.timeout ? new $c995945a643dde76$var$Timer(()=>this.close(toastKey), options.timeout) : null
66
+ timer: options.timeout ? new $c995945a643dde76$var$Timer(()=>this.close(toastKey), options.timeout) : undefined
64
67
  };
65
- let low = 0;
66
- let high = this.queue.length;
67
- while(low < high){
68
- let mid = Math.floor((low + high) / 2);
69
- if ((toast.priority || 0) > (this.queue[mid].priority || 0)) high = mid;
70
- else low = mid + 1;
71
- }
72
- this.queue.splice(low, 0, toast);
73
- toast.animation = low < this.maxVisibleToasts ? 'entering' : 'queued';
74
- let i = this.maxVisibleToasts;
75
- while(i < this.queue.length)this.queue[i++].animation = 'queued';
76
- this.updateVisibleToasts({
77
- action: 'add'
78
- });
68
+ this.queue.unshift(toast);
69
+ this.updateVisibleToasts('add');
79
70
  return toastKey;
80
71
  }
81
72
  /**
82
- * Closes a toast. If `hasExitAnimation` is true, the toast
83
- * transitions to an "exiting" state instead of being removed immediately.
73
+ * Closes a toast.
84
74
  */ close(key) {
85
75
  let index = this.queue.findIndex((t)=>t.key === key);
86
76
  if (index >= 0) {
@@ -88,36 +78,13 @@ class $c995945a643dde76$export$f1f8569633bbbec4 {
88
78
  (_this_queue_index_onClose = (_this_queue_index = this.queue[index]).onClose) === null || _this_queue_index_onClose === void 0 ? void 0 : _this_queue_index_onClose.call(_this_queue_index);
89
79
  this.queue.splice(index, 1);
90
80
  }
91
- this.updateVisibleToasts({
92
- action: 'close',
93
- key: key
94
- });
95
- }
96
- /** Removes a toast from the visible toasts after an exiting animation. */ remove(key) {
97
- this.updateVisibleToasts({
98
- action: 'remove',
99
- key: key
100
- });
81
+ this.updateVisibleToasts('remove');
101
82
  }
102
- updateVisibleToasts(options) {
103
- let { action: action, key: key } = options;
104
- let toasts = this.queue.slice(0, this.maxVisibleToasts);
105
- if (action === 'add' && this.hasExitAnimation) {
106
- let prevToasts = this.visibleToasts.filter((t)=>!toasts.some((t2)=>t.key === t2.key)).map((t)=>({
107
- ...t,
108
- animation: 'exiting'
109
- }));
110
- this.visibleToasts = prevToasts.concat(toasts).sort((a, b)=>b.priority - a.priority);
111
- } else if (action === 'close' && this.hasExitAnimation) // Cause a rerender to happen for exit animation
112
- this.visibleToasts = this.visibleToasts.map((t)=>{
113
- if (t.key !== key) return t;
114
- else return {
115
- ...t,
116
- animation: 'exiting'
117
- };
118
- });
119
- else this.visibleToasts = toasts;
120
- for (let fn of this.subscriptions)fn();
83
+ updateVisibleToasts(action) {
84
+ this.visibleToasts = this.queue.slice(0, this.maxVisibleToasts);
85
+ this.runWithWrapUpdate(()=>{
86
+ for (let fn of this.subscriptions)fn();
87
+ }, action);
121
88
  }
122
89
  /** Pauses the timers for all visible toasts. */ pauseAll() {
123
90
  for (let toast of this.visibleToasts)if (toast.timer) toast.timer.pause();
@@ -125,14 +92,17 @@ class $c995945a643dde76$export$f1f8569633bbbec4 {
125
92
  /** Resumes the timers for all visible toasts. */ resumeAll() {
126
93
  for (let toast of this.visibleToasts)if (toast.timer) toast.timer.resume();
127
94
  }
95
+ clear() {
96
+ this.queue = [];
97
+ this.updateVisibleToasts('clear');
98
+ }
128
99
  constructor(options){
129
100
  this.queue = [];
130
101
  this.subscriptions = new Set();
131
102
  /** The currently visible toasts. */ this.visibleToasts = [];
132
103
  var _options_maxVisibleToasts;
133
- this.maxVisibleToasts = (_options_maxVisibleToasts = options === null || options === void 0 ? void 0 : options.maxVisibleToasts) !== null && _options_maxVisibleToasts !== void 0 ? _options_maxVisibleToasts : 1;
134
- var _options_hasExitAnimation;
135
- this.hasExitAnimation = (_options_hasExitAnimation = options === null || options === void 0 ? void 0 : options.hasExitAnimation) !== null && _options_hasExitAnimation !== void 0 ? _options_hasExitAnimation : false;
104
+ this.maxVisibleToasts = (_options_maxVisibleToasts = options === null || options === void 0 ? void 0 : options.maxVisibleToasts) !== null && _options_maxVisibleToasts !== void 0 ? _options_maxVisibleToasts : Infinity;
105
+ this.wrapUpdate = options === null || options === void 0 ? void 0 : options.wrapUpdate;
136
106
  }
137
107
  }
138
108
  class $c995945a643dde76$var$Timer {
@@ -156,6 +126,7 @@ class $c995945a643dde76$var$Timer {
156
126
  }, this.remaining);
157
127
  }
158
128
  constructor(callback, delay){
129
+ this.startTime = null;
159
130
  this.remaining = delay;
160
131
  this.callback = callback;
161
132
  }
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-stately/toast/src/useToastState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {useCallback, useMemo} from 'react';\n// Shim to support React 17 and below.\nimport {useSyncExternalStore} from 'use-sync-external-store/shim/index.js';\n\nexport interface ToastStateProps {\n /** The maximum number of toasts to display at a time. */\n maxVisibleToasts?: number,\n /**\n * Whether toasts have an exit animation. If true, toasts are not\n * removed immediately but transition into an \"exiting\" state instead.\n * Once the animation is complete, call the `remove` function.\n */\n hasExitAnimation?: boolean\n}\n\nexport interface ToastOptions {\n /** Handler that is called when the toast is closed, either by the user or after a timeout. */\n onClose?: () => void,\n /** A timeout to automatically close the toast after, in milliseconds. */\n timeout?: number,\n /** The priority of the toast relative to other toasts. Larger numbers indicate higher priority. */\n priority?: number\n}\n\nexport interface QueuedToast<T> extends ToastOptions {\n /** The content of the toast. */\n content: T,\n /** A unique key for the toast. */\n key: string,\n /** A timer for the toast, if a timeout was set. */\n timer?: Timer,\n /** The current animation state for the toast. */\n animation?: 'entering' | 'queued' | 'exiting'\n}\n\nexport interface ToastState<T> {\n /** Adds a new toast to the queue. */\n add(content: T, options?: ToastOptions): string,\n /**\n * Closes a toast. If `hasExitAnimation` is true, the toast\n * transitions to an \"exiting\" state instead of being removed immediately.\n */\n close(key: string): void,\n /** Removes a toast from the visible toasts after an exiting animation. */\n remove(key: string): void,\n /** Pauses the timers for all visible toasts. */\n pauseAll(): void,\n /** Resumes the timers for all visible toasts. */\n resumeAll(): void,\n /** The visible toasts. */\n visibleToasts: QueuedToast<T>[]\n}\n\n/**\n * Provides state management for a toast queue. Toasts display brief, temporary notifications\n * of actions, errors, or other events in an application.\n */\nexport function useToastState<T>(props: ToastStateProps = {}): ToastState<T> {\n let {maxVisibleToasts = 1, hasExitAnimation = false} = props;\n let queue = useMemo(() => new ToastQueue<T>({maxVisibleToasts, hasExitAnimation}), [maxVisibleToasts, hasExitAnimation]);\n return useToastQueue(queue);\n}\n\n/**\n * Subscribes to a provided toast queue and provides methods to update it.\n */\nexport function useToastQueue<T>(queue: ToastQueue<T>): ToastState<T> {\n let subscribe = useCallback(fn => queue.subscribe(fn), [queue]);\n let getSnapshot = useCallback(() => queue.visibleToasts, [queue]);\n let visibleToasts = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return {\n visibleToasts,\n add: (content, options) => queue.add(content, options),\n close: key => queue.close(key),\n remove: key => queue.remove(key),\n pauseAll: () => queue.pauseAll(),\n resumeAll: () => queue.resumeAll()\n };\n}\n\n/**\n * A ToastQueue is a priority queue of toasts.\n */\nexport class ToastQueue<T> {\n private queue: QueuedToast<T>[] = [];\n private subscriptions: Set<() => void> = new Set();\n private maxVisibleToasts: number;\n private hasExitAnimation: boolean;\n /** The currently visible toasts. */\n visibleToasts: QueuedToast<T>[] = [];\n\n constructor(options?: ToastStateProps) {\n this.maxVisibleToasts = options?.maxVisibleToasts ?? 1;\n this.hasExitAnimation = options?.hasExitAnimation ?? false;\n }\n\n /** Subscribes to updates to the visible toasts. */\n subscribe(fn: () => void) {\n this.subscriptions.add(fn);\n return () => this.subscriptions.delete(fn);\n }\n\n /** Adds a new toast to the queue. */\n add(content: T, options: ToastOptions = {}) {\n let toastKey = Math.random().toString(36);\n let toast: QueuedToast<T> = {\n ...options,\n content,\n key: toastKey,\n timer: options.timeout ? new Timer(() => this.close(toastKey), options.timeout) : null\n };\n\n let low = 0;\n let high = this.queue.length;\n while (low < high) {\n let mid = Math.floor((low + high) / 2);\n if ((toast.priority || 0) > (this.queue[mid].priority || 0)) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n this.queue.splice(low, 0, toast);\n\n toast.animation = low < this.maxVisibleToasts ? 'entering' : 'queued';\n let i = this.maxVisibleToasts;\n while (i < this.queue.length) {\n this.queue[i++].animation = 'queued';\n }\n\n this.updateVisibleToasts({action: 'add'});\n return toastKey;\n }\n\n /**\n * Closes a toast. If `hasExitAnimation` is true, the toast\n * transitions to an \"exiting\" state instead of being removed immediately.\n */\n close(key: string) {\n let index = this.queue.findIndex(t => t.key === key);\n if (index >= 0) {\n this.queue[index].onClose?.();\n this.queue.splice(index, 1);\n }\n\n this.updateVisibleToasts({action: 'close', key});\n }\n\n /** Removes a toast from the visible toasts after an exiting animation. */\n remove(key: string) {\n this.updateVisibleToasts({action: 'remove', key});\n }\n\n private updateVisibleToasts(options: {action: 'add' | 'close' | 'remove', key?: string}) {\n let {action, key} = options;\n let toasts = this.queue.slice(0, this.maxVisibleToasts);\n\n if (action === 'add' && this.hasExitAnimation) {\n let prevToasts: QueuedToast<T>[] = this.visibleToasts\n .filter(t => !toasts.some(t2 => t.key === t2.key))\n .map(t => ({...t, animation: 'exiting'}));\n this.visibleToasts = prevToasts.concat(toasts).sort((a, b) => b.priority - a.priority);\n } else if (action === 'close' && this.hasExitAnimation) {\n // Cause a rerender to happen for exit animation\n this.visibleToasts = this.visibleToasts.map(t => {\n if (t.key !== key) {\n return t;\n } else {\n return {...t, animation: 'exiting'};\n }\n });\n } else {\n this.visibleToasts = toasts;\n }\n\n for (let fn of this.subscriptions) {\n fn();\n }\n }\n\n /** Pauses the timers for all visible toasts. */\n pauseAll() {\n for (let toast of this.visibleToasts) {\n if (toast.timer) {\n toast.timer.pause();\n }\n }\n }\n\n /** Resumes the timers for all visible toasts. */\n resumeAll() {\n for (let toast of this.visibleToasts) {\n if (toast.timer) {\n toast.timer.resume();\n }\n }\n }\n}\n\nclass Timer {\n private timerId;\n private startTime: number;\n private remaining: number;\n private callback: () => void;\n\n constructor(callback: () => void, delay: number) {\n this.remaining = delay;\n this.callback = callback;\n }\n\n reset(delay: number) {\n this.remaining = delay;\n this.resume();\n }\n\n pause() {\n if (this.timerId == null) {\n return;\n }\n\n clearTimeout(this.timerId);\n this.timerId = null;\n this.remaining -= Date.now() - this.startTime;\n }\n\n resume() {\n if (this.remaining <= 0) {\n return;\n }\n\n this.startTime = Date.now();\n this.timerId = setTimeout(() => {\n this.timerId = null;\n this.remaining = 0;\n this.callback();\n }, this.remaining);\n }\n}\n"],"names":[],"version":3,"file":"useToastState.main.js.map"}
1
+ {"mappings":";;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;AAiDM,SAAS,0CAAiB,QAAyB,CAAC,CAAC;IAC1D,IAAI,oBAAC,mBAAmB,eAAG,UAAU,EAAC,GAAG;IACzC,IAAI,QAAQ,CAAA,GAAA,oBAAM,EAAE,IAAM,IAAI,0CAAc;8BAAC;wBAAkB;QAAU,IAAI;QAAC;QAAkB;KAAW;IAC3G,OAAO,0CAAc;AACvB;AAKO,SAAS,0CAAiB,KAAoB;IACnD,IAAI,YAAY,CAAA,GAAA,wBAAU,EAAE,CAAA,KAAM,MAAM,SAAS,CAAC,KAAK;QAAC;KAAM;IAC9D,IAAI,cAAc,CAAA,GAAA,wBAAU,EAAE,IAAM,MAAM,aAAa,EAAE;QAAC;KAAM;IAChE,IAAI,gBAAgB,CAAA,GAAA,2DAAmB,EAAE,WAAW,aAAa;IAEjE,OAAO;uBACL;QACA,KAAK,CAAC,SAAS,UAAY,MAAM,GAAG,CAAC,SAAS;QAC9C,OAAO,CAAA,MAAO,MAAM,KAAK,CAAC;QAC1B,UAAU,IAAM,MAAM,QAAQ;QAC9B,WAAW,IAAM,MAAM,SAAS;IAClC;AACF;AAKO,MAAM;IAaH,kBAAkB,EAAc,EAAE,MAAmB,EAAQ;QACnE,IAAI,IAAI,CAAC,UAAU,EACjB,IAAI,CAAC,UAAU,CAAC,IAAI;aAEpB;IAEJ;IAEA,iDAAiD,GACjD,UAAU,EAAc,EAAc;QACpC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;QACvB,OAAO,IAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;IACzC;IAEA,mCAAmC,GACnC,IAAI,OAAU,EAAE,UAAwB,CAAC,CAAC,EAAU;QAClD,IAAI,WAAW,MAAM,KAAK,MAAM,GAAG,QAAQ,CAAC,IAAI,KAAK,CAAC;QACtD,IAAI,QAAwB;YAC1B,GAAG,OAAO;qBACV;YACA,KAAK;YACL,OAAO,QAAQ,OAAO,GAAG,IAAI,4BAAM,IAAM,IAAI,CAAC,KAAK,CAAC,WAAW,QAAQ,OAAO,IAAI;QACpF;QAEA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QAEnB,IAAI,CAAC,mBAAmB,CAAC;QACzB,OAAO;IACT;IAEA;;GAEC,GACD,MAAM,GAAW,EAAQ;QACvB,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA,IAAK,EAAE,GAAG,KAAK;QAChD,IAAI,SAAS,GAAG;gBACd,2BAAA;aAAA,4BAAA,CAAA,oBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,EAAC,OAAO,cAAzB,gDAAA,+BAAA;YACA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO;QAC3B;QAEA,IAAI,CAAC,mBAAmB,CAAC;IAC3B;IAEQ,oBAAoB,MAAmB,EAAE;QAC/C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,gBAAgB;QAE9D,IAAI,CAAC,iBAAiB,CAAC;YACrB,KAAK,IAAI,MAAM,IAAI,CAAC,aAAa,CAC/B;QAEJ,GAAG;IACL;IAEA,8CAA8C,GAC9C,WAAiB;QACf,KAAK,IAAI,SAAS,IAAI,CAAC,aAAa,CAClC,IAAI,MAAM,KAAK,EACb,MAAM,KAAK,CAAC,KAAK;IAGvB;IAEA,+CAA+C,GAC/C,YAAkB;QAChB,KAAK,IAAI,SAAS,IAAI,CAAC,aAAa,CAClC,IAAI,MAAM,KAAK,EACb,MAAM,KAAK,CAAC,MAAM;IAGxB;IAEA,QAAc;QACZ,IAAI,CAAC,KAAK,GAAG,EAAE;QACf,IAAI,CAAC,mBAAmB,CAAC;IAC3B;IA/EA,YAAY,OAAyB,CAAE;aAP/B,QAA0B,EAAE;aAC5B,gBAAiC,IAAI;QAG7C,kCAAkC,QAClC,gBAAkC,EAAE;YAGV;QAAxB,IAAI,CAAC,gBAAgB,GAAG,CAAA,4BAAA,oBAAA,8BAAA,QAAS,gBAAgB,cAAzB,uCAAA,4BAA6B;QACrD,IAAI,CAAC,UAAU,GAAG,oBAAA,8BAAA,QAAS,UAAU;IACvC;AA6EF;AAEA,MAAM;IAWJ,MAAM,KAAa,EAAE;QACnB,IAAI,CAAC,SAAS,GAAG;QACjB,IAAI,CAAC,MAAM;IACb;IAEA,QAAQ;QACN,IAAI,IAAI,CAAC,OAAO,IAAI,MAClB;QAGF,aAAa,IAAI,CAAC,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG;QACf,IAAI,CAAC,SAAS,IAAI,KAAK,GAAG,KAAK,IAAI,CAAC,SAAS;IAC/C;IAEA,SAAS;QACP,IAAI,IAAI,CAAC,SAAS,IAAI,GACpB;QAGF,IAAI,CAAC,SAAS,GAAG,KAAK,GAAG;QACzB,IAAI,CAAC,OAAO,GAAG,WAAW;YACxB,IAAI,CAAC,OAAO,GAAG;YACf,IAAI,CAAC,SAAS,GAAG;YACjB,IAAI,CAAC,QAAQ;QACf,GAAG,IAAI,CAAC,SAAS;IACnB;IA/BA,YAAY,QAAoB,EAAE,KAAa,CAAE;aAJzC,YAA2B;QAKjC,IAAI,CAAC,SAAS,GAAG;QACjB,IAAI,CAAC,QAAQ,GAAG;IAClB;AA6BF","sources":["packages/@react-stately/toast/src/useToastState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {useCallback, useMemo} from 'react';\n// Shim to support React 17 and below.\nimport {useSyncExternalStore} from 'use-sync-external-store/shim/index.js';\n\ntype ToastAction = 'add' | 'remove' | 'clear';\nexport interface ToastStateProps {\n /** The maximum number of toasts to display at a time. */\n maxVisibleToasts?: number,\n /** Function to wrap updates in (i.e. document.startViewTransition()). */\n wrapUpdate?: (fn: () => void, action: ToastAction) => void\n}\n\nexport interface ToastOptions {\n /** Handler that is called when the toast is closed, either by the user or after a timeout. */\n onClose?: () => void,\n /** A timeout to automatically close the toast after, in milliseconds. */\n timeout?: number\n}\n\nexport interface QueuedToast<T> extends ToastOptions {\n /** The content of the toast. */\n content: T,\n /** A unique key for the toast. */\n key: string,\n /** A timer for the toast, if a timeout was set. */\n timer?: Timer\n}\n\nexport interface ToastState<T> {\n /** Adds a new toast to the queue. */\n add(content: T, options?: ToastOptions): string,\n /**\n * Closes a toast.\n */\n close(key: string): void,\n /** Pauses the timers for all visible toasts. */\n pauseAll(): void,\n /** Resumes the timers for all visible toasts. */\n resumeAll(): void,\n /** The visible toasts. */\n visibleToasts: QueuedToast<T>[]\n}\n\n/**\n * Provides state management for a toast queue. Toasts display brief, temporary notifications\n * of actions, errors, or other events in an application.\n */\nexport function useToastState<T>(props: ToastStateProps = {}): ToastState<T> {\n let {maxVisibleToasts = 1, wrapUpdate} = props;\n let queue = useMemo(() => new ToastQueue<T>({maxVisibleToasts, wrapUpdate}), [maxVisibleToasts, wrapUpdate]);\n return useToastQueue(queue);\n}\n\n/**\n * Subscribes to a provided toast queue and provides methods to update it.\n */\nexport function useToastQueue<T>(queue: ToastQueue<T>): ToastState<T> {\n let subscribe = useCallback(fn => queue.subscribe(fn), [queue]);\n let getSnapshot = useCallback(() => queue.visibleToasts, [queue]);\n let visibleToasts = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return {\n visibleToasts,\n add: (content, options) => queue.add(content, options),\n close: key => queue.close(key),\n pauseAll: () => queue.pauseAll(),\n resumeAll: () => queue.resumeAll()\n };\n}\n\n/**\n * A ToastQueue manages the order of toasts.\n */\nexport class ToastQueue<T> {\n private queue: QueuedToast<T>[] = [];\n private subscriptions: Set<() => void> = new Set();\n private maxVisibleToasts: number;\n private wrapUpdate?: (fn: () => void, action: ToastAction) => void;\n /** The currently visible toasts. */\n visibleToasts: QueuedToast<T>[] = [];\n\n constructor(options?: ToastStateProps) {\n this.maxVisibleToasts = options?.maxVisibleToasts ?? Infinity;\n this.wrapUpdate = options?.wrapUpdate;\n }\n\n private runWithWrapUpdate(fn: () => void, action: ToastAction): void {\n if (this.wrapUpdate) {\n this.wrapUpdate(fn, action);\n } else {\n fn();\n }\n }\n\n /** Subscribes to updates to the visible toasts. */\n subscribe(fn: () => void): () => void {\n this.subscriptions.add(fn);\n return () => this.subscriptions.delete(fn);\n }\n\n /** Adds a new toast to the queue. */\n add(content: T, options: ToastOptions = {}): string {\n let toastKey = '_' + Math.random().toString(36).slice(2);\n let toast: QueuedToast<T> = {\n ...options,\n content,\n key: toastKey,\n timer: options.timeout ? new Timer(() => this.close(toastKey), options.timeout) : undefined\n };\n\n this.queue.unshift(toast);\n\n this.updateVisibleToasts('add');\n return toastKey;\n }\n\n /**\n * Closes a toast.\n */\n close(key: string): void {\n let index = this.queue.findIndex(t => t.key === key);\n if (index >= 0) {\n this.queue[index].onClose?.();\n this.queue.splice(index, 1);\n }\n\n this.updateVisibleToasts('remove');\n }\n\n private updateVisibleToasts(action: ToastAction) {\n this.visibleToasts = this.queue.slice(0, this.maxVisibleToasts);\n\n this.runWithWrapUpdate(() => {\n for (let fn of this.subscriptions) {\n fn();\n }\n }, action);\n }\n\n /** Pauses the timers for all visible toasts. */\n pauseAll(): void {\n for (let toast of this.visibleToasts) {\n if (toast.timer) {\n toast.timer.pause();\n }\n }\n }\n\n /** Resumes the timers for all visible toasts. */\n resumeAll(): void {\n for (let toast of this.visibleToasts) {\n if (toast.timer) {\n toast.timer.resume();\n }\n }\n }\n\n clear(): void {\n this.queue = [];\n this.updateVisibleToasts('clear');\n }\n}\n\nclass Timer {\n private timerId;\n private startTime: number | null = null;\n private remaining: number;\n private callback: () => void;\n\n constructor(callback: () => void, delay: number) {\n this.remaining = delay;\n this.callback = callback;\n }\n\n reset(delay: number) {\n this.remaining = delay;\n this.resume();\n }\n\n pause() {\n if (this.timerId == null) {\n return;\n }\n\n clearTimeout(this.timerId);\n this.timerId = null;\n this.remaining -= Date.now() - this.startTime!;\n }\n\n resume() {\n if (this.remaining <= 0) {\n return;\n }\n\n this.startTime = Date.now();\n this.timerId = setTimeout(() => {\n this.timerId = null;\n this.remaining = 0;\n this.callback();\n }, this.remaining);\n }\n}\n"],"names":[],"version":3,"file":"useToastState.main.js.map"}
@@ -14,13 +14,13 @@ import {useSyncExternalStore as $cNx9A$useSyncExternalStore} from "use-sync-exte
14
14
  */
15
15
 
16
16
  function $77b352cf12efcf73$export$c7b26b20d3ced9c5(props = {}) {
17
- let { maxVisibleToasts: maxVisibleToasts = 1, hasExitAnimation: hasExitAnimation = false } = props;
17
+ let { maxVisibleToasts: maxVisibleToasts = 1, wrapUpdate: wrapUpdate } = props;
18
18
  let queue = (0, $cNx9A$useMemo)(()=>new $77b352cf12efcf73$export$f1f8569633bbbec4({
19
19
  maxVisibleToasts: maxVisibleToasts,
20
- hasExitAnimation: hasExitAnimation
20
+ wrapUpdate: wrapUpdate
21
21
  }), [
22
22
  maxVisibleToasts,
23
- hasExitAnimation
23
+ wrapUpdate
24
24
  ]);
25
25
  return $77b352cf12efcf73$export$84726ef35ca2129a(queue);
26
26
  }
@@ -36,43 +36,33 @@ function $77b352cf12efcf73$export$84726ef35ca2129a(queue) {
36
36
  visibleToasts: visibleToasts,
37
37
  add: (content, options)=>queue.add(content, options),
38
38
  close: (key)=>queue.close(key),
39
- remove: (key)=>queue.remove(key),
40
39
  pauseAll: ()=>queue.pauseAll(),
41
40
  resumeAll: ()=>queue.resumeAll()
42
41
  };
43
42
  }
44
43
  class $77b352cf12efcf73$export$f1f8569633bbbec4 {
44
+ runWithWrapUpdate(fn, action) {
45
+ if (this.wrapUpdate) this.wrapUpdate(fn, action);
46
+ else fn();
47
+ }
45
48
  /** Subscribes to updates to the visible toasts. */ subscribe(fn) {
46
49
  this.subscriptions.add(fn);
47
50
  return ()=>this.subscriptions.delete(fn);
48
51
  }
49
52
  /** Adds a new toast to the queue. */ add(content, options = {}) {
50
- let toastKey = Math.random().toString(36);
53
+ let toastKey = '_' + Math.random().toString(36).slice(2);
51
54
  let toast = {
52
55
  ...options,
53
56
  content: content,
54
57
  key: toastKey,
55
- timer: options.timeout ? new $77b352cf12efcf73$var$Timer(()=>this.close(toastKey), options.timeout) : null
58
+ timer: options.timeout ? new $77b352cf12efcf73$var$Timer(()=>this.close(toastKey), options.timeout) : undefined
56
59
  };
57
- let low = 0;
58
- let high = this.queue.length;
59
- while(low < high){
60
- let mid = Math.floor((low + high) / 2);
61
- if ((toast.priority || 0) > (this.queue[mid].priority || 0)) high = mid;
62
- else low = mid + 1;
63
- }
64
- this.queue.splice(low, 0, toast);
65
- toast.animation = low < this.maxVisibleToasts ? 'entering' : 'queued';
66
- let i = this.maxVisibleToasts;
67
- while(i < this.queue.length)this.queue[i++].animation = 'queued';
68
- this.updateVisibleToasts({
69
- action: 'add'
70
- });
60
+ this.queue.unshift(toast);
61
+ this.updateVisibleToasts('add');
71
62
  return toastKey;
72
63
  }
73
64
  /**
74
- * Closes a toast. If `hasExitAnimation` is true, the toast
75
- * transitions to an "exiting" state instead of being removed immediately.
65
+ * Closes a toast.
76
66
  */ close(key) {
77
67
  let index = this.queue.findIndex((t)=>t.key === key);
78
68
  if (index >= 0) {
@@ -80,36 +70,13 @@ class $77b352cf12efcf73$export$f1f8569633bbbec4 {
80
70
  (_this_queue_index_onClose = (_this_queue_index = this.queue[index]).onClose) === null || _this_queue_index_onClose === void 0 ? void 0 : _this_queue_index_onClose.call(_this_queue_index);
81
71
  this.queue.splice(index, 1);
82
72
  }
83
- this.updateVisibleToasts({
84
- action: 'close',
85
- key: key
86
- });
87
- }
88
- /** Removes a toast from the visible toasts after an exiting animation. */ remove(key) {
89
- this.updateVisibleToasts({
90
- action: 'remove',
91
- key: key
92
- });
73
+ this.updateVisibleToasts('remove');
93
74
  }
94
- updateVisibleToasts(options) {
95
- let { action: action, key: key } = options;
96
- let toasts = this.queue.slice(0, this.maxVisibleToasts);
97
- if (action === 'add' && this.hasExitAnimation) {
98
- let prevToasts = this.visibleToasts.filter((t)=>!toasts.some((t2)=>t.key === t2.key)).map((t)=>({
99
- ...t,
100
- animation: 'exiting'
101
- }));
102
- this.visibleToasts = prevToasts.concat(toasts).sort((a, b)=>b.priority - a.priority);
103
- } else if (action === 'close' && this.hasExitAnimation) // Cause a rerender to happen for exit animation
104
- this.visibleToasts = this.visibleToasts.map((t)=>{
105
- if (t.key !== key) return t;
106
- else return {
107
- ...t,
108
- animation: 'exiting'
109
- };
110
- });
111
- else this.visibleToasts = toasts;
112
- for (let fn of this.subscriptions)fn();
75
+ updateVisibleToasts(action) {
76
+ this.visibleToasts = this.queue.slice(0, this.maxVisibleToasts);
77
+ this.runWithWrapUpdate(()=>{
78
+ for (let fn of this.subscriptions)fn();
79
+ }, action);
113
80
  }
114
81
  /** Pauses the timers for all visible toasts. */ pauseAll() {
115
82
  for (let toast of this.visibleToasts)if (toast.timer) toast.timer.pause();
@@ -117,14 +84,17 @@ class $77b352cf12efcf73$export$f1f8569633bbbec4 {
117
84
  /** Resumes the timers for all visible toasts. */ resumeAll() {
118
85
  for (let toast of this.visibleToasts)if (toast.timer) toast.timer.resume();
119
86
  }
87
+ clear() {
88
+ this.queue = [];
89
+ this.updateVisibleToasts('clear');
90
+ }
120
91
  constructor(options){
121
92
  this.queue = [];
122
93
  this.subscriptions = new Set();
123
94
  /** The currently visible toasts. */ this.visibleToasts = [];
124
95
  var _options_maxVisibleToasts;
125
- this.maxVisibleToasts = (_options_maxVisibleToasts = options === null || options === void 0 ? void 0 : options.maxVisibleToasts) !== null && _options_maxVisibleToasts !== void 0 ? _options_maxVisibleToasts : 1;
126
- var _options_hasExitAnimation;
127
- this.hasExitAnimation = (_options_hasExitAnimation = options === null || options === void 0 ? void 0 : options.hasExitAnimation) !== null && _options_hasExitAnimation !== void 0 ? _options_hasExitAnimation : false;
96
+ this.maxVisibleToasts = (_options_maxVisibleToasts = options === null || options === void 0 ? void 0 : options.maxVisibleToasts) !== null && _options_maxVisibleToasts !== void 0 ? _options_maxVisibleToasts : Infinity;
97
+ this.wrapUpdate = options === null || options === void 0 ? void 0 : options.wrapUpdate;
128
98
  }
129
99
  }
130
100
  class $77b352cf12efcf73$var$Timer {
@@ -148,6 +118,7 @@ class $77b352cf12efcf73$var$Timer {
148
118
  }, this.remaining);
149
119
  }
150
120
  constructor(callback, delay){
121
+ this.startTime = null;
151
122
  this.remaining = delay;
152
123
  this.callback = callback;
153
124
  }
@@ -14,13 +14,13 @@ import {useSyncExternalStore as $cNx9A$useSyncExternalStore} from "use-sync-exte
14
14
  */
15
15
 
16
16
  function $77b352cf12efcf73$export$c7b26b20d3ced9c5(props = {}) {
17
- let { maxVisibleToasts: maxVisibleToasts = 1, hasExitAnimation: hasExitAnimation = false } = props;
17
+ let { maxVisibleToasts: maxVisibleToasts = 1, wrapUpdate: wrapUpdate } = props;
18
18
  let queue = (0, $cNx9A$useMemo)(()=>new $77b352cf12efcf73$export$f1f8569633bbbec4({
19
19
  maxVisibleToasts: maxVisibleToasts,
20
- hasExitAnimation: hasExitAnimation
20
+ wrapUpdate: wrapUpdate
21
21
  }), [
22
22
  maxVisibleToasts,
23
- hasExitAnimation
23
+ wrapUpdate
24
24
  ]);
25
25
  return $77b352cf12efcf73$export$84726ef35ca2129a(queue);
26
26
  }
@@ -36,43 +36,33 @@ function $77b352cf12efcf73$export$84726ef35ca2129a(queue) {
36
36
  visibleToasts: visibleToasts,
37
37
  add: (content, options)=>queue.add(content, options),
38
38
  close: (key)=>queue.close(key),
39
- remove: (key)=>queue.remove(key),
40
39
  pauseAll: ()=>queue.pauseAll(),
41
40
  resumeAll: ()=>queue.resumeAll()
42
41
  };
43
42
  }
44
43
  class $77b352cf12efcf73$export$f1f8569633bbbec4 {
44
+ runWithWrapUpdate(fn, action) {
45
+ if (this.wrapUpdate) this.wrapUpdate(fn, action);
46
+ else fn();
47
+ }
45
48
  /** Subscribes to updates to the visible toasts. */ subscribe(fn) {
46
49
  this.subscriptions.add(fn);
47
50
  return ()=>this.subscriptions.delete(fn);
48
51
  }
49
52
  /** Adds a new toast to the queue. */ add(content, options = {}) {
50
- let toastKey = Math.random().toString(36);
53
+ let toastKey = '_' + Math.random().toString(36).slice(2);
51
54
  let toast = {
52
55
  ...options,
53
56
  content: content,
54
57
  key: toastKey,
55
- timer: options.timeout ? new $77b352cf12efcf73$var$Timer(()=>this.close(toastKey), options.timeout) : null
58
+ timer: options.timeout ? new $77b352cf12efcf73$var$Timer(()=>this.close(toastKey), options.timeout) : undefined
56
59
  };
57
- let low = 0;
58
- let high = this.queue.length;
59
- while(low < high){
60
- let mid = Math.floor((low + high) / 2);
61
- if ((toast.priority || 0) > (this.queue[mid].priority || 0)) high = mid;
62
- else low = mid + 1;
63
- }
64
- this.queue.splice(low, 0, toast);
65
- toast.animation = low < this.maxVisibleToasts ? 'entering' : 'queued';
66
- let i = this.maxVisibleToasts;
67
- while(i < this.queue.length)this.queue[i++].animation = 'queued';
68
- this.updateVisibleToasts({
69
- action: 'add'
70
- });
60
+ this.queue.unshift(toast);
61
+ this.updateVisibleToasts('add');
71
62
  return toastKey;
72
63
  }
73
64
  /**
74
- * Closes a toast. If `hasExitAnimation` is true, the toast
75
- * transitions to an "exiting" state instead of being removed immediately.
65
+ * Closes a toast.
76
66
  */ close(key) {
77
67
  let index = this.queue.findIndex((t)=>t.key === key);
78
68
  if (index >= 0) {
@@ -80,36 +70,13 @@ class $77b352cf12efcf73$export$f1f8569633bbbec4 {
80
70
  (_this_queue_index_onClose = (_this_queue_index = this.queue[index]).onClose) === null || _this_queue_index_onClose === void 0 ? void 0 : _this_queue_index_onClose.call(_this_queue_index);
81
71
  this.queue.splice(index, 1);
82
72
  }
83
- this.updateVisibleToasts({
84
- action: 'close',
85
- key: key
86
- });
87
- }
88
- /** Removes a toast from the visible toasts after an exiting animation. */ remove(key) {
89
- this.updateVisibleToasts({
90
- action: 'remove',
91
- key: key
92
- });
73
+ this.updateVisibleToasts('remove');
93
74
  }
94
- updateVisibleToasts(options) {
95
- let { action: action, key: key } = options;
96
- let toasts = this.queue.slice(0, this.maxVisibleToasts);
97
- if (action === 'add' && this.hasExitAnimation) {
98
- let prevToasts = this.visibleToasts.filter((t)=>!toasts.some((t2)=>t.key === t2.key)).map((t)=>({
99
- ...t,
100
- animation: 'exiting'
101
- }));
102
- this.visibleToasts = prevToasts.concat(toasts).sort((a, b)=>b.priority - a.priority);
103
- } else if (action === 'close' && this.hasExitAnimation) // Cause a rerender to happen for exit animation
104
- this.visibleToasts = this.visibleToasts.map((t)=>{
105
- if (t.key !== key) return t;
106
- else return {
107
- ...t,
108
- animation: 'exiting'
109
- };
110
- });
111
- else this.visibleToasts = toasts;
112
- for (let fn of this.subscriptions)fn();
75
+ updateVisibleToasts(action) {
76
+ this.visibleToasts = this.queue.slice(0, this.maxVisibleToasts);
77
+ this.runWithWrapUpdate(()=>{
78
+ for (let fn of this.subscriptions)fn();
79
+ }, action);
113
80
  }
114
81
  /** Pauses the timers for all visible toasts. */ pauseAll() {
115
82
  for (let toast of this.visibleToasts)if (toast.timer) toast.timer.pause();
@@ -117,14 +84,17 @@ class $77b352cf12efcf73$export$f1f8569633bbbec4 {
117
84
  /** Resumes the timers for all visible toasts. */ resumeAll() {
118
85
  for (let toast of this.visibleToasts)if (toast.timer) toast.timer.resume();
119
86
  }
87
+ clear() {
88
+ this.queue = [];
89
+ this.updateVisibleToasts('clear');
90
+ }
120
91
  constructor(options){
121
92
  this.queue = [];
122
93
  this.subscriptions = new Set();
123
94
  /** The currently visible toasts. */ this.visibleToasts = [];
124
95
  var _options_maxVisibleToasts;
125
- this.maxVisibleToasts = (_options_maxVisibleToasts = options === null || options === void 0 ? void 0 : options.maxVisibleToasts) !== null && _options_maxVisibleToasts !== void 0 ? _options_maxVisibleToasts : 1;
126
- var _options_hasExitAnimation;
127
- this.hasExitAnimation = (_options_hasExitAnimation = options === null || options === void 0 ? void 0 : options.hasExitAnimation) !== null && _options_hasExitAnimation !== void 0 ? _options_hasExitAnimation : false;
96
+ this.maxVisibleToasts = (_options_maxVisibleToasts = options === null || options === void 0 ? void 0 : options.maxVisibleToasts) !== null && _options_maxVisibleToasts !== void 0 ? _options_maxVisibleToasts : Infinity;
97
+ this.wrapUpdate = options === null || options === void 0 ? void 0 : options.wrapUpdate;
128
98
  }
129
99
  }
130
100
  class $77b352cf12efcf73$var$Timer {
@@ -148,6 +118,7 @@ class $77b352cf12efcf73$var$Timer {
148
118
  }, this.remaining);
149
119
  }
150
120
  constructor(callback, delay){
121
+ this.startTime = null;
151
122
  this.remaining = delay;
152
123
  this.callback = callback;
153
124
  }
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-stately/toast/src/useToastState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {useCallback, useMemo} from 'react';\n// Shim to support React 17 and below.\nimport {useSyncExternalStore} from 'use-sync-external-store/shim/index.js';\n\nexport interface ToastStateProps {\n /** The maximum number of toasts to display at a time. */\n maxVisibleToasts?: number,\n /**\n * Whether toasts have an exit animation. If true, toasts are not\n * removed immediately but transition into an \"exiting\" state instead.\n * Once the animation is complete, call the `remove` function.\n */\n hasExitAnimation?: boolean\n}\n\nexport interface ToastOptions {\n /** Handler that is called when the toast is closed, either by the user or after a timeout. */\n onClose?: () => void,\n /** A timeout to automatically close the toast after, in milliseconds. */\n timeout?: number,\n /** The priority of the toast relative to other toasts. Larger numbers indicate higher priority. */\n priority?: number\n}\n\nexport interface QueuedToast<T> extends ToastOptions {\n /** The content of the toast. */\n content: T,\n /** A unique key for the toast. */\n key: string,\n /** A timer for the toast, if a timeout was set. */\n timer?: Timer,\n /** The current animation state for the toast. */\n animation?: 'entering' | 'queued' | 'exiting'\n}\n\nexport interface ToastState<T> {\n /** Adds a new toast to the queue. */\n add(content: T, options?: ToastOptions): string,\n /**\n * Closes a toast. If `hasExitAnimation` is true, the toast\n * transitions to an \"exiting\" state instead of being removed immediately.\n */\n close(key: string): void,\n /** Removes a toast from the visible toasts after an exiting animation. */\n remove(key: string): void,\n /** Pauses the timers for all visible toasts. */\n pauseAll(): void,\n /** Resumes the timers for all visible toasts. */\n resumeAll(): void,\n /** The visible toasts. */\n visibleToasts: QueuedToast<T>[]\n}\n\n/**\n * Provides state management for a toast queue. Toasts display brief, temporary notifications\n * of actions, errors, or other events in an application.\n */\nexport function useToastState<T>(props: ToastStateProps = {}): ToastState<T> {\n let {maxVisibleToasts = 1, hasExitAnimation = false} = props;\n let queue = useMemo(() => new ToastQueue<T>({maxVisibleToasts, hasExitAnimation}), [maxVisibleToasts, hasExitAnimation]);\n return useToastQueue(queue);\n}\n\n/**\n * Subscribes to a provided toast queue and provides methods to update it.\n */\nexport function useToastQueue<T>(queue: ToastQueue<T>): ToastState<T> {\n let subscribe = useCallback(fn => queue.subscribe(fn), [queue]);\n let getSnapshot = useCallback(() => queue.visibleToasts, [queue]);\n let visibleToasts = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return {\n visibleToasts,\n add: (content, options) => queue.add(content, options),\n close: key => queue.close(key),\n remove: key => queue.remove(key),\n pauseAll: () => queue.pauseAll(),\n resumeAll: () => queue.resumeAll()\n };\n}\n\n/**\n * A ToastQueue is a priority queue of toasts.\n */\nexport class ToastQueue<T> {\n private queue: QueuedToast<T>[] = [];\n private subscriptions: Set<() => void> = new Set();\n private maxVisibleToasts: number;\n private hasExitAnimation: boolean;\n /** The currently visible toasts. */\n visibleToasts: QueuedToast<T>[] = [];\n\n constructor(options?: ToastStateProps) {\n this.maxVisibleToasts = options?.maxVisibleToasts ?? 1;\n this.hasExitAnimation = options?.hasExitAnimation ?? false;\n }\n\n /** Subscribes to updates to the visible toasts. */\n subscribe(fn: () => void) {\n this.subscriptions.add(fn);\n return () => this.subscriptions.delete(fn);\n }\n\n /** Adds a new toast to the queue. */\n add(content: T, options: ToastOptions = {}) {\n let toastKey = Math.random().toString(36);\n let toast: QueuedToast<T> = {\n ...options,\n content,\n key: toastKey,\n timer: options.timeout ? new Timer(() => this.close(toastKey), options.timeout) : null\n };\n\n let low = 0;\n let high = this.queue.length;\n while (low < high) {\n let mid = Math.floor((low + high) / 2);\n if ((toast.priority || 0) > (this.queue[mid].priority || 0)) {\n high = mid;\n } else {\n low = mid + 1;\n }\n }\n\n this.queue.splice(low, 0, toast);\n\n toast.animation = low < this.maxVisibleToasts ? 'entering' : 'queued';\n let i = this.maxVisibleToasts;\n while (i < this.queue.length) {\n this.queue[i++].animation = 'queued';\n }\n\n this.updateVisibleToasts({action: 'add'});\n return toastKey;\n }\n\n /**\n * Closes a toast. If `hasExitAnimation` is true, the toast\n * transitions to an \"exiting\" state instead of being removed immediately.\n */\n close(key: string) {\n let index = this.queue.findIndex(t => t.key === key);\n if (index >= 0) {\n this.queue[index].onClose?.();\n this.queue.splice(index, 1);\n }\n\n this.updateVisibleToasts({action: 'close', key});\n }\n\n /** Removes a toast from the visible toasts after an exiting animation. */\n remove(key: string) {\n this.updateVisibleToasts({action: 'remove', key});\n }\n\n private updateVisibleToasts(options: {action: 'add' | 'close' | 'remove', key?: string}) {\n let {action, key} = options;\n let toasts = this.queue.slice(0, this.maxVisibleToasts);\n\n if (action === 'add' && this.hasExitAnimation) {\n let prevToasts: QueuedToast<T>[] = this.visibleToasts\n .filter(t => !toasts.some(t2 => t.key === t2.key))\n .map(t => ({...t, animation: 'exiting'}));\n this.visibleToasts = prevToasts.concat(toasts).sort((a, b) => b.priority - a.priority);\n } else if (action === 'close' && this.hasExitAnimation) {\n // Cause a rerender to happen for exit animation\n this.visibleToasts = this.visibleToasts.map(t => {\n if (t.key !== key) {\n return t;\n } else {\n return {...t, animation: 'exiting'};\n }\n });\n } else {\n this.visibleToasts = toasts;\n }\n\n for (let fn of this.subscriptions) {\n fn();\n }\n }\n\n /** Pauses the timers for all visible toasts. */\n pauseAll() {\n for (let toast of this.visibleToasts) {\n if (toast.timer) {\n toast.timer.pause();\n }\n }\n }\n\n /** Resumes the timers for all visible toasts. */\n resumeAll() {\n for (let toast of this.visibleToasts) {\n if (toast.timer) {\n toast.timer.resume();\n }\n }\n }\n}\n\nclass Timer {\n private timerId;\n private startTime: number;\n private remaining: number;\n private callback: () => void;\n\n constructor(callback: () => void, delay: number) {\n this.remaining = delay;\n this.callback = callback;\n }\n\n reset(delay: number) {\n this.remaining = delay;\n this.resume();\n }\n\n pause() {\n if (this.timerId == null) {\n return;\n }\n\n clearTimeout(this.timerId);\n this.timerId = null;\n this.remaining -= Date.now() - this.startTime;\n }\n\n resume() {\n if (this.remaining <= 0) {\n return;\n }\n\n this.startTime = Date.now();\n this.timerId = setTimeout(() => {\n this.timerId = null;\n this.remaining = 0;\n this.callback();\n }, this.remaining);\n }\n}\n"],"names":[],"version":3,"file":"useToastState.module.js.map"}
1
+ {"mappings":";;;AAAA;;;;;;;;;;CAUC;;AAiDM,SAAS,0CAAiB,QAAyB,CAAC,CAAC;IAC1D,IAAI,oBAAC,mBAAmB,eAAG,UAAU,EAAC,GAAG;IACzC,IAAI,QAAQ,CAAA,GAAA,cAAM,EAAE,IAAM,IAAI,0CAAc;8BAAC;wBAAkB;QAAU,IAAI;QAAC;QAAkB;KAAW;IAC3G,OAAO,0CAAc;AACvB;AAKO,SAAS,0CAAiB,KAAoB;IACnD,IAAI,YAAY,CAAA,GAAA,kBAAU,EAAE,CAAA,KAAM,MAAM,SAAS,CAAC,KAAK;QAAC;KAAM;IAC9D,IAAI,cAAc,CAAA,GAAA,kBAAU,EAAE,IAAM,MAAM,aAAa,EAAE;QAAC;KAAM;IAChE,IAAI,gBAAgB,CAAA,GAAA,2BAAmB,EAAE,WAAW,aAAa;IAEjE,OAAO;uBACL;QACA,KAAK,CAAC,SAAS,UAAY,MAAM,GAAG,CAAC,SAAS;QAC9C,OAAO,CAAA,MAAO,MAAM,KAAK,CAAC;QAC1B,UAAU,IAAM,MAAM,QAAQ;QAC9B,WAAW,IAAM,MAAM,SAAS;IAClC;AACF;AAKO,MAAM;IAaH,kBAAkB,EAAc,EAAE,MAAmB,EAAQ;QACnE,IAAI,IAAI,CAAC,UAAU,EACjB,IAAI,CAAC,UAAU,CAAC,IAAI;aAEpB;IAEJ;IAEA,iDAAiD,GACjD,UAAU,EAAc,EAAc;QACpC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;QACvB,OAAO,IAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;IACzC;IAEA,mCAAmC,GACnC,IAAI,OAAU,EAAE,UAAwB,CAAC,CAAC,EAAU;QAClD,IAAI,WAAW,MAAM,KAAK,MAAM,GAAG,QAAQ,CAAC,IAAI,KAAK,CAAC;QACtD,IAAI,QAAwB;YAC1B,GAAG,OAAO;qBACV;YACA,KAAK;YACL,OAAO,QAAQ,OAAO,GAAG,IAAI,4BAAM,IAAM,IAAI,CAAC,KAAK,CAAC,WAAW,QAAQ,OAAO,IAAI;QACpF;QAEA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QAEnB,IAAI,CAAC,mBAAmB,CAAC;QACzB,OAAO;IACT;IAEA;;GAEC,GACD,MAAM,GAAW,EAAQ;QACvB,IAAI,QAAQ,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA,IAAK,EAAE,GAAG,KAAK;QAChD,IAAI,SAAS,GAAG;gBACd,2BAAA;aAAA,4BAAA,CAAA,oBAAA,IAAI,CAAC,KAAK,CAAC,MAAM,EAAC,OAAO,cAAzB,gDAAA,+BAAA;YACA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO;QAC3B;QAEA,IAAI,CAAC,mBAAmB,CAAC;IAC3B;IAEQ,oBAAoB,MAAmB,EAAE;QAC/C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,gBAAgB;QAE9D,IAAI,CAAC,iBAAiB,CAAC;YACrB,KAAK,IAAI,MAAM,IAAI,CAAC,aAAa,CAC/B;QAEJ,GAAG;IACL;IAEA,8CAA8C,GAC9C,WAAiB;QACf,KAAK,IAAI,SAAS,IAAI,CAAC,aAAa,CAClC,IAAI,MAAM,KAAK,EACb,MAAM,KAAK,CAAC,KAAK;IAGvB;IAEA,+CAA+C,GAC/C,YAAkB;QAChB,KAAK,IAAI,SAAS,IAAI,CAAC,aAAa,CAClC,IAAI,MAAM,KAAK,EACb,MAAM,KAAK,CAAC,MAAM;IAGxB;IAEA,QAAc;QACZ,IAAI,CAAC,KAAK,GAAG,EAAE;QACf,IAAI,CAAC,mBAAmB,CAAC;IAC3B;IA/EA,YAAY,OAAyB,CAAE;aAP/B,QAA0B,EAAE;aAC5B,gBAAiC,IAAI;QAG7C,kCAAkC,QAClC,gBAAkC,EAAE;YAGV;QAAxB,IAAI,CAAC,gBAAgB,GAAG,CAAA,4BAAA,oBAAA,8BAAA,QAAS,gBAAgB,cAAzB,uCAAA,4BAA6B;QACrD,IAAI,CAAC,UAAU,GAAG,oBAAA,8BAAA,QAAS,UAAU;IACvC;AA6EF;AAEA,MAAM;IAWJ,MAAM,KAAa,EAAE;QACnB,IAAI,CAAC,SAAS,GAAG;QACjB,IAAI,CAAC,MAAM;IACb;IAEA,QAAQ;QACN,IAAI,IAAI,CAAC,OAAO,IAAI,MAClB;QAGF,aAAa,IAAI,CAAC,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG;QACf,IAAI,CAAC,SAAS,IAAI,KAAK,GAAG,KAAK,IAAI,CAAC,SAAS;IAC/C;IAEA,SAAS;QACP,IAAI,IAAI,CAAC,SAAS,IAAI,GACpB;QAGF,IAAI,CAAC,SAAS,GAAG,KAAK,GAAG;QACzB,IAAI,CAAC,OAAO,GAAG,WAAW;YACxB,IAAI,CAAC,OAAO,GAAG;YACf,IAAI,CAAC,SAAS,GAAG;YACjB,IAAI,CAAC,QAAQ;QACf,GAAG,IAAI,CAAC,SAAS;IACnB;IA/BA,YAAY,QAAoB,EAAE,KAAa,CAAE;aAJzC,YAA2B;QAKjC,IAAI,CAAC,SAAS,GAAG;QACjB,IAAI,CAAC,QAAQ,GAAG;IAClB;AA6BF","sources":["packages/@react-stately/toast/src/useToastState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {useCallback, useMemo} from 'react';\n// Shim to support React 17 and below.\nimport {useSyncExternalStore} from 'use-sync-external-store/shim/index.js';\n\ntype ToastAction = 'add' | 'remove' | 'clear';\nexport interface ToastStateProps {\n /** The maximum number of toasts to display at a time. */\n maxVisibleToasts?: number,\n /** Function to wrap updates in (i.e. document.startViewTransition()). */\n wrapUpdate?: (fn: () => void, action: ToastAction) => void\n}\n\nexport interface ToastOptions {\n /** Handler that is called when the toast is closed, either by the user or after a timeout. */\n onClose?: () => void,\n /** A timeout to automatically close the toast after, in milliseconds. */\n timeout?: number\n}\n\nexport interface QueuedToast<T> extends ToastOptions {\n /** The content of the toast. */\n content: T,\n /** A unique key for the toast. */\n key: string,\n /** A timer for the toast, if a timeout was set. */\n timer?: Timer\n}\n\nexport interface ToastState<T> {\n /** Adds a new toast to the queue. */\n add(content: T, options?: ToastOptions): string,\n /**\n * Closes a toast.\n */\n close(key: string): void,\n /** Pauses the timers for all visible toasts. */\n pauseAll(): void,\n /** Resumes the timers for all visible toasts. */\n resumeAll(): void,\n /** The visible toasts. */\n visibleToasts: QueuedToast<T>[]\n}\n\n/**\n * Provides state management for a toast queue. Toasts display brief, temporary notifications\n * of actions, errors, or other events in an application.\n */\nexport function useToastState<T>(props: ToastStateProps = {}): ToastState<T> {\n let {maxVisibleToasts = 1, wrapUpdate} = props;\n let queue = useMemo(() => new ToastQueue<T>({maxVisibleToasts, wrapUpdate}), [maxVisibleToasts, wrapUpdate]);\n return useToastQueue(queue);\n}\n\n/**\n * Subscribes to a provided toast queue and provides methods to update it.\n */\nexport function useToastQueue<T>(queue: ToastQueue<T>): ToastState<T> {\n let subscribe = useCallback(fn => queue.subscribe(fn), [queue]);\n let getSnapshot = useCallback(() => queue.visibleToasts, [queue]);\n let visibleToasts = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n return {\n visibleToasts,\n add: (content, options) => queue.add(content, options),\n close: key => queue.close(key),\n pauseAll: () => queue.pauseAll(),\n resumeAll: () => queue.resumeAll()\n };\n}\n\n/**\n * A ToastQueue manages the order of toasts.\n */\nexport class ToastQueue<T> {\n private queue: QueuedToast<T>[] = [];\n private subscriptions: Set<() => void> = new Set();\n private maxVisibleToasts: number;\n private wrapUpdate?: (fn: () => void, action: ToastAction) => void;\n /** The currently visible toasts. */\n visibleToasts: QueuedToast<T>[] = [];\n\n constructor(options?: ToastStateProps) {\n this.maxVisibleToasts = options?.maxVisibleToasts ?? Infinity;\n this.wrapUpdate = options?.wrapUpdate;\n }\n\n private runWithWrapUpdate(fn: () => void, action: ToastAction): void {\n if (this.wrapUpdate) {\n this.wrapUpdate(fn, action);\n } else {\n fn();\n }\n }\n\n /** Subscribes to updates to the visible toasts. */\n subscribe(fn: () => void): () => void {\n this.subscriptions.add(fn);\n return () => this.subscriptions.delete(fn);\n }\n\n /** Adds a new toast to the queue. */\n add(content: T, options: ToastOptions = {}): string {\n let toastKey = '_' + Math.random().toString(36).slice(2);\n let toast: QueuedToast<T> = {\n ...options,\n content,\n key: toastKey,\n timer: options.timeout ? new Timer(() => this.close(toastKey), options.timeout) : undefined\n };\n\n this.queue.unshift(toast);\n\n this.updateVisibleToasts('add');\n return toastKey;\n }\n\n /**\n * Closes a toast.\n */\n close(key: string): void {\n let index = this.queue.findIndex(t => t.key === key);\n if (index >= 0) {\n this.queue[index].onClose?.();\n this.queue.splice(index, 1);\n }\n\n this.updateVisibleToasts('remove');\n }\n\n private updateVisibleToasts(action: ToastAction) {\n this.visibleToasts = this.queue.slice(0, this.maxVisibleToasts);\n\n this.runWithWrapUpdate(() => {\n for (let fn of this.subscriptions) {\n fn();\n }\n }, action);\n }\n\n /** Pauses the timers for all visible toasts. */\n pauseAll(): void {\n for (let toast of this.visibleToasts) {\n if (toast.timer) {\n toast.timer.pause();\n }\n }\n }\n\n /** Resumes the timers for all visible toasts. */\n resumeAll(): void {\n for (let toast of this.visibleToasts) {\n if (toast.timer) {\n toast.timer.resume();\n }\n }\n }\n\n clear(): void {\n this.queue = [];\n this.updateVisibleToasts('clear');\n }\n}\n\nclass Timer {\n private timerId;\n private startTime: number | null = null;\n private remaining: number;\n private callback: () => void;\n\n constructor(callback: () => void, delay: number) {\n this.remaining = delay;\n this.callback = callback;\n }\n\n reset(delay: number) {\n this.remaining = delay;\n this.resume();\n }\n\n pause() {\n if (this.timerId == null) {\n return;\n }\n\n clearTimeout(this.timerId);\n this.timerId = null;\n this.remaining -= Date.now() - this.startTime!;\n }\n\n resume() {\n if (this.remaining <= 0) {\n return;\n }\n\n this.startTime = Date.now();\n this.timerId = setTimeout(() => {\n this.timerId = null;\n this.remaining = 0;\n this.callback();\n }, this.remaining);\n }\n}\n"],"names":[],"version":3,"file":"useToastState.module.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-stately/toast",
3
- "version": "3.0.0-nightly.5042+68403fe55",
3
+ "version": "3.1.0",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -23,16 +23,16 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "@swc/helpers": "^0.5.0",
26
- "use-sync-external-store": "^1.2.0"
26
+ "use-sync-external-store": "^1.4.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/use-sync-external-store": "^0.0.3"
30
30
  },
31
31
  "peerDependencies": {
32
- "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0"
32
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
33
33
  },
34
34
  "publishConfig": {
35
35
  "access": "public"
36
36
  },
37
- "gitHead": "68403fe55489dce3de1b3094c957d598ad719861"
37
+ "gitHead": "9b66d270572f482948afee95622a85cdf68ed408"
38
38
  }
@@ -14,24 +14,19 @@ import {useCallback, useMemo} from 'react';
14
14
  // Shim to support React 17 and below.
15
15
  import {useSyncExternalStore} from 'use-sync-external-store/shim/index.js';
16
16
 
17
+ type ToastAction = 'add' | 'remove' | 'clear';
17
18
  export interface ToastStateProps {
18
19
  /** The maximum number of toasts to display at a time. */
19
20
  maxVisibleToasts?: number,
20
- /**
21
- * Whether toasts have an exit animation. If true, toasts are not
22
- * removed immediately but transition into an "exiting" state instead.
23
- * Once the animation is complete, call the `remove` function.
24
- */
25
- hasExitAnimation?: boolean
21
+ /** Function to wrap updates in (i.e. document.startViewTransition()). */
22
+ wrapUpdate?: (fn: () => void, action: ToastAction) => void
26
23
  }
27
24
 
28
25
  export interface ToastOptions {
29
26
  /** Handler that is called when the toast is closed, either by the user or after a timeout. */
30
27
  onClose?: () => void,
31
28
  /** A timeout to automatically close the toast after, in milliseconds. */
32
- timeout?: number,
33
- /** The priority of the toast relative to other toasts. Larger numbers indicate higher priority. */
34
- priority?: number
29
+ timeout?: number
35
30
  }
36
31
 
37
32
  export interface QueuedToast<T> extends ToastOptions {
@@ -40,21 +35,16 @@ export interface QueuedToast<T> extends ToastOptions {
40
35
  /** A unique key for the toast. */
41
36
  key: string,
42
37
  /** A timer for the toast, if a timeout was set. */
43
- timer?: Timer,
44
- /** The current animation state for the toast. */
45
- animation?: 'entering' | 'queued' | 'exiting'
38
+ timer?: Timer
46
39
  }
47
40
 
48
41
  export interface ToastState<T> {
49
42
  /** Adds a new toast to the queue. */
50
43
  add(content: T, options?: ToastOptions): string,
51
44
  /**
52
- * Closes a toast. If `hasExitAnimation` is true, the toast
53
- * transitions to an "exiting" state instead of being removed immediately.
45
+ * Closes a toast.
54
46
  */
55
47
  close(key: string): void,
56
- /** Removes a toast from the visible toasts after an exiting animation. */
57
- remove(key: string): void,
58
48
  /** Pauses the timers for all visible toasts. */
59
49
  pauseAll(): void,
60
50
  /** Resumes the timers for all visible toasts. */
@@ -68,8 +58,8 @@ export interface ToastState<T> {
68
58
  * of actions, errors, or other events in an application.
69
59
  */
70
60
  export function useToastState<T>(props: ToastStateProps = {}): ToastState<T> {
71
- let {maxVisibleToasts = 1, hasExitAnimation = false} = props;
72
- let queue = useMemo(() => new ToastQueue<T>({maxVisibleToasts, hasExitAnimation}), [maxVisibleToasts, hasExitAnimation]);
61
+ let {maxVisibleToasts = 1, wrapUpdate} = props;
62
+ let queue = useMemo(() => new ToastQueue<T>({maxVisibleToasts, wrapUpdate}), [maxVisibleToasts, wrapUpdate]);
73
63
  return useToastQueue(queue);
74
64
  }
75
65
 
@@ -85,115 +75,82 @@ export function useToastQueue<T>(queue: ToastQueue<T>): ToastState<T> {
85
75
  visibleToasts,
86
76
  add: (content, options) => queue.add(content, options),
87
77
  close: key => queue.close(key),
88
- remove: key => queue.remove(key),
89
78
  pauseAll: () => queue.pauseAll(),
90
79
  resumeAll: () => queue.resumeAll()
91
80
  };
92
81
  }
93
82
 
94
83
  /**
95
- * A ToastQueue is a priority queue of toasts.
84
+ * A ToastQueue manages the order of toasts.
96
85
  */
97
86
  export class ToastQueue<T> {
98
87
  private queue: QueuedToast<T>[] = [];
99
88
  private subscriptions: Set<() => void> = new Set();
100
89
  private maxVisibleToasts: number;
101
- private hasExitAnimation: boolean;
90
+ private wrapUpdate?: (fn: () => void, action: ToastAction) => void;
102
91
  /** The currently visible toasts. */
103
92
  visibleToasts: QueuedToast<T>[] = [];
104
93
 
105
94
  constructor(options?: ToastStateProps) {
106
- this.maxVisibleToasts = options?.maxVisibleToasts ?? 1;
107
- this.hasExitAnimation = options?.hasExitAnimation ?? false;
95
+ this.maxVisibleToasts = options?.maxVisibleToasts ?? Infinity;
96
+ this.wrapUpdate = options?.wrapUpdate;
97
+ }
98
+
99
+ private runWithWrapUpdate(fn: () => void, action: ToastAction): void {
100
+ if (this.wrapUpdate) {
101
+ this.wrapUpdate(fn, action);
102
+ } else {
103
+ fn();
104
+ }
108
105
  }
109
106
 
110
107
  /** Subscribes to updates to the visible toasts. */
111
- subscribe(fn: () => void) {
108
+ subscribe(fn: () => void): () => void {
112
109
  this.subscriptions.add(fn);
113
110
  return () => this.subscriptions.delete(fn);
114
111
  }
115
112
 
116
113
  /** Adds a new toast to the queue. */
117
- add(content: T, options: ToastOptions = {}) {
118
- let toastKey = Math.random().toString(36);
114
+ add(content: T, options: ToastOptions = {}): string {
115
+ let toastKey = '_' + Math.random().toString(36).slice(2);
119
116
  let toast: QueuedToast<T> = {
120
117
  ...options,
121
118
  content,
122
119
  key: toastKey,
123
- timer: options.timeout ? new Timer(() => this.close(toastKey), options.timeout) : null
120
+ timer: options.timeout ? new Timer(() => this.close(toastKey), options.timeout) : undefined
124
121
  };
125
122
 
126
- let low = 0;
127
- let high = this.queue.length;
128
- while (low < high) {
129
- let mid = Math.floor((low + high) / 2);
130
- if ((toast.priority || 0) > (this.queue[mid].priority || 0)) {
131
- high = mid;
132
- } else {
133
- low = mid + 1;
134
- }
135
- }
123
+ this.queue.unshift(toast);
136
124
 
137
- this.queue.splice(low, 0, toast);
138
-
139
- toast.animation = low < this.maxVisibleToasts ? 'entering' : 'queued';
140
- let i = this.maxVisibleToasts;
141
- while (i < this.queue.length) {
142
- this.queue[i++].animation = 'queued';
143
- }
144
-
145
- this.updateVisibleToasts({action: 'add'});
125
+ this.updateVisibleToasts('add');
146
126
  return toastKey;
147
127
  }
148
128
 
149
129
  /**
150
- * Closes a toast. If `hasExitAnimation` is true, the toast
151
- * transitions to an "exiting" state instead of being removed immediately.
130
+ * Closes a toast.
152
131
  */
153
- close(key: string) {
132
+ close(key: string): void {
154
133
  let index = this.queue.findIndex(t => t.key === key);
155
134
  if (index >= 0) {
156
135
  this.queue[index].onClose?.();
157
136
  this.queue.splice(index, 1);
158
137
  }
159
138
 
160
- this.updateVisibleToasts({action: 'close', key});
161
- }
162
-
163
- /** Removes a toast from the visible toasts after an exiting animation. */
164
- remove(key: string) {
165
- this.updateVisibleToasts({action: 'remove', key});
139
+ this.updateVisibleToasts('remove');
166
140
  }
167
141
 
168
- private updateVisibleToasts(options: {action: 'add' | 'close' | 'remove', key?: string}) {
169
- let {action, key} = options;
170
- let toasts = this.queue.slice(0, this.maxVisibleToasts);
171
-
172
- if (action === 'add' && this.hasExitAnimation) {
173
- let prevToasts: QueuedToast<T>[] = this.visibleToasts
174
- .filter(t => !toasts.some(t2 => t.key === t2.key))
175
- .map(t => ({...t, animation: 'exiting'}));
176
- this.visibleToasts = prevToasts.concat(toasts).sort((a, b) => b.priority - a.priority);
177
- } else if (action === 'close' && this.hasExitAnimation) {
178
- // Cause a rerender to happen for exit animation
179
- this.visibleToasts = this.visibleToasts.map(t => {
180
- if (t.key !== key) {
181
- return t;
182
- } else {
183
- return {...t, animation: 'exiting'};
184
- }
185
- });
186
- } else {
187
- this.visibleToasts = toasts;
188
- }
142
+ private updateVisibleToasts(action: ToastAction) {
143
+ this.visibleToasts = this.queue.slice(0, this.maxVisibleToasts);
189
144
 
190
- for (let fn of this.subscriptions) {
191
- fn();
192
- }
145
+ this.runWithWrapUpdate(() => {
146
+ for (let fn of this.subscriptions) {
147
+ fn();
148
+ }
149
+ }, action);
193
150
  }
194
151
 
195
152
  /** Pauses the timers for all visible toasts. */
196
- pauseAll() {
153
+ pauseAll(): void {
197
154
  for (let toast of this.visibleToasts) {
198
155
  if (toast.timer) {
199
156
  toast.timer.pause();
@@ -202,18 +159,23 @@ export class ToastQueue<T> {
202
159
  }
203
160
 
204
161
  /** Resumes the timers for all visible toasts. */
205
- resumeAll() {
162
+ resumeAll(): void {
206
163
  for (let toast of this.visibleToasts) {
207
164
  if (toast.timer) {
208
165
  toast.timer.resume();
209
166
  }
210
167
  }
211
168
  }
169
+
170
+ clear(): void {
171
+ this.queue = [];
172
+ this.updateVisibleToasts('clear');
173
+ }
212
174
  }
213
175
 
214
176
  class Timer {
215
177
  private timerId;
216
- private startTime: number;
178
+ private startTime: number | null = null;
217
179
  private remaining: number;
218
180
  private callback: () => void;
219
181
 
@@ -234,7 +196,7 @@ class Timer {
234
196
 
235
197
  clearTimeout(this.timerId);
236
198
  this.timerId = null;
237
- this.remaining -= Date.now() - this.startTime;
199
+ this.remaining -= Date.now() - this.startTime!;
238
200
  }
239
201
 
240
202
  resume() {