@ahmedramez-org/nexus-chat 1.0.0-beta.4 → 1.0.0-beta.6

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 (3) hide show
  1. package/README.md +9 -4
  2. package/package.json +17 -1
  3. package/react.js +27 -3
package/README.md CHANGED
@@ -32,10 +32,15 @@ page's background colour, the chat is drawn smaller when floating or docked, and
32
32
  shimmers while the chat loads. `theme` is followed live; `locale` is read when the chat first opens.
33
33
 
34
34
  The Incorta cluster needs `iframe.inclusion.enabled` (and `frame-ancestors` set to the app's
35
- domains), and the user signed in to Incorta in that browser. The iframe reaches the Incorta
36
- session only where the browser allows third-party cookies: Chrome by default; Safari ("Prevent
37
- cross-site tracking" off), Firefox (a cookie exception for the Incorta site) and private windows
38
- need that setting.
35
+ domains). Where the browser keeps the Incorta session from the iframe (Safari, Firefox, private
36
+ windows), the chat shows Continue with Incorta: the browser asks the user to allow it once, and
37
+ the chat starts on their Incorta session. A user not signed in to Incorta signs in through a small
38
+ Incorta window that closes itself afterwards. No browser setting is needed.
39
+
40
+ While the user clicks or types in the app, the component tells the chat at most every ten seconds,
41
+ so Incorta's own idle timeout does not end the chat's session while the app is in use. A page that
42
+ places the iframe itself can do the same: `iframe.contentWindow.postMessage({ nexusChat: 'active' },
43
+ '<incorta origin>')`. If the session ends anyway, the chat shows Sign in to Incorta.
39
44
 
40
45
  ### Direct
41
46
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahmedramez-org/nexus-chat",
3
- "version": "1.0.0-beta.4",
3
+ "version": "1.0.0-beta.6",
4
4
  "description": "NexusChat for any app: a connector and React component that load the prebuilt chat from IncortaCopilot (or a pinned copy), and the host contract types and checks.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -33,6 +33,22 @@
33
33
  },
34
34
  "./package.json": "./package.json"
35
35
  },
36
+ "typesVersions": {
37
+ "*": {
38
+ "react": [
39
+ "./react.d.ts"
40
+ ],
41
+ "contract": [
42
+ "./contract/index.d.ts"
43
+ ],
44
+ "conformance": [
45
+ "./contract/conformance.d.ts"
46
+ ],
47
+ "host": [
48
+ "./contract/host.d.ts"
49
+ ]
50
+ }
51
+ },
36
52
  "files": [
37
53
  "index.js",
38
54
  "index.d.ts",
package/react.js CHANGED
@@ -181,6 +181,8 @@ const NARROW_VIEWPORT = 768;
181
181
  const REM_BASE = { floating: 16, docked: 16, fullscreen: 14 };
182
182
  /** If the page never says it is ready (an Incorta login page instead), stop the shimmer. */
183
183
  const READY_FALLBACK_MS = 5_000;
184
+ /** At most this often, the app tells the chat the user is working (the chat paces its session reads). */
185
+ const KEEP_ALIVE_MS = 10_000;
184
186
 
185
187
  const ICON = `data:image/svg+xml,${encodeURIComponent(
186
188
  "<svg width='107' height='120' viewBox='0 0 107 120' fill='none' xmlns='http://www.w3.org/2000/svg'><g clip-path='url(#clip0_108_873)'><path d='M84.0333 35.3749C89.81 37.6474 95.214 41.1522 99.8334 45.8891C102.44 48.5657 104.644 51.4847 106.465 54.5652L106.677 35.385C106.717 31.9611 104.936 28.7896 101.997 27.0423L63.1104 3.93311C66.1798 5.83193 69.078 8.13474 71.7147 10.8517C78.508 17.8208 82.604 26.4261 84.0333 35.3749Z' fill='url(#paint0_linear_108_873)'/><path d='M22.8859 84.8047C17.1092 82.532 11.7049 79.0273 7.0856 74.2907C4.35831 71.4927 2.07382 68.432 0.212009 65.2002L0.000668115 84.6433C-0.0395873 88.0667 1.74171 91.2387 4.68035 92.986L43.9092 116.297C40.7995 114.378 37.8709 112.055 35.204 109.328C28.4109 102.359 24.3149 93.7533 22.8859 84.8047Z' fill='url(#paint1_linear_108_873)'/><path d='M106.114 85.8249L106.456 54.5647C104.645 51.4841 102.431 48.5651 99.824 45.8886C95.2047 41.1517 89.8006 37.6469 84.024 35.3743C86.258 49.4237 81.9006 64.3012 71.0013 75.0076C57.878 87.8849 38.9278 91.1269 22.876 84.8149C24.305 93.7636 28.401 102.369 35.1941 109.338C37.861 112.075 40.7896 114.398 43.8993 116.307L45.1674 117.054L47.9148 118.69C48.891 119.266 49.9376 119.65 51.0144 119.862C53.1882 120.266 55.4626 119.923 57.4553 118.802L101.253 94.0663C104.222 92.3896 106.074 89.2489 106.114 85.8349V85.8249Z' fill='url(#paint2_linear_108_873)'/><path d='M35.908 45.1805C49.0312 32.3027 67.9813 29.0606 84.0333 35.3732C82.604 26.4245 78.508 17.8191 71.7153 10.85C69.0786 8.14313 66.18 5.84031 63.1106 3.93137L61.6714 3.07286L58.7529 1.33563C57.7063 0.709427 56.5691 0.315517 55.4118 0.123615C53.3184 -0.219791 51.1346 0.153915 49.2225 1.22453L5.41455 25.9699C2.44572 27.6465 0.593974 30.7877 0.553719 34.2015L0.211548 65.1889C2.07336 68.4313 4.35785 71.4813 7.08516 74.2787C11.7044 79.016 17.1088 82.5207 22.8854 84.7933C20.6512 70.744 25.0088 55.8664 35.908 45.1603V45.1805Z' fill='#00A098'/><path d='M22.8857 84.8051C22.9663 85.3104 23.0568 85.8251 23.1575 86.3304C23.1877 86.4917 23.2279 86.6637 23.2581 86.8251C23.3285 87.1684 23.399 87.5117 23.4795 87.8551C23.5197 88.0471 23.5701 88.2391 23.6103 88.4311C23.6909 88.7544 23.7713 89.0777 23.8619 89.4004C23.9123 89.5924 23.9626 89.7744 24.0129 89.9664C24.1236 90.3604 24.2443 90.7544 24.3651 91.1377C24.4457 91.3904 24.5261 91.6431 24.6067 91.8851C24.7073 92.1984 24.818 92.5117 24.9287 92.8244C25.0193 93.0671 25.1099 93.3197 25.2004 93.5617C25.291 93.7944 25.3715 94.0164 25.4621 94.2491C25.5627 94.5111 25.6734 94.7837 25.7841 95.0464C25.8647 95.2384 25.9451 95.4304 26.0357 95.6224C26.1565 95.9151 26.2873 96.1977 26.4181 96.4811C26.4584 96.5717 26.4987 96.6524 26.5389 96.7331C26.8609 97.4304 27.2031 98.1171 27.5654 98.8037C27.6057 98.8744 27.6359 98.9451 27.6761 99.0157C27.8573 99.3491 28.0384 99.6824 28.2297 100.006C28.29 100.117 28.3504 100.218 28.4108 100.329C28.602 100.662 28.7932 100.996 28.9945 101.319C29.0448 101.4 29.0951 101.47 29.1354 101.551C29.8399 102.682 30.5947 103.804 31.4098 104.884C31.8225 104.874 92.7287 102.874 96.2107 42.546C96.5533 36.6576 96.352 30.2238 95.486 23.1739L63.1109 3.93311C66.1804 5.83193 69.0787 8.13474 71.7153 10.8517C78.5087 17.8208 82.6047 26.4261 84.0333 35.3749C86.268 49.4242 81.91 64.3017 71.0113 75.0077C57.8878 87.8857 38.9376 91.1277 22.8857 84.8151V84.8051Z' fill='url(#paint3_linear_108_873)'/><path d='M84.0334 35.3745C83.9527 34.8695 83.862 34.3544 83.7614 33.8494C83.7314 33.6878 83.6914 33.5161 83.6607 33.3545C83.5907 33.0111 83.52 32.6677 83.4394 32.3243C83.3994 32.1324 83.3487 31.9405 83.3087 31.7486C83.228 31.4254 83.1474 31.1021 83.0574 30.7789C83.0067 30.5871 82.9567 30.4053 82.906 30.2133C82.7954 29.8195 82.6747 29.4255 82.554 29.0417C82.4734 28.7892 82.3927 28.5367 82.3127 28.2943C82.212 27.9812 82.1014 27.6681 81.99 27.355C81.9 27.1126 81.8094 26.8601 81.7187 26.6177C81.628 26.3854 81.5474 26.1632 81.4567 25.9309C81.356 25.6683 81.2454 25.3956 81.1347 25.133C81.0547 24.9411 80.974 24.7491 80.8834 24.5573C80.7627 24.2643 80.632 23.9815 80.5007 23.6987C80.4607 23.6079 80.4207 23.5271 80.38 23.4463C80.058 22.7493 79.716 22.0625 79.3534 21.3757C79.3134 21.305 79.2834 21.2343 79.2427 21.1636C79.062 20.8303 78.8807 20.497 78.6894 20.1738C78.6294 20.0627 78.5687 19.9617 78.508 19.8506C78.3174 19.5173 78.126 19.184 77.9247 18.8607C77.874 18.7799 77.824 18.7093 77.7834 18.6285C77.0794 17.4973 76.3247 16.3761 75.5094 15.2954C75.0967 15.3055 14.1902 17.3053 10.7082 77.6333C10.366 83.522 10.5673 89.956 11.4328 97.006L43.8082 116.247C40.7386 114.348 37.8403 112.045 35.2036 109.328C28.4104 102.359 24.3145 93.7533 22.8854 84.8047C20.6512 70.7553 25.0089 55.8779 35.908 45.1717C49.0313 32.294 67.9814 29.0518 84.0334 35.3644V35.3745Z' fill='url(#paint4_linear_108_873)'/></g><defs><linearGradient id='paint0_linear_108_873' x1='104.644' y1='41.0916' x2='52.1952' y2='1.61001' gradientUnits='userSpaceOnUse'><stop stop-color='#4854FE'/><stop offset='1' stop-color='#241C55'/></linearGradient><linearGradient id='paint1_linear_108_873' x1='0.000668115' y1='90.7533' x2='43.9092' y2='90.7533' gradientUnits='userSpaceOnUse'><stop stop-color='#4854FE'/><stop offset='1' stop-color='#241C55'/></linearGradient><linearGradient id='paint2_linear_108_873' x1='31.5078' y1='40.5846' x2='92.6593' y2='102.893' gradientUnits='userSpaceOnUse'><stop stop-color='white'/><stop offset='1' stop-color='#4854FE'/></linearGradient><linearGradient id='paint3_linear_108_873' x1='86.272' y1='19.1173' x2='41.5609' y2='98.7424' gradientUnits='userSpaceOnUse'><stop stop-color='#4854FE' stop-opacity='0.93'/><stop offset='1' stop-color='#006EF0' stop-opacity='0'/></linearGradient><linearGradient id='paint4_linear_108_873' x1='19.9156' y1='103.321' x2='61.0359' y2='27.5007' gradientUnits='userSpaceOnUse'><stop stop-color='#006EF0'/><stop offset='1' stop-color='#006EF0' stop-opacity='0'/></linearGradient><clipPath id='clip0_108_873'><rect width='106.667' height='120' fill='white'/></clipPath></defs></svg>",
@@ -206,8 +208,8 @@ function EmbeddedChat({ embedUrl, modes = MODES, defaultMode, theme = 'light', l
206
208
  // Created on first open and kept while minimized, so the conversation stays.
207
209
  const [opened, setOpened] = useState(view !== 'minimized');
208
210
  const [ready, setReady] = useState(false);
209
- // The chat itself is up, and draws the window's controls; until then (loading,
210
- // signed out, failed) the window keeps a close of its own.
211
+ // The chat itself is up, and draws the window's controls; otherwise (loading,
212
+ // signed out, failed, its session ended) the window keeps a close of its own.
211
213
  const [mounted, setMounted] = useState(false);
212
214
  const [narrow, setNarrow] = useState(isNarrow);
213
215
  const [background, setBackground] = useState('Canvas');
@@ -262,7 +264,7 @@ function EmbeddedChat({ embedUrl, modes = MODES, defaultMode, theme = 'light', l
262
264
  const onMessage = (event) => {
263
265
  if (event.source === frame.current?.contentWindow && event.data?.nexusChat === 'ready') {
264
266
  setReady(true);
265
- if (event.data.mounted === true) setMounted(true);
267
+ setMounted(event.data.mounted === true);
266
268
  }
267
269
  };
268
270
  window.addEventListener('message', onMessage);
@@ -287,6 +289,28 @@ function EmbeddedChat({ embedUrl, modes = MODES, defaultMode, theme = 'light', l
287
289
  return () => window.removeEventListener('message', onMessage);
288
290
  }, [side, canFullscreen, embedUrl]);
289
291
 
292
+ // The chat inside sees none of this page's activity, and Incorta ends an idle session:
293
+ // working in the app counts as using the chat's Incorta session too.
294
+ useEffect(() => {
295
+ if (!opened) return;
296
+ let last = 0;
297
+ const onActivity = () => {
298
+ if (Date.now() - last < KEEP_ALIVE_MS) return;
299
+ last = Date.now();
300
+ frame.current?.contentWindow?.postMessage(
301
+ { nexusChat: 'active' },
302
+ new URL(embedUrl, location.href).origin,
303
+ );
304
+ };
305
+ const options = { capture: true, passive: true };
306
+ window.addEventListener('pointerdown', onActivity, options);
307
+ window.addEventListener('keydown', onActivity, options);
308
+ return () => {
309
+ window.removeEventListener('pointerdown', onActivity, options);
310
+ window.removeEventListener('keydown', onActivity, options);
311
+ };
312
+ }, [opened, embedUrl]);
313
+
290
314
  // Theme, type size and the window's state follow the app without reloading
291
315
  // the iframe. The chat draws its own dock and close controls from the state:
292
316
  // "docked" means beside the page (floating or docked), the opposite of full screen.