@blumessage/react-chat 1.3.0 → 1.4.1

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/README.md CHANGED
@@ -15,10 +15,38 @@ A React TypeScript chat widget component with floating button, theming, and Blum
15
15
 
16
16
  ## Installation
17
17
 
18
+ ### NPM Package (Recommended)
19
+
18
20
  ```bash
19
21
  npm i @blumessage/react-chat
20
22
  ```
21
23
 
24
+ ### Browser Versions
25
+
26
+ #### Option 1: Standalone (Includes React)
27
+
28
+ For the simplest setup with everything included:
29
+
30
+ ```html
31
+ <!-- Load the Blumessage Chat component (includes React) -->
32
+ <script src="path/to/index.js"></script>
33
+ ```
34
+
35
+ #### Option 2: External React (Smaller Bundle)
36
+
37
+ For when you already have React loaded:
38
+
39
+ ```html
40
+ <!-- Load React and ReactDOM from CDN -->
41
+ <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
42
+ <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
43
+
44
+ <!-- Load the Blumessage Chat component -->
45
+ <script src="path/to/blumessage-chat.browser.js"></script>
46
+ ```
47
+
48
+ See [BROWSER_USAGE.md](./BROWSER_USAGE.md) for complete browser usage documentation.
49
+
22
50
  ## Quick Start
23
51
 
24
52
  ### Floating Chat Widget (Default)
@@ -86,6 +114,8 @@ function App() {
86
114
  | `showTimestamps` | `boolean` | `false` | Display timestamps: today="2:00 PM", older="17 July, 1:00 PM" |
87
115
  | `typingText` | `string` | `"Agent is typing..."` | Custom text shown while waiting for assistant response |
88
116
  | `emptyStateText` | `string` | `"Start a conversation!"` | Text shown when no messages are present |
117
+ | `markdown` | `boolean` | `true` | Enable markdown rendering for messages |
118
+ | `disableAutoScroll` | `boolean` | `false` | Disable automatic scrolling to bottom when new messages arrive |
89
119
  | **Event Callbacks** |
90
120
  | `onUserMessage` | `(message: Message) => void` | - | Called when user sends message |
91
121
  | `onAssistantMessage` | `(message: Message) => void` | - | Called when assistant responds |
@@ -206,6 +236,17 @@ const initialMessages = [
206
236
  />
207
237
  ```
208
238
 
239
+ ### Disable Auto-Scroll
240
+
241
+ ```tsx
242
+ <BlumessageChat
243
+ apiKey="your-api-key"
244
+ disableAutoScroll={true} // Prevents automatic scrolling to bottom
245
+ // Useful when you want users to maintain their scroll position
246
+ // or when implementing custom scroll behavior
247
+ />
248
+ ```
249
+
209
250
  ## Icon Options
210
251
 
211
252
  The `icon` prop accepts **any lucide-react icon name** with flexible naming patterns. The component intelligently matches your input to the appropriate lucide-react icon:
@@ -431,6 +472,32 @@ interface BlumessageChatRef {
431
472
  - React 18+
432
473
  - TypeScript 4.5+
433
474
 
475
+ ## Building
476
+
477
+ ### Standard Build (ES Modules)
478
+
479
+ ```bash
480
+ npm run build
481
+ ```
482
+
483
+ ### Browser Versions
484
+
485
+ #### Standalone (Includes React)
486
+
487
+ ```bash
488
+ npm run build:commonjs
489
+ ```
490
+
491
+ This creates `dist/index.js` which includes React and can be used directly in browsers.
492
+
493
+ #### External React (Smaller Bundle)
494
+
495
+ ```bash
496
+ npm run build:browser
497
+ ```
498
+
499
+ This creates `dist/blumessage-chat.browser.js` which requires React to be loaded separately.
500
+
434
501
  ## License
435
502
 
436
503
  UNLICENSED - For use only by customers with an active Blumessage subscription.
@@ -120,24 +120,24 @@ var useIsMobile = function () {
120
120
  return isMobile;
121
121
  };
122
122
  export var BlumessageChat = forwardRef(function (_a, ref) {
123
- var apiKey = _a.apiKey, _b = _a.placeholder, placeholder = _b === void 0 ? "Type your message..." : _b, _c = _a.theme, theme = _c === void 0 ? 'light' : _c, width = _a.width, height = _a.height, _d = _a.size, size = _d === void 0 ? 'medium' : _d, _e = _a.name, name = _e === void 0 ? "Blumessage AI" : _e, _f = _a.subtitle, subtitle = _f === void 0 ? "Online • Instant responses" : _f, _g = _a.initialMessages, initialMessages = _g === void 0 ? [] : _g, onUserMessage = _a.onUserMessage, onAssistantMessage = _a.onAssistantMessage, initialToken = _a.token, onTokenChange = _a.onTokenChange, onChatWidgetOpen = _a.onChatWidgetOpen, onChatWidgetClosed = _a.onChatWidgetClosed, onError = _a.onError, _h = _a.persistent, persistent = _h === void 0 ? false : _h, _j = _a.showTimestamps, showTimestamps = _j === void 0 ? false : _j, _k = _a.typingText, typingText = _k === void 0 ? "Agent is typing..." : _k, _l = _a.emptyStateText, emptyStateText = _l === void 0 ? "Start a conversation!" : _l, _m = _a.markdown, markdown = _m === void 0 ? true : _m,
123
+ var apiKey = _a.apiKey, _b = _a.placeholder, placeholder = _b === void 0 ? "Type your message..." : _b, _c = _a.theme, theme = _c === void 0 ? 'light' : _c, width = _a.width, height = _a.height, _d = _a.size, size = _d === void 0 ? 'medium' : _d, _e = _a.name, name = _e === void 0 ? "Blumessage AI" : _e, _f = _a.subtitle, subtitle = _f === void 0 ? "Online • Instant responses" : _f, _g = _a.initialMessages, initialMessages = _g === void 0 ? [] : _g, onUserMessage = _a.onUserMessage, onAssistantMessage = _a.onAssistantMessage, initialToken = _a.token, onTokenChange = _a.onTokenChange, onChatWidgetOpen = _a.onChatWidgetOpen, onChatWidgetClosed = _a.onChatWidgetClosed, onError = _a.onError, _h = _a.persistent, persistent = _h === void 0 ? false : _h, _j = _a.showTimestamps, showTimestamps = _j === void 0 ? false : _j, _k = _a.typingText, typingText = _k === void 0 ? "Agent is typing..." : _k, _l = _a.emptyStateText, emptyStateText = _l === void 0 ? "Start a conversation!" : _l, _m = _a.markdown, markdown = _m === void 0 ? true : _m, _o = _a.disableAutoScroll, disableAutoScroll = _o === void 0 ? false : _o,
124
124
  // Floating button props
125
- _o = _a.floating,
125
+ _p = _a.floating,
126
126
  // Floating button props
127
- floating = _o === void 0 ? true : _o, _p = _a.buttonText, buttonText = _p === void 0 ? "Chat with us" : _p, _q = _a.buttonPosition, buttonPosition = _q === void 0 ? 'bottom-right' : _q, buttonStyle = _a.buttonStyle, _r = _a.defaultOpen, defaultOpen = _r === void 0 ? false : _r, _s = _a.maximizeToggleButton, maximizeToggleButton = _s === void 0 ? true : _s, _t = _a.fullScreen, fullScreen = _t === void 0 ? false : _t, _u = _a.icon, icon = _u === void 0 ? 'message-circle' : _u,
127
+ floating = _p === void 0 ? true : _p, _q = _a.buttonText, buttonText = _q === void 0 ? "Chat with us" : _q, _r = _a.buttonPosition, buttonPosition = _r === void 0 ? 'bottom-right' : _r, buttonStyle = _a.buttonStyle, _s = _a.defaultOpen, defaultOpen = _s === void 0 ? false : _s, _t = _a.maximizeToggleButton, maximizeToggleButton = _t === void 0 ? true : _t, _u = _a.fullScreen, fullScreen = _u === void 0 ? false : _u, _v = _a.icon, icon = _v === void 0 ? 'message-circle' : _v,
128
128
  // Styling props
129
- _v = _a.primaryColor,
129
+ _w = _a.primaryColor,
130
130
  // Styling props
131
- primaryColor = _v === void 0 ? "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" : _v;
132
- var _w = useState(false), isInitialized = _w[0], setIsInitialized = _w[1];
133
- var _x = useState(null), error = _x[0], setError = _x[1];
134
- var _y = useState(initialMessages), messages = _y[0], setMessages = _y[1];
135
- var _z = useState(''), inputValue = _z[0], setInputValue = _z[1];
136
- var _0 = useState(initialToken || getStoredConversationToken(persistent)), token = _0[0], setToken = _0[1];
137
- var _1 = useState(defaultOpen), isOpen = _1[0], setIsOpen = _1[1];
138
- var _2 = useState(false), isAnimating = _2[0], setIsAnimating = _2[1];
139
- var _3 = useState(false), isLoading = _3[0], setIsLoading = _3[1];
140
- var _4 = useState(false), isMaximized = _4[0], setIsMaximized = _4[1];
131
+ primaryColor = _w === void 0 ? "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" : _w;
132
+ var _x = useState(false), isInitialized = _x[0], setIsInitialized = _x[1];
133
+ var _y = useState(null), error = _y[0], setError = _y[1];
134
+ var _z = useState(initialMessages), messages = _z[0], setMessages = _z[1];
135
+ var _0 = useState(''), inputValue = _0[0], setInputValue = _0[1];
136
+ var _1 = useState(initialToken || getStoredConversationToken(persistent)), token = _1[0], setToken = _1[1];
137
+ var _2 = useState(defaultOpen), isOpen = _2[0], setIsOpen = _2[1];
138
+ var _3 = useState(false), isAnimating = _3[0], setIsAnimating = _3[1];
139
+ var _4 = useState(false), isLoading = _4[0], setIsLoading = _4[1];
140
+ var _5 = useState(false), isMaximized = _5[0], setIsMaximized = _5[1];
141
141
  var messagesEndRef = useRef(null);
142
142
  var isInitialLoad = useRef(true);
143
143
  // Mobile detection
@@ -207,7 +207,7 @@ export var BlumessageChat = forwardRef(function (_a, ref) {
207
207
  }
208
208
  return dimensions;
209
209
  };
210
- var _5 = getDimensions(), actualWidth = _5.width, actualHeight = _5.height;
210
+ var _6 = getDimensions(), actualWidth = _6.width, actualHeight = _6.height;
211
211
  // Function to clear conversation and start fresh
212
212
  var clearConversation = function () {
213
213
  updateConversationToken(null);
@@ -480,18 +480,20 @@ export var BlumessageChat = forwardRef(function (_a, ref) {
480
480
  // Auto-scroll to bottom when messages change
481
481
  useEffect(function () {
482
482
  var _a;
483
- (_a = messagesEndRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: 'smooth' });
483
+ if (!disableAutoScroll) {
484
+ (_a = messagesEndRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: 'smooth' });
485
+ }
484
486
  }, [messages]);
485
487
  // Auto-scroll to bottom when chat widget opens
486
488
  useEffect(function () {
487
- if (isOpen && floating) {
489
+ if (isOpen && floating && !disableAutoScroll) {
488
490
  // Add a small delay to ensure the DOM is updated after the animation starts
489
491
  setTimeout(function () {
490
492
  var _a;
491
493
  (_a = messagesEndRef.current) === null || _a === void 0 ? void 0 : _a.scrollIntoView({ behavior: 'smooth' });
492
494
  }, 50);
493
495
  }
494
- }, [isOpen, floating]);
496
+ }, [isOpen, floating, disableAutoScroll]);
495
497
  // Handle opening the chat with animation
496
498
  var handleOpenChat = function () {
497
499
  if (!isOpen && !isAnimating) {