@apps-in-toss/framework 0.0.0-dev.1758198081085 → 0.0.0-dev.1760064876537

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.js CHANGED
@@ -5,7 +5,7 @@ import { Analytics as InternalAnalytics } from "@apps-in-toss/analytics";
5
5
  import { Analytics } from "@apps-in-toss/analytics";
6
6
  import { isMinVersionSupported as isMinVersionSupported2, setIosSwipeGestureEnabled, eventLog } from "@apps-in-toss/native-modules";
7
7
  import { Granite as Granite6 } from "@granite-js/react-native";
8
- import { TDSProvider } from "@toss-design-system/react-native";
8
+ import { TDSProvider } from "@toss/tds-react-native";
9
9
  import { AppRegistry } from "react-native";
10
10
 
11
11
  // src/core/components/AppEvent.tsx
@@ -151,7 +151,7 @@ function AppUpdate() {
151
151
 
152
152
  // src/core/hooks/useAppsInTossBridge.ts
153
153
  import { appsInTossEvent } from "@apps-in-toss/native-modules";
154
- import { useBridge } from "@toss-design-system/react-native";
154
+ import { useBridge } from "@toss/tds-react-native";
155
155
  import { useEffect as useEffect4 } from "react";
156
156
 
157
157
  // src/core/utils/getAppsInTossGlobals.ts
@@ -189,8 +189,8 @@ function useAppsInTossBridge() {
189
189
 
190
190
  // src/components/NavigationBar/RNNavigationBar.tsx
191
191
  import { closeView, useBackEventContext, useNavigation } from "@granite-js/react-native";
192
- import { useDialog as useDialog2 } from "@toss-design-system/react-native";
193
- import { NavigationBackButton, NavigationLeft, TopNavigation } from "@toss-design-system/react-native/private";
192
+ import { useDialog as useDialog3 } from "@toss/tds-react-native";
193
+ import { NavigationBackButton, NavigationLeft, TopNavigation } from "@toss/tds-react-native/private";
194
194
  import { josa } from "es-hangul";
195
195
  import { useCallback as useCallback3, useEffect as useEffect7 } from "react";
196
196
  import { BackHandler } from "react-native";
@@ -302,10 +302,17 @@ function NavigationBarImpressionArea({
302
302
  // src/core/hooks/useMoreButtonBottomSheet/index.tsx
303
303
  import { INTERNAL__appBridgeHandler, isMinVersionSupported } from "@apps-in-toss/native-modules";
304
304
  import { openURL as openURL3 } from "@granite-js/react-native";
305
- import { BottomSheet, List, ListHeader, ListRow } from "@toss-design-system/react-native";
306
- import { useAdaptive, useOverlay } from "@toss-design-system/react-native/private";
305
+ import { BottomSheet, List, ListHeader, ListRow as ListRow2 } from "@toss/tds-react-native";
306
+ import { useAdaptive as useAdaptive2, useOverlay } from "@toss/tds-react-native/private";
307
307
  import { useEffect as useEffect6, useState } from "react";
308
308
 
309
+ // src/core/hooks/useMoreButtonBottomSheet/AppShareListMenu.tsx
310
+ import { getOperationalEnvironment } from "@apps-in-toss/native-modules";
311
+ import { getSchemeUri as getSchemeUri4 } from "@granite-js/react-native";
312
+ import { ListRow, useDialog } from "@toss/tds-react-native";
313
+ import { useAdaptive } from "@toss/tds-react-native/private";
314
+ import { NativeModules } from "react-native";
315
+
309
316
  // src/core/hooks/useMoreButtonBottomSheet/useMoreButtonBottomSheetLogging.tsx
310
317
  import { INTERNAL__module as INTERNAL__module4 } from "@apps-in-toss/native-modules";
311
318
  import { Granite as Granite4 } from "@granite-js/react-native";
@@ -375,10 +382,77 @@ function useMoreButtonBottomSheetLogging() {
375
382
  };
376
383
  }
377
384
 
385
+ // src/core/utils/url.ts
386
+ function addParamsToUrl(url, params) {
387
+ const urlObj = new URL(url);
388
+ for (const [key, value] of Object.entries(params)) {
389
+ urlObj.searchParams.set(key, value);
390
+ }
391
+ return urlObj.toString();
392
+ }
393
+
394
+ // src/core/hooks/useMoreButtonBottomSheet/AppShareListMenu.tsx
395
+ import { jsx as jsx3 } from "react/jsx-runtime";
396
+ var SHARE_SCHEME_REFERRER = "appsintoss.common_module_share";
397
+ var APP_SHARE_MENU_INFO = {
398
+ contactItemName: "\uACF5\uC720\uD558\uAE30",
399
+ contactIconUrl: "https://static.toss.im/icons/png/4x/icon-share-dots-mono.png"
400
+ };
401
+ function AppShareListMenu() {
402
+ const globals = getAppsInTossGlobals();
403
+ const adaptive = useAdaptive();
404
+ const logging = useMoreButtonBottomSheetLogging();
405
+ const initialScheme = getSchemeUri4();
406
+ const isSandbox = getOperationalEnvironment() === "sandbox";
407
+ const { openConfirm } = useDialog();
408
+ const schemeForShare = addParamsToUrl(initialScheme, {
409
+ referrer: SHARE_SCHEME_REFERRER
410
+ });
411
+ return /* @__PURE__ */ jsx3(
412
+ ListRow,
413
+ {
414
+ left: /* @__PURE__ */ jsx3(
415
+ ListRow.Icon,
416
+ {
417
+ color: globals.brandPrimaryColor,
418
+ source: { uri: APP_SHARE_MENU_INFO.contactIconUrl },
419
+ type: "background"
420
+ }
421
+ ),
422
+ contents: /* @__PURE__ */ jsx3(
423
+ ListRow.Texts,
424
+ {
425
+ type: "1RowTypeA",
426
+ top: APP_SHARE_MENU_INFO.contactItemName,
427
+ topProps: { color: adaptive.grey700 }
428
+ }
429
+ ),
430
+ verticalPadding: "extraSmall",
431
+ onPress: () => {
432
+ if (isSandbox) {
433
+ openConfirm({
434
+ title: "\uACF5\uC720\uD558\uAE30 \uAE30\uB2A5 \uBBF8\uC9C0\uC6D0",
435
+ description: "\uC0CC\uB4DC\uBC15\uC2A4 \uD658\uACBD\uC5D0\uC11C\uB294 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC5B4\uC694. \uCF58\uC194\uC744 \uD1B5\uD574 \uD1A0\uC2A4\uC571\uC5D0\uC11C \uD14C\uC2A4\uD2B8\uD574 \uC8FC\uC138\uC694.",
436
+ rightButton: "\uD655\uC778",
437
+ closeOnDimmerClick: true
438
+ });
439
+ return;
440
+ }
441
+ logging.menuClick({ title: APP_SHARE_MENU_INFO.contactItemName });
442
+ NativeModules.AppsInTossModule.shareWithScheme({
443
+ params: {
444
+ schemeURL: schemeForShare
445
+ }
446
+ });
447
+ }
448
+ }
449
+ );
450
+ }
451
+
378
452
  // src/hooks/useAppUpdateDialog.tsx
379
453
  import { INTERNAL__module as INTERNAL__module5 } from "@apps-in-toss/native-modules";
380
454
  import { Granite as Granite5, openURL as openURL2 } from "@granite-js/react-native";
381
- import { useDialog } from "@toss-design-system/react-native";
455
+ import { useDialog as useDialog2 } from "@toss/tds-react-native";
382
456
  import { useCallback as useCallback2 } from "react";
383
457
 
384
458
  // src/utils/market.ts
@@ -391,7 +465,7 @@ var getMarketLink = () => {
391
465
 
392
466
  // src/hooks/useAppUpdateDialog.tsx
393
467
  function useAppUpdateDialog() {
394
- const { openConfirm } = useDialog();
468
+ const { openConfirm } = useDialog2();
395
469
  const logging = useAppUpdateDialogLogging();
396
470
  const openAppUpdateDialog = useCallback2(
397
471
  async ({
@@ -478,22 +552,30 @@ function ensureValue(value, name) {
478
552
  }
479
553
 
480
554
  // src/core/hooks/useMoreButtonBottomSheet/index.tsx
481
- import { Fragment as Fragment3, jsx as jsx3 } from "react/jsx-runtime";
555
+ import { Fragment as Fragment3, jsx as jsx4, jsxs } from "react/jsx-runtime";
482
556
  var APP_BRIDGE_METHOD_NAME = "getMiniAppsSupportContact";
557
+ var MIN_VERSION = {
558
+ BOTTOM_SHEET: {
559
+ android: "5.226.0",
560
+ ios: "5.226.0"
561
+ },
562
+ SHARE_LIST_MENU: {
563
+ android: "5.230.0",
564
+ ios: "5.230.0"
565
+ }
566
+ };
483
567
  function useMoreButtonBottomSheet() {
484
568
  const globals = getAppsInTossGlobals();
485
- const adaptive = useAdaptive();
569
+ const adaptive = useAdaptive2();
486
570
  const [itemList, setItemList] = useState([]);
487
571
  const appUpdateDialog = useAppUpdateDialog();
488
572
  const logging = useMoreButtonBottomSheetLogging();
489
573
  const overlay = useOverlay();
490
574
  const title = ensureValue(globals.brandDisplayName, "displayName");
491
- const isSupported = isMinVersionSupported({
492
- android: "5.226.0",
493
- ios: "5.226.0"
494
- });
575
+ const isBottomSheetSupported = isMinVersionSupported(MIN_VERSION.BOTTOM_SHEET);
576
+ const isShareListMenuSupported = isMinVersionSupported(MIN_VERSION.SHARE_LIST_MENU);
495
577
  useEffect6(() => {
496
- if (!isSupported) {
578
+ if (!isBottomSheetSupported) {
497
579
  return;
498
580
  }
499
581
  INTERNAL__appBridgeHandler.invokeAppBridgeMethod(
@@ -504,10 +586,10 @@ function useMoreButtonBottomSheet() {
504
586
  onError: (error) => console.error("\uBA54\uB274 \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uB294 \uB370 \uC2E4\uD328\uD588\uC5B4\uC694:", error)
505
587
  }
506
588
  );
507
- }, [isSupported]);
589
+ }, [isBottomSheetSupported]);
508
590
  const onClickHandler = async () => {
509
591
  logging.open();
510
- if (!isSupported) {
592
+ if (!isBottomSheetSupported) {
511
593
  await appUpdateDialog.open({
512
594
  title: `\uC774 \uAE30\uB2A5\uC744 \uC4F0\uB824\uBA74 \uC571 \uC5C5\uB370\uC774\uD2B8\uAC00 \uD544\uC694\uD574\uC694`,
513
595
  description: `\uBB38\uC758, \uAD8C\uD55C \uC124\uC815, \uC2E0\uACE0 \uB4F1 \uAE30\uB2A5\uC744 \uC4F8 \uC218 \uC788\uC5B4\uC694`
@@ -519,17 +601,17 @@ function useMoreButtonBottomSheet() {
519
601
  logging.close();
520
602
  close();
521
603
  };
522
- return /* @__PURE__ */ jsx3(BottomSheetImpressionArea, { children: /* @__PURE__ */ jsx3(
604
+ return /* @__PURE__ */ jsx4(BottomSheetImpressionArea, { children: /* @__PURE__ */ jsx4(
523
605
  BottomSheet.Root,
524
606
  {
525
- header: /* @__PURE__ */ jsx3(
607
+ header: /* @__PURE__ */ jsx4(
526
608
  ListHeader,
527
609
  {
528
- title: /* @__PURE__ */ jsx3(ListHeader.TitleParagraph, { color: adaptive.grey800, fontWeight: "bold", typography: "t5", children: title })
610
+ title: /* @__PURE__ */ jsx4(ListHeader.TitleParagraph, { color: adaptive.grey800, fontWeight: "bold", typography: "t5", children: title })
529
611
  }
530
612
  ),
531
613
  open: isOpen,
532
- cta: /* @__PURE__ */ jsx3(
614
+ cta: /* @__PURE__ */ jsx4(
533
615
  BottomSheet.CTA,
534
616
  {
535
617
  size: "large",
@@ -543,35 +625,38 @@ function useMoreButtonBottomSheet() {
543
625
  ),
544
626
  onClose: handleClose,
545
627
  onExited: exit,
546
- children: /* @__PURE__ */ jsx3(List, { rowSeparator: "none", children: itemList.map((item) => {
547
- return /* @__PURE__ */ jsx3(
548
- ListRow,
549
- {
550
- left: /* @__PURE__ */ jsx3(
551
- ListRow.Icon,
552
- {
553
- color: globals.brandPrimaryColor,
554
- source: { uri: item.contactIconUrl },
555
- type: "background"
556
- }
557
- ),
558
- contents: /* @__PURE__ */ jsx3(
559
- ListRow.Texts,
560
- {
561
- type: "1RowTypeA",
562
- top: item.contactItemName,
563
- topProps: { color: adaptive.grey700 }
628
+ children: /* @__PURE__ */ jsxs(List, { rowSeparator: "none", children: [
629
+ itemList.map((item) => {
630
+ return /* @__PURE__ */ jsx4(
631
+ ListRow2,
632
+ {
633
+ left: /* @__PURE__ */ jsx4(
634
+ ListRow2.Icon,
635
+ {
636
+ color: globals.brandPrimaryColor,
637
+ source: { uri: item.contactIconUrl },
638
+ type: "background"
639
+ }
640
+ ),
641
+ contents: /* @__PURE__ */ jsx4(
642
+ ListRow2.Texts,
643
+ {
644
+ type: "1RowTypeA",
645
+ top: item.contactItemName,
646
+ topProps: { color: adaptive.grey700 }
647
+ }
648
+ ),
649
+ verticalPadding: "extraSmall",
650
+ onPress: () => {
651
+ logging.menuClick({ title: item.contactItemName });
652
+ openURL3(item.contactUri);
564
653
  }
565
- ),
566
- verticalPadding: "extraSmall",
567
- onPress: () => {
568
- logging.menuClick({ title: item.contactItemName });
569
- openURL3(item.contactUri);
570
- }
571
- },
572
- item.contactItemName
573
- );
574
- }) })
654
+ },
655
+ item.contactItemName
656
+ );
657
+ }),
658
+ isShareListMenuSupported && /* @__PURE__ */ jsx4(AppShareListMenu, {})
659
+ ] })
575
660
  }
576
661
  ) });
577
662
  });
@@ -583,7 +668,7 @@ function BottomSheetImpressionArea({ children }) {
583
668
  useEffect6(() => {
584
669
  logging.show();
585
670
  }, [logging]);
586
- return /* @__PURE__ */ jsx3(Fragment3, { children });
671
+ return /* @__PURE__ */ jsx4(Fragment3, { children });
587
672
  }
588
673
 
589
674
  // src/core/utils/safeParseNavigationBar.ts
@@ -599,12 +684,12 @@ function safeParseNavigationBar(navigationBar) {
599
684
  }
600
685
 
601
686
  // src/components/NavigationBar/RNNavigationBar.tsx
602
- import { jsx as jsx4 } from "react/jsx-runtime";
687
+ import { jsx as jsx5 } from "react/jsx-runtime";
603
688
  function RNNavigationBar() {
604
689
  const globals = getAppsInTossGlobals();
605
690
  const { captureExitLog } = useCaptureExitLog();
606
691
  const logging = useNavigationBarLogging();
607
- const { openConfirm } = useDialog2();
692
+ const { openConfirm } = useDialog3();
608
693
  const { open: openMoreButtonBottomSheet } = useMoreButtonBottomSheet();
609
694
  const parsedNavigationBar = globals.navigationBar != null ? safeParseNavigationBar(globals.navigationBar) : null;
610
695
  const withHomeButton = parsedNavigationBar?.withHomeButton ?? false;
@@ -649,7 +734,7 @@ function RNNavigationBar() {
649
734
  BackHandler.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
650
735
  };
651
736
  }, [handleBack]);
652
- return /* @__PURE__ */ jsx4(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx4(
737
+ return /* @__PURE__ */ jsx5(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx5(
653
738
  TopNavigation,
654
739
  {
655
740
  title: globals.brandDisplayName,
@@ -664,7 +749,7 @@ function RNNavigationBar() {
664
749
  icon: initialAccessoryButton.icon,
665
750
  id: initialAccessoryButton.id
666
751
  } : void 0,
667
- children: /* @__PURE__ */ jsx4(NavigationLeft, { visible: withBackButton, children: /* @__PURE__ */ jsx4(NavigationBackButton, { onPress: handleBack, canGoBack: false }) })
752
+ children: /* @__PURE__ */ jsx5(NavigationLeft, { visible: withBackButton, children: /* @__PURE__ */ jsx5(NavigationBackButton, { onPress: handleBack, canGoBack: false }) })
668
753
  }
669
754
  ) });
670
755
  }
@@ -682,28 +767,28 @@ function useBackOrCloseNavigation() {
682
767
  }
683
768
 
684
769
  // src/core/registerApp.tsx
685
- import { Fragment as Fragment4, jsx as jsx5, jsxs } from "react/jsx-runtime";
770
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
686
771
  function AppsInTossContainer(Container, { children, ...initialProps }) {
687
772
  if (!isMinVersionSupported2({
688
773
  android: "5.220.0",
689
774
  ios: "5.221.0"
690
775
  })) {
691
- return /* @__PURE__ */ jsxs(Fragment4, { children: [
692
- /* @__PURE__ */ jsx5(AppEvent.Entry, {}),
693
- /* @__PURE__ */ jsx5(AppEvent.System, { ...initialProps }),
694
- /* @__PURE__ */ jsx5(AppUpdate, {})
776
+ return /* @__PURE__ */ jsxs2(Fragment4, { children: [
777
+ /* @__PURE__ */ jsx6(AppEvent.Entry, {}),
778
+ /* @__PURE__ */ jsx6(AppEvent.System, { ...initialProps }),
779
+ /* @__PURE__ */ jsx6(AppUpdate, {})
695
780
  ] });
696
781
  }
697
- return /* @__PURE__ */ jsxs(Fragment4, { children: [
698
- /* @__PURE__ */ jsx5(AppEvent.StayTime, {}),
699
- /* @__PURE__ */ jsx5(AppEvent.Entry, {}),
700
- /* @__PURE__ */ jsx5(AppEvent.System, { ...initialProps }),
701
- /* @__PURE__ */ jsx5(Container, { ...initialProps, children: /* @__PURE__ */ jsx5(TDSProvider, { colorPreference: "light", token: { color: { primary: getAppsInTossGlobals().brandPrimaryColor } }, children: /* @__PURE__ */ jsx5(TDSContainer, { ...initialProps, children }) }) })
782
+ return /* @__PURE__ */ jsxs2(Fragment4, { children: [
783
+ /* @__PURE__ */ jsx6(AppEvent.StayTime, {}),
784
+ /* @__PURE__ */ jsx6(AppEvent.Entry, {}),
785
+ /* @__PURE__ */ jsx6(AppEvent.System, { ...initialProps }),
786
+ /* @__PURE__ */ jsx6(Container, { ...initialProps, children: /* @__PURE__ */ jsx6(TDSProvider, { colorPreference: "light", token: { color: { primary: getAppsInTossGlobals().brandPrimaryColor } }, children: /* @__PURE__ */ jsx6(TDSContainer, { ...initialProps, children }) }) })
702
787
  ] });
703
788
  }
704
789
  function TDSContainer({ children }) {
705
790
  useAppsInTossBridge();
706
- return /* @__PURE__ */ jsx5(Fragment4, { children });
791
+ return /* @__PURE__ */ jsx6(Fragment4, { children });
707
792
  }
708
793
  function registerApp(container, { context, analytics }) {
709
794
  const appName = getAppName();
@@ -730,8 +815,8 @@ function registerApp(container, { context, analytics }) {
730
815
  }
731
816
  function AppsInTossScreenContainer({ children }) {
732
817
  const isReactNativeService = getAppsInTossGlobals().webViewType == null;
733
- return /* @__PURE__ */ jsxs(Analytics.Screen, { children: [
734
- isReactNativeService && /* @__PURE__ */ jsx5(RNNavigationBar, {}),
818
+ return /* @__PURE__ */ jsxs2(Analytics.Screen, { children: [
819
+ isReactNativeService && /* @__PURE__ */ jsx6(RNNavigationBar, {}),
735
820
  children
736
821
  ] });
737
822
  }
@@ -750,29 +835,36 @@ var AppsInToss = {
750
835
  };
751
836
 
752
837
  // src/components/WebView.tsx
753
- import { GoogleAdMob, IAP, Storage, AppsInTossModule, appsInTossEvent as appsInTossEvent5 } from "@apps-in-toss/native-modules";
838
+ import {
839
+ GoogleAdMob,
840
+ IAP,
841
+ Storage,
842
+ AppsInTossModule,
843
+ appsInTossEvent as appsInTossEvent3,
844
+ iapCreateOneTimePurchaseOrder,
845
+ processProductGrant,
846
+ requestOneTimePurchase
847
+ } from "@apps-in-toss/native-modules";
754
848
  import * as appsInTossAsyncBridges from "@apps-in-toss/native-modules/async-bridges";
755
849
  import * as appsInTossConstantBridges from "@apps-in-toss/native-modules/constant-bridges";
756
850
  import * as appsInTossEventBridges from "@apps-in-toss/native-modules/event-bridges";
757
- import { getSchemeUri as getSchemeUri5, useGraniteEvent } from "@granite-js/react-native";
758
- import * as graniteAsyncBridges from "@granite-js/react-native/async-bridges";
759
- import * as graniteConstantBridges from "@granite-js/react-native/constant-bridges";
760
- import { ExternalWebViewScreen, tdsEvent } from "@toss-design-system/react-native";
761
- import { useSafeAreaBottom, useSafeAreaTop as useSafeAreaTop2, useTopNavigation } from "@toss-design-system/react-native/private";
762
- import { useCallback as useCallback9, useMemo as useMemo3, useState as useState5 } from "react";
763
- import { Platform as Platform4 } from "react-native";
851
+ import { getSchemeUri as getSchemeUri6 } from "@granite-js/react-native";
852
+ import { ExternalWebViewScreen, tdsEvent } from "@toss/tds-react-native";
853
+ import { useSafeAreaBottom, useSafeAreaTop as useSafeAreaTop2, useTopNavigation } from "@toss/tds-react-native/private";
854
+ import { useEffect as useEffect11, useMemo as useMemo5, useRef as useRef6, useState as useState5 } from "react";
855
+ import { BackHandler as BackHandler2, Platform as Platform4 } from "react-native";
764
856
 
765
857
  // src/components/GameWebView.tsx
766
- import { setIosSwipeGestureEnabled as setIosSwipeGestureEnabled2, appsInTossEvent as appsInTossEvent2, getOperationalEnvironment } from "@apps-in-toss/native-modules";
858
+ import { setIosSwipeGestureEnabled as setIosSwipeGestureEnabled2, appsInTossEvent as appsInTossEvent2, getOperationalEnvironment as getOperationalEnvironment2 } from "@apps-in-toss/native-modules";
767
859
  import {
768
860
  WebView as PlainWebView
769
861
  } from "@granite-js/native/react-native-webview";
770
- import { forwardRef, useEffect as useEffect10, useState as useState3 } from "react";
862
+ import { forwardRef, useEffect as useEffect9, useState as useState3 } from "react";
771
863
  import { Platform as Platform3 } from "react-native";
772
864
 
773
865
  // src/components/GameProfile.tsx
774
866
  import { getGameCenterGameProfile as getGameCenterGameProfile2, isMinVersionSupported as isMinVersionSupported3 } from "@apps-in-toss/native-modules";
775
- import { Loader } from "@toss-design-system/react-native";
867
+ import { Loader } from "@toss/tds-react-native";
776
868
  import { useEffect as useEffect8 } from "react";
777
869
  import { Pressable, View } from "react-native";
778
870
 
@@ -786,20 +878,20 @@ var GAME_CENTER_MIN_VERSION = {
786
878
  // src/hooks/useGameCenterProfile.ts
787
879
  import { getGameCenterGameProfile } from "@apps-in-toss/native-modules";
788
880
  import { closeView as closeView2, openURL as openURL5 } from "@granite-js/react-native";
789
- import { useDialog as useDialog3 } from "@toss-design-system/react-native";
881
+ import { useDialog as useDialog4 } from "@toss/tds-react-native";
790
882
  import { josa as josa2 } from "es-hangul";
791
883
  import { useCallback as useCallback4, useRef as useRef3, useState as useState2 } from "react";
792
884
 
793
885
  // src/components/GameProfileToast.tsx
794
- import { Asset, Toast } from "@toss-design-system/react-native";
795
- import { AdaptiveColorProvider, ColorPreferenceProvider, useOverlay as useOverlay2 } from "@toss-design-system/react-native/private";
796
- import { jsx as jsx6 } from "react/jsx-runtime";
886
+ import { Asset, Toast } from "@toss/tds-react-native";
887
+ import { AdaptiveColorProvider, ColorPreferenceProvider, useOverlay as useOverlay2 } from "@toss/tds-react-native/private";
888
+ import { jsx as jsx7 } from "react/jsx-runtime";
797
889
  var useGameProfileToast = () => {
798
890
  const overlay = useOverlay2();
799
891
  const openGameProfileToast = (nickname, profileImageUri) => {
800
892
  return new Promise((resolve) => {
801
893
  overlay.open(({ isOpen, close, exit }) => {
802
- return /* @__PURE__ */ jsx6(ColorPreferenceProvider, { colorPreference: "dark", children: /* @__PURE__ */ jsx6(AdaptiveColorProvider, { children: /* @__PURE__ */ jsx6(
894
+ return /* @__PURE__ */ jsx7(ColorPreferenceProvider, { colorPreference: "dark", children: /* @__PURE__ */ jsx7(AdaptiveColorProvider, { children: /* @__PURE__ */ jsx7(
803
895
  Toast,
804
896
  {
805
897
  open: isOpen,
@@ -810,7 +902,7 @@ var useGameProfileToast = () => {
810
902
  onExited: exit,
811
903
  position: "top",
812
904
  text: `${nickname}\uB2D8 \uBC18\uAC00\uC6CC\uC694!`,
813
- icon: /* @__PURE__ */ jsx6(
905
+ icon: /* @__PURE__ */ jsx7(
814
906
  Asset.Image,
815
907
  {
816
908
  style: { borderRadius: 64, overflow: "hidden" },
@@ -880,7 +972,7 @@ var useGameCenterProfile = (isReadyForProfileUI) => {
880
972
  const canShowBottomSheetOrToast = !isProfileDataLoading && isReadyForProfileUI;
881
973
  const [isWebviewLoading, setIsWebviewLoading] = useState2(false);
882
974
  const isCompletedProfileFlow = useRef3(false);
883
- const { openAlert, openConfirm } = useDialog3();
975
+ const { openAlert, openConfirm } = useDialog4();
884
976
  const { openGameProfileToast } = useGameProfileToast();
885
977
  const openErrorAlert = useCallback4(async () => {
886
978
  await openAlert({
@@ -965,7 +1057,7 @@ var Z_INDEX = {
965
1057
  };
966
1058
 
967
1059
  // src/components/GameProfile.tsx
968
- import { Fragment as Fragment5, jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
1060
+ import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
969
1061
  var GameProfile = ({ children, isReadyForProfileUI }) => {
970
1062
  const {
971
1063
  profileData,
@@ -1025,9 +1117,9 @@ var GameProfile = ({ children, isReadyForProfileUI }) => {
1025
1117
  updateAppToSupportedMinVersion
1026
1118
  ]);
1027
1119
  if (!isMinVersionSupported3(GAME_CENTER_MIN_VERSION)) {
1028
- return /* @__PURE__ */ jsxs2(Fragment5, { children: [
1029
- /* @__PURE__ */ jsx7(View, { style: { flex: 1, position: "relative" }, children }),
1030
- /* @__PURE__ */ jsx7(
1120
+ return /* @__PURE__ */ jsxs3(Fragment5, { children: [
1121
+ /* @__PURE__ */ jsx8(View, { style: { flex: 1, position: "relative" }, children }),
1122
+ /* @__PURE__ */ jsx8(
1031
1123
  Pressable,
1032
1124
  {
1033
1125
  style: {
@@ -1041,9 +1133,9 @@ var GameProfile = ({ children, isReadyForProfileUI }) => {
1041
1133
  ] });
1042
1134
  }
1043
1135
  if (shouldShowLoadingOverlay || isProfileDataRefetching) {
1044
- return /* @__PURE__ */ jsxs2(Fragment5, { children: [
1045
- /* @__PURE__ */ jsx7(View, { style: { flex: 1, position: "relative" }, children }),
1046
- /* @__PURE__ */ jsx7(
1136
+ return /* @__PURE__ */ jsxs3(Fragment5, { children: [
1137
+ /* @__PURE__ */ jsx8(View, { style: { flex: 1, position: "relative" }, children }),
1138
+ /* @__PURE__ */ jsx8(
1047
1139
  View,
1048
1140
  {
1049
1141
  style: {
@@ -1052,15 +1144,15 @@ var GameProfile = ({ children, isReadyForProfileUI }) => {
1052
1144
  alignItems: "center",
1053
1145
  backgroundColor: "rgba(0, 0, 0, 0.2)"
1054
1146
  },
1055
- children: /* @__PURE__ */ jsx7(Loader, { size: "large", type: "light" })
1147
+ children: /* @__PURE__ */ jsx8(Loader, { size: "large", type: "light" })
1056
1148
  }
1057
1149
  )
1058
1150
  ] });
1059
1151
  }
1060
1152
  if (shouldShowProfileNotFoundOverlay) {
1061
- return /* @__PURE__ */ jsxs2(Fragment5, { children: [
1062
- /* @__PURE__ */ jsx7(View, { style: { flex: 1, position: "relative" }, children }),
1063
- shouldShowProfileNotFoundOverlay && /* @__PURE__ */ jsx7(
1153
+ return /* @__PURE__ */ jsxs3(Fragment5, { children: [
1154
+ /* @__PURE__ */ jsx8(View, { style: { flex: 1, position: "relative" }, children }),
1155
+ shouldShowProfileNotFoundOverlay && /* @__PURE__ */ jsx8(
1064
1156
  Pressable,
1065
1157
  {
1066
1158
  style: {
@@ -1073,7 +1165,7 @@ var GameProfile = ({ children, isReadyForProfileUI }) => {
1073
1165
  )
1074
1166
  ] });
1075
1167
  }
1076
- return /* @__PURE__ */ jsx7(Fragment5, { children: /* @__PURE__ */ jsx7(View, { style: { flex: 1, position: "relative" }, children }) });
1168
+ return /* @__PURE__ */ jsx8(Fragment5, { children: /* @__PURE__ */ jsx8(View, { style: { flex: 1, position: "relative" }, children }) });
1077
1169
  };
1078
1170
  var overlayStyle = {
1079
1171
  position: "absolute",
@@ -1086,15 +1178,15 @@ var overlayStyle = {
1086
1178
 
1087
1179
  // src/components/NavigationBar/GameWebviewNavigationBar.tsx
1088
1180
  import { closeView as closeView3 } from "@granite-js/react-native";
1089
- import { PageNavbar, useDialog as useDialog4 } from "@toss-design-system/react-native";
1090
- import { NavigationRightContent, useSafeAreaTop } from "@toss-design-system/react-native/private";
1181
+ import { PageNavbar, useDialog as useDialog5 } from "@toss/tds-react-native";
1182
+ import { NavigationRightContent, useSafeAreaTop } from "@toss/tds-react-native/private";
1091
1183
  import { josa as josa3 } from "es-hangul";
1092
- import { useCallback as useCallback5, useEffect as useEffect9 } from "react";
1093
- import { BackHandler as BackHandler2, Platform as Platform2, View as View2 } from "react-native";
1094
- import { Fragment as Fragment6, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
1184
+ import { useCallback as useCallback5 } from "react";
1185
+ import { Platform as Platform2, View as View2 } from "react-native";
1186
+ import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1095
1187
  function GameWebviewNavigationBar() {
1096
1188
  const safeAreaTop = useSafeAreaTop();
1097
- const { openConfirm } = useDialog4();
1189
+ const { openConfirm } = useDialog5();
1098
1190
  const { captureExitLog } = useCaptureExitLog();
1099
1191
  const global2 = getAppsInTossGlobals();
1100
1192
  const logging = useNavigationBarLogging();
@@ -1102,6 +1194,7 @@ function GameWebviewNavigationBar() {
1102
1194
  const parsedNavigationBar = global2.navigationBar != null ? safeParseNavigationBar(global2.navigationBar) : null;
1103
1195
  const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
1104
1196
  const handleGameWebviewClose = useCallback5(async () => {
1197
+ logging.closeButtonClick();
1105
1198
  const isConfirmed = await openConfirm({
1106
1199
  title: `${josa3(global2.brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
1107
1200
  leftButton: "\uCDE8\uC18C",
@@ -1115,17 +1208,9 @@ function GameWebviewNavigationBar() {
1115
1208
  closeView3();
1116
1209
  }
1117
1210
  }, [captureExitLog, global2.brandDisplayName, logging, openConfirm]);
1118
- useEffect9(() => {
1119
- const handleAndroidBackEvent = () => {
1120
- handleGameWebviewClose();
1121
- return true;
1122
- };
1123
- BackHandler2.addEventListener("hardwareBackPress", handleAndroidBackEvent);
1124
- return () => BackHandler2.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
1125
- }, [handleGameWebviewClose]);
1126
- return /* @__PURE__ */ jsxs3(Fragment6, { children: [
1127
- /* @__PURE__ */ jsx8(PageNavbar, { preference: { type: "none" } }),
1128
- /* @__PURE__ */ jsx8(
1211
+ return /* @__PURE__ */ jsxs4(Fragment6, { children: [
1212
+ /* @__PURE__ */ jsx9(PageNavbar, { preference: { type: "none" } }),
1213
+ /* @__PURE__ */ jsx9(
1129
1214
  View2,
1130
1215
  {
1131
1216
  style: {
@@ -1141,13 +1226,12 @@ function GameWebviewNavigationBar() {
1141
1226
  paddingRight: 10
1142
1227
  },
1143
1228
  pointerEvents: "box-none",
1144
- children: /* @__PURE__ */ jsx8(
1229
+ children: /* @__PURE__ */ jsx9(
1145
1230
  NavigationRightContent,
1146
1231
  {
1147
1232
  fixedRightButton: initialAccessoryButton,
1148
1233
  onPressDots: openMoreButtonBottomSheet,
1149
1234
  onPressClose: () => {
1150
- logging.closeButtonClick();
1151
1235
  handleGameWebviewClose();
1152
1236
  },
1153
1237
  theme: "dark"
@@ -1159,10 +1243,10 @@ function GameWebviewNavigationBar() {
1159
1243
  }
1160
1244
 
1161
1245
  // src/components/GameWebView.tsx
1162
- import { Fragment as Fragment7, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1246
+ import { Fragment as Fragment7, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
1163
1247
  var GameWebView = forwardRef(function GameWebView2(props, ref) {
1164
1248
  const [isEntryMessageExited, setIsEntryMessageExited] = useState3(false);
1165
- useEffect10(() => {
1249
+ useEffect9(() => {
1166
1250
  if (Platform3.OS === "ios") {
1167
1251
  setIosSwipeGestureEnabled2({ isEnabled: false });
1168
1252
  return () => {
@@ -1171,49 +1255,42 @@ var GameWebView = forwardRef(function GameWebView2(props, ref) {
1171
1255
  }
1172
1256
  return;
1173
1257
  }, []);
1174
- useEffect10(() => {
1258
+ useEffect9(() => {
1175
1259
  appsInTossEvent2.addEventListener("entryMessageExited", {
1176
1260
  onEvent: () => {
1177
1261
  setIsEntryMessageExited(true);
1178
1262
  }
1179
1263
  });
1180
1264
  }, []);
1181
- return /* @__PURE__ */ jsxs4(Fragment7, { children: [
1182
- /* @__PURE__ */ jsx9(GameWebviewNavigationBar, {}),
1183
- getOperationalEnvironment() === "toss" ? /* @__PURE__ */ jsx9(GameProfile, { isReadyForProfileUI: isEntryMessageExited, children: /* @__PURE__ */ jsx9(PlainWebView, { ref, ...props }) }) : /* @__PURE__ */ jsx9(PlainWebView, { ref, ...props })
1265
+ return /* @__PURE__ */ jsxs5(Fragment7, { children: [
1266
+ /* @__PURE__ */ jsx10(GameWebviewNavigationBar, {}),
1267
+ getOperationalEnvironment2() === "toss" ? /* @__PURE__ */ jsx10(GameProfile, { isReadyForProfileUI: isEntryMessageExited, children: /* @__PURE__ */ jsx10(PlainWebView, { ref, ...props }) }) : /* @__PURE__ */ jsx10(PlainWebView, { ref, ...props })
1184
1268
  ] });
1185
1269
  });
1186
1270
 
1187
1271
  // src/components/PartnerWebView.tsx
1188
- import { appsInTossEvent as appsInTossEvent4, closeView as closeView5 } from "@apps-in-toss/native-modules";
1189
1272
  import {
1190
1273
  WebView as PlainWebView2
1191
1274
  } from "@granite-js/native/react-native-webview";
1192
- import { forwardRef as forwardRef2, useCallback as useCallback7, useEffect as useEffect11, useRef as useRef4 } from "react";
1193
- import { BackHandler as BackHandler3 } from "react-native";
1275
+ import { forwardRef as forwardRef2 } from "react";
1194
1276
 
1195
1277
  // src/components/NavigationBar/PartnerWebviewNavigationBar.tsx
1196
- import { appsInTossEvent as appsInTossEvent3 } from "@apps-in-toss/native-modules";
1197
1278
  import { closeView as closeView4 } from "@granite-js/react-native";
1198
- import { useDialog as useDialog5 } from "@toss-design-system/react-native";
1199
- import { NavigationBackButton as NavigationBackButton2, NavigationLeft as NavigationLeft2, TopNavigation as TopNavigation2 } from "@toss-design-system/react-native/private";
1279
+ import { useDialog as useDialog6 } from "@toss/tds-react-native";
1280
+ import { NavigationBackButton as NavigationBackButton2, NavigationLeft as NavigationLeft2, TopNavigation as TopNavigation2 } from "@toss/tds-react-native/private";
1200
1281
  import { josa as josa4 } from "es-hangul";
1201
1282
  import { useCallback as useCallback6 } from "react";
1202
- import { jsx as jsx10 } from "react/jsx-runtime";
1203
- function PartnerWebviewNavigationBar({ handleBackEvent }) {
1283
+ import { jsx as jsx11 } from "react/jsx-runtime";
1284
+ function PartnerWebviewNavigationBar({ onBackButtonClick, onHomeButtonClick }) {
1204
1285
  const globals = getAppsInTossGlobals();
1205
1286
  const { captureExitLog } = useCaptureExitLog();
1206
1287
  const logging = useNavigationBarLogging();
1207
- const { openConfirm } = useDialog5();
1288
+ const { openConfirm } = useDialog6();
1208
1289
  const { open: openMoreButtonBottomSheet } = useMoreButtonBottomSheet();
1209
1290
  const parsedNavigationBar = globals.navigationBar != null ? safeParseNavigationBar(globals.navigationBar) : null;
1210
1291
  const withHomeButton = parsedNavigationBar?.withHomeButton ?? false;
1211
1292
  const withBackButton = parsedNavigationBar?.withBackButton ?? true;
1212
1293
  const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
1213
- const handlePressTitle = useCallback6(() => {
1214
- logging.homeButtonClick();
1215
- appsInTossEvent3.emit("homeIconButtonClickEvent", void 0);
1216
- }, [logging]);
1217
1294
  const handleClose = useCallback6(async () => {
1218
1295
  logging.closeButtonClick();
1219
1296
  const isConfirmed = await openConfirm({
@@ -1229,86 +1306,41 @@ function PartnerWebviewNavigationBar({ handleBackEvent }) {
1229
1306
  closeView4();
1230
1307
  }
1231
1308
  }, [captureExitLog, globals.brandDisplayName, logging, openConfirm]);
1232
- return /* @__PURE__ */ jsx10(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx10(
1309
+ return /* @__PURE__ */ jsx11(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx11(
1233
1310
  TopNavigation2,
1234
1311
  {
1235
1312
  title: globals.brandDisplayName,
1236
1313
  icon: toIcon(globals.brandIcon),
1237
1314
  onPressDots: openMoreButtonBottomSheet,
1238
1315
  contentVisible: true,
1239
- onPressTitle: withHomeButton ? handlePressTitle : void 0,
1316
+ onPressTitle: withHomeButton ? onHomeButtonClick : void 0,
1240
1317
  onPressClose: handleClose,
1241
1318
  withHome: withHomeButton,
1242
1319
  fixedRightButton: initialAccessoryButton,
1243
- children: /* @__PURE__ */ jsx10(NavigationLeft2, { visible: withBackButton, children: /* @__PURE__ */ jsx10(NavigationBackButton2, { onPress: handleBackEvent, canGoBack: false }) })
1320
+ children: /* @__PURE__ */ jsx11(NavigationLeft2, { visible: withBackButton, children: /* @__PURE__ */ jsx11(NavigationBackButton2, { onPress: onBackButtonClick, canGoBack: false }) })
1244
1321
  }
1245
1322
  ) });
1246
1323
  }
1247
1324
 
1248
- // src/core/utils/mergeRefs.ts
1249
- function mergeRefs(...refs) {
1250
- return (value) => {
1251
- refs.forEach((ref) => {
1252
- if (typeof ref === "function") {
1253
- ref(value);
1254
- } else if (ref != null) {
1255
- ref.current = value;
1256
- }
1257
- });
1258
- };
1259
- }
1260
-
1261
1325
  // src/components/PartnerWebView.tsx
1262
- import { Fragment as Fragment8, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
1263
- var PartnerWebView = forwardRef2(function PartnerWebViewScreen({ canHistoryGoBack, ...webViewProps }, ref) {
1264
- const webViewRef = useRef4(null);
1265
- const refs = mergeRefs(ref, webViewRef);
1266
- const { captureExitLog } = useCaptureExitLog();
1267
- const handleBackEvent = useCallback7(() => {
1268
- if (canHistoryGoBack) {
1269
- webViewRef.current?.goBack();
1270
- } else {
1271
- captureExitLog(Date.now());
1272
- closeView5();
1273
- }
1274
- }, [canHistoryGoBack, captureExitLog]);
1275
- useEffect11(() => {
1276
- const handleAndroidBackEvent = () => {
1277
- if (canHistoryGoBack) {
1278
- webViewRef.current?.goBack();
1279
- return true;
1280
- } else {
1281
- captureExitLog(Date.now());
1282
- return false;
1283
- }
1284
- };
1285
- BackHandler3.addEventListener("hardwareBackPress", handleAndroidBackEvent);
1286
- return () => BackHandler3.removeEventListener("hardwareBackPress", handleAndroidBackEvent);
1287
- }, [canHistoryGoBack, captureExitLog]);
1288
- useEffect11(() => {
1289
- return appsInTossEvent4.addEventListener("homeIconButtonClickEvent", {
1290
- onEvent: () => {
1291
- webViewRef.current?.injectJavaScript(`
1292
- (function() {
1293
- window.history.replaceState(null, '', '/');
1294
- true;
1295
- })();
1296
- `);
1297
- }
1298
- });
1299
- }, [webViewRef]);
1300
- return /* @__PURE__ */ jsxs5(Fragment8, { children: [
1301
- /* @__PURE__ */ jsx11(PartnerWebviewNavigationBar, { handleBackEvent }),
1302
- /* @__PURE__ */ jsx11(PlainWebView2, { ref: refs, ...webViewProps, style: { flex: 1 } })
1326
+ import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
1327
+ var PartnerWebView = forwardRef2(function PartnerWebViewScreen({ onBackButtonClick, onHomeButtonClick, ...webViewProps }, ref) {
1328
+ return /* @__PURE__ */ jsxs6(Fragment8, { children: [
1329
+ /* @__PURE__ */ jsx12(PartnerWebviewNavigationBar, { onBackButtonClick, onHomeButtonClick }),
1330
+ /* @__PURE__ */ jsx12(PlainWebView2, { ref, ...webViewProps, style: { flex: 1 } })
1303
1331
  ] });
1304
1332
  });
1305
1333
 
1306
1334
  // src/bridge-handler/useBridgeHandler.tsx
1307
- import { useCallback as useCallback8, useMemo as useMemo2, useRef as useRef5 } from "react";
1335
+ import { useCallback as useCallback7, useMemo as useMemo2, useRef as useRef4 } from "react";
1308
1336
  function serializeError(error) {
1309
1337
  return JSON.stringify(error, (_, value) => {
1310
1338
  if (value instanceof Error) {
1311
1339
  return {
1340
+ ...Object.entries(value).reduce((acc, [key, value2]) => {
1341
+ acc[key] = value2;
1342
+ return acc;
1343
+ }, {}),
1312
1344
  name: value.name,
1313
1345
  message: value.message,
1314
1346
  stack: value.stack,
@@ -1353,7 +1385,7 @@ function useBridgeHandler({
1353
1385
  eventListenerMap,
1354
1386
  injectedJavaScript: originalInjectedJavaScript
1355
1387
  }) {
1356
- const ref = useRef5(null);
1388
+ const ref = useRef4(null);
1357
1389
  const injectedJavaScript = useMemo2(
1358
1390
  () => [
1359
1391
  `window.__CONSTANT_HANDLER_MAP = ${JSON.stringify(
@@ -1381,7 +1413,7 @@ function useBridgeHandler({
1381
1413
  window.__GRANITE_NATIVE_EMITTER.emit('${functionName}/onError/${eventId}', ${serializedError});
1382
1414
  `);
1383
1415
  };
1384
- const $onMessage = useCallback8(
1416
+ const $onMessage = useCallback7(
1385
1417
  async (e) => {
1386
1418
  onMessage?.(e);
1387
1419
  const data = JSON.parse(e.nativeEvent.data);
@@ -1431,6 +1463,155 @@ function useBridgeHandler({
1431
1463
  };
1432
1464
  }
1433
1465
 
1466
+ // src/core/hooks/useWebBackHandler.tsx
1467
+ import { closeView as closeView5, useBackEventState } from "@granite-js/react-native";
1468
+ import { useDialog as useDialog7 } from "@toss/tds-react-native";
1469
+ import { josa as josa5 } from "es-hangul";
1470
+ import { useCallback as useCallback9, useMemo as useMemo4 } from "react";
1471
+
1472
+ // src/hooks/useWebviewHistoryStack.tsx
1473
+ import { useCallback as useCallback8, useMemo as useMemo3, useReducer } from "react";
1474
+ var INITIAL_STATE = { stack: [], index: -1 };
1475
+ function reducer(state, action) {
1476
+ switch (action.type) {
1477
+ case "NAVIGATION_CHANGE": {
1478
+ const { url, canGoForward } = action;
1479
+ if (state.stack.length === 0) {
1480
+ return { stack: [url], index: 0 };
1481
+ }
1482
+ const { stack, index } = state;
1483
+ const cur = stack[index];
1484
+ if (url === cur) {
1485
+ return state;
1486
+ }
1487
+ const prev = index > 0 ? stack[index - 1] : void 0;
1488
+ const next = index < stack.length - 1 ? stack[index + 1] : void 0;
1489
+ if (prev && url === prev && canGoForward) {
1490
+ return { ...state, index: index - 1 };
1491
+ }
1492
+ if (next && url === next) {
1493
+ return { ...state, index: index + 1 };
1494
+ }
1495
+ const base = stack.slice(0, index + 1);
1496
+ const nextStack = [...base, url];
1497
+ return { stack: nextStack, index: nextStack.length - 1 };
1498
+ }
1499
+ default:
1500
+ return state;
1501
+ }
1502
+ }
1503
+ function useWebViewHistory() {
1504
+ const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
1505
+ const onNavigationStateChange = useCallback8(({ url, canGoForward: canGoForward2 }) => {
1506
+ dispatch({ type: "NAVIGATION_CHANGE", url, canGoForward: canGoForward2 });
1507
+ }, []);
1508
+ const { canGoBack, canGoForward } = useMemo3(() => {
1509
+ const canBack = state.index > 0;
1510
+ const canFwd = state.index >= 0 && state.index < state.stack.length - 1;
1511
+ return { canGoBack: canBack, canGoForward: canFwd };
1512
+ }, [state.index, state.stack.length]);
1513
+ return { onNavigationStateChange, hasHistory: canGoBack, canGoForward };
1514
+ }
1515
+
1516
+ // src/core/hooks/useWebBackHandler.tsx
1517
+ var HISTORY_BACK_SCRIPT = `
1518
+ (function() {
1519
+ window.history.back();
1520
+ true;
1521
+ })();
1522
+ `;
1523
+ var HISTORY_HOME_SCRIPT = `
1524
+ (function() {
1525
+ window.location.href = '/';
1526
+ true;
1527
+ })();
1528
+ `;
1529
+ function useWebBackHandler(webViewRef) {
1530
+ const { captureExitLog } = useCaptureExitLog();
1531
+ const { hasHistory, onNavigationStateChange } = useWebViewHistory();
1532
+ const {
1533
+ handlersRef: webBackHandlersRef,
1534
+ hasBackEvent: hasWebBackEvent,
1535
+ addEventListener: addWebBackEventListener,
1536
+ removeEventListener: removeWebBackEventListener
1537
+ } = useBackEventState();
1538
+ const logging = useNavigationBarLogging();
1539
+ const { openConfirm } = useDialog7();
1540
+ const global2 = getAppsInTossGlobals();
1541
+ const addEventListener = useCallback9(
1542
+ (handler) => {
1543
+ addWebBackEventListener(handler);
1544
+ },
1545
+ [addWebBackEventListener]
1546
+ );
1547
+ const removeEventListener = useCallback9(
1548
+ (handler) => {
1549
+ removeWebBackEventListener(handler);
1550
+ },
1551
+ [removeWebBackEventListener]
1552
+ );
1553
+ const handleWebBack = useCallback9(async () => {
1554
+ if (hasWebBackEvent) {
1555
+ for (const handler of webBackHandlersRef) {
1556
+ handler();
1557
+ }
1558
+ return;
1559
+ }
1560
+ if (hasHistory) {
1561
+ webViewRef.current?.injectJavaScript(HISTORY_BACK_SCRIPT);
1562
+ } else {
1563
+ const isConfirmed = await openConfirm({
1564
+ title: `${josa5(global2.brandDisplayName, "\uC744/\uB97C")} \uC885\uB8CC\uD560\uAE4C\uC694?`,
1565
+ leftButton: "\uCDE8\uC18C",
1566
+ rightButton: "\uC885\uB8CC\uD558\uAE30",
1567
+ closeOnDimmerClick: true,
1568
+ onEntered: logging.closePopupShow
1569
+ });
1570
+ logging.closePopupCtaClick(isConfirmed);
1571
+ if (isConfirmed) {
1572
+ captureExitLog(Date.now());
1573
+ closeView5();
1574
+ }
1575
+ }
1576
+ }, [
1577
+ captureExitLog,
1578
+ global2.brandDisplayName,
1579
+ hasHistory,
1580
+ hasWebBackEvent,
1581
+ webBackHandlersRef,
1582
+ logging,
1583
+ openConfirm,
1584
+ webViewRef
1585
+ ]);
1586
+ const handleWebHome = useCallback9(() => {
1587
+ logging.homeButtonClick();
1588
+ if (hasWebBackEvent) {
1589
+ for (const handler of webBackHandlersRef) {
1590
+ handler();
1591
+ }
1592
+ return;
1593
+ }
1594
+ webViewRef.current?.injectJavaScript(HISTORY_HOME_SCRIPT);
1595
+ }, [hasWebBackEvent, webBackHandlersRef, logging, webViewRef]);
1596
+ return useMemo4(
1597
+ () => ({ addEventListener, removeEventListener, handleWebBack, handleWebHome, onNavigationStateChange }),
1598
+ [addEventListener, removeEventListener, handleWebBack, handleWebHome, onNavigationStateChange]
1599
+ );
1600
+ }
1601
+
1602
+ // src/core/utils/mergeRefs.ts
1603
+ function mergeRefs(...refs) {
1604
+ return (value) => {
1605
+ refs.forEach((ref) => {
1606
+ if (typeof ref === "function") {
1607
+ ref(value);
1608
+ } else if (ref != null) {
1609
+ ref.current = value;
1610
+ }
1611
+ });
1612
+ };
1613
+ }
1614
+
1434
1615
  // src/hooks/useCreateUserAgent.ts
1435
1616
  import { getPlatformOS, getTossAppVersion } from "@apps-in-toss/native-modules";
1436
1617
  import { useWindowDimensions } from "react-native";
@@ -1590,11 +1771,11 @@ function useCreateUserAgent({
1590
1771
  // src/hooks/useGeolocation.ts
1591
1772
  import { startUpdateLocation } from "@apps-in-toss/native-modules";
1592
1773
  import { useVisibility as useVisibility3 } from "@granite-js/react-native";
1593
- import { useEffect as useEffect12, useState as useState4 } from "react";
1774
+ import { useEffect as useEffect10, useState as useState4 } from "react";
1594
1775
  function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1595
1776
  const isVisible = useVisibility3();
1596
1777
  const [location, setLocation] = useState4(null);
1597
- useEffect12(() => {
1778
+ useEffect10(() => {
1598
1779
  if (!isVisible) {
1599
1780
  return;
1600
1781
  }
@@ -1611,9 +1792,39 @@ function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1611
1792
  return location;
1612
1793
  }
1613
1794
 
1795
+ // src/hooks/useWaitForReturnNavigator.tsx
1796
+ import { useNavigation as useNavigation2, useVisibilityChange } from "@granite-js/react-native";
1797
+ import { useCallback as useCallback10, useRef as useRef5 } from "react";
1798
+ function useWaitForReturnNavigator() {
1799
+ const callbacks = useRef5([]).current;
1800
+ const navigation = useNavigation2();
1801
+ const startNavigating = useCallback10(
1802
+ (route, params) => {
1803
+ return new Promise((resolve) => {
1804
+ callbacks.push(resolve);
1805
+ navigation.navigate(route, params);
1806
+ });
1807
+ },
1808
+ [callbacks, navigation]
1809
+ );
1810
+ const handleVisibilityChange = useCallback10(
1811
+ (state) => {
1812
+ if (state === "visible" && callbacks.length > 0) {
1813
+ for (const callback of callbacks) {
1814
+ callback();
1815
+ }
1816
+ callbacks.splice(0, callbacks.length);
1817
+ }
1818
+ },
1819
+ [callbacks]
1820
+ );
1821
+ useVisibilityChange(handleVisibilityChange);
1822
+ return startNavigating;
1823
+ }
1824
+
1614
1825
  // src/utils/log.ts
1615
1826
  import { eventLog as eventLogNative } from "@apps-in-toss/native-modules";
1616
- import { getSchemeUri as getSchemeUri4 } from "@granite-js/react-native";
1827
+ import { getSchemeUri as getSchemeUri5 } from "@granite-js/react-native";
1617
1828
 
1618
1829
  // src/utils/extractDateFromUUIDv7.ts
1619
1830
  var extractDateFromUUIDv7 = (uuid) => {
@@ -1639,7 +1850,7 @@ var getGroupId = (url) => {
1639
1850
  };
1640
1851
  var getReferrer = () => {
1641
1852
  try {
1642
- const referrer = new URL(getSchemeUri4());
1853
+ const referrer = new URL(getSchemeUri5());
1643
1854
  return referrer.searchParams.get("referrer");
1644
1855
  } catch {
1645
1856
  return "";
@@ -1661,7 +1872,7 @@ var trackScreen = (url) => {
1661
1872
  };
1662
1873
 
1663
1874
  // src/components/WebView.tsx
1664
- import { jsx as jsx12 } from "react/jsx-runtime";
1875
+ import { jsx as jsx13 } from "react/jsx-runtime";
1665
1876
  var operationalEnvironment = appsInTossConstantBridges.getOperationalEnvironment();
1666
1877
  var TYPES = ["partner", "external", "game"];
1667
1878
  var WEBVIEW_TYPES = {
@@ -1671,7 +1882,7 @@ var WEBVIEW_TYPES = {
1671
1882
  };
1672
1883
  function mergeSchemeQueryParamsInto(url) {
1673
1884
  const baseUrl = new URL(url);
1674
- const schemeUrl = new URL(getSchemeUri5());
1885
+ const schemeUrl = new URL(getSchemeUri6());
1675
1886
  baseUrl.pathname = schemeUrl.pathname;
1676
1887
  for (const [key, value] of schemeUrl.searchParams.entries()) {
1677
1888
  baseUrl.searchParams.set(key, value);
@@ -1695,8 +1906,9 @@ function WebView({ type, local, onMessage, ...props }) {
1695
1906
  if (!TYPES.includes(type)) {
1696
1907
  throw new Error(`Invalid WebView type: '${type}'`);
1697
1908
  }
1698
- const graniteEvent = useGraniteEvent();
1699
- const uri = useMemo3(() => getWebViewUri(local), [local]);
1909
+ const webViewRef = useRef6(null);
1910
+ const webBackHandler = useWebBackHandler(webViewRef);
1911
+ const uri = useMemo5(() => getWebViewUri(local), [local]);
1700
1912
  const top = useSafeAreaTop2();
1701
1913
  const bottom = useSafeAreaBottom();
1702
1914
  const global2 = getAppsInTossGlobals();
@@ -1718,11 +1930,16 @@ function WebView({ type, local, onMessage, ...props }) {
1718
1930
  eventListenerMap: {
1719
1931
  ...appsInTossEventBridges,
1720
1932
  navigationAccessoryEvent: ({ onEvent, onError }) => tdsEvent.addEventListener("navigationAccessoryEvent", { onEvent, onError }),
1721
- backEvent: ({ onEvent, onError, options }) => graniteEvent.addEventListener("backEvent", { onEvent, onError, options }),
1722
- entryMessageExited: ({ onEvent, onError }) => appsInTossEvent5.addEventListener("entryMessageExited", { onEvent, onError }),
1723
- updateLocationEvent: ({ onEvent, onError, options }) => appsInTossEvent5.addEventListener("updateLocationEvent", { onEvent, onError, options }),
1933
+ backEvent: ({ onEvent }) => {
1934
+ webBackHandler.addEventListener(onEvent);
1935
+ return () => {
1936
+ webBackHandler.removeEventListener(onEvent);
1937
+ };
1938
+ },
1939
+ entryMessageExited: ({ onEvent, onError }) => appsInTossEvent3.addEventListener("entryMessageExited", { onEvent, onError }),
1940
+ updateLocationEvent: ({ onEvent, onError, options }) => appsInTossEvent3.addEventListener("updateLocationEvent", { onEvent, onError, options }),
1724
1941
  /** @internal */
1725
- appBridgeCallbackEvent: ({ onEvent, onError, options }) => appsInTossEvent5.addEventListener("appBridgeCallbackEvent", { onEvent, onError, options }),
1942
+ appBridgeCallbackEvent: ({ onEvent, onError, options }) => appsInTossEvent3.addEventListener("appBridgeCallbackEvent", { onEvent, onError, options }),
1726
1943
  /** AdMob */
1727
1944
  loadAdMobInterstitialAd: GoogleAdMob.loadAdMobInterstitialAd,
1728
1945
  showAdMobInterstitialAd: GoogleAdMob.showAdMobInterstitialAd,
@@ -1730,10 +1947,12 @@ function WebView({ type, local, onMessage, ...props }) {
1730
1947
  showAdMobRewardedAd: GoogleAdMob.showAdMobRewardedAd,
1731
1948
  /** AdMobV2 */
1732
1949
  loadAppsInTossAdMob: GoogleAdMob.loadAppsInTossAdMob,
1733
- showAppsInTossAdMob: GoogleAdMob.showAppsInTossAdMob
1950
+ showAppsInTossAdMob: GoogleAdMob.showAppsInTossAdMob,
1951
+ /** IAP */
1952
+ iapCreateOneTimePurchaseOrder: IAP.createOneTimePurchaseOrder,
1953
+ requestOneTimePurchase
1734
1954
  },
1735
1955
  constantHandlerMap: {
1736
- ...graniteConstantBridges,
1737
1956
  ...appsInTossConstantBridges,
1738
1957
  getSafeAreaTop: () => top,
1739
1958
  getSafeAreaBottom: () => bottom,
@@ -1750,7 +1969,6 @@ function WebView({ type, local, onMessage, ...props }) {
1750
1969
  getDeploymentId: env.getDeploymentId
1751
1970
  },
1752
1971
  asyncHandlerMap: {
1753
- ...graniteAsyncBridges,
1754
1972
  ...appsInTossAsyncBridges,
1755
1973
  setIosSwipeGestureEnabled: (options) => {
1756
1974
  setAllowsBackForwardNavigationGestures(options.isEnabled);
@@ -1774,11 +1992,14 @@ function WebView({ type, local, onMessage, ...props }) {
1774
1992
  removeStorageItem: Storage.removeItem,
1775
1993
  clearItems: Storage.clearItems,
1776
1994
  /** IAP */
1777
- iapCreateOneTimePurchaseOrder: IAP.createOneTimePurchaseOrder,
1778
- iapGetProductItemList: IAP.getProductItemList
1995
+ iapGetProductItemList: IAP.getProductItemList,
1996
+ iapCreateOneTimePurchaseOrder,
1997
+ processProductGrant,
1998
+ getPendingOrders: IAP.getPendingOrders,
1999
+ getCompletedOrRefundedOrders: IAP.getCompletedOrRefundedOrders
1779
2000
  }
1780
2001
  });
1781
- const headerPropForExternalWebView = useMemo3(() => {
2002
+ const headerPropForExternalWebView = useMemo5(() => {
1782
2003
  const parsedNavigationBar = global2.navigationBar != null ? safeParseNavigationBar(global2.navigationBar) : null;
1783
2004
  const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
1784
2005
  const withBackButton = parsedNavigationBar?.withBackButton ?? true;
@@ -1795,23 +2016,22 @@ function WebView({ type, local, onMessage, ...props }) {
1795
2016
  }, [global2.navigationBar, type]);
1796
2017
  const BaseWebView = WEBVIEW_TYPES[type];
1797
2018
  const webViewDebuggingEnabled = operationalEnvironment === "sandbox";
1798
- const [canHistoryGoBack, setCanHistoryGoBack] = useState5(false);
1799
- const handleNavigationStateChange = useCallback9(
1800
- (event) => {
1801
- if (event.url) {
1802
- trackScreen(event.url);
1803
- }
1804
- setCanHistoryGoBack(event.canGoBack);
1805
- },
1806
- [setCanHistoryGoBack]
1807
- );
1808
2019
  const userAgent = useCreateUserAgent({
1809
2020
  colorPreference: "light"
1810
2021
  });
1811
- return /* @__PURE__ */ jsx12(
2022
+ const refs = mergeRefs(handler.ref, webViewRef);
2023
+ useEffect11(() => {
2024
+ const callback = () => {
2025
+ webBackHandler.handleWebBack();
2026
+ return true;
2027
+ };
2028
+ BackHandler2.addEventListener("hardwareBackPress", callback);
2029
+ return () => BackHandler2.removeEventListener("hardwareBackPress", callback);
2030
+ }, [webBackHandler]);
2031
+ return /* @__PURE__ */ jsx13(
1812
2032
  BaseWebView,
1813
2033
  {
1814
- ref: handler.ref,
2034
+ ref: refs,
1815
2035
  ...props,
1816
2036
  ...headerPropForExternalWebView,
1817
2037
  source: {
@@ -1821,13 +2041,20 @@ function WebView({ type, local, onMessage, ...props }) {
1821
2041
  "User-Agent": userAgent
1822
2042
  }
1823
2043
  },
2044
+ onHomeButtonClick: webBackHandler.handleWebHome,
2045
+ onBackButtonClick: webBackHandler.handleWebBack,
2046
+ onNavigationStateChange: (event) => {
2047
+ if (event.url) {
2048
+ trackScreen(event.url);
2049
+ }
2050
+ props.onNavigationStateChange?.(event);
2051
+ webBackHandler.onNavigationStateChange(event);
2052
+ },
1824
2053
  userAgent: Platform4.OS === "ios" ? userAgent : void 0,
1825
2054
  sharedCookiesEnabled: true,
1826
2055
  webviewDebuggingEnabled: webViewDebuggingEnabled,
1827
2056
  thirdPartyCookiesEnabled: true,
1828
2057
  onMessage: handler.onMessage,
1829
- canHistoryGoBack,
1830
- onNavigationStateChange: handleNavigationStateChange,
1831
2058
  injectedJavaScript: handler.injectedJavaScript,
1832
2059
  injectedJavaScriptBeforeContentLoaded: handler.injectedJavaScript,
1833
2060
  decelerationRate: Platform4.OS === "ios" ? 1 : void 0,
@@ -1838,7 +2065,7 @@ function WebView({ type, local, onMessage, ...props }) {
1838
2065
 
1839
2066
  // src/index.ts
1840
2067
  export * from "@apps-in-toss/analytics";
1841
- import { useTopNavigation as useTopNavigation2 } from "@toss-design-system/react-native/private";
2068
+ import { useTopNavigation as useTopNavigation2, useOverlay as useOverlay3, OverlayProvider } from "@toss/tds-react-native/private";
1842
2069
  export * from "@apps-in-toss/native-modules";
1843
2070
  export * from "@apps-in-toss/types";
1844
2071
  var Analytics2 = {
@@ -1851,9 +2078,12 @@ export {
1851
2078
  Analytics2 as Analytics,
1852
2079
  AppsInToss,
1853
2080
  INTERNAL__onVisibilityChangedByTransparentServiceWeb,
2081
+ OverlayProvider,
1854
2082
  WebView,
1855
2083
  env,
1856
2084
  useCreateUserAgent,
1857
2085
  useGeolocation,
1858
- useTopNavigation2 as useTopNavigation
2086
+ useOverlay3 as useOverlay,
2087
+ useTopNavigation2 as useTopNavigation,
2088
+ useWaitForReturnNavigator
1859
2089
  };