@object-ui/plugin-chatbot 3.1.5 → 3.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 (42) hide show
  1. package/.turbo/turbo-build.log +39 -8
  2. package/CHANGELOG.md +18 -0
  3. package/README.md +86 -4
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +11875 -2897
  6. package/dist/index.umd.cjs +71 -28
  7. package/dist/{src → packages/plugin-chatbot/src}/ChatbotEnhanced.d.ts +8 -0
  8. package/dist/packages/plugin-chatbot/src/ChatbotEnhanced.d.ts.map +1 -0
  9. package/dist/packages/plugin-chatbot/src/FloatingChatbot.d.ts +15 -0
  10. package/dist/packages/plugin-chatbot/src/FloatingChatbot.d.ts.map +1 -0
  11. package/dist/packages/plugin-chatbot/src/FloatingChatbotPanel.d.ts +29 -0
  12. package/dist/packages/plugin-chatbot/src/FloatingChatbotPanel.d.ts.map +1 -0
  13. package/dist/packages/plugin-chatbot/src/FloatingChatbotProvider.d.ts +37 -0
  14. package/dist/packages/plugin-chatbot/src/FloatingChatbotProvider.d.ts.map +1 -0
  15. package/dist/packages/plugin-chatbot/src/FloatingChatbotTrigger.d.ts +21 -0
  16. package/dist/packages/plugin-chatbot/src/FloatingChatbotTrigger.d.ts.map +1 -0
  17. package/dist/{src → packages/plugin-chatbot/src}/index.d.ts +10 -0
  18. package/dist/packages/plugin-chatbot/src/index.d.ts.map +1 -0
  19. package/dist/packages/plugin-chatbot/src/renderer.d.ts.map +1 -0
  20. package/dist/packages/plugin-chatbot/src/useObjectChat.d.ts +112 -0
  21. package/dist/packages/plugin-chatbot/src/useObjectChat.d.ts.map +1 -0
  22. package/dist/packages/plugin-chatbot/src/utils.d.ts.map +1 -0
  23. package/package.json +10 -8
  24. package/src/ChatbotEnhanced.tsx +55 -4
  25. package/src/FloatingChatbot.tsx +89 -0
  26. package/src/FloatingChatbotPanel.tsx +102 -0
  27. package/src/FloatingChatbotProvider.tsx +80 -0
  28. package/src/FloatingChatbotTrigger.tsx +55 -0
  29. package/src/__tests__/ChatbotEnhancedStreaming.test.tsx +159 -0
  30. package/src/__tests__/FloatingChatbotProvider.test.tsx +134 -0
  31. package/src/__tests__/FloatingChatbotWidgets.test.tsx +165 -0
  32. package/src/__tests__/useObjectChat.test.tsx +347 -0
  33. package/src/index.tsx +19 -0
  34. package/src/renderer.tsx +261 -92
  35. package/src/useObjectChat.ts +344 -0
  36. package/vite.config.ts +2 -1
  37. package/dist/src/ChatbotEnhanced.d.ts.map +0 -1
  38. package/dist/src/index.d.ts.map +0 -1
  39. package/dist/src/renderer.d.ts.map +0 -1
  40. package/dist/src/utils.d.ts.map +0 -1
  41. /package/dist/{src → packages/plugin-chatbot/src}/renderer.d.ts +0 -0
  42. /package/dist/{src → packages/plugin-chatbot/src}/utils.d.ts +0 -0
@@ -20,7 +20,15 @@ export interface ChatbotEnhancedProps extends React.HTMLAttributes<HTMLDivElemen
20
20
  placeholder?: string;
21
21
  onSendMessage?: (message: string, files?: File[]) => void;
22
22
  onClear?: () => void;
23
+ /** Stop the current streaming response (API mode only) */
24
+ onStop?: () => void;
25
+ /** Reload / retry the last assistant message (API mode only) */
26
+ onReload?: () => void;
23
27
  disabled?: boolean;
28
+ /** Whether the assistant is currently generating a response */
29
+ isLoading?: boolean;
30
+ /** Current streaming/API error */
31
+ error?: Error;
24
32
  showTimestamp?: boolean;
25
33
  userAvatarUrl?: string;
26
34
  userAvatarFallback?: string;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatbotEnhanced.d.ts","sourceRoot":"","sources":["../../../../src/ChatbotEnhanced.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAA;IACrC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAChF,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;IACzD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,kCAAkC;IAClC,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACjE;AAiED,QAAA,MAAM,eAAe,6FAgTpB,CAAA;AAID,OAAO,EAAE,eAAe,EAAE,CAAA"}
@@ -0,0 +1,15 @@
1
+ import { FloatingChatbotConfig } from '@object-ui/types';
2
+ import { ChatbotEnhancedProps } from './ChatbotEnhanced';
3
+ export interface FloatingChatbotProps extends ChatbotEnhancedProps {
4
+ /** Floating configuration */
5
+ floatingConfig?: FloatingChatbotConfig;
6
+ }
7
+ /**
8
+ * Floating Chatbot — Airtable-style FAB widget.
9
+ *
10
+ * Wraps `ChatbotEnhanced` in a floating panel that can be toggled
11
+ * via a fixed FAB trigger button. Uses React portal to avoid
12
+ * DOM/z-index conflicts.
13
+ */
14
+ export declare function FloatingChatbot({ floatingConfig, ...chatbotProps }: FloatingChatbotProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=FloatingChatbot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FloatingChatbot.d.ts","sourceRoot":"","sources":["../../../../src/FloatingChatbot.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AAI7D,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAE9E,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,6BAA6B;IAC7B,cAAc,CAAC,EAAE,qBAAqB,CAAA;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,EAC9B,cAAc,EACd,GAAG,YAAY,EAChB,EAAE,oBAAoB,2CAyDtB"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import * as React from "react";
9
+ export interface FloatingChatbotPanelProps {
10
+ /** Panel title */
11
+ title?: string;
12
+ /** Position of the panel (anchored to FAB corner) */
13
+ position?: "bottom-right" | "bottom-left";
14
+ /** Panel width in pixels (ignored in fullscreen) */
15
+ width?: number;
16
+ /** Panel height in pixels (ignored in fullscreen) */
17
+ height?: number;
18
+ /** Content to render inside the panel body */
19
+ children: React.ReactNode;
20
+ /** Custom className for the panel container */
21
+ className?: string;
22
+ }
23
+ /**
24
+ * Floating panel overlay for the chatbot.
25
+ * Renders above all content, anchored to the configured position.
26
+ * Supports fullscreen toggle and close.
27
+ */
28
+ export declare function FloatingChatbotPanel({ title, position, width, height, children, className, }: FloatingChatbotPanelProps): import("react/jsx-runtime").JSX.Element | null;
29
+ //# sourceMappingURL=FloatingChatbotPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FloatingChatbotPanel.d.ts","sourceRoot":"","sources":["../../../../src/FloatingChatbotPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,WAAW,yBAAyB;IACxC,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qDAAqD;IACrD,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,CAAA;IACzC,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,8CAA8C;IAC9C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,KAAc,EACd,QAAyB,EACzB,KAAW,EACX,MAAY,EACZ,QAAQ,EACR,SAAS,GACV,EAAE,yBAAyB,kDA4D3B"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import * as React from "react";
9
+ export interface FloatingChatbotState {
10
+ /** Whether the floating panel is currently open */
11
+ isOpen: boolean;
12
+ /** Whether the panel is in fullscreen mode */
13
+ isFullscreen: boolean;
14
+ }
15
+ export interface FloatingChatbotActions {
16
+ /** Open the floating panel */
17
+ open: () => void;
18
+ /** Close the floating panel */
19
+ close: () => void;
20
+ /** Toggle the floating panel open/closed */
21
+ toggle: () => void;
22
+ /** Toggle fullscreen mode */
23
+ toggleFullscreen: () => void;
24
+ }
25
+ export type FloatingChatbotContextValue = FloatingChatbotState & FloatingChatbotActions;
26
+ export interface FloatingChatbotProviderProps {
27
+ /** Whether the panel is open by default */
28
+ defaultOpen?: boolean;
29
+ children: React.ReactNode;
30
+ }
31
+ export declare function FloatingChatbotProvider({ defaultOpen, children, }: FloatingChatbotProviderProps): import("react/jsx-runtime").JSX.Element;
32
+ /**
33
+ * Hook to access the floating chatbot state and actions.
34
+ * Must be used within a `FloatingChatbotProvider`.
35
+ */
36
+ export declare function useFloatingChatbot(): FloatingChatbotContextValue;
37
+ //# sourceMappingURL=FloatingChatbotProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FloatingChatbotProvider.d.ts","sourceRoot":"","sources":["../../../../src/FloatingChatbotProvider.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,MAAM,EAAE,OAAO,CAAA;IACf,8CAA8C;IAC9C,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,6BAA6B;IAC7B,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B;AAED,MAAM,MAAM,2BAA2B,GAAG,oBAAoB,GAAG,sBAAsB,CAAA;AAIvF,MAAM,WAAW,4BAA4B;IAC3C,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,uBAAuB,CAAC,EACtC,WAAmB,EACnB,QAAQ,GACT,EAAE,4BAA4B,2CAwB9B;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,2BAA2B,CAQhE"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ export interface FloatingChatbotTriggerProps {
9
+ /** Position of the FAB */
10
+ position?: "bottom-right" | "bottom-left";
11
+ /** Size of the trigger button in pixels */
12
+ size?: number;
13
+ /** Custom className */
14
+ className?: string;
15
+ }
16
+ /**
17
+ * Floating Action Button (FAB) trigger for the chatbot.
18
+ * Renders a circular button fixed to the viewport corner.
19
+ */
20
+ export declare function FloatingChatbotTrigger({ position, size, className, }: FloatingChatbotTriggerProps): import("react/jsx-runtime").JSX.Element;
21
+ //# sourceMappingURL=FloatingChatbotTrigger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FloatingChatbotTrigger.d.ts","sourceRoot":"","sources":["../../../../src/FloatingChatbotTrigger.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,2BAA2B;IAC1C,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,CAAA;IACzC,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uBAAuB;IACvB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAyB,EACzB,IAAS,EACT,SAAS,GACV,EAAE,2BAA2B,2CAuB7B"}
@@ -41,5 +41,15 @@ export interface TypingIndicatorProps extends React.HTMLAttributes<HTMLDivElemen
41
41
  }
42
42
  declare const TypingIndicator: React.ForwardRefExoticComponent<TypingIndicatorProps & React.RefAttributes<HTMLDivElement>>;
43
43
  export { Chatbot, TypingIndicator };
44
+ export { useObjectChat } from './useObjectChat';
45
+ export type { UseObjectChatOptions, UseObjectChatReturn } from './useObjectChat';
46
+ export { FloatingChatbot } from './FloatingChatbot';
47
+ export type { FloatingChatbotProps } from './FloatingChatbot';
48
+ export { FloatingChatbotProvider, useFloatingChatbot } from './FloatingChatbotProvider';
49
+ export type { FloatingChatbotProviderProps, FloatingChatbotState, FloatingChatbotActions, FloatingChatbotContextValue, } from './FloatingChatbotProvider';
50
+ export { FloatingChatbotTrigger } from './FloatingChatbotTrigger';
51
+ export type { FloatingChatbotTriggerProps } from './FloatingChatbotTrigger';
52
+ export { FloatingChatbotPanel } from './FloatingChatbotPanel';
53
+ export type { FloatingChatbotPanelProps } from './FloatingChatbotPanel';
44
54
  export * from './renderer';
45
55
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAM9B,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAA;IACrC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAGD,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACxE,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAGD,QAAA,MAAM,OAAO,qFAwGZ,CAAA;AAID,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,WAAW,CAAA;IACpB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC;AAiED,MAAM,WAAW,oBAAqB,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IAChF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,QAAA,MAAM,eAAe,6FAkBpB,CAAA;AAGD,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,CAAA;AAGnC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGjF,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACxF,YAAY,EACV,4BAA4B,EAC5B,oBAAoB,EACpB,sBAAsB,EACtB,2BAA2B,GAC5B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAGxE,cAAc,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../src/renderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,112 @@
1
+ import { ChatMessage as OuiChatMessage } from '@object-ui/types';
2
+ /**
3
+ * Configuration options for useObjectChat hook.
4
+ */
5
+ export interface UseObjectChatOptions {
6
+ /**
7
+ * Backend API endpoint for streaming chat.
8
+ * When provided, uses @ai-sdk/react useChat for SSE streaming.
9
+ * When absent, operates in local/legacy mode.
10
+ */
11
+ api?: string;
12
+ /**
13
+ * Initial messages to populate the chat.
14
+ */
15
+ initialMessages?: OuiChatMessage[];
16
+ /**
17
+ * Conversation ID for multi-turn context.
18
+ */
19
+ conversationId?: string;
20
+ /**
21
+ * System prompt for the assistant.
22
+ */
23
+ systemPrompt?: string;
24
+ /**
25
+ * AI model identifier.
26
+ */
27
+ model?: string;
28
+ /**
29
+ * Whether streaming is enabled.
30
+ * @default true
31
+ */
32
+ streamingEnabled?: boolean;
33
+ /**
34
+ * Additional headers to send with API requests.
35
+ */
36
+ headers?: Record<string, string>;
37
+ /**
38
+ * Additional body parameters for each API request.
39
+ */
40
+ body?: Record<string, unknown>;
41
+ /**
42
+ * Maximum tool-calling round-trips per message.
43
+ * @default 5
44
+ */
45
+ maxToolRoundtrips?: number;
46
+ /**
47
+ * Error callback.
48
+ */
49
+ onError?: (error: Error) => void;
50
+ /**
51
+ * Show timestamps on messages.
52
+ */
53
+ showTimestamp?: boolean;
54
+ /**
55
+ * Enable local auto-response (legacy/demo mode). Ignored when `api` is set.
56
+ */
57
+ autoResponse?: boolean;
58
+ /**
59
+ * Auto-response text for legacy/demo mode.
60
+ */
61
+ autoResponseText?: string;
62
+ /**
63
+ * Auto-response delay in ms for legacy/demo mode.
64
+ * @default 1000
65
+ */
66
+ autoResponseDelay?: number;
67
+ /**
68
+ * External send callback (fires for both modes).
69
+ */
70
+ onSend?: (content: string, messages: OuiChatMessage[]) => void;
71
+ }
72
+ /**
73
+ * Return type of useObjectChat.
74
+ */
75
+ export interface UseObjectChatReturn {
76
+ /** Current chat messages */
77
+ messages: OuiChatMessage[];
78
+ /** Whether the assistant is currently generating a response */
79
+ isLoading: boolean;
80
+ /** Current error, if any */
81
+ error: Error | undefined;
82
+ /** Send a new user message */
83
+ sendMessage: (content: string, files?: File[]) => void;
84
+ /** Stop the current streaming response */
85
+ stop: () => void;
86
+ /** Reload / retry the last assistant message */
87
+ reload: () => void;
88
+ /** Clear all messages */
89
+ clear: () => void;
90
+ /** Whether the hook is operating in API (streaming) mode */
91
+ isApiMode: boolean;
92
+ /** Input value (controlled by the hook for API mode) */
93
+ input: string;
94
+ /** Set input value */
95
+ setInput: (value: string) => void;
96
+ /** Handle input change event */
97
+ handleInputChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
98
+ }
99
+ /**
100
+ * useObjectChat – Composable hook for ObjectUI Chatbot.
101
+ *
102
+ * When `api` is provided, delegates to @ai-sdk/react's useChat for
103
+ * SSE streaming, tool-calling, and production-grade chat.
104
+ *
105
+ * When `api` is absent, operates in local/legacy mode with optional
106
+ * auto-response for demos and playground use.
107
+ *
108
+ * The mode is locked on first render to satisfy the Rules of Hooks.
109
+ * If `api` changes after mount, the mode will NOT switch dynamically.
110
+ */
111
+ export declare function useObjectChat(options?: UseObjectChatOptions): UseObjectChatReturn;
112
+ //# sourceMappingURL=useObjectChat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useObjectChat.d.ts","sourceRoot":"","sources":["../../../../src/useObjectChat.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAItE;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,eAAe,CAAC,EAAE,cAAc,EAAE,CAAC;IACnC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAGxB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;CAChE;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,+DAA+D;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB,4BAA4B;IAC5B,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,8BAA8B;IAC9B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IACvD,0CAA0C;IAC1C,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,gDAAgD;IAChD,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,yBAAyB;IACzB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,4DAA4D;IAC5D,SAAS,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,gCAAgC;IAChC,iBAAiB,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,KAAK,IAAI,CAAC;CAC3F;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CAwMrF"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,SAAQ,GAAG,MAAM,CAKvD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-chatbot",
3
- "version": "3.1.5",
3
+ "version": "3.3.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Chatbot interface plugin for Object UI",
@@ -24,14 +24,16 @@
24
24
  }
25
25
  },
26
26
  "dependencies": {
27
- "lucide-react": "^0.577.0",
27
+ "@ai-sdk/react": "^3.0.160",
28
+ "ai": "^6.0.158",
29
+ "lucide-react": "^1.8.0",
28
30
  "react-markdown": "^10.1.0",
29
31
  "react-syntax-highlighter": "^16.1.1",
30
32
  "remark-gfm": "^4.0.1",
31
- "@object-ui/components": "3.1.5",
32
- "@object-ui/core": "3.1.5",
33
- "@object-ui/react": "3.1.5",
34
- "@object-ui/types": "3.1.5"
33
+ "@object-ui/components": "3.3.0",
34
+ "@object-ui/core": "3.3.0",
35
+ "@object-ui/react": "3.3.0",
36
+ "@object-ui/types": "3.3.0"
35
37
  },
36
38
  "peerDependencies": {
37
39
  "react": "^18.0.0 || ^19.0.0",
@@ -42,8 +44,8 @@
42
44
  "@types/react-dom": "19.2.3",
43
45
  "@types/react-syntax-highlighter": "^15.5.13",
44
46
  "@vitejs/plugin-react": "^6.0.1",
45
- "typescript": "^5.9.3",
46
- "vite": "^8.0.1",
47
+ "typescript": "^6.0.2",
48
+ "vite": "^8.0.8",
47
49
  "vite-plugin-dts": "^4.5.4"
48
50
  },
49
51
  "scripts": {
@@ -9,7 +9,7 @@
9
9
  import * as React from "react"
10
10
  import { cn } from "@object-ui/components"
11
11
  import { Button, Input, ScrollArea, Avatar, AvatarFallback, AvatarImage } from "@object-ui/components"
12
- import { Send, Trash2, Paperclip, X } from "lucide-react"
12
+ import { Send, Trash2, Paperclip, X, Square, RefreshCw, AlertCircle } from "lucide-react"
13
13
  import ReactMarkdown from "react-markdown"
14
14
  import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"
15
15
  import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism"
@@ -30,7 +30,15 @@ export interface ChatbotEnhancedProps extends React.HTMLAttributes<HTMLDivElemen
30
30
  placeholder?: string
31
31
  onSendMessage?: (message: string, files?: File[]) => void
32
32
  onClear?: () => void
33
+ /** Stop the current streaming response (API mode only) */
34
+ onStop?: () => void
35
+ /** Reload / retry the last assistant message (API mode only) */
36
+ onReload?: () => void
33
37
  disabled?: boolean
38
+ /** Whether the assistant is currently generating a response */
39
+ isLoading?: boolean
40
+ /** Current streaming/API error */
41
+ error?: Error
34
42
  showTimestamp?: boolean
35
43
  userAvatarUrl?: string
36
44
  userAvatarFallback?: string
@@ -115,7 +123,11 @@ const ChatbotEnhanced = React.forwardRef<HTMLDivElement, ChatbotEnhancedProps>(
115
123
  placeholder = "Type your message...",
116
124
  onSendMessage,
117
125
  onClear,
126
+ onStop,
127
+ onReload,
118
128
  disabled = false,
129
+ isLoading = false,
130
+ error,
119
131
  showTimestamp = false,
120
132
  userAvatarUrl,
121
133
  userAvatarFallback = "You",
@@ -155,6 +167,9 @@ const ChatbotEnhanced = React.forwardRef<HTMLDivElement, ChatbotEnhancedProps>(
155
167
  }
156
168
  }
157
169
 
170
+ const isInputDisabled = disabled || isLoading
171
+ const isSendDisabled = isInputDisabled || (!inputValue.trim() && selectedFiles.length === 0)
172
+
158
173
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
159
174
  if (e.key === "Enter" && !e.shiftKey) {
160
175
  e.preventDefault()
@@ -322,6 +337,42 @@ const ChatbotEnhanced = React.forwardRef<HTMLDivElement, ChatbotEnhancedProps>(
322
337
  </div>
323
338
  )}
324
339
 
340
+ {/* Error display */}
341
+ {error && (
342
+ <div className="flex items-center gap-2 px-4 py-2 border-t bg-destructive/10 text-destructive text-sm" role="alert">
343
+ <AlertCircle className="h-4 w-4 flex-shrink-0" />
344
+ <span className="flex-1 truncate">{error.message || 'An error occurred'}</span>
345
+ {onReload && (
346
+ <Button
347
+ variant="ghost"
348
+ size="sm"
349
+ onClick={onReload}
350
+ className="h-7 text-xs"
351
+ aria-label="Retry"
352
+ >
353
+ <RefreshCw className="h-3 w-3 mr-1" />
354
+ Retry
355
+ </Button>
356
+ )}
357
+ </div>
358
+ )}
359
+
360
+ {/* Streaming controls */}
361
+ {isLoading && onStop && (
362
+ <div className="flex items-center justify-center px-4 py-2 border-t">
363
+ <Button
364
+ variant="outline"
365
+ size="sm"
366
+ onClick={onStop}
367
+ className="h-8 text-xs"
368
+ aria-label="Stop generating"
369
+ >
370
+ <Square className="h-3 w-3 mr-1" />
371
+ Stop generating
372
+ </Button>
373
+ </div>
374
+ )}
375
+
325
376
  {/* Input area */}
326
377
  <div className="flex items-center gap-2 p-4 border-t">
327
378
  {enableFileUpload && (
@@ -338,7 +389,7 @@ const ChatbotEnhanced = React.forwardRef<HTMLDivElement, ChatbotEnhancedProps>(
338
389
  variant="ghost"
339
390
  size="icon"
340
391
  onClick={() => fileInputRef.current?.click()}
341
- disabled={disabled}
392
+ disabled={isInputDisabled}
342
393
  aria-label="Attach file"
343
394
  >
344
395
  <Paperclip className="h-4 w-4" />
@@ -352,13 +403,13 @@ const ChatbotEnhanced = React.forwardRef<HTMLDivElement, ChatbotEnhancedProps>(
352
403
  onChange={(e) => setInputValue(e.target.value)}
353
404
  onKeyDown={handleKeyDown}
354
405
  placeholder={placeholder}
355
- disabled={disabled}
406
+ disabled={isInputDisabled}
356
407
  className="flex-1"
357
408
  />
358
409
 
359
410
  <Button
360
411
  onClick={handleSend}
361
- disabled={disabled || (!inputValue.trim() && selectedFiles.length === 0)}
412
+ disabled={isSendDisabled}
362
413
  size="icon"
363
414
  aria-label="Send message"
364
415
  >
@@ -0,0 +1,89 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+
9
+ import * as React from "react"
10
+ import * as ReactDOM from "react-dom"
11
+ import type { FloatingChatbotConfig } from "@object-ui/types"
12
+ import { FloatingChatbotProvider } from "./FloatingChatbotProvider"
13
+ import { FloatingChatbotTrigger } from "./FloatingChatbotTrigger"
14
+ import { FloatingChatbotPanel } from "./FloatingChatbotPanel"
15
+ import { ChatbotEnhanced, type ChatbotEnhancedProps } from "./ChatbotEnhanced"
16
+
17
+ export interface FloatingChatbotProps extends ChatbotEnhancedProps {
18
+ /** Floating configuration */
19
+ floatingConfig?: FloatingChatbotConfig
20
+ }
21
+
22
+ /**
23
+ * Floating Chatbot — Airtable-style FAB widget.
24
+ *
25
+ * Wraps `ChatbotEnhanced` in a floating panel that can be toggled
26
+ * via a fixed FAB trigger button. Uses React portal to avoid
27
+ * DOM/z-index conflicts.
28
+ */
29
+ export function FloatingChatbot({
30
+ floatingConfig,
31
+ ...chatbotProps
32
+ }: FloatingChatbotProps) {
33
+ const {
34
+ position = "bottom-right",
35
+ defaultOpen = false,
36
+ panelWidth = 400,
37
+ panelHeight = 520,
38
+ title = "Chat",
39
+ triggerSize = 56,
40
+ } = floatingConfig ?? {}
41
+
42
+ const [portalContainer, setPortalContainer] = React.useState<HTMLElement | null>(null)
43
+
44
+ React.useEffect(() => {
45
+ // Create a portal root so the floating UI sits outside the normal DOM tree
46
+ let container = document.getElementById("floating-chatbot-portal")
47
+ if (!container) {
48
+ container = document.createElement("div")
49
+ container.id = "floating-chatbot-portal"
50
+ document.body.appendChild(container)
51
+ }
52
+ setPortalContainer(container)
53
+
54
+ return () => {
55
+ // Only remove if we created it and it's still in the DOM
56
+ if (container && container.parentNode && !container.hasChildNodes()) {
57
+ container.parentNode.removeChild(container)
58
+ }
59
+ }
60
+ }, [])
61
+
62
+ const content = (
63
+ <FloatingChatbotProvider defaultOpen={defaultOpen}>
64
+ <FloatingChatbotTrigger
65
+ position={position}
66
+ size={triggerSize}
67
+ />
68
+ <FloatingChatbotPanel
69
+ title={title}
70
+ position={position}
71
+ width={panelWidth}
72
+ height={panelHeight}
73
+ >
74
+ <ChatbotEnhanced
75
+ {...chatbotProps}
76
+ maxHeight="100%"
77
+ className="h-full border-0 rounded-none"
78
+ />
79
+ </FloatingChatbotPanel>
80
+ </FloatingChatbotProvider>
81
+ )
82
+
83
+ // Use portal rendering when in browser, fallback to inline for SSR / tests
84
+ if (portalContainer) {
85
+ return ReactDOM.createPortal(content, portalContainer)
86
+ }
87
+
88
+ return content
89
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+
9
+ import * as React from "react"
10
+ import { cn } from "@object-ui/components"
11
+ import { Button } from "@object-ui/components"
12
+ import { X, Maximize2, Minimize2 } from "lucide-react"
13
+ import { useFloatingChatbot } from "./FloatingChatbotProvider"
14
+
15
+ export interface FloatingChatbotPanelProps {
16
+ /** Panel title */
17
+ title?: string
18
+ /** Position of the panel (anchored to FAB corner) */
19
+ position?: "bottom-right" | "bottom-left"
20
+ /** Panel width in pixels (ignored in fullscreen) */
21
+ width?: number
22
+ /** Panel height in pixels (ignored in fullscreen) */
23
+ height?: number
24
+ /** Content to render inside the panel body */
25
+ children: React.ReactNode
26
+ /** Custom className for the panel container */
27
+ className?: string
28
+ }
29
+
30
+ /**
31
+ * Floating panel overlay for the chatbot.
32
+ * Renders above all content, anchored to the configured position.
33
+ * Supports fullscreen toggle and close.
34
+ */
35
+ export function FloatingChatbotPanel({
36
+ title = "Chat",
37
+ position = "bottom-right",
38
+ width = 400,
39
+ height = 520,
40
+ children,
41
+ className,
42
+ }: FloatingChatbotPanelProps) {
43
+ const { isOpen, isFullscreen, close, toggleFullscreen } = useFloatingChatbot()
44
+
45
+ if (!isOpen) return null
46
+
47
+ const panelStyle: React.CSSProperties = isFullscreen
48
+ ? { inset: 0, width: "100vw", height: "100vh" }
49
+ : { width, height, maxHeight: "calc(100vh - 100px)" }
50
+
51
+ return (
52
+ <div
53
+ className={cn(
54
+ "fixed z-50 flex flex-col rounded-lg border bg-background shadow-xl overflow-hidden transition-all",
55
+ isFullscreen
56
+ ? "inset-0 rounded-none"
57
+ : position === "bottom-right"
58
+ ? "right-6 bottom-20"
59
+ : "left-6 bottom-20",
60
+ className
61
+ )}
62
+ style={panelStyle}
63
+ role="dialog"
64
+ aria-label={title}
65
+ data-testid="floating-chatbot-panel"
66
+ >
67
+ {/* Header */}
68
+ <div className="flex items-center justify-between px-4 py-2 border-b bg-muted/40">
69
+ <span className="text-sm font-medium truncate">{title}</span>
70
+ <div className="flex items-center gap-1">
71
+ <Button
72
+ variant="ghost"
73
+ size="icon"
74
+ className="h-7 w-7"
75
+ onClick={toggleFullscreen}
76
+ aria-label={isFullscreen ? "Exit fullscreen" : "Fullscreen"}
77
+ data-testid="floating-chatbot-fullscreen"
78
+ >
79
+ {isFullscreen ? (
80
+ <Minimize2 className="h-4 w-4" />
81
+ ) : (
82
+ <Maximize2 className="h-4 w-4" />
83
+ )}
84
+ </Button>
85
+ <Button
86
+ variant="ghost"
87
+ size="icon"
88
+ className="h-7 w-7"
89
+ onClick={close}
90
+ aria-label="Close chat"
91
+ data-testid="floating-chatbot-close"
92
+ >
93
+ <X className="h-4 w-4" />
94
+ </Button>
95
+ </div>
96
+ </div>
97
+
98
+ {/* Body */}
99
+ <div className="flex-1 overflow-hidden">{children}</div>
100
+ </div>
101
+ )
102
+ }