@burdenoff/fe-libs 2026.1029.10 → 2026.1029.11

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.
@@ -548,6 +548,7 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
548
548
  readonly 'offer.notAvailable': "{{page}} isn't in your menu right now.";
549
549
  readonly 'offer.open': "Open {{page}}";
550
550
  readonly 'overlay.launcher': "AI Assistant";
551
+ readonly 'overlay.launcherQuick': "Open quick assistant";
551
552
  readonly 'overlay.launcherTitle': "AI Assistant ({{shortcut}})";
552
553
  readonly 'panel.ariaLabel': "AI Assistant";
553
554
  readonly 'pendingWrite.approve': "Approve this change";
@@ -661,6 +662,9 @@ export declare const ASSISTANT_I18N_LITERAL_COPY: {
661
662
  readonly 'waitingChange.review': "Review";
662
663
  readonly 'waitingChange.reviewLabel': "Review the change waiting for your approval";
663
664
  readonly 'waitingChange.status': "{{count}} change(s) waiting for your approval";
665
+ readonly 'window.minimize': "Minimize";
666
+ readonly 'window.openFull': "Open full assistant";
667
+ readonly 'window.title': "Quick assistant";
664
668
  readonly 'writeConsent.body': "In {{mode}} mode the assistant can read AND change your data — creating records, logging activity, updating details, and more, on your behalf.";
665
669
  readonly 'writeConsent.cancel': "Stay in {{mode}}";
666
670
  readonly 'writeConsent.confirm': "Enable {{mode}}";
@@ -441,6 +441,7 @@ var g = {
441
441
  "offer.notAvailable": "{{page}} isn't in your menu right now.",
442
442
  "offer.open": "Open {{page}}",
443
443
  "overlay.launcher": "AI Assistant",
444
+ "overlay.launcherQuick": "Open quick assistant",
444
445
  "overlay.launcherTitle": "AI Assistant ({{shortcut}})",
445
446
  "panel.ariaLabel": "AI Assistant",
446
447
  "pendingWrite.approve": "Approve this change",
@@ -554,6 +555,9 @@ var g = {
554
555
  "waitingChange.review": "Review",
555
556
  "waitingChange.reviewLabel": "Review the change waiting for your approval",
556
557
  "waitingChange.status": "{{count}} change(s) waiting for your approval",
558
+ "window.minimize": "Minimize",
559
+ "window.openFull": "Open full assistant",
560
+ "window.title": "Quick assistant",
557
561
  "writeConsent.body": "In {{mode}} mode the assistant can read AND change your data — creating records, logging activity, updating details, and more, on your behalf.",
558
562
  "writeConsent.cancel": "Stay in {{mode}}",
559
563
  "writeConsent.confirm": "Enable {{mode}}",
@@ -380,4 +380,6 @@ export * from './ui/compact/AssistantDiscardDraftDialog';
380
380
  export * from './ui/compact/AssistantMenuView';
381
381
  export * from './ui/compact/AssistantVoiceLanguageSettings';
382
382
  export * from './ui/compact/AssistantWaitingChangeRow';
383
+ export * from './ui/compact/AssistantWindowHeader';
384
+ export * from './ui/useAssistantVisualViewport';
383
385
  export * from './ui/compact/waitingChange';
@@ -5,6 +5,7 @@ import { AssistantNavigate } from './AssistantMarkdownRenderer';
5
5
  import { AssistantLiveAvatarSeam } from './assistantLiveAvatarSeam';
6
6
  import { AssistantPreviewController } from '../preview/types';
7
7
  import { AssistantPresentation } from './composer/AssistantComposer';
8
+ import { AssistantSurface } from './assistantOverlayState';
8
9
  export type AIAssistantPanelProps = PanelProps & {
9
10
  /** When provided, renders a dock/float toggle in the header. */
10
11
  docked?: boolean;
@@ -124,6 +125,23 @@ export type AIAssistantPanelProps = PanelProps & {
124
125
  * without a host that honours it the control would do nothing.
125
126
  */
126
127
  onExpandedChange?: (expanded: boolean) => void;
128
+ /**
129
+ * BOFF-10178 (compact only): which surface the overlay is showing this ONE
130
+ * panel in. `window` is the Quick assistant: a slim header (Open full
131
+ * assistant, Minimize) in place of the full header, no ☰ view, no Expand, no
132
+ * Avatar tab. `panel` or absent is the full assistant. The chat area and the
133
+ * composer are the same instance either way, so a draft, its attachments and
134
+ * a turn in flight survive the switch.
135
+ */
136
+ surface?: AssistantSurface;
137
+ /** Compact window: switch to the full assistant. Same instance, nothing re-sent. */
138
+ onOpenFull?: () => void;
139
+ /**
140
+ * Compact window: hide the window and keep it mounted (the overlay then passes
141
+ * `visible={false}`). The window has no Close (CW-M), so this is also what
142
+ * Escape does there: it never asks to discard a draft the hidden window keeps.
143
+ */
144
+ onMinimize?: () => void;
127
145
  };
128
146
  /**
129
147
  * The panel.
@@ -29,239 +29,256 @@ import { AssistantCompactHeader as Pe } from "./compact/AssistantCompactHeader.j
29
29
  import { AssistantConversationMenu as Fe } from "./compact/AssistantConversationMenu.js";
30
30
  import { AssistantDiscardDraftDialog as Ie } from "./compact/AssistantDiscardDraftDialog.js";
31
31
  import { AssistantMenuView as Le } from "./compact/AssistantMenuView.js";
32
- import { useCallback as n, useEffect as r, useId as Re, useMemo as i, useRef as a, useState as o } from "react";
33
- import { Fragment as ze, jsx as s, jsxs as c } from "react/jsx-runtime";
32
+ import { AssistantWindowHeader as Re } from "./compact/AssistantWindowHeader.js";
33
+ import { useCallback as n, useEffect as r, useId as ze, useMemo as i, useRef as a, useState as o } from "react";
34
+ import { Fragment as Be, jsx as s, jsxs as c } from "react/jsx-runtime";
34
35
  //#region src/shared/assistant/ui/AIAssistantPanel.tsx
35
- var l = ({ onClose: l, visible: u, docked: d, onToggleDock: f, writeAccess: Be, onNavigate: Ve, isShellLessTarget: He, connectSourceHref: Ue, onConnectSource: We, preview: p, liveAvatar: m, presentation: h, onExpandedChange: g, serverHistory: Ge = !1 }) => {
36
- let Ke = te(), qe = de(m);
37
- Te(Ge);
38
- let [_, v] = o(!1), y = ge(p);
39
- _ && !y && v(!1);
40
- let b = _ && y;
36
+ var Ve = { backgroundColor: "var(--color-bg-elevated)" }, l = ({ onClose: l, visible: u, docked: d, onToggleDock: f, writeAccess: He, onNavigate: Ue, isShellLessTarget: We, connectSourceHref: Ge, onConnectSource: Ke, preview: p, liveAvatar: m, presentation: h, onExpandedChange: g, surface: _, onOpenFull: v, onMinimize: y, serverHistory: qe = !1 }) => {
37
+ let b = te(), Je = de(m);
38
+ Te(qe);
39
+ let [Ye, x] = o(!1), S = ge(p);
40
+ Ye && !S && x(!1);
41
+ let C = Ye && S;
41
42
  me(_e(p, ve()));
42
- let x = a(null);
43
- e(x);
44
- let { conversations: Je, activeConversationId: Ye, conversationListOpen: S, setConversationListOpen: C, createConversation: w } = ne(), T = h === "compact", [E, D] = o(!1), O = a(!1);
45
- E && (!T || S || b) && D(!1);
46
- let k = T && E, [Xe, A] = o(!1), j = je(T && g !== void 0), [M, N] = o(!1), P = j && M;
43
+ let w = a(null);
44
+ e(w);
45
+ let { conversations: Xe, activeConversationId: Ze, conversationListOpen: T, setConversationListOpen: E, createConversation: D } = ne(), O = h === "compact", k = O && _ === "window", [Qe, A] = o(!1), j = a(!1);
46
+ Qe && (!O || k || T || C) && A(!1);
47
+ let M = O && Qe, [$e, et] = o(!1), N = je(O && !k && g !== void 0), [P, tt] = o(!1), F = N && P;
47
48
  r(() => {
48
- M && !j && (N(!1), g?.(!1));
49
+ P && !N && (tt(!1), g?.(!1));
49
50
  }, [
50
- M,
51
- j,
51
+ P,
52
+ N,
52
53
  g
53
54
  ]);
54
- let Ze = () => {
55
- let e = !P;
56
- N(e), g?.(e);
57
- }, F = a(!1), I = a(g);
55
+ let nt = () => {
56
+ let e = !F;
57
+ tt(e), g?.(e);
58
+ }, rt = a(!1), it = a(g);
58
59
  r(() => {
59
- F.current = P, I.current = g;
60
+ rt.current = F, it.current = g;
60
61
  }), r(() => () => {
61
- F.current && I.current?.(!1);
62
+ rt.current && it.current?.(!1);
62
63
  }, []);
63
- let L = S || b || k, R = m?.tab, Qe = fe(R), [z, B] = o(!1);
64
- z && (!R || u === !1) && B(!1);
65
- let V = R !== void 0 && (Qe || z), H = Re(), $e = Re(), U = i(() => V ? {
66
- chatTab: `${H}-chat-tab`,
67
- avatarTab: `${H}-avatar-tab`,
68
- chatPanel: `${H}-chat-panel`,
69
- avatarPanel: `${H}-avatar-panel`,
70
- leaveHint: `${H}-avatar-leave`
71
- } : null, [V, H]), et = n(() => B(!1), []), W = a(null), tt = n((e) => {
72
- W.current = e;
73
- }, []), nt = i(() => ({
74
- open: z,
75
- close: et,
76
- ids: U,
77
- covered: L,
78
- setReplyEscape: tt
64
+ let I = T || C || M, L = m?.tab, at = fe(L), [R, z] = o(!1);
65
+ R && (!L || u === !1 || k) && z(!1);
66
+ let B = L !== void 0 && (at || R), V = ze(), ot = ze(), H = i(() => B ? {
67
+ chatTab: `${V}-chat-tab`,
68
+ avatarTab: `${V}-avatar-tab`,
69
+ chatPanel: `${V}-chat-panel`,
70
+ avatarPanel: `${V}-avatar-panel`,
71
+ leaveHint: `${V}-avatar-leave`
72
+ } : null, [B, V]), st = n(() => z(!1), []), U = a(null), ct = n((e) => {
73
+ U.current = e;
74
+ }, []), lt = i(() => ({
75
+ open: R,
76
+ close: st,
77
+ ids: H,
78
+ covered: I,
79
+ setReplyEscape: ct
79
80
  }), [
80
- z,
81
- et,
82
- U,
83
- L,
84
- tt
85
- ]), rt = (e) => B(e === "avatar"), it = () => {
86
- D(!1), rt("avatar"), O.current = !0;
87
- }, at = oe({
88
- historyOpen: S,
89
- previewOpen: b,
90
- avatarOpen: z
91
- }) ?? (k ? "menu" : null), G = (e) => {
81
+ R,
82
+ st,
83
+ H,
84
+ I,
85
+ ct
86
+ ]), ut = (e) => z(e === "avatar"), dt = () => {
87
+ A(!1), ut("avatar"), j.current = !0;
88
+ }, ft = oe({
89
+ historyOpen: T,
90
+ previewOpen: C,
91
+ avatarOpen: R
92
+ }) ?? (M ? "menu" : null), W = (e) => {
92
93
  let t = ce({
93
- historyOpen: S,
94
- previewOpen: b
94
+ historyOpen: T,
95
+ previewOpen: C
95
96
  }, e);
96
- C(t.historyOpen), v(t.previewOpen);
97
+ E(t.historyOpen), x(t.previewOpen);
97
98
  };
98
- t("assistant.history", i(() => ({ run: () => S ? { status: "already" } : (C(!0), v(!1), { status: "done" }) }), [S, C])), t("assistant.preview", i(() => y ? {
99
+ t("assistant.history", i(() => ({ run: () => T ? { status: "already" } : (E(!0), x(!1), { status: "done" }) }), [T, E])), t("assistant.preview", i(() => S ? {
99
100
  surface: "panel",
100
- run: () => b ? { status: "already" } : (C(!1), v(!0), { status: "done" }),
101
- close: () => b ? (v(!1), { status: "done" }) : { status: "already" }
101
+ run: () => C ? { status: "already" } : (E(!1), x(!0), { status: "done" }),
102
+ close: () => C ? (x(!1), { status: "done" }) : { status: "already" }
102
103
  } : null, [
103
- y,
104
- b,
105
- C
104
+ S,
105
+ C,
106
+ E
106
107
  ]));
107
- let ot = Je.find((e) => e.id === Ye);
108
- Oe(ot?.backendSessionId ?? null, ot?.mode ?? null, u ?? !0), Ee(u ?? !0);
109
- let st = ee(u !== !1), K = Ne(), q = a(!1), ct = n((e) => {
108
+ let G = Xe.find((e) => e.id === Ze);
109
+ Oe(G?.backendSessionId ?? null, G?.mode ?? null, u ?? !0), Ee(u ?? !0);
110
+ let pt = ee(u !== !1), K = Ne(), q = a(!1), mt = n((e) => {
110
111
  q.current = e;
111
- }, []), J = a(!1), [lt, Y] = o(!1), X = n(() => Ae({
112
- compact: T,
112
+ }, []), J = a(!1), [ht, Y] = o(!1), X = n(() => Ae({
113
+ compact: O,
113
114
  unsent: q.current,
114
115
  confirmed: J.current
115
- }) === "close" ? !1 : (Y(!0), !0), [T]);
116
+ }) === "close" ? !1 : (Y(!0), !0), [O]);
116
117
  r(() => {
117
- if (!(!T || !K)) return K(X);
118
+ if (!(!O || !K)) return K(X);
118
119
  }, [
119
- T,
120
+ O,
120
121
  K,
121
122
  X
122
123
  ]);
123
124
  let Z = n(() => {
125
+ if (k && y) {
126
+ y();
127
+ return;
128
+ }
124
129
  X() || l();
125
- }, [X, l]), ut = () => {
130
+ }, [
131
+ k,
132
+ y,
133
+ X,
134
+ l
135
+ ]), gt = () => {
126
136
  J.current = !0, q.current = !1, Y(!1);
127
137
  try {
128
138
  l();
129
139
  } finally {
130
140
  J.current = !1;
131
141
  }
132
- }, Q = a(null), dt = a(null), ft = a(null), pt = n(() => D(!1), []), [mt, ht] = o(0), gt = n(() => {
133
- w(), D(!1), C(!1), ht((e) => e + 1);
134
- }, [w, C]), _t = n(() => {
135
- D(!1), A(!0);
142
+ }, Q = a(null), _t = a(null), vt = a(null), yt = n(() => A(!1), []), [bt, xt] = o(0), St = n(() => {
143
+ D(), A(!1), E(!1), xt((e) => e + 1);
144
+ }, [D, E]), Ct = n(() => {
145
+ v?.(), xt((e) => e + 1);
146
+ }, [v]), wt = n(() => {
147
+ A(!1), et(!0);
136
148
  }, []), $ = a(!1);
137
149
  return r(() => {
138
- if ($.current && !k) {
150
+ if ($.current && !M) {
139
151
  let e = document.activeElement;
140
- (!e || e === document.body || e === x.current) && dt.current?.focus({ preventScroll: !0 });
152
+ (!e || e === document.body || e === w.current) && _t.current?.focus({ preventScroll: !0 });
141
153
  }
142
- $.current = k;
143
- }, [k]), r(() => {
144
- mt > 0 && Q.current?.focus({ preventScroll: !0 });
145
- }, [mt]), r(() => {
146
- !O.current || !z || !U || (O.current = !1, document.getElementById(U.avatarTab)?.focus({ preventScroll: !0 }));
147
- }, [z, U]), ke({
148
- panelRef: x,
149
- inputRef: T ? Q : void 0,
150
- onNewConversation: T ? gt : void 0,
151
- onOpenConversationMenu: T ? _t : void 0,
154
+ $.current = M;
155
+ }, [M]), r(() => {
156
+ bt > 0 && Q.current?.focus({ preventScroll: !0 });
157
+ }, [bt]), r(() => {
158
+ !j.current || !R || !H || (j.current = !1, document.getElementById(H.avatarTab)?.focus({ preventScroll: !0 }));
159
+ }, [R, H]), ke({
160
+ panelRef: w,
161
+ inputRef: O ? Q : void 0,
162
+ onNewConversation: O ? St : void 0,
163
+ onOpenConversationMenu: O && !k ? wt : void 0,
152
164
  onClose: () => {
153
165
  let e = se({
154
- historyOpen: S,
155
- previewOpen: b,
156
- avatarOpen: z,
157
- tabReplySpeaking: W.current !== null
166
+ historyOpen: T,
167
+ previewOpen: C,
168
+ avatarOpen: R,
169
+ tabReplySpeaking: U.current !== null
158
170
  });
159
171
  if (e === "overlay") {
160
- C(!1), v(!1);
172
+ E(!1), x(!1);
161
173
  return;
162
174
  }
163
175
  if (e === "tab-reply") {
164
- W.current?.();
176
+ U.current?.();
165
177
  return;
166
178
  }
167
179
  if (e === "tab") {
168
- B(!1), U && document.getElementById(U.chatTab)?.focus();
180
+ z(!1), H && document.getElementById(H.chatTab)?.focus();
169
181
  return;
170
182
  }
171
- if (k) {
172
- D(!1);
183
+ if (M) {
184
+ A(!1);
173
185
  return;
174
186
  }
175
187
  Z();
176
188
  }
177
189
  }), /* @__PURE__ */ s(re, {
178
190
  visible: u ?? !0,
179
- engine: qe,
191
+ engine: Je,
180
192
  children: /* @__PURE__ */ s(le, {
181
193
  value: m,
182
194
  children: /* @__PURE__ */ s(ue.Provider, {
183
- value: nt,
195
+ value: lt,
184
196
  children: /* @__PURE__ */ s(pe, {
185
197
  value: p,
186
198
  children: /* @__PURE__ */ s(we, {
187
- navigate: Ve,
188
- isShellLessTarget: He,
199
+ navigate: Ue,
200
+ isShellLessTarget: We,
189
201
  children: /* @__PURE__ */ s(he, {
190
- value: Ue,
191
- onOpen: We,
202
+ value: Ge,
203
+ onOpen: Ke,
192
204
  children: /* @__PURE__ */ s(Se, { children: /* @__PURE__ */ s(Ce, { children: /* @__PURE__ */ c("div", {
193
- ref: x,
205
+ ref: w,
194
206
  className: "relative flex h-full w-full flex-col bg-bg-surface",
207
+ style: k ? Ve : void 0,
195
208
  role: "complementary",
196
- "aria-label": Ke("panel.ariaLabel", "AI Assistant"),
209
+ "aria-label": k ? b("window.title", "Quick assistant") : b("panel.ariaLabel", "AI Assistant"),
197
210
  "data-testid": "ai-assistant-panel",
198
211
  [ae]: "",
199
- ...at ? { [ie]: at } : {},
200
- ...T ? {
212
+ ...ft ? { [ie]: ft } : {},
213
+ ...O ? {
201
214
  "data-presentation": "compact",
202
- ...P ? { "data-assistant-expanded": "" } : {}
215
+ ..._ ? { "data-assistant-surface": _ } : {},
216
+ ...F ? { "data-assistant-expanded": "" } : {}
203
217
  } : {},
204
218
  tabIndex: -1,
205
219
  children: [
206
220
  /* @__PURE__ */ c("div", {
207
221
  className: "contents",
208
- inert: L || void 0,
209
- children: [T ? /* @__PURE__ */ c(ze, { children: [/* @__PURE__ */ s(Pe, {
210
- contextLabel: st,
211
- menuOpen: k,
212
- menuViewId: $e,
213
- onOpenMenu: () => D(!0),
214
- menuButtonRef: dt,
222
+ inert: I || void 0,
223
+ children: [O ? /* @__PURE__ */ c(Be, { children: [k ? /* @__PURE__ */ s(Re, {
224
+ onOpenFull: Ct,
225
+ onMinimize: () => y?.()
226
+ }) : /* @__PURE__ */ s(Pe, {
227
+ contextLabel: pt,
228
+ menuOpen: M,
229
+ menuViewId: ot,
230
+ onOpenMenu: () => A(!0),
231
+ menuButtonRef: _t,
215
232
  conversationMenu: /* @__PURE__ */ s(Fe, {
216
- open: Xe,
217
- onOpenChange: A,
218
- triggerRef: ft
233
+ open: $e,
234
+ onOpenChange: et,
235
+ triggerRef: vt
219
236
  }),
220
- expandOffered: j,
221
- expanded: P,
222
- onToggleExpanded: Ze,
223
- onTogglePreview: () => G("preview"),
224
- previewOpen: b,
237
+ expandOffered: N,
238
+ expanded: F,
239
+ onToggleExpanded: nt,
240
+ onTogglePreview: () => W("preview"),
241
+ previewOpen: C,
225
242
  onClose: Z
226
243
  }), /* @__PURE__ */ s(Ie, {
227
- open: lt,
244
+ open: ht,
228
245
  onKeep: () => Y(!1),
229
- onDiscard: ut
246
+ onDiscard: gt
230
247
  })] }) : /* @__PURE__ */ s(be, {
231
- contextLabel: st,
232
- onNewConversation: () => w(),
233
- onOpenHistory: () => G("history"),
234
- historyOpen: S,
235
- onTogglePreview: () => G("preview"),
236
- previewOpen: b,
248
+ contextLabel: pt,
249
+ onNewConversation: () => D(),
250
+ onOpenHistory: () => W("history"),
251
+ historyOpen: T,
252
+ onTogglePreview: () => W("preview"),
253
+ previewOpen: C,
237
254
  onClose: l,
238
255
  docked: d,
239
256
  onToggleDock: f
240
- }), U ? /* @__PURE__ */ s(De, {
241
- selected: z ? "avatar" : "chat",
242
- onSelect: rt,
243
- ids: U
257
+ }), H && !k ? /* @__PURE__ */ s(De, {
258
+ selected: R ? "avatar" : "chat",
259
+ onSelect: ut,
260
+ ids: H
244
261
  }) : null]
245
262
  }),
246
- S ? /* @__PURE__ */ s(xe, { presentation: h }) : k ? /* @__PURE__ */ s(Le, {
247
- id: $e,
248
- onClose: pt,
263
+ T ? /* @__PURE__ */ s(xe, { presentation: h }) : M ? /* @__PURE__ */ s(Le, {
264
+ id: ot,
265
+ onClose: yt,
249
266
  onRequestClosePanel: Z,
250
- onNewConversation: gt,
251
- onOpenAvatar: V ? it : void 0,
267
+ onNewConversation: St,
268
+ onOpenAvatar: B ? dt : void 0,
252
269
  docked: d,
253
270
  onToggleDock: f
254
271
  }) : null,
255
- b && /* @__PURE__ */ s(ye, { onClose: () => v(!1) }),
272
+ C && /* @__PURE__ */ s(ye, { onClose: () => x(!1) }),
256
273
  /* @__PURE__ */ s("div", {
257
274
  className: "contents",
258
- inert: L || void 0,
275
+ inert: I || void 0,
259
276
  children: /* @__PURE__ */ s(Me, {
260
277
  visible: u ?? !0,
261
- writeAccess: Be,
278
+ writeAccess: He,
262
279
  presentation: h,
263
- inputRef: T ? Q : void 0,
264
- onDraftDirtyChange: T ? ct : void 0
280
+ inputRef: O ? Q : void 0,
281
+ onDraftDirtyChange: O ? mt : void 0
265
282
  })
266
283
  })
267
284
  ]
@@ -2772,7 +2772,7 @@ var Gi = () => () => {}, Ki = () => "off", qi = ({ visible: qi = !0, writeAccess
2772
2772
  active: fo,
2773
2773
  onSelect: Qi ? Ll : El
2774
2774
  } : void 0,
2775
- suspendDictation: J,
2775
+ suspendDictation: J || Qi && !qi,
2776
2776
  onVoiceStateChange: q.ids ? rl : void 0,
2777
2777
  presentation: Yi,
2778
2778
  turnInFlight: G,
@@ -2,7 +2,8 @@ import { ReactNode } from 'react';
2
2
  import { QuotaKind } from '../quota';
3
3
  import { AIAssistantPanelProps } from './AIAssistantPanel';
4
4
  import { AssistantNavigate } from './AssistantMarkdownRenderer';
5
- import { AssistantOverlayKeys } from './assistantOverlayState';
5
+ import { AssistantPresentation } from './composer/AssistantComposer';
6
+ import { AssistantOverlayKeys, AssistantSurface } from './assistantOverlayState';
6
7
  export interface AssistantOverlayContextValue {
7
8
  isOpen: boolean;
8
9
  open: () => void;
@@ -29,6 +30,43 @@ export interface AssistantOverlayContextValue {
29
30
  * that builds this value itself keeps compiling.
30
31
  */
31
32
  registerCloseGuard?: (guard: () => boolean) => () => void;
33
+ /** How the assistant is presented. `classic` unless the provider was given `compact`. */
34
+ presentation: AssistantPresentation;
35
+ /**
36
+ * BOFF-10178: what the open assistant is showing, in the ONE container it
37
+ * always renders: the Quick assistant `window` or the full `panel`. Always
38
+ * `panel` in the classic presentation. Session-scoped, like `isOpen`.
39
+ */
40
+ surface: AssistantSurface;
41
+ /** The Quick assistant window is hidden but mounted (compact only; false in classic). */
42
+ minimized: boolean;
43
+ /**
44
+ * The FULL assistant is open and showing: the state a header button that
45
+ * opens it reports as `aria-expanded`. In classic: the same as `isOpen`.
46
+ */
47
+ fullOpen: boolean;
48
+ /**
49
+ * Open the FULL assistant, whatever it is doing now: closed, the Quick
50
+ * window, or minimized. The same instance is kept, so a draft and a turn in
51
+ * flight carry over. Idempotent. This is what Ctrl/Cmd+Shift+A, the
52
+ * `<prefix>:toggle-ai-assistant` event with `detail.open: true`, and a
53
+ * product's own header button call. In classic it is `open()`.
54
+ */
55
+ openFull: () => void;
56
+ /**
57
+ * Open the Quick assistant window — or, when it is minimized, bring it back.
58
+ * The launcher calls it. Does nothing to a full panel that is already open
59
+ * and, in classic, is `open()`.
60
+ */
61
+ openWindow: () => void;
62
+ /** Hide the Quick assistant window, keeping everything in it. A no-op for the full panel and in classic. */
63
+ minimize: () => void;
64
+ /**
65
+ * The full panel is Expanded to its fixed 760 px (compact, N2). Reported by
66
+ * the panel itself; per session, never stored. Always false in classic.
67
+ */
68
+ expanded: boolean;
69
+ setExpanded: (expanded: boolean) => void;
32
70
  }
33
71
  /** The overlay state in force, or null when no provider is mounted. */
34
72
  export declare function useAssistantOverlayOrNull(): AssistantOverlayContextValue | null;
@@ -73,6 +111,19 @@ export interface AssistantOverlayProviderProps {
73
111
  product: string;
74
112
  onExhausted: (kind: QuotaKind, event: Event) => void;
75
113
  };
114
+ /**
115
+ * BOFF-10178: how the overlay is presented. Absent or `classic`: the overlay
116
+ * of before, attribute for attribute (the eager write of the legacy dock key
117
+ * included). `compact` opts this product into the Quick assistant window, the
118
+ * `surface`, the N2 geometry, the D1-A layout rule, the published insets of
119
+ * the new geometry and the keyboard-aware sheet.
120
+ *
121
+ * ★ On the PROVIDER, not the overlay, because the provider owns what it
122
+ * changes (the open and layout state, the shortcut and the published
123
+ * variables). The overlay reads it from here and hands the panel
124
+ * `presentation="compact"` itself, so the two cannot disagree.
125
+ */
126
+ presentation?: AssistantPresentation;
76
127
  children: ReactNode;
77
128
  }
78
129
  /**
@@ -88,7 +139,7 @@ export interface AssistantOverlayProviderProps {
88
139
  * Mount ONE per page: the published dock width and panel inset are single
89
140
  * `<html>` variables.
90
141
  */
91
- export declare function AssistantOverlayProvider({ keyPrefix, quota, children, }: AssistantOverlayProviderProps): import('react/jsx-runtime').JSX.Element;
142
+ export declare function AssistantOverlayProvider({ keyPrefix, quota, presentation, children, }: AssistantOverlayProviderProps): import('react/jsx-runtime').JSX.Element;
92
143
  /** What the overlay hands the panel it renders. */
93
144
  export interface AssistantOverlayPanelProps {
94
145
  panelId: string;
@@ -99,7 +150,29 @@ export interface AssistantOverlayPanelProps {
99
150
  onNavigate?: AssistantNavigate;
100
151
  /** Opens in a new tab, leaving this page alone: a tap on it asks nothing (BOFF-8060 N4). */
101
152
  isShellLessTarget?: (path: string) => boolean;
153
+ /**
154
+ * Compact presentation only (BOFF-10178) — absent in classic, so a product's
155
+ * own `renderPanel` wrapper that spreads these onto the shared panel passes
156
+ * exactly what it passed before. The overlay's own values win over
157
+ * `panelProps`.
158
+ */
159
+ presentation?: AssistantPresentation;
160
+ /** Which surface this one panel is shown in. */
161
+ surface?: AssistantSurface;
162
+ /** The window's "Open full assistant": the same instance, shown as the full panel. */
163
+ onOpenFull?: () => void;
164
+ /** The window's "Minimize" (and its Escape): hidden, mounted, `visible` false. */
165
+ onMinimize?: () => void;
166
+ /** Told when Expand/Restore is pressed, so the container takes the N2 width. */
167
+ onExpandedChange?: (expanded: boolean) => void;
102
168
  }
169
+ /**
170
+ * The props the overlay itself decides, which a product's `panelProps` may not
171
+ * set. `presentation` and `onExpandedChange` are NOT in it: both were already
172
+ * accepted in `panelProps` (Slice 2), and the overlay's value is merged over
173
+ * them only in the compact presentation.
174
+ */
175
+ type AssistantOverlayOwnedPanelProp = 'panelId' | 'visible' | 'onClose' | 'docked' | 'onToggleDock' | 'onNavigate' | 'isShellLessTarget' | 'surface' | 'onOpenFull' | 'onMinimize';
103
176
  export interface AssistantOverlayProps {
104
177
  /** Panel id handed to the panel. */
105
178
  panelId?: string;
@@ -118,7 +191,7 @@ export interface AssistantOverlayProps {
118
191
  * closed panel's turns and deletes queued keeps going out, and a reopened
119
192
  * panel finds the list already current.
120
193
  */
121
- panelProps?: Omit<AIAssistantPanelProps, keyof AssistantOverlayPanelProps>;
194
+ panelProps?: Omit<AIAssistantPanelProps, AssistantOverlayOwnedPanelProp>;
122
195
  /**
123
196
  * Render something other than the shared `AIAssistantPanel` — a product
124
197
  * wrapper around it. Receives the props the overlay owns; spread them.
@@ -158,3 +231,4 @@ export interface AssistantOverlayProps {
158
231
  * `AssistantOverlayProvider` above it — there is no state to show.
159
232
  */
160
233
  export declare function AssistantOverlay(props: AssistantOverlayProps): import('react/jsx-runtime').JSX.Element | null;
234
+ export {};