@apps-in-toss/framework 0.0.0-dev.1761559152736 → 0.0.0-dev.1763036638916

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
@@ -163,10 +163,8 @@ function AppUpdate() {
163
163
  return /* @__PURE__ */ jsx(Fragment, {});
164
164
  }
165
165
 
166
- // src/core/hooks/useAppsInTossBridge.ts
167
- import { appsInTossEvent } from "@apps-in-toss/native-modules";
168
- import { useBridge } from "@toss/tds-react-native";
169
- import { useEffect as useEffect4 } from "react";
166
+ // src/core/context/NavigationBarContext.tsx
167
+ import { createContext, useContext, useState } from "react";
170
168
 
171
169
  // src/core/utils/getAppsInTossGlobals.ts
172
170
  function getAppsInTossGlobals() {
@@ -176,6 +174,54 @@ function getAppsInTossGlobals() {
176
174
  return global.__appsInToss;
177
175
  }
178
176
 
177
+ // src/core/utils/safeParseNavigationBar.ts
178
+ function safeParseNavigationBar(navigationBar) {
179
+ if (typeof navigationBar === "object") {
180
+ return navigationBar;
181
+ }
182
+ try {
183
+ return JSON.parse(navigationBar);
184
+ } catch {
185
+ return null;
186
+ }
187
+ }
188
+
189
+ // src/core/context/NavigationBarContext.tsx
190
+ import { jsx as jsx2 } from "react/jsx-runtime";
191
+ var NavigationBarContext = createContext(null);
192
+ function NavigationBarContextProvider({ children }) {
193
+ const globals = getAppsInTossGlobals();
194
+ const parsedNavigationBar = globals.navigationBar != null ? safeParseNavigationBar(globals.navigationBar) : null;
195
+ const [navigationRightButton, setNavigationRightButton] = useState(
196
+ parsedNavigationBar?.initialAccessoryButton
197
+ );
198
+ const addNavigationRightButton = (button) => {
199
+ setNavigationRightButton(button);
200
+ };
201
+ const removeNavigationRightButton = () => {
202
+ setNavigationRightButton(void 0);
203
+ };
204
+ return /* @__PURE__ */ jsx2(
205
+ NavigationBarContext.Provider,
206
+ {
207
+ value: { navigationRightButton, addNavigationRightButton, removeNavigationRightButton },
208
+ children
209
+ }
210
+ );
211
+ }
212
+ function useNavigationBarContext() {
213
+ const context = useContext(NavigationBarContext);
214
+ if (context == null) {
215
+ throw Error("useNavigationBarContext must be used within NavigationBarContextProvider");
216
+ }
217
+ return context;
218
+ }
219
+
220
+ // src/core/hooks/useAppsInTossBridge.ts
221
+ import { appsInTossEvent } from "@apps-in-toss/native-modules";
222
+ import { useBridge } from "@toss/tds-react-native";
223
+ import { useEffect as useEffect4 } from "react";
224
+
179
225
  // src/core/utils/toIcon.ts
180
226
  function toIcon(source) {
181
227
  return source.startsWith("http") ? { source: { uri: source } } : { name: source };
@@ -201,7 +247,7 @@ function useAppsInTossBridge() {
201
247
 
202
248
  // src/components/RNAppContainer.tsx
203
249
  import { appsInTossEvent as appsInTossEvent2, setIosSwipeGestureEnabled } from "@apps-in-toss/native-modules";
204
- import { useEffect as useEffect9, useState as useState4 } from "react";
250
+ import { useEffect as useEffect9, useState as useState5 } from "react";
205
251
  import { Platform as Platform3 } from "react-native";
206
252
 
207
253
  // src/components/GameInitializer.tsx
@@ -317,7 +363,7 @@ function useAppUpdateDialogLogging() {
317
363
 
318
364
  // src/hooks/useGameCenterProfile.ts
319
365
  import { getGameCenterGameProfile } from "@apps-in-toss/native-modules";
320
- import { useCallback as useCallback6, useState as useState2 } from "react";
366
+ import { useCallback as useCallback6, useState as useState3 } from "react";
321
367
 
322
368
  // src/hooks/useErrorAlert.ts
323
369
  import { closeView } from "@granite-js/react-native";
@@ -344,7 +390,7 @@ var useErrorAlert = () => {
344
390
  };
345
391
 
346
392
  // src/hooks/useTransparentWebview.tsx
347
- import { useCallback as useCallback4, useState } from "react";
393
+ import { useCallback as useCallback4, useState as useState2 } from "react";
348
394
 
349
395
  // src/utils/openTransparentWebView.ts
350
396
  import { openURL as openURL3 } from "@granite-js/react-native";
@@ -386,7 +432,7 @@ var openTransparentWebView = ({
386
432
 
387
433
  // src/hooks/useTransparentWebview.tsx
388
434
  var useTransparentWebview = () => {
389
- const [isWebviewLoading, setIsWebviewLoading] = useState(false);
435
+ const [isWebviewLoading, setIsWebviewLoading] = useState2(false);
390
436
  const { open: openErrorAlert } = useErrorAlert();
391
437
  const _openTransparentWebview = useCallback4(
392
438
  ({ webUrl, onClose, onError }) => {
@@ -423,14 +469,14 @@ var useTransparentWebview = () => {
423
469
  import { Asset, Toast } from "@toss/tds-react-native";
424
470
  import { AdaptiveColorProvider, ColorPreferenceProvider, useOverlay } from "@toss/tds-react-native/private";
425
471
  import { useCallback as useCallback5 } from "react";
426
- import { jsx as jsx2 } from "react/jsx-runtime";
472
+ import { jsx as jsx3 } from "react/jsx-runtime";
427
473
  var useGameProfileToast = () => {
428
474
  const overlay = useOverlay();
429
475
  const openGameProfileToast = useCallback5(
430
476
  (nickname, profileImageUri) => {
431
477
  return new Promise((resolve) => {
432
478
  overlay.open(({ isOpen, close, exit }) => {
433
- return /* @__PURE__ */ jsx2(ColorPreferenceProvider, { colorPreference: "dark", children: /* @__PURE__ */ jsx2(AdaptiveColorProvider, { children: /* @__PURE__ */ jsx2(
479
+ return /* @__PURE__ */ jsx3(ColorPreferenceProvider, { colorPreference: "dark", children: /* @__PURE__ */ jsx3(AdaptiveColorProvider, { children: /* @__PURE__ */ jsx3(
434
480
  Toast,
435
481
  {
436
482
  open: isOpen,
@@ -441,7 +487,7 @@ var useGameProfileToast = () => {
441
487
  onExited: exit,
442
488
  position: "top",
443
489
  text: `${nickname}\uB2D8 \uBC18\uAC00\uC6CC\uC694!`,
444
- icon: /* @__PURE__ */ jsx2(
490
+ icon: /* @__PURE__ */ jsx3(
445
491
  Asset.Image,
446
492
  {
447
493
  style: { borderRadius: 64, overflow: "hidden" },
@@ -461,9 +507,9 @@ var useGameProfileToast = () => {
461
507
 
462
508
  // src/hooks/useGameCenterProfile.ts
463
509
  var useGameCenterProfile = (isReadyForProfileUI) => {
464
- const [profileData, setProfileData] = useState2(void 0);
465
- const [isProfileDataLoading, setIsProfileDataLoading] = useState2(true);
466
- const [isProfileDataRefetching, setIsProfileDataRefetching] = useState2(false);
510
+ const [profileData, setProfileData] = useState3(void 0);
511
+ const [isProfileDataLoading, setIsProfileDataLoading] = useState3(true);
512
+ const [isProfileDataRefetching, setIsProfileDataRefetching] = useState3(false);
467
513
  const shouldShowProfileLoadingOverlay = isProfileDataLoading && isReadyForProfileUI || isProfileDataRefetching;
468
514
  const shouldShowProfileNotFoundOverlay = profileData?.statusCode === "PROFILE_NOT_FOUND" && isReadyForProfileUI && !isProfileDataRefetching;
469
515
  const canShowBottomSheetOrToast = !isProfileDataLoading && isReadyForProfileUI;
@@ -527,7 +573,7 @@ var Z_INDEX = {
527
573
  };
528
574
 
529
575
  // src/components/GameInitializer.tsx
530
- import { Fragment as Fragment2, jsx as jsx3, jsxs } from "react/jsx-runtime";
576
+ import { Fragment as Fragment2, jsx as jsx4, jsxs } from "react/jsx-runtime";
531
577
  var GameInitializer = ({ children, isReadyForProfileUI }) => {
532
578
  const {
533
579
  profileData,
@@ -581,8 +627,8 @@ var GameInitializer = ({ children, isReadyForProfileUI }) => {
581
627
  ]);
582
628
  if (!isMinVersionSupported(GAME_MIN_VERSION)) {
583
629
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
584
- /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
585
- /* @__PURE__ */ jsx3(
630
+ /* @__PURE__ */ jsx4(View, { style: { flex: 1, position: "relative" }, children }),
631
+ /* @__PURE__ */ jsx4(
586
632
  Pressable,
587
633
  {
588
634
  style: {
@@ -603,8 +649,8 @@ var GameInitializer = ({ children, isReadyForProfileUI }) => {
603
649
  }
604
650
  if (shouldShowProfileLoadingOverlay) {
605
651
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
606
- /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
607
- /* @__PURE__ */ jsx3(
652
+ /* @__PURE__ */ jsx4(View, { style: { flex: 1, position: "relative" }, children }),
653
+ /* @__PURE__ */ jsx4(
608
654
  View,
609
655
  {
610
656
  style: {
@@ -613,15 +659,15 @@ var GameInitializer = ({ children, isReadyForProfileUI }) => {
613
659
  alignItems: "center",
614
660
  backgroundColor: "rgba(0, 0, 0, 0.2)"
615
661
  },
616
- children: /* @__PURE__ */ jsx3(Loader, { size: "large", type: "light" })
662
+ children: /* @__PURE__ */ jsx4(Loader, { size: "large", type: "light" })
617
663
  }
618
664
  )
619
665
  ] });
620
666
  }
621
667
  if (shouldShowProfileNotFoundOverlay) {
622
668
  return /* @__PURE__ */ jsxs(Fragment2, { children: [
623
- /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }),
624
- shouldShowProfileNotFoundOverlay && /* @__PURE__ */ jsx3(
669
+ /* @__PURE__ */ jsx4(View, { style: { flex: 1, position: "relative" }, children }),
670
+ shouldShowProfileNotFoundOverlay && /* @__PURE__ */ jsx4(
625
671
  Pressable,
626
672
  {
627
673
  style: {
@@ -634,7 +680,7 @@ var GameInitializer = ({ children, isReadyForProfileUI }) => {
634
680
  )
635
681
  ] });
636
682
  }
637
- return /* @__PURE__ */ jsx3(Fragment2, { children: /* @__PURE__ */ jsx3(View, { style: { flex: 1, position: "relative" }, children }) });
683
+ return /* @__PURE__ */ jsx4(Fragment2, { children: /* @__PURE__ */ jsx4(View, { style: { flex: 1, position: "relative" }, children }) });
638
684
  };
639
685
  var overlayStyle = {
640
686
  position: "absolute",
@@ -813,7 +859,7 @@ import { INTERNAL__appBridgeHandler, isMinVersionSupported as isMinVersionSuppor
813
859
  import { openURL as openURL4 } from "@granite-js/react-native";
814
860
  import { BottomSheet, List, ListHeader, ListRow as ListRow2 } from "@toss/tds-react-native";
815
861
  import { useAdaptive as useAdaptive2, useOverlay as useOverlay2 } from "@toss/tds-react-native/private";
816
- import { useEffect as useEffect7, useState as useState3 } from "react";
862
+ import { useEffect as useEffect7, useState as useState4 } from "react";
817
863
 
818
864
  // src/core/hooks/useMoreButtonBottomSheet/AppShareListMenu.tsx
819
865
  import { getOperationalEnvironment } from "@apps-in-toss/native-modules";
@@ -901,7 +947,7 @@ function addParamsToUrl(url, params) {
901
947
  }
902
948
 
903
949
  // src/core/hooks/useMoreButtonBottomSheet/AppShareListMenu.tsx
904
- import { jsx as jsx4 } from "react/jsx-runtime";
950
+ import { jsx as jsx5 } from "react/jsx-runtime";
905
951
  var SHARE_SCHEME_REFERRER = "appsintoss.common_module_share";
906
952
  var APP_SHARE_MENU_INFO = {
907
953
  contactItemName: "\uACF5\uC720\uD558\uAE30",
@@ -917,10 +963,10 @@ function AppShareListMenu() {
917
963
  const schemeForShare = addParamsToUrl(initialScheme, {
918
964
  referrer: SHARE_SCHEME_REFERRER
919
965
  });
920
- return /* @__PURE__ */ jsx4(
966
+ return /* @__PURE__ */ jsx5(
921
967
  ListRow,
922
968
  {
923
- left: /* @__PURE__ */ jsx4(
969
+ left: /* @__PURE__ */ jsx5(
924
970
  ListRow.Icon,
925
971
  {
926
972
  color: globals.brandPrimaryColor,
@@ -928,7 +974,7 @@ function AppShareListMenu() {
928
974
  type: "background"
929
975
  }
930
976
  ),
931
- contents: /* @__PURE__ */ jsx4(
977
+ contents: /* @__PURE__ */ jsx5(
932
978
  ListRow.Texts,
933
979
  {
934
980
  type: "1RowTypeA",
@@ -967,7 +1013,7 @@ function ensureValue(value, name) {
967
1013
  }
968
1014
 
969
1015
  // src/core/hooks/useMoreButtonBottomSheet/index.tsx
970
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
1016
+ import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
971
1017
  var APP_BRIDGE_METHOD_NAME = "getMiniAppsSupportContact";
972
1018
  var MIN_VERSION = {
973
1019
  BOTTOM_SHEET: {
@@ -982,7 +1028,7 @@ var MIN_VERSION = {
982
1028
  function useMoreButtonBottomSheet() {
983
1029
  const globals = getAppsInTossGlobals();
984
1030
  const adaptive = useAdaptive2();
985
- const [itemList, setItemList] = useState3([]);
1031
+ const [itemList, setItemList] = useState4([]);
986
1032
  const appUpdateDialog = useAppUpdateDialog();
987
1033
  const logging = useMoreButtonBottomSheetLogging();
988
1034
  const overlay = useOverlay2();
@@ -1016,17 +1062,17 @@ function useMoreButtonBottomSheet() {
1016
1062
  logging.close();
1017
1063
  close();
1018
1064
  };
1019
- return /* @__PURE__ */ jsx5(BottomSheetImpressionArea, { children: /* @__PURE__ */ jsx5(
1065
+ return /* @__PURE__ */ jsx6(BottomSheetImpressionArea, { children: /* @__PURE__ */ jsx6(
1020
1066
  BottomSheet.Root,
1021
1067
  {
1022
- header: /* @__PURE__ */ jsx5(
1068
+ header: /* @__PURE__ */ jsx6(
1023
1069
  ListHeader,
1024
1070
  {
1025
- title: /* @__PURE__ */ jsx5(ListHeader.TitleParagraph, { color: adaptive.grey800, fontWeight: "bold", typography: "t5", children: title })
1071
+ title: /* @__PURE__ */ jsx6(ListHeader.TitleParagraph, { color: adaptive.grey800, fontWeight: "bold", typography: "t5", children: title })
1026
1072
  }
1027
1073
  ),
1028
1074
  open: isOpen,
1029
- cta: /* @__PURE__ */ jsx5(
1075
+ cta: /* @__PURE__ */ jsx6(
1030
1076
  BottomSheet.CTA,
1031
1077
  {
1032
1078
  size: "large",
@@ -1042,10 +1088,10 @@ function useMoreButtonBottomSheet() {
1042
1088
  onExited: exit,
1043
1089
  children: /* @__PURE__ */ jsxs2(List, { rowSeparator: "none", children: [
1044
1090
  itemList.map((item) => {
1045
- return /* @__PURE__ */ jsx5(
1091
+ return /* @__PURE__ */ jsx6(
1046
1092
  ListRow2,
1047
1093
  {
1048
- left: /* @__PURE__ */ jsx5(
1094
+ left: /* @__PURE__ */ jsx6(
1049
1095
  ListRow2.Icon,
1050
1096
  {
1051
1097
  color: globals.brandPrimaryColor,
@@ -1053,7 +1099,7 @@ function useMoreButtonBottomSheet() {
1053
1099
  type: "background"
1054
1100
  }
1055
1101
  ),
1056
- contents: /* @__PURE__ */ jsx5(
1102
+ contents: /* @__PURE__ */ jsx6(
1057
1103
  ListRow2.Texts,
1058
1104
  {
1059
1105
  type: "1RowTypeA",
@@ -1070,7 +1116,7 @@ function useMoreButtonBottomSheet() {
1070
1116
  item.contactItemName
1071
1117
  );
1072
1118
  }),
1073
- isShareListMenuSupported && /* @__PURE__ */ jsx5(AppShareListMenu, {})
1119
+ isShareListMenuSupported && /* @__PURE__ */ jsx6(AppShareListMenu, {})
1074
1120
  ] })
1075
1121
  }
1076
1122
  ) });
@@ -1083,24 +1129,12 @@ function BottomSheetImpressionArea({ children }) {
1083
1129
  useEffect7(() => {
1084
1130
  logging.show();
1085
1131
  }, [logging]);
1086
- return /* @__PURE__ */ jsx5(Fragment3, { children });
1087
- }
1088
-
1089
- // src/core/utils/safeParseNavigationBar.ts
1090
- function safeParseNavigationBar(navigationBar) {
1091
- if (typeof navigationBar === "object") {
1092
- return navigationBar;
1093
- }
1094
- try {
1095
- return JSON.parse(navigationBar);
1096
- } catch {
1097
- return null;
1098
- }
1132
+ return /* @__PURE__ */ jsx6(Fragment3, { children });
1099
1133
  }
1100
1134
 
1101
1135
  // src/components/NavigationBar/common/NavigationBarImpressionArea.tsx
1102
1136
  import { useEffect as useEffect8, useRef as useRef3 } from "react";
1103
- import { Fragment as Fragment4, jsx as jsx6 } from "react/jsx-runtime";
1137
+ import { Fragment as Fragment4, jsx as jsx7 } from "react/jsx-runtime";
1104
1138
  function NavigationBarImpressionArea({
1105
1139
  children,
1106
1140
  withHomeButton
@@ -1113,21 +1147,21 @@ function NavigationBarImpressionArea({
1113
1147
  hasLogged.current = true;
1114
1148
  }
1115
1149
  }, [logging, withHomeButton]);
1116
- return /* @__PURE__ */ jsx6(Fragment4, { children });
1150
+ return /* @__PURE__ */ jsx7(Fragment4, { children });
1117
1151
  }
1118
1152
 
1119
1153
  // src/components/NavigationBar/RNNavigationBar/Default.tsx
1120
- import { jsx as jsx7 } from "react/jsx-runtime";
1154
+ import { jsx as jsx8 } from "react/jsx-runtime";
1121
1155
  function DefaultNavigationBar() {
1122
1156
  const globals = getAppsInTossGlobals();
1123
1157
  const { open: openMoreButtonBottomSheet } = useMoreButtonBottomSheet();
1124
1158
  const parsedNavigationBar = globals.navigationBar != null ? safeParseNavigationBar(globals.navigationBar) : null;
1125
1159
  const withHomeButton = parsedNavigationBar?.withHomeButton ?? false;
1126
1160
  const withBackButton = parsedNavigationBar?.withBackButton ?? true;
1127
- const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
1161
+ const { navigationRightButton } = useNavigationBarContext();
1128
1162
  const navigationEvent = useNavigationEvent();
1129
1163
  useHardwareBackPress(navigationEvent.handleBack);
1130
- return /* @__PURE__ */ jsx7(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx7(
1164
+ return /* @__PURE__ */ jsx8(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx8(
1131
1165
  TopNavigation,
1132
1166
  {
1133
1167
  title: globals.brandDisplayName,
@@ -1137,28 +1171,28 @@ function DefaultNavigationBar() {
1137
1171
  onPressTitle: withHomeButton ? navigationEvent.handleHomeButtonClick : void 0,
1138
1172
  onPressClose: navigationEvent.handleCloseButtonClick,
1139
1173
  withHome: withHomeButton,
1140
- fixedRightButton: initialAccessoryButton,
1141
- children: /* @__PURE__ */ jsx7(NavigationLeft, { visible: withBackButton, children: /* @__PURE__ */ jsx7(NavigationBackButton, { onPress: navigationEvent.handleBack, canGoBack: false }) })
1174
+ fixedRightButton: navigationRightButton,
1175
+ children: /* @__PURE__ */ jsx8(NavigationLeft, { visible: withBackButton, children: /* @__PURE__ */ jsx8(NavigationBackButton, { onPress: navigationEvent.handleBack, canGoBack: false }) })
1142
1176
  }
1143
1177
  ) });
1144
1178
  }
1145
1179
 
1146
1180
  // src/components/NavigationBar/RNNavigationBar/Game.tsx
1181
+ import { useSafeAreaInsets } from "@granite-js/native/react-native-safe-area-context";
1147
1182
  import { PageNavbar } from "@toss/tds-react-native";
1148
1183
  import { NavigationRightContent, useSafeAreaTop } from "@toss/tds-react-native/private";
1149
1184
  import { Platform as Platform2, View as View2 } from "react-native";
1150
- import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
1185
+ import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
1151
1186
  function GameNavigationBar() {
1152
1187
  const safeAreaTop = useSafeAreaTop();
1153
- const global2 = getAppsInTossGlobals();
1154
1188
  const { open: openMoreButtonBottomSheet } = useMoreButtonBottomSheet();
1155
1189
  const navigationEvent = useNavigationEvent();
1190
+ const { navigationRightButton } = useNavigationBarContext();
1191
+ const { right: safeAreaRight } = useSafeAreaInsets();
1156
1192
  useHardwareBackPress(navigationEvent.handleBack);
1157
- const parsedNavigationBar = global2.navigationBar != null ? safeParseNavigationBar(global2.navigationBar) : null;
1158
- const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
1159
1193
  return /* @__PURE__ */ jsxs3(Fragment5, { children: [
1160
- /* @__PURE__ */ jsx8(PageNavbar, { preference: { type: "none" } }),
1161
- /* @__PURE__ */ jsx8(
1194
+ /* @__PURE__ */ jsx9(PageNavbar, { preference: { type: "none" } }),
1195
+ /* @__PURE__ */ jsx9(
1162
1196
  View2,
1163
1197
  {
1164
1198
  style: {
@@ -1171,13 +1205,13 @@ function GameNavigationBar() {
1171
1205
  position: "absolute",
1172
1206
  zIndex: Z_INDEX.CLOSE_BUTTON,
1173
1207
  marginTop: safeAreaTop,
1174
- paddingRight: 10
1208
+ paddingRight: safeAreaRight + 10
1175
1209
  },
1176
1210
  pointerEvents: "box-none",
1177
- children: /* @__PURE__ */ jsx8(
1211
+ children: /* @__PURE__ */ jsx9(
1178
1212
  NavigationRightContent,
1179
1213
  {
1180
- fixedRightButton: initialAccessoryButton,
1214
+ fixedRightButton: navigationRightButton,
1181
1215
  onPressDots: openMoreButtonBottomSheet,
1182
1216
  onPressClose: navigationEvent.handleCloseButtonClick,
1183
1217
  theme: "dark"
@@ -1204,19 +1238,19 @@ import * as constant_bridges_star from "@apps-in-toss/native-modules/constant-br
1204
1238
  import * as event_bridges_star from "@apps-in-toss/native-modules/event-bridges";
1205
1239
 
1206
1240
  // src/components/RNAppContainer.tsx
1207
- import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1241
+ import { Fragment as Fragment6, jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
1208
1242
  function RNAppContainer({ children }) {
1209
1243
  const global2 = getAppsInTossGlobals();
1210
1244
  switch (global2.appType) {
1211
1245
  case "game":
1212
- return /* @__PURE__ */ jsx9(GameAppContainer, { children });
1246
+ return /* @__PURE__ */ jsx10(GameAppContainer, { children });
1213
1247
  case "general":
1214
1248
  default:
1215
- return /* @__PURE__ */ jsx9(GeneralAppContainer, { children });
1249
+ return /* @__PURE__ */ jsx10(GeneralAppContainer, { children });
1216
1250
  }
1217
1251
  }
1218
1252
  function GameAppContainer({ children }) {
1219
- const [isEntryMessageExited, setIsEntryMessageExited] = useState4(false);
1253
+ const [isEntryMessageExited, setIsEntryMessageExited] = useState5(false);
1220
1254
  useEffect9(() => {
1221
1255
  if (Platform3.OS === "ios") {
1222
1256
  setIosSwipeGestureEnabled({ isEnabled: false });
@@ -1234,40 +1268,40 @@ function GameAppContainer({ children }) {
1234
1268
  });
1235
1269
  }, []);
1236
1270
  return /* @__PURE__ */ jsxs4(Fragment6, { children: [
1237
- /* @__PURE__ */ jsx9(RNNavigationBar.Game, {}),
1238
- (0, bridge_entry_exports.getOperationalEnvironment)() === "toss" ? /* @__PURE__ */ jsx9(GameInitializer, { isReadyForProfileUI: isEntryMessageExited, children }) : children
1271
+ /* @__PURE__ */ jsx10(RNNavigationBar.Game, {}),
1272
+ (0, bridge_entry_exports.getOperationalEnvironment)() === "toss" ? /* @__PURE__ */ jsx10(GameInitializer, { isReadyForProfileUI: isEntryMessageExited, children }) : children
1239
1273
  ] });
1240
1274
  }
1241
1275
  function GeneralAppContainer({ children }) {
1242
1276
  return /* @__PURE__ */ jsxs4(Fragment6, { children: [
1243
- /* @__PURE__ */ jsx9(RNNavigationBar.Default, {}),
1277
+ /* @__PURE__ */ jsx10(RNNavigationBar.Default, {}),
1244
1278
  children
1245
1279
  ] });
1246
1280
  }
1247
1281
 
1248
1282
  // src/core/registerApp.tsx
1249
- import { Fragment as Fragment7, jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
1283
+ import { Fragment as Fragment7, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
1250
1284
  function AppsInTossContainer(Container, { children, ...initialProps }) {
1251
1285
  if (!isMinVersionSupported3({
1252
1286
  android: "5.220.0",
1253
1287
  ios: "5.221.0"
1254
1288
  })) {
1255
1289
  return /* @__PURE__ */ jsxs5(Fragment7, { children: [
1256
- /* @__PURE__ */ jsx10(AppEvent.Entry, {}),
1257
- /* @__PURE__ */ jsx10(AppEvent.System, { ...initialProps }),
1258
- /* @__PURE__ */ jsx10(AppUpdate, {})
1290
+ /* @__PURE__ */ jsx11(AppEvent.Entry, {}),
1291
+ /* @__PURE__ */ jsx11(AppEvent.System, { ...initialProps }),
1292
+ /* @__PURE__ */ jsx11(AppUpdate, {})
1259
1293
  ] });
1260
1294
  }
1261
1295
  return /* @__PURE__ */ jsxs5(Fragment7, { children: [
1262
- /* @__PURE__ */ jsx10(AppEvent.StayTime, {}),
1263
- /* @__PURE__ */ jsx10(AppEvent.Entry, {}),
1264
- /* @__PURE__ */ jsx10(AppEvent.System, { ...initialProps }),
1265
- /* @__PURE__ */ jsx10(Container, { ...initialProps, children: /* @__PURE__ */ jsx10(TDSProvider, { colorPreference: "light", token: { color: { primary: getAppsInTossGlobals().brandPrimaryColor } }, children: /* @__PURE__ */ jsx10(TDSContainer, { ...initialProps, children }) }) })
1296
+ /* @__PURE__ */ jsx11(AppEvent.StayTime, {}),
1297
+ /* @__PURE__ */ jsx11(AppEvent.Entry, {}),
1298
+ /* @__PURE__ */ jsx11(AppEvent.System, { ...initialProps }),
1299
+ /* @__PURE__ */ jsx11(Container, { ...initialProps, children: /* @__PURE__ */ jsx11(TDSProvider, { colorPreference: "light", token: { color: { primary: getAppsInTossGlobals().brandPrimaryColor } }, children: /* @__PURE__ */ jsx11(TDSContainer, { ...initialProps, children }) }) })
1266
1300
  ] });
1267
1301
  }
1268
1302
  function TDSContainer({ children }) {
1269
1303
  useAppsInTossBridge();
1270
- return /* @__PURE__ */ jsx10(Fragment7, { children });
1304
+ return /* @__PURE__ */ jsx11(Fragment7, { children });
1271
1305
  }
1272
1306
  function registerApp(container, { context, analytics }) {
1273
1307
  const appName = getAppName();
@@ -1294,7 +1328,7 @@ function registerApp(container, { context, analytics }) {
1294
1328
  }
1295
1329
  function AppsInTossScreenContainer({ children }) {
1296
1330
  const isRNApp = getAppsInTossGlobals().webViewType == null;
1297
- return /* @__PURE__ */ jsx10(Analytics.Screen, { children: isRNApp ? /* @__PURE__ */ jsx10(RNAppContainer, { children }) : children });
1331
+ return /* @__PURE__ */ jsx11(NavigationBarContextProvider, { children: /* @__PURE__ */ jsx11(Analytics.Screen, { children: isRNApp ? /* @__PURE__ */ jsx11(RNAppContainer, { children }) : children }) });
1298
1332
  }
1299
1333
  function getAppName() {
1300
1334
  try {
@@ -1312,10 +1346,10 @@ var AppsInToss = {
1312
1346
 
1313
1347
  // src/components/WebView.tsx
1314
1348
  import {
1349
+ AppsInTossModule,
1315
1350
  GoogleAdMob,
1316
1351
  IAP,
1317
1352
  Storage,
1318
- AppsInTossModule,
1319
1353
  appsInTossEvent as appsInTossEvent4,
1320
1354
  iapCreateOneTimePurchaseOrder,
1321
1355
  processProductGrant,
@@ -1324,10 +1358,11 @@ import {
1324
1358
  import * as appsInTossAsyncBridges from "@apps-in-toss/native-modules/async-bridges";
1325
1359
  import * as appsInTossConstantBridges from "@apps-in-toss/native-modules/constant-bridges";
1326
1360
  import * as appsInTossEventBridges from "@apps-in-toss/native-modules/event-bridges";
1361
+ import { useSafeAreaInsets as useSafeAreaInsets4 } from "@granite-js/native/react-native-safe-area-context";
1327
1362
  import { getSchemeUri as getSchemeUri6 } from "@granite-js/react-native";
1328
1363
  import { ExternalWebViewScreen, tdsEvent } from "@toss/tds-react-native";
1329
- import { useSafeAreaBottom, useSafeAreaTop as useSafeAreaTop3, useTopNavigation } from "@toss/tds-react-native/private";
1330
- import { useEffect as useEffect12, useMemo as useMemo6, useRef as useRef6, useState as useState7 } from "react";
1364
+ import { useSafeAreaBottom, useSafeAreaTop as useSafeAreaTop3 } from "@toss/tds-react-native/private";
1365
+ import { useEffect as useEffect14, useMemo as useMemo7, useRef as useRef6, useState as useState8 } from "react";
1331
1366
  import { BackHandler as BackHandler2, Platform as Platform6 } from "react-native";
1332
1367
 
1333
1368
  // src/components/GameWebView.tsx
@@ -1335,17 +1370,18 @@ import { setIosSwipeGestureEnabled as setIosSwipeGestureEnabled3, appsInTossEven
1335
1370
  import {
1336
1371
  WebView as PlainWebView
1337
1372
  } from "@granite-js/native/react-native-webview";
1338
- import { forwardRef, useEffect as useEffect10, useState as useState5 } from "react";
1373
+ import { forwardRef, useEffect as useEffect10, useState as useState6 } from "react";
1339
1374
  import { Platform as Platform5 } from "react-native";
1340
1375
 
1341
1376
  // src/components/NavigationBar/GameWebviewNavigationBar.tsx
1377
+ import { useSafeAreaInsets as useSafeAreaInsets2 } from "@granite-js/native/react-native-safe-area-context";
1342
1378
  import { closeView as closeView4 } from "@granite-js/react-native";
1343
1379
  import { PageNavbar as PageNavbar2, useDialog as useDialog5 } from "@toss/tds-react-native";
1344
1380
  import { NavigationRightContent as NavigationRightContent2, useSafeAreaTop as useSafeAreaTop2 } from "@toss/tds-react-native/private";
1345
1381
  import { josa as josa3 } from "es-hangul";
1346
1382
  import { useCallback as useCallback8 } from "react";
1347
1383
  import { Platform as Platform4, View as View3 } from "react-native";
1348
- import { Fragment as Fragment8, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
1384
+ import { Fragment as Fragment8, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
1349
1385
  function GameWebviewNavigationBar() {
1350
1386
  const safeAreaTop = useSafeAreaTop2();
1351
1387
  const { openConfirm } = useDialog5();
@@ -1353,8 +1389,8 @@ function GameWebviewNavigationBar() {
1353
1389
  const global2 = getAppsInTossGlobals();
1354
1390
  const logging = useNavigationBarLogging();
1355
1391
  const { open: openMoreButtonBottomSheet } = useMoreButtonBottomSheet();
1356
- const parsedNavigationBar = global2.navigationBar != null ? safeParseNavigationBar(global2.navigationBar) : null;
1357
- const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
1392
+ const { navigationRightButton } = useNavigationBarContext();
1393
+ const { right: safeAreaRight } = useSafeAreaInsets2();
1358
1394
  const handleGameWebviewClose = useCallback8(async () => {
1359
1395
  logging.closeButtonClick();
1360
1396
  const isConfirmed = await openConfirm({
@@ -1371,8 +1407,8 @@ function GameWebviewNavigationBar() {
1371
1407
  }
1372
1408
  }, [captureExitLog, global2.brandDisplayName, logging, openConfirm]);
1373
1409
  return /* @__PURE__ */ jsxs6(Fragment8, { children: [
1374
- /* @__PURE__ */ jsx11(PageNavbar2, { preference: { type: "none" } }),
1375
- /* @__PURE__ */ jsx11(
1410
+ /* @__PURE__ */ jsx12(PageNavbar2, { preference: { type: "none" } }),
1411
+ /* @__PURE__ */ jsx12(
1376
1412
  View3,
1377
1413
  {
1378
1414
  style: {
@@ -1385,13 +1421,13 @@ function GameWebviewNavigationBar() {
1385
1421
  position: "absolute",
1386
1422
  zIndex: Z_INDEX.CLOSE_BUTTON,
1387
1423
  marginTop: safeAreaTop,
1388
- paddingRight: 10
1424
+ paddingRight: safeAreaRight + 10
1389
1425
  },
1390
1426
  pointerEvents: "box-none",
1391
- children: /* @__PURE__ */ jsx11(
1427
+ children: /* @__PURE__ */ jsx12(
1392
1428
  NavigationRightContent2,
1393
1429
  {
1394
- fixedRightButton: initialAccessoryButton,
1430
+ fixedRightButton: navigationRightButton,
1395
1431
  onPressDots: openMoreButtonBottomSheet,
1396
1432
  onPressClose: () => {
1397
1433
  handleGameWebviewClose();
@@ -1405,9 +1441,9 @@ function GameWebviewNavigationBar() {
1405
1441
  }
1406
1442
 
1407
1443
  // src/components/GameWebView.tsx
1408
- import { Fragment as Fragment9, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1444
+ import { Fragment as Fragment9, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1409
1445
  var GameWebView = forwardRef(function GameWebView2(props, ref) {
1410
- const [isEntryMessageExited, setIsEntryMessageExited] = useState5(false);
1446
+ const [isEntryMessageExited, setIsEntryMessageExited] = useState6(false);
1411
1447
  useEffect10(() => {
1412
1448
  if (Platform5.OS === "ios") {
1413
1449
  setIosSwipeGestureEnabled3({ isEnabled: false });
@@ -1425,8 +1461,8 @@ var GameWebView = forwardRef(function GameWebView2(props, ref) {
1425
1461
  });
1426
1462
  }, []);
1427
1463
  return /* @__PURE__ */ jsxs7(Fragment9, { children: [
1428
- /* @__PURE__ */ jsx12(GameWebviewNavigationBar, {}),
1429
- getOperationalEnvironment3() === "toss" ? /* @__PURE__ */ jsx12(GameInitializer, { isReadyForProfileUI: isEntryMessageExited, children: /* @__PURE__ */ jsx12(PlainWebView, { ref, ...props }) }) : /* @__PURE__ */ jsx12(PlainWebView, { ref, ...props })
1464
+ /* @__PURE__ */ jsx13(GameWebviewNavigationBar, {}),
1465
+ getOperationalEnvironment3() === "toss" ? /* @__PURE__ */ jsx13(GameInitializer, { isReadyForProfileUI: isEntryMessageExited, children: /* @__PURE__ */ jsx13(PlainWebView, { ref, ...props }) }) : /* @__PURE__ */ jsx13(PlainWebView, { ref, ...props })
1430
1466
  ] });
1431
1467
  });
1432
1468
 
@@ -1442,7 +1478,7 @@ import { useDialog as useDialog6 } from "@toss/tds-react-native";
1442
1478
  import { NavigationBackButton as NavigationBackButton2, NavigationLeft as NavigationLeft2, TopNavigation as TopNavigation2 } from "@toss/tds-react-native/private";
1443
1479
  import { josa as josa4 } from "es-hangul";
1444
1480
  import { useCallback as useCallback9 } from "react";
1445
- import { jsx as jsx13 } from "react/jsx-runtime";
1481
+ import { jsx as jsx14 } from "react/jsx-runtime";
1446
1482
  function PartnerWebviewNavigationBar({ onBackButtonClick, onHomeButtonClick }) {
1447
1483
  const globals = getAppsInTossGlobals();
1448
1484
  const { captureExitLog } = useCaptureExitLog();
@@ -1452,7 +1488,7 @@ function PartnerWebviewNavigationBar({ onBackButtonClick, onHomeButtonClick }) {
1452
1488
  const parsedNavigationBar = globals.navigationBar != null ? safeParseNavigationBar(globals.navigationBar) : null;
1453
1489
  const withHomeButton = parsedNavigationBar?.withHomeButton ?? false;
1454
1490
  const withBackButton = parsedNavigationBar?.withBackButton ?? true;
1455
- const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
1491
+ const { navigationRightButton } = useNavigationBarContext();
1456
1492
  const handleClose = useCallback9(async () => {
1457
1493
  logging.closeButtonClick();
1458
1494
  const isConfirmed = await openConfirm({
@@ -1468,7 +1504,7 @@ function PartnerWebviewNavigationBar({ onBackButtonClick, onHomeButtonClick }) {
1468
1504
  closeView5();
1469
1505
  }
1470
1506
  }, [captureExitLog, globals.brandDisplayName, logging, openConfirm]);
1471
- return /* @__PURE__ */ jsx13(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx13(
1507
+ return /* @__PURE__ */ jsx14(NavigationBarImpressionArea, { withHomeButton, children: /* @__PURE__ */ jsx14(
1472
1508
  TopNavigation2,
1473
1509
  {
1474
1510
  title: globals.brandDisplayName,
@@ -1478,23 +1514,23 @@ function PartnerWebviewNavigationBar({ onBackButtonClick, onHomeButtonClick }) {
1478
1514
  onPressTitle: withHomeButton ? onHomeButtonClick : void 0,
1479
1515
  onPressClose: handleClose,
1480
1516
  withHome: withHomeButton,
1481
- fixedRightButton: initialAccessoryButton,
1482
- children: /* @__PURE__ */ jsx13(NavigationLeft2, { visible: withBackButton, children: /* @__PURE__ */ jsx13(NavigationBackButton2, { onPress: onBackButtonClick, canGoBack: false }) })
1517
+ fixedRightButton: navigationRightButton,
1518
+ children: /* @__PURE__ */ jsx14(NavigationLeft2, { visible: withBackButton, children: /* @__PURE__ */ jsx14(NavigationBackButton2, { onPress: onBackButtonClick, canGoBack: false }) })
1483
1519
  }
1484
1520
  ) });
1485
1521
  }
1486
1522
 
1487
1523
  // src/components/PartnerWebView.tsx
1488
- import { Fragment as Fragment10, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1524
+ import { Fragment as Fragment10, jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
1489
1525
  var PartnerWebView = forwardRef2(function PartnerWebViewScreen({ onBackButtonClick, onHomeButtonClick, ...webViewProps }, ref) {
1490
1526
  return /* @__PURE__ */ jsxs8(Fragment10, { children: [
1491
- /* @__PURE__ */ jsx14(PartnerWebviewNavigationBar, { onBackButtonClick, onHomeButtonClick }),
1492
- /* @__PURE__ */ jsx14(PlainWebView2, { ref, ...webViewProps, style: { flex: 1 } })
1527
+ /* @__PURE__ */ jsx15(PartnerWebviewNavigationBar, { onBackButtonClick, onHomeButtonClick }),
1528
+ /* @__PURE__ */ jsx15(PlainWebView2, { ref, ...webViewProps, style: { flex: 1 } })
1493
1529
  ] });
1494
1530
  });
1495
1531
 
1496
1532
  // src/bridge-handler/useBridgeHandler.tsx
1497
- import { useCallback as useCallback10, useMemo as useMemo3, useRef as useRef4 } from "react";
1533
+ import { useCallback as useCallback10, useEffect as useEffect11, useMemo as useMemo3, useRef as useRef4 } from "react";
1498
1534
  function serializeError(error) {
1499
1535
  return JSON.stringify(error, (_, value) => {
1500
1536
  if (value instanceof Error) {
@@ -1544,26 +1580,24 @@ function useBridgeHandler({
1544
1580
  onMessage,
1545
1581
  constantHandlerMap,
1546
1582
  asyncHandlerMap,
1547
- eventListenerMap,
1548
- injectedJavaScript: originalInjectedJavaScript
1583
+ eventListenerMap
1549
1584
  }) {
1550
1585
  const ref = useRef4(null);
1551
1586
  const injectedJavaScript = useMemo3(
1552
- () => [
1553
- `window.__CONSTANT_HANDLER_MAP = ${JSON.stringify(
1554
- Object.entries(constantHandlerMap).reduce(
1555
- (acc, [key, value]) => {
1556
- acc[key] = typeof value === "function" ? value() : value;
1557
- return acc;
1558
- },
1559
- {}
1560
- )
1561
- )};`,
1562
- originalInjectedJavaScript,
1563
- "true"
1564
- ].join("\n"),
1565
- [constantHandlerMap, originalInjectedJavaScript]
1587
+ () => `window.__CONSTANT_HANDLER_MAP = ${JSON.stringify(
1588
+ Object.entries(constantHandlerMap).reduce(
1589
+ (acc, [key, value]) => {
1590
+ acc[key] = typeof value === "function" ? value() : value;
1591
+ return acc;
1592
+ },
1593
+ {}
1594
+ )
1595
+ )};`,
1596
+ [constantHandlerMap]
1566
1597
  );
1598
+ useEffect11(() => {
1599
+ ref.current?.injectJavaScript(injectedJavaScript);
1600
+ }, [injectedJavaScript]);
1567
1601
  const createHandleOnEvent = (functionName, eventId) => (response) => {
1568
1602
  ref.current?.injectJavaScript(`
1569
1603
  window.__GRANITE_NATIVE_EMITTER.emit('${functionName}/onEvent/${eventId}', ${JSON.stringify(response, null, 0)});
@@ -1578,7 +1612,7 @@ function useBridgeHandler({
1578
1612
  const $onMessage = useCallback10(
1579
1613
  async (e) => {
1580
1614
  onMessage?.(e);
1581
- const data = JSON.parse(e.nativeEvent.data);
1615
+ const data = parseNativeEventData(e.nativeEvent.data);
1582
1616
  if (typeof data !== "object" || data === null || typeof data.functionName !== "string" || typeof data.eventId !== "string" || typeof data.type !== "string" || !["addEventListener", "removeEventListener", "method"].includes(data.type)) {
1583
1617
  return;
1584
1618
  }
@@ -1624,15 +1658,59 @@ function useBridgeHandler({
1624
1658
  onMessage: $onMessage
1625
1659
  };
1626
1660
  }
1661
+ function parseNativeEventData(data) {
1662
+ try {
1663
+ return JSON.parse(data);
1664
+ } catch (error) {
1665
+ console.error(error);
1666
+ return null;
1667
+ }
1668
+ }
1669
+
1670
+ // src/core/hooks/useSafeAreaInsetsEmitter.tsx
1671
+ import { useSafeAreaInsets as useSafeAreaInsets3 } from "@granite-js/native/react-native-safe-area-context";
1672
+ import { useEffect as useEffect12, useMemo as useMemo4 } from "react";
1673
+ var EventEmitter = class {
1674
+ listeners = {};
1675
+ on(event, listener) {
1676
+ if (!this.listeners[event]) {
1677
+ this.listeners[event] = [];
1678
+ }
1679
+ this.listeners[event].push(listener);
1680
+ }
1681
+ emit(event, ...args) {
1682
+ if (!this.listeners[event]) {
1683
+ return;
1684
+ }
1685
+ this.listeners[event].forEach((listener) => listener(...args));
1686
+ }
1687
+ off(event, listener) {
1688
+ if (!this.listeners[event]) {
1689
+ return;
1690
+ }
1691
+ this.listeners[event] = this.listeners[event].filter((l) => l !== listener);
1692
+ }
1693
+ };
1694
+ function useSafeAreaInsetsEmitter() {
1695
+ const insets = useSafeAreaInsets3();
1696
+ const emitter = useMemo4(() => new EventEmitter(), []);
1697
+ useEffect12(() => {
1698
+ emitter.emit("safeAreaInsetsChange", insets);
1699
+ return () => {
1700
+ emitter.off("safeAreaInsetsChange", (listener) => listener(insets));
1701
+ };
1702
+ }, [emitter, insets]);
1703
+ return emitter;
1704
+ }
1627
1705
 
1628
1706
  // src/core/hooks/useWebBackHandler.tsx
1629
1707
  import { closeView as closeView6, useBackEventState } from "@granite-js/react-native";
1630
1708
  import { useDialog as useDialog7 } from "@toss/tds-react-native";
1631
1709
  import { josa as josa5 } from "es-hangul";
1632
- import { useCallback as useCallback12, useMemo as useMemo5 } from "react";
1710
+ import { useCallback as useCallback12, useMemo as useMemo6 } from "react";
1633
1711
 
1634
1712
  // src/hooks/useWebviewHistoryStack.tsx
1635
- import { useCallback as useCallback11, useMemo as useMemo4, useReducer } from "react";
1713
+ import { useCallback as useCallback11, useMemo as useMemo5, useReducer } from "react";
1636
1714
  var INITIAL_STATE = { stack: [], index: -1 };
1637
1715
  function reducer(state, action) {
1638
1716
  switch (action.type) {
@@ -1667,7 +1745,7 @@ function useWebViewHistory() {
1667
1745
  const onNavigationStateChange = useCallback11(({ url, canGoForward: canGoForward2 }) => {
1668
1746
  dispatch({ type: "NAVIGATION_CHANGE", url, canGoForward: canGoForward2 });
1669
1747
  }, []);
1670
- const { canGoBack, canGoForward } = useMemo4(() => {
1748
+ const { canGoBack, canGoForward } = useMemo5(() => {
1671
1749
  const canBack = state.index > 0;
1672
1750
  const canFwd = state.index >= 0 && state.index < state.stack.length - 1;
1673
1751
  return { canGoBack: canBack, canGoForward: canFwd };
@@ -1755,7 +1833,7 @@ function useWebBackHandler(webViewRef) {
1755
1833
  }
1756
1834
  webViewRef.current?.injectJavaScript(HISTORY_HOME_SCRIPT);
1757
1835
  }, [hasWebBackEvent, webBackHandlersRef, logging, webViewRef]);
1758
- return useMemo5(
1836
+ return useMemo6(
1759
1837
  () => ({ addEventListener, removeEventListener, handleWebBack, handleWebHome, onNavigationStateChange }),
1760
1838
  [addEventListener, removeEventListener, handleWebBack, handleWebHome, onNavigationStateChange]
1761
1839
  );
@@ -1912,7 +1990,7 @@ function useCreateUserAgent({
1912
1990
  const platform = getPlatformOS();
1913
1991
  const appVersion = getTossAppVersion();
1914
1992
  const { fontScale } = useWindowDimensions();
1915
- const platformString = platform === "ios" ? "iPhone" : "Android";
1993
+ const platformString = platform === "ios" ? "iPhone" : "Android phone";
1916
1994
  const fontA11y = mapFontScaleToCategory(fontScale, platform);
1917
1995
  const normalizedFontScale = convertToAndroidStyleScale(fontScale, platform);
1918
1996
  return [
@@ -1933,11 +2011,11 @@ function useCreateUserAgent({
1933
2011
  // src/hooks/useGeolocation.ts
1934
2012
  import { startUpdateLocation } from "@apps-in-toss/native-modules";
1935
2013
  import { useVisibility as useVisibility3 } from "@granite-js/react-native";
1936
- import { useEffect as useEffect11, useState as useState6 } from "react";
2014
+ import { useEffect as useEffect13, useState as useState7 } from "react";
1937
2015
  function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1938
2016
  const isVisible = useVisibility3();
1939
- const [location, setLocation] = useState6(null);
1940
- useEffect11(() => {
2017
+ const [location, setLocation] = useState7(null);
2018
+ useEffect13(() => {
1941
2019
  if (!isVisible) {
1942
2020
  return;
1943
2021
  }
@@ -1984,6 +2062,15 @@ function useWaitForReturnNavigator() {
1984
2062
  return startNavigating;
1985
2063
  }
1986
2064
 
2065
+ // src/hooks/useTopNavigation.tsx
2066
+ function useTopNavigation() {
2067
+ const { addNavigationRightButton, removeNavigationRightButton } = useNavigationBarContext();
2068
+ return {
2069
+ addAccessoryButton: addNavigationRightButton,
2070
+ removeAccessoryButton: removeNavigationRightButton
2071
+ };
2072
+ }
2073
+
1987
2074
  // src/utils/log.ts
1988
2075
  import { eventLog as eventLogNative } from "@apps-in-toss/native-modules";
1989
2076
  import { getSchemeUri as getSchemeUri5 } from "@granite-js/react-native";
@@ -2034,7 +2121,7 @@ var trackScreen = (url) => {
2034
2121
  };
2035
2122
 
2036
2123
  // src/components/WebView.tsx
2037
- import { jsx as jsx15 } from "react/jsx-runtime";
2124
+ import { jsx as jsx16 } from "react/jsx-runtime";
2038
2125
  var operationalEnvironment = appsInTossConstantBridges.getOperationalEnvironment();
2039
2126
  var TYPES = ["partner", "external", "game"];
2040
2127
  var WEBVIEW_TYPES = {
@@ -2070,24 +2157,18 @@ function WebView({ type, local, onMessage, ...props }) {
2070
2157
  }
2071
2158
  const webViewRef = useRef6(null);
2072
2159
  const webBackHandler = useWebBackHandler(webViewRef);
2073
- const uri = useMemo6(() => getWebViewUri(local), [local]);
2160
+ const uri = useMemo7(() => getWebViewUri(local), [local]);
2074
2161
  const top = useSafeAreaTop3();
2075
2162
  const bottom = useSafeAreaBottom();
2163
+ const insets = useSafeAreaInsets4();
2076
2164
  const global2 = getAppsInTossGlobals();
2077
- const topNavigation = useTopNavigation();
2078
- const disableTextSelectionCSS = `
2079
- (function() {
2080
- const style = document.createElement('style');
2081
- style.textContent = '*:not(input):not(textarea) { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-touch-callout: none; }';
2082
- document.head.appendChild(style);
2083
- })();
2084
- `;
2085
- const [allowsBackForwardNavigationGestures, setAllowsBackForwardNavigationGestures] = useState7(
2165
+ const navigationBarContext = useNavigationBarContext();
2166
+ const safeAreaInsetsEmitter = useSafeAreaInsetsEmitter();
2167
+ const [allowsBackForwardNavigationGestures, setAllowsBackForwardNavigationGestures] = useState8(
2086
2168
  props.allowsBackForwardNavigationGestures
2087
2169
  );
2088
2170
  const handler = useBridgeHandler({
2089
2171
  onMessage,
2090
- injectedJavaScript: [disableTextSelectionCSS].join("\n"),
2091
2172
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2092
2173
  eventListenerMap: {
2093
2174
  ...appsInTossEventBridges,
@@ -2100,6 +2181,12 @@ function WebView({ type, local, onMessage, ...props }) {
2100
2181
  },
2101
2182
  entryMessageExited: ({ onEvent, onError }) => appsInTossEvent4.addEventListener("entryMessageExited", { onEvent, onError }),
2102
2183
  updateLocationEvent: ({ onEvent, onError, options }) => appsInTossEvent4.addEventListener("updateLocationEvent", { onEvent, onError, options }),
2184
+ safeAreaInsetsChange: ({ onEvent }) => {
2185
+ safeAreaInsetsEmitter.on("safeAreaInsetsChange", onEvent);
2186
+ return () => {
2187
+ safeAreaInsetsEmitter.off("safeAreaInsetsChange", onEvent);
2188
+ };
2189
+ },
2103
2190
  /** @internal */
2104
2191
  appBridgeCallbackEvent: ({ onEvent, onError, options }) => appsInTossEvent4.addEventListener("appBridgeCallbackEvent", { onEvent, onError, options }),
2105
2192
  /** AdMob */
@@ -2118,6 +2205,8 @@ function WebView({ type, local, onMessage, ...props }) {
2118
2205
  ...appsInTossConstantBridges,
2119
2206
  getSafeAreaTop: () => top,
2120
2207
  getSafeAreaBottom: () => bottom,
2208
+ getSafeAreaLeft: () => insets.left,
2209
+ getSafeAreaRight: () => insets.right,
2121
2210
  ...Object.fromEntries(Object.entries(global2).map(([key, value]) => [key, () => value])),
2122
2211
  /** AdMob */
2123
2212
  loadAdMobInterstitialAd_isSupported: GoogleAdMob.loadAdMobInterstitialAd.isSupported,
@@ -2136,8 +2225,8 @@ function WebView({ type, local, onMessage, ...props }) {
2136
2225
  setAllowsBackForwardNavigationGestures(options.isEnabled);
2137
2226
  return appsInTossAsyncBridges.setIosSwipeGestureEnabled(options);
2138
2227
  },
2139
- addAccessoryButton: async (params) => topNavigation.addAccessoryButton(params),
2140
- removeAccessoryButton: async () => topNavigation.removeAccessoryButton(),
2228
+ addAccessoryButton: async (params) => navigationBarContext.addNavigationRightButton(params),
2229
+ removeAccessoryButton: async () => navigationBarContext.removeNavigationRightButton(),
2141
2230
  /** permissions */
2142
2231
  requestPermission: appsInTossAsyncBridges.requestPermission,
2143
2232
  openPermissionDialog: appsInTossAsyncBridges.openPermissionDialog,
@@ -2162,7 +2251,7 @@ function WebView({ type, local, onMessage, ...props }) {
2162
2251
  completeProductGrant: IAP.completeProductGrant
2163
2252
  }
2164
2253
  });
2165
- const headerPropForExternalWebView = useMemo6(() => {
2254
+ const headerPropForExternalWebView = useMemo7(() => {
2166
2255
  const parsedNavigationBar = global2.navigationBar != null ? safeParseNavigationBar(global2.navigationBar) : null;
2167
2256
  const initialAccessoryButton = parsedNavigationBar?.initialAccessoryButton;
2168
2257
  const withBackButton = parsedNavigationBar?.withBackButton ?? true;
@@ -2183,7 +2272,7 @@ function WebView({ type, local, onMessage, ...props }) {
2183
2272
  colorPreference: "light"
2184
2273
  });
2185
2274
  const refs = mergeRefs(handler.ref, webViewRef);
2186
- useEffect12(() => {
2275
+ useEffect14(() => {
2187
2276
  const callback = () => {
2188
2277
  webBackHandler.handleWebBack();
2189
2278
  return true;
@@ -2191,7 +2280,8 @@ function WebView({ type, local, onMessage, ...props }) {
2191
2280
  BackHandler2.addEventListener("hardwareBackPress", callback);
2192
2281
  return () => BackHandler2.removeEventListener("hardwareBackPress", callback);
2193
2282
  }, [webBackHandler]);
2194
- return /* @__PURE__ */ jsx15(
2283
+ const globalScripts = useGlobalScripts();
2284
+ return /* @__PURE__ */ jsx16(
2195
2285
  BaseWebView,
2196
2286
  {
2197
2287
  ref: refs,
@@ -2218,17 +2308,78 @@ function WebView({ type, local, onMessage, ...props }) {
2218
2308
  webviewDebuggingEnabled: webViewDebuggingEnabled,
2219
2309
  thirdPartyCookiesEnabled: true,
2220
2310
  onMessage: handler.onMessage,
2221
- injectedJavaScript: handler.injectedJavaScript,
2222
- injectedJavaScriptBeforeContentLoaded: handler.injectedJavaScript,
2311
+ injectedJavaScript: globalScripts.afterLoad,
2312
+ injectedJavaScriptBeforeContentLoaded: mergeScripts(handler.injectedJavaScript, globalScripts.beforeLoad),
2223
2313
  decelerationRate: Platform6.OS === "ios" ? 1 : void 0,
2224
2314
  allowsBackForwardNavigationGestures
2225
2315
  }
2226
2316
  );
2227
2317
  }
2318
+ function useGlobalScripts() {
2319
+ const global2 = getAppsInTossGlobals();
2320
+ const disableTextSelectionCSS = `
2321
+ const style = document.createElement('style');
2322
+ style.textContent = '*:not(input):not(textarea) { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-touch-callout: none; }';
2323
+ document.head.appendChild(style);
2324
+ `;
2325
+ const applyGameResourcesCache = `
2326
+ (function () {
2327
+ if (typeof caches === 'undefined') {
2328
+ return;
2329
+ }
2330
+ const cacheKeyPrefix = '@apps-in-toss/caches/';
2331
+ const cacheKey = \`\${cacheKeyPrefix}${global2.deploymentId}\`;
2332
+ window.addEventListener('load', async () => {
2333
+ const keys = await caches.keys();
2334
+ for (const key of keys) {
2335
+ if (key.startsWith(cacheKeyPrefix) && key !== cacheKey) {
2336
+ await caches.delete(key);
2337
+ }
2338
+ }
2339
+ });
2340
+ window.fetch = new Proxy(window.fetch, {
2341
+ async apply(originalFetch, thisArg, args) {
2342
+ const request = new Request(args[0], args[1]);
2343
+ if (!/\\.(data|wasm|framework\\.js)(?:\\.gz|\\.br|\\.unityweb)?$/.test(request.url)) {
2344
+ return await originalFetch.call(thisArg, request);
2345
+ }
2346
+ const cache = await caches.open(cacheKey);
2347
+ const cached = await cache.match(request);
2348
+ if (cached) {
2349
+ const eTag = cached.headers.get('ETag');
2350
+ const lastModified = cached.headers.get('Last-Modified');
2351
+ if (eTag) {
2352
+ request.headers.set('If-None-Match', eTag);
2353
+ }
2354
+ if (lastModified) {
2355
+ request.headers.set('If-Modified-Since', lastModified);
2356
+ }
2357
+ const revalidated = await originalFetch.call(thisArg, request);
2358
+ if (revalidated.status === 304) {
2359
+ return cached;
2360
+ }
2361
+ cache.put(request, revalidated.clone());
2362
+ return revalidated;
2363
+ }
2364
+ const response = await originalFetch.call(thisArg, request);
2365
+ cache.put(request, response.clone());
2366
+ return response;
2367
+ },
2368
+ });
2369
+ })();
2370
+ `;
2371
+ return {
2372
+ beforeLoad: mergeScripts(global2.webViewType === "game" && applyGameResourcesCache),
2373
+ afterLoad: mergeScripts(disableTextSelectionCSS)
2374
+ };
2375
+ }
2376
+ function mergeScripts(...scripts) {
2377
+ return scripts.filter((script) => typeof script === "string").join("\n");
2378
+ }
2228
2379
 
2229
2380
  // src/index.ts
2230
2381
  export * from "@apps-in-toss/analytics";
2231
- import { useTopNavigation as useTopNavigation2, useOverlay as useOverlay3, OverlayProvider } from "@toss/tds-react-native/private";
2382
+ import { useOverlay as useOverlay3, OverlayProvider } from "@toss/tds-react-native/private";
2232
2383
  export * from "@apps-in-toss/native-modules";
2233
2384
  export * from "@apps-in-toss/types";
2234
2385
  var Analytics2 = {
@@ -2247,6 +2398,6 @@ export {
2247
2398
  useCreateUserAgent,
2248
2399
  useGeolocation,
2249
2400
  useOverlay3 as useOverlay,
2250
- useTopNavigation2 as useTopNavigation,
2401
+ useTopNavigation,
2251
2402
  useWaitForReturnNavigator
2252
2403
  };