@rematter/pylon-react-native 0.1.4
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/README.md +503 -0
- package/RNPylonChat.podspec +33 -0
- package/android/build.gradle +74 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/com/pylon/chatwidget/Pylon.kt +149 -0
- package/android/src/main/java/com/pylon/chatwidget/PylonChat.kt +715 -0
- package/android/src/main/java/com/pylon/chatwidget/PylonChatController.kt +63 -0
- package/android/src/main/java/com/pylon/chatwidget/PylonChatListener.kt +76 -0
- package/android/src/main/java/com/pylon/chatwidget/PylonChatView.kt +7 -0
- package/android/src/main/java/com/pylon/chatwidget/PylonConfig.kt +62 -0
- package/android/src/main/java/com/pylon/chatwidget/PylonDebugView.kt +76 -0
- package/android/src/main/java/com/pylon/chatwidget/PylonUser.kt +41 -0
- package/android/src/main/java/com/pylonchat/reactnative/RNPylonChatPackage.kt +17 -0
- package/android/src/main/java/com/pylonchat/reactnative/RNPylonChatView.kt +298 -0
- package/android/src/main/java/com/pylonchat/reactnative/RNPylonChatViewManager.kt +201 -0
- package/ios/PylonChat/PylonChat.swift +865 -0
- package/ios/RNPylonChatView.swift +332 -0
- package/ios/RNPylonChatViewManager.m +55 -0
- package/ios/RNPylonChatViewManager.swift +23 -0
- package/lib/PylonChatView.d.ts +27 -0
- package/lib/PylonChatView.js +78 -0
- package/lib/PylonChatWidget.android.d.ts +19 -0
- package/lib/PylonChatWidget.android.js +144 -0
- package/lib/PylonChatWidget.ios.d.ts +14 -0
- package/lib/PylonChatWidget.ios.js +79 -0
- package/lib/PylonModule.d.ts +32 -0
- package/lib/PylonModule.js +44 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +15 -0
- package/lib/types.d.ts +34 -0
- package/lib/types.js +2 -0
- package/package.json +39 -0
- package/src/PylonChatView.tsx +170 -0
- package/src/PylonChatWidget.android.tsx +165 -0
- package/src/PylonChatWidget.d.ts +15 -0
- package/src/PylonChatWidget.ios.tsx +79 -0
- package/src/PylonModule.ts +52 -0
- package/src/index.ts +15 -0
- package/src/types.ts +37 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
useCallback,
|
|
4
|
+
useImperativeHandle,
|
|
5
|
+
useRef,
|
|
6
|
+
} from "react";
|
|
7
|
+
import { StyleSheet } from "react-native";
|
|
8
|
+
import type {
|
|
9
|
+
PylonChatViewInternalRef,
|
|
10
|
+
PylonChatViewRef,
|
|
11
|
+
} from "./PylonChatView";
|
|
12
|
+
import { PylonChatView } from "./PylonChatView";
|
|
13
|
+
import type { PylonChatWidgetProps } from "./PylonChatWidget";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* iOS implementation - simple passthrough.
|
|
17
|
+
*
|
|
18
|
+
* iOS uses native hitTest for touch pass-through, so no proxy logic needed.
|
|
19
|
+
*
|
|
20
|
+
* State Management:
|
|
21
|
+
* - State lives entirely in native layer (no React state needed for iOS)
|
|
22
|
+
* - Imperative methods call native, which handles everything
|
|
23
|
+
* - Events are simply forwarded to user's listener
|
|
24
|
+
*/
|
|
25
|
+
export const PylonChatWidget = forwardRef<
|
|
26
|
+
PylonChatViewRef,
|
|
27
|
+
PylonChatWidgetProps
|
|
28
|
+
>(({ config, user, listener, style, topInset }, ref) => {
|
|
29
|
+
// Internal ref - typed as any since iOS doesn't need clickElementAtSelector.
|
|
30
|
+
const chatRef = useRef<PylonChatViewInternalRef>(null);
|
|
31
|
+
|
|
32
|
+
// Forward ref methods - all state managed in native layer
|
|
33
|
+
useImperativeHandle(ref, () => ({
|
|
34
|
+
openChat: () => chatRef.current?.openChat(),
|
|
35
|
+
closeChat: () => chatRef.current?.closeChat(),
|
|
36
|
+
showChatBubble: () => chatRef.current?.showChatBubble(),
|
|
37
|
+
hideChatBubble: () => chatRef.current?.hideChatBubble(),
|
|
38
|
+
showNewMessage: (message: string, isHtml?: boolean) =>
|
|
39
|
+
chatRef.current?.showNewMessage(message, isHtml),
|
|
40
|
+
setNewIssueCustomFields: (fields: Record<string, any>) =>
|
|
41
|
+
chatRef.current?.setNewIssueCustomFields(fields),
|
|
42
|
+
setTicketFormFields: (fields: Record<string, any>) =>
|
|
43
|
+
chatRef.current?.setTicketFormFields(fields),
|
|
44
|
+
updateEmailHash: (emailHash: string | null) =>
|
|
45
|
+
chatRef.current?.updateEmailHash(emailHash),
|
|
46
|
+
showTicketForm: (slug: string) => chatRef.current?.showTicketForm(slug),
|
|
47
|
+
showKnowledgeBaseArticle: (articleId: string) =>
|
|
48
|
+
chatRef.current?.showKnowledgeBaseArticle(articleId),
|
|
49
|
+
}));
|
|
50
|
+
|
|
51
|
+
// Event handlers - forward to user's listener
|
|
52
|
+
const handleChatOpened = useCallback(() => {
|
|
53
|
+
listener?.onChatOpened?.();
|
|
54
|
+
}, [listener]);
|
|
55
|
+
|
|
56
|
+
const handleChatClosed = useCallback(
|
|
57
|
+
(wasOpen: boolean) => {
|
|
58
|
+
listener?.onChatClosed?.(wasOpen);
|
|
59
|
+
},
|
|
60
|
+
[listener]
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<PylonChatView
|
|
65
|
+
ref={chatRef}
|
|
66
|
+
style={style || StyleSheet.absoluteFillObject}
|
|
67
|
+
config={config}
|
|
68
|
+
user={user}
|
|
69
|
+
topInset={topInset}
|
|
70
|
+
listener={{
|
|
71
|
+
...listener,
|
|
72
|
+
onChatOpened: handleChatOpened,
|
|
73
|
+
onChatClosed: handleChatClosed,
|
|
74
|
+
}}
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
PylonChatWidget.displayName = "PylonChatWidget";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { PylonConfig, PylonUser } from "./types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pylon SDK - Singleton for managing global configuration.
|
|
5
|
+
*
|
|
6
|
+
* Note: This is optional - you can also pass config directly to PylonChatView.
|
|
7
|
+
* This singleton is useful if you want to initialize once and reuse across multiple views.
|
|
8
|
+
*/
|
|
9
|
+
export class Pylon {
|
|
10
|
+
private static instance: Pylon;
|
|
11
|
+
private _config?: PylonConfig;
|
|
12
|
+
private _user?: PylonUser;
|
|
13
|
+
|
|
14
|
+
private constructor() {}
|
|
15
|
+
|
|
16
|
+
static get shared(): Pylon {
|
|
17
|
+
if (!Pylon.instance) {
|
|
18
|
+
Pylon.instance = new Pylon();
|
|
19
|
+
}
|
|
20
|
+
return Pylon.instance;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initialize the Pylon SDK with configuration.
|
|
25
|
+
*/
|
|
26
|
+
initialize(config: PylonConfig): void {
|
|
27
|
+
this._config = config;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Set the current user for the chat.
|
|
32
|
+
*/
|
|
33
|
+
setUser(user: PylonUser): void {
|
|
34
|
+
this._user = user;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get the current configuration.
|
|
39
|
+
*/
|
|
40
|
+
get config(): PylonConfig | undefined {
|
|
41
|
+
return this._config;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the current user.
|
|
46
|
+
*/
|
|
47
|
+
get user(): PylonUser | undefined {
|
|
48
|
+
return this._user;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export default Pylon.shared;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { PylonChatView } from "./PylonChatView";
|
|
2
|
+
export type {
|
|
3
|
+
PylonChatViewRef,
|
|
4
|
+
PylonChatViewInternalRef,
|
|
5
|
+
} from "./PylonChatView";
|
|
6
|
+
// React Native will automatically resolve to .ios.tsx or .android.tsx at runtime
|
|
7
|
+
// TypeScript just needs to find the types from one of them
|
|
8
|
+
export { PylonChatWidget } from "./PylonChatWidget";
|
|
9
|
+
export { Pylon, default as PylonSDK } from "./PylonModule";
|
|
10
|
+
export type {
|
|
11
|
+
InteractiveBound,
|
|
12
|
+
PylonChatListener,
|
|
13
|
+
PylonConfig,
|
|
14
|
+
PylonUser,
|
|
15
|
+
} from "./types";
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface PylonConfig {
|
|
2
|
+
appId: string;
|
|
3
|
+
enableLogging?: boolean;
|
|
4
|
+
primaryColor?: string;
|
|
5
|
+
debugMode?: boolean;
|
|
6
|
+
widgetBaseUrl?: string;
|
|
7
|
+
widgetScriptUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PylonUser {
|
|
11
|
+
email: string;
|
|
12
|
+
name: string;
|
|
13
|
+
avatarUrl?: string;
|
|
14
|
+
emailHash?: string;
|
|
15
|
+
accountId?: string;
|
|
16
|
+
accountExternalId?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface InteractiveBound {
|
|
20
|
+
selector: string;
|
|
21
|
+
left: number;
|
|
22
|
+
top: number;
|
|
23
|
+
right: number;
|
|
24
|
+
bottom: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface PylonChatListener {
|
|
28
|
+
onPylonLoaded?: () => void;
|
|
29
|
+
onPylonInitialized?: () => void;
|
|
30
|
+
onPylonReady?: () => void;
|
|
31
|
+
onMessageReceived?: (message: string) => void;
|
|
32
|
+
onChatOpened?: () => void;
|
|
33
|
+
onChatClosed?: (wasOpen: boolean) => void;
|
|
34
|
+
onPylonError?: (error: string) => void;
|
|
35
|
+
onUnreadCountChanged?: (count: number) => void;
|
|
36
|
+
onInteractiveBoundsChanged?: (bounds: InteractiveBound) => void;
|
|
37
|
+
}
|