@tonconnect/ui 2.0.0-beta.4 → 2.0.0-beta.5

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/lib/index.d.ts CHANGED
@@ -160,6 +160,11 @@ interface TonConnectUiOptions {
160
160
  * Configuration for action-period (e.g. sendTransaction) UI elements: modals and notifications and wallet behaviour (return strategy).
161
161
  */
162
162
  actionsConfiguration?: ActionConfiguration;
163
+ /**
164
+ * Specifies whether the Android back button should be used to close modals and notifications on Android devices.
165
+ * @default true
166
+ */
167
+ enableAndroidBackHandler?: boolean;
163
168
  }
164
169
 
165
170
  declare type TonConnectUiCreateOptions = TonConnectUiOptionsWithConnector | TonConnectUiOptionsWithManifest;
@@ -1706,6 +1706,43 @@ function rgba(color, opacity) {
1706
1706
  function toPx(value) {
1707
1707
  return value.toString() + "px";
1708
1708
  }
1709
+ const _InMemoryStorage = class {
1710
+ constructor() {
1711
+ __publicField(this, "storage", {});
1712
+ }
1713
+ static getInstance() {
1714
+ if (!_InMemoryStorage.instance) {
1715
+ _InMemoryStorage.instance = new _InMemoryStorage();
1716
+ }
1717
+ return _InMemoryStorage.instance;
1718
+ }
1719
+ get length() {
1720
+ return Object.keys(this.storage).length;
1721
+ }
1722
+ clear() {
1723
+ this.storage = {};
1724
+ }
1725
+ getItem(key) {
1726
+ var _a2;
1727
+ return (_a2 = this.storage[key]) != null ? _a2 : null;
1728
+ }
1729
+ key(index) {
1730
+ var _a2;
1731
+ const keys = Object.keys(this.storage);
1732
+ if (index < 0 || index >= keys.length) {
1733
+ return null;
1734
+ }
1735
+ return (_a2 = keys[index]) != null ? _a2 : null;
1736
+ }
1737
+ removeItem(key) {
1738
+ delete this.storage[key];
1739
+ }
1740
+ setItem(key, value) {
1741
+ this.storage[key] = value;
1742
+ }
1743
+ };
1744
+ let InMemoryStorage = _InMemoryStorage;
1745
+ __publicField(InMemoryStorage, "instance");
1709
1746
  class TonConnectUIError extends TonConnectError {
1710
1747
  constructor(...args) {
1711
1748
  super(...args);
@@ -1770,16 +1807,13 @@ function defineStylesRoot() {
1770
1807
  });
1771
1808
  }
1772
1809
  function preloadImages(images) {
1773
- images.forEach((img) => {
1774
- const node = new window.Image();
1775
- node.src = img;
1776
- });
1777
- }
1778
- function checkLocalStorageExists() {
1779
- if (typeof localStorage === "undefined") {
1780
- throw new TonConnectUIError(
1781
- "window.localStorage is undefined. localStorage is required for TonConnectUI"
1782
- );
1810
+ if (document.readyState !== "complete") {
1811
+ window.addEventListener("load", () => preloadImages(images), { once: true });
1812
+ } else {
1813
+ images.forEach((img) => {
1814
+ const node = new window.Image();
1815
+ node.src = img;
1816
+ });
1783
1817
  }
1784
1818
  }
1785
1819
  function getWindow$1() {
@@ -1788,6 +1822,27 @@ function getWindow$1() {
1788
1822
  }
1789
1823
  return void 0;
1790
1824
  }
1825
+ function tryGetLocalStorage() {
1826
+ if (isLocalStorageAvailable()) {
1827
+ return localStorage;
1828
+ }
1829
+ if (isNodeJs()) {
1830
+ throw new TonConnectUIError(
1831
+ "`localStorage` is unavailable, but it is required for TonConnect. For more details, see https://github.com/ton-connect/sdk/tree/main/packages/sdk#init-connector"
1832
+ );
1833
+ }
1834
+ return InMemoryStorage.getInstance();
1835
+ }
1836
+ function isLocalStorageAvailable() {
1837
+ try {
1838
+ return typeof localStorage !== "undefined";
1839
+ } catch (e2) {
1840
+ return false;
1841
+ }
1842
+ }
1843
+ function isNodeJs() {
1844
+ return typeof process !== "undefined" && process.versions != null && process.versions.node != null;
1845
+ }
1791
1846
  function getUserAgent() {
1792
1847
  var _a2, _b;
1793
1848
  const results = new UAParser().getResult();
@@ -1841,8 +1896,7 @@ class WalletInfoStorage {
1841
1896
  constructor() {
1842
1897
  __publicField(this, "localStorage");
1843
1898
  __publicField(this, "storageKey", "ton-connect-ui_wallet-info");
1844
- checkLocalStorageExists();
1845
- this.localStorage = localStorage;
1899
+ this.localStorage = tryGetLocalStorage();
1846
1900
  }
1847
1901
  setWalletInfo(walletInfo) {
1848
1902
  this.localStorage.setItem(this.storageKey, JSON.stringify(walletInfo));
@@ -1862,8 +1916,7 @@ class PreferredWalletStorage {
1862
1916
  constructor() {
1863
1917
  __publicField(this, "localStorage");
1864
1918
  __publicField(this, "storageKey", "ton-connect-ui_preferred-wallet");
1865
- checkLocalStorageExists();
1866
- this.localStorage = localStorage;
1919
+ this.localStorage = tryGetLocalStorage();
1867
1920
  }
1868
1921
  setPreferredWalletAppName(name) {
1869
1922
  this.localStorage.setItem(this.storageKey, name);
@@ -1876,8 +1929,7 @@ class LastSelectedWalletInfoStorage {
1876
1929
  constructor() {
1877
1930
  __publicField(this, "localStorage");
1878
1931
  __publicField(this, "storageKey", "ton-connect-ui_last-selected-wallet-info");
1879
- checkLocalStorageExists();
1880
- this.localStorage = localStorage;
1932
+ this.localStorage = tryGetLocalStorage();
1881
1933
  }
1882
1934
  setLastSelectedWalletInfo(walletInfo) {
1883
1935
  this.localStorage.setItem(this.storageKey, JSON.stringify(walletInfo));
@@ -2999,30 +3051,40 @@ function escPressed(_, accessor) {
2999
3051
  document.body.addEventListener("keydown", onKeyPress);
3000
3052
  onCleanup(() => document.body.removeEventListener("keydown", onKeyPress));
3001
3053
  }
3002
- function androidBackHandler$1(_, accessor) {
3054
+ function androidBackHandler$1(_, config) {
3055
+ const {
3056
+ isEnabled,
3057
+ onClose
3058
+ } = config();
3059
+ if (!isEnabled) {
3060
+ return;
3061
+ }
3003
3062
  const userOSIsAndroid = getUserAgent().os === "android";
3004
3063
  if (!userOSIsAndroid) {
3005
3064
  return;
3006
3065
  }
3007
- let historyEntryAdded = true;
3008
- window.history.pushState({}, "");
3066
+ window.history.pushState(ROUTE_STATE, "");
3009
3067
  const popstateHandler = (event) => {
3010
- var _a2;
3011
- historyEntryAdded = false;
3012
3068
  event.preventDefault();
3013
- (_a2 = accessor()) == null ? void 0 : _a2();
3069
+ onClose();
3014
3070
  };
3015
3071
  window.addEventListener("popstate", popstateHandler, {
3016
3072
  once: true
3017
3073
  });
3018
3074
  onCleanup(() => {
3019
3075
  window.removeEventListener("popstate", popstateHandler);
3020
- if (historyEntryAdded) {
3021
- historyEntryAdded = false;
3022
- window.history.back();
3023
- }
3076
+ new Promise((resolve) => requestAnimationFrame(resolve)).then(() => {
3077
+ var _a2;
3078
+ if (((_a2 = window.history.state) == null ? void 0 : _a2[ROUTE_STATE_KEY]) === true) {
3079
+ window.history.back();
3080
+ }
3081
+ });
3024
3082
  });
3025
3083
  }
3084
+ const ROUTE_STATE_KEY = "androidBackHandler";
3085
+ const ROUTE_STATE = {
3086
+ [ROUTE_STATE_KEY]: true
3087
+ };
3026
3088
  const _tmpl$$v = /* @__PURE__ */ template$1(`<svg><path fill-rule="evenodd" clip-rule="evenodd" d="M10.2122 14.3407C10.5384 14.0854 10.5959 13.614 10.3406 13.2878L6.20237 8.00003L10.3406 2.71227C10.5959 2.38607 10.5384 1.91469 10.2122 1.6594C9.88604 1.40412 9.41465 1.46161 9.15937 1.7878L4.65937 7.5378C4.44688 7.80932 4.44688 8.19074 4.65937 8.46226L9.15937 14.2123C9.41465 14.5385 9.88604 14.5959 10.2122 14.3407Z"></path></svg>`, 4, true);
3027
3089
  const rotationDegrees = {
3028
3090
  left: 0,
@@ -3230,6 +3292,77 @@ const ModalFooterStyled = styled.div`
3230
3292
  const QuestionButtonStyled = styled(IconButton)`
3231
3293
  background-color: ${(props) => rgba(props.theme.colors.icon.secondary, 0.12)};
3232
3294
  `;
3295
+ function logWarning(...args) {
3296
+ {
3297
+ try {
3298
+ console.warn("[TON_CONNECT_UI]", ...args);
3299
+ } catch (e2) {
3300
+ }
3301
+ }
3302
+ }
3303
+ class AnimationTimelineNoop {
3304
+ constructor() {
3305
+ __publicField(this, "currentTime", 0);
3306
+ }
3307
+ }
3308
+ const _AnimationNoop = class {
3309
+ constructor() {
3310
+ __publicField(this, "currentTime", 0);
3311
+ __publicField(this, "playbackRate", 1);
3312
+ __publicField(this, "startTime", null);
3313
+ __publicField(this, "timeline", new AnimationTimelineNoop());
3314
+ __publicField(this, "finished", Promise.resolve(this));
3315
+ __publicField(this, "effect", null);
3316
+ __publicField(this, "id", "");
3317
+ __publicField(this, "pending", false);
3318
+ __publicField(this, "playState", "finished");
3319
+ __publicField(this, "replaceState", "active");
3320
+ __publicField(this, "ready", Promise.resolve(this));
3321
+ __publicField(this, "oncancel", null);
3322
+ __publicField(this, "onfinish", null);
3323
+ __publicField(this, "onremove", null);
3324
+ }
3325
+ static create() {
3326
+ if (!_AnimationNoop._instance) {
3327
+ logWarning(
3328
+ "Animation is not supported in this environment: please consider using the `web-animations-js` polyfill to provide a fallback implementation of the Web Animations API."
3329
+ );
3330
+ _AnimationNoop._instance = new _AnimationNoop();
3331
+ }
3332
+ return _AnimationNoop._instance;
3333
+ }
3334
+ cancel() {
3335
+ }
3336
+ finish() {
3337
+ }
3338
+ pause() {
3339
+ }
3340
+ play() {
3341
+ }
3342
+ reverse() {
3343
+ }
3344
+ addEventListener(_type, _listener, _options) {
3345
+ }
3346
+ dispatchEvent(_event) {
3347
+ return false;
3348
+ }
3349
+ removeEventListener(_type, _callback, _options) {
3350
+ }
3351
+ updatePlaybackRate(_playbackRate) {
3352
+ }
3353
+ commitStyles() {
3354
+ }
3355
+ persist() {
3356
+ }
3357
+ };
3358
+ let AnimationNoop = _AnimationNoop;
3359
+ __publicField(AnimationNoop, "_instance", null);
3360
+ function animate(element, keyframes, options) {
3361
+ if ("animate" in element) {
3362
+ return element.animate(keyframes, options);
3363
+ }
3364
+ return AnimationNoop.create();
3365
+ }
3233
3366
  const _tmpl$$t = /* @__PURE__ */ template$1(`<div></div>`);
3234
3367
  const clickOutside = clickOutside$1;
3235
3368
  const keyPressed = escPressed;
@@ -3247,7 +3380,7 @@ const Modal = (props) => {
3247
3380
  return createComponent(Transition, {
3248
3381
  onBeforeEnter: (el) => {
3249
3382
  const duration = isDevice("mobile") ? 200 : 100;
3250
- el.animate([{
3383
+ animate(el, [{
3251
3384
  opacity: 0
3252
3385
  }, {
3253
3386
  opacity: 1
@@ -3255,7 +3388,7 @@ const Modal = (props) => {
3255
3388
  duration
3256
3389
  });
3257
3390
  if (isDevice("mobile")) {
3258
- el.firstElementChild.animate([{
3391
+ animate(el.firstElementChild, [{
3259
3392
  transform: "translateY(390px)"
3260
3393
  }, {
3261
3394
  transform: "translateY(0)"
@@ -3266,7 +3399,7 @@ const Modal = (props) => {
3266
3399
  },
3267
3400
  onExit: (el, done) => {
3268
3401
  const duration = isDevice("mobile") ? 200 : 100;
3269
- const backgroundAnimation = el.animate([{
3402
+ const backgroundAnimation = animate(el, [{
3270
3403
  opacity: 1
3271
3404
  }, {
3272
3405
  opacity: 0
@@ -3274,7 +3407,7 @@ const Modal = (props) => {
3274
3407
  duration
3275
3408
  });
3276
3409
  if (isDevice("mobile")) {
3277
- const contentAnimation = el.firstElementChild.animate([{
3410
+ const contentAnimation = animate(el.firstElementChild, [{
3278
3411
  transform: "translateY(0)"
3279
3412
  }, {
3280
3413
  transform: "translateY(390px)"
@@ -3297,7 +3430,10 @@ const Modal = (props) => {
3297
3430
  }, dataAttrs, {
3298
3431
  get children() {
3299
3432
  const _el$ = _tmpl$$t.cloneNode(true);
3300
- use(androidBackHandler, _el$, () => () => props.onClose());
3433
+ use(androidBackHandler, _el$, () => ({
3434
+ isEnabled: props.enableAndroidBackHandler,
3435
+ onClose: () => props.onClose()
3436
+ }));
3301
3437
  use(keyPressed, _el$, () => () => props.onClose());
3302
3438
  use(clickOutside, _el$, () => () => props.onClose());
3303
3439
  insert(_el$, createComponent(ModalBodyStyled, {
@@ -5315,7 +5451,7 @@ const QRCode = (props) => {
5315
5451
  }
5316
5452
  }), createComponent(Transition, {
5317
5453
  onBeforeEnter: (el) => {
5318
- el.animate([{
5454
+ animate(el, [{
5319
5455
  opacity: 0,
5320
5456
  transform: "translate(-50%, 44px)"
5321
5457
  }, {
@@ -5327,7 +5463,7 @@ const QRCode = (props) => {
5327
5463
  });
5328
5464
  },
5329
5465
  onExit: (el, done) => {
5330
- el.animate([{
5466
+ animate(el, [{
5331
5467
  opacity: 1,
5332
5468
  transform: "translate(-50%, 0)"
5333
5469
  }, {
@@ -6223,8 +6359,10 @@ if (getWindow$1()) {
6223
6359
  window.addEventListener("resize", () => setWindowHeight(window.innerHeight));
6224
6360
  }
6225
6361
  const [isMobile, setIsMobile] = createSignal(isDevice("mobile"));
6362
+ const updateIsMobile = () => setIsMobile(isDevice("mobile"));
6226
6363
  if (getWindow$1()) {
6227
- window.addEventListener("resize", () => setIsMobile(isDevice("mobile")));
6364
+ window.addEventListener("resize", () => updateIsMobile());
6365
+ window.addEventListener("load", () => updateIsMobile(), { once: true });
6228
6366
  }
6229
6367
  const ScrollContainer = (props) => {
6230
6368
  const [scrolled, setScrolled] = createSignal(false);
@@ -6624,7 +6762,7 @@ const Notifications = (props) => {
6624
6762
  const _el$ = _tmpl$$4.cloneNode(true);
6625
6763
  insert(_el$, createComponent(TransitionGroup, {
6626
6764
  onBeforeEnter: (el) => {
6627
- el.animate([{
6765
+ animate(el, [{
6628
6766
  opacity: 0,
6629
6767
  transform: "translateY(0)"
6630
6768
  }, {
@@ -6635,7 +6773,7 @@ const Notifications = (props) => {
6635
6773
  });
6636
6774
  },
6637
6775
  onExit: (el, done) => {
6638
- const a2 = el.animate([{
6776
+ const a2 = animate(el, [{
6639
6777
  opacity: 1,
6640
6778
  transform: "translateY(-8px)"
6641
6779
  }, {
@@ -7559,7 +7697,7 @@ const AccountButton = () => {
7559
7697
  },
7560
7698
  get children() {
7561
7699
  return createComponent(AccountButtonStyled, {
7562
- onClick: () => tonConnectUI.connectWallet(),
7700
+ onClick: () => tonConnectUI.openModal(),
7563
7701
  "data-tc-connect-button": "true",
7564
7702
  scale: "s",
7565
7703
  get children() {
@@ -7612,7 +7750,7 @@ const AccountButton = () => {
7612
7750
  _el$._$owner = getOwner();
7613
7751
  insert(_el$, createComponent(Transition, {
7614
7752
  onBeforeEnter: (el) => {
7615
- el.animate([{
7753
+ animate(el, [{
7616
7754
  opacity: 0,
7617
7755
  transform: "translateY(-8px)"
7618
7756
  }, {
@@ -7623,7 +7761,7 @@ const AccountButton = () => {
7623
7761
  });
7624
7762
  },
7625
7763
  onExit: (el, done) => {
7626
- const a2 = el.animate([{
7764
+ const a2 = animate(el, [{
7627
7765
  opacity: 1,
7628
7766
  transform: "translateY(0)"
7629
7767
  }, {
@@ -7723,7 +7861,8 @@ const [appState, setAppState] = createStore({
7723
7861
  language: "en",
7724
7862
  returnStrategy: "back",
7725
7863
  twaReturnUrl: void 0,
7726
- walletsListConfiguration: {}
7864
+ walletsListConfiguration: {},
7865
+ enableAndroidBackHandler: true
7727
7866
  });
7728
7867
  function uniq(array) {
7729
7868
  return [...new Set(array)];
@@ -8913,7 +9052,7 @@ const MobileUniversalModal = (props) => {
8913
9052
  const walletsBridges = () => [...new Set(props.walletsList.filter(isWalletInfoRemote).map((item) => item.bridgeUrl)).values()].map((bridgeUrl) => ({
8914
9053
  bridgeUrl
8915
9054
  }));
8916
- const universalLink = createMemo(() => connector.connect(walletsBridges(), props.additionalRequest));
9055
+ const getUniversalLink = () => connector.connect(walletsBridges(), props.additionalRequest);
8917
9056
  setLastSelectedWalletInfo({
8918
9057
  openMethod: "universal-link"
8919
9058
  });
@@ -8922,12 +9061,12 @@ const MobileUniversalModal = (props) => {
8922
9061
  if (isCopiedShown() !== void 0) {
8923
9062
  clearTimeout(isCopiedShown());
8924
9063
  }
8925
- yield copyToClipboard(universalLink());
9064
+ yield copyToClipboard(getUniversalLink());
8926
9065
  const timeoutId = setTimeout(() => setIsCopiedShown(void 0), 1500);
8927
9066
  setIsCopiedShown(timeoutId);
8928
9067
  });
8929
9068
  const onSelectUniversal = () => {
8930
- openLinkBlank(addReturnStrategy(universalLink(), appState.returnStrategy));
9069
+ openLinkBlank(addReturnStrategy(getUniversalLink(), appState.returnStrategy));
8931
9070
  };
8932
9071
  const onSelectTelegram = () => {
8933
9072
  const atWallet = props.walletsList.find((wallet) => wallet.appName === AT_WALLET_APP_NAME);
@@ -8967,7 +9106,7 @@ const MobileUniversalModal = (props) => {
8967
9106
  onClick: onCloseQR
8968
9107
  }), createComponent(MobileUniversalQR, {
8969
9108
  get universalLink() {
8970
- return universalLink();
9109
+ return getUniversalLink();
8971
9110
  }
8972
9111
  })];
8973
9112
  }
@@ -9251,6 +9390,11 @@ const WalletsModal = () => {
9251
9390
  locale
9252
9391
  } = useI18n()[1];
9253
9392
  createEffect(() => locale(appState.language));
9393
+ createEffect(() => {
9394
+ if (getWalletsModalIsOpened()) {
9395
+ updateIsMobile();
9396
+ }
9397
+ });
9254
9398
  const connector = useContext(ConnectorContext);
9255
9399
  const tonConnectUI = useContext(TonConnectUiContext);
9256
9400
  const [fetchedWalletsList] = createResource(() => tonConnectUI.getWallets());
@@ -9308,6 +9452,9 @@ const WalletsModal = () => {
9308
9452
  get opened() {
9309
9453
  return getWalletsModalIsOpened();
9310
9454
  },
9455
+ get enableAndroidBackHandler() {
9456
+ return appState.enableAndroidBackHandler;
9457
+ },
9311
9458
  onClose: () => onClose("action-cancelled"),
9312
9459
  onClickQuestion: () => setInfoTab((v) => !v),
9313
9460
  "data-tc-wallets-modal-container": "true",
@@ -9553,6 +9700,9 @@ const ActionsModal = () => {
9553
9700
  var _a2;
9554
9701
  return createMemo(() => action() !== null)() && ((_a2 = action()) == null ? void 0 : _a2.openModal) === true;
9555
9702
  },
9703
+ get enableAndroidBackHandler() {
9704
+ return appState.enableAndroidBackHandler;
9705
+ },
9556
9706
  onClose: () => setAction(null),
9557
9707
  "data-tc-actions-modal-container": "true",
9558
9708
  get children() {
@@ -9839,6 +9989,9 @@ class TonConnectUI {
9839
9989
  if (options.buttonRootId !== void 0) {
9840
9990
  merged.buttonRootId = options.buttonRootId;
9841
9991
  }
9992
+ if (options.enableAndroidBackHandler !== void 0) {
9993
+ merged.enableAndroidBackHandler = options.enableAndroidBackHandler;
9994
+ }
9842
9995
  return merged;
9843
9996
  });
9844
9997
  }
@@ -10177,4 +10330,4 @@ export {
10177
10330
  TonConnectUI,
10178
10331
  TonConnectUIError
10179
10332
  };
10180
- //# sourceMappingURL=index.js.map
10333
+ //# sourceMappingURL=index.mjs.map