@noodleseed/assistant 1.21.0 → 1.22.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.
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import {
2
2
  ASSISTANT_TAG_NAME,
3
3
  NoodleAssistantElement,
4
4
  registerNoodleAssistant
5
- } from "./chunk-LEKEIHJV.js";
5
+ } from "./chunk-6TT3R555.js";
6
6
  import "./chunk-ZPZHPXIQ.js";
7
7
  import "./chunk-3YYTUJPJ.js";
8
8
  import "./chunk-5FUTL2UF.js";
package/dist/react.cjs CHANGED
@@ -31599,6 +31599,33 @@ var AssistantElementPageContextController = class {
31599
31599
  }
31600
31600
  };
31601
31601
 
31602
+ // src/element-presentation-gate.ts
31603
+ var AssistantElementPresentationGate = class {
31604
+ #host;
31605
+ #primeSession;
31606
+ #focusComposer;
31607
+ constructor(host, primeSession, focusComposer) {
31608
+ this.#host = host;
31609
+ this.#primeSession = primeSession;
31610
+ this.#focusComposer = focusComposer;
31611
+ }
31612
+ syncOpenState() {
31613
+ const open = this.#host.hasAttribute("open");
31614
+ const presentationReady = this.#host.hasAttribute("data-presentation-ready");
31615
+ const launcher = this.#host.shadowRoot?.querySelector(".launcher");
31616
+ launcher?.setAttribute("aria-expanded", String(open && presentationReady));
31617
+ launcher?.setAttribute("aria-busy", String(open && !presentationReady));
31618
+ if (launcher) launcher.disabled = open && !presentationReady;
31619
+ if (open && this.#host.isConnected) this.#primeSession();
31620
+ }
31621
+ reveal() {
31622
+ if (this.#host.hasAttribute("data-presentation-ready")) return;
31623
+ this.#host.setAttribute("data-presentation-ready", "");
31624
+ this.syncOpenState();
31625
+ if (this.#host.hasAttribute("open")) queueMicrotask(this.#focusComposer);
31626
+ }
31627
+ };
31628
+
31602
31629
  // src/element-scroll-controller.ts
31603
31630
  var AssistantElementScrollController = class {
31604
31631
  #region;
@@ -31714,9 +31741,10 @@ var ASSISTANT_ELEMENT_STYLES = `<style>
31714
31741
  .launcher:hover { transform: translateY(-2px) scale(1.03); box-shadow: 0 8px 26px rgba(0,0,0,.16); }
31715
31742
  .launcher img { width: 28px; height: 28px; border-radius: 50%; object-fit: contain; }
31716
31743
  .panel { display: none; flex-direction: column; width: min(var(--ns-assistant-panel-width, var(--ns-assistant-default-panel-width)), calc(100vw - 40px)); min-height: var(--ns-assistant-min-height, var(--ns-assistant-default-min-height)); max-height: min(var(--ns-assistant-max-height, var(--ns-assistant-default-max-height)), calc(100vh - 40px)); overflow: hidden; color: var(--ns-assistant-panel-text, var(--ns-assistant-text, var(--ns-assistant-default-text))); background: var(--ns-assistant-panel, var(--ns-assistant-default-panel)); border: 1px solid var(--ns-assistant-panel-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))); border-radius: var(--ns-assistant-panel-radius, var(--ns-assistant-default-panel-radius)); box-shadow: var(--ns-assistant-shadow, var(--ns-assistant-default-shadow)); transform-origin: bottom right; isolation: isolate; animation: halo-panel-in .28s cubic-bezier(.23,1,.32,1) both; }
31717
- :host([open]) .panel { display: flex; }
31744
+ :host([open][data-presentation-ready]) .panel { display: flex; }
31718
31745
  .panel { position: relative; }
31719
- :host([open]) .launcher { display: none; }
31746
+ :host([open][data-presentation-ready]) .launcher { display: none; }
31747
+ :host([open]:not([data-presentation-ready])) .launcher { cursor: progress; opacity: .72; transform: none; }
31720
31748
  header { display: flex; flex: 0 0 auto; gap: 10px; align-items: center; min-height: 64px; padding: 12px 18px; color: var(--ns-assistant-header-text, inherit); background: var(--ns-assistant-header, transparent); border-bottom: 1px solid color-mix(in srgb, var(--ns-assistant-header-border, var(--ns-assistant-divider, var(--ns-assistant-default-divider))) 78%, transparent); }
31721
31749
  header strong { flex: 1; font-size: 16px; font-weight: 600; letter-spacing: 0; }
31722
31750
  .brand-logo { display: block; max-width: 120px; max-height: 28px; object-fit: contain; }
@@ -32342,6 +32370,11 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32342
32370
  #automaticPageContext = new AssistantElementPageContextController(
32343
32371
  () => !this.#pageContext
32344
32372
  );
32373
+ #presentationGate = new AssistantElementPresentationGate(
32374
+ this,
32375
+ () => this.#primeSession(),
32376
+ () => this.focusComposer()
32377
+ );
32345
32378
  #pendingUserEcho;
32346
32379
  #sessionState = "idle";
32347
32380
  #startOpenApplied = false;
@@ -32412,6 +32445,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32412
32445
  if (!this.sessionEndpoint) this.sessionEndpoint = this.getAttribute("session-endpoint") ?? "";
32413
32446
  if (!this.embedId) this.embedId = this.getAttribute("embed-id") ?? "";
32414
32447
  if (!this.serviceUrl) this.serviceUrl = this.getAttribute("service-url") ?? "";
32448
+ if (!this.sessionEndpoint && !this.embedId) this.#presentationGate.reveal();
32415
32449
  this.#media = globalThis.matchMedia?.("(prefers-color-scheme: dark)");
32416
32450
  this.#media?.addEventListener("change", this.#handleSystemTheme);
32417
32451
  document.addEventListener("keydown", this.#handleDocumentKeydown);
@@ -32428,7 +32462,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32428
32462
  } else if (!this.embedId) {
32429
32463
  this.#primeSession();
32430
32464
  }
32431
- this.#syncOpenState();
32465
+ this.#presentationGate.syncOpenState();
32432
32466
  }
32433
32467
  disconnectedCallback() {
32434
32468
  this.#conversationGeneration += 1;
@@ -32446,7 +32480,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32446
32480
  }
32447
32481
  attributeChangedCallback(name21) {
32448
32482
  if (name21 === "theme") this.#applyTheme();
32449
- if (name21 === "open") this.#syncOpenState();
32483
+ if (name21 === "open") this.#presentationGate.syncOpenState();
32450
32484
  }
32451
32485
  open() {
32452
32486
  this.setAttribute("open", "");
@@ -32636,6 +32670,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32636
32670
  const bootstrap = client.connect().catch((error51) => {
32637
32671
  if (generation !== this.#conversationGeneration || this.#client !== client) return;
32638
32672
  this.#dispatchClientError(error51, "session_failed");
32673
+ this.#presentationGate.reveal();
32639
32674
  }).finally(() => {
32640
32675
  if (this.#sessionBootstrap === bootstrap) this.#sessionBootstrap = void 0;
32641
32676
  });
@@ -32645,6 +32680,7 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32645
32680
  this.dispatchEvent(new CustomEvent("assistant-event", { detail: event }));
32646
32681
  this.#events.handle(event);
32647
32682
  if (event.event === "session_started") {
32683
+ this.#presentationGate.reveal();
32648
32684
  this.#setSessionState("ready");
32649
32685
  this.#messages?.querySelector(".conversation-error")?.remove();
32650
32686
  }
@@ -32814,11 +32850,6 @@ var NoodleAssistantElement = class extends HTMLElementBase {
32814
32850
  this.#sessionState = state;
32815
32851
  syncAssistantSessionVisualState(this, this.shadowRoot, state, this.#appearance);
32816
32852
  }
32817
- #syncOpenState() {
32818
- const open = this.hasAttribute("open");
32819
- this.shadowRoot?.querySelector(".launcher")?.setAttribute("aria-expanded", String(open));
32820
- if (open && this.isConnected) this.#primeSession();
32821
- }
32822
32853
  #closeAndRestoreFocus() {
32823
32854
  this.close();
32824
32855
  this.shadowRoot?.querySelector(".launcher")?.focus();