diff --git a/android/src/main/java/com/iterable/reactnative/RNIterableAPIModule.java b/android/src/main/java/com/iterable/reactnative/RNIterableAPIModule.java index 9b0bed33a..cd46cc2ba 100644 --- a/android/src/main/java/com/iterable/reactnative/RNIterableAPIModule.java +++ b/android/src/main/java/com/iterable/reactnative/RNIterableAPIModule.java @@ -482,6 +482,33 @@ public void updateVisibleRows(ReadableArray visibleRows) { // --------------------------------------------------------------------------------------- // endregion + // --------------------------------------------------------------------------------------- + // region Embedded APIs + + @ReactMethod + public void getEmbeddedMessages(Integer placementId, Promise promise) { + IterableLogger.d(TAG, "getEmbeddedMessages for placement: " + placementId); + + try { + JSONArray embeddedMessageJsonArray = Serialization.serializeEmbeddedMessages(IterableApi.getInstance().getEmbeddedManager().getMessages(placementId)); + IterableLogger.d(TAG, "Messages for placement: " + embeddedMessageJsonArray); + + promise.resolve(Serialization.convertJsonToArray(embeddedMessageJsonArray)); + } catch (JSONException e) { + IterableLogger.e(TAG, e.getLocalizedMessage()); + promise.reject("", "Failed to fetch messages with error " + e.getLocalizedMessage()); + } + } + + private JSONObject createTestPlacement(int placementId) throws JSONException { + JSONObject placement = new JSONObject(); + placement.put("placementId", placementId); + return placement; + } + + // --------------------------------------------------------------------------------------- + // endregion + // --------------------------------------------------------------------------------------- // region Private Serialization Functions diff --git a/android/src/main/java/com/iterable/reactnative/Serialization.java b/android/src/main/java/com/iterable/reactnative/Serialization.java index 3a1f536a6..af33e2e1d 100644 --- a/android/src/main/java/com/iterable/reactnative/Serialization.java +++ b/android/src/main/java/com/iterable/reactnative/Serialization.java @@ -16,6 +16,7 @@ import com.iterable.iterableapi.IterableActionContext; import com.iterable.iterableapi.IterableConfig; import com.iterable.iterableapi.IterableDataRegion; +import com.iterable.iterableapi.IterableEmbeddedMessage; import com.iterable.iterableapi.IterableInAppCloseAction; import com.iterable.iterableapi.IterableInAppDeleteActionType; import com.iterable.iterableapi.IterableInAppHandler; @@ -136,6 +137,17 @@ static JSONArray serializeInAppMessages(List inAppMessages return inAppMessagesJson; } + static JSONArray serializeEmbeddedMessages(List embeddedMessages) { + JSONArray embeddedMessagesJson = new JSONArray(); + if (embeddedMessages != null) { + for (IterableEmbeddedMessage message : embeddedMessages) { + JSONObject messageJson = IterableEmbeddedMessage.Companion.toJSONObject(message); + embeddedMessagesJson.put(messageJson); + } + } + return embeddedMessagesJson; + } + static IterableConfig.Builder getConfigFromReadableMap(ReadableMap iterableContextMap) { try { JSONObject iterableContextJSON = convertMapToJson(iterableContextMap); @@ -221,6 +233,10 @@ static IterableConfig.Builder getConfigFromReadableMap(ReadableMap iterableConte configBuilder.setEncryptionEnforced(iterableContextJSON.optBoolean("encryptionEnforced")); } + if (iterableContextJSON.has("enableEmbeddedMessaging")) { + configBuilder.setEnableEmbeddedMessaging(iterableContextJSON.optBoolean("enableEmbeddedMessaging")); + } + return configBuilder; } catch (JSONException e) { e.printStackTrace(); diff --git a/ios/RNIterableAPI/RNIterableAPI.m b/ios/RNIterableAPI/RNIterableAPI.m index 8850c755a..68c90b76c 100644 --- a/ios/RNIterableAPI/RNIterableAPI.m +++ b/ios/RNIterableAPI/RNIterableAPI.m @@ -133,6 +133,11 @@ @interface RCT_EXTERN_REMAP_MODULE(RNIterableAPI, ReactIterableAPI, NSObject) RCT_EXTERN_METHOD(updateVisibleRows: (nonnull NSArray *) visibleRows) +// MARK: - SDK Embedded Manager Functions + +RCT_EXTERN_METHOD(getEmbeddedPlacements: (RCTPromiseResolveBlock) resolve + rejecter: (RCTPromiseRejectBlock) reject) + // MARK: - SDK Auth Manager Functions RCT_EXTERN_METHOD(passAlongAuthToken: (NSString *) authToken) diff --git a/ios/RNIterableAPI/ReactIterableAPI.swift b/ios/RNIterableAPI/ReactIterableAPI.swift index 4db314f20..02b8fd2d9 100644 --- a/ios/RNIterableAPI/ReactIterableAPI.swift +++ b/ios/RNIterableAPI/ReactIterableAPI.swift @@ -470,6 +470,22 @@ class ReactIterableAPI: RCTEventEmitter { inboxSessionManager.updateVisibleRows(visibleRows: serializedRows) } + + // MARK: - SDK Embedded Manager Functions + + @objc(getEmbeddedPlacements:rejecter:) + func getEmbeddedPlacements(resolver: @escaping RCTPromiseResolveBlock, + rejecter: @escaping RCTPromiseRejectBlock) { + ITBInfo() + + // Create test data + let testPlacements: [[String: Any]] = [ + ["placementId": "meow"], + ["placementId": "woof woof"] + ] + + resolver(testPlacements) + } // MARK: - SDK Auth Manager Functions diff --git a/ios/RNIterableAPI/Serialization.swift b/ios/RNIterableAPI/Serialization.swift index cb27026be..ea82bcf35 100644 --- a/ios/RNIterableAPI/Serialization.swift +++ b/ios/RNIterableAPI/Serialization.swift @@ -92,7 +92,10 @@ extension IterableConfig { config.dataRegion = IterableDataRegion.US } } - + + if let enableEmbeddedMessaging = dict["enableEmbeddedMesssaging"] as? Bool { + config.enableEmbeddedMessaging = enableEmbeddedMessaging + } return config } diff --git a/src/__tests__/IterableEmbeddedMessage.test.ts b/src/__tests__/IterableEmbeddedMessage.test.ts new file mode 100644 index 000000000..3e8a99b7c --- /dev/null +++ b/src/__tests__/IterableEmbeddedMessage.test.ts @@ -0,0 +1,162 @@ +import { IterableEmbeddedMessage } from '../embedded/classes/IterableEmbeddedMessage'; +import { Iterable } from '../core/classes/Iterable'; + +describe('IterableEmbeddedMessage', () => { + it('should create an instance with all properties', () => { + Iterable.logger.log('iterableEmbeddedMessage_fromDict_all_properties'); + + const dict = { + metadata: { + messageId: 'msg-123', + placementId: 1, + campaignId: 456, + isProof: false, + }, + elements: { + title: 'Awesome Title', + body: 'Radical Body Text', + mediaUrl: 'https://example.com/image.jpg', + mediaUrlCaption: 'Check out this sick image!', + defaultAction: { + type: 'openUrl', + data: 'https://example.com', + }, + buttons: [ + { + id: 'button-1', + title: 'Click Me!', + action: { + type: 'openUrl', + data: 'https://example.com/button1', + }, + }, + ], + text: [ + { + id: 'text-1', + text: 'Some cool text', + type: 'body', + }, + ], + }, + payload: { + customKey: 'customValue', + anotherKey: 123, + }, + }; + + const message = new IterableEmbeddedMessage(dict); + + expect(message).toBeInstanceOf(IterableEmbeddedMessage); + + // Check metadata + expect(message.metadata).toBeInstanceOf(Object); + expect(message.metadata.messageId).toBe('msg-123'); + expect(message.metadata.placementId).toBe(1); + expect(message.metadata.campaignId).toBe(456); + expect(message.metadata.isProof).toBe(false); + + // Check elements + expect(message.elements).toBeInstanceOf(Object); + expect(message.elements?.title).toBe('Awesome Title'); + expect(message.elements?.body).toBe('Radical Body Text'); + expect(message.elements?.mediaUrl).toBe('https://example.com/image.jpg'); + expect(message.elements?.mediaUrlCaption).toBe( + 'Check out this sick image!' + ); + + // Check payload + expect(message.payload).toEqual({ + customKey: 'customValue', + anotherKey: 123, + }); + }); + + it('should create an instance with only required metadata', () => { + Iterable.logger.log('iterableEmbeddedMessage_fromDict_required_only'); + + const dict = { + metadata: { + messageId: 'msg-123', + placementId: 1, + isProof: false, + }, + }; + + const message = new IterableEmbeddedMessage(dict); + + expect(message).toBeInstanceOf(IterableEmbeddedMessage); + expect(message.metadata).toBeInstanceOf(Object); + expect(message.metadata.messageId).toBe('msg-123'); + expect(message.metadata.placementId).toBe(1); + expect(message.metadata.campaignId).toBeUndefined(); + expect(message.metadata.isProof).toBe(false); + expect(message.elements).toBeUndefined(); + expect(message.payload).toBeUndefined(); + }); + + it('should throw an error if metadata is missing', () => { + Iterable.logger.log('iterableEmbeddedMessage_fromDict_missing_metadata'); + + const dict = { + elements: { + title: 'Some Title', + body: 'Some Body', + }, + }; + + // @ts-expect-error - metadata is purposely missing + expect(() => new IterableEmbeddedMessage(dict)).toThrow( + 'metadata is required' + ); + }); + + it('should create an instance with elements but no payload', () => { + Iterable.logger.log('iterableEmbeddedMessage_fromDict_elements_only'); + + const dict = { + metadata: { + messageId: 'msg-123', + placementId: 1, + isProof: false, + }, + elements: { + title: 'Elements Only', + body: 'No payload here', + }, + }; + + const message = new IterableEmbeddedMessage(dict); + + expect(message).toBeInstanceOf(IterableEmbeddedMessage); + expect(message.metadata).toBeInstanceOf(Object); + expect(message.elements).toBeInstanceOf(Object); + expect(message.elements?.title).toBe('Elements Only'); + expect(message.elements?.body).toBe('No payload here'); + expect(message.payload).toBeUndefined(); + }); + + it('should create an instance with payload but no elements', () => { + Iterable.logger.log('iterableEmbeddedMessage_fromDict_payload_only'); + + const dict = { + metadata: { + messageId: 'msg-123', + placementId: 1, + isProof: false, + }, + payload: { + someData: 'someValue', + }, + }; + + const message = new IterableEmbeddedMessage(dict); + + expect(message).toBeInstanceOf(IterableEmbeddedMessage); + expect(message.metadata).toBeInstanceOf(Object); + expect(message.elements).toBeUndefined(); + expect(message.payload).toEqual({ + someData: 'someValue', + }); + }); +}); diff --git a/src/__tests__/IterableEmbeddedMessageButton.test.ts b/src/__tests__/IterableEmbeddedMessageButton.test.ts new file mode 100644 index 000000000..5e20f90c0 --- /dev/null +++ b/src/__tests__/IterableEmbeddedMessageButton.test.ts @@ -0,0 +1,86 @@ +import { IterableEmbeddedMessageButton } from '../embedded/classes/IterableEmbeddedMessageButton'; +import { Iterable } from '../core/classes/Iterable'; + +describe('IterableEmbeddedMessageButton', () => { + it('should create an instance with all properties including button action', () => { + Iterable.logger.log( + 'iterableEmbeddedMessageButton_fromDict_all_properties' + ); + + const dict = { + id: 'button-123', + title: 'Click Me!', + action: { type: 'openUrl', data: 'https://example.com' }, + }; + + const button = new IterableEmbeddedMessageButton(dict); + + expect(button).toBeInstanceOf(IterableEmbeddedMessageButton); + expect(button.id).toBe('button-123'); + expect(button.title).toBe('Click Me!'); + expect(button.action).toBeInstanceOf(Object); + expect(button.action?.type).toBe('openUrl'); + expect(button.action?.data).toBe('https://example.com'); + }); + + it('should create an instance with only required properties', () => { + Iterable.logger.log('iterableEmbeddedMessageButton_fromDict_required_only'); + + const dict = { id: 'button-123' }; + + const button = new IterableEmbeddedMessageButton(dict); + + expect(button).toBeInstanceOf(IterableEmbeddedMessageButton); + expect(button.id).toBe('button-123'); + expect(button.title).toBeUndefined(); + expect(button.action).toBeUndefined(); + }); + + it('should create an instance with title but no action', () => { + Iterable.logger.log('iterableEmbeddedMessageButton_fromDict_title_only'); + + const dict = { + id: 'button-123', + title: 'Click Me!', + }; + + const button = new IterableEmbeddedMessageButton(dict); + + expect(button).toBeInstanceOf(IterableEmbeddedMessageButton); + expect(button.id).toBe('button-123'); + expect(button.title).toBe('Click Me!'); + expect(button.action).toBeUndefined(); + }); + + it('should throw an error if id is missing', () => { + Iterable.logger.log('iterableEmbeddedMessageButton_fromDict_missing_id'); + + const dict = { + title: 'Click Me!', + action: { type: 'openUrl', data: 'https://example.com' }, + }; + // @ts-expect-error - id is purposely missing + expect(() => new IterableEmbeddedMessageButton(dict)).toThrow( + 'id is required' + ); + }); + + it('should handle button action with only type', () => { + Iterable.logger.log( + 'iterableEmbeddedMessageButton_fromDict_action_type_only' + ); + + const dict = { + id: 'button-123', + action: { type: 'close' }, + }; + + const button = new IterableEmbeddedMessageButton(dict); + + expect(button).toBeInstanceOf(IterableEmbeddedMessageButton); + expect(button.id).toBe('button-123'); + expect(button.action).toBeInstanceOf(Object); + expect(button.action?.type).toBe('close'); + expect(button.action?.data).toBeUndefined(); + }); +}); diff --git a/src/__tests__/IterableEmbeddedMessageText.test.ts b/src/__tests__/IterableEmbeddedMessageText.test.ts new file mode 100644 index 000000000..2ac677d55 --- /dev/null +++ b/src/__tests__/IterableEmbeddedMessageText.test.ts @@ -0,0 +1,39 @@ +import { IterableEmbeddedMessageText } from '../embedded/classes/IterableEmbeddedMessageText'; +import { Iterable } from '../core/classes/Iterable'; + +describe('IterableEmbeddedMessageText', () => { + it('should create an instance from a dictionary with all properties', () => { + Iterable.logger.log('iterableEmbeddedMessageText_fromDict_all_properties'); + + const dict = { id: 'text-123', text: 'Hello World!', type: 'heading' }; + const text = new IterableEmbeddedMessageText(dict); + + expect(text).toBeInstanceOf(IterableEmbeddedMessageText); + expect(text.id).toBe('text-123'); + expect(text.text).toBe('Hello World!'); + expect(text.type).toBe('heading'); + }); + + it('should create an instance from a dictionary with only required properties', () => { + Iterable.logger.log('iterableEmbeddedMessageText_fromDict_required_only'); + + const dict = { id: 'text-123' }; + const text = new IterableEmbeddedMessageText(dict); + + expect(text).toBeInstanceOf(IterableEmbeddedMessageText); + expect(text.id).toBe('text-123'); + expect(text.text).toBeUndefined(); + expect(text.type).toBeUndefined(); + }); + + it('should throw an error if id is missing in fromDict', () => { + Iterable.logger.log('iterableEmbeddedMessageText_fromDict_missing_id'); + + const dict = { text: 'Hello World!', type: 'heading' }; + + // @ts-expect-error - id is purposely missing + expect(() => new IterableEmbeddedMessageText(dict)).toThrow( + 'id is required' + ); + }); +}); diff --git a/src/core/classes/IterableConfig.ts b/src/core/classes/IterableConfig.ts index 1c0550b0c..55539139c 100644 --- a/src/core/classes/IterableConfig.ts +++ b/src/core/classes/IterableConfig.ts @@ -294,6 +294,13 @@ export class IterableConfig { */ encryptionEnforced = false; + /** + * This specifies whether the SDK should enable embedded messaging. + * + * By default, the SDK will not enable embedded messaging. + */ + enableEmbeddedMessaging = false; + /** * Converts the IterableConfig instance to a dictionary object. * @@ -342,6 +349,7 @@ export class IterableConfig { dataRegion: this.dataRegion, pushPlatform: this.pushPlatform, encryptionEnforced: this.encryptionEnforced, + enableEmbeddedMessaging: this.enableEmbeddedMessaging, }; } } diff --git a/src/embedded/classes/IterableEmbeddedManager.ts b/src/embedded/classes/IterableEmbeddedManager.ts new file mode 100644 index 000000000..a50235bf0 --- /dev/null +++ b/src/embedded/classes/IterableEmbeddedManager.ts @@ -0,0 +1,27 @@ +import { NativeModules } from 'react-native'; + +import { Iterable } from '../../core/classes/Iterable'; +import type { IterableEmbeddedMessage } from './IterableEmbeddedMessage'; + +const RNIterableAPI = NativeModules.RNIterableAPI; + +/** + * Manages embedded messages for the current user. + * + * This class provides methods to interact with embedded messages, including retrieving placements. + */ +export class IterableEmbeddedManager { + /** + * Retrieve the current user's list of embedded placements. + * + * @param {number} placementId The ID of the placement to retrieve messages from. + * @returns A Promise that resolves to an array of embedded placements. + */ + getMessages(placementId: number): Promise { + Iterable?.logger?.log( + `EmbeddedManager.getMessages for placement ${placementId}` + ); + + return RNIterableAPI.getEmbeddedMessages(placementId); + } +} diff --git a/src/embedded/classes/IterableEmbeddedMessage.ts b/src/embedded/classes/IterableEmbeddedMessage.ts new file mode 100644 index 000000000..9d528504d --- /dev/null +++ b/src/embedded/classes/IterableEmbeddedMessage.ts @@ -0,0 +1,131 @@ +import { IterableEmbeddedMessageButton } from './IterableEmbeddedMessageButton'; +import { IterableEmbeddedMessageText } from './IterableEmbeddedMessageText'; + +/** + * IterableEmbeddedMessage represents an embedded message. + */ +export class IterableEmbeddedMessage { + /** The metadata of the embedded message */ + readonly metadata: { + /** The id of the message */ + messageId: string; + /** The placement id of the message */ + placementId: number; + /** The campaign id of the message */ + campaignId?: number; + /** Whether the message is a proof */ + isProof: boolean; + }; + /** The elements of the embedded message */ + readonly elements?: { + /** The title of the embedded message */ + title?: string; + /** The body of the embedded message */ + body?: string; + /** The media url of the embedded message */ + mediaUrl?: string; + /** The media url caption of the embedded message */ + mediaUrlCaption?: string; + /** The default action of the embedded message */ + defaultAction?: { + /** The type of action */ + type: string; + /** The url for the action when the type is `openUrl` */ + data?: string; + }; + /** The buttons of the embedded message */ + buttons?: IterableEmbeddedMessageButton[]; + /** The text of the embedded message */ + text?: IterableEmbeddedMessageText[]; + }; + /** The custom payload of the embedded message */ + readonly payload?: Record; + + /** + * Creates an instance of `IterableEmbeddedMessage`. + * + * @param dict - The dictionary object containing the properties to initialize the `IterableEmbeddedMessage` instance. + */ + constructor(dict: EmbeddedMessageDict) { + if (!dict.metadata) { + throw new Error('metadata is required'); + } + this.metadata = { + messageId: dict.metadata.messageId, + placementId: dict.metadata.placementId, + campaignId: dict.metadata.campaignId, + isProof: dict.metadata.isProof, + }; + + if (dict.elements) { + this.elements = { + title: dict.elements?.title, + body: dict.elements?.body, + mediaUrl: dict.elements?.mediaUrl, + mediaUrlCaption: dict.elements?.mediaUrlCaption, + }; + + if (dict.elements?.defaultAction) { + this.elements.defaultAction = { + type: dict.elements.defaultAction.type, + data: dict.elements.defaultAction.data, + }; + } + + if (dict.elements?.buttons) { + this.elements.buttons = dict.elements.buttons.map( + (button) => new IterableEmbeddedMessageButton(button) + ); + } + + if (dict.elements?.text) { + this.elements.text = dict.elements.text.map( + (text) => new IterableEmbeddedMessageText(text) + ); + } + } + + this.payload = dict.payload; + } +} + +/** + * An interface defining the dictionary object containing the properties for the embedded message. + */ +export interface EmbeddedMessageDict { + /** The metadata of the embedded message */ + metadata: { + /** The id of the message */ + messageId: string; + /** The placement id of the message */ + placementId: number; + /** The campaign id of the message */ + campaignId?: number; + /** Whether the message is a proof */ + isProof: boolean; + }; + /** The elements of the embedded message */ + elements?: { + /** The title of the embedded message */ + title?: string; + /** The body of the embedded message */ + body?: string; + /** The media url of the embedded message */ + mediaUrl?: string; + /** The media url caption of the embedded message */ + mediaUrlCaption?: string; + /** The default action of the embedded message */ + defaultAction?: { + /** The type of action */ + type: string; + /** The url for the action when the type is `openUrl` */ + data?: string; + }; + /** The buttons of the embedded message */ + buttons?: IterableEmbeddedMessageButton[]; + /** The text of the embedded message */ + text?: IterableEmbeddedMessageText[]; + }; + /** The custom payload of the embedded message */ + payload?: Record; +} diff --git a/src/embedded/classes/IterableEmbeddedMessageButton.ts b/src/embedded/classes/IterableEmbeddedMessageButton.ts new file mode 100644 index 000000000..9a0896d96 --- /dev/null +++ b/src/embedded/classes/IterableEmbeddedMessageButton.ts @@ -0,0 +1,54 @@ +/** + * IterableEmbeddedMessageElementsButton represents a button in an embedded message. + */ +export class IterableEmbeddedMessageButton { + /** The ID for the embedded message button */ + readonly id: string; + /** The title for the embedded message button */ + readonly title?: string; + /** The action for the embedded message button */ + readonly action?: { + /** The type of action */ + type: string; + /** The url for the action when the type is `openUrl` */ + data?: string; + }; + + /** + * Creates an instance of IterableEmbeddedMessageButton. + * + * @param dict - The dictionary object containing the properties to initialize the `IterableEmbeddedMessageButton` instance. + */ + constructor(dict: EmbeddedMessageElementsButtonDict) { + if (!dict.id) { + throw new Error('id is required'); + } + + this.id = dict.id; + this.title = dict.title; + + if (dict.action) { + this.action = { + type: dict.action.type, + data: dict.action.data, + }; + } + } +} + +/** + * An interface defining the dictionary object containing the properties for the embedded message button. + */ +export interface EmbeddedMessageElementsButtonDict { + /** The ID for the embedded message button */ + id: string; + /** The title for the embedded message button */ + title?: string; + /** The action for the embedded message button */ + action?: { + /** The type of action */ + type: string; + /** The url for the action when the type is `openUrl` */ + data?: string; + }; +} diff --git a/src/embedded/classes/IterableEmbeddedMessageText.ts b/src/embedded/classes/IterableEmbeddedMessageText.ts new file mode 100644 index 000000000..3b88dc8a8 --- /dev/null +++ b/src/embedded/classes/IterableEmbeddedMessageText.ts @@ -0,0 +1,40 @@ +/** + * IterableEmbeddedMessageText represents a text element in an embedded message. + */ +export class IterableEmbeddedMessageText { + /** The id of the text element */ + readonly id: string; + /** The text of the text element */ + readonly text?: string; + /** The type of the text element */ + readonly type?: string; + + /** + * Creates an instance of `IterableEmbeddedMessageText`. + * + * @param id - The id of the text element + * @param text - The text of the text element + * @param type - The type of the text element + */ + constructor(dict: EmbeddedMessageTextDict) { + if (!dict.id) { + throw new Error('id is required'); + } + + this.id = dict.id; + this.text = dict.text; + this.type = dict.type; + } +} + +/** + * An interface defining the dictionary object containing the properties for an embedded message text. + */ +export interface EmbeddedMessageTextDict { + /** The id of the text element */ + id: string; + /** The text of the text element */ + text?: string; + /** The type of the text element */ + type?: string; +} diff --git a/src/embedded/classes/IterableEmbeddedPlacement.ts b/src/embedded/classes/IterableEmbeddedPlacement.ts new file mode 100644 index 000000000..6a02aabfe --- /dev/null +++ b/src/embedded/classes/IterableEmbeddedPlacement.ts @@ -0,0 +1,11 @@ +/** + * Iterable embedded placement + * Contains placement id and the associated embedded messages + */ +export class IterableEmbeddedPlacement { + readonly placementId: number; + + constructor(placementId: number) { + this.placementId = placementId; + } +} diff --git a/src/embedded/classes/index.ts b/src/embedded/classes/index.ts new file mode 100644 index 000000000..2a2abba63 --- /dev/null +++ b/src/embedded/classes/index.ts @@ -0,0 +1,5 @@ +export * from './IterableEmbeddedManager'; +export * from './IterableEmbeddedPlacement'; +export * from './IterableEmbeddedMessage'; +export * from './IterableEmbeddedMessageButton'; +export * from './IterableEmbeddedMessageText'; diff --git a/src/embedded/index.ts b/src/embedded/index.ts new file mode 100644 index 000000000..d7d17c691 --- /dev/null +++ b/src/embedded/index.ts @@ -0,0 +1 @@ +export * from './classes'; diff --git a/src/index.tsx b/src/index.tsx index 885cd74bd..8f13478c5 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -25,6 +25,10 @@ export { type IterableDeviceOrientation, } from './core/hooks'; export { type IterableEdgeInsetDetails } from './core/types'; +export { + IterableEmbeddedManager, + IterableEmbeddedPlacement, +} from './embedded/classes'; export { IterableHtmlInAppContent, IterableInAppCloseSource,