@apps-in-toss/framework 0.0.0-dev.1747216176095 → 0.0.0-dev.1752114017143

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.cjs CHANGED
@@ -35,6 +35,8 @@ __export(src_exports, {
35
35
  Analytics: () => Analytics2,
36
36
  AppsInToss: () => AppsInToss,
37
37
  GoogleAdMob: () => GoogleAdMob,
38
+ IAP: () => IAP,
39
+ INTERNAL__onVisibilityChangedByTransparentServiceWeb: () => INTERNAL__onVisibilityChangedByTransparentServiceWeb,
38
40
  Storage: () => Storage,
39
41
  TossPay: () => TossPay,
40
42
  WebView: () => WebView,
@@ -52,7 +54,9 @@ __export(src_exports, {
52
54
  getTossShareLink: () => getTossShareLink,
53
55
  isMinVersionSupported: () => isMinVersionSupported,
54
56
  openCamera: () => openCamera,
57
+ saveBase64Data: () => saveBase64Data,
55
58
  setClipboardText: () => setClipboardText,
59
+ setDeviceOrientation: () => setDeviceOrientation,
56
60
  startUpdateLocation: () => startUpdateLocation,
57
61
  useGeolocation: () => useGeolocation
58
62
  });
@@ -62,7 +66,7 @@ var import_analytics2 = require("@apps-in-toss/analytics");
62
66
  // src/core/registerApp.tsx
63
67
  var import_analytics = require("@apps-in-toss/analytics");
64
68
  var import_react_native6 = require("@toss-design-system/react-native");
65
- var import_react_native_bedrock7 = require("react-native-bedrock");
69
+ var import_react_native_bedrock8 = require("react-native-bedrock");
66
70
 
67
71
  // src/core/components/AppEvent.tsx
68
72
  var import_react2 = require("react");
@@ -260,7 +264,7 @@ var import_react_native5 = require("@toss-design-system/react-native");
260
264
  var import_react3 = require("react");
261
265
 
262
266
  // src/native-event-emitter/appsInTossEvent.ts
263
- var import_react_native_bedrock6 = require("react-native-bedrock");
267
+ var import_react_native_bedrock7 = require("react-native-bedrock");
264
268
 
265
269
  // src/native-event-emitter/event-plugins/EntryMessageExitedEvent.ts
266
270
  var import_react_native_bedrock3 = require("react-native-bedrock");
@@ -419,11 +423,39 @@ var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends import_react_
419
423
  }
420
424
  };
421
425
 
426
+ // src/native-event-emitter/internal/VisibilityChangedByTransparentServiceWebEvent.ts
427
+ var import_react_native_bedrock6 = require("react-native-bedrock");
428
+ var VisibilityChangedByTransparentServiceWebEvent = class extends import_react_native_bedrock6.BedrockEventDefinition {
429
+ name = "onVisibilityChangedByTransparentServiceWeb";
430
+ subscription = null;
431
+ remove() {
432
+ this.subscription?.remove();
433
+ this.subscription = null;
434
+ }
435
+ listener(options, onEvent, onError) {
436
+ const subscription = nativeEventEmitter.addListener("visibilityChangedByTransparentServiceWeb", (params) => {
437
+ if (this.isVisibilityChangedByTransparentServiceWebResult(params)) {
438
+ if (params.callbackId === options.callbackId) {
439
+ onEvent(params.isVisible);
440
+ }
441
+ } else {
442
+ onError(new Error("Invalid visibility changed by transparent service web result"));
443
+ }
444
+ });
445
+ this.subscription = subscription;
446
+ }
447
+ isVisibilityChangedByTransparentServiceWebResult(params) {
448
+ return typeof params === "object" && typeof params.callbackId === "string" && typeof params.isVisible === "boolean";
449
+ }
450
+ };
451
+
422
452
  // src/native-event-emitter/appsInTossEvent.ts
423
- var appsInTossEvent = new import_react_native_bedrock6.BedrockEvent([
424
- new AppBridgeCallbackEvent(),
453
+ var appsInTossEvent = new import_react_native_bedrock7.BedrockEvent([
425
454
  new UpdateLocationEvent(),
426
- new EntryMessageExitedEvent()
455
+ new EntryMessageExitedEvent(),
456
+ // Internal events
457
+ new AppBridgeCallbackEvent(),
458
+ new VisibilityChangedByTransparentServiceWebEvent()
427
459
  ]);
428
460
 
429
461
  // src/core/utils/getAppsInTossGlobals.ts
@@ -471,7 +503,9 @@ __export(async_bridges_exports, {
471
503
  getCurrentLocation: () => getCurrentLocation,
472
504
  getTossShareLink: () => getTossShareLink,
473
505
  openCamera: () => openCamera,
474
- setClipboardText: () => setClipboardText
506
+ saveBase64Data: () => saveBase64Data,
507
+ setClipboardText: () => setClipboardText,
508
+ setDeviceOrientation: () => setDeviceOrientation
475
509
  });
476
510
 
477
511
  // src/native-modules/setClipboardText.ts
@@ -598,6 +632,31 @@ async function getTossShareLink(path) {
598
632
  return shareUrl.toString();
599
633
  }
600
634
 
635
+ // src/native-modules/setDeviceOrientation.ts
636
+ async function setDeviceOrientation(options) {
637
+ const isSupported = isMinVersionSupported({
638
+ android: "5.215.0",
639
+ ios: "5.215.0"
640
+ });
641
+ if (!isSupported) {
642
+ return;
643
+ }
644
+ return AppsInTossModule.setDeviceOrientation(options);
645
+ }
646
+
647
+ // src/native-modules/saveBase64Data.ts
648
+ async function saveBase64Data(params) {
649
+ const isSupported = isMinVersionSupported({
650
+ android: "5.218.0",
651
+ ios: "5.216.0"
652
+ });
653
+ if (!isSupported) {
654
+ console.warn("saveBase64Data is not supported in this app version");
655
+ return;
656
+ }
657
+ await AppsInTossModule.saveBase64Data(params);
658
+ }
659
+
601
660
  // src/core/registerApp.tsx
602
661
  var import_jsx_runtime = require("react/jsx-runtime");
603
662
  function AppsInTossContainer(Container, { children, ...initialProps }) {
@@ -616,7 +675,7 @@ function registerApp(container, { context, analytics }) {
616
675
  logger: (params) => void eventLog(params),
617
676
  debug: analytics?.debug ?? __DEV__
618
677
  });
619
- return import_react_native_bedrock7.Bedrock.registerApp(AppsInTossContainer.bind(null, container), {
678
+ return import_react_native_bedrock8.Bedrock.registerApp(AppsInTossContainer.bind(null, container), {
620
679
  appName: getAppName(),
621
680
  context,
622
681
  router: {
@@ -739,7 +798,6 @@ var ENVIRONMENT = getOperationalEnvironment();
739
798
  function createIsSupported() {
740
799
  return () => {
741
800
  if (ENVIRONMENT !== "toss") {
742
- console.warn("Google AdMob is not supported in the current environment");
743
801
  return false;
744
802
  }
745
803
  return isMinVersionSupported({
@@ -786,6 +844,32 @@ var Storage = {
786
844
  clearItems
787
845
  };
788
846
 
847
+ // src/native-modules/iap.ts
848
+ async function createOneTimePurchaseOrder(params) {
849
+ const isSupported = isMinVersionSupported({
850
+ android: "5.219.0",
851
+ ios: "5.219.0"
852
+ });
853
+ if (!isSupported) {
854
+ return;
855
+ }
856
+ return AppsInTossModule.iapCreateOneTimePurchaseOrder(params);
857
+ }
858
+ async function getProductItemList() {
859
+ const isSupported = isMinVersionSupported({
860
+ android: "5.219.0",
861
+ ios: "5.219.0"
862
+ });
863
+ if (!isSupported) {
864
+ return;
865
+ }
866
+ return AppsInTossModule.iapGetProductItemList({});
867
+ }
868
+ var IAP = {
869
+ createOneTimePurchaseOrder,
870
+ getProductItemList
871
+ };
872
+
789
873
  // src/native-modules/index.ts
790
874
  var TossPay = {
791
875
  checkoutPayment
@@ -801,7 +885,7 @@ var GoogleAdMob = {
801
885
  var import_react_native14 = require("@toss-design-system/react-native");
802
886
  var import_private = require("@toss-design-system/react-native/private");
803
887
  var import_react6 = require("react");
804
- var import_react_native_bedrock10 = require("react-native-bedrock");
888
+ var import_react_native_bedrock11 = require("react-native-bedrock");
805
889
  var bedrockAsyncBridges = __toESM(require("react-native-bedrock/async-bridges"), 1);
806
890
  var bedrockConstantBridges = __toESM(require("react-native-bedrock/constant-bridges"), 1);
807
891
 
@@ -811,7 +895,7 @@ var import_react_native12 = require("@toss-design-system/react-native");
811
895
  var import_es_hangul = require("es-hangul");
812
896
  var import_react4 = require("react");
813
897
  var import_react_native13 = require("react-native");
814
- var import_react_native_bedrock8 = require("react-native-bedrock");
898
+ var import_react_native_bedrock9 = require("react-native-bedrock");
815
899
 
816
900
  // src/components/GameWebViewNavigationBar/GameNavigationBar.tsx
817
901
  var import_react_native_svg = require("@react-native-bedrock/native/react-native-svg");
@@ -922,14 +1006,14 @@ var GameWebView = (0, import_react4.forwardRef)(function GameWebView2(props, ref
922
1006
  closeOnDimmerClick: true
923
1007
  });
924
1008
  if (isConfirmed) {
925
- (0, import_react_native_bedrock8.closeView)();
1009
+ (0, import_react_native_bedrock9.closeView)();
926
1010
  }
927
1011
  }, [brandDisplayName, openConfirm]);
928
1012
  (0, import_react4.useEffect)(() => {
929
1013
  if (import_react_native13.Platform.OS === "ios") {
930
- (0, import_react_native_bedrock8.setIosSwipeGestureEnabled)({ isEnabled: false });
1014
+ (0, import_react_native_bedrock9.setIosSwipeGestureEnabled)({ isEnabled: false });
931
1015
  return () => {
932
- (0, import_react_native_bedrock8.setIosSwipeGestureEnabled)({ isEnabled: true });
1016
+ (0, import_react_native_bedrock9.setIosSwipeGestureEnabled)({ isEnabled: true });
933
1017
  };
934
1018
  }
935
1019
  return;
@@ -1092,7 +1176,7 @@ __export(event_bridges_exports, {
1092
1176
  });
1093
1177
 
1094
1178
  // src/utils/log.ts
1095
- var import_react_native_bedrock9 = require("react-native-bedrock");
1179
+ var import_react_native_bedrock10 = require("react-native-bedrock");
1096
1180
 
1097
1181
  // src/utils/extractDateFromUUIDv7.ts
1098
1182
  var extractDateFromUUIDv7 = (uuid) => {
@@ -1118,7 +1202,7 @@ var getGroupId = (url) => {
1118
1202
  };
1119
1203
  var getReferrer = () => {
1120
1204
  try {
1121
- const referrer = new URL((0, import_react_native_bedrock9.getSchemeUri)());
1205
+ const referrer = new URL((0, import_react_native_bedrock10.getSchemeUri)());
1122
1206
  return referrer.searchParams.get("referrer");
1123
1207
  } catch {
1124
1208
  return "";
@@ -1151,7 +1235,7 @@ var WEBVIEW_TYPES = {
1151
1235
  };
1152
1236
  function mergeSchemeQueryParamsInto(url) {
1153
1237
  const baseUrl = new URL(url);
1154
- const schemeUrl = new URL((0, import_react_native_bedrock10.getSchemeUri)());
1238
+ const schemeUrl = new URL((0, import_react_native_bedrock11.getSchemeUri)());
1155
1239
  baseUrl.pathname = schemeUrl.pathname;
1156
1240
  for (const [key, value] of schemeUrl.searchParams.entries()) {
1157
1241
  baseUrl.searchParams.set(key, value);
@@ -1175,7 +1259,7 @@ function WebView({ type, local, onMessage, ...props }) {
1175
1259
  if (!TYPES.includes(type)) {
1176
1260
  throw new Error(`Invalid WebView type: '${type}'`);
1177
1261
  }
1178
- const bedrockEvent = (0, import_react_native_bedrock10.useBedrockEvent)();
1262
+ const bedrockEvent = (0, import_react_native_bedrock11.useBedrockEvent)();
1179
1263
  const uri = (0, import_react6.useMemo)(() => getWebViewUri(local), [local]);
1180
1264
  const top = (0, import_private.useSafeAreaTop)();
1181
1265
  const bottom = (0, import_private.useSafeAreaBottom)();
@@ -1217,7 +1301,10 @@ function WebView({ type, local, onMessage, ...props }) {
1217
1301
  getStorageItem: Storage.getItem,
1218
1302
  setStorageItem: Storage.setItem,
1219
1303
  removeStorageItem: Storage.removeItem,
1220
- clearItems: Storage.clearItems
1304
+ clearItems: Storage.clearItems,
1305
+ /** IAP */
1306
+ iapCreateOneTimePurchaseOrder: IAP.createOneTimePurchaseOrder,
1307
+ iapGetProductItemList: IAP.getProductItemList
1221
1308
  }
1222
1309
  });
1223
1310
  const baseProps = (0, import_react6.useMemo)(() => {
@@ -1282,9 +1369,9 @@ function ensureValue(value, name) {
1282
1369
 
1283
1370
  // src/hooks/useGeolocation.ts
1284
1371
  var import_react7 = require("react");
1285
- var import_react_native_bedrock11 = require("react-native-bedrock");
1372
+ var import_react_native_bedrock12 = require("react-native-bedrock");
1286
1373
  function useGeolocation({ accuracy, distanceInterval, timeInterval }) {
1287
- const isVisible = (0, import_react_native_bedrock11.useVisibility)();
1374
+ const isVisible = (0, import_react_native_bedrock12.useVisibility)();
1288
1375
  const [location, setLocation] = (0, import_react7.useState)(null);
1289
1376
  (0, import_react7.useEffect)(() => {
1290
1377
  if (!isVisible) {
@@ -1314,6 +1401,14 @@ var Accuracy2 = /* @__PURE__ */ ((Accuracy3) => {
1314
1401
  return Accuracy3;
1315
1402
  })(Accuracy2 || {});
1316
1403
 
1404
+ // src/native-event-emitter/internal/onVisibilityChangedByTransparentServiceWeb.ts
1405
+ function onVisibilityChangedByTransparentServiceWeb(eventParams) {
1406
+ return appsInTossEvent.addEventListener("onVisibilityChangedByTransparentServiceWeb", eventParams);
1407
+ }
1408
+
1409
+ // src/private.ts
1410
+ var INTERNAL__onVisibilityChangedByTransparentServiceWeb = onVisibilityChangedByTransparentServiceWeb;
1411
+
1317
1412
  // src/index.ts
1318
1413
  __reExport(src_exports, require("@apps-in-toss/analytics"), module.exports);
1319
1414
  var Analytics2 = {
@@ -1328,6 +1423,8 @@ var Analytics2 = {
1328
1423
  Analytics,
1329
1424
  AppsInToss,
1330
1425
  GoogleAdMob,
1426
+ IAP,
1427
+ INTERNAL__onVisibilityChangedByTransparentServiceWeb,
1331
1428
  Storage,
1332
1429
  TossPay,
1333
1430
  WebView,
@@ -1345,7 +1442,9 @@ var Analytics2 = {
1345
1442
  getTossShareLink,
1346
1443
  isMinVersionSupported,
1347
1444
  openCamera,
1445
+ saveBase64Data,
1348
1446
  setClipboardText,
1447
+ setDeviceOrientation,
1349
1448
  startUpdateLocation,
1350
1449
  useGeolocation,
1351
1450
  ...require("@apps-in-toss/analytics")
package/dist/index.d.cts CHANGED
@@ -1652,6 +1652,268 @@ declare function eventLog(params: EventLogParams): Promise<void>;
1652
1652
  */
1653
1653
  declare function getTossShareLink(path: string): Promise<string>;
1654
1654
 
1655
+ /**
1656
+ * @public
1657
+ * @category 화면 제어
1658
+ * @kind function
1659
+ * @name setDeviceOrientation
1660
+ * @description
1661
+ * `setDeviceOrientation` 함수는 기기의 화면 방향을 설정하는 기능을 제공해요.
1662
+ * 이 기능은 특정 화면에서 가로 모드나 세로 모드를 강제로 지정해야 할 때 유용해요.
1663
+ *
1664
+ * `type` 옵션을 통해 원하는 화면 방향을 지정할 수 있어요. 특히, 이 함수는 앱 전체에 영향을 미치므로
1665
+ * 특정 화면에서만 사용하려면 화면을 벗어날 때 이전 상태로 복구하는 추가 작업이 필요해요.
1666
+ *
1667
+ * 예를 들어, 동영상 감상 화면에서는 가로 모드를 강제하고, 화면을 떠날 때 설정을 복구해서
1668
+ * 다른 화면들의 방향 설정에 영향을 주지 않도록 할 수 있어요.
1669
+ *
1670
+ * @param {object} options 화면 방향 설정 값이에요.
1671
+ * @param {string} options.type 화면 방향을 지정하는 옵션이에요.
1672
+ * 'portrait' | 'landscape' 중 하나를 선택할 수 있어요.
1673
+ *
1674
+ * @returns {Promise<void>} 화면 방향 설정이 완료되면 해결되는 Promise를 반환해요.
1675
+ *
1676
+ * @example
1677
+ * ### 화면 방향 설정하기
1678
+ *
1679
+ * ```tsx
1680
+ * import { Button } from 'react-native';
1681
+ * import { setDeviceOrientation } from '@apps-in-toss/framework';
1682
+ *
1683
+ * function SetDeviceOrientation() {
1684
+ * return (
1685
+ * <Button
1686
+ * title="가로 모드로 변경"
1687
+ * onPress={() => {
1688
+ * setDeviceOrientation({ type: 'landscape' });
1689
+ * }}
1690
+ * />
1691
+ * );
1692
+ * }
1693
+ * ```
1694
+ *
1695
+ * ### 화면 방향 복구하기
1696
+ * 특정 화면을 벗어날 때 이전 상태로 복구하려면 다음과 같이 `useEffect`를 사용하세요.
1697
+ *
1698
+ * ```tsx
1699
+ * import { useEffect } from 'react';
1700
+ * import { setDeviceOrientation } from '@apps-in-toss/framework';
1701
+ *
1702
+ * function VideoScreen() {
1703
+ * useEffect(() => {
1704
+ * setDeviceOrientation({ type: 'landscape' });
1705
+ *
1706
+ * return () => {
1707
+ * setDeviceOrientation({ type: 'portrait' }); // 설정을 이전 상태로 복구해요.
1708
+ * };
1709
+ * }, []);
1710
+ *
1711
+ * return <Text>동영상을 감상하는 화면</Text>;
1712
+ * }
1713
+ * ```
1714
+ */
1715
+ declare function setDeviceOrientation(options: {
1716
+ type: 'portrait' | 'landscape';
1717
+ }): Promise<void>;
1718
+
1719
+ interface SaveBase64DataParams {
1720
+ data: string;
1721
+ fileName: string;
1722
+ mimeType: string;
1723
+ }
1724
+ /**
1725
+ * @public
1726
+ * @category 데이터
1727
+ * @name saveBase64Data
1728
+ * @description 문자열로 인코딩된 Base64 데이터를 지정한 파일 이름과 MIME 타입으로 사용자 기기에 저장해요. 이미지, 텍스트, PDF 등 다양한 형식의 데이터를 저장할 수 있어요.
1729
+ * @param {SaveBase64DataParams} params - 저장할 데이터와 파일 정보를 담은 객체예요.
1730
+ * @param {string} params.data - Base64 형식으로 인코딩된 데이터 문자열이에요.
1731
+ * @param {string} params.fileName - 저장할 파일 이름이에요. 확장자도 같이 붙여줘야해요. 예를 들어, 'example.png'로 저장할 수 있어요.
1732
+ * @param {string} params.mimeType - 저장할 파일의 MIME 타입이에요. 예를 들어 'image/png' 로 지정하면 이미지, 'application/pdf'는 PDF 파일이에요. 자세한 내용은 [MIME 문서](https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/MIME_types)를 참고해주세요.
1733
+ *
1734
+ * @example
1735
+ * ### Base64 이미지 데이터를 사용자 기기에 저장하기
1736
+ *
1737
+ * ```tsx
1738
+ * import { Button } from 'react-native';
1739
+ * import { saveBase64Data } from '@apps-in-toss/framework';
1740
+ *
1741
+ * // '저장' 버튼을 누르면 이미지가 사용자 기기에 저장돼요.
1742
+ * function SaveButton() {
1743
+ * const handleSave = async () => {
1744
+ * try {
1745
+ * await saveBase64Data({
1746
+ * data: 'iVBORw0KGgo...',
1747
+ * fileName: 'some-photo.png',
1748
+ * mimeType: 'image/png',
1749
+ * });
1750
+ * } catch (error) {
1751
+ * console.error('데이터 저장에 실패했어요:', error);
1752
+ * }
1753
+ * };
1754
+ *
1755
+ * return <Button title="저장" onPress={handleSave} />;
1756
+ * }
1757
+ * ```
1758
+ */
1759
+ declare function saveBase64Data(params: SaveBase64DataParams): Promise<void>;
1760
+
1761
+ /**
1762
+ * @public
1763
+ * @category 인앱결제
1764
+ * @name IapCreateOneTimePurchaseOrderOptions
1765
+ * @description 인앱결제 1건을 요청할 때 필요한 정보예요.
1766
+ * @property {string} productId - 주문할 상품의 ID예요.
1767
+ */
1768
+ interface IapCreateOneTimePurchaseOrderOptions {
1769
+ productId: string;
1770
+ }
1771
+ /**
1772
+ * @public
1773
+ * @category 인앱결제
1774
+ * @name IapCreateOneTimePurchaseOrderResult
1775
+ * @description 인앱결제 1건이 완료되면 결제 세부 정보와 상품 정보를 담아 반환해요. 반환된 정보로 결제한 상품의 정보를 화면에 표시할 수 있어요.
1776
+ * @property {string | null} miniAppIconUrl - 미니앱 아이콘 이미지의 URL이에요. 아이콘은 앱인토스 콘솔에서 설정한 이미지예요. 콘솔에서 아이콘을 등록하지 않았다면 `null`로 반환돼요.
1777
+ * @property {string} displayName - 화면에 표시할 상품 이름이에요.
1778
+ * @property {string} displayAmount - 통화 단위가 포함된 가격 정보예요. 예를 들어 `1,000원`으로 가격과 통화가 함께 표시돼요.
1779
+ * @property {number} amount - 상품 가격 숫자 값이에요. 화폐 단위와 쉼표를 제외한 순수 숫자예요. 예를 들어 `1000`으로 표시돼요.
1780
+ * @property {string} currency - [ISO 4217 표준](https://ko.wikipedia.org/wiki/ISO_4217)에 따른 상품 가격 통화 단위예요. 예를 들어 원화는 `KRW`, 달러는 `USD`로 표시돼요.
1781
+ * @property {number} fraction - 가격을 표시할 때 소수점 아래 몇 자리까지 보여줄지 정하는 값이에요. 예를 들어 달러는 소수점 둘째 자리까지 보여줘서 `2`, 원화는 소수점이 필요 없어서 `0`이에요
1782
+ */
1783
+ interface IapCreateOneTimePurchaseOrderResult {
1784
+ miniAppIconUrl: string | null;
1785
+ displayName: string;
1786
+ displayAmount: string;
1787
+ amount: number;
1788
+ currency: string;
1789
+ fraction: number;
1790
+ }
1791
+ /**
1792
+ * @public
1793
+ * @category 인앱결제
1794
+ * @name iapCreateOneTimePurchaseOrder
1795
+ * @description
1796
+ * 특정 인앱결제 주문서 페이지로 이동해요. 사용자가 상품 구매 버튼을 누르는 상황 등에 사용할 수 있어요. 사용자의 결제는 이동한 페이지에서 진행돼요. 만약 결제 중에 에러가 발생하면 에러 유형에 따라 에러 페이지로 이동해요.
1797
+ * @param {IapCreateOneTimePurchaseOrderOptions} params - 인앱결제를 생성할 때 필요한 정보예요.
1798
+ * @param {string} params.productId - 주문할 상품의 ID예요.
1799
+ * @returns {Promise<IapCreateOneTimePurchaseOrderResult | undefined>} 결제에 성공하면 결제 결과 객체를 반환해요. 앱 버전이 최소 지원 버전(안드로이드 5.219.0, iOS 5.219.0)보다 낮으면 인앱결제를 실행할 수 없어서 `undefined`를 반환해요.
1800
+ *
1801
+ * @throw {code: "INVALID_PRODUCT_ID"} - 유효하지 않은 상품 ID이거나, 해당 상품이 존재하지 않을 때 발생해요.
1802
+ * @throw {code: "PAYMENT_PENDING"} - 사용자가 요청한 결제가 아직 승인을 기다리고 있을 때 발생해요.
1803
+ * @throw {code: "NETWORK_ERROR"} - 서버 내부 문제로 요청을 처리할 수 없을 때 발생해요.
1804
+ * @throw {code: "INVALID_USER_ENVIRONMENT"} - 특정 기기, 계정 또는 설정 환경에서 구매할 수 없는 상품일 때 발생해요.
1805
+ * @throw {code: "ITEM_ALREADY_OWNED"} - 사용자가 이미 구매한 상품을 다시 구매하려고 할 때 발생해요.
1806
+ * @throw {code: "APP_MARKET_VERIFICATION_FAILED"} - 사용자가 결제를 완료했지만, 앱스토어에서 사용자 정보 검증에 실패했을 때 발생해요. 사용자가 앱스토어에 문의해서 환불을 요청해야해요.
1807
+ * @throw {code: "TOSS_SERVER_VERIFICATION_FAILED"} - 사용자가 결제를 완료했지만, 서버 전송에 실패해서 결제 정보를 저장할 수 없을 때 발생해요.
1808
+ * @throw {code: "INTERNAL_ERROR"} - 서버 내부 문제로 요청을 처리할 수 없을 때 발생해요.
1809
+ * @throw {code: "KOREAN_ACCOUNT_ONLY"} - iOS 환경에서 사용자의 계정이 한국 계정이 아닐 때 발생해요.
1810
+ * @throw {code: "USER_CANCELED"} - 사용자가 결제를 완료하지 않고 주문서 페이지를 이탈했을 때 발생해요.
1811
+ *
1812
+ * @example
1813
+ * ### 특정 인앱결제 주문서 페이지로 이동하기
1814
+ *
1815
+ * ```tsx
1816
+ * import { Button } from 'react-native';
1817
+ * import { IAP } from '@apps-in-toss/framework';
1818
+ *
1819
+ * interface Props {
1820
+ * productId: string;
1821
+ * }
1822
+ *
1823
+ * function IapCreateOneTimePurchaseOrderButton({ productId }: Props) {
1824
+ * const handleClick = async () => {
1825
+ * try {
1826
+ * await IAP.createOneTimePurchaseOrder({
1827
+ * productId,
1828
+ * });
1829
+ * } catch (error) {
1830
+ * console.error('인앱결제에 실패했어요:', error);
1831
+ * }
1832
+ * };
1833
+ *
1834
+ * return <Button title="구매하기" onPress={handleClick} />;
1835
+ * }
1836
+ * ```
1837
+ */
1838
+ declare function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions): Promise<IapCreateOneTimePurchaseOrderResult | undefined>;
1839
+ /**
1840
+ * @public
1841
+ * @category 인앱결제
1842
+ * @name IapProductListItem
1843
+ * @description 인앱결제로 구매할 수 있는 상품 하나의 정보를 담은 객체예요. 상품 목록을 화면에 표시할 때 사용해요.
1844
+ * @property {string} sku - 상품의 고유 ID예요. [인앱결제 주문서 페이지로 이동할때](/bedrock/reference/framework/인앱결제/createOneTimePurchaseOrder.html) 사용하는 `productId`와 동일한 값이에요.
1845
+ * @property {string} displayName - 화면에 표시할 상품 이름이에요. 상품 이름은 앱인토스 콘솔에서 설정한 값이에요.
1846
+ * @property {string} displayAmount - 통화 단위가 포함된 가격 정보예요. 예를 들어 `1,000원`으로 가격과 통화가 함께 표시돼요.
1847
+ * @property {string} iconUrl - 상품 아이콘 이미지의 URL이에요. 아이콘은 앱인토스 콘솔에서 설정한 이미지예요.
1848
+ * @property {string} description - 상품에 대한 설명이에요. 설명은 앱인토스 콘솔에서 설정한 값이에요.
1849
+ */
1850
+ interface IapProductListItem {
1851
+ sku: string;
1852
+ displayAmount: string;
1853
+ displayName: string;
1854
+ iconUrl: string;
1855
+ description: string;
1856
+ }
1857
+ /**
1858
+ * @public
1859
+ * @category 인앱결제
1860
+ * @name iapGetProductItemList
1861
+ * @description 인앱결제로 구매할 수 있는 상품 목록을 가져와요. 상품 목록 화면에 진입할 때 호출해요.
1862
+ * @returns {Promise<{ products: IapProductListItem[] } | undefined>} 상품 목록을 포함한 객체를 반환해요. 앱 버전이 최소 지원 버전(안드로이드 5.219.0, iOS 5.219.0)보다 낮으면 `undefined`를 반환해요.
1863
+ *
1864
+ * @example
1865
+ * ### 구매 가능한 인앱결제 상품목록 가져오기
1866
+ *
1867
+ * ```tsx
1868
+ * import { useEffect, useState } from 'react';
1869
+ * import { List, ListRow, Txt } from '@toss-design-system/react-native';
1870
+ * import { IAP } from '@apps-in-toss/framework';
1871
+ *
1872
+ * function IapGetProductItemList() {
1873
+ * const [products, setProducts] = useState<IapProductListItem[]>([]);
1874
+ *
1875
+ * useEffect(() => {
1876
+ * async function fetchProducts() {
1877
+ * try {
1878
+ * const response = await IAP.getProductItemList();
1879
+ * setProducts(response?.products ?? []);
1880
+ * } catch (error) {
1881
+ * console.error('상품 목록을 가져오는 데 실패했어요:', error);
1882
+ * }
1883
+ * }
1884
+ *
1885
+ * fetchProducts();
1886
+ * }, []);
1887
+ *
1888
+ * return (
1889
+ * <List>
1890
+ * {products.map((product) => (
1891
+ * <ListRow
1892
+ * key={product.sku}
1893
+ * contents={<Txt>{product.displayName}</Txt>}
1894
+ * />
1895
+ * ))}
1896
+ * </List>
1897
+ * );
1898
+ * }
1899
+ * ```
1900
+ */
1901
+ declare function getProductItemList(): Promise<{
1902
+ products: IapProductListItem[];
1903
+ } | undefined>;
1904
+ /**
1905
+ * @public
1906
+ * @category 인앱결제
1907
+ * @name IAP
1908
+ * @description 인앱결제 관련 기능을 모은 객체예요. 단건 인앱결제 주문서 이동과 상품 목록 조회 기능을 제공해요.
1909
+ * @property {typeof createOneTimePurchaseOrder} [createOneTimePurchaseOrder] 특정 인앱결제 주문서 페이지로 이동해요. 자세한 내용은 [createOneTimePurchaseOrder](/bedrock/reference/framework/인앱결제/createOneTimePurchaseOrder.html) 문서를 참고하세요.
1910
+ * @property {typeof getProductItemList} [getProductItemList] 인앱결제로 구매할 수 있는 상품 목록을 가져와요. 자세한 내용은 [getProductItemList](/bedrock/reference/framework/인앱결제/getProductItemList.html) 문서를 참고하세요.
1911
+ */
1912
+ declare const IAP: {
1913
+ createOneTimePurchaseOrder: typeof createOneTimePurchaseOrder;
1914
+ getProductItemList: typeof getProductItemList;
1915
+ };
1916
+
1655
1917
  /**
1656
1918
  * @public
1657
1919
  * @category 토스페이
@@ -1795,7 +2057,26 @@ declare class AppBridgeCallbackEvent extends BedrockEventDefinition<void, AppBri
1795
2057
  private ensureInvokeAppBridgeCallback;
1796
2058
  }
1797
2059
 
1798
- declare const appsInTossEvent: BedrockEvent<EntryMessageExitedEvent | AppBridgeCallbackEvent | UpdateLocationEvent>;
2060
+ interface VisibilityChangedByTransparentServiceWebOptions {
2061
+ callbackId: string;
2062
+ }
2063
+ declare class VisibilityChangedByTransparentServiceWebEvent extends BedrockEventDefinition<VisibilityChangedByTransparentServiceWebOptions, boolean> {
2064
+ name: "onVisibilityChangedByTransparentServiceWeb";
2065
+ subscription: EmitterSubscription | null;
2066
+ remove(): void;
2067
+ listener(options: VisibilityChangedByTransparentServiceWebOptions, onEvent: (isVisible: boolean) => void, onError: (error: unknown) => void): void;
2068
+ private isVisibilityChangedByTransparentServiceWebResult;
2069
+ }
2070
+
2071
+ declare const appsInTossEvent: BedrockEvent<EntryMessageExitedEvent | VisibilityChangedByTransparentServiceWebEvent | UpdateLocationEvent | AppBridgeCallbackEvent>;
2072
+
2073
+ declare function onVisibilityChangedByTransparentServiceWeb(eventParams: {
2074
+ options: VisibilityChangedByTransparentServiceWebOptions;
2075
+ onEvent: (isVisible: boolean) => void;
2076
+ onError: (error: unknown) => void;
2077
+ }): () => void;
2078
+
2079
+ declare const INTERNAL__onVisibilityChangedByTransparentServiceWeb: typeof onVisibilityChangedByTransparentServiceWeb;
1799
2080
 
1800
2081
  declare const Analytics: {
1801
2082
  init: (options: _apps_in_toss_analytics.AnalyticsConfig) => void;
@@ -1804,4 +2085,4 @@ declare const Analytics: {
1804
2085
  Area: ({ children, params: _params, ...props }: _apps_in_toss_analytics.LoggingAreaProps) => react_jsx_runtime.JSX.Element;
1805
2086
  };
1806
2087
 
1807
- export { Accuracy, Analytics, AppsInToss, type ContactEntity, type EventLogParams, type ExternalWebViewProps, type FetchAlbumPhotosOptions, type GameWebViewProps, type GetCurrentLocationOptions, GoogleAdMob, type ImageResponse, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type Location, type LocationCoords, type OpenCameraOptions, type PartnerWebViewProps, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, type StartUpdateLocationOptions$1 as StartUpdateLocationOptions, type StartUpdateLocationSubscription, Storage, TossPay, type UpdateLocationEventEmitter, type UseGeolocationOptions, WebView, type WebViewProps, appLogin, appsInTossEvent, env, eventLog, fetchAlbumPhotos, fetchContacts, getClipboardText, getCurrentLocation, getDeviceId, getOperationalEnvironment, getTossAppVersion, getTossShareLink, isMinVersionSupported, openCamera, setClipboardText, startUpdateLocation, useGeolocation };
2088
+ export { Accuracy, Analytics, AppsInToss, type ContactEntity, type EventLogParams, type ExternalWebViewProps, type FetchAlbumPhotosOptions, type GameWebViewProps, type GetCurrentLocationOptions, GoogleAdMob, IAP, INTERNAL__onVisibilityChangedByTransparentServiceWeb, type IapCreateOneTimePurchaseOrderOptions, type IapCreateOneTimePurchaseOrderResult, type IapProductListItem, type ImageResponse, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type Location, type LocationCoords, type OpenCameraOptions, type PartnerWebViewProps, type SaveBase64DataParams, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, type StartUpdateLocationOptions$1 as StartUpdateLocationOptions, type StartUpdateLocationSubscription, Storage, TossPay, type UpdateLocationEventEmitter, type UseGeolocationOptions, WebView, type WebViewProps, appLogin, appsInTossEvent, env, eventLog, fetchAlbumPhotos, fetchContacts, getClipboardText, getCurrentLocation, getDeviceId, getOperationalEnvironment, getTossAppVersion, getTossShareLink, isMinVersionSupported, openCamera, saveBase64Data, setClipboardText, setDeviceOrientation, startUpdateLocation, useGeolocation };
package/dist/index.d.ts CHANGED
@@ -1652,6 +1652,268 @@ declare function eventLog(params: EventLogParams): Promise<void>;
1652
1652
  */
1653
1653
  declare function getTossShareLink(path: string): Promise<string>;
1654
1654
 
1655
+ /**
1656
+ * @public
1657
+ * @category 화면 제어
1658
+ * @kind function
1659
+ * @name setDeviceOrientation
1660
+ * @description
1661
+ * `setDeviceOrientation` 함수는 기기의 화면 방향을 설정하는 기능을 제공해요.
1662
+ * 이 기능은 특정 화면에서 가로 모드나 세로 모드를 강제로 지정해야 할 때 유용해요.
1663
+ *
1664
+ * `type` 옵션을 통해 원하는 화면 방향을 지정할 수 있어요. 특히, 이 함수는 앱 전체에 영향을 미치므로
1665
+ * 특정 화면에서만 사용하려면 화면을 벗어날 때 이전 상태로 복구하는 추가 작업이 필요해요.
1666
+ *
1667
+ * 예를 들어, 동영상 감상 화면에서는 가로 모드를 강제하고, 화면을 떠날 때 설정을 복구해서
1668
+ * 다른 화면들의 방향 설정에 영향을 주지 않도록 할 수 있어요.
1669
+ *
1670
+ * @param {object} options 화면 방향 설정 값이에요.
1671
+ * @param {string} options.type 화면 방향을 지정하는 옵션이에요.
1672
+ * 'portrait' | 'landscape' 중 하나를 선택할 수 있어요.
1673
+ *
1674
+ * @returns {Promise<void>} 화면 방향 설정이 완료되면 해결되는 Promise를 반환해요.
1675
+ *
1676
+ * @example
1677
+ * ### 화면 방향 설정하기
1678
+ *
1679
+ * ```tsx
1680
+ * import { Button } from 'react-native';
1681
+ * import { setDeviceOrientation } from '@apps-in-toss/framework';
1682
+ *
1683
+ * function SetDeviceOrientation() {
1684
+ * return (
1685
+ * <Button
1686
+ * title="가로 모드로 변경"
1687
+ * onPress={() => {
1688
+ * setDeviceOrientation({ type: 'landscape' });
1689
+ * }}
1690
+ * />
1691
+ * );
1692
+ * }
1693
+ * ```
1694
+ *
1695
+ * ### 화면 방향 복구하기
1696
+ * 특정 화면을 벗어날 때 이전 상태로 복구하려면 다음과 같이 `useEffect`를 사용하세요.
1697
+ *
1698
+ * ```tsx
1699
+ * import { useEffect } from 'react';
1700
+ * import { setDeviceOrientation } from '@apps-in-toss/framework';
1701
+ *
1702
+ * function VideoScreen() {
1703
+ * useEffect(() => {
1704
+ * setDeviceOrientation({ type: 'landscape' });
1705
+ *
1706
+ * return () => {
1707
+ * setDeviceOrientation({ type: 'portrait' }); // 설정을 이전 상태로 복구해요.
1708
+ * };
1709
+ * }, []);
1710
+ *
1711
+ * return <Text>동영상을 감상하는 화면</Text>;
1712
+ * }
1713
+ * ```
1714
+ */
1715
+ declare function setDeviceOrientation(options: {
1716
+ type: 'portrait' | 'landscape';
1717
+ }): Promise<void>;
1718
+
1719
+ interface SaveBase64DataParams {
1720
+ data: string;
1721
+ fileName: string;
1722
+ mimeType: string;
1723
+ }
1724
+ /**
1725
+ * @public
1726
+ * @category 데이터
1727
+ * @name saveBase64Data
1728
+ * @description 문자열로 인코딩된 Base64 데이터를 지정한 파일 이름과 MIME 타입으로 사용자 기기에 저장해요. 이미지, 텍스트, PDF 등 다양한 형식의 데이터를 저장할 수 있어요.
1729
+ * @param {SaveBase64DataParams} params - 저장할 데이터와 파일 정보를 담은 객체예요.
1730
+ * @param {string} params.data - Base64 형식으로 인코딩된 데이터 문자열이에요.
1731
+ * @param {string} params.fileName - 저장할 파일 이름이에요. 확장자도 같이 붙여줘야해요. 예를 들어, 'example.png'로 저장할 수 있어요.
1732
+ * @param {string} params.mimeType - 저장할 파일의 MIME 타입이에요. 예를 들어 'image/png' 로 지정하면 이미지, 'application/pdf'는 PDF 파일이에요. 자세한 내용은 [MIME 문서](https://developer.mozilla.org/ko/docs/Web/HTTP/Guides/MIME_types)를 참고해주세요.
1733
+ *
1734
+ * @example
1735
+ * ### Base64 이미지 데이터를 사용자 기기에 저장하기
1736
+ *
1737
+ * ```tsx
1738
+ * import { Button } from 'react-native';
1739
+ * import { saveBase64Data } from '@apps-in-toss/framework';
1740
+ *
1741
+ * // '저장' 버튼을 누르면 이미지가 사용자 기기에 저장돼요.
1742
+ * function SaveButton() {
1743
+ * const handleSave = async () => {
1744
+ * try {
1745
+ * await saveBase64Data({
1746
+ * data: 'iVBORw0KGgo...',
1747
+ * fileName: 'some-photo.png',
1748
+ * mimeType: 'image/png',
1749
+ * });
1750
+ * } catch (error) {
1751
+ * console.error('데이터 저장에 실패했어요:', error);
1752
+ * }
1753
+ * };
1754
+ *
1755
+ * return <Button title="저장" onPress={handleSave} />;
1756
+ * }
1757
+ * ```
1758
+ */
1759
+ declare function saveBase64Data(params: SaveBase64DataParams): Promise<void>;
1760
+
1761
+ /**
1762
+ * @public
1763
+ * @category 인앱결제
1764
+ * @name IapCreateOneTimePurchaseOrderOptions
1765
+ * @description 인앱결제 1건을 요청할 때 필요한 정보예요.
1766
+ * @property {string} productId - 주문할 상품의 ID예요.
1767
+ */
1768
+ interface IapCreateOneTimePurchaseOrderOptions {
1769
+ productId: string;
1770
+ }
1771
+ /**
1772
+ * @public
1773
+ * @category 인앱결제
1774
+ * @name IapCreateOneTimePurchaseOrderResult
1775
+ * @description 인앱결제 1건이 완료되면 결제 세부 정보와 상품 정보를 담아 반환해요. 반환된 정보로 결제한 상품의 정보를 화면에 표시할 수 있어요.
1776
+ * @property {string | null} miniAppIconUrl - 미니앱 아이콘 이미지의 URL이에요. 아이콘은 앱인토스 콘솔에서 설정한 이미지예요. 콘솔에서 아이콘을 등록하지 않았다면 `null`로 반환돼요.
1777
+ * @property {string} displayName - 화면에 표시할 상품 이름이에요.
1778
+ * @property {string} displayAmount - 통화 단위가 포함된 가격 정보예요. 예를 들어 `1,000원`으로 가격과 통화가 함께 표시돼요.
1779
+ * @property {number} amount - 상품 가격 숫자 값이에요. 화폐 단위와 쉼표를 제외한 순수 숫자예요. 예를 들어 `1000`으로 표시돼요.
1780
+ * @property {string} currency - [ISO 4217 표준](https://ko.wikipedia.org/wiki/ISO_4217)에 따른 상품 가격 통화 단위예요. 예를 들어 원화는 `KRW`, 달러는 `USD`로 표시돼요.
1781
+ * @property {number} fraction - 가격을 표시할 때 소수점 아래 몇 자리까지 보여줄지 정하는 값이에요. 예를 들어 달러는 소수점 둘째 자리까지 보여줘서 `2`, 원화는 소수점이 필요 없어서 `0`이에요
1782
+ */
1783
+ interface IapCreateOneTimePurchaseOrderResult {
1784
+ miniAppIconUrl: string | null;
1785
+ displayName: string;
1786
+ displayAmount: string;
1787
+ amount: number;
1788
+ currency: string;
1789
+ fraction: number;
1790
+ }
1791
+ /**
1792
+ * @public
1793
+ * @category 인앱결제
1794
+ * @name iapCreateOneTimePurchaseOrder
1795
+ * @description
1796
+ * 특정 인앱결제 주문서 페이지로 이동해요. 사용자가 상품 구매 버튼을 누르는 상황 등에 사용할 수 있어요. 사용자의 결제는 이동한 페이지에서 진행돼요. 만약 결제 중에 에러가 발생하면 에러 유형에 따라 에러 페이지로 이동해요.
1797
+ * @param {IapCreateOneTimePurchaseOrderOptions} params - 인앱결제를 생성할 때 필요한 정보예요.
1798
+ * @param {string} params.productId - 주문할 상품의 ID예요.
1799
+ * @returns {Promise<IapCreateOneTimePurchaseOrderResult | undefined>} 결제에 성공하면 결제 결과 객체를 반환해요. 앱 버전이 최소 지원 버전(안드로이드 5.219.0, iOS 5.219.0)보다 낮으면 인앱결제를 실행할 수 없어서 `undefined`를 반환해요.
1800
+ *
1801
+ * @throw {code: "INVALID_PRODUCT_ID"} - 유효하지 않은 상품 ID이거나, 해당 상품이 존재하지 않을 때 발생해요.
1802
+ * @throw {code: "PAYMENT_PENDING"} - 사용자가 요청한 결제가 아직 승인을 기다리고 있을 때 발생해요.
1803
+ * @throw {code: "NETWORK_ERROR"} - 서버 내부 문제로 요청을 처리할 수 없을 때 발생해요.
1804
+ * @throw {code: "INVALID_USER_ENVIRONMENT"} - 특정 기기, 계정 또는 설정 환경에서 구매할 수 없는 상품일 때 발생해요.
1805
+ * @throw {code: "ITEM_ALREADY_OWNED"} - 사용자가 이미 구매한 상품을 다시 구매하려고 할 때 발생해요.
1806
+ * @throw {code: "APP_MARKET_VERIFICATION_FAILED"} - 사용자가 결제를 완료했지만, 앱스토어에서 사용자 정보 검증에 실패했을 때 발생해요. 사용자가 앱스토어에 문의해서 환불을 요청해야해요.
1807
+ * @throw {code: "TOSS_SERVER_VERIFICATION_FAILED"} - 사용자가 결제를 완료했지만, 서버 전송에 실패해서 결제 정보를 저장할 수 없을 때 발생해요.
1808
+ * @throw {code: "INTERNAL_ERROR"} - 서버 내부 문제로 요청을 처리할 수 없을 때 발생해요.
1809
+ * @throw {code: "KOREAN_ACCOUNT_ONLY"} - iOS 환경에서 사용자의 계정이 한국 계정이 아닐 때 발생해요.
1810
+ * @throw {code: "USER_CANCELED"} - 사용자가 결제를 완료하지 않고 주문서 페이지를 이탈했을 때 발생해요.
1811
+ *
1812
+ * @example
1813
+ * ### 특정 인앱결제 주문서 페이지로 이동하기
1814
+ *
1815
+ * ```tsx
1816
+ * import { Button } from 'react-native';
1817
+ * import { IAP } from '@apps-in-toss/framework';
1818
+ *
1819
+ * interface Props {
1820
+ * productId: string;
1821
+ * }
1822
+ *
1823
+ * function IapCreateOneTimePurchaseOrderButton({ productId }: Props) {
1824
+ * const handleClick = async () => {
1825
+ * try {
1826
+ * await IAP.createOneTimePurchaseOrder({
1827
+ * productId,
1828
+ * });
1829
+ * } catch (error) {
1830
+ * console.error('인앱결제에 실패했어요:', error);
1831
+ * }
1832
+ * };
1833
+ *
1834
+ * return <Button title="구매하기" onPress={handleClick} />;
1835
+ * }
1836
+ * ```
1837
+ */
1838
+ declare function createOneTimePurchaseOrder(params: IapCreateOneTimePurchaseOrderOptions): Promise<IapCreateOneTimePurchaseOrderResult | undefined>;
1839
+ /**
1840
+ * @public
1841
+ * @category 인앱결제
1842
+ * @name IapProductListItem
1843
+ * @description 인앱결제로 구매할 수 있는 상품 하나의 정보를 담은 객체예요. 상품 목록을 화면에 표시할 때 사용해요.
1844
+ * @property {string} sku - 상품의 고유 ID예요. [인앱결제 주문서 페이지로 이동할때](/bedrock/reference/framework/인앱결제/createOneTimePurchaseOrder.html) 사용하는 `productId`와 동일한 값이에요.
1845
+ * @property {string} displayName - 화면에 표시할 상품 이름이에요. 상품 이름은 앱인토스 콘솔에서 설정한 값이에요.
1846
+ * @property {string} displayAmount - 통화 단위가 포함된 가격 정보예요. 예를 들어 `1,000원`으로 가격과 통화가 함께 표시돼요.
1847
+ * @property {string} iconUrl - 상품 아이콘 이미지의 URL이에요. 아이콘은 앱인토스 콘솔에서 설정한 이미지예요.
1848
+ * @property {string} description - 상품에 대한 설명이에요. 설명은 앱인토스 콘솔에서 설정한 값이에요.
1849
+ */
1850
+ interface IapProductListItem {
1851
+ sku: string;
1852
+ displayAmount: string;
1853
+ displayName: string;
1854
+ iconUrl: string;
1855
+ description: string;
1856
+ }
1857
+ /**
1858
+ * @public
1859
+ * @category 인앱결제
1860
+ * @name iapGetProductItemList
1861
+ * @description 인앱결제로 구매할 수 있는 상품 목록을 가져와요. 상품 목록 화면에 진입할 때 호출해요.
1862
+ * @returns {Promise<{ products: IapProductListItem[] } | undefined>} 상품 목록을 포함한 객체를 반환해요. 앱 버전이 최소 지원 버전(안드로이드 5.219.0, iOS 5.219.0)보다 낮으면 `undefined`를 반환해요.
1863
+ *
1864
+ * @example
1865
+ * ### 구매 가능한 인앱결제 상품목록 가져오기
1866
+ *
1867
+ * ```tsx
1868
+ * import { useEffect, useState } from 'react';
1869
+ * import { List, ListRow, Txt } from '@toss-design-system/react-native';
1870
+ * import { IAP } from '@apps-in-toss/framework';
1871
+ *
1872
+ * function IapGetProductItemList() {
1873
+ * const [products, setProducts] = useState<IapProductListItem[]>([]);
1874
+ *
1875
+ * useEffect(() => {
1876
+ * async function fetchProducts() {
1877
+ * try {
1878
+ * const response = await IAP.getProductItemList();
1879
+ * setProducts(response?.products ?? []);
1880
+ * } catch (error) {
1881
+ * console.error('상품 목록을 가져오는 데 실패했어요:', error);
1882
+ * }
1883
+ * }
1884
+ *
1885
+ * fetchProducts();
1886
+ * }, []);
1887
+ *
1888
+ * return (
1889
+ * <List>
1890
+ * {products.map((product) => (
1891
+ * <ListRow
1892
+ * key={product.sku}
1893
+ * contents={<Txt>{product.displayName}</Txt>}
1894
+ * />
1895
+ * ))}
1896
+ * </List>
1897
+ * );
1898
+ * }
1899
+ * ```
1900
+ */
1901
+ declare function getProductItemList(): Promise<{
1902
+ products: IapProductListItem[];
1903
+ } | undefined>;
1904
+ /**
1905
+ * @public
1906
+ * @category 인앱결제
1907
+ * @name IAP
1908
+ * @description 인앱결제 관련 기능을 모은 객체예요. 단건 인앱결제 주문서 이동과 상품 목록 조회 기능을 제공해요.
1909
+ * @property {typeof createOneTimePurchaseOrder} [createOneTimePurchaseOrder] 특정 인앱결제 주문서 페이지로 이동해요. 자세한 내용은 [createOneTimePurchaseOrder](/bedrock/reference/framework/인앱결제/createOneTimePurchaseOrder.html) 문서를 참고하세요.
1910
+ * @property {typeof getProductItemList} [getProductItemList] 인앱결제로 구매할 수 있는 상품 목록을 가져와요. 자세한 내용은 [getProductItemList](/bedrock/reference/framework/인앱결제/getProductItemList.html) 문서를 참고하세요.
1911
+ */
1912
+ declare const IAP: {
1913
+ createOneTimePurchaseOrder: typeof createOneTimePurchaseOrder;
1914
+ getProductItemList: typeof getProductItemList;
1915
+ };
1916
+
1655
1917
  /**
1656
1918
  * @public
1657
1919
  * @category 토스페이
@@ -1795,7 +2057,26 @@ declare class AppBridgeCallbackEvent extends BedrockEventDefinition<void, AppBri
1795
2057
  private ensureInvokeAppBridgeCallback;
1796
2058
  }
1797
2059
 
1798
- declare const appsInTossEvent: BedrockEvent<EntryMessageExitedEvent | AppBridgeCallbackEvent | UpdateLocationEvent>;
2060
+ interface VisibilityChangedByTransparentServiceWebOptions {
2061
+ callbackId: string;
2062
+ }
2063
+ declare class VisibilityChangedByTransparentServiceWebEvent extends BedrockEventDefinition<VisibilityChangedByTransparentServiceWebOptions, boolean> {
2064
+ name: "onVisibilityChangedByTransparentServiceWeb";
2065
+ subscription: EmitterSubscription | null;
2066
+ remove(): void;
2067
+ listener(options: VisibilityChangedByTransparentServiceWebOptions, onEvent: (isVisible: boolean) => void, onError: (error: unknown) => void): void;
2068
+ private isVisibilityChangedByTransparentServiceWebResult;
2069
+ }
2070
+
2071
+ declare const appsInTossEvent: BedrockEvent<EntryMessageExitedEvent | VisibilityChangedByTransparentServiceWebEvent | UpdateLocationEvent | AppBridgeCallbackEvent>;
2072
+
2073
+ declare function onVisibilityChangedByTransparentServiceWeb(eventParams: {
2074
+ options: VisibilityChangedByTransparentServiceWebOptions;
2075
+ onEvent: (isVisible: boolean) => void;
2076
+ onError: (error: unknown) => void;
2077
+ }): () => void;
2078
+
2079
+ declare const INTERNAL__onVisibilityChangedByTransparentServiceWeb: typeof onVisibilityChangedByTransparentServiceWeb;
1799
2080
 
1800
2081
  declare const Analytics: {
1801
2082
  init: (options: _apps_in_toss_analytics.AnalyticsConfig) => void;
@@ -1804,4 +2085,4 @@ declare const Analytics: {
1804
2085
  Area: ({ children, params: _params, ...props }: _apps_in_toss_analytics.LoggingAreaProps) => react_jsx_runtime.JSX.Element;
1805
2086
  };
1806
2087
 
1807
- export { Accuracy, Analytics, AppsInToss, type ContactEntity, type EventLogParams, type ExternalWebViewProps, type FetchAlbumPhotosOptions, type GameWebViewProps, type GetCurrentLocationOptions, GoogleAdMob, type ImageResponse, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type Location, type LocationCoords, type OpenCameraOptions, type PartnerWebViewProps, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, type StartUpdateLocationOptions$1 as StartUpdateLocationOptions, type StartUpdateLocationSubscription, Storage, TossPay, type UpdateLocationEventEmitter, type UseGeolocationOptions, WebView, type WebViewProps, appLogin, appsInTossEvent, env, eventLog, fetchAlbumPhotos, fetchContacts, getClipboardText, getCurrentLocation, getDeviceId, getOperationalEnvironment, getTossAppVersion, getTossShareLink, isMinVersionSupported, openCamera, setClipboardText, startUpdateLocation, useGeolocation };
2088
+ export { Accuracy, Analytics, AppsInToss, type ContactEntity, type EventLogParams, type ExternalWebViewProps, type FetchAlbumPhotosOptions, type GameWebViewProps, type GetCurrentLocationOptions, GoogleAdMob, IAP, INTERNAL__onVisibilityChangedByTransparentServiceWeb, type IapCreateOneTimePurchaseOrderOptions, type IapCreateOneTimePurchaseOrderResult, type IapProductListItem, type ImageResponse, type LoadAdMobInterstitialAdEvent, type LoadAdMobInterstitialAdOptions, type LoadAdMobRewardedAdEvent, type LoadAdMobRewardedAdOptions, type Location, type LocationCoords, type OpenCameraOptions, type PartnerWebViewProps, type SaveBase64DataParams, type ShowAdMobInterstitialAdEvent, type ShowAdMobInterstitialAdOptions, type ShowAdMobRewardedAdEvent, type ShowAdMobRewardedAdOptions, type StartUpdateLocationOptions$1 as StartUpdateLocationOptions, type StartUpdateLocationSubscription, Storage, TossPay, type UpdateLocationEventEmitter, type UseGeolocationOptions, WebView, type WebViewProps, appLogin, appsInTossEvent, env, eventLog, fetchAlbumPhotos, fetchContacts, getClipboardText, getCurrentLocation, getDeviceId, getOperationalEnvironment, getTossAppVersion, getTossShareLink, isMinVersionSupported, openCamera, saveBase64Data, setClipboardText, setDeviceOrientation, startUpdateLocation, useGeolocation };
package/dist/index.js CHANGED
@@ -367,11 +367,39 @@ var AppBridgeCallbackEvent = class _AppBridgeCallbackEvent extends BedrockEventD
367
367
  }
368
368
  };
369
369
 
370
+ // src/native-event-emitter/internal/VisibilityChangedByTransparentServiceWebEvent.ts
371
+ import { BedrockEventDefinition as BedrockEventDefinition4 } from "react-native-bedrock";
372
+ var VisibilityChangedByTransparentServiceWebEvent = class extends BedrockEventDefinition4 {
373
+ name = "onVisibilityChangedByTransparentServiceWeb";
374
+ subscription = null;
375
+ remove() {
376
+ this.subscription?.remove();
377
+ this.subscription = null;
378
+ }
379
+ listener(options, onEvent, onError) {
380
+ const subscription = nativeEventEmitter.addListener("visibilityChangedByTransparentServiceWeb", (params) => {
381
+ if (this.isVisibilityChangedByTransparentServiceWebResult(params)) {
382
+ if (params.callbackId === options.callbackId) {
383
+ onEvent(params.isVisible);
384
+ }
385
+ } else {
386
+ onError(new Error("Invalid visibility changed by transparent service web result"));
387
+ }
388
+ });
389
+ this.subscription = subscription;
390
+ }
391
+ isVisibilityChangedByTransparentServiceWebResult(params) {
392
+ return typeof params === "object" && typeof params.callbackId === "string" && typeof params.isVisible === "boolean";
393
+ }
394
+ };
395
+
370
396
  // src/native-event-emitter/appsInTossEvent.ts
371
397
  var appsInTossEvent = new BedrockEvent([
372
- new AppBridgeCallbackEvent(),
373
398
  new UpdateLocationEvent(),
374
- new EntryMessageExitedEvent()
399
+ new EntryMessageExitedEvent(),
400
+ // Internal events
401
+ new AppBridgeCallbackEvent(),
402
+ new VisibilityChangedByTransparentServiceWebEvent()
375
403
  ]);
376
404
 
377
405
  // src/core/utils/getAppsInTossGlobals.ts
@@ -419,7 +447,9 @@ __export(async_bridges_exports, {
419
447
  getCurrentLocation: () => getCurrentLocation,
420
448
  getTossShareLink: () => getTossShareLink,
421
449
  openCamera: () => openCamera,
422
- setClipboardText: () => setClipboardText
450
+ saveBase64Data: () => saveBase64Data,
451
+ setClipboardText: () => setClipboardText,
452
+ setDeviceOrientation: () => setDeviceOrientation
423
453
  });
424
454
 
425
455
  // src/native-modules/setClipboardText.ts
@@ -546,6 +576,31 @@ async function getTossShareLink(path) {
546
576
  return shareUrl.toString();
547
577
  }
548
578
 
579
+ // src/native-modules/setDeviceOrientation.ts
580
+ async function setDeviceOrientation(options) {
581
+ const isSupported = isMinVersionSupported({
582
+ android: "5.215.0",
583
+ ios: "5.215.0"
584
+ });
585
+ if (!isSupported) {
586
+ return;
587
+ }
588
+ return AppsInTossModule.setDeviceOrientation(options);
589
+ }
590
+
591
+ // src/native-modules/saveBase64Data.ts
592
+ async function saveBase64Data(params) {
593
+ const isSupported = isMinVersionSupported({
594
+ android: "5.218.0",
595
+ ios: "5.216.0"
596
+ });
597
+ if (!isSupported) {
598
+ console.warn("saveBase64Data is not supported in this app version");
599
+ return;
600
+ }
601
+ await AppsInTossModule.saveBase64Data(params);
602
+ }
603
+
549
604
  // src/core/registerApp.tsx
550
605
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
551
606
  function AppsInTossContainer(Container, { children, ...initialProps }) {
@@ -687,7 +742,6 @@ var ENVIRONMENT = getOperationalEnvironment();
687
742
  function createIsSupported() {
688
743
  return () => {
689
744
  if (ENVIRONMENT !== "toss") {
690
- console.warn("Google AdMob is not supported in the current environment");
691
745
  return false;
692
746
  }
693
747
  return isMinVersionSupported({
@@ -734,6 +788,32 @@ var Storage = {
734
788
  clearItems
735
789
  };
736
790
 
791
+ // src/native-modules/iap.ts
792
+ async function createOneTimePurchaseOrder(params) {
793
+ const isSupported = isMinVersionSupported({
794
+ android: "5.219.0",
795
+ ios: "5.219.0"
796
+ });
797
+ if (!isSupported) {
798
+ return;
799
+ }
800
+ return AppsInTossModule.iapCreateOneTimePurchaseOrder(params);
801
+ }
802
+ async function getProductItemList() {
803
+ const isSupported = isMinVersionSupported({
804
+ android: "5.219.0",
805
+ ios: "5.219.0"
806
+ });
807
+ if (!isSupported) {
808
+ return;
809
+ }
810
+ return AppsInTossModule.iapGetProductItemList({});
811
+ }
812
+ var IAP = {
813
+ createOneTimePurchaseOrder,
814
+ getProductItemList
815
+ };
816
+
737
817
  // src/native-modules/index.ts
738
818
  var TossPay = {
739
819
  checkoutPayment
@@ -1170,7 +1250,10 @@ function WebView({ type, local, onMessage, ...props }) {
1170
1250
  getStorageItem: Storage.getItem,
1171
1251
  setStorageItem: Storage.setItem,
1172
1252
  removeStorageItem: Storage.removeItem,
1173
- clearItems: Storage.clearItems
1253
+ clearItems: Storage.clearItems,
1254
+ /** IAP */
1255
+ iapCreateOneTimePurchaseOrder: IAP.createOneTimePurchaseOrder,
1256
+ iapGetProductItemList: IAP.getProductItemList
1174
1257
  }
1175
1258
  });
1176
1259
  const baseProps = useMemo3(() => {
@@ -1267,6 +1350,14 @@ var Accuracy2 = /* @__PURE__ */ ((Accuracy3) => {
1267
1350
  return Accuracy3;
1268
1351
  })(Accuracy2 || {});
1269
1352
 
1353
+ // src/native-event-emitter/internal/onVisibilityChangedByTransparentServiceWeb.ts
1354
+ function onVisibilityChangedByTransparentServiceWeb(eventParams) {
1355
+ return appsInTossEvent.addEventListener("onVisibilityChangedByTransparentServiceWeb", eventParams);
1356
+ }
1357
+
1358
+ // src/private.ts
1359
+ var INTERNAL__onVisibilityChangedByTransparentServiceWeb = onVisibilityChangedByTransparentServiceWeb;
1360
+
1270
1361
  // src/index.ts
1271
1362
  export * from "@apps-in-toss/analytics";
1272
1363
  var Analytics2 = {
@@ -1280,6 +1371,8 @@ export {
1280
1371
  Analytics2 as Analytics,
1281
1372
  AppsInToss,
1282
1373
  GoogleAdMob,
1374
+ IAP,
1375
+ INTERNAL__onVisibilityChangedByTransparentServiceWeb,
1283
1376
  Storage,
1284
1377
  TossPay,
1285
1378
  WebView,
@@ -1297,7 +1390,9 @@ export {
1297
1390
  getTossShareLink,
1298
1391
  isMinVersionSupported,
1299
1392
  openCamera,
1393
+ saveBase64Data,
1300
1394
  setClipboardText,
1395
+ setDeviceOrientation,
1301
1396
  startUpdateLocation,
1302
1397
  useGeolocation
1303
1398
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@apps-in-toss/framework",
3
3
  "type": "module",
4
- "version": "0.0.0-dev.1747216176095",
4
+ "version": "0.0.0-dev.1752114017143",
5
5
  "description": "The framework for Apps In Toss",
6
6
  "scripts": {
7
7
  "prepack": "yarn build",
@@ -57,16 +57,16 @@
57
57
  "ait": "./bin/ait.js"
58
58
  },
59
59
  "dependencies": {
60
- "@apps-in-toss/analytics": "0.0.0-dev.1747216176095",
61
- "@apps-in-toss/cli": "0.0.0-dev.1747216176095",
62
- "@apps-in-toss/plugins": "0.0.0-dev.1747216176095",
60
+ "@apps-in-toss/analytics": "0.0.0-dev.1752114017143",
61
+ "@apps-in-toss/cli": "0.0.0-dev.1752114017143",
62
+ "@apps-in-toss/plugins": "0.0.0-dev.1752114017143",
63
63
  "es-hangul": "^2.3.2"
64
64
  },
65
65
  "devDependencies": {
66
- "@react-native-bedrock/mpack-next": "0.0.0-dev.1747215740094",
67
- "@react-native-bedrock/native": "0.0.0-dev.1747215740094",
68
- "@react-native-bedrock/plugin-core": "0.0.0-dev.1747215740094",
69
- "@react-native-bedrock/utils": "0.0.0-dev.1747215740094",
66
+ "@react-native-bedrock/mpack-next": "0.0.25",
67
+ "@react-native-bedrock/native": "0.0.25",
68
+ "@react-native-bedrock/plugin-core": "0.0.25",
69
+ "@react-native-bedrock/utils": "0.0.25",
70
70
  "@toss-design-system/react-native": "^0.5.0",
71
71
  "@types/kill-port": "^2.0.1",
72
72
  "@types/react": "18.3.3",
@@ -76,22 +76,22 @@
76
76
  "kill-port": "^2.0.1",
77
77
  "react": "18.2.0",
78
78
  "react-native": "0.72.6",
79
- "react-native-bedrock": "0.0.0-dev.1747215740094",
79
+ "react-native-bedrock": "0.0.25",
80
80
  "tsup": "^8.3.5",
81
81
  "typescript": "5.8.3",
82
82
  "vitest": "^3.0.3",
83
83
  "workspace-tools": "^0.38.2"
84
84
  },
85
85
  "peerDependencies": {
86
- "@react-native-bedrock/native": "*",
86
+ "@react-native-bedrock/native": ">= 0.0.18",
87
87
  "@toss-design-system/react-native": ">= 0.5.0",
88
88
  "@types/react": "*",
89
89
  "react": "*",
90
90
  "react-native": "*",
91
- "react-native-bedrock": "*"
91
+ "react-native-bedrock": ">= 0.0.18"
92
92
  },
93
93
  "publishConfig": {
94
94
  "access": "public"
95
95
  },
96
- "gitHead": "b9097d25120bc711f8c90351a5c6d0346d41f7fa"
96
+ "gitHead": "d4d3441684f79edb0dd69330007f32b737ee01dc"
97
97
  }
@@ -8,3 +8,5 @@ export * from './native-modules/appLogin';
8
8
  export * from './native-modules/checkoutPayment';
9
9
  export * from './native-modules/eventLog';
10
10
  export * from './native-modules/getTossShareLink';
11
+ export * from './native-modules/setDeviceOrientation';
12
+ export * from './native-modules/saveBase64Data';