@sendoracloud/sdk-react-native 1.3.0 → 1.4.0

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.
@@ -31,7 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var contact_widget_exports = {};
32
32
  __export(contact_widget_exports, {
33
33
  ContactWidget: () => ContactWidget,
34
- useContactWidget: () => useContactWidget
34
+ TicketHistory: () => TicketHistory,
35
+ useContactWidget: () => useContactWidget,
36
+ useTicketHistory: () => useTicketHistory
35
37
  });
36
38
  module.exports = __toCommonJS(contact_widget_exports);
37
39
  var React = __toESM(require("react"), 1);
@@ -134,8 +136,87 @@ function useContactWidget(widgetId, defaults) {
134
136
  );
135
137
  return { open, close, View: View2, lastResult };
136
138
  }
139
+ function TicketHistory({
140
+ visible,
141
+ widgetId,
142
+ accessToken,
143
+ workerHost = "https://go.sendoracloud.com",
144
+ theme = "auto",
145
+ onClose
146
+ }) {
147
+ const didFire = React.useRef(false);
148
+ React.useEffect(() => {
149
+ if (visible) didFire.current = false;
150
+ }, [visible]);
151
+ if (!widgetId || !accessToken) return null;
152
+ const params = new URLSearchParams({ widgetId, theme });
153
+ const uri = `${workerHost}/embed/tickets?${params.toString()}#access=${encodeURIComponent(accessToken)}`;
154
+ const handleClose = (result) => {
155
+ if (didFire.current) return;
156
+ didFire.current = true;
157
+ onClose(result);
158
+ };
159
+ const onNav = (req) => {
160
+ const url = req.url || "";
161
+ if (url.startsWith("sendora://close")) {
162
+ handleClose({ ticketId: "", portalUrl: null, submitted: false });
163
+ return false;
164
+ }
165
+ if (!url.startsWith("https://") && !url.startsWith("about:")) return false;
166
+ return true;
167
+ };
168
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
169
+ import_react_native.Modal,
170
+ {
171
+ visible,
172
+ animationType: "slide",
173
+ presentationStyle: "pageSheet",
174
+ onRequestClose: () => handleClose({ ticketId: "", portalUrl: null, submitted: false }),
175
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
176
+ import_react_native_webview.WebView,
177
+ {
178
+ source: { uri },
179
+ onShouldStartLoadWithRequest: onNav,
180
+ originWhitelist: ["https://*", "about:*", "sendora://*"],
181
+ setSupportMultipleWindows: false,
182
+ javaScriptEnabled: true,
183
+ domStorageEnabled: true,
184
+ allowsBackForwardNavigationGestures: false
185
+ }
186
+ ) })
187
+ }
188
+ );
189
+ }
190
+ function useTicketHistory(widgetId, getAccessToken, defaults) {
191
+ const [visible, setVisible] = React.useState(false);
192
+ const [token, setToken] = React.useState(null);
193
+ const open = React.useCallback(async () => {
194
+ const t = await getAccessToken();
195
+ if (!t) return;
196
+ setToken(t);
197
+ setVisible(true);
198
+ }, [getAccessToken]);
199
+ const close = React.useCallback(() => setVisible(false), []);
200
+ const View2 = React.useCallback(
201
+ () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
202
+ TicketHistory,
203
+ {
204
+ widgetId,
205
+ visible,
206
+ accessToken: token,
207
+ workerHost: defaults?.workerHost,
208
+ theme: defaults?.theme,
209
+ onClose: () => setVisible(false)
210
+ }
211
+ ),
212
+ [widgetId, visible, token, defaults]
213
+ );
214
+ return { open, close, View: View2 };
215
+ }
137
216
  // Annotate the CommonJS export names for ESM import in node:
138
217
  0 && (module.exports = {
139
218
  ContactWidget,
140
- useContactWidget
219
+ TicketHistory,
220
+ useContactWidget,
221
+ useTicketHistory
141
222
  });
@@ -99,5 +99,40 @@ declare function useContactWidget(widgetId: string, defaults?: Omit<ContactWidge
99
99
  View: () => React.ReactElement | null;
100
100
  lastResult: ContactWidgetResult | null;
101
101
  };
102
+ interface TicketHistoryProps {
103
+ /** Whether the modal sheet is visible. */
104
+ visible: boolean;
105
+ /** Widget UUID that scopes the org. */
106
+ widgetId: string;
107
+ /**
108
+ * Current SDK access token (from `SendoraCloud.auth.getAccessToken()`).
109
+ * Passed in the URL hash fragment so it never appears in server
110
+ * logs / referer headers. Embed scrubs the hash on load.
111
+ * The widget is no-op when this is null/empty.
112
+ */
113
+ accessToken: string | null | undefined;
114
+ workerHost?: string;
115
+ theme?: "auto" | "light" | "dark";
116
+ onClose: (result: ContactWidgetResult) => void;
117
+ }
118
+ declare function TicketHistory({ visible, widgetId, accessToken, workerHost, theme, onClose, }: TicketHistoryProps): React.ReactElement | null;
119
+ /**
120
+ * Convenience hook for the ticket history view. Takes the SDK's
121
+ * `getAccessToken` helper (deferred — called lazily on open) so the
122
+ * host doesn't have to thread token state by hand.
123
+ *
124
+ * import SendoraCloud from "@sendoracloud/sdk-react-native";
125
+ * const history = useTicketHistory("widget-uuid", () => SendoraCloud.auth.getAccessToken());
126
+ * <Button onPress={history.open} title="My tickets" />
127
+ * <history.View />
128
+ */
129
+ declare function useTicketHistory(widgetId: string, getAccessToken: () => Promise<string | null>, defaults?: {
130
+ workerHost?: string;
131
+ theme?: "auto" | "light" | "dark";
132
+ }): {
133
+ open: () => void;
134
+ close: () => void;
135
+ View: () => React.ReactElement | null;
136
+ };
102
137
 
103
- export { ContactWidget, type ContactWidgetProps, type ContactWidgetResult, useContactWidget };
138
+ export { ContactWidget, type ContactWidgetProps, type ContactWidgetResult, TicketHistory, type TicketHistoryProps, useContactWidget, useTicketHistory };
@@ -99,5 +99,40 @@ declare function useContactWidget(widgetId: string, defaults?: Omit<ContactWidge
99
99
  View: () => React.ReactElement | null;
100
100
  lastResult: ContactWidgetResult | null;
101
101
  };
102
+ interface TicketHistoryProps {
103
+ /** Whether the modal sheet is visible. */
104
+ visible: boolean;
105
+ /** Widget UUID that scopes the org. */
106
+ widgetId: string;
107
+ /**
108
+ * Current SDK access token (from `SendoraCloud.auth.getAccessToken()`).
109
+ * Passed in the URL hash fragment so it never appears in server
110
+ * logs / referer headers. Embed scrubs the hash on load.
111
+ * The widget is no-op when this is null/empty.
112
+ */
113
+ accessToken: string | null | undefined;
114
+ workerHost?: string;
115
+ theme?: "auto" | "light" | "dark";
116
+ onClose: (result: ContactWidgetResult) => void;
117
+ }
118
+ declare function TicketHistory({ visible, widgetId, accessToken, workerHost, theme, onClose, }: TicketHistoryProps): React.ReactElement | null;
119
+ /**
120
+ * Convenience hook for the ticket history view. Takes the SDK's
121
+ * `getAccessToken` helper (deferred — called lazily on open) so the
122
+ * host doesn't have to thread token state by hand.
123
+ *
124
+ * import SendoraCloud from "@sendoracloud/sdk-react-native";
125
+ * const history = useTicketHistory("widget-uuid", () => SendoraCloud.auth.getAccessToken());
126
+ * <Button onPress={history.open} title="My tickets" />
127
+ * <history.View />
128
+ */
129
+ declare function useTicketHistory(widgetId: string, getAccessToken: () => Promise<string | null>, defaults?: {
130
+ workerHost?: string;
131
+ theme?: "auto" | "light" | "dark";
132
+ }): {
133
+ open: () => void;
134
+ close: () => void;
135
+ View: () => React.ReactElement | null;
136
+ };
102
137
 
103
- export { ContactWidget, type ContactWidgetProps, type ContactWidgetResult, useContactWidget };
138
+ export { ContactWidget, type ContactWidgetProps, type ContactWidgetResult, TicketHistory, type TicketHistoryProps, useContactWidget, useTicketHistory };
@@ -99,7 +99,86 @@ function useContactWidget(widgetId, defaults) {
99
99
  );
100
100
  return { open, close, View: View2, lastResult };
101
101
  }
102
+ function TicketHistory({
103
+ visible,
104
+ widgetId,
105
+ accessToken,
106
+ workerHost = "https://go.sendoracloud.com",
107
+ theme = "auto",
108
+ onClose
109
+ }) {
110
+ const didFire = React.useRef(false);
111
+ React.useEffect(() => {
112
+ if (visible) didFire.current = false;
113
+ }, [visible]);
114
+ if (!widgetId || !accessToken) return null;
115
+ const params = new URLSearchParams({ widgetId, theme });
116
+ const uri = `${workerHost}/embed/tickets?${params.toString()}#access=${encodeURIComponent(accessToken)}`;
117
+ const handleClose = (result) => {
118
+ if (didFire.current) return;
119
+ didFire.current = true;
120
+ onClose(result);
121
+ };
122
+ const onNav = (req) => {
123
+ const url = req.url || "";
124
+ if (url.startsWith("sendora://close")) {
125
+ handleClose({ ticketId: "", portalUrl: null, submitted: false });
126
+ return false;
127
+ }
128
+ if (!url.startsWith("https://") && !url.startsWith("about:")) return false;
129
+ return true;
130
+ };
131
+ return /* @__PURE__ */ jsx(
132
+ Modal,
133
+ {
134
+ visible,
135
+ animationType: "slide",
136
+ presentationStyle: "pageSheet",
137
+ onRequestClose: () => handleClose({ ticketId: "", portalUrl: null, submitted: false }),
138
+ children: /* @__PURE__ */ jsx(View, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
139
+ WebView,
140
+ {
141
+ source: { uri },
142
+ onShouldStartLoadWithRequest: onNav,
143
+ originWhitelist: ["https://*", "about:*", "sendora://*"],
144
+ setSupportMultipleWindows: false,
145
+ javaScriptEnabled: true,
146
+ domStorageEnabled: true,
147
+ allowsBackForwardNavigationGestures: false
148
+ }
149
+ ) })
150
+ }
151
+ );
152
+ }
153
+ function useTicketHistory(widgetId, getAccessToken, defaults) {
154
+ const [visible, setVisible] = React.useState(false);
155
+ const [token, setToken] = React.useState(null);
156
+ const open = React.useCallback(async () => {
157
+ const t = await getAccessToken();
158
+ if (!t) return;
159
+ setToken(t);
160
+ setVisible(true);
161
+ }, [getAccessToken]);
162
+ const close = React.useCallback(() => setVisible(false), []);
163
+ const View2 = React.useCallback(
164
+ () => /* @__PURE__ */ jsx(
165
+ TicketHistory,
166
+ {
167
+ widgetId,
168
+ visible,
169
+ accessToken: token,
170
+ workerHost: defaults?.workerHost,
171
+ theme: defaults?.theme,
172
+ onClose: () => setVisible(false)
173
+ }
174
+ ),
175
+ [widgetId, visible, token, defaults]
176
+ );
177
+ return { open, close, View: View2 };
178
+ }
102
179
  export {
103
180
  ContactWidget,
104
- useContactWidget
181
+ TicketHistory,
182
+ useContactWidget,
183
+ useTicketHistory
105
184
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendoracloud/sdk-react-native",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Sendora Cloud React Native + Expo SDK — analytics, identity, push-token registration, auth, deep links (Branch / Firebase Dynamic Links parity). Auth + analytics + deep links work in Expo Go; push token registration requires a Dev Client (EAS Build or `npx expo prebuild`).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",