@wowlabtech/mini-app-adapter 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -66,7 +66,7 @@ interface MiniAppInitOptions {
66
66
  */
67
67
  debug?: boolean;
68
68
  /**
69
- * Dynamically loads Eruda devtools if supported.
69
+ * Enables Eruda devtools when host app already exposed `window.eruda`.
70
70
  */
71
71
  eruda?: boolean;
72
72
  /**
@@ -75,13 +75,45 @@ interface MiniAppInitOptions {
75
75
  mockForMacOS?: boolean;
76
76
  }
77
77
  interface MiniAppShareStoryOptions {
78
+ /**
79
+ * Shared story caption. Used by Telegram directly.
80
+ * For VK this value is converted into a simple text sticker when `vk.stickers` is not provided.
81
+ */
78
82
  text?: string;
79
- widgetLink?: {
83
+ /**
84
+ * Universal CTA link.
85
+ * Telegram maps it to `widgetLink`, VK maps it to `attachment` when custom VK attachment is not provided.
86
+ */
87
+ link?: {
80
88
  url: string;
81
89
  name?: string;
82
90
  };
91
+ /**
92
+ * Telegram-specific options.
93
+ */
94
+ telegram?: {
95
+ text?: string;
96
+ widgetLink?: {
97
+ url: string;
98
+ name?: string;
99
+ };
100
+ };
101
+ /**
102
+ * VK-specific options.
103
+ */
104
+ vk?: {
105
+ backgroundType?: 'image' | 'video';
106
+ locked?: boolean;
107
+ attachment?: {
108
+ type: string;
109
+ text?: string;
110
+ url?: string;
111
+ [key: string]: unknown;
112
+ };
113
+ stickers?: Array<Record<string, unknown>>;
114
+ };
83
115
  }
84
- type MiniAppCapability = 'haptics' | 'popup' | 'qrScanner' | 'closeApp' | 'backButton' | 'backButtonVisibility' | 'bindCssVariables' | 'requestPhone' | 'notifications';
116
+ type MiniAppCapability = 'haptics' | 'popup' | 'qrScanner' | 'closeApp' | 'backButton' | 'backButtonVisibility' | 'bindCssVariables' | 'requestPhone' | 'notifications' | 'openInternalLink' | 'requestFullscreen' | 'verticalSwipes' | 'viewVisibility' | 'shareUrl' | 'shareStory' | 'copyTextToClipboard' | 'downloadFile' | 'addToHomeScreen' | 'checkHomeScreenStatus' | 'denyNotifications';
85
117
  interface MiniAppPopupButton {
86
118
  id: string;
87
119
  text?: string;
@@ -307,7 +339,7 @@ declare abstract class BaseMiniAppAdapter implements MiniAppAdapter {
307
339
  onPushToken(callback: (token: string) => void): () => void;
308
340
  onDeepLink(callback: (path: string) => void): () => void;
309
341
  openExternalLink(url: string): Promise<void>;
310
- openInternalLink(_url: string): Promise<void>;
342
+ openInternalLink(url: string): Promise<void>;
311
343
  closeApp(): Promise<void>;
312
344
  setBackButtonVisibility(_visible: boolean): void;
313
345
  onAppearanceChange(callback: (appearance: 'dark' | 'light' | undefined) => void): () => void;
@@ -361,6 +393,7 @@ declare class MaxMiniAppAdapter extends BaseMiniAppAdapter {
361
393
  onBackButton(callback: () => void): () => void;
362
394
  setBackButtonVisibility(visible: boolean): void;
363
395
  openExternalLink(url: string): Promise<void>;
396
+ openInternalLink(url: string): Promise<void>;
364
397
  closeApp(): Promise<void>;
365
398
  vibrateImpact(style: ImpactHapticFeedbackStyle): void;
366
399
  vibrateNotification(type: NotificationHapticFeedbackType): void;
@@ -505,6 +538,7 @@ declare class VKMiniAppAdapter extends BaseMiniAppAdapter {
505
538
  declare class WebMiniAppAdapter extends BaseMiniAppAdapter {
506
539
  private deferredPrompt;
507
540
  constructor();
541
+ supports(capability: MiniAppCapability): boolean | Promise<boolean>;
508
542
  downloadFile(url: string, filename: string): Promise<void>;
509
543
  scanQRCode(_options?: MiniAppQrScanOptions): Promise<string | null>;
510
544
  shareUrl(url: string, text: string): void;
package/dist/index.d.ts CHANGED
@@ -66,7 +66,7 @@ interface MiniAppInitOptions {
66
66
  */
67
67
  debug?: boolean;
68
68
  /**
69
- * Dynamically loads Eruda devtools if supported.
69
+ * Enables Eruda devtools when host app already exposed `window.eruda`.
70
70
  */
71
71
  eruda?: boolean;
72
72
  /**
@@ -75,13 +75,45 @@ interface MiniAppInitOptions {
75
75
  mockForMacOS?: boolean;
76
76
  }
77
77
  interface MiniAppShareStoryOptions {
78
+ /**
79
+ * Shared story caption. Used by Telegram directly.
80
+ * For VK this value is converted into a simple text sticker when `vk.stickers` is not provided.
81
+ */
78
82
  text?: string;
79
- widgetLink?: {
83
+ /**
84
+ * Universal CTA link.
85
+ * Telegram maps it to `widgetLink`, VK maps it to `attachment` when custom VK attachment is not provided.
86
+ */
87
+ link?: {
80
88
  url: string;
81
89
  name?: string;
82
90
  };
91
+ /**
92
+ * Telegram-specific options.
93
+ */
94
+ telegram?: {
95
+ text?: string;
96
+ widgetLink?: {
97
+ url: string;
98
+ name?: string;
99
+ };
100
+ };
101
+ /**
102
+ * VK-specific options.
103
+ */
104
+ vk?: {
105
+ backgroundType?: 'image' | 'video';
106
+ locked?: boolean;
107
+ attachment?: {
108
+ type: string;
109
+ text?: string;
110
+ url?: string;
111
+ [key: string]: unknown;
112
+ };
113
+ stickers?: Array<Record<string, unknown>>;
114
+ };
83
115
  }
84
- type MiniAppCapability = 'haptics' | 'popup' | 'qrScanner' | 'closeApp' | 'backButton' | 'backButtonVisibility' | 'bindCssVariables' | 'requestPhone' | 'notifications';
116
+ type MiniAppCapability = 'haptics' | 'popup' | 'qrScanner' | 'closeApp' | 'backButton' | 'backButtonVisibility' | 'bindCssVariables' | 'requestPhone' | 'notifications' | 'openInternalLink' | 'requestFullscreen' | 'verticalSwipes' | 'viewVisibility' | 'shareUrl' | 'shareStory' | 'copyTextToClipboard' | 'downloadFile' | 'addToHomeScreen' | 'checkHomeScreenStatus' | 'denyNotifications';
85
117
  interface MiniAppPopupButton {
86
118
  id: string;
87
119
  text?: string;
@@ -307,7 +339,7 @@ declare abstract class BaseMiniAppAdapter implements MiniAppAdapter {
307
339
  onPushToken(callback: (token: string) => void): () => void;
308
340
  onDeepLink(callback: (path: string) => void): () => void;
309
341
  openExternalLink(url: string): Promise<void>;
310
- openInternalLink(_url: string): Promise<void>;
342
+ openInternalLink(url: string): Promise<void>;
311
343
  closeApp(): Promise<void>;
312
344
  setBackButtonVisibility(_visible: boolean): void;
313
345
  onAppearanceChange(callback: (appearance: 'dark' | 'light' | undefined) => void): () => void;
@@ -361,6 +393,7 @@ declare class MaxMiniAppAdapter extends BaseMiniAppAdapter {
361
393
  onBackButton(callback: () => void): () => void;
362
394
  setBackButtonVisibility(visible: boolean): void;
363
395
  openExternalLink(url: string): Promise<void>;
396
+ openInternalLink(url: string): Promise<void>;
364
397
  closeApp(): Promise<void>;
365
398
  vibrateImpact(style: ImpactHapticFeedbackStyle): void;
366
399
  vibrateNotification(type: NotificationHapticFeedbackType): void;
@@ -505,6 +538,7 @@ declare class VKMiniAppAdapter extends BaseMiniAppAdapter {
505
538
  declare class WebMiniAppAdapter extends BaseMiniAppAdapter {
506
539
  private deferredPrompt;
507
540
  constructor();
541
+ supports(capability: MiniAppCapability): boolean | Promise<boolean>;
508
542
  downloadFile(url: string, filename: string): Promise<void>;
509
543
  scanQRCode(_options?: MiniAppQrScanOptions): Promise<string | null>;
510
544
  shareUrl(url: string, text: string): void;
package/dist/index.js CHANGED
@@ -580,7 +580,8 @@ var BaseMiniAppAdapter = class {
580
580
  async openExternalLink(url) {
581
581
  window.open(url, "_blank", "noopener,noreferrer");
582
582
  }
583
- async openInternalLink(_url) {
583
+ async openInternalLink(url) {
584
+ window.open(url, "_self", "noopener,noreferrer");
584
585
  }
585
586
  async closeApp() {
586
587
  if (window.history.length > 1) {
@@ -806,6 +807,10 @@ var MaxMiniAppAdapter = class extends BaseMiniAppAdapter {
806
807
  return Boolean(bridge2?.BackButton?.onClick);
807
808
  case "backButtonVisibility":
808
809
  return Boolean(bridge2?.BackButton?.show && bridge2.BackButton.hide);
810
+ case "openInternalLink":
811
+ return typeof bridge2?.openMaxLink === "function";
812
+ case "downloadFile":
813
+ return typeof bridge2?.downloadFile === "function";
809
814
  case "requestPhone":
810
815
  if (!bridge2) {
811
816
  return false;
@@ -860,6 +865,14 @@ var MaxMiniAppAdapter = class extends BaseMiniAppAdapter {
860
865
  }
861
866
  await super.openExternalLink(url);
862
867
  }
868
+ async openInternalLink(url) {
869
+ const bridge2 = getMaxBridge();
870
+ if (bridge2?.openMaxLink) {
871
+ bridge2.openMaxLink(url);
872
+ return;
873
+ }
874
+ await super.openInternalLink(url);
875
+ }
863
876
  async closeApp() {
864
877
  const bridge2 = getMaxBridge();
865
878
  if (bridge2?.close) {
@@ -1287,6 +1300,30 @@ var TelegramMiniAppAdapter = class extends BaseMiniAppAdapter {
1287
1300
  return backButton.hide.isSupported();
1288
1301
  case "bindCssVariables":
1289
1302
  return true;
1303
+ case "openInternalLink":
1304
+ return true;
1305
+ case "requestFullscreen":
1306
+ return Boolean(
1307
+ typeof rawViewport.requestFullscreen === "function" || viewport.requestFullscreen?.isAvailable?.()
1308
+ );
1309
+ case "verticalSwipes":
1310
+ return Boolean(
1311
+ swipeBehavior.enableVertical.isAvailable() || swipeBehavior.disableVertical.isAvailable()
1312
+ );
1313
+ case "viewVisibility":
1314
+ return true;
1315
+ case "shareUrl":
1316
+ return typeof shareURLSdk === "function";
1317
+ case "shareStory":
1318
+ return typeof shareStorySdk === "function";
1319
+ case "copyTextToClipboard":
1320
+ return typeof copyTextToClipboardSdk === "function";
1321
+ case "downloadFile":
1322
+ return typeof downloadFileSdk === "function";
1323
+ case "addToHomeScreen":
1324
+ return typeof addToHomeScreenSdk?.isAvailable === "function" ? addToHomeScreenSdk.isAvailable() : typeof addToHomeScreenSdk === "function";
1325
+ case "checkHomeScreenStatus":
1326
+ return typeof checkHomeScreenStatusSdk === "function";
1290
1327
  case "requestPhone": {
1291
1328
  return Boolean(isFeatureAvailable(requestPhoneAccess) || isFeatureAvailable(requestContact));
1292
1329
  }
@@ -1532,7 +1569,15 @@ var TelegramMiniAppAdapter = class extends BaseMiniAppAdapter {
1532
1569
  await super.downloadFile(url, filename);
1533
1570
  }
1534
1571
  async shareStory(mediaUrl, options) {
1535
- shareStorySdk(mediaUrl, options);
1572
+ const text = options?.telegram?.text ?? options?.text;
1573
+ const widgetLink = options?.telegram?.widgetLink ?? (options?.link ? {
1574
+ url: options.link.url,
1575
+ ...options.link.name ? { name: options.link.name } : {}
1576
+ } : void 0);
1577
+ shareStorySdk(mediaUrl, {
1578
+ ...text ? { text } : {},
1579
+ ...widgetLink ? { widgetLink } : {}
1580
+ });
1536
1581
  }
1537
1582
  async addToHomeScreen() {
1538
1583
  const isAvailable = typeof addToHomeScreenSdk?.isAvailable === "function" ? addToHomeScreenSdk.isAvailable() : true;
@@ -1889,17 +1934,41 @@ var VKMiniAppAdapter = class extends BaseMiniAppAdapter {
1889
1934
  };
1890
1935
  }
1891
1936
  async supports(capability) {
1892
- if (capability === "requestPhone") {
1893
- const [supportsPhoneNumber, supportsPersonalCard] = await Promise.all([
1894
- this.supportsBridgeMethod("VKWebAppGetPhoneNumber"),
1895
- this.supportsBridgeMethod("VKWebAppGetPersonalCard")
1896
- ]);
1897
- return supportsPhoneNumber || supportsPersonalCard;
1898
- }
1899
- if (capability === "notifications") {
1900
- return this.supportsBridgeMethod("VKWebAppAllowNotifications");
1937
+ switch (capability) {
1938
+ case "haptics": {
1939
+ const [impact, notification, selection] = await Promise.all([
1940
+ this.supportsBridgeMethod("VKWebAppTapticImpactOccurred"),
1941
+ this.supportsBridgeMethod("VKWebAppTapticNotificationOccurred"),
1942
+ this.supportsBridgeMethod("VKWebAppTapticSelectionChanged")
1943
+ ]);
1944
+ return impact || notification || selection;
1945
+ }
1946
+ case "qrScanner":
1947
+ return this.supportsBridgeMethod("VKWebAppOpenCodeReader");
1948
+ case "requestPhone": {
1949
+ const [supportsPhoneNumber, supportsPersonalCard] = await Promise.all([
1950
+ this.supportsBridgeMethod("VKWebAppGetPhoneNumber"),
1951
+ this.supportsBridgeMethod("VKWebAppGetPersonalCard")
1952
+ ]);
1953
+ return supportsPhoneNumber || supportsPersonalCard;
1954
+ }
1955
+ case "notifications":
1956
+ return this.supportsBridgeMethod("VKWebAppAllowNotifications");
1957
+ case "shareUrl":
1958
+ return this.supportsBridgeMethod("VKWebAppShare");
1959
+ case "shareStory":
1960
+ return this.supportsBridgeMethod("VKWebAppShowStoryBox");
1961
+ case "downloadFile":
1962
+ return this.supportsBridgeMethod("VKWebAppDownloadFile");
1963
+ case "addToHomeScreen":
1964
+ return this.supportsBridgeMethod("VKWebAppAddToHomeScreen");
1965
+ case "denyNotifications":
1966
+ return this.supportsBridgeMethod("VKWebAppDenyNotifications");
1967
+ case "viewVisibility":
1968
+ return true;
1969
+ default:
1970
+ return await super.supports(capability);
1901
1971
  }
1902
- return await super.supports(capability);
1903
1972
  }
1904
1973
  async requestPhone() {
1905
1974
  const [supportsPhoneNumber, supportsPersonalCard] = await Promise.all([
@@ -2001,9 +2070,34 @@ var VKMiniAppAdapter = class extends BaseMiniAppAdapter {
2001
2070
  };
2002
2071
  }
2003
2072
  async shareStory(mediaUrl, _options) {
2073
+ const options = _options;
2074
+ const vkOptions = options?.vk;
2075
+ const fallbackAttachment = options?.link ? {
2076
+ type: "url",
2077
+ text: "open",
2078
+ url: options.link.url
2079
+ } : void 0;
2080
+ const fallbackStickers = options?.text ? [{
2081
+ sticker_type: "native",
2082
+ sticker: {
2083
+ action_type: "text",
2084
+ action: {
2085
+ text: options.text,
2086
+ style: "classic",
2087
+ background_style: "none"
2088
+ },
2089
+ transform: {
2090
+ gravity: "center_bottom",
2091
+ translation_y: -0.2
2092
+ }
2093
+ }
2094
+ }] : void 0;
2004
2095
  const bridgeOptions = {
2005
- background_type: "image",
2006
- url: mediaUrl
2096
+ background_type: vkOptions?.backgroundType ?? "image",
2097
+ url: mediaUrl,
2098
+ locked: vkOptions?.locked ?? true,
2099
+ ...vkOptions?.attachment ?? fallbackAttachment ? { attachment: vkOptions?.attachment ?? fallbackAttachment } : {},
2100
+ ...vkOptions?.stickers ?? fallbackStickers ? { stickers: vkOptions?.stickers ?? fallbackStickers } : {}
2007
2101
  };
2008
2102
  await bridge.send("VKWebAppShowStoryBox", bridgeOptions);
2009
2103
  }
@@ -2392,6 +2486,22 @@ var WebMiniAppAdapter = class extends BaseMiniAppAdapter {
2392
2486
  });
2393
2487
  }
2394
2488
  }
2489
+ supports(capability) {
2490
+ switch (capability) {
2491
+ case "copyTextToClipboard":
2492
+ return typeof navigator !== "undefined" && Boolean(navigator.clipboard?.writeText);
2493
+ case "downloadFile":
2494
+ return typeof document !== "undefined";
2495
+ case "shareUrl":
2496
+ return typeof navigator !== "undefined" && (Boolean(navigator.share) || Boolean(navigator.clipboard?.writeText));
2497
+ case "addToHomeScreen":
2498
+ return /android/i.test(navigator.userAgent) && Boolean(this.deferredPrompt);
2499
+ case "checkHomeScreenStatus":
2500
+ return true;
2501
+ default:
2502
+ return super.supports(capability);
2503
+ }
2504
+ }
2395
2505
  async downloadFile(url, filename) {
2396
2506
  try {
2397
2507
  await triggerFileDownload(url, filename, { preferBlob: true });