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.
Files changed (74) hide show
  1. package/dist/array.full.es5.js +1 -1
  2. package/dist/array.full.js +1 -1
  3. package/dist/array.full.no-external.js +1 -1
  4. package/dist/array.js +1 -1
  5. package/dist/array.no-external.js +1 -1
  6. package/dist/conversations.js +1 -1
  7. package/dist/conversations.js.map +1 -1
  8. package/dist/customizations.full.js +1 -1
  9. package/dist/lazy-recorder.js +1 -1
  10. package/dist/main.js +1 -1
  11. package/dist/main.js.map +1 -1
  12. package/dist/module.d.ts +43 -1
  13. package/dist/module.full.d.ts +43 -1
  14. package/dist/module.full.js +1 -1
  15. package/dist/module.full.js.map +1 -1
  16. package/dist/module.full.no-external.d.ts +43 -1
  17. package/dist/module.full.no-external.js +1 -1
  18. package/dist/module.full.no-external.js.map +1 -1
  19. package/dist/module.js +1 -1
  20. package/dist/module.js.map +1 -1
  21. package/dist/module.no-external.d.ts +43 -1
  22. package/dist/module.no-external.js +1 -1
  23. package/dist/module.no-external.js.map +1 -1
  24. package/dist/posthog-recorder.js +1 -1
  25. package/dist/product-tours-preview.d.ts +2 -0
  26. package/dist/product-tours-preview.js +1 -1
  27. package/dist/product-tours-preview.js.map +1 -1
  28. package/dist/product-tours.js +1 -1
  29. package/dist/product-tours.js.map +1 -1
  30. package/dist/src/extensions/conversations/external/components/ConversationsWidget.d.ts +43 -2
  31. package/dist/src/extensions/conversations/external/components/TicketListItem.d.ts +13 -0
  32. package/dist/src/extensions/conversations/external/components/TicketListView.d.ts +15 -0
  33. package/dist/src/extensions/conversations/external/components/styles.d.ts +184 -0
  34. package/dist/src/extensions/conversations/external/components/utils.d.ts +8 -0
  35. package/dist/src/extensions/conversations/external/index.d.ts +39 -1
  36. package/dist/src/extensions/product-tours/product-tours.d.ts +2 -0
  37. package/dist/src/posthog-product-tours-types.d.ts +42 -0
  38. package/dist/surveys-preview.d.ts +2 -0
  39. package/lib/package.json +1 -1
  40. package/lib/src/extensions/conversations/external/components/ConversationsWidget.d.ts +43 -2
  41. package/lib/src/extensions/conversations/external/components/ConversationsWidget.js +96 -28
  42. package/lib/src/extensions/conversations/external/components/ConversationsWidget.js.map +1 -1
  43. package/lib/src/extensions/conversations/external/components/TicketListItem.d.ts +13 -0
  44. package/lib/src/extensions/conversations/external/components/TicketListItem.js +47 -0
  45. package/lib/src/extensions/conversations/external/components/TicketListItem.js.map +1 -0
  46. package/lib/src/extensions/conversations/external/components/TicketListView.d.ts +15 -0
  47. package/lib/src/extensions/conversations/external/components/TicketListView.js +75 -0
  48. package/lib/src/extensions/conversations/external/components/TicketListView.js.map +1 -0
  49. package/lib/src/extensions/conversations/external/components/styles.d.ts +184 -0
  50. package/lib/src/extensions/conversations/external/components/styles.js +189 -0
  51. package/lib/src/extensions/conversations/external/components/styles.js.map +1 -1
  52. package/lib/src/extensions/conversations/external/components/utils.d.ts +8 -0
  53. package/lib/src/extensions/conversations/external/components/utils.js +49 -0
  54. package/lib/src/extensions/conversations/external/components/utils.js.map +1 -0
  55. package/lib/src/extensions/conversations/external/index.d.ts +39 -1
  56. package/lib/src/extensions/conversations/external/index.js +253 -31
  57. package/lib/src/extensions/conversations/external/index.js.map +1 -1
  58. package/lib/src/extensions/product-tours/components/ProductTourSurveyStepInner.js +1 -1
  59. package/lib/src/extensions/product-tours/components/ProductTourSurveyStepInner.js.map +1 -1
  60. package/lib/src/extensions/product-tours/product-tours.d.ts +2 -0
  61. package/lib/src/extensions/product-tours/product-tours.js +78 -71
  62. package/lib/src/extensions/product-tours/product-tours.js.map +1 -1
  63. package/lib/src/posthog-product-tours-types.d.ts +42 -0
  64. package/lib/src/posthog-product-tours-types.js +43 -1
  65. package/lib/src/posthog-product-tours-types.js.map +1 -1
  66. package/lib/src/utils/product-tour-event-receiver.js +2 -1
  67. package/lib/src/utils/product-tour-event-receiver.js.map +1 -1
  68. package/lib/tsconfig.tsbuildinfo +1 -1
  69. package/package.json +3 -3
  70. package/react/dist/esm/index.js +25 -1
  71. package/react/dist/esm/index.js.map +1 -1
  72. package/react/dist/types/index.d.ts +4 -2
  73. package/react/dist/umd/index.js +25 -0
  74. 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: this._formatTime(message.created_at) })] }, message.id));
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.render = function () {
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, messages = _a.messages, inputValue = _a.inputValue, isLoading = _a.isLoading, error = _a.error, showIdentificationForm = _a.showIdentificationForm;
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
- 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.jsx)("div", { style: styles.headerTitle, children: (0, jsx_runtime_1.jsx)("span", { children: "Support Chat" }) }), (0, jsx_runtime_1.jsx)("div", { style: styles.headerActions, children: (0, jsx_runtime_1.jsx)(CloseChatButton_1.CloseChatButton, { primaryColor: primaryColor, handleClose: this._handleClose }) })] }), showIdentificationForm ? (this._renderIdentificationForm(styles)) : ((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) {
405
- _this._messagesEndRef = el;
406
- } })] }), 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) {
407
- _this._inputRef = el;
408
- }, 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 })] })] }))] }) }));
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"]}