@mustib/web-components 0.0.0-alpha.5 → 0.0.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,189 @@
1
+ import { C as CustomEventEmitter } from '../common-BBjg-zl9.js';
2
+ import { T as TOAST_LOCK_SYMBOL } from '../constants-DPnKJ57t.js';
3
+ import { Toast } from './Toast.js';
4
+
5
+ class ToastController {
6
+ get maxVisibleToastsCount() {
7
+ return this._maxVisibleToastsCount;
8
+ }
9
+ set maxVisibleToastsCount(value) {
10
+ this._maxVisibleToastsCount = value;
11
+ this.rolloverQueuedToasts();
12
+ }
13
+ get position() {
14
+ return this.portal.position;
15
+ }
16
+ set position(value) {
17
+ this.portal.position = value;
18
+ }
19
+ set stackToasts(value) {
20
+ this._stackToasts = value;
21
+ this.portal.requestUpdate();
22
+ }
23
+ /**
24
+ * Indicates if toast notifications should stack atop each other,
25
+ * such that only the latest is fully visible while older toasts
26
+ * are partially hidden beneath it. This enhances focus and reduces clutter.
27
+ */
28
+ get stackToasts() {
29
+ return this._stackToasts;
30
+ }
31
+ constructor(portal) {
32
+ this.portal = portal;
33
+ this.toastsIdMap = new Map();
34
+ this.queuedToastsQueue = [];
35
+ this.toastsQueue = [];
36
+ this._maxVisibleToastsCount = 3;
37
+ this._stackToasts = true;
38
+ this.interactingBehavior = 'pause-progress';
39
+ this.colorHue = {
40
+ success: 120,
41
+ error: 0,
42
+ warning: 60,
43
+ info: 200,
44
+ };
45
+ this.defaultDuration = 10000;
46
+ this.defaultLeaveAnimationDuration = 300;
47
+ this.defaultEnterAnimationDuration = 300;
48
+ this.defaultDirection = getComputedStyle(this.portal).direction;
49
+ this.emitter = new CustomEventEmitter({
50
+ 'state.request.remove.toast': {
51
+ runningBehavior: 'async-sequential',
52
+ dispatchable: false,
53
+ lockSymbol: TOAST_LOCK_SYMBOL,
54
+ beforeAll: (data) => {
55
+ const toast = data.listenerValue.toast;
56
+ this.toastsIdMap.delete(toast.id);
57
+ if (toast.status === 'queued') {
58
+ this.queuedToastsQueue = this.queuedToastsQueue.filter((t) => t.id !== toast.id);
59
+ return;
60
+ }
61
+ this.toastsQueue = this.toastsQueue.filter((t) => t.id !== toast.id);
62
+ this.rolloverQueuedToasts();
63
+ this.portal.requestUpdate();
64
+ },
65
+ },
66
+ });
67
+ }
68
+ gracefulRemoveVisible() {
69
+ this.toastsQueue.forEach((t) => {
70
+ t.gracefulRemove();
71
+ });
72
+ }
73
+ gracefulRemoveAll() {
74
+ this.gracefulRemoveVisible();
75
+ this.queuedToastsQueue.forEach((t) => {
76
+ t.remove();
77
+ });
78
+ }
79
+ /**
80
+ * Re-parents the toast portal to the specified node.
81
+ *
82
+ * Useful for ensuring toasts appear correctly when top-layer elements like fullscreen containers
83
+ * or dialogs are active. The specified node should be a valid container element (not void elements like <img />).
84
+ *
85
+ * @param node - The new parent node for the toast portal.
86
+ */
87
+ reParent(node = document.body) {
88
+ if (node === this.portal.parentNode)
89
+ return;
90
+ node.appendChild(this.portal);
91
+ }
92
+ /**
93
+ * Makes the toast portal a popover,
94
+ * ensuring that toasts appear above all other elements
95
+ * (e.g., dialogs, fullscreen content) in the top-layer.
96
+ * This is useful for proper overlay stacking and visibility.
97
+ */
98
+ popover() {
99
+ const { portal } = this;
100
+ portal.popover = 'manual';
101
+ portal.hidePopover();
102
+ portal.showPopover();
103
+ }
104
+ success(message) {
105
+ return this.create({
106
+ message,
107
+ label: 'Success:',
108
+ labelIcon: 'checkMark',
109
+ role: 'status',
110
+ colorHue: this.colorHue.success,
111
+ });
112
+ }
113
+ error(message) {
114
+ return this.create({
115
+ message,
116
+ label: 'Error:',
117
+ labelIcon: 'error',
118
+ role: 'alert',
119
+ colorHue: this.colorHue.error,
120
+ priority: 'important',
121
+ });
122
+ }
123
+ warning(message) {
124
+ return this.create({
125
+ message,
126
+ label: 'Warning:',
127
+ labelIcon: 'warning',
128
+ role: 'alert',
129
+ colorHue: this.colorHue.warning,
130
+ priority: 'important',
131
+ });
132
+ }
133
+ info(message) {
134
+ return this.create({
135
+ message,
136
+ label: 'Info:',
137
+ role: 'status',
138
+ labelIcon: 'info',
139
+ colorHue: this.colorHue.info,
140
+ });
141
+ }
142
+ create(toastData) {
143
+ const toast = new Toast({
144
+ toastData: typeof toastData === 'string' ? { message: toastData } : toastData,
145
+ controller: this,
146
+ });
147
+ this.toastsIdMap.set(toast.id, toast);
148
+ switch (toast.priority) {
149
+ case 'immediate':
150
+ this.queuedToastsQueue.unshift(toast);
151
+ if (this.toastsQueue.length >= this._maxVisibleToastsCount) {
152
+ (this.toastsQueue.find((t) => t.priority === 'normal') ||
153
+ this.toastsQueue[0])?.remove();
154
+ }
155
+ break;
156
+ case 'important':
157
+ this.queuedToastsQueue.unshift(toast);
158
+ if (this.toastsQueue.length >= this._maxVisibleToastsCount) {
159
+ (this.toastsQueue.find((t) => t.priority === 'normal') ||
160
+ this.toastsQueue[0])?.gracefulRemove();
161
+ }
162
+ break;
163
+ case 'normal':
164
+ this.queuedToastsQueue.push(toast);
165
+ break;
166
+ }
167
+ this.rolloverQueuedToasts();
168
+ return toast;
169
+ }
170
+ rolloverQueuedToasts() {
171
+ if (this.toastsQueue.length >= this.maxVisibleToastsCount) {
172
+ return;
173
+ }
174
+ const rolloverToastsCount = this.maxVisibleToastsCount - this.toastsQueue.length;
175
+ const rolloverToasts = this.queuedToastsQueue.splice(0, rolloverToastsCount);
176
+ if (rolloverToasts.length === 0) {
177
+ return;
178
+ }
179
+ rolloverToasts.forEach((t) => {
180
+ t.emitter.dispatch('state.await.rendering', undefined, {
181
+ lockSymbol: TOAST_LOCK_SYMBOL,
182
+ });
183
+ });
184
+ this.toastsQueue.push(...rolloverToasts);
185
+ this.portal.requestUpdate();
186
+ }
187
+ }
188
+
189
+ export { ToastController };