posthog-js 1.347.2 → 1.348.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.
- package/dist/array.full.es5.js +1 -1
- package/dist/array.full.js +1 -1
- package/dist/array.full.no-external.js +1 -1
- package/dist/array.js +1 -1
- package/dist/array.no-external.js +1 -1
- package/dist/conversations.js +1 -1
- package/dist/conversations.js.map +1 -1
- package/dist/customizations.full.js +1 -1
- package/dist/lazy-recorder.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.d.ts +43 -1
- package/dist/module.full.d.ts +43 -1
- package/dist/module.full.js +1 -1
- package/dist/module.full.js.map +1 -1
- package/dist/module.full.no-external.d.ts +43 -1
- package/dist/module.full.no-external.js +1 -1
- package/dist/module.full.no-external.js.map +1 -1
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/module.no-external.d.ts +43 -1
- package/dist/module.no-external.js +1 -1
- package/dist/module.no-external.js.map +1 -1
- package/dist/posthog-recorder.js +1 -1
- package/dist/product-tours-preview.d.ts +2 -0
- package/dist/product-tours-preview.js +1 -1
- package/dist/product-tours-preview.js.map +1 -1
- package/dist/product-tours.js +1 -1
- package/dist/product-tours.js.map +1 -1
- package/dist/src/extensions/conversations/external/components/ConversationsWidget.d.ts +43 -2
- package/dist/src/extensions/conversations/external/components/TicketListItem.d.ts +13 -0
- package/dist/src/extensions/conversations/external/components/TicketListView.d.ts +15 -0
- package/dist/src/extensions/conversations/external/components/styles.d.ts +184 -0
- package/dist/src/extensions/conversations/external/components/utils.d.ts +8 -0
- package/dist/src/extensions/conversations/external/index.d.ts +39 -1
- package/dist/src/extensions/product-tours/product-tours.d.ts +2 -0
- package/dist/src/posthog-product-tours-types.d.ts +42 -0
- package/dist/surveys-preview.d.ts +2 -0
- package/lib/package.json +1 -1
- package/lib/src/extensions/conversations/external/components/ConversationsWidget.d.ts +43 -2
- package/lib/src/extensions/conversations/external/components/ConversationsWidget.js +96 -28
- package/lib/src/extensions/conversations/external/components/ConversationsWidget.js.map +1 -1
- package/lib/src/extensions/conversations/external/components/TicketListItem.d.ts +13 -0
- package/lib/src/extensions/conversations/external/components/TicketListItem.js +47 -0
- package/lib/src/extensions/conversations/external/components/TicketListItem.js.map +1 -0
- package/lib/src/extensions/conversations/external/components/TicketListView.d.ts +15 -0
- package/lib/src/extensions/conversations/external/components/TicketListView.js +75 -0
- package/lib/src/extensions/conversations/external/components/TicketListView.js.map +1 -0
- package/lib/src/extensions/conversations/external/components/styles.d.ts +184 -0
- package/lib/src/extensions/conversations/external/components/styles.js +189 -0
- package/lib/src/extensions/conversations/external/components/styles.js.map +1 -1
- package/lib/src/extensions/conversations/external/components/utils.d.ts +8 -0
- package/lib/src/extensions/conversations/external/components/utils.js +49 -0
- package/lib/src/extensions/conversations/external/components/utils.js.map +1 -0
- package/lib/src/extensions/conversations/external/index.d.ts +39 -1
- package/lib/src/extensions/conversations/external/index.js +253 -31
- package/lib/src/extensions/conversations/external/index.js.map +1 -1
- package/lib/src/extensions/product-tours/components/ProductTourSurveyStepInner.js +1 -1
- package/lib/src/extensions/product-tours/components/ProductTourSurveyStepInner.js.map +1 -1
- package/lib/src/extensions/product-tours/product-tours.d.ts +2 -0
- package/lib/src/extensions/product-tours/product-tours.js +78 -71
- package/lib/src/extensions/product-tours/product-tours.js.map +1 -1
- package/lib/src/posthog-product-tours-types.d.ts +42 -0
- package/lib/src/posthog-product-tours-types.js +43 -1
- package/lib/src/posthog-product-tours-types.js.map +1 -1
- package/lib/src/utils/product-tour-event-receiver.js +2 -1
- package/lib/src/utils/product-tour-event-receiver.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/react/dist/esm/index.js +25 -1
- package/react/dist/esm/index.js.map +1 -1
- package/react/dist/types/index.d.ts +4 -2
- package/react/dist/umd/index.js +25 -0
- package/react/dist/umd/index.js.map +1 -1
|
@@ -97,6 +97,8 @@ var OpenChatButton_1 = require("./OpenChatButton");
|
|
|
97
97
|
var SendMessageButton_1 = require("./SendMessageButton");
|
|
98
98
|
var CloseChatButton_1 = require("./CloseChatButton");
|
|
99
99
|
var RichContent_1 = require("./RichContent");
|
|
100
|
+
var TicketListView_1 = require("./TicketListView");
|
|
101
|
+
var utils_1 = require("./utils");
|
|
100
102
|
var logger = (0, logger_1.createLogger)('[ConversationsWidget]');
|
|
101
103
|
var ConversationsWidget = /** @class */ (function (_super) {
|
|
102
104
|
__extends(ConversationsWidget, _super);
|
|
@@ -112,6 +114,21 @@ var ConversationsWidget = /** @class */ (function (_super) {
|
|
|
112
114
|
_this._handleClose = function () {
|
|
113
115
|
_this.setState({ state: 'closed' });
|
|
114
116
|
};
|
|
117
|
+
_this._handleSelectTicket = function (ticketId) {
|
|
118
|
+
if (_this.props.onSelectTicket) {
|
|
119
|
+
_this.props.onSelectTicket(ticketId);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
_this._handleNewConversation = function () {
|
|
123
|
+
if (_this.props.onNewConversation) {
|
|
124
|
+
_this.props.onNewConversation();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
_this._handleBackToTickets = function () {
|
|
128
|
+
if (_this.props.onBackToTickets) {
|
|
129
|
+
_this.props.onBackToTickets();
|
|
130
|
+
}
|
|
131
|
+
};
|
|
115
132
|
_this._handleInputChange = function (e) {
|
|
116
133
|
var target = e.target;
|
|
117
134
|
_this.setState({ inputValue: target.value });
|
|
@@ -217,7 +234,10 @@ var ConversationsWidget = /** @class */ (function (_super) {
|
|
|
217
234
|
var needsIdentification = _this._needsIdentification(props.config, userTraits, props.isUserIdentified);
|
|
218
235
|
_this.state = {
|
|
219
236
|
state: props.initialState || 'closed',
|
|
237
|
+
view: props.initialView || 'messages',
|
|
220
238
|
messages: [],
|
|
239
|
+
tickets: props.initialTickets || [],
|
|
240
|
+
ticketsLoading: false,
|
|
221
241
|
inputValue: '',
|
|
222
242
|
isLoading: false,
|
|
223
243
|
error: null,
|
|
@@ -227,6 +247,7 @@ var ConversationsWidget = /** @class */ (function (_super) {
|
|
|
227
247
|
formEmailError: null,
|
|
228
248
|
userTraits: userTraits,
|
|
229
249
|
unreadCount: 0,
|
|
250
|
+
hasMultipleTickets: props.hasMultipleTickets || false,
|
|
230
251
|
};
|
|
231
252
|
return _this;
|
|
232
253
|
}
|
|
@@ -250,8 +271,8 @@ var ConversationsWidget = /** @class */ (function (_super) {
|
|
|
250
271
|
return true;
|
|
251
272
|
};
|
|
252
273
|
ConversationsWidget.prototype.componentDidMount = function () {
|
|
253
|
-
// Add greeting message if no messages exist
|
|
254
|
-
if (this.state.messages.length === 0 && this.props.config.greetingText) {
|
|
274
|
+
// Add greeting message if no messages exist and we're in message view
|
|
275
|
+
if (this.state.view === 'messages' && this.state.messages.length === 0 && this.props.config.greetingText) {
|
|
255
276
|
this._addGreetingMessage();
|
|
256
277
|
}
|
|
257
278
|
};
|
|
@@ -296,24 +317,6 @@ var ConversationsWidget = /** @class */ (function (_super) {
|
|
|
296
317
|
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
297
318
|
return emailRegex.test(email);
|
|
298
319
|
};
|
|
299
|
-
ConversationsWidget.prototype._formatTime = function (isoString) {
|
|
300
|
-
var date = new Date(isoString);
|
|
301
|
-
var now = new Date();
|
|
302
|
-
var diffMs = now.getTime() - date.getTime();
|
|
303
|
-
var diffMins = Math.floor(diffMs / 60000);
|
|
304
|
-
if (diffMins < 1) {
|
|
305
|
-
return 'Just now';
|
|
306
|
-
}
|
|
307
|
-
else if (diffMins < 60) {
|
|
308
|
-
return "".concat(diffMins, "m ago");
|
|
309
|
-
}
|
|
310
|
-
else if (diffMins < 1440) {
|
|
311
|
-
return "".concat(Math.floor(diffMins / 60), "h ago");
|
|
312
|
-
}
|
|
313
|
-
else {
|
|
314
|
-
return date.toLocaleDateString();
|
|
315
|
-
}
|
|
316
|
-
};
|
|
317
320
|
/**
|
|
318
321
|
* Public method to add messages from outside
|
|
319
322
|
*/
|
|
@@ -369,6 +372,50 @@ var ConversationsWidget = /** @class */ (function (_super) {
|
|
|
369
372
|
ConversationsWidget.prototype.setUnreadCount = function (count) {
|
|
370
373
|
this.setState({ unreadCount: count });
|
|
371
374
|
};
|
|
375
|
+
/**
|
|
376
|
+
* Update the tickets list (called by manager during polling)
|
|
377
|
+
*/
|
|
378
|
+
ConversationsWidget.prototype.updateTickets = function (tickets) {
|
|
379
|
+
this.setState({
|
|
380
|
+
tickets: tickets,
|
|
381
|
+
ticketsLoading: false,
|
|
382
|
+
hasMultipleTickets: tickets.length > 1,
|
|
383
|
+
});
|
|
384
|
+
};
|
|
385
|
+
/**
|
|
386
|
+
* Set the current view (tickets list or messages)
|
|
387
|
+
*/
|
|
388
|
+
ConversationsWidget.prototype.setView = function (view) {
|
|
389
|
+
this.setState({ view: view });
|
|
390
|
+
if (this.props.onViewChange) {
|
|
391
|
+
this.props.onViewChange(view);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
/**
|
|
395
|
+
* Get the current view
|
|
396
|
+
*/
|
|
397
|
+
ConversationsWidget.prototype.getView = function () {
|
|
398
|
+
return this.state.view;
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* Set tickets loading state
|
|
402
|
+
*/
|
|
403
|
+
ConversationsWidget.prototype.setTicketsLoading = function (loading) {
|
|
404
|
+
this.setState({ ticketsLoading: loading });
|
|
405
|
+
};
|
|
406
|
+
/**
|
|
407
|
+
* Clear messages (used when switching tickets or starting new conversation)
|
|
408
|
+
* @param addGreeting - If true, adds the greeting message after clearing
|
|
409
|
+
*/
|
|
410
|
+
ConversationsWidget.prototype.clearMessages = function (addGreeting) {
|
|
411
|
+
var _this = this;
|
|
412
|
+
if (addGreeting === void 0) { addGreeting = false; }
|
|
413
|
+
this.setState({ messages: [] }, function () {
|
|
414
|
+
if (addGreeting && _this.props.config.greetingText) {
|
|
415
|
+
_this._addGreetingMessage();
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
};
|
|
372
419
|
ConversationsWidget.prototype._renderIdentificationForm = function (styles) {
|
|
373
420
|
var config = this.props.config;
|
|
374
421
|
var _a = this.state, formName = _a.formName, formEmail = _a.formEmail, formEmailError = _a.formEmailError;
|
|
@@ -385,12 +432,27 @@ var ConversationsWidget = /** @class */ (function (_super) {
|
|
|
385
432
|
var isCustomer = message.author_type === 'customer';
|
|
386
433
|
var messageStyle = __assign(__assign({}, styles.message), (isCustomer ? styles.messageCustomer : styles.messageAgent));
|
|
387
434
|
var contentStyle = __assign(__assign({}, styles.messageContent), (isCustomer ? styles.messageContentCustomer : styles.messageContentAgent));
|
|
388
|
-
return ((0, jsx_runtime_1.jsxs)("div", { style: messageStyle, children: [!isCustomer && message.author_name && (0, jsx_runtime_1.jsx)("div", { style: styles.messageAuthor, children: message.author_name }), (0, jsx_runtime_1.jsx)("div", { style: contentStyle, children: (0, jsx_runtime_1.jsx)(RichContent_1.RichContent, { richContent: message.rich_content, content: message.content, isCustomer: isCustomer, primaryColor: primaryColor }) }), (0, jsx_runtime_1.jsx)("div", { style: styles.messageTime, children:
|
|
435
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: messageStyle, children: [!isCustomer && message.author_name && (0, jsx_runtime_1.jsx)("div", { style: styles.messageAuthor, children: message.author_name }), (0, jsx_runtime_1.jsx)("div", { style: contentStyle, children: (0, jsx_runtime_1.jsx)(RichContent_1.RichContent, { richContent: message.rich_content, content: message.content, isCustomer: isCustomer, primaryColor: primaryColor }) }), (0, jsx_runtime_1.jsx)("div", { style: styles.messageTime, children: (0, utils_1.formatRelativeTime)(message.created_at) })] }, message.id));
|
|
389
436
|
};
|
|
390
|
-
ConversationsWidget.prototype.
|
|
437
|
+
ConversationsWidget.prototype._renderBackButton = function (styles) {
|
|
438
|
+
return ((0, jsx_runtime_1.jsx)("button", { style: styles.backButton, onClick: this._handleBackToTickets, "aria-label": "Back to conversations", children: (0, jsx_runtime_1.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: (0, jsx_runtime_1.jsx)("polyline", { points: "15 18 9 12 15 6" }) }) }));
|
|
439
|
+
};
|
|
440
|
+
ConversationsWidget.prototype._renderTicketList = function (styles) {
|
|
441
|
+
var _a = this.state, tickets = _a.tickets, ticketsLoading = _a.ticketsLoading;
|
|
442
|
+
return ((0, jsx_runtime_1.jsx)(TicketListView_1.TicketListView, { tickets: tickets, isLoading: ticketsLoading, styles: styles, onSelectTicket: this._handleSelectTicket, onNewConversation: this._handleNewConversation }));
|
|
443
|
+
};
|
|
444
|
+
ConversationsWidget.prototype._renderMessages = function (styles, primaryColor, placeholderText) {
|
|
391
445
|
var _this = this;
|
|
446
|
+
var _a = this.state, messages = _a.messages, inputValue = _a.inputValue, isLoading = _a.isLoading, error = _a.error;
|
|
447
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { style: styles.messages, children: [messages.map(function (message) { return _this._renderMessage(message, styles, primaryColor); }), (0, jsx_runtime_1.jsx)("div", { ref: function (el) {
|
|
448
|
+
_this._messagesEndRef = el;
|
|
449
|
+
} })] }), error && (0, jsx_runtime_1.jsx)("div", { style: styles.error, children: error }), (0, jsx_runtime_1.jsxs)("div", { style: styles.inputContainer, children: [(0, jsx_runtime_1.jsx)("textarea", { ref: function (el) {
|
|
450
|
+
_this._inputRef = el;
|
|
451
|
+
}, style: styles.input, placeholder: placeholderText, value: inputValue, onInput: this._handleInputChange, onKeyPress: this._handleKeyPress, rows: 1, disabled: isLoading }), (0, jsx_runtime_1.jsx)(SendMessageButton_1.SendMessageButton, { primaryColor: primaryColor, inputValue: inputValue, isLoading: isLoading, handleSendMessage: this._handleSendMessage })] })] }));
|
|
452
|
+
};
|
|
453
|
+
ConversationsWidget.prototype.render = function () {
|
|
392
454
|
var config = this.props.config;
|
|
393
|
-
var _a = this.state, state = _a.state,
|
|
455
|
+
var _a = this.state, state = _a.state, view = _a.view, showIdentificationForm = _a.showIdentificationForm;
|
|
394
456
|
var primaryColor = config.color || '#5375ff';
|
|
395
457
|
var widgetPosition = config.widgetPosition || 'bottom_right';
|
|
396
458
|
var placeholderText = config.placeholderText || 'Type your message...';
|
|
@@ -401,11 +463,17 @@ var ConversationsWidget = /** @class */ (function (_super) {
|
|
|
401
463
|
}
|
|
402
464
|
// Open state
|
|
403
465
|
var windowStyle = __assign(__assign({}, styles.window), styles.windowOpen);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
466
|
+
// Determine header title based on view
|
|
467
|
+
var headerTitle = view === 'tickets' ? 'Conversations' : 'Support Chat';
|
|
468
|
+
// Show back button in message view when there are multiple tickets
|
|
469
|
+
var showBackButton = view === 'messages' && this.state.hasMultipleTickets;
|
|
470
|
+
return ((0, jsx_runtime_1.jsx)("div", { style: styles.widget, children: (0, jsx_runtime_1.jsxs)("div", { style: windowStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: styles.header, children: [(0, jsx_runtime_1.jsxs)("div", { style: showBackButton ? styles.headerWithBack : styles.headerTitle, children: [showBackButton && this._renderBackButton(styles), (0, jsx_runtime_1.jsx)("span", { style: styles.headerTitle, children: headerTitle })] }), (0, jsx_runtime_1.jsx)("div", { style: styles.headerActions, children: (0, jsx_runtime_1.jsx)(CloseChatButton_1.CloseChatButton, { primaryColor: primaryColor, handleClose: this._handleClose }) })] }), showIdentificationForm
|
|
471
|
+
? this._renderIdentificationForm(styles)
|
|
472
|
+
: view === 'tickets'
|
|
473
|
+
? // Ticket list view
|
|
474
|
+
this._renderTicketList(styles)
|
|
475
|
+
: // Messages view
|
|
476
|
+
this._renderMessages(styles, primaryColor, placeholderText)] }) }));
|
|
409
477
|
};
|
|
410
478
|
return ConversationsWidget;
|
|
411
479
|
}(preact_1.Component));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationsWidget.js","sourceRoot":"","sources":["../../../../../../src/extensions/conversations/external/components/ConversationsWidget.tsx"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { h, Component, Fragment } from 'preact'\nimport {\n ConversationsRemoteConfig,\n Message,\n ConversationsWidgetState,\n UserProvidedTraits,\n} from '../../../../posthog-conversations-types'\nimport { createLogger } from '../../../../utils/logger'\nimport { getStyles } from './styles'\nimport { OpenChatButton } from './OpenChatButton'\nimport { SendMessageButton } from './SendMessageButton'\nimport { CloseChatButton } from './CloseChatButton'\nimport { RichContent } from './RichContent'\n\nconst logger = createLogger('[ConversationsWidget]')\n\ninterface WidgetProps {\n config: ConversationsRemoteConfig\n initialState?: ConversationsWidgetState\n initialUserTraits?: UserProvidedTraits | null\n isUserIdentified?: boolean\n onSendMessage: (message: string) => Promise<void>\n onStateChange?: (state: ConversationsWidgetState) => void\n onIdentify?: (traits: UserProvidedTraits) => void\n}\n\ninterface WidgetState {\n state: ConversationsWidgetState\n messages: Message[]\n inputValue: string\n isLoading: boolean\n error: string | null\n showIdentificationForm: boolean\n formName: string\n formEmail: string\n formEmailError: string | null\n userTraits: UserProvidedTraits | null\n unreadCount: number\n}\n\nexport class ConversationsWidget extends Component<WidgetProps, WidgetState> {\n private _messagesEndRef: HTMLDivElement | null = null\n private _inputRef: HTMLTextAreaElement | null = null\n\n constructor(props: WidgetProps) {\n super(props)\n\n // Determine if we need to show the identification form\n const userTraits = props.initialUserTraits || null\n const needsIdentification = this._needsIdentification(props.config, userTraits, props.isUserIdentified)\n\n this.state = {\n state: props.initialState || 'closed',\n messages: [],\n inputValue: '',\n isLoading: false,\n error: null,\n showIdentificationForm: needsIdentification,\n formName: userTraits?.name || '',\n formEmail: userTraits?.email || '',\n formEmailError: null,\n userTraits,\n unreadCount: 0,\n }\n }\n\n /**\n * Check if we need to show the identification form\n */\n private _needsIdentification(\n config: ConversationsRemoteConfig,\n traits: UserProvidedTraits | null,\n isUserIdentified?: boolean\n ): boolean {\n // If user is already identified via PostHog, no form needed\n // They've called posthog.identify() so we have their identity\n if (isUserIdentified) {\n return false\n }\n\n // If requireEmail is not set, no identification needed\n if (!config.requireEmail) {\n return false\n }\n\n // If we already have an email, no form needed\n if (traits?.email) {\n return false\n }\n\n return true\n }\n\n componentDidMount() {\n // Add greeting message if no messages exist\n if (this.state.messages.length === 0 && this.props.config.greetingText) {\n this._addGreetingMessage()\n }\n }\n\n componentDidUpdate(_prevProps: WidgetProps, prevState: WidgetState) {\n // Scroll to bottom when messages change\n if (this.state.messages.length !== prevState.messages.length) {\n this._scrollToBottom()\n }\n\n // Notify parent of state changes\n if (this.state.state !== prevState.state && this.props.onStateChange) {\n this.props.onStateChange(this.state.state)\n }\n\n // Focus input and scroll to bottom when opening\n if (this.state.state === 'open' && prevState.state !== 'open') {\n this._focusInput()\n this._scrollToBottom()\n }\n }\n\n private _addGreetingMessage() {\n const greetingMessage: Message = {\n id: 'greeting',\n content: this.props.config.greetingText || 'Hi! How can we help?',\n author_type: 'AI',\n author_name: 'Support',\n created_at: new Date().toISOString(),\n is_private: false,\n }\n this.setState({ messages: [greetingMessage] })\n }\n\n private _scrollToBottom() {\n if (this._messagesEndRef) {\n this._messagesEndRef.scrollIntoView({ behavior: 'smooth' })\n }\n }\n\n private _focusInput() {\n if (this._inputRef) {\n this._inputRef.focus()\n }\n }\n\n private _handleToggleOpen = () => {\n this.setState((prevState) => ({\n state: prevState.state === 'open' ? 'closed' : 'open',\n }))\n }\n\n private _handleClose = () => {\n this.setState({ state: 'closed' })\n }\n\n private _handleInputChange = (e: Event) => {\n const target = e.target as HTMLTextAreaElement\n this.setState({ inputValue: target.value })\n }\n\n private _handleKeyPress = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n this._handleSendMessage()\n }\n }\n\n // Identification form handlers\n private _handleFormNameChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n this.setState({ formName: target.value })\n }\n\n private _handleFormEmailChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n this.setState({ formEmail: target.value, formEmailError: null })\n }\n\n private _validateEmail(email: string): boolean {\n // Basic email validation\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(email)\n }\n\n private _handleFormSubmit = (e: Event) => {\n e.preventDefault()\n\n const { formEmail, formName } = this.state\n const { config, onIdentify } = this.props\n\n // Validate email if required\n if (config.requireEmail && !formEmail.trim()) {\n this.setState({ formEmailError: 'Email is required' })\n return\n }\n\n if (formEmail.trim() && !this._validateEmail(formEmail.trim())) {\n this.setState({ formEmailError: 'Please enter a valid email address' })\n return\n }\n\n // Create traits object\n const traits: UserProvidedTraits = {}\n if (formName.trim()) {\n traits.name = formName.trim()\n }\n if (formEmail.trim()) {\n traits.email = formEmail.trim()\n }\n\n // Update state and notify parent\n this.setState({\n userTraits: traits,\n showIdentificationForm: false,\n })\n\n if (onIdentify) {\n onIdentify(traits)\n }\n }\n\n private _handleSendMessage = async () => {\n const { inputValue } = this.state\n const trimmedMessage = inputValue.trim()\n\n if (!trimmedMessage) {\n return\n }\n\n // Add user message to UI immediately\n const userMessage: Message = {\n id: `temp-${Date.now()}`,\n content: trimmedMessage,\n author_type: 'customer',\n author_name: 'You',\n created_at: new Date().toISOString(),\n is_private: false,\n }\n\n this.setState({\n messages: [...this.state.messages, userMessage],\n inputValue: '',\n isLoading: true,\n error: null,\n })\n\n try {\n await this.props.onSendMessage(trimmedMessage)\n // Success - message will be updated via addMessage()\n this.setState({ isLoading: false })\n } catch (error) {\n logger.error('Failed to send message', error)\n this.setState({\n isLoading: false,\n error: error instanceof Error ? error.message : 'Failed to send message',\n })\n\n // Remove the temporary message on error\n this.setState((prevState) => ({\n messages: prevState.messages.filter((m) => m.id !== userMessage.id),\n }))\n }\n }\n\n private _formatTime(isoString: string): string {\n const date = new Date(isoString)\n const now = new Date()\n const diffMs = now.getTime() - date.getTime()\n const diffMins = Math.floor(diffMs / 60000)\n\n if (diffMins < 1) {\n return 'Just now'\n } else if (diffMins < 60) {\n return `${diffMins}m ago`\n } else if (diffMins < 1440) {\n return `${Math.floor(diffMins / 60)}h ago`\n } else {\n return date.toLocaleDateString()\n }\n }\n\n /**\n * Public method to add messages from outside\n */\n addMessages(messages: Message[]) {\n this.setState((prevState) => {\n // Filter out duplicates\n const existingIds = new Set(prevState.messages.map((m) => m.id))\n const newMessages = messages.filter((m) => !existingIds.has(m.id))\n\n if (newMessages.length > 0) {\n return {\n messages: [...prevState.messages, ...newMessages],\n }\n }\n return null\n })\n }\n\n /**\n * Public method to show the widget\n */\n show() {\n this.setState({ state: 'open' })\n }\n\n /**\n * Public method to hide the widget\n */\n hide() {\n this.setState({ state: 'closed' })\n }\n\n /**\n * Public method to close the widget completely\n */\n close() {\n this.setState({ state: 'closed' })\n }\n\n /**\n * Get user traits (either provided via form or from props)\n */\n getUserTraits(): UserProvidedTraits | null {\n return this.state.userTraits\n }\n\n /**\n * Called when user identifies via posthog.identify()\n * Hides the identification form since we now know who they are\n */\n setUserIdentified(): void {\n if (this.state.showIdentificationForm) {\n this.setState({ showIdentificationForm: false })\n }\n }\n\n /**\n * Set the unread message count (called by manager)\n */\n setUnreadCount(count: number): void {\n this.setState({ unreadCount: count })\n }\n\n private _renderIdentificationForm(styles: ReturnType<typeof getStyles>) {\n const { config } = this.props\n const { formName, formEmail, formEmailError } = this.state\n\n const title = config.identificationFormTitle || 'Before we start...'\n const description =\n config.identificationFormDescription || 'Please provide your details so we can help you better.'\n const showNameField = config.collectName !== false // Show by default unless explicitly disabled\n\n return (\n <div style={styles.identificationForm}>\n <div style={styles.formTitle}>{title}</div>\n <div style={styles.formDescription}>{description}</div>\n\n <form onSubmit={this._handleFormSubmit}>\n {showNameField && (\n <div style={styles.formField}>\n <label style={styles.formLabel}>\n Name <span style={styles.formOptional}>(optional)</span>\n </label>\n <input\n type=\"text\"\n style={styles.formInput}\n value={formName}\n onInput={this._handleFormNameChange}\n placeholder=\"Your name\"\n autoComplete=\"name\"\n />\n </div>\n )}\n\n <div style={styles.formField}>\n <label style={styles.formLabel}>\n Email {!config.requireEmail && <span style={styles.formOptional}>(optional)</span>}\n </label>\n <input\n type=\"email\"\n style={{\n ...styles.formInput,\n ...(formEmailError ? styles.formInputError : {}),\n }}\n value={formEmail}\n onInput={this._handleFormEmailChange}\n placeholder=\"you@example.com\"\n autoComplete=\"email\"\n />\n {formEmailError && <div style={styles.formError}>{formEmailError}</div>}\n </div>\n\n <button\n type=\"submit\"\n style={styles.formSubmitButton}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '0.9'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = '1'\n }}\n >\n Start Chat\n </button>\n </form>\n </div>\n )\n }\n\n private _renderMessage(message: Message, styles: ReturnType<typeof getStyles>, primaryColor: string) {\n const isCustomer = message.author_type === 'customer'\n const messageStyle = {\n ...styles.message,\n ...(isCustomer ? styles.messageCustomer : styles.messageAgent),\n }\n const contentStyle = {\n ...styles.messageContent,\n ...(isCustomer ? styles.messageContentCustomer : styles.messageContentAgent),\n }\n\n return (\n <div key={message.id} style={messageStyle}>\n {!isCustomer && message.author_name && <div style={styles.messageAuthor}>{message.author_name}</div>}\n <div style={contentStyle}>\n <RichContent\n richContent={message.rich_content}\n content={message.content}\n isCustomer={isCustomer}\n primaryColor={primaryColor}\n />\n </div>\n <div style={styles.messageTime}>{this._formatTime(message.created_at)}</div>\n </div>\n )\n }\n\n render() {\n const { config } = this.props\n const { state, messages, inputValue, isLoading, error, showIdentificationForm } = this.state\n const primaryColor = config.color || '#5375ff'\n const widgetPosition = config.widgetPosition || 'bottom_right'\n const placeholderText = config.placeholderText || 'Type your message...'\n const styles = getStyles(primaryColor, widgetPosition)\n\n // Button only (closed state)\n if (state === 'closed') {\n return (\n <OpenChatButton\n primaryColor={primaryColor}\n position={widgetPosition}\n handleToggleOpen={this._handleToggleOpen}\n unreadCount={this.state.unreadCount}\n />\n )\n }\n\n // Open state\n const windowStyle = {\n ...styles.window,\n ...styles.windowOpen,\n }\n\n return (\n <div style={styles.widget}>\n <div style={windowStyle}>\n {/* Header */}\n <div style={styles.header}>\n <div style={styles.headerTitle}>\n <span>Support Chat</span>\n </div>\n <div style={styles.headerActions}>\n <CloseChatButton primaryColor={primaryColor} handleClose={this._handleClose} />\n </div>\n </div>\n\n {/* Show identification form if needed, otherwise show chat */}\n {showIdentificationForm ? (\n this._renderIdentificationForm(styles)\n ) : (\n <>\n <div style={styles.messages}>\n {messages.map((message) => this._renderMessage(message, styles, primaryColor))}\n <div\n ref={(el) => {\n this._messagesEndRef = el\n }}\n />\n </div>\n\n {/* Error message */}\n {error && <div style={styles.error}>{error}</div>}\n\n {/* Input */}\n <div style={styles.inputContainer}>\n <textarea\n ref={(el) => {\n this._inputRef = el\n }}\n style={styles.input}\n placeholder={placeholderText}\n value={inputValue}\n onInput={this._handleInputChange}\n onKeyPress={this._handleKeyPress}\n rows={1}\n disabled={isLoading}\n />\n <SendMessageButton\n primaryColor={primaryColor}\n inputValue={inputValue}\n isLoading={isLoading}\n handleSendMessage={this._handleSendMessage}\n />\n </div>\n </>\n )}\n </div>\n </div>\n )\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ConversationsWidget.js","sourceRoot":"","sources":["../../../../../../src/extensions/conversations/external/components/ConversationsWidget.tsx"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { h, Component, Fragment } from 'preact'\nimport {\n ConversationsRemoteConfig,\n Message,\n ConversationsWidgetState,\n UserProvidedTraits,\n Ticket,\n} from '../../../../posthog-conversations-types'\nimport { createLogger } from '../../../../utils/logger'\nimport { getStyles } from './styles'\nimport { OpenChatButton } from './OpenChatButton'\nimport { SendMessageButton } from './SendMessageButton'\nimport { CloseChatButton } from './CloseChatButton'\nimport { RichContent } from './RichContent'\nimport { TicketListView } from './TicketListView'\nimport { formatRelativeTime } from './utils'\n\nconst logger = createLogger('[ConversationsWidget]')\n\n/**\n * Type for the current view in the widget\n */\nexport type WidgetView = 'tickets' | 'messages'\n\ninterface WidgetProps {\n config: ConversationsRemoteConfig\n initialState?: ConversationsWidgetState\n initialUserTraits?: UserProvidedTraits | null\n isUserIdentified?: boolean\n initialView?: WidgetView\n initialTickets?: Ticket[]\n hasMultipleTickets?: boolean\n onSendMessage: (message: string) => Promise<void>\n onStateChange?: (state: ConversationsWidgetState) => void\n onIdentify?: (traits: UserProvidedTraits) => void\n onSelectTicket?: (ticketId: string) => void\n onNewConversation?: () => void\n onBackToTickets?: () => void\n onViewChange?: (view: WidgetView) => void\n}\n\ninterface WidgetState {\n state: ConversationsWidgetState\n view: WidgetView\n messages: Message[]\n tickets: Ticket[]\n ticketsLoading: boolean\n inputValue: string\n isLoading: boolean\n error: string | null\n showIdentificationForm: boolean\n formName: string\n formEmail: string\n formEmailError: string | null\n userTraits: UserProvidedTraits | null\n unreadCount: number\n hasMultipleTickets: boolean\n}\n\nexport class ConversationsWidget extends Component<WidgetProps, WidgetState> {\n private _messagesEndRef: HTMLDivElement | null = null\n private _inputRef: HTMLTextAreaElement | null = null\n\n constructor(props: WidgetProps) {\n super(props)\n\n // Determine if we need to show the identification form\n const userTraits = props.initialUserTraits || null\n const needsIdentification = this._needsIdentification(props.config, userTraits, props.isUserIdentified)\n\n this.state = {\n state: props.initialState || 'closed',\n view: props.initialView || 'messages',\n messages: [],\n tickets: props.initialTickets || [],\n ticketsLoading: false,\n inputValue: '',\n isLoading: false,\n error: null,\n showIdentificationForm: needsIdentification,\n formName: userTraits?.name || '',\n formEmail: userTraits?.email || '',\n formEmailError: null,\n userTraits,\n unreadCount: 0,\n hasMultipleTickets: props.hasMultipleTickets || false,\n }\n }\n\n /**\n * Check if we need to show the identification form\n */\n private _needsIdentification(\n config: ConversationsRemoteConfig,\n traits: UserProvidedTraits | null,\n isUserIdentified?: boolean\n ): boolean {\n // If user is already identified via PostHog, no form needed\n // They've called posthog.identify() so we have their identity\n if (isUserIdentified) {\n return false\n }\n\n // If requireEmail is not set, no identification needed\n if (!config.requireEmail) {\n return false\n }\n\n // If we already have an email, no form needed\n if (traits?.email) {\n return false\n }\n\n return true\n }\n\n componentDidMount() {\n // Add greeting message if no messages exist and we're in message view\n if (this.state.view === 'messages' && this.state.messages.length === 0 && this.props.config.greetingText) {\n this._addGreetingMessage()\n }\n }\n\n componentDidUpdate(_prevProps: WidgetProps, prevState: WidgetState) {\n // Scroll to bottom when messages change\n if (this.state.messages.length !== prevState.messages.length) {\n this._scrollToBottom()\n }\n\n // Notify parent of state changes\n if (this.state.state !== prevState.state && this.props.onStateChange) {\n this.props.onStateChange(this.state.state)\n }\n\n // Focus input and scroll to bottom when opening\n if (this.state.state === 'open' && prevState.state !== 'open') {\n this._focusInput()\n this._scrollToBottom()\n }\n }\n\n private _addGreetingMessage() {\n const greetingMessage: Message = {\n id: 'greeting',\n content: this.props.config.greetingText || 'Hi! How can we help?',\n author_type: 'AI',\n author_name: 'Support',\n created_at: new Date().toISOString(),\n is_private: false,\n }\n this.setState({ messages: [greetingMessage] })\n }\n\n private _scrollToBottom() {\n if (this._messagesEndRef) {\n this._messagesEndRef.scrollIntoView({ behavior: 'smooth' })\n }\n }\n\n private _focusInput() {\n if (this._inputRef) {\n this._inputRef.focus()\n }\n }\n\n private _handleToggleOpen = () => {\n this.setState((prevState) => ({\n state: prevState.state === 'open' ? 'closed' : 'open',\n }))\n }\n\n private _handleClose = () => {\n this.setState({ state: 'closed' })\n }\n\n private _handleSelectTicket = (ticketId: string) => {\n if (this.props.onSelectTicket) {\n this.props.onSelectTicket(ticketId)\n }\n }\n\n private _handleNewConversation = () => {\n if (this.props.onNewConversation) {\n this.props.onNewConversation()\n }\n }\n\n private _handleBackToTickets = () => {\n if (this.props.onBackToTickets) {\n this.props.onBackToTickets()\n }\n }\n\n private _handleInputChange = (e: Event) => {\n const target = e.target as HTMLTextAreaElement\n this.setState({ inputValue: target.value })\n }\n\n private _handleKeyPress = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n this._handleSendMessage()\n }\n }\n\n // Identification form handlers\n private _handleFormNameChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n this.setState({ formName: target.value })\n }\n\n private _handleFormEmailChange = (e: Event) => {\n const target = e.target as HTMLInputElement\n this.setState({ formEmail: target.value, formEmailError: null })\n }\n\n private _validateEmail(email: string): boolean {\n // Basic email validation\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(email)\n }\n\n private _handleFormSubmit = (e: Event) => {\n e.preventDefault()\n\n const { formEmail, formName } = this.state\n const { config, onIdentify } = this.props\n\n // Validate email if required\n if (config.requireEmail && !formEmail.trim()) {\n this.setState({ formEmailError: 'Email is required' })\n return\n }\n\n if (formEmail.trim() && !this._validateEmail(formEmail.trim())) {\n this.setState({ formEmailError: 'Please enter a valid email address' })\n return\n }\n\n // Create traits object\n const traits: UserProvidedTraits = {}\n if (formName.trim()) {\n traits.name = formName.trim()\n }\n if (formEmail.trim()) {\n traits.email = formEmail.trim()\n }\n\n // Update state and notify parent\n this.setState({\n userTraits: traits,\n showIdentificationForm: false,\n })\n\n if (onIdentify) {\n onIdentify(traits)\n }\n }\n\n private _handleSendMessage = async () => {\n const { inputValue } = this.state\n const trimmedMessage = inputValue.trim()\n\n if (!trimmedMessage) {\n return\n }\n\n // Add user message to UI immediately\n const userMessage: Message = {\n id: `temp-${Date.now()}`,\n content: trimmedMessage,\n author_type: 'customer',\n author_name: 'You',\n created_at: new Date().toISOString(),\n is_private: false,\n }\n\n this.setState({\n messages: [...this.state.messages, userMessage],\n inputValue: '',\n isLoading: true,\n error: null,\n })\n\n try {\n await this.props.onSendMessage(trimmedMessage)\n // Success - message will be updated via addMessage()\n this.setState({ isLoading: false })\n } catch (error) {\n logger.error('Failed to send message', error)\n this.setState({\n isLoading: false,\n error: error instanceof Error ? error.message : 'Failed to send message',\n })\n\n // Remove the temporary message on error\n this.setState((prevState) => ({\n messages: prevState.messages.filter((m) => m.id !== userMessage.id),\n }))\n }\n }\n\n /**\n * Public method to add messages from outside\n */\n addMessages(messages: Message[]) {\n this.setState((prevState) => {\n // Filter out duplicates\n const existingIds = new Set(prevState.messages.map((m) => m.id))\n const newMessages = messages.filter((m) => !existingIds.has(m.id))\n\n if (newMessages.length > 0) {\n return {\n messages: [...prevState.messages, ...newMessages],\n }\n }\n return null\n })\n }\n\n /**\n * Public method to show the widget\n */\n show() {\n this.setState({ state: 'open' })\n }\n\n /**\n * Public method to hide the widget\n */\n hide() {\n this.setState({ state: 'closed' })\n }\n\n /**\n * Public method to close the widget completely\n */\n close() {\n this.setState({ state: 'closed' })\n }\n\n /**\n * Get user traits (either provided via form or from props)\n */\n getUserTraits(): UserProvidedTraits | null {\n return this.state.userTraits\n }\n\n /**\n * Called when user identifies via posthog.identify()\n * Hides the identification form since we now know who they are\n */\n setUserIdentified(): void {\n if (this.state.showIdentificationForm) {\n this.setState({ showIdentificationForm: false })\n }\n }\n\n /**\n * Set the unread message count (called by manager)\n */\n setUnreadCount(count: number): void {\n this.setState({ unreadCount: count })\n }\n\n /**\n * Update the tickets list (called by manager during polling)\n */\n updateTickets(tickets: Ticket[]): void {\n this.setState({\n tickets,\n ticketsLoading: false,\n hasMultipleTickets: tickets.length > 1,\n })\n }\n\n /**\n * Set the current view (tickets list or messages)\n */\n setView(view: WidgetView): void {\n this.setState({ view })\n if (this.props.onViewChange) {\n this.props.onViewChange(view)\n }\n }\n\n /**\n * Get the current view\n */\n getView(): WidgetView {\n return this.state.view\n }\n\n /**\n * Set tickets loading state\n */\n setTicketsLoading(loading: boolean): void {\n this.setState({ ticketsLoading: loading })\n }\n\n /**\n * Clear messages (used when switching tickets or starting new conversation)\n * @param addGreeting - If true, adds the greeting message after clearing\n */\n clearMessages(addGreeting: boolean = false): void {\n this.setState({ messages: [] }, () => {\n if (addGreeting && this.props.config.greetingText) {\n this._addGreetingMessage()\n }\n })\n }\n\n private _renderIdentificationForm(styles: ReturnType<typeof getStyles>) {\n const { config } = this.props\n const { formName, formEmail, formEmailError } = this.state\n\n const title = config.identificationFormTitle || 'Before we start...'\n const description =\n config.identificationFormDescription || 'Please provide your details so we can help you better.'\n const showNameField = config.collectName !== false // Show by default unless explicitly disabled\n\n return (\n <div style={styles.identificationForm}>\n <div style={styles.formTitle}>{title}</div>\n <div style={styles.formDescription}>{description}</div>\n\n <form onSubmit={this._handleFormSubmit}>\n {showNameField && (\n <div style={styles.formField}>\n <label style={styles.formLabel}>\n Name <span style={styles.formOptional}>(optional)</span>\n </label>\n <input\n type=\"text\"\n style={styles.formInput}\n value={formName}\n onInput={this._handleFormNameChange}\n placeholder=\"Your name\"\n autoComplete=\"name\"\n />\n </div>\n )}\n\n <div style={styles.formField}>\n <label style={styles.formLabel}>\n Email {!config.requireEmail && <span style={styles.formOptional}>(optional)</span>}\n </label>\n <input\n type=\"email\"\n style={{\n ...styles.formInput,\n ...(formEmailError ? styles.formInputError : {}),\n }}\n value={formEmail}\n onInput={this._handleFormEmailChange}\n placeholder=\"you@example.com\"\n autoComplete=\"email\"\n />\n {formEmailError && <div style={styles.formError}>{formEmailError}</div>}\n </div>\n\n <button\n type=\"submit\"\n style={styles.formSubmitButton}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '0.9'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = '1'\n }}\n >\n Start Chat\n </button>\n </form>\n </div>\n )\n }\n\n private _renderMessage(message: Message, styles: ReturnType<typeof getStyles>, primaryColor: string) {\n const isCustomer = message.author_type === 'customer'\n const messageStyle = {\n ...styles.message,\n ...(isCustomer ? styles.messageCustomer : styles.messageAgent),\n }\n const contentStyle = {\n ...styles.messageContent,\n ...(isCustomer ? styles.messageContentCustomer : styles.messageContentAgent),\n }\n\n return (\n <div key={message.id} style={messageStyle}>\n {!isCustomer && message.author_name && <div style={styles.messageAuthor}>{message.author_name}</div>}\n <div style={contentStyle}>\n <RichContent\n richContent={message.rich_content}\n content={message.content}\n isCustomer={isCustomer}\n primaryColor={primaryColor}\n />\n </div>\n <div style={styles.messageTime}>{formatRelativeTime(message.created_at)}</div>\n </div>\n )\n }\n\n private _renderBackButton(styles: ReturnType<typeof getStyles>) {\n return (\n <button style={styles.backButton} onClick={this._handleBackToTickets} aria-label=\"Back to conversations\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n </button>\n )\n }\n\n private _renderTicketList(styles: ReturnType<typeof getStyles>) {\n const { tickets, ticketsLoading } = this.state\n\n return (\n <TicketListView\n tickets={tickets}\n isLoading={ticketsLoading}\n styles={styles}\n onSelectTicket={this._handleSelectTicket}\n onNewConversation={this._handleNewConversation}\n />\n )\n }\n\n private _renderMessages(styles: ReturnType<typeof getStyles>, primaryColor: string, placeholderText: string) {\n const { messages, inputValue, isLoading, error } = this.state\n\n return (\n <>\n <div style={styles.messages}>\n {messages.map((message) => this._renderMessage(message, styles, primaryColor))}\n <div\n ref={(el) => {\n this._messagesEndRef = el\n }}\n />\n </div>\n\n {/* Error message */}\n {error && <div style={styles.error}>{error}</div>}\n\n {/* Input */}\n <div style={styles.inputContainer}>\n <textarea\n ref={(el) => {\n this._inputRef = el\n }}\n style={styles.input}\n placeholder={placeholderText}\n value={inputValue}\n onInput={this._handleInputChange}\n onKeyPress={this._handleKeyPress}\n rows={1}\n disabled={isLoading}\n />\n <SendMessageButton\n primaryColor={primaryColor}\n inputValue={inputValue}\n isLoading={isLoading}\n handleSendMessage={this._handleSendMessage}\n />\n </div>\n </>\n )\n }\n\n render() {\n const { config } = this.props\n const { state, view, showIdentificationForm } = this.state\n const primaryColor = config.color || '#5375ff'\n const widgetPosition = config.widgetPosition || 'bottom_right'\n const placeholderText = config.placeholderText || 'Type your message...'\n const styles = getStyles(primaryColor, widgetPosition)\n\n // Button only (closed state)\n if (state === 'closed') {\n return (\n <OpenChatButton\n primaryColor={primaryColor}\n position={widgetPosition}\n handleToggleOpen={this._handleToggleOpen}\n unreadCount={this.state.unreadCount}\n />\n )\n }\n\n // Open state\n const windowStyle = {\n ...styles.window,\n ...styles.windowOpen,\n }\n\n // Determine header title based on view\n const headerTitle = view === 'tickets' ? 'Conversations' : 'Support Chat'\n\n // Show back button in message view when there are multiple tickets\n const showBackButton = view === 'messages' && this.state.hasMultipleTickets\n\n return (\n <div style={styles.widget}>\n <div style={windowStyle}>\n {/* Header */}\n <div style={styles.header}>\n <div style={showBackButton ? styles.headerWithBack : styles.headerTitle}>\n {showBackButton && this._renderBackButton(styles)}\n <span style={styles.headerTitle}>{headerTitle}</span>\n </div>\n <div style={styles.headerActions}>\n <CloseChatButton primaryColor={primaryColor} handleClose={this._handleClose} />\n </div>\n </div>\n\n {/* Show identification form if needed */}\n {showIdentificationForm\n ? this._renderIdentificationForm(styles)\n : view === 'tickets'\n ? // Ticket list view\n this._renderTicketList(styles)\n : // Messages view\n this._renderMessages(styles, primaryColor, placeholderText)}\n </div>\n </div>\n )\n }\n}\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FunctionComponent } from 'preact';
|
|
2
|
+
import { Ticket } from '../../../../posthog-conversations-types';
|
|
3
|
+
import { getStyles } from './styles';
|
|
4
|
+
interface TicketListItemProps {
|
|
5
|
+
ticket: Ticket;
|
|
6
|
+
styles: ReturnType<typeof getStyles>;
|
|
7
|
+
onClick: (ticketId: string) => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A single ticket item in the ticket list
|
|
11
|
+
*/
|
|
12
|
+
export declare const TicketListItem: FunctionComponent<TicketListItemProps>;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.TicketListItem = void 0;
|
|
15
|
+
var jsx_runtime_1 = require("preact/jsx-runtime");
|
|
16
|
+
var utils_1 = require("./utils");
|
|
17
|
+
/**
|
|
18
|
+
* Get a human-readable status label
|
|
19
|
+
* Matches the display logic in PostHog main app
|
|
20
|
+
*/
|
|
21
|
+
function getStatusLabel(status) {
|
|
22
|
+
if (status === 'on_hold') {
|
|
23
|
+
return 'On hold';
|
|
24
|
+
}
|
|
25
|
+
// Capitalize first letter: 'new' -> 'New', 'open' -> 'Open', etc.
|
|
26
|
+
return status.charAt(0).toUpperCase() + status.slice(1);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A single ticket item in the ticket list
|
|
30
|
+
*/
|
|
31
|
+
var TicketListItem = function (_a) {
|
|
32
|
+
var ticket = _a.ticket, styles = _a.styles, onClick = _a.onClick;
|
|
33
|
+
var hasUnread = (ticket.unread_count || 0) > 0;
|
|
34
|
+
var statusLabel = getStatusLabel(ticket.status);
|
|
35
|
+
var handleClick = function () {
|
|
36
|
+
onClick(ticket.id);
|
|
37
|
+
};
|
|
38
|
+
var itemStyle = __assign(__assign({}, styles.ticketItem), (hasUnread ? styles.ticketItemUnread : {}));
|
|
39
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: itemStyle, onClick: handleClick, onKeyDown: function (e) {
|
|
40
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
41
|
+
e.preventDefault();
|
|
42
|
+
handleClick();
|
|
43
|
+
}
|
|
44
|
+
}, role: "button", tabIndex: 0, children: [(0, jsx_runtime_1.jsxs)("div", { style: styles.ticketItemContent, children: [(0, jsx_runtime_1.jsxs)("div", { style: styles.ticketItemHeader, children: [(0, jsx_runtime_1.jsx)("span", { style: hasUnread ? styles.ticketPreviewUnread : styles.ticketPreview, children: (0, utils_1.truncateText)(ticket.last_message, 60) }), hasUnread && (0, jsx_runtime_1.jsx)("span", { style: styles.ticketUnreadBadge, children: ticket.unread_count })] }), (0, jsx_runtime_1.jsxs)("div", { style: styles.ticketMeta, children: [(0, jsx_runtime_1.jsx)("span", { style: styles.ticketTime, children: (0, utils_1.formatRelativeTime)(ticket.last_message_at || ticket.created_at) }), (0, jsx_runtime_1.jsx)("span", { style: styles.ticketStatus, children: statusLabel })] })] }), (0, jsx_runtime_1.jsx)("div", { style: styles.ticketItemArrow, children: (0, jsx_runtime_1.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: (0, jsx_runtime_1.jsx)("polyline", { points: "9 18 15 12 9 6" }) }) })] }));
|
|
45
|
+
};
|
|
46
|
+
exports.TicketListItem = TicketListItem;
|
|
47
|
+
//# sourceMappingURL=TicketListItem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TicketListItem.js","sourceRoot":"","sources":["../../../../../../src/extensions/conversations/external/components/TicketListItem.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;AAIA,iCAA0D;AAQ1D;;;GAGG;AACH,SAAS,cAAc,CAAC,MAAoB;IACxC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,SAAS,CAAA;IACpB,CAAC;IACD,kEAAkE;IAClE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;AAC3D,CAAC;AAED;;GAEG;AACI,IAAM,cAAc,GAA2C,UAAC,EAA2B;QAAzB,MAAM,YAAA,EAAE,MAAM,YAAA,EAAE,OAAO,aAAA;IAC5F,IAAM,SAAS,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;IAChD,IAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAEjD,IAAM,WAAW,GAAG;QAChB,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACtB,CAAC,CAAA;IAED,IAAM,SAAS,yBACR,MAAM,CAAC,UAAU,GACjB,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAChD,CAAA;IAED,OAAO,CACH,iCACI,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,UAAC,CAAC;YACT,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;gBACrC,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,WAAW,EAAE,CAAA;YACjB,CAAC;QACL,CAAC,EACD,IAAI,EAAC,QAAQ,EACb,QAAQ,EAAE,CAAC,aAEX,iCAAK,KAAK,EAAE,MAAM,CAAC,iBAAiB,aAChC,iCAAK,KAAK,EAAE,MAAM,CAAC,gBAAgB,aAC/B,iCAAM,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,YACrE,IAAA,oBAAY,EAAC,MAAM,CAAC,YAAY,EAAE,EAAE,CAAC,GACnC,EACN,SAAS,IAAI,iCAAM,KAAK,EAAE,MAAM,CAAC,iBAAiB,YAAG,MAAM,CAAC,YAAY,GAAQ,IAC/E,EACN,iCAAK,KAAK,EAAE,MAAM,CAAC,UAAU,aACzB,iCAAM,KAAK,EAAE,MAAM,CAAC,UAAU,YACzB,IAAA,0BAAkB,EAAC,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,UAAU,CAAC,GAC7D,EACP,iCAAM,KAAK,EAAE,MAAM,CAAC,YAAY,YAAG,WAAW,GAAQ,IACpD,IACJ,EAEN,gCAAK,KAAK,EAAE,MAAM,CAAC,eAAe,YAC9B,gCAAK,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,GAAG,YAC7F,qCAAU,MAAM,EAAC,gBAAgB,GAAG,GAClC,GACJ,IACJ,CACT,CAAA;AACL,CAAC,CAAA;AAhDY,QAAA,cAAc,kBAgD1B","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { h, FunctionComponent } from 'preact'\nimport { Ticket, TicketStatus } from '../../../../posthog-conversations-types'\nimport { getStyles } from './styles'\nimport { formatRelativeTime, truncateText } from './utils'\n\ninterface TicketListItemProps {\n ticket: Ticket\n styles: ReturnType<typeof getStyles>\n onClick: (ticketId: string) => void\n}\n\n/**\n * Get a human-readable status label\n * Matches the display logic in PostHog main app\n */\nfunction getStatusLabel(status: TicketStatus): string {\n if (status === 'on_hold') {\n return 'On hold'\n }\n // Capitalize first letter: 'new' -> 'New', 'open' -> 'Open', etc.\n return status.charAt(0).toUpperCase() + status.slice(1)\n}\n\n/**\n * A single ticket item in the ticket list\n */\nexport const TicketListItem: FunctionComponent<TicketListItemProps> = ({ ticket, styles, onClick }) => {\n const hasUnread = (ticket.unread_count || 0) > 0\n const statusLabel = getStatusLabel(ticket.status)\n\n const handleClick = () => {\n onClick(ticket.id)\n }\n\n const itemStyle = {\n ...styles.ticketItem,\n ...(hasUnread ? styles.ticketItemUnread : {}),\n }\n\n return (\n <div\n style={itemStyle}\n onClick={handleClick}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleClick()\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n <div style={styles.ticketItemContent}>\n <div style={styles.ticketItemHeader}>\n <span style={hasUnread ? styles.ticketPreviewUnread : styles.ticketPreview}>\n {truncateText(ticket.last_message, 60)}\n </span>\n {hasUnread && <span style={styles.ticketUnreadBadge}>{ticket.unread_count}</span>}\n </div>\n <div style={styles.ticketMeta}>\n <span style={styles.ticketTime}>\n {formatRelativeTime(ticket.last_message_at || ticket.created_at)}\n </span>\n <span style={styles.ticketStatus}>{statusLabel}</span>\n </div>\n </div>\n {/* Right arrow indicator */}\n <div style={styles.ticketItemArrow}>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n </div>\n </div>\n )\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FunctionComponent } from 'preact';
|
|
2
|
+
import { Ticket } from '../../../../posthog-conversations-types';
|
|
3
|
+
import { getStyles } from './styles';
|
|
4
|
+
interface TicketListViewProps {
|
|
5
|
+
tickets: Ticket[];
|
|
6
|
+
isLoading: boolean;
|
|
7
|
+
styles: ReturnType<typeof getStyles>;
|
|
8
|
+
onSelectTicket: (ticketId: string) => void;
|
|
9
|
+
onNewConversation: () => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Ticket list view showing all user's tickets
|
|
13
|
+
*/
|
|
14
|
+
export declare const TicketListView: FunctionComponent<TicketListViewProps>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
3
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
4
|
+
if (!m) return o;
|
|
5
|
+
var i = m.call(o), r, ar = [], e;
|
|
6
|
+
try {
|
|
7
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
8
|
+
}
|
|
9
|
+
catch (error) { e = { error: error }; }
|
|
10
|
+
finally {
|
|
11
|
+
try {
|
|
12
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
13
|
+
}
|
|
14
|
+
finally { if (e) throw e.error; }
|
|
15
|
+
}
|
|
16
|
+
return ar;
|
|
17
|
+
};
|
|
18
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
19
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
20
|
+
if (ar || !(i in from)) {
|
|
21
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
22
|
+
ar[i] = from[i];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.TicketListView = void 0;
|
|
29
|
+
var jsx_runtime_1 = require("preact/jsx-runtime");
|
|
30
|
+
var TicketListItem_1 = require("./TicketListItem");
|
|
31
|
+
/**
|
|
32
|
+
* Loading state component
|
|
33
|
+
*/
|
|
34
|
+
var LoadingState = function (_a) {
|
|
35
|
+
var styles = _a.styles;
|
|
36
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: styles.ticketListLoading, children: [(0, jsx_runtime_1.jsx)("div", { style: styles.loadingSpinner }), (0, jsx_runtime_1.jsx)("span", { children: "Loading conversations..." })] }));
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Empty state component when there are no tickets
|
|
40
|
+
*/
|
|
41
|
+
var EmptyState = function (_a) {
|
|
42
|
+
var styles = _a.styles, onNewConversation = _a.onNewConversation;
|
|
43
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: styles.ticketListEmpty, children: [(0, jsx_runtime_1.jsx)("div", { style: styles.emptyStateIcon, children: (0, jsx_runtime_1.jsx)("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: (0, jsx_runtime_1.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }) }), (0, jsx_runtime_1.jsx)("div", { style: styles.emptyStateTitle, children: "No conversations yet" }), (0, jsx_runtime_1.jsx)("div", { style: styles.emptyStateDescription, children: "Start a new conversation to get help from our team." }), (0, jsx_runtime_1.jsx)("button", { style: styles.newConversationButtonLarge, onClick: onNewConversation, onMouseEnter: function (e) {
|
|
44
|
+
e.currentTarget.style.opacity = '0.9';
|
|
45
|
+
}, onMouseLeave: function (e) {
|
|
46
|
+
e.currentTarget.style.opacity = '1';
|
|
47
|
+
}, children: "Start a conversation" })] }));
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Ticket list view showing all user's tickets
|
|
51
|
+
*/
|
|
52
|
+
var TicketListView = function (_a) {
|
|
53
|
+
var tickets = _a.tickets, isLoading = _a.isLoading, styles = _a.styles, onSelectTicket = _a.onSelectTicket, onNewConversation = _a.onNewConversation;
|
|
54
|
+
// Show loading state
|
|
55
|
+
if (isLoading && tickets.length === 0) {
|
|
56
|
+
return (0, jsx_runtime_1.jsx)(LoadingState, { styles: styles });
|
|
57
|
+
}
|
|
58
|
+
// Show empty state when no tickets
|
|
59
|
+
if (tickets.length === 0) {
|
|
60
|
+
return (0, jsx_runtime_1.jsx)(EmptyState, { styles: styles, onNewConversation: onNewConversation });
|
|
61
|
+
}
|
|
62
|
+
// Show ticket list
|
|
63
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: styles.ticketListContainer, children: [(0, jsx_runtime_1.jsx)("div", { style: styles.ticketList, children: __spreadArray([], __read(tickets), false).sort(function (a, b) {
|
|
64
|
+
var dateA = new Date(a.last_message_at || a.created_at).getTime();
|
|
65
|
+
var dateB = new Date(b.last_message_at || b.created_at).getTime();
|
|
66
|
+
return dateB - dateA; // Descending order (newest first)
|
|
67
|
+
})
|
|
68
|
+
.map(function (ticket) { return ((0, jsx_runtime_1.jsx)(TicketListItem_1.TicketListItem, { ticket: ticket, styles: styles, onClick: onSelectTicket }, ticket.id)); }) }), (0, jsx_runtime_1.jsxs)("button", { style: styles.newConversationButton, onClick: onNewConversation, onMouseEnter: function (e) {
|
|
69
|
+
e.currentTarget.style.opacity = '0.9';
|
|
70
|
+
}, onMouseLeave: function (e) {
|
|
71
|
+
e.currentTarget.style.opacity = '1';
|
|
72
|
+
}, children: [(0, jsx_runtime_1.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", style: { marginRight: '8px' }, children: [(0, jsx_runtime_1.jsx)("line", { x1: "12", y1: "5", x2: "12", y2: "19" }), (0, jsx_runtime_1.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" })] }), "New conversation"] })] }));
|
|
73
|
+
};
|
|
74
|
+
exports.TicketListView = TicketListView;
|
|
75
|
+
//# sourceMappingURL=TicketListView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TicketListView.js","sourceRoot":"","sources":["../../../../../../src/extensions/conversations/external/components/TicketListView.tsx"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { h, FunctionComponent } from 'preact'\nimport { Ticket } from '../../../../posthog-conversations-types'\nimport { getStyles } from './styles'\nimport { TicketListItem } from './TicketListItem'\n\ninterface TicketListViewProps {\n tickets: Ticket[]\n isLoading: boolean\n styles: ReturnType<typeof getStyles>\n onSelectTicket: (ticketId: string) => void\n onNewConversation: () => void\n}\n\n/**\n * Loading state component\n */\nconst LoadingState: FunctionComponent<{ styles: ReturnType<typeof getStyles> }> = ({ styles }) => (\n <div style={styles.ticketListLoading}>\n <div style={styles.loadingSpinner} />\n <span>Loading conversations...</span>\n </div>\n)\n\n/**\n * Empty state component when there are no tickets\n */\nconst EmptyState: FunctionComponent<{\n styles: ReturnType<typeof getStyles>\n onNewConversation: () => void\n}> = ({ styles, onNewConversation }) => (\n <div style={styles.ticketListEmpty}>\n <div style={styles.emptyStateIcon}>\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n </div>\n <div style={styles.emptyStateTitle}>No conversations yet</div>\n <div style={styles.emptyStateDescription}>Start a new conversation to get help from our team.</div>\n <button\n style={styles.newConversationButtonLarge}\n onClick={onNewConversation}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '0.9'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = '1'\n }}\n >\n Start a conversation\n </button>\n </div>\n)\n\n/**\n * Ticket list view showing all user's tickets\n */\nexport const TicketListView: FunctionComponent<TicketListViewProps> = ({\n tickets,\n isLoading,\n styles,\n onSelectTicket,\n onNewConversation,\n}) => {\n // Show loading state\n if (isLoading && tickets.length === 0) {\n return <LoadingState styles={styles} />\n }\n\n // Show empty state when no tickets\n if (tickets.length === 0) {\n return <EmptyState styles={styles} onNewConversation={onNewConversation} />\n }\n\n // Show ticket list\n return (\n <div style={styles.ticketListContainer}>\n {/* Ticket list - sorted by most recent activity */}\n <div style={styles.ticketList}>\n {[...tickets]\n .sort((a, b) => {\n const dateA = new Date(a.last_message_at || a.created_at).getTime()\n const dateB = new Date(b.last_message_at || b.created_at).getTime()\n return dateB - dateA // Descending order (newest first)\n })\n .map((ticket) => (\n <TicketListItem key={ticket.id} ticket={ticket} styles={styles} onClick={onSelectTicket} />\n ))}\n </div>\n\n {/* New conversation button at bottom */}\n <button\n style={styles.newConversationButton}\n onClick={onNewConversation}\n onMouseEnter={(e) => {\n e.currentTarget.style.opacity = '0.9'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.opacity = '1'\n }}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n style={{ marginRight: '8px' }}\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n New conversation\n </button>\n </div>\n )\n}\n"]}
|