@oxy.so/bloom 4.8.0 → 4.10.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.
Files changed (59) hide show
  1. package/docs/adoption-matrix.mdx +2 -2
  2. package/docs/ai-chat.mdx +21 -0
  3. package/docs/composer-panel.mdx +1 -1
  4. package/lib/commonjs/ai-chat/AiChatContainer.js +384 -77
  5. package/lib/commonjs/ai-chat/AiChatContainer.js.map +1 -1
  6. package/lib/commonjs/ai-chat/context.js +28 -1
  7. package/lib/commonjs/ai-chat/context.js.map +1 -1
  8. package/lib/commonjs/ai-chat/index.js +6 -0
  9. package/lib/commonjs/ai-chat/index.js.map +1 -1
  10. package/lib/commonjs/ai-chat/index.web.js +6 -0
  11. package/lib/commonjs/ai-chat/index.web.js.map +1 -1
  12. package/lib/commonjs/composer-panel/ComposerPanelBase.js +5 -1
  13. package/lib/commonjs/composer-panel/ComposerPanelBase.js.map +1 -1
  14. package/lib/module/ai-chat/AiChatContainer.js +386 -79
  15. package/lib/module/ai-chat/AiChatContainer.js.map +1 -1
  16. package/lib/module/ai-chat/context.js +26 -0
  17. package/lib/module/ai-chat/context.js.map +1 -1
  18. package/lib/module/ai-chat/index.js +1 -1
  19. package/lib/module/ai-chat/index.js.map +1 -1
  20. package/lib/module/ai-chat/index.web.js +1 -1
  21. package/lib/module/ai-chat/index.web.js.map +1 -1
  22. package/lib/module/composer-panel/ComposerPanelBase.js +5 -1
  23. package/lib/module/composer-panel/ComposerPanelBase.js.map +1 -1
  24. package/lib/typescript/commonjs/ai-chat/AiChatContainer.d.ts +24 -1
  25. package/lib/typescript/commonjs/ai-chat/AiChatContainer.d.ts.map +1 -1
  26. package/lib/typescript/commonjs/ai-chat/context.d.ts +32 -0
  27. package/lib/typescript/commonjs/ai-chat/context.d.ts.map +1 -1
  28. package/lib/typescript/commonjs/ai-chat/index.d.ts +2 -2
  29. package/lib/typescript/commonjs/ai-chat/index.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/ai-chat/index.web.d.ts +2 -2
  31. package/lib/typescript/commonjs/ai-chat/index.web.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/ai-chat/types.d.ts +17 -0
  33. package/lib/typescript/commonjs/ai-chat/types.d.ts.map +1 -1
  34. package/lib/typescript/commonjs/composer-panel/ComposerPanelBase.d.ts +1 -1
  35. package/lib/typescript/commonjs/composer-panel/ComposerPanelBase.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/composer-panel/types.d.ts +7 -0
  37. package/lib/typescript/commonjs/composer-panel/types.d.ts.map +1 -1
  38. package/lib/typescript/module/ai-chat/AiChatContainer.d.ts +24 -1
  39. package/lib/typescript/module/ai-chat/AiChatContainer.d.ts.map +1 -1
  40. package/lib/typescript/module/ai-chat/context.d.ts +32 -0
  41. package/lib/typescript/module/ai-chat/context.d.ts.map +1 -1
  42. package/lib/typescript/module/ai-chat/index.d.ts +2 -2
  43. package/lib/typescript/module/ai-chat/index.d.ts.map +1 -1
  44. package/lib/typescript/module/ai-chat/index.web.d.ts +2 -2
  45. package/lib/typescript/module/ai-chat/index.web.d.ts.map +1 -1
  46. package/lib/typescript/module/ai-chat/types.d.ts +17 -0
  47. package/lib/typescript/module/ai-chat/types.d.ts.map +1 -1
  48. package/lib/typescript/module/composer-panel/ComposerPanelBase.d.ts +1 -1
  49. package/lib/typescript/module/composer-panel/ComposerPanelBase.d.ts.map +1 -1
  50. package/lib/typescript/module/composer-panel/types.d.ts +7 -0
  51. package/lib/typescript/module/composer-panel/types.d.ts.map +1 -1
  52. package/package.json +1 -1
  53. package/src/ai-chat/AiChatContainer.tsx +343 -59
  54. package/src/ai-chat/context.ts +39 -0
  55. package/src/ai-chat/index.ts +2 -2
  56. package/src/ai-chat/index.web.ts +2 -2
  57. package/src/ai-chat/types.ts +17 -0
  58. package/src/composer-panel/ComposerPanelBase.tsx +5 -1
  59. package/src/composer-panel/types.ts +8 -0
@@ -79,3 +79,42 @@ export const AiChatShellContext = createContext<AiChatShellState | null>(null);
79
79
  export function useAiChatShell(): AiChatShellState | null {
80
80
  return useContext(AiChatShellContext);
81
81
  }
82
+
83
+ /**
84
+ * The heights an `AiChatContainer floatingChrome` measures for the chrome it
85
+ * floats over its `children`: the header block at the top and the footer
86
+ * (`AgentThinking` + composer, with its fade strip) at the bottom, px.
87
+ */
88
+ export interface AiChatChromeInsets {
89
+ top: number;
90
+ bottom: number;
91
+ }
92
+
93
+ /** Where the thread is, reported to the container so each edge knows when to fade. */
94
+ export interface AiChatScrollMetrics {
95
+ offset: number;
96
+ viewport: number;
97
+ content: number;
98
+ }
99
+
100
+ /**
101
+ * What a floating-chrome container hands its `children`. Internal: the thread
102
+ * reads `insets` and reports its scroll; hosts read only the insets, through
103
+ * `useAiChatChromeInsets()`.
104
+ */
105
+ export interface AiChatFloatingChrome {
106
+ insets: AiChatChromeInsets;
107
+ reportScroll: (metrics: AiChatScrollMetrics) => void;
108
+ }
109
+
110
+ export const AiChatFloatingChromeContext = createContext<AiChatFloatingChrome | null>(null);
111
+
112
+ /**
113
+ * Inside `AiChatContainer floatingChrome`: how much of the top and bottom of the
114
+ * card the floating header and composer cover, so a custom child (an empty
115
+ * state, a scroller of its own) can keep its resting content clear of them.
116
+ * `null` anywhere else — outside a container, or in one that stacks its chrome.
117
+ */
118
+ export function useAiChatChromeInsets(): AiChatChromeInsets | null {
119
+ return useContext(AiChatFloatingChromeContext)?.insets ?? null;
120
+ }
@@ -15,8 +15,8 @@ export {
15
15
  AiChatUserMessage,
16
16
  } from './AiChatMessages';
17
17
  export { AiChatMobileHeader, AiChatResizeHandle, AiChatShell } from './AiChatShell';
18
- export { useAiChatShell } from './context';
19
- export type { AiChatShellState } from './context';
18
+ export { useAiChatChromeInsets, useAiChatShell } from './context';
19
+ export type { AiChatChromeInsets, AiChatShellState } from './context';
20
20
  export type {
21
21
  AiChatAssistantMessageProps,
22
22
  AiChatBulletListProps,
@@ -20,8 +20,8 @@ export {
20
20
  AiChatUserMessage,
21
21
  } from './AiChatMessages';
22
22
  export { AiChatMobileHeader, AiChatResizeHandle, AiChatShell } from './AiChatShell';
23
- export { useAiChatShell } from './context';
24
- export type { AiChatShellState } from './context';
23
+ export { useAiChatChromeInsets, useAiChatShell } from './context';
24
+ export type { AiChatChromeInsets, AiChatShellState } from './context';
25
25
  export type {
26
26
  AiChatAssistantMessageProps,
27
27
  AiChatBulletListProps,
@@ -317,6 +317,23 @@ export interface AiChatContainerProps {
317
317
  * `false` leaves the root transparent.
318
318
  */
319
319
  surface?: boolean;
320
+ /**
321
+ * Float the header and the composer OVER the transcript instead of stacking
322
+ * them around it. Default `false`: header row, thread, footer, as siblings.
323
+ *
324
+ * With it, `children` fill the whole card and scroll BEHIND both: the header
325
+ * slot and breadcrumb row are pinned to the top with no band of their own,
326
+ * the footer (`AgentThinking` + `composer`) to the bottom. Each edge paints a
327
+ * fade of the card's surface only while the transcript actually runs under
328
+ * it, ramping in over the first px of overlap. An `AiChatThread` inside pads
329
+ * its content by the measured heights of both, so the first and last turns
330
+ * rest clear of them; a custom child reads the same numbers from
331
+ * `useAiChatChromeInsets()`.
332
+ *
333
+ * The fades are background-secondary; with `surface={false}` there is no
334
+ * known colour to fade to, so the chrome floats without them.
335
+ */
336
+ floatingChrome?: boolean;
320
337
  labels?: AiChatContainerLabels;
321
338
  style?: StyleProp<ViewStyle>;
322
339
  testID?: string;
@@ -145,6 +145,7 @@ export function ComposerPanelBase({
145
145
  onRemoveAttachment,
146
146
  status,
147
147
  emptyAction,
148
+ onKeyPress: onKeyPressProp,
148
149
  inputRef,
149
150
  labels: labelOverrides,
150
151
  style,
@@ -200,12 +201,15 @@ export function ComposerPanelBase({
200
201
 
201
202
  const onKeyPress = useCallback(
202
203
  (event: NativeSyntheticEvent<TextInputKeyPressEventData>) => {
204
+ // The host sees the key first and may take it (a suggestion list).
205
+ onKeyPressProp?.(event);
206
+ if (event.defaultPrevented) return;
203
207
  const native: TextInputKeyPressEventData & { shiftKey?: boolean; isComposing?: boolean } = event.nativeEvent;
204
208
  if (!IS_WEB || native.key !== 'Enter' || native.shiftKey || native.isComposing) return;
205
209
  event.preventDefault();
206
210
  submit();
207
211
  },
208
- [submit],
212
+ [submit, onKeyPressProp],
209
213
  );
210
214
 
211
215
  const hasAttachments = !!attachments && attachments.length > 0;
@@ -271,6 +271,14 @@ export interface ComposerPanelProps {
271
271
  */
272
272
  emptyAction?: ReactNode;
273
273
 
274
+ /**
275
+ * The field's key events, BEFORE the panel's own Enter rule, so a host can
276
+ * take a key from it — the pill's contract. Calling `preventDefault()` stops
277
+ * the panel acting on that key: a suggestion list over the composer drives
278
+ * the arrows, Enter and Escape this way.
279
+ */
280
+ onKeyPress?: (event: NativeSyntheticEvent<TextInputKeyPressEventData>) => void;
281
+
274
282
  /** The prompt field itself, for focus or a scripted demo. */
275
283
  inputRef?: RefObject<TextInput | null>;
276
284
  labels?: ComposerPanelLabels;