@oxy.so/bloom 7.2.0 → 7.3.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 (107) hide show
  1. package/docs/adoption-matrix.mdx +9 -9
  2. package/docs/app-shell.mdx +22 -0
  3. package/docs/chip.mdx +5 -0
  4. package/docs/content-panel.mdx +5 -0
  5. package/docs/error-boundary.mdx +35 -0
  6. package/docs/settings-modal.mdx +5 -0
  7. package/lib/commonjs/app-shell/AppShellSplit.js +26 -14
  8. package/lib/commonjs/app-shell/AppShellSplit.js.map +1 -1
  9. package/lib/commonjs/chip/Chip.js +51 -7
  10. package/lib/commonjs/chip/Chip.js.map +1 -1
  11. package/lib/commonjs/content-panel/ContentPanel.js +6 -1
  12. package/lib/commonjs/content-panel/ContentPanel.js.map +1 -1
  13. package/lib/commonjs/content-panel/ContentPanel.web.js +6 -1
  14. package/lib/commonjs/content-panel/ContentPanel.web.js.map +1 -1
  15. package/lib/commonjs/error-boundary/ErrorBoundary.js +10 -0
  16. package/lib/commonjs/error-boundary/ErrorBoundary.js.map +1 -1
  17. package/lib/commonjs/error-boundary/PanelErrorBoundary.js +64 -0
  18. package/lib/commonjs/error-boundary/PanelErrorBoundary.js.map +1 -0
  19. package/lib/commonjs/error-boundary/index.js +7 -0
  20. package/lib/commonjs/error-boundary/index.js.map +1 -1
  21. package/lib/commonjs/index.js +7 -0
  22. package/lib/commonjs/index.js.map +1 -1
  23. package/lib/commonjs/index.web.js +7 -0
  24. package/lib/commonjs/index.web.js.map +1 -1
  25. package/lib/commonjs/settings-modal/SettingsPlanCard.js +11 -7
  26. package/lib/commonjs/settings-modal/SettingsPlanCard.js.map +1 -1
  27. package/lib/module/app-shell/AppShellSplit.js +26 -14
  28. package/lib/module/app-shell/AppShellSplit.js.map +1 -1
  29. package/lib/module/chip/Chip.js +51 -7
  30. package/lib/module/chip/Chip.js.map +1 -1
  31. package/lib/module/content-panel/ContentPanel.js +6 -1
  32. package/lib/module/content-panel/ContentPanel.js.map +1 -1
  33. package/lib/module/content-panel/ContentPanel.web.js +6 -1
  34. package/lib/module/content-panel/ContentPanel.web.js.map +1 -1
  35. package/lib/module/error-boundary/ErrorBoundary.js +10 -0
  36. package/lib/module/error-boundary/ErrorBoundary.js.map +1 -1
  37. package/lib/module/error-boundary/PanelErrorBoundary.js +59 -0
  38. package/lib/module/error-boundary/PanelErrorBoundary.js.map +1 -0
  39. package/lib/module/error-boundary/index.js +1 -0
  40. package/lib/module/error-boundary/index.js.map +1 -1
  41. package/lib/module/index.js +1 -1
  42. package/lib/module/index.js.map +1 -1
  43. package/lib/module/index.web.js +1 -1
  44. package/lib/module/index.web.js.map +1 -1
  45. package/lib/module/settings-modal/SettingsPlanCard.js +7 -3
  46. package/lib/module/settings-modal/SettingsPlanCard.js.map +1 -1
  47. package/lib/typescript/commonjs/app-shell/AppShellSplit.d.ts.map +1 -1
  48. package/lib/typescript/commonjs/app-shell/types.d.ts +5 -0
  49. package/lib/typescript/commonjs/app-shell/types.d.ts.map +1 -1
  50. package/lib/typescript/commonjs/chip/Chip.d.ts.map +1 -1
  51. package/lib/typescript/commonjs/content-panel/ContentPanel.d.ts.map +1 -1
  52. package/lib/typescript/commonjs/content-panel/ContentPanel.web.d.ts.map +1 -1
  53. package/lib/typescript/commonjs/content-panel/types.d.ts +3 -0
  54. package/lib/typescript/commonjs/content-panel/types.d.ts.map +1 -1
  55. package/lib/typescript/commonjs/error-boundary/ErrorBoundary.d.ts +1 -0
  56. package/lib/typescript/commonjs/error-boundary/ErrorBoundary.d.ts.map +1 -1
  57. package/lib/typescript/commonjs/error-boundary/PanelErrorBoundary.d.ts +4 -0
  58. package/lib/typescript/commonjs/error-boundary/PanelErrorBoundary.d.ts.map +1 -0
  59. package/lib/typescript/commonjs/error-boundary/index.d.ts +2 -1
  60. package/lib/typescript/commonjs/error-boundary/index.d.ts.map +1 -1
  61. package/lib/typescript/commonjs/error-boundary/types.d.ts +16 -0
  62. package/lib/typescript/commonjs/error-boundary/types.d.ts.map +1 -1
  63. package/lib/typescript/commonjs/index.d.ts +2 -2
  64. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  65. package/lib/typescript/commonjs/index.web.d.ts +2 -2
  66. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  67. package/lib/typescript/commonjs/settings-modal/SettingsPlanCard.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/settings-modal/types.d.ts +3 -0
  69. package/lib/typescript/commonjs/settings-modal/types.d.ts.map +1 -1
  70. package/lib/typescript/module/app-shell/AppShellSplit.d.ts.map +1 -1
  71. package/lib/typescript/module/app-shell/types.d.ts +5 -0
  72. package/lib/typescript/module/app-shell/types.d.ts.map +1 -1
  73. package/lib/typescript/module/chip/Chip.d.ts.map +1 -1
  74. package/lib/typescript/module/content-panel/ContentPanel.d.ts.map +1 -1
  75. package/lib/typescript/module/content-panel/ContentPanel.web.d.ts.map +1 -1
  76. package/lib/typescript/module/content-panel/types.d.ts +3 -0
  77. package/lib/typescript/module/content-panel/types.d.ts.map +1 -1
  78. package/lib/typescript/module/error-boundary/ErrorBoundary.d.ts +1 -0
  79. package/lib/typescript/module/error-boundary/ErrorBoundary.d.ts.map +1 -1
  80. package/lib/typescript/module/error-boundary/PanelErrorBoundary.d.ts +4 -0
  81. package/lib/typescript/module/error-boundary/PanelErrorBoundary.d.ts.map +1 -0
  82. package/lib/typescript/module/error-boundary/index.d.ts +2 -1
  83. package/lib/typescript/module/error-boundary/index.d.ts.map +1 -1
  84. package/lib/typescript/module/error-boundary/types.d.ts +16 -0
  85. package/lib/typescript/module/error-boundary/types.d.ts.map +1 -1
  86. package/lib/typescript/module/index.d.ts +2 -2
  87. package/lib/typescript/module/index.d.ts.map +1 -1
  88. package/lib/typescript/module/index.web.d.ts +2 -2
  89. package/lib/typescript/module/index.web.d.ts.map +1 -1
  90. package/lib/typescript/module/settings-modal/SettingsPlanCard.d.ts.map +1 -1
  91. package/lib/typescript/module/settings-modal/types.d.ts +3 -0
  92. package/lib/typescript/module/settings-modal/types.d.ts.map +1 -1
  93. package/package.json +1 -1
  94. package/src/app-shell/AppShellSplit.tsx +16 -7
  95. package/src/app-shell/types.ts +5 -0
  96. package/src/chip/Chip.tsx +26 -5
  97. package/src/content-panel/ContentPanel.tsx +3 -1
  98. package/src/content-panel/ContentPanel.web.tsx +3 -1
  99. package/src/content-panel/types.ts +3 -0
  100. package/src/error-boundary/ErrorBoundary.tsx +6 -0
  101. package/src/error-boundary/PanelErrorBoundary.tsx +38 -0
  102. package/src/error-boundary/index.ts +3 -0
  103. package/src/error-boundary/types.ts +18 -0
  104. package/src/index.ts +3 -1
  105. package/src/index.web.ts +3 -1
  106. package/src/settings-modal/SettingsPlanCard.tsx +2 -0
  107. package/src/settings-modal/types.ts +3 -0
@@ -83,6 +83,12 @@ export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundarySt
83
83
  this.props.onError?.(error, errorInfo);
84
84
  }
85
85
 
86
+ componentDidUpdate(previous: ErrorBoundaryProps): void {
87
+ if (this.state.hasError && !Object.is(previous.resetKey, this.props.resetKey)) {
88
+ this.setState({ hasError: false, error: null, errorInfo: null, retryCount: 0 });
89
+ }
90
+ }
91
+
86
92
  private handleRetry = (): void => {
87
93
  this.setState((prev) => ({
88
94
  hasError: false,
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import { ScrollView } from 'react-native';
3
+ import { EmptyState } from '../empty-state';
4
+ import { useBottomEdgeInset } from '../layout/bottom-edge';
5
+ import { useMessages } from '../locale/messages';
6
+ import { space } from '../styles/tokens';
7
+ import { ErrorBoundary } from './ErrorBoundary';
8
+ import { ERROR_BOUNDARY_MESSAGES } from './messages';
9
+ import type { PanelErrorBoundaryProps } from './types';
10
+
11
+ /** Local recovery inside a healthy Bloom shell. Catastrophic/provider errors belong to ErrorBoundary. */
12
+ export function PanelErrorBoundary({ children, fallback, emptyState, bottomInset, ...props }: PanelErrorBoundaryProps) {
13
+ const { messages } = useMessages(ERROR_BOUNDARY_MESSAGES);
14
+ const inheritedBottom = useBottomEdgeInset();
15
+ return (
16
+ <ErrorBoundary {...props} fallback={fallback !== undefined ? fallback : (({ retry }) => (
17
+ <ScrollView
18
+ style={{ flex: 1, minHeight: 0 }}
19
+ contentContainerStyle={{ flexGrow: 1, paddingHorizontal: space.md, paddingBottom: bottomInset ?? inheritedBottom }}
20
+ >
21
+ <EmptyState
22
+ variant="compact"
23
+ {...emptyState}
24
+ title={emptyState?.title ?? messages.title}
25
+ description={emptyState?.description ?? messages.message}
26
+ style={[{ flexGrow: 1 }, emptyState?.style]}
27
+ action={{
28
+ ...emptyState?.action,
29
+ label: emptyState?.action?.label ?? messages.retry,
30
+ onPress: () => { emptyState?.action?.onPress?.(); retry(); },
31
+ }}
32
+ />
33
+ </ScrollView>
34
+ ))}>
35
+ {children}
36
+ </ErrorBoundary>
37
+ );
38
+ }
@@ -1,6 +1,9 @@
1
1
  export { ErrorBoundary } from './ErrorBoundary';
2
+ export { PanelErrorBoundary } from './PanelErrorBoundary';
2
3
  export type {
3
4
  ErrorBoundaryProps,
4
5
  ErrorBoundaryFallback,
5
6
  ErrorBoundaryFallbackContext,
7
+ PanelErrorBoundaryOptions,
8
+ PanelErrorBoundaryProps,
6
9
  } from './types';
@@ -1,4 +1,5 @@
1
1
  import type { ReactNode, ErrorInfo } from 'react';
2
+ import type { EmptyStateProps } from '../empty-state/types';
2
3
 
3
4
  /**
4
5
  * Context passed to a render-prop `fallback` when an ErrorBoundary catches an
@@ -38,6 +39,8 @@ export type ErrorBoundaryFallback =
38
39
 
39
40
  export interface ErrorBoundaryProps {
40
41
  children: ReactNode;
42
+ /** Changing this identity resets a failed boundary without remounting healthy children. */
43
+ resetKey?: string | number;
41
44
  /**
42
45
  * Custom fallback UI to render on error. Accepts either:
43
46
  * - a ReactNode (static — same UI on every error), or
@@ -57,3 +60,18 @@ export interface ErrorBoundaryProps {
57
60
  onError?: (error: Error, errorInfo: ErrorInfo) => void;
58
61
  testID?: string;
59
62
  }
63
+
64
+ /** Recovery UI for a panel inside a healthy Bloom provider. */
65
+ export interface PanelErrorBoundaryOptions {
66
+ resetKey?: ErrorBoundaryProps['resetKey'];
67
+ onError?: ErrorBoundaryProps['onError'];
68
+ fallback?: ErrorBoundaryFallback;
69
+ /** Defaults to localized error wording and a retry action. A supplied action runs before retry. */
70
+ emptyState?: EmptyStateProps;
71
+ /** Override inherited bottom chrome clearance when the parent has already reserved it. */
72
+ bottomInset?: number;
73
+ }
74
+
75
+ export interface PanelErrorBoundaryProps extends PanelErrorBoundaryOptions {
76
+ children: ReactNode;
77
+ }
package/src/index.ts CHANGED
@@ -220,11 +220,13 @@ export * from './task-list';
220
220
  export * from './agent-chat';
221
221
  export * from './ai-chat';
222
222
  export * from './radio-indicator';
223
- export { ErrorBoundary } from './error-boundary';
223
+ export { ErrorBoundary, PanelErrorBoundary } from './error-boundary';
224
224
  export type {
225
225
  ErrorBoundaryProps,
226
226
  ErrorBoundaryFallback,
227
227
  ErrorBoundaryFallbackContext,
228
+ PanelErrorBoundaryOptions,
229
+ PanelErrorBoundaryProps,
228
230
  } from './error-boundary';
229
231
  export * as Shapes from './shapes';
230
232
  export * from './avatar';
package/src/index.web.ts CHANGED
@@ -225,11 +225,13 @@ export * from './task-list';
225
225
  export * from './agent-chat/index.web';
226
226
  export * from './ai-chat/index.web';
227
227
  export * from './radio-indicator';
228
- export { ErrorBoundary } from './error-boundary';
228
+ export { ErrorBoundary, PanelErrorBoundary } from './error-boundary';
229
229
  export type {
230
230
  ErrorBoundaryProps,
231
231
  ErrorBoundaryFallback,
232
232
  ErrorBoundaryFallbackContext,
233
+ PanelErrorBoundaryOptions,
234
+ PanelErrorBoundaryProps,
233
235
  } from './error-boundary';
234
236
  export * as Shapes from './shapes';
235
237
  export * from './avatar';
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import { EmptyState } from '../empty-state';
2
3
  import { StyleSheet, View } from 'react-native';
3
4
 
4
5
  import { useMessages } from '../locale/messages';
@@ -81,6 +82,7 @@ function Sections({ sections }: { sections: SettingsPageSection[] }) {
81
82
  {sections.map((section) => {
82
83
  const card = (
83
84
  <SettingsCard>
85
+ {section.rows.length === 0 && section.emptyState ? <EmptyState variant="compact" {...section.emptyState} /> : null}
84
86
  {section.rows.map((row) => (
85
87
  <SettingsRow key={row.key} label={row.label} description={row.description}>
86
88
  {row.control}
@@ -1,3 +1,4 @@
1
+ import type { EmptyStateProps } from '../empty-state/types';
1
2
  import type { ComponentType, ReactNode } from 'react';
2
3
  import type { StyleProp, ViewStyle } from 'react-native';
3
4
 
@@ -212,6 +213,8 @@ export interface SettingsPageSection {
212
213
  description?: string;
213
214
  action?: ReactNode;
214
215
  rows: SettingsRowData[];
216
+ /** Rendered inside the section card only when rows is empty. */
217
+ emptyState?: EmptyStateProps;
215
218
  }
216
219
 
217
220
  export interface SettingsGeneralPageProps {