@capgo/capacitor-pretty-toast 8.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.
Files changed (85) hide show
  1. package/CapgoCapacitorPrettyToast.podspec +17 -0
  2. package/LICENSE +373 -0
  3. package/Package.swift +28 -0
  4. package/README.md +341 -0
  5. package/android/build.gradle +71 -0
  6. package/android/src/main/AndroidManifest.xml +6 -0
  7. package/android/src/main/java/com/toast/PrettyToastPlugin.kt +197 -0
  8. package/android/src/main/java/com/toast/ToastOverlay.kt +495 -0
  9. package/android/src/main/java/com/toast/anim/CutoutMorphAnimator.kt +235 -0
  10. package/android/src/main/java/com/toast/anim/SlideAnimator.kt +64 -0
  11. package/android/src/main/java/com/toast/anim/ToastAnimator.kt +23 -0
  12. package/android/src/main/java/com/toast/backdrop/BackdropSampler.kt +142 -0
  13. package/android/src/main/java/com/toast/backdrop/OutlineController.kt +100 -0
  14. package/android/src/main/java/com/toast/cutout/CutoutDetector.kt +88 -0
  15. package/android/src/main/java/com/toast/cutout/CutoutInfo.kt +28 -0
  16. package/android/src/main/java/com/toast/gesture/ToastGestureHandler.kt +68 -0
  17. package/android/src/main/java/com/toast/ui/IconMapper.kt +26 -0
  18. package/android/src/main/java/com/toast/ui/PassThroughFrameLayout.kt +53 -0
  19. package/android/src/main/java/com/toast/ui/ToastViewFactory.kt +224 -0
  20. package/android/src/main/java/com/toast/util/Density.kt +17 -0
  21. package/android/src/main/java/com/toast/util/StatusBarController.kt +24 -0
  22. package/android/src/main/java/com/toast/util/ToastConstants.kt +36 -0
  23. package/android/src/main/res/.gitkeep +0 -0
  24. package/android/src/main/res/drawable/ic_arrow_downward.xml +9 -0
  25. package/android/src/main/res/drawable/ic_arrow_upward.xml +9 -0
  26. package/android/src/main/res/drawable/ic_cancel.xml +9 -0
  27. package/android/src/main/res/drawable/ic_check_circle.xml +9 -0
  28. package/android/src/main/res/drawable/ic_favorite.xml +9 -0
  29. package/android/src/main/res/drawable/ic_info.xml +9 -0
  30. package/android/src/main/res/drawable/ic_mail.xml +9 -0
  31. package/android/src/main/res/drawable/ic_notifications.xml +9 -0
  32. package/android/src/main/res/drawable/ic_touch_app.xml +9 -0
  33. package/android/src/main/res/drawable/ic_warning.xml +9 -0
  34. package/android/src/main/res/drawable/ic_wifi.xml +9 -0
  35. package/android/src/main/res/values/colors.xml +3 -0
  36. package/android/src/main/res/values/strings.xml +3 -0
  37. package/android/src/main/res/values/styles.xml +3 -0
  38. package/android/src/test/java/com/toast/PrettyToastPluginTest.kt +26 -0
  39. package/dist/docs.json +459 -0
  40. package/dist/esm/controller.d.ts +30 -0
  41. package/dist/esm/controller.js +271 -0
  42. package/dist/esm/controller.js.map +1 -0
  43. package/dist/esm/definitions.d.ts +144 -0
  44. package/dist/esm/definitions.js +2 -0
  45. package/dist/esm/definitions.js.map +1 -0
  46. package/dist/esm/driver.d.ts +19 -0
  47. package/dist/esm/driver.js +24 -0
  48. package/dist/esm/driver.js.map +1 -0
  49. package/dist/esm/icons.d.ts +14 -0
  50. package/dist/esm/icons.js +138 -0
  51. package/dist/esm/icons.js.map +1 -0
  52. package/dist/esm/index.d.ts +2 -0
  53. package/dist/esm/index.js +2 -0
  54. package/dist/esm/index.js.map +1 -0
  55. package/dist/esm/internal-plugin.d.ts +2 -0
  56. package/dist/esm/internal-plugin.js +5 -0
  57. package/dist/esm/internal-plugin.js.map +1 -0
  58. package/dist/esm/internal-types.d.ts +31 -0
  59. package/dist/esm/internal-types.js +2 -0
  60. package/dist/esm/internal-types.js.map +1 -0
  61. package/dist/esm/toast.d.ts +1 -0
  62. package/dist/esm/toast.js +5 -0
  63. package/dist/esm/toast.js.map +1 -0
  64. package/dist/esm/web-renderer.d.ts +36 -0
  65. package/dist/esm/web-renderer.js +296 -0
  66. package/dist/esm/web-renderer.js.map +1 -0
  67. package/dist/esm/web.d.ts +10 -0
  68. package/dist/esm/web.js +28 -0
  69. package/dist/esm/web.js.map +1 -0
  70. package/dist/plugin.cjs.js +770 -0
  71. package/dist/plugin.cjs.js.map +1 -0
  72. package/dist/plugin.js +773 -0
  73. package/dist/plugin.js.map +1 -0
  74. package/ios/Sources/PrettyToastPlugin/CustomHostingView.swift +13 -0
  75. package/ios/Sources/PrettyToastPlugin/PassThroughWindow.swift +143 -0
  76. package/ios/Sources/PrettyToastPlugin/PrettyToastColorParser.swift +94 -0
  77. package/ios/Sources/PrettyToastPlugin/PrettyToastPlugin.swift +138 -0
  78. package/ios/Sources/PrettyToastPlugin/PrettyToastView.swift +267 -0
  79. package/ios/Sources/PrettyToastPlugin/Toast.swift +29 -0
  80. package/ios/Sources/PrettyToastPlugin/ToastManager.swift +392 -0
  81. package/ios/Tests/PrettyToastPluginTests/PrettyToastPluginTests.swift +21 -0
  82. package/package.json +98 -0
  83. package/scripts/check-capacitor-plugin-wiring.mjs +254 -0
  84. package/scripts/deploy-example-capgo.mjs +86 -0
  85. package/scripts/test-ios.sh +14 -0
@@ -0,0 +1,770 @@
1
+ 'use strict';
2
+
3
+ var core = require('@capacitor/core');
4
+
5
+ const ICON_MAP = [
6
+ ['checkmark', { glyph: '✓', color: '#30D158' }],
7
+ ['xmark', { glyph: '✕', color: '#FF453A' }],
8
+ ['info', { glyph: 'ℹ', color: '#0A84FF' }],
9
+ ['exclamation', { glyph: '!', color: '#FF9F0A' }],
10
+ ['heart', { glyph: '♥', color: '#FF375F' }],
11
+ ['arrow.up', { glyph: '↑', color: '#0A84FF' }],
12
+ ['arrow.down', { glyph: '↓', color: '#0A84FF' }],
13
+ ['arrow', { glyph: '↑', color: '#0A84FF' }],
14
+ ['envelope', { glyph: '✉', color: '#FFFFFF' }],
15
+ ['mail', { glyph: '✉', color: '#FFFFFF' }],
16
+ ['wifi', { glyph: '◉', color: '#FFFFFF' }],
17
+ ];
18
+ const DEFAULT_ICON_SYMBOL = 'bell.badge.fill';
19
+ const svgRasterCache = new Map();
20
+ function isSvgIcon(value) {
21
+ return typeof value === 'string' && value.trimStart().startsWith('<svg');
22
+ }
23
+ function normalizeIconSource(source) {
24
+ if (!source)
25
+ return undefined;
26
+ if (typeof source === 'string') {
27
+ return source.trim() || undefined;
28
+ }
29
+ if (typeof source.uri === 'string') {
30
+ return source.uri.trim() || undefined;
31
+ }
32
+ return undefined;
33
+ }
34
+ function getSymbolIcon(symbol) {
35
+ const normalized = symbol !== null && symbol !== void 0 ? symbol : '';
36
+ for (const [key, info] of ICON_MAP) {
37
+ if (normalized.includes(key))
38
+ return info;
39
+ }
40
+ return { glyph: null, color: '#FFFFFF' };
41
+ }
42
+ function getAccessibilityAnnouncement(config) {
43
+ if (config.accessibilityAnnouncement !== undefined) {
44
+ return config.accessibilityAnnouncement;
45
+ }
46
+ return [config.title, config.message].filter(Boolean).join('. ');
47
+ }
48
+ function isNativeSafeIconUri(uri) {
49
+ if (!uri)
50
+ return false;
51
+ return (uri.startsWith('https://') ||
52
+ uri.startsWith('http://') ||
53
+ uri.startsWith('file://') ||
54
+ uri.startsWith('data:') ||
55
+ uri.startsWith('/'));
56
+ }
57
+ async function rasterizeSvgToPngDataUrl(svg) {
58
+ let pending = svgRasterCache.get(svg);
59
+ if (!pending) {
60
+ pending = rasterizeSvgToPngDataUrlInternal(svg);
61
+ svgRasterCache.set(svg, pending);
62
+ }
63
+ return pending;
64
+ }
65
+ async function blobUrlToDataUrl(uri) {
66
+ if (typeof window === 'undefined' || typeof fetch === 'undefined' || typeof FileReader === 'undefined') {
67
+ return null;
68
+ }
69
+ try {
70
+ const response = await fetch(uri);
71
+ const blob = await response.blob();
72
+ return await new Promise((resolve) => {
73
+ const reader = new FileReader();
74
+ reader.onload = () => {
75
+ resolve(typeof reader.result === 'string' ? reader.result : null);
76
+ };
77
+ reader.onerror = () => resolve(null);
78
+ reader.readAsDataURL(blob);
79
+ });
80
+ }
81
+ catch (_a) {
82
+ return null;
83
+ }
84
+ }
85
+ function rasterizeSvgToPngDataUrlInternal(svg) {
86
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
87
+ return Promise.resolve(null);
88
+ }
89
+ const encodedSvg = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
90
+ return new Promise((resolve) => {
91
+ const image = new Image();
92
+ image.onload = () => {
93
+ try {
94
+ const sourceWidth = image.naturalWidth || 96;
95
+ const sourceHeight = image.naturalHeight || 96;
96
+ const maxSide = Math.max(sourceWidth, sourceHeight, 1);
97
+ const scale = 128 / maxSide;
98
+ const width = Math.max(1, Math.round(sourceWidth * scale));
99
+ const height = Math.max(1, Math.round(sourceHeight * scale));
100
+ const canvas = document.createElement('canvas');
101
+ canvas.width = width;
102
+ canvas.height = height;
103
+ const context = canvas.getContext('2d');
104
+ if (!context) {
105
+ resolve(null);
106
+ return;
107
+ }
108
+ context.clearRect(0, 0, width, height);
109
+ context.drawImage(image, 0, 0, width, height);
110
+ resolve(canvas.toDataURL('image/png'));
111
+ }
112
+ catch (_a) {
113
+ resolve(null);
114
+ }
115
+ };
116
+ image.onerror = () => resolve(null);
117
+ image.src = encodedSvg;
118
+ });
119
+ }
120
+ function parseSvgElement(svgMarkup) {
121
+ if (typeof DOMParser === 'undefined')
122
+ return null;
123
+ try {
124
+ const documentNode = new DOMParser().parseFromString(svgMarkup, 'image/svg+xml');
125
+ if (documentNode.querySelector('parsererror') || documentNode.querySelector('script')) {
126
+ return null;
127
+ }
128
+ const root = documentNode.documentElement;
129
+ if (!root || root.tagName.toLowerCase() !== 'svg')
130
+ return null;
131
+ const svg = root.cloneNode(true);
132
+ svg.setAttribute('width', '40');
133
+ svg.setAttribute('height', '40');
134
+ svg.setAttribute('aria-hidden', 'true');
135
+ svg.style.display = 'block';
136
+ return svg;
137
+ }
138
+ catch (_a) {
139
+ return null;
140
+ }
141
+ }
142
+
143
+ const VARIANT_ICONS = {
144
+ success: 'checkmark.circle.fill',
145
+ error: 'xmark.circle.fill',
146
+ info: 'info.circle.fill',
147
+ warning: 'exclamationmark.triangle.fill',
148
+ loading: 'arrow.triangle.2.circlepath',
149
+ };
150
+ class ToastController {
151
+ constructor(driver) {
152
+ this.driver = driver;
153
+ this.queue = [];
154
+ this.current = null;
155
+ this.isShowing = false;
156
+ this.idCounter = 0;
157
+ this.autoDismissTimer = null;
158
+ this.autoDismissed = false;
159
+ this.driver.subscribe({
160
+ onDismiss: (event) => this.handleDismiss(event.id),
161
+ onPress: (event) => this.handlePress(event.id),
162
+ onActionPress: (event) => this.handleActionPress(event.id),
163
+ });
164
+ this.ref = {
165
+ show: (config, options) => this.show(config, options),
166
+ success: (title, config, options) => this.showVariant('success', title, config, options),
167
+ error: (title, config, options) => this.showVariant('error', title, config, options),
168
+ info: (title, config, options) => this.showVariant('info', title, config, options),
169
+ warning: (title, config, options) => this.showVariant('warning', title, config, options),
170
+ loading: (title, config, options) => this.showVariant('loading', title, config, options),
171
+ update: (id, partial) => this.update(id, partial),
172
+ promise: (promise, messages) => this.promise(promise, messages),
173
+ dismiss: (id) => this.dismiss(id),
174
+ dismissAll: () => this.dismissAll(),
175
+ };
176
+ }
177
+ show(config, options) {
178
+ var _a, _b;
179
+ const id = (_a = config.id) !== null && _a !== void 0 ? _a : this.generateId();
180
+ const entry = this.hydrateEntry(Object.assign(Object.assign({}, config), { id }));
181
+ if ((options === null || options === void 0 ? void 0 : options.force) && this.isShowing) {
182
+ this.queue.unshift(entry);
183
+ this.clearAutoDismissTimer();
184
+ this.autoDismissed = false;
185
+ void this.driver.dismiss((_b = this.current) === null || _b === void 0 ? void 0 : _b.id);
186
+ return id;
187
+ }
188
+ if (!this.isShowing) {
189
+ this.presentToast(entry);
190
+ return id;
191
+ }
192
+ this.queue.push(entry);
193
+ this.prepareSvgIcon(entry);
194
+ return id;
195
+ }
196
+ update(id, partial) {
197
+ var _a;
198
+ if (((_a = this.current) === null || _a === void 0 ? void 0 : _a.id) === id) {
199
+ this.current = this.hydrateEntry(Object.assign(Object.assign(Object.assign({}, this.current), partial), { id }), this.current);
200
+ this.armAutoDismissTimer(this.current);
201
+ void this.driver.update(this.buildPayload(this.current));
202
+ this.prepareSvgIcon(this.current);
203
+ return;
204
+ }
205
+ const index = this.queue.findIndex((entry) => entry.id === id);
206
+ if (index === -1)
207
+ return;
208
+ const existing = this.queue[index];
209
+ const updated = this.hydrateEntry(Object.assign(Object.assign(Object.assign({}, existing), partial), { id }), existing);
210
+ this.queue[index] = updated;
211
+ this.prepareSvgIcon(updated);
212
+ }
213
+ dismiss(id) {
214
+ var _a;
215
+ if (id && ((_a = this.current) === null || _a === void 0 ? void 0 : _a.id) !== id) {
216
+ this.queue = this.queue.filter((entry) => entry.id !== id);
217
+ return;
218
+ }
219
+ if (!this.current)
220
+ return;
221
+ this.clearAutoDismissTimer();
222
+ this.autoDismissed = false;
223
+ void this.driver.dismiss(this.current.id);
224
+ }
225
+ dismissAll() {
226
+ this.queue = [];
227
+ if (!this.current)
228
+ return;
229
+ this.clearAutoDismissTimer();
230
+ this.autoDismissed = false;
231
+ void this.driver.dismiss(this.current.id);
232
+ }
233
+ promise(promise, messages) {
234
+ const loadingConfig = typeof messages.loading === 'string'
235
+ ? { title: messages.loading }
236
+ : Object.assign({}, messages.loading);
237
+ if (loadingConfig.autoDismiss === undefined) {
238
+ loadingConfig.autoDismiss = false;
239
+ }
240
+ if (!loadingConfig.icon) {
241
+ loadingConfig.icon = VARIANT_ICONS.loading;
242
+ }
243
+ const id = this.show(loadingConfig);
244
+ promise.then((value) => {
245
+ const next = typeof messages.success === 'function' ? messages.success(value) : messages.success;
246
+ const config = typeof next === 'string' ? { title: next } : Object.assign({}, next);
247
+ if (!config.icon)
248
+ config.icon = VARIANT_ICONS.success;
249
+ if (config.autoDismiss === undefined)
250
+ config.autoDismiss = true;
251
+ if (config.duration === undefined)
252
+ config.duration = 3000;
253
+ this.update(id, config);
254
+ }, (error) => {
255
+ const next = typeof messages.error === 'function' ? messages.error(error) : messages.error;
256
+ const config = typeof next === 'string' ? { title: next } : Object.assign({}, next);
257
+ if (!config.icon)
258
+ config.icon = VARIANT_ICONS.error;
259
+ if (config.autoDismiss === undefined)
260
+ config.autoDismiss = true;
261
+ if (config.duration === undefined)
262
+ config.duration = 3000;
263
+ this.update(id, config);
264
+ });
265
+ return promise;
266
+ }
267
+ showVariant(variant, title, config, options) {
268
+ var _a;
269
+ const toastConfig = Object.assign(Object.assign({}, config), { title, icon: (_a = config === null || config === void 0 ? void 0 : config.icon) !== null && _a !== void 0 ? _a : VARIANT_ICONS[variant], _fallbackIcon: VARIANT_ICONS[variant] });
270
+ if (variant === 'loading' && toastConfig.autoDismiss === undefined) {
271
+ toastConfig.autoDismiss = false;
272
+ }
273
+ return this.show(toastConfig, options);
274
+ }
275
+ presentToast(entry) {
276
+ var _a;
277
+ this.isShowing = true;
278
+ this.current = entry;
279
+ this.armAutoDismissTimer(entry);
280
+ (_a = entry.onShow) === null || _a === void 0 ? void 0 : _a.call(entry);
281
+ void this.driver.show(this.buildPayload(entry));
282
+ this.prepareSvgIcon(entry);
283
+ }
284
+ showNext() {
285
+ const next = this.queue.shift();
286
+ if (!next) {
287
+ this.isShowing = false;
288
+ this.current = null;
289
+ return;
290
+ }
291
+ this.presentToast(next);
292
+ }
293
+ handleDismiss(id) {
294
+ var _a, _b;
295
+ if (!this.current || this.current.id !== id)
296
+ return;
297
+ const entry = this.current;
298
+ this.clearAutoDismissTimer();
299
+ if (this.autoDismissed) {
300
+ (_a = entry.onAutoDismiss) === null || _a === void 0 ? void 0 : _a.call(entry);
301
+ }
302
+ (_b = entry.onHide) === null || _b === void 0 ? void 0 : _b.call(entry);
303
+ this.autoDismissed = false;
304
+ this.showNext();
305
+ }
306
+ handlePress(id) {
307
+ if (!this.current || this.current.id !== id || !this.current.onPress)
308
+ return;
309
+ this.current.onPress();
310
+ this.clearAutoDismissTimer();
311
+ this.autoDismissed = false;
312
+ void this.driver.dismiss(id);
313
+ }
314
+ handleActionPress(id) {
315
+ if (!this.current || this.current.id !== id || !this.current.action)
316
+ return;
317
+ this.current.action.onPress();
318
+ this.clearAutoDismissTimer();
319
+ this.autoDismissed = false;
320
+ void this.driver.dismiss(id);
321
+ }
322
+ armAutoDismissTimer(entry) {
323
+ var _a, _b;
324
+ this.clearAutoDismissTimer();
325
+ this.autoDismissed = false;
326
+ const autoDismiss = (_a = entry.autoDismiss) !== null && _a !== void 0 ? _a : true;
327
+ const duration = (_b = entry.duration) !== null && _b !== void 0 ? _b : 3000;
328
+ if (!autoDismiss || duration <= 0)
329
+ return;
330
+ this.autoDismissTimer = setTimeout(() => {
331
+ this.autoDismissTimer = null;
332
+ this.autoDismissed = true;
333
+ }, duration);
334
+ }
335
+ clearAutoDismissTimer() {
336
+ if (!this.autoDismissTimer)
337
+ return;
338
+ clearTimeout(this.autoDismissTimer);
339
+ this.autoDismissTimer = null;
340
+ }
341
+ hydrateEntry(config, previous) {
342
+ var _a, _b, _c;
343
+ const iconSourceUri = normalizeIconSource(config.iconSource);
344
+ const rawIcon = typeof config.icon === 'string' ? config.icon : '';
345
+ const rawSvg = !iconSourceUri && isSvgIcon(rawIcon) ? rawIcon.trim() : undefined;
346
+ const fallbackIcon = (_b = (_a = config._fallbackIcon) !== null && _a !== void 0 ? _a : previous === null || previous === void 0 ? void 0 : previous._fallbackIcon) !== null && _b !== void 0 ? _b : DEFAULT_ICON_SYMBOL;
347
+ const iconSymbol = rawSvg ? fallbackIcon : rawIcon || fallbackIcon;
348
+ const resolvedIconUri = iconSourceUri && isNativeSafeIconUri(iconSourceUri)
349
+ ? iconSourceUri
350
+ : rawSvg && (previous === null || previous === void 0 ? void 0 : previous.rawSvg) === rawSvg
351
+ ? previous.resolvedIconUri
352
+ : iconSourceUri && (previous === null || previous === void 0 ? void 0 : previous.iconSourceUri) === iconSourceUri
353
+ ? previous.resolvedIconUri
354
+ : undefined;
355
+ return Object.assign(Object.assign({}, config), { id: config.id, iconSymbol,
356
+ iconSourceUri,
357
+ rawSvg,
358
+ resolvedIconUri, isPreparingSvg: rawSvg ? ((_c = previous === null || previous === void 0 ? void 0 : previous.isPreparingSvg) !== null && _c !== void 0 ? _c : false) : false });
359
+ }
360
+ buildPayload(entry) {
361
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
362
+ const iconUri = (_b = (_a = entry.iconSourceUri) !== null && _a !== void 0 ? _a : entry.resolvedIconUri) !== null && _b !== void 0 ? _b : '';
363
+ return {
364
+ id: entry.id,
365
+ icon: entry.iconSymbol,
366
+ iconUri,
367
+ webIconUri: (_c = entry.iconSourceUri) !== null && _c !== void 0 ? _c : iconUri,
368
+ iconSvg: entry.iconSourceUri ? '' : ((_d = entry.rawSvg) !== null && _d !== void 0 ? _d : ''),
369
+ title: (_e = entry.title) !== null && _e !== void 0 ? _e : '',
370
+ message: (_f = entry.message) !== null && _f !== void 0 ? _f : '',
371
+ duration: (_g = entry.duration) !== null && _g !== void 0 ? _g : 3000,
372
+ autoDismiss: (_h = entry.autoDismiss) !== null && _h !== void 0 ? _h : true,
373
+ enableSwipeDismiss: (_j = entry.enableSwipeDismiss) !== null && _j !== void 0 ? _j : true,
374
+ useDynamicIsland: true,
375
+ accentColor: entry.accentColor,
376
+ strokeColor: entry.strokeColor,
377
+ disableBackdropSampling: (_k = entry.disableBackdropSampling) !== null && _k !== void 0 ? _k : false,
378
+ actionLabel: (_m = (_l = entry.action) === null || _l === void 0 ? void 0 : _l.label) !== null && _m !== void 0 ? _m : '',
379
+ accessibilityAnnouncement: getAccessibilityAnnouncement(entry),
380
+ };
381
+ }
382
+ prepareSvgIcon(entry) {
383
+ var _a, _b;
384
+ if (entry.isPreparingSvg || entry.resolvedIconUri) {
385
+ return;
386
+ }
387
+ const needsSvgRaster = Boolean(entry.rawSvg);
388
+ const needsBlobConversion = Boolean((_a = entry.iconSourceUri) === null || _a === void 0 ? void 0 : _a.startsWith('blob:'));
389
+ if (!needsSvgRaster && !needsBlobConversion) {
390
+ return;
391
+ }
392
+ entry.isPreparingSvg = true;
393
+ const resolveAsset = needsSvgRaster && entry.rawSvg
394
+ ? rasterizeSvgToPngDataUrl(entry.rawSvg)
395
+ : blobUrlToDataUrl((_b = entry.iconSourceUri) !== null && _b !== void 0 ? _b : '');
396
+ void resolveAsset.then((dataUrl) => {
397
+ var _a;
398
+ entry.isPreparingSvg = false;
399
+ if (!dataUrl)
400
+ return;
401
+ entry.resolvedIconUri = dataUrl;
402
+ if (((_a = this.current) === null || _a === void 0 ? void 0 : _a.id) === entry.id) {
403
+ void this.driver.update(this.buildPayload(entry));
404
+ }
405
+ });
406
+ }
407
+ generateId() {
408
+ this.idCounter += 1;
409
+ return `toast-${this.idCounter}-${Date.now()}`;
410
+ }
411
+ }
412
+
413
+ const PrettyToastBridge = core.registerPlugin('PrettyToast', {
414
+ web: () => Promise.resolve().then(function () { return web; }).then((module) => new module.PrettyToastWeb()),
415
+ });
416
+
417
+ class CapacitorToastDriver {
418
+ constructor() {
419
+ this.subscribed = false;
420
+ }
421
+ subscribe(events) {
422
+ if (this.subscribed)
423
+ return;
424
+ this.subscribed = true;
425
+ void PrettyToastBridge.addListener('toastDismiss', events.onDismiss);
426
+ void PrettyToastBridge.addListener('toastPress', events.onPress);
427
+ void PrettyToastBridge.addListener('toastActionPress', events.onActionPress);
428
+ }
429
+ show(payload) {
430
+ return PrettyToastBridge.showCurrentToast(payload);
431
+ }
432
+ update(payload) {
433
+ return PrettyToastBridge.updateCurrentToast(payload);
434
+ }
435
+ dismiss(id) {
436
+ return PrettyToastBridge.dismissCurrentToast(id ? { id } : {});
437
+ }
438
+ }
439
+
440
+ const controller = new ToastController(new CapacitorToastDriver());
441
+ const toast = controller.ref;
442
+
443
+ const ENTER_MS = 450;
444
+ const EXIT_MS = 350;
445
+ const ENTER_EASING = 'cubic-bezier(0.22, 1.2, 0.36, 1)';
446
+ const EXIT_EASING = 'cubic-bezier(0.4, 0, 0.2, 1)';
447
+ const SWIPE_THRESHOLD = -40;
448
+ class WebToastRenderer {
449
+ constructor(events) {
450
+ this.events = events;
451
+ this.current = null;
452
+ this.root = null;
453
+ this.iconSlot = null;
454
+ this.titleNode = null;
455
+ this.messageNode = null;
456
+ this.actionButton = null;
457
+ this.autoDismissTimer = null;
458
+ this.exitTimer = null;
459
+ this.prefersDark = false;
460
+ this.dragStartY = null;
461
+ this.dragY = 0;
462
+ this.isDragging = false;
463
+ if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {
464
+ this.prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
465
+ }
466
+ }
467
+ show(payload) {
468
+ this.current = payload;
469
+ this.clearExitTimer();
470
+ this.clearAutoDismissTimer();
471
+ this.dragStartY = null;
472
+ this.dragY = 0;
473
+ this.isDragging = false;
474
+ this.ensureElements();
475
+ this.render(payload);
476
+ this.applyEnteringState();
477
+ requestAnimationFrame(() => {
478
+ var _a;
479
+ if (!this.root || ((_a = this.current) === null || _a === void 0 ? void 0 : _a.id) !== payload.id)
480
+ return;
481
+ this.root.style.transform = 'translate(-50%, 0) scale(1)';
482
+ this.root.style.opacity = '1';
483
+ });
484
+ this.armAutoDismiss(payload);
485
+ }
486
+ update(payload) {
487
+ if (!this.root || !this.current || this.current.id !== payload.id)
488
+ return;
489
+ this.current = payload;
490
+ this.render(payload);
491
+ this.armAutoDismiss(payload);
492
+ }
493
+ dismiss(id) {
494
+ if (!this.current || (id && this.current.id !== id) || !this.root)
495
+ return;
496
+ this.clearAutoDismissTimer();
497
+ this.startExit();
498
+ }
499
+ ensureElements() {
500
+ if (typeof document === 'undefined')
501
+ return;
502
+ if (this.root) {
503
+ if (!this.root.isConnected) {
504
+ document.body.appendChild(this.root);
505
+ }
506
+ return;
507
+ }
508
+ const root = document.createElement('div');
509
+ root.setAttribute('role', 'status');
510
+ root.setAttribute('aria-live', 'polite');
511
+ root.style.position = 'fixed';
512
+ root.style.top = 'calc(var(--safe-area-inset-top, env(safe-area-inset-top, 0px)) + 10px)';
513
+ root.style.left = '50%';
514
+ root.style.zIndex = '2147483647';
515
+ root.style.width = 'min(360px, calc(100vw - 20px))';
516
+ root.style.boxSizing = 'border-box';
517
+ root.style.background = '#000';
518
+ root.style.borderRadius = '30px';
519
+ root.style.padding = '14px 20px';
520
+ root.style.display = 'flex';
521
+ root.style.alignItems = 'center';
522
+ root.style.gap = '10px';
523
+ root.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
524
+ root.style.userSelect = 'none';
525
+ root.style.touchAction = 'none';
526
+ root.style.boxShadow = '0 10px 30px rgba(0, 0, 0, 0.35)';
527
+ root.style.transform = 'translate(-50%, -40px) scale(0.8)';
528
+ root.style.opacity = '0';
529
+ root.style.transition = `transform ${ENTER_MS}ms ${ENTER_EASING}, opacity ${ENTER_MS}ms ${ENTER_EASING}`;
530
+ root.addEventListener('pointerdown', (event) => this.handlePointerDown(event));
531
+ root.addEventListener('pointermove', (event) => this.handlePointerMove(event));
532
+ root.addEventListener('pointerup', (event) => this.handlePointerUp(event));
533
+ root.addEventListener('pointercancel', (event) => this.handlePointerUp(event));
534
+ root.addEventListener('click', () => {
535
+ if (!this.current || this.dragY < -4)
536
+ return;
537
+ this.events.onPress(this.current.id);
538
+ });
539
+ const iconSlot = document.createElement('div');
540
+ iconSlot.style.width = '50px';
541
+ iconSlot.style.flexShrink = '0';
542
+ iconSlot.style.display = 'flex';
543
+ iconSlot.style.alignItems = 'center';
544
+ iconSlot.style.justifyContent = 'center';
545
+ iconSlot.style.fontSize = '35px';
546
+ iconSlot.style.lineHeight = '1';
547
+ const textWrap = document.createElement('div');
548
+ textWrap.style.flex = '1';
549
+ textWrap.style.minWidth = '0';
550
+ const titleNode = document.createElement('div');
551
+ titleNode.style.color = '#fff';
552
+ titleNode.style.fontWeight = '600';
553
+ titleNode.style.fontSize = '15px';
554
+ titleNode.style.lineHeight = '20px';
555
+ titleNode.style.wordBreak = 'break-word';
556
+ const messageNode = document.createElement('div');
557
+ messageNode.style.color = 'rgba(255, 255, 255, 0.6)';
558
+ messageNode.style.fontSize = '12px';
559
+ messageNode.style.lineHeight = '16px';
560
+ messageNode.style.wordBreak = 'break-word';
561
+ textWrap.appendChild(titleNode);
562
+ textWrap.appendChild(messageNode);
563
+ const actionButton = document.createElement('button');
564
+ actionButton.type = 'button';
565
+ actionButton.style.flexShrink = '0';
566
+ actionButton.style.marginLeft = '4px';
567
+ actionButton.style.padding = '6px 12px';
568
+ actionButton.style.background = 'rgba(255,255,255,0.12)';
569
+ actionButton.style.border = 'none';
570
+ actionButton.style.borderRadius = '999px';
571
+ actionButton.style.fontSize = '13px';
572
+ actionButton.style.fontWeight = '600';
573
+ actionButton.style.cursor = 'pointer';
574
+ actionButton.style.display = 'none';
575
+ actionButton.addEventListener('click', (event) => {
576
+ event.stopPropagation();
577
+ if (!this.current)
578
+ return;
579
+ this.events.onActionPress(this.current.id);
580
+ });
581
+ actionButton.addEventListener('pointerdown', (event) => event.stopPropagation());
582
+ root.appendChild(iconSlot);
583
+ root.appendChild(textWrap);
584
+ root.appendChild(actionButton);
585
+ document.body.appendChild(root);
586
+ this.root = root;
587
+ this.iconSlot = iconSlot;
588
+ this.titleNode = titleNode;
589
+ this.messageNode = messageNode;
590
+ this.actionButton = actionButton;
591
+ }
592
+ render(payload) {
593
+ var _a, _b, _c;
594
+ if (!this.root || !this.iconSlot || !this.titleNode || !this.messageNode || !this.actionButton) {
595
+ return;
596
+ }
597
+ const symbolInfo = getSymbolIcon(payload.icon);
598
+ const accentColor = (_a = payload.accentColor) !== null && _a !== void 0 ? _a : symbolInfo.color;
599
+ const outline = payload.strokeColor
600
+ ? payload.strokeColor
601
+ : payload.disableBackdropSampling
602
+ ? 'rgba(255,255,255,0.06)'
603
+ : this.prefersDark
604
+ ? `color-mix(in srgb, ${accentColor} 20%, transparent)`
605
+ : '';
606
+ this.root.style.border = outline ? `2px solid ${outline}` : 'none';
607
+ this.root.style.cursor = payload.actionLabel || payload.icon ? 'pointer' : 'default';
608
+ this.root.setAttribute('aria-label', payload.accessibilityAnnouncement || '');
609
+ this.iconSlot.style.color = accentColor;
610
+ this.iconSlot.replaceChildren();
611
+ const renderableUri = payload.webIconUri || payload.iconUri;
612
+ if (renderableUri) {
613
+ const image = document.createElement('img');
614
+ image.src = renderableUri;
615
+ image.alt = '';
616
+ image.style.width = '40px';
617
+ image.style.height = '40px';
618
+ image.style.objectFit = 'contain';
619
+ this.iconSlot.appendChild(image);
620
+ }
621
+ else if (payload.iconSvg) {
622
+ const svg = parseSvgElement(payload.iconSvg);
623
+ if (svg) {
624
+ this.iconSlot.appendChild(svg);
625
+ }
626
+ else {
627
+ this.iconSlot.textContent = (_b = getSymbolIcon(payload.icon || DEFAULT_ICON_SYMBOL).glyph) !== null && _b !== void 0 ? _b : '';
628
+ }
629
+ }
630
+ else {
631
+ const glyph = (_c = symbolInfo.glyph) !== null && _c !== void 0 ? _c : getSymbolIcon(DEFAULT_ICON_SYMBOL).glyph;
632
+ if (glyph) {
633
+ this.iconSlot.textContent = glyph;
634
+ }
635
+ else {
636
+ this.iconSlot.innerHTML =
637
+ '<svg width="28" height="28" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2.25a1 1 0 0 1 1 1v.6a7 7 0 0 1 6 6.93v3.36l1.38 2.07A1.25 1.25 0 0 1 19.34 18H4.66a1.25 1.25 0 0 1-1.04-1.94L5 14v-3.22a7 7 0 0 1 6-6.93v-.6a1 1 0 0 1 1-1Zm-2.5 17.25a2.5 2.5 0 0 0 5 0h-5Z" /></svg>';
638
+ }
639
+ }
640
+ this.titleNode.textContent = payload.title;
641
+ this.titleNode.style.display = payload.title ? 'block' : 'none';
642
+ this.messageNode.textContent = payload.message;
643
+ this.messageNode.style.display = payload.message ? 'block' : 'none';
644
+ this.messageNode.style.marginTop = payload.title && payload.message ? '4px' : '0';
645
+ this.actionButton.textContent = payload.actionLabel;
646
+ this.actionButton.style.color = accentColor;
647
+ this.actionButton.style.display = payload.actionLabel ? 'inline-flex' : 'none';
648
+ }
649
+ armAutoDismiss(payload) {
650
+ this.clearAutoDismissTimer();
651
+ if (!payload.autoDismiss || payload.duration <= 0)
652
+ return;
653
+ this.autoDismissTimer = setTimeout(() => {
654
+ this.startExit();
655
+ }, payload.duration);
656
+ }
657
+ startExit() {
658
+ if (!this.root || !this.current || this.exitTimer)
659
+ return;
660
+ const currentId = this.current.id;
661
+ this.root.style.transition = `transform ${EXIT_MS}ms ${EXIT_EASING}, opacity ${EXIT_MS}ms ${EXIT_EASING}`;
662
+ this.root.style.transform = `translate(-50%, ${this.dragY - 40}px) scale(1)`;
663
+ this.root.style.opacity = '0';
664
+ this.exitTimer = setTimeout(() => {
665
+ var _a;
666
+ this.exitTimer = null;
667
+ this.clearAutoDismissTimer();
668
+ this.dragY = 0;
669
+ this.isDragging = false;
670
+ this.dragStartY = null;
671
+ if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.isConnected) {
672
+ this.root.remove();
673
+ }
674
+ this.root = null;
675
+ this.iconSlot = null;
676
+ this.titleNode = null;
677
+ this.messageNode = null;
678
+ this.actionButton = null;
679
+ this.current = null;
680
+ this.events.onDismiss(currentId);
681
+ }, EXIT_MS);
682
+ }
683
+ applyEnteringState() {
684
+ if (!this.root)
685
+ return;
686
+ this.root.style.transition = `transform ${ENTER_MS}ms ${ENTER_EASING}, opacity ${ENTER_MS}ms ${ENTER_EASING}`;
687
+ this.root.style.transform = 'translate(-50%, -40px) scale(0.8)';
688
+ this.root.style.opacity = '0';
689
+ }
690
+ handlePointerDown(event) {
691
+ var _a, _b;
692
+ if (event.button !== 0)
693
+ return;
694
+ this.dragStartY = event.clientY;
695
+ this.dragY = 0;
696
+ (_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.setPointerCapture) === null || _b === void 0 ? void 0 : _b.call(_a, event.pointerId);
697
+ }
698
+ handlePointerMove(event) {
699
+ if (!this.root || this.dragStartY === null)
700
+ return;
701
+ const nextDragY = Math.min(0, event.clientY - this.dragStartY);
702
+ this.dragY = nextDragY;
703
+ this.isDragging = nextDragY < -2;
704
+ if (!this.isDragging)
705
+ return;
706
+ this.root.style.transition = 'none';
707
+ this.root.style.transform = `translate(-50%, ${nextDragY}px) scale(1)`;
708
+ }
709
+ handlePointerUp(event) {
710
+ var _a, _b;
711
+ if (!this.root || this.dragStartY === null)
712
+ return;
713
+ this.dragStartY = null;
714
+ (_b = (_a = this.root).releasePointerCapture) === null || _b === void 0 ? void 0 : _b.call(_a, event.pointerId);
715
+ if (this.dragY < SWIPE_THRESHOLD) {
716
+ this.startExit();
717
+ return;
718
+ }
719
+ this.isDragging = false;
720
+ this.dragY = 0;
721
+ this.root.style.transition = `transform ${EXIT_MS}ms ${EXIT_EASING}, opacity ${EXIT_MS}ms ${EXIT_EASING}`;
722
+ this.root.style.transform = 'translate(-50%, 0) scale(1)';
723
+ }
724
+ clearAutoDismissTimer() {
725
+ if (!this.autoDismissTimer)
726
+ return;
727
+ clearTimeout(this.autoDismissTimer);
728
+ this.autoDismissTimer = null;
729
+ }
730
+ clearExitTimer() {
731
+ if (!this.exitTimer)
732
+ return;
733
+ clearTimeout(this.exitTimer);
734
+ this.exitTimer = null;
735
+ }
736
+ }
737
+
738
+ class PrettyToastWeb extends core.WebPlugin {
739
+ constructor() {
740
+ super(...arguments);
741
+ this.renderer = new WebToastRenderer({
742
+ onDismiss: (id) => {
743
+ this.notifyListeners('toastDismiss', { id });
744
+ },
745
+ onPress: (id) => {
746
+ this.notifyListeners('toastPress', { id });
747
+ },
748
+ onActionPress: (id) => {
749
+ this.notifyListeners('toastActionPress', { id });
750
+ },
751
+ });
752
+ }
753
+ async showCurrentToast(options) {
754
+ this.renderer.show(options);
755
+ }
756
+ async updateCurrentToast(options) {
757
+ this.renderer.update(options);
758
+ }
759
+ async dismissCurrentToast(options) {
760
+ this.renderer.dismiss(options === null || options === void 0 ? void 0 : options.id);
761
+ }
762
+ }
763
+
764
+ var web = /*#__PURE__*/Object.freeze({
765
+ __proto__: null,
766
+ PrettyToastWeb: PrettyToastWeb
767
+ });
768
+
769
+ exports.toast = toast;
770
+ //# sourceMappingURL=plugin.cjs.js.map