@superatomai/application-react 0.0.3 → 0.0.5

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/dist/index.cjs CHANGED
@@ -68148,6 +68148,7 @@ var SuperAtomAuthError = class extends Error {
68148
68148
  super(message);
68149
68149
  this.name = "SuperAtomAuthError";
68150
68150
  this.code = code4;
68151
+ this.reason = options.reason;
68151
68152
  this.status = options.status;
68152
68153
  this.fatal = options.fatal;
68153
68154
  if (options.cause !== void 0) this.cause = options.cause;
@@ -68213,8 +68214,10 @@ var SdkSession = class {
68213
68214
  }
68214
68215
  renew() {
68215
68216
  if (!this.inFlight) {
68217
+ this.opts.onSigningIn?.(true);
68216
68218
  this.inFlight = this.exchange().finally(() => {
68217
68219
  this.inFlight = null;
68220
+ this.opts.onSigningIn?.(false);
68218
68221
  });
68219
68222
  }
68220
68223
  return this.inFlight;
@@ -68249,7 +68252,11 @@ var SdkSession = class {
68249
68252
  const message = typeof body?.error === "string" ? body.error : `Sign-in failed (${res.status})`;
68250
68253
  const fatal = res.status >= 400 && res.status < 500 && res.status !== 429;
68251
68254
  throw this.fail(
68252
- new SuperAtomAuthError(fatal ? "exchange_rejected" : "exchange_unavailable", message, { status: res.status, fatal })
68255
+ new SuperAtomAuthError(fatal ? "exchange_rejected" : "exchange_unavailable", message, {
68256
+ status: res.status,
68257
+ reason: typeof body?.code === "string" ? body.code : void 0,
68258
+ fatal
68259
+ })
68253
68260
  );
68254
68261
  }
68255
68262
  if (typeof body?.token !== "string" || !body.user?.id) {
@@ -69448,6 +69455,8 @@ function resetRegistration() {
69448
69455
  }
69449
69456
  var current = null;
69450
69457
  var retrying = null;
69458
+ var signingIn = false;
69459
+ var chatReady = false;
69451
69460
  var listeners = /* @__PURE__ */ new Set();
69452
69461
  function setAuthStatus(error51) {
69453
69462
  if (current === error51) return;
@@ -69460,6 +69469,36 @@ function setRetryingStatus(error51) {
69460
69469
  retrying = error51;
69461
69470
  listeners.forEach((l) => l());
69462
69471
  }
69472
+ function setSigningIn(value) {
69473
+ if (signingIn === value) return;
69474
+ signingIn = value;
69475
+ listeners.forEach((l) => l());
69476
+ }
69477
+ function useSigningIn() {
69478
+ return React6.useSyncExternalStore(
69479
+ (l) => {
69480
+ listeners.add(l);
69481
+ return () => listeners.delete(l);
69482
+ },
69483
+ () => signingIn,
69484
+ () => false
69485
+ );
69486
+ }
69487
+ function setChatReady(value) {
69488
+ if (chatReady === value) return;
69489
+ chatReady = value;
69490
+ listeners.forEach((l) => l());
69491
+ }
69492
+ function useStartingUp() {
69493
+ return React6.useSyncExternalStore(
69494
+ (l) => {
69495
+ listeners.add(l);
69496
+ return () => listeners.delete(l);
69497
+ },
69498
+ () => !chatReady,
69499
+ () => false
69500
+ );
69501
+ }
69463
69502
  function useRetryingStatus() {
69464
69503
  return React6.useSyncExternalStore(
69465
69504
  (l) => {
@@ -69480,12 +69519,34 @@ function useAuthStatus() {
69480
69519
  () => null
69481
69520
  );
69482
69521
  }
69522
+ var SETUP_REASONS = /* @__PURE__ */ new Set([
69523
+ "bad_request",
69524
+ "bad_project_id",
69525
+ "unknown_project",
69526
+ "bad_sub",
69527
+ "bad_email",
69528
+ "bad_roles",
69529
+ "bad_access",
69530
+ "bad_access_values",
69531
+ "bad_access_filters",
69532
+ "access_not_set_up",
69533
+ "lifetime_too_long",
69534
+ "issued_in_future",
69535
+ "email_linked_elsewhere"
69536
+ ]);
69483
69537
  function authStatusMessage(error51) {
69484
69538
  switch (error51.code) {
69485
69539
  case "get_token_failed":
69486
69540
  return "Your session has ended. Please sign in again to continue.";
69487
69541
  case "exchange_rejected":
69488
- return error51.status === 403 ? "This account cannot use the chat. Please contact your administrator." : "Your session is no longer valid. Please sign in again to continue.";
69542
+ if (error51.reason === "inactive") return "This account has been deactivated.";
69543
+ if (error51.reason === "sdk_not_enabled" || error51.status === 403) {
69544
+ return "This account cannot use the chat. Please contact your administrator.";
69545
+ }
69546
+ if (error51.reason && SETUP_REASONS.has(error51.reason)) {
69547
+ return `This app\u2019s Superatom sign-in is not set up correctly: ${error51.message}`;
69548
+ }
69549
+ return "Your session is no longer valid. Please sign in again to continue.";
69489
69550
  default:
69490
69551
  return "Could not connect to Superatom. Please try again in a moment.";
69491
69552
  }
@@ -69685,6 +69746,7 @@ function useSuperAtom({
69685
69746
  if (sdkSignIn && token) throw new Error("[SuperAtom] Pass either token or getToken, not both");
69686
69747
  const [user, setUser] = React6.useState(null);
69687
69748
  const [authError, setAuthError] = React6.useState(null);
69749
+ const [isSigningIn, setIsSigningIn] = React6.useState(false);
69688
69750
  const [signInAttempt, setSignInAttempt] = React6.useState(0);
69689
69751
  const directUserId = (() => {
69690
69752
  if (sdkSignIn) return void 0;
@@ -69750,7 +69812,13 @@ function useSuperAtom({
69750
69812
  },
69751
69813
  // Superatom unreachable or down, after a couple of tries: say so in the
69752
69814
  // chat instead of sitting on "Connecting…".
69753
- onRetrying: (err) => setRetryingStatus(err)
69815
+ onRetrying: (err) => setRetryingStatus(err),
69816
+ // Lets the chat show "Signing in…" instead of an empty chat while a
69817
+ // sign-in — including one after reconnect() — is in flight.
69818
+ onSigningIn: (value) => {
69819
+ setSigningIn(value);
69820
+ setIsSigningIn(value);
69821
+ }
69754
69822
  });
69755
69823
  sessionRef.current = session;
69756
69824
  for (let delay = 1e3; ; delay = Math.min(delay * 2, 3e4)) {
@@ -69877,6 +69945,7 @@ function useSuperAtom({
69877
69945
  if (!cancelled) {
69878
69946
  setupDoneRef.current = true;
69879
69947
  setBundleReady(true);
69948
+ setChatReady(true);
69880
69949
  }
69881
69950
  } catch (err) {
69882
69951
  console.error("[SuperAtom] Setup failed:", err);
@@ -69896,6 +69965,7 @@ function useSuperAtom({
69896
69965
  setAuthStatus(null);
69897
69966
  setupDoneRef.current = false;
69898
69967
  setBundleReady(false);
69968
+ setChatReady(false);
69899
69969
  };
69900
69970
  }, [directUserId, sdkSignIn, projectId, apiUrl, wsUrl, debug, signInAttempt]);
69901
69971
  const reconnect = React6.useCallback(() => {
@@ -70328,8 +70398,9 @@ function useSuperAtom({
70328
70398
  removed.add(msg.id);
70329
70399
  }
70330
70400
  setMessages((prev) => prev.filter((m) => !removed.has(m.id)));
70401
+ refreshThreads();
70331
70402
  return { success: true };
70332
- }, [resolvedUserId]);
70403
+ }, [resolvedUserId, refreshThreads]);
70333
70404
  React6.useEffect(() => {
70334
70405
  setMessageActions({ deleteMessage });
70335
70406
  return () => setMessageActions({});
@@ -70361,6 +70432,7 @@ function useSuperAtom({
70361
70432
  isNewChat: bundleReady && !isLoadingThread && messages2.length === 0,
70362
70433
  user,
70363
70434
  authError,
70435
+ isSigningIn,
70364
70436
  reconnect
70365
70437
  };
70366
70438
  }
@@ -70458,6 +70530,7 @@ function ChatInput({
70458
70530
  onStop
70459
70531
  }) {
70460
70532
  const authError = useAuthStatus();
70533
+ const startingUp = useStartingUp();
70461
70534
  const isLocked = disabled || !!authError;
70462
70535
  const textareaRef = React6.useRef(null);
70463
70536
  const historyRef = React6.useRef(null);
@@ -70490,15 +70563,35 @@ function ChatInput({
70490
70563
  window.addEventListener("keydown", onKeyDown);
70491
70564
  return () => window.removeEventListener("keydown", onKeyDown);
70492
70565
  }, [showStop, onStop]);
70493
- React6.useEffect(() => {
70566
+ const resize = React6.useCallback(() => {
70494
70567
  const textarea = textareaRef.current;
70495
70568
  if (!textarea) return;
70496
70569
  textarea.style.height = "auto";
70497
70570
  const newHeight = Math.min(textarea.scrollHeight, 200);
70498
70571
  textarea.style.height = `${newHeight}px`;
70499
- const shouldBeMultiline = newHeight > 60;
70500
- if (shouldBeMultiline !== isMultiline) setIsMultiline(shouldBeMultiline);
70501
- }, [input, isMultiline]);
70572
+ setIsMultiline(newHeight > 60);
70573
+ }, []);
70574
+ React6.useEffect(resize, [input, resize]);
70575
+ React6.useEffect(() => {
70576
+ const frame = requestAnimationFrame(resize);
70577
+ document.fonts?.ready.then(resize).catch(() => {
70578
+ });
70579
+ const textarea = textareaRef.current;
70580
+ if (!textarea || typeof ResizeObserver === "undefined") {
70581
+ return () => cancelAnimationFrame(frame);
70582
+ }
70583
+ let width = textarea.clientWidth;
70584
+ const observer = new ResizeObserver(() => {
70585
+ if (textarea.clientWidth === width) return;
70586
+ width = textarea.clientWidth;
70587
+ resize();
70588
+ });
70589
+ observer.observe(textarea);
70590
+ return () => {
70591
+ cancelAnimationFrame(frame);
70592
+ observer.disconnect();
70593
+ };
70594
+ }, [resize]);
70502
70595
  const setCursorToEnd = (textarea) => {
70503
70596
  setTimeout(() => {
70504
70597
  textarea.setSelectionRange(textarea.value.length, textarea.value.length);
@@ -70520,6 +70613,7 @@ function ChatInput({
70520
70613
  }, [input, isLocked, onSend, getOrCreateHistory]);
70521
70614
  const themeColor = getThemeColor();
70522
70615
  const effectivePlaceholder = authError ? authStatusMessage(authError) : placeholder;
70616
+ if (startingUp) return null;
70523
70617
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `sa-ui shrink-0 bg-base-100 border-t border-base-300 px-4 py-2 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `group ${isMultiline ? "rounded-3xl" : "rounded-full"} bg-base-200 transition-all duration-200 w-full max-w-2xl mx-auto`, children: /* @__PURE__ */ jsxRuntime.jsx(
70524
70618
  "div",
70525
70619
  {
@@ -70741,7 +70835,7 @@ function MessageBubble({ message, onStop }) {
70741
70835
  setConfirmOpen(false);
70742
70836
  if (!res.success) console.error("[SuperAtom] Could not delete the message:", res.error);
70743
70837
  };
70744
- const deleteButton = deleteMessage && responseComplete && !isAborted ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end mt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
70838
+ const deleteButton = deleteMessage && responseComplete && !isAborted ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-2 right-2 opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity duration-200", children: /* @__PURE__ */ jsxRuntime.jsx(
70745
70839
  "button",
70746
70840
  {
70747
70841
  onClick: () => setConfirmOpen(true),
@@ -70837,12 +70931,12 @@ function MessageBubble({ message, onStop }) {
70837
70931
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-base-content/70", children: "Generating component..." })
70838
70932
  ] })
70839
70933
  ] }) }),
70840
- hasComponent && /* @__PURE__ */ jsxRuntime.jsxs("div", { id: `box-${message.id}`, className: "w-full px-4 lg:px-16 xl:px-24 2xl:px-32", children: [
70934
+ hasComponent && /* @__PURE__ */ jsxRuntime.jsx("div", { id: `box-${message.id}`, className: "w-full px-4 lg:px-16 xl:px-24 2xl:px-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group relative", children: [
70841
70935
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl shadow-sm bg-base-100 border-2 border-base-300 min-h-[85vh] overflow-auto flex items-center justify-center p-5", children: /* @__PURE__ */ jsxRuntime.jsx(DSLRenderer, { dsl: message.schema.ui, data: message.schema.data ?? {} }) }),
70842
70936
  deleteButton
70843
- ] }),
70844
- !isStreaming && !hasComponent && hasText && isTextOnly && !isAborted && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center w-full px-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full md:w-[60vw]", children: [
70845
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl shadow-sm bg-base-100 border-2 border-base-300 p-4 text-base-content", children: /* @__PURE__ */ jsxRuntime.jsx(Markdown_default, { content: fullText, isStreaming: false }) }),
70937
+ ] }) }),
70938
+ !isStreaming && !hasComponent && hasText && isTextOnly && !isAborted && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center w-full px-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full md:w-[60vw] group relative", children: [
70939
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl shadow-sm bg-base-100 border-2 border-base-300 p-4 pb-10 text-base-content", children: /* @__PURE__ */ jsxRuntime.jsx(Markdown_default, { content: fullText, isStreaming: false }) }),
70846
70940
  deleteButton
70847
70941
  ] }) }),
70848
70942
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -70955,8 +71049,12 @@ function MessageList({
70955
71049
  }, [messages2]);
70956
71050
  const authError = useAuthStatus();
70957
71051
  const retrying2 = useRetryingStatus();
71052
+ const signingIn2 = useSigningIn();
70958
71053
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `sa-ui flex-1 relative overflow-hidden ${className}`, children: [
70959
- /* @__PURE__ */ jsxRuntime.jsx("main", { ref: containerRef, className: "h-full overflow-y-auto py-6", children: authError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-3 px-6 text-center", children: [
71054
+ /* @__PURE__ */ jsxRuntime.jsx("main", { ref: containerRef, className: "h-full overflow-y-auto py-6", children: signingIn2 && !bundleReady ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-3 text-base-content/50", children: [
71055
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "loading loading-spinner loading-lg" }),
71056
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "Signing in to Superatom\u2026" })
71057
+ ] }) : authError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-3 px-6 text-center", children: [
70960
71058
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { icon: "mdi:lock-alert-outline", width: 28, height: 28, className: "text-base-content/40" }),
70961
71059
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-base-content/70 max-w-sm", children: authStatusMessage(authError) })
70962
71060
  ] }) : !bundleReady || isLoadingThread && messages2.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-3 text-base-content/50", children: [
@@ -71407,6 +71505,7 @@ function Sidebar({
71407
71505
  setThreadToDelete(null);
71408
71506
  }
71409
71507
  };
71508
+ const startingUp = useStartingUp();
71410
71509
  const [collapsed, setCollapsed] = React6.useState(() => {
71411
71510
  try {
71412
71511
  return localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === "true";
@@ -71491,6 +71590,7 @@ function Sidebar({
71491
71590
  });
71492
71591
  }
71493
71592
  }
71593
+ if (startingUp) return null;
71494
71594
  return /* @__PURE__ */ jsxRuntime.jsxs(
71495
71595
  "aside",
71496
71596
  {