@repzo/widget-react-native 1.1.0 → 1.2.1

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.
Files changed (107) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +92 -3
  3. package/lib/commonjs/api/client.js +35 -0
  4. package/lib/commonjs/api/client.js.map +1 -1
  5. package/lib/commonjs/i18n.js +14 -0
  6. package/lib/commonjs/i18n.js.map +1 -1
  7. package/lib/commonjs/index.js +2 -1
  8. package/lib/commonjs/index.js.map +1 -1
  9. package/lib/commonjs/locales.js +13 -0
  10. package/lib/commonjs/locales.js.map +1 -1
  11. package/lib/commonjs/push/push-notifications.js +65 -8
  12. package/lib/commonjs/push/push-notifications.js.map +1 -1
  13. package/lib/commonjs/state/widget-store.js +451 -7
  14. package/lib/commonjs/state/widget-store.js.map +1 -1
  15. package/lib/commonjs/types.js +15 -0
  16. package/lib/commonjs/types.js.map +1 -1
  17. package/lib/commonjs/ui/WidgetProvider.js +64 -2
  18. package/lib/commonjs/ui/WidgetProvider.js.map +1 -1
  19. package/lib/commonjs/ui/components/Post.js +1241 -0
  20. package/lib/commonjs/ui/components/Post.js.map +1 -0
  21. package/lib/commonjs/ui/utils/html.js +1 -0
  22. package/lib/commonjs/ui/utils/html.js.map +1 -1
  23. package/lib/commonjs/ui/utils/post-html.js +276 -0
  24. package/lib/commonjs/ui/utils/post-html.js.map +1 -0
  25. package/lib/commonjs/ui/utils/safe-url.js +16 -0
  26. package/lib/commonjs/ui/utils/safe-url.js.map +1 -1
  27. package/lib/module/api/client.js +35 -0
  28. package/lib/module/api/client.js.map +1 -1
  29. package/lib/module/i18n.js +14 -0
  30. package/lib/module/i18n.js.map +1 -1
  31. package/lib/module/index.js +2 -1
  32. package/lib/module/index.js.map +1 -1
  33. package/lib/module/locales.js +13 -0
  34. package/lib/module/locales.js.map +1 -1
  35. package/lib/module/push/push-notifications.js +65 -8
  36. package/lib/module/push/push-notifications.js.map +1 -1
  37. package/lib/module/state/widget-store.js +450 -6
  38. package/lib/module/state/widget-store.js.map +1 -1
  39. package/lib/module/types.js +15 -0
  40. package/lib/module/types.js.map +1 -1
  41. package/lib/module/ui/WidgetProvider.js +65 -3
  42. package/lib/module/ui/WidgetProvider.js.map +1 -1
  43. package/lib/module/ui/components/Post.js +1236 -0
  44. package/lib/module/ui/components/Post.js.map +1 -0
  45. package/lib/module/ui/utils/html.js +1 -1
  46. package/lib/module/ui/utils/html.js.map +1 -1
  47. package/lib/module/ui/utils/post-html.js +271 -0
  48. package/lib/module/ui/utils/post-html.js.map +1 -0
  49. package/lib/module/ui/utils/safe-url.js +15 -0
  50. package/lib/module/ui/utils/safe-url.js.map +1 -1
  51. package/lib/typescript/commonjs/api/client.d.ts +21 -1
  52. package/lib/typescript/commonjs/api/client.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/i18n.d.ts +13 -0
  54. package/lib/typescript/commonjs/i18n.d.ts.map +1 -1
  55. package/lib/typescript/commonjs/index.d.ts +14 -1
  56. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  57. package/lib/typescript/commonjs/locales.d.ts.map +1 -1
  58. package/lib/typescript/commonjs/push/push-notifications.d.ts +26 -2
  59. package/lib/typescript/commonjs/push/push-notifications.d.ts.map +1 -1
  60. package/lib/typescript/commonjs/state/widget-store.d.ts +84 -1
  61. package/lib/typescript/commonjs/state/widget-store.d.ts.map +1 -1
  62. package/lib/typescript/commonjs/types.d.ts +77 -0
  63. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  64. package/lib/typescript/commonjs/ui/WidgetProvider.d.ts.map +1 -1
  65. package/lib/typescript/commonjs/ui/components/Post.d.ts +69 -0
  66. package/lib/typescript/commonjs/ui/components/Post.d.ts.map +1 -0
  67. package/lib/typescript/commonjs/ui/utils/html.d.ts +1 -0
  68. package/lib/typescript/commonjs/ui/utils/html.d.ts.map +1 -1
  69. package/lib/typescript/commonjs/ui/utils/post-html.d.ts +54 -0
  70. package/lib/typescript/commonjs/ui/utils/post-html.d.ts.map +1 -0
  71. package/lib/typescript/commonjs/ui/utils/safe-url.d.ts +6 -0
  72. package/lib/typescript/commonjs/ui/utils/safe-url.d.ts.map +1 -1
  73. package/lib/typescript/module/api/client.d.ts +21 -1
  74. package/lib/typescript/module/api/client.d.ts.map +1 -1
  75. package/lib/typescript/module/i18n.d.ts +13 -0
  76. package/lib/typescript/module/i18n.d.ts.map +1 -1
  77. package/lib/typescript/module/index.d.ts +14 -1
  78. package/lib/typescript/module/index.d.ts.map +1 -1
  79. package/lib/typescript/module/locales.d.ts.map +1 -1
  80. package/lib/typescript/module/push/push-notifications.d.ts +26 -2
  81. package/lib/typescript/module/push/push-notifications.d.ts.map +1 -1
  82. package/lib/typescript/module/state/widget-store.d.ts +84 -1
  83. package/lib/typescript/module/state/widget-store.d.ts.map +1 -1
  84. package/lib/typescript/module/types.d.ts +77 -0
  85. package/lib/typescript/module/types.d.ts.map +1 -1
  86. package/lib/typescript/module/ui/WidgetProvider.d.ts.map +1 -1
  87. package/lib/typescript/module/ui/components/Post.d.ts +69 -0
  88. package/lib/typescript/module/ui/components/Post.d.ts.map +1 -0
  89. package/lib/typescript/module/ui/utils/html.d.ts +1 -0
  90. package/lib/typescript/module/ui/utils/html.d.ts.map +1 -1
  91. package/lib/typescript/module/ui/utils/post-html.d.ts +54 -0
  92. package/lib/typescript/module/ui/utils/post-html.d.ts.map +1 -0
  93. package/lib/typescript/module/ui/utils/safe-url.d.ts +6 -0
  94. package/lib/typescript/module/ui/utils/safe-url.d.ts.map +1 -1
  95. package/package.json +1 -1
  96. package/src/api/client.ts +32 -0
  97. package/src/i18n.ts +14 -0
  98. package/src/index.tsx +17 -0
  99. package/src/locales.ts +13 -0
  100. package/src/push/push-notifications.ts +74 -8
  101. package/src/state/widget-store.ts +429 -6
  102. package/src/types.ts +77 -0
  103. package/src/ui/WidgetProvider.tsx +78 -2
  104. package/src/ui/components/Post.tsx +943 -0
  105. package/src/ui/utils/html.ts +1 -1
  106. package/src/ui/utils/post-html.ts +256 -0
  107. package/src/ui/utils/safe-url.ts +15 -0
@@ -6,7 +6,7 @@
6
6
  * the modal (or never mounting it) never drops a conversation.
7
7
  */
8
8
 
9
- import { useCallback, useMemo } from 'react';
9
+ import { useCallback, useEffect, useMemo, useState } from 'react';
10
10
  import {
11
11
  ActivityIndicator,
12
12
  Modal,
@@ -29,10 +29,11 @@ import {
29
29
  import { controller } from '../controller';
30
30
  import { buildLabels, createTranslator, formatLabel, localizeWelcomeText } from '../i18n';
31
31
  import { useWidgetState } from '../state/use-widget-state';
32
- import type { AgentUiAction, OutgoingAttachment, WidgetSpaceType } from '../types';
32
+ import type { AgentUiAction, OutgoingAttachment, PostInteractionKind, WidgetSpaceType } from '../types';
33
33
  import { WidgetErrorBoundary } from './components/ErrorBoundary';
34
34
  import { AlertIcon } from './components/icons';
35
35
  import { InAppNotification } from './components/InAppNotification';
36
+ import { PostOverlay } from './components/Post';
36
37
  import { OutboundMessageCard } from './components/OutboundMessageCard';
37
38
  import { WidgetPanel } from './components/WidgetPanel';
38
39
  import { useKeyboardOverlap } from './hooks/use-keyboard-overlap';
@@ -62,6 +63,9 @@ export interface RepzoWidgetProviderProps {
62
63
  presentationStyle?: 'pageSheet' | 'fullScreen';
63
64
  }
64
65
 
66
+ /** Longest the messenger's iOS slide-out is waited on when `onDismiss` doesn't arrive. */
67
+ const MESSENGER_DISMISS_FALLBACK_MS = 600;
68
+
65
69
  export function RepzoWidgetProvider({
66
70
  children,
67
71
  presentationStyle = 'pageSheet',
@@ -235,6 +239,57 @@ export function RepzoWidgetProvider({
235
239
  );
236
240
  const handleDismissNotification = useCallback(() => store.dismissInAppNotification(), [store]);
237
241
 
242
+ // iOS can't present the post's modal while the messenger's is still sliding
243
+ // away (it would silently never show), so a post waits for that to finish.
244
+ // `onDismiss` is the signal; the timer covers React Native versions where it
245
+ // doesn't fire.
246
+ const [messengerOnScreen, setMessengerOnScreen] = useState(state.isOpen);
247
+ useEffect(() => {
248
+ if (state.isOpen || Platform.OS !== 'ios') {
249
+ setMessengerOnScreen(state.isOpen);
250
+ return undefined;
251
+ }
252
+ const timer = setTimeout(() => setMessengerOnScreen(false), MESSENGER_DISMISS_FALLBACK_MS);
253
+ return () => clearTimeout(timer);
254
+ }, [state.isOpen]);
255
+ const handleMessengerDismiss = useCallback(() => setMessengerOnScreen(false), []);
256
+
257
+ const handlePostShown = useCallback((campaignId: string) => store.postDidShow(campaignId), [store]);
258
+ const handlePostExpand = useCallback((campaignId: string) => store.expandPost(campaignId), [store]);
259
+ const handlePostMinimize = useCallback((campaignId: string) => store.minimizePost(campaignId), [store]);
260
+ const handlePostCollapse = useCallback((campaignId: string) => store.collapsePost(campaignId), [store]);
261
+ // The post steps aside first: iOS can't present the messenger while the post's modal is still up.
262
+ const handlePostOpenConversation = useCallback(
263
+ (campaignId: string, conversationId: string) => {
264
+ store.collapsePost(campaignId);
265
+ setTimeout(() => void store.openConversation(conversationId), Platform.OS === 'ios' ? 400 : 0);
266
+ },
267
+ [store]
268
+ );
269
+ const handlePostInteract = useCallback(
270
+ (campaignId: string, kind: Exclude<PostInteractionKind, 'view' | 'open' | 'minimize'>, value?: string) =>
271
+ store.recordPostInteraction(campaignId, kind, value),
272
+ [store]
273
+ );
274
+ const postLabels = useMemo(
275
+ () => ({
276
+ from: labels.postFrom,
277
+ newMessage: labels.postNewMessage,
278
+ openHint: labels.postOpenHint,
279
+ close: labels.postClose,
280
+ minimize: labels.postMinimize,
281
+ replyPlaceholder: labels.postReplyPlaceholder,
282
+ send: labels.postSend,
283
+ sent: labels.postSent,
284
+ replyFailed: labels.postReplyFailed,
285
+ reactions: labels.postReactions,
286
+ thanks: labels.postThanks,
287
+ conversation: labels.postConversation,
288
+ continueChat: labels.postContinueChat,
289
+ }),
290
+ [labels]
291
+ );
292
+
238
293
  const handleTabChange = useCallback((tab: WidgetSpaceType) => store.setActiveTab(tab), [store]);
239
294
 
240
295
  // Rejections reach ChatView, which keeps unsent attachments for a retry.
@@ -463,6 +518,26 @@ export function RepzoWidgetProvider({
463
518
  return (
464
519
  <>
465
520
  {children}
521
+ {/* A post steps aside while the messenger is open, and its card while a reply card shows. */}
522
+ {state.post && !state.isOpen && !messengerOnScreen && (state.postExpanded || !state.inAppNotification) ? (
523
+ <WidgetErrorBoundary resetKey={state.post.id} fallback={() => null}>
524
+ <PostOverlay
525
+ // A new post remounts, so it reports its view.
526
+ key={state.post.id}
527
+ post={state.post}
528
+ expanded={state.postExpanded}
529
+ color={theme.primaryColor}
530
+ insets={insets}
531
+ labels={postLabels}
532
+ onShown={handlePostShown}
533
+ onExpand={handlePostExpand}
534
+ onMinimize={handlePostMinimize}
535
+ onCollapse={handlePostCollapse}
536
+ onOpenConversation={handlePostOpenConversation}
537
+ onInteract={handlePostInteract}
538
+ />
539
+ </WidgetErrorBoundary>
540
+ ) : null}
466
541
  {state.inAppNotification ? (
467
542
  <InAppNotification
468
543
  // A new reply remounts the card, so it slides in fresh.
@@ -486,6 +561,7 @@ export function RepzoWidgetProvider({
486
561
  animationType="slide"
487
562
  presentationStyle={Platform.OS === 'ios' ? presentationStyle : undefined}
488
563
  onRequestClose={handleClose}
564
+ onDismiss={handleMessengerDismiss}
489
565
  // Edge to edge on every Android version, so the insets below are the
490
566
  // only top spacing (a non-translucent modal used to add a second one).
491
567
  statusBarTranslucent>