@pocketping/widget 1.5.2 → 1.6.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/index.js CHANGED
@@ -148,7 +148,7 @@ function styles(primaryColor, theme) {
148
148
  display: flex;
149
149
  align-items: center;
150
150
  justify-content: space-between;
151
- padding: 16px;
151
+ padding: 12px 14px;
152
152
  background: ${primaryColor};
153
153
  color: white;
154
154
  }
@@ -156,24 +156,24 @@ function styles(primaryColor, theme) {
156
156
  .pp-header-info {
157
157
  display: flex;
158
158
  align-items: center;
159
- gap: 12px;
159
+ gap: 10px;
160
160
  }
161
161
 
162
162
  .pp-avatar {
163
- width: 40px;
164
- height: 40px;
163
+ width: 36px;
164
+ height: 36px;
165
165
  border-radius: 50%;
166
166
  object-fit: cover;
167
167
  }
168
168
 
169
169
  .pp-header-title {
170
170
  font-weight: 600;
171
- font-size: 16px;
171
+ font-size: 15px;
172
172
  }
173
173
 
174
174
  .pp-header-status {
175
- font-size: 12px;
176
- opacity: 0.9;
175
+ font-size: 11px;
176
+ opacity: 0.85;
177
177
  display: flex;
178
178
  align-items: center;
179
179
  gap: 4px;
@@ -219,10 +219,10 @@ function styles(primaryColor, theme) {
219
219
  .pp-messages {
220
220
  flex: 1;
221
221
  overflow-y: auto;
222
- padding: 16px;
222
+ padding: 12px;
223
223
  display: flex;
224
224
  flex-direction: column;
225
- gap: 12px;
225
+ gap: 3px;
226
226
  }
227
227
 
228
228
  .pp-welcome {
@@ -232,14 +232,32 @@ function styles(primaryColor, theme) {
232
232
  font-size: 13px;
233
233
  }
234
234
 
235
+ .pp-date-separator {
236
+ display: flex;
237
+ align-items: center;
238
+ justify-content: center;
239
+ margin: 16px 0 12px;
240
+ }
241
+
242
+ .pp-date-separator span {
243
+ background: ${colors.bgSecondary};
244
+ color: ${colors.textSecondary};
245
+ font-size: 11px;
246
+ padding: 4px 12px;
247
+ border-radius: 12px;
248
+ font-weight: 500;
249
+ }
250
+
235
251
  .pp-message {
236
- max-width: 80%;
237
- padding: 10px 14px;
238
- border-radius: 16px;
252
+ max-width: 85%;
253
+ padding: 6px 10px;
254
+ border-radius: 12px;
239
255
  word-wrap: break-word;
240
256
  position: relative;
241
257
  user-select: text;
242
258
  -webkit-user-select: text;
259
+ font-size: 14px;
260
+ line-height: 1.35;
243
261
  }
244
262
 
245
263
  /* Hover actions container - positioned above message (Slack style) */
@@ -331,7 +349,8 @@ function styles(primaryColor, theme) {
331
349
  align-self: flex-end;
332
350
  background: ${primaryColor};
333
351
  color: white;
334
- border-bottom-right-radius: 4px;
352
+ border-bottom-right-radius: 3px;
353
+ margin-left: 32px;
335
354
  }
336
355
 
337
356
  .pp-message-operator,
@@ -339,19 +358,31 @@ function styles(primaryColor, theme) {
339
358
  align-self: flex-start;
340
359
  background: ${colors.messageBg};
341
360
  color: ${colors.text};
342
- border-bottom-left-radius: 4px;
361
+ border-bottom-left-radius: 3px;
362
+ margin-right: 32px;
363
+ }
364
+
365
+ /* Add spacing between different senders */
366
+ .pp-message-visitor + .pp-message-operator,
367
+ .pp-message-visitor + .pp-message-ai,
368
+ .pp-message-operator + .pp-message-visitor,
369
+ .pp-message-ai + .pp-message-visitor {
370
+ margin-top: 8px;
343
371
  }
344
372
 
345
373
  .pp-message-content {
346
- margin-bottom: 4px;
374
+ display: inline;
347
375
  }
348
376
 
349
377
  .pp-message-time {
350
- font-size: 11px;
351
- opacity: 0.7;
352
- display: flex;
378
+ font-size: 10px;
379
+ opacity: 0.6;
380
+ display: inline-flex;
353
381
  align-items: center;
354
- gap: 4px;
382
+ gap: 3px;
383
+ float: right;
384
+ margin-left: 8px;
385
+ margin-top: 4px;
355
386
  }
356
387
 
357
388
  .pp-ai-badge {
@@ -388,13 +419,13 @@ function styles(primaryColor, theme) {
388
419
 
389
420
  .pp-typing {
390
421
  display: flex;
391
- gap: 4px;
392
- padding: 14px 18px;
422
+ gap: 3px;
423
+ padding: 8px 12px;
393
424
  }
394
425
 
395
426
  .pp-typing span {
396
- width: 8px;
397
- height: 8px;
427
+ width: 6px;
428
+ height: 6px;
398
429
  background: ${colors.textSecondary};
399
430
  border-radius: 50%;
400
431
  animation: pp-bounce 1.4s infinite ease-in-out both;
@@ -410,14 +441,18 @@ function styles(primaryColor, theme) {
410
441
 
411
442
  .pp-input-form {
412
443
  display: flex;
413
- padding: 12px;
444
+ padding: 10px 12px;
414
445
  gap: 8px;
415
446
  border-top: 1px solid ${colors.border};
447
+ align-items: center;
416
448
  }
417
449
 
418
450
  .pp-input {
419
451
  flex: 1;
420
- padding: 10px 14px;
452
+ min-width: 0;
453
+ height: 40px;
454
+ line-height: 40px;
455
+ padding: 0 16px;
421
456
  border: 1px solid ${colors.border};
422
457
  border-radius: 20px;
423
458
  background: ${colors.bg};
@@ -425,6 +460,8 @@ function styles(primaryColor, theme) {
425
460
  font-size: 14px;
426
461
  outline: none;
427
462
  transition: border-color 0.2s;
463
+ box-sizing: border-box;
464
+ margin: 0;
428
465
  }
429
466
 
430
467
  .pp-input:focus {
@@ -438,6 +475,7 @@ function styles(primaryColor, theme) {
438
475
  .pp-send-btn {
439
476
  width: 40px;
440
477
  height: 40px;
478
+ min-width: 40px;
441
479
  border-radius: 50%;
442
480
  background: ${primaryColor};
443
481
  color: white;
@@ -446,7 +484,18 @@ function styles(primaryColor, theme) {
446
484
  display: flex;
447
485
  align-items: center;
448
486
  justify-content: center;
449
- transition: opacity 0.2s;
487
+ transition: opacity 0.2s, transform 0.1s;
488
+ flex-shrink: 0;
489
+ margin: 0;
490
+ padding: 0;
491
+ }
492
+
493
+ .pp-send-btn:not(:disabled):hover {
494
+ transform: scale(1.05);
495
+ }
496
+
497
+ .pp-send-btn:not(:disabled):active {
498
+ transform: scale(0.95);
450
499
  }
451
500
 
452
501
  .pp-send-btn:disabled {
@@ -465,6 +514,7 @@ function styles(primaryColor, theme) {
465
514
  font-size: 11px;
466
515
  color: ${colors.textSecondary};
467
516
  border-top: 1px solid ${colors.border};
517
+ opacity: 0.7;
468
518
  }
469
519
 
470
520
  .pp-footer a {
@@ -493,6 +543,7 @@ function styles(primaryColor, theme) {
493
543
  .pp-attach-btn {
494
544
  width: 40px;
495
545
  height: 40px;
546
+ min-width: 40px;
496
547
  border-radius: 50%;
497
548
  background: transparent;
498
549
  color: ${colors.textSecondary};
@@ -501,6 +552,8 @@ function styles(primaryColor, theme) {
501
552
  display: flex;
502
553
  align-items: center;
503
554
  justify-content: center;
555
+ margin: 0;
556
+ padding: 0;
504
557
  transition: color 0.2s, border-color 0.2s;
505
558
  flex-shrink: 0;
506
559
  }
@@ -1019,6 +1072,24 @@ function styles(primaryColor, theme) {
1019
1072
 
1020
1073
  // src/components/ChatWidget.tsx
1021
1074
  import { Fragment as Fragment2, jsx, jsxs } from "preact/jsx-runtime";
1075
+ function formatDateSeparator(date) {
1076
+ const now = /* @__PURE__ */ new Date();
1077
+ const messageDate = new Date(date);
1078
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
1079
+ const msgDay = new Date(messageDate.getFullYear(), messageDate.getMonth(), messageDate.getDate());
1080
+ const diffDays = Math.floor((today.getTime() - msgDay.getTime()) / (1e3 * 60 * 60 * 24));
1081
+ if (diffDays === 0) return "Today";
1082
+ if (diffDays === 1) return "Yesterday";
1083
+ return messageDate.toLocaleDateString("en-US", {
1084
+ month: "short",
1085
+ day: "numeric",
1086
+ year: messageDate.getFullYear() !== now.getFullYear() ? "numeric" : void 0
1087
+ });
1088
+ }
1089
+ function getDateKey(date) {
1090
+ const d = new Date(date);
1091
+ return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
1092
+ }
1022
1093
  function ChatWidget({ client: client2, config: initialConfig }) {
1023
1094
  const [isOpen, setIsOpen] = useState(false);
1024
1095
  const [messages, setMessages] = useState([]);
@@ -1428,9 +1499,12 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1428
1499
  ] }),
1429
1500
  /* @__PURE__ */ jsxs("div", { class: "pp-messages", ref: messagesContainerRef, children: [
1430
1501
  config.welcomeMessage && messages.length === 0 && /* @__PURE__ */ jsx("div", { class: "pp-welcome", children: config.welcomeMessage }),
1431
- messages.map((msg) => {
1502
+ messages.map((msg, index) => {
1432
1503
  const isDeleted = !!msg.deletedAt;
1433
1504
  const isEdited = !!msg.editedAt;
1505
+ const msgDate = new Date(msg.timestamp);
1506
+ const prevMsg = index > 0 ? messages[index - 1] : null;
1507
+ const showDateSeparator = !prevMsg || getDateKey(new Date(prevMsg.timestamp)) !== getDateKey(msgDate);
1434
1508
  let replyData = null;
1435
1509
  if (msg.replyTo) {
1436
1510
  if (typeof msg.replyTo === "object") {
@@ -1452,86 +1526,88 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1452
1526
  }
1453
1527
  const isHovered = hoveredMessageId === msg.id;
1454
1528
  const showActions = isHovered && !isDeleted;
1455
- return /* @__PURE__ */ jsxs(
1456
- "div",
1457
- {
1458
- id: `pp-msg-${msg.id}`,
1459
- class: `pp-message pp-message-${msg.sender} ${isDeleted ? "pp-message-deleted" : ""}`,
1460
- onContextMenu: (e) => handleMessageContextMenu(e, msg),
1461
- onMouseEnter: () => setHoveredMessageId(msg.id),
1462
- onMouseLeave: () => setHoveredMessageId(null),
1463
- onTouchStart: () => handleTouchStart(msg),
1464
- onTouchEnd: handleTouchEnd,
1465
- onTouchCancel: handleTouchEnd,
1466
- children: [
1467
- showActions && /* @__PURE__ */ jsxs("div", { class: `pp-message-actions ${msg.sender === "visitor" ? "pp-actions-left" : "pp-actions-right"}`, children: [
1468
- /* @__PURE__ */ jsx(
1469
- "button",
1470
- {
1471
- class: "pp-action-btn",
1472
- onClick: () => handleReply(msg),
1473
- title: "Reply",
1474
- children: /* @__PURE__ */ jsx(ReplyIcon, { color: actionIconColor })
1475
- }
1476
- ),
1477
- msg.sender === "visitor" && /* @__PURE__ */ jsxs(Fragment2, { children: [
1529
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1530
+ showDateSeparator && /* @__PURE__ */ jsx("div", { class: "pp-date-separator", children: /* @__PURE__ */ jsx("span", { children: formatDateSeparator(msgDate) }) }),
1531
+ /* @__PURE__ */ jsxs(
1532
+ "div",
1533
+ {
1534
+ id: `pp-msg-${msg.id}`,
1535
+ class: `pp-message pp-message-${msg.sender} ${isDeleted ? "pp-message-deleted" : ""}`,
1536
+ onContextMenu: (e) => handleMessageContextMenu(e, msg),
1537
+ onMouseEnter: () => setHoveredMessageId(msg.id),
1538
+ onMouseLeave: () => setHoveredMessageId(null),
1539
+ onTouchStart: () => handleTouchStart(msg),
1540
+ onTouchEnd: handleTouchEnd,
1541
+ onTouchCancel: handleTouchEnd,
1542
+ children: [
1543
+ showActions && /* @__PURE__ */ jsxs("div", { class: `pp-message-actions ${msg.sender === "visitor" ? "pp-actions-left" : "pp-actions-right"}`, children: [
1478
1544
  /* @__PURE__ */ jsx(
1479
1545
  "button",
1480
1546
  {
1481
1547
  class: "pp-action-btn",
1482
- onClick: () => handleStartEdit(msg),
1483
- title: "Edit",
1484
- children: /* @__PURE__ */ jsx(EditIcon, { color: actionIconColor })
1548
+ onClick: () => handleReply(msg),
1549
+ title: "Reply",
1550
+ children: /* @__PURE__ */ jsx(ReplyIcon, { color: actionIconColor })
1485
1551
  }
1486
1552
  ),
1487
- /* @__PURE__ */ jsx(
1488
- "button",
1489
- {
1490
- class: "pp-action-btn pp-action-delete",
1491
- onClick: () => handleDelete(msg),
1492
- title: "Delete",
1493
- children: /* @__PURE__ */ jsx(DeleteIcon, { color: actionIconColor })
1494
- }
1495
- )
1553
+ msg.sender === "visitor" && /* @__PURE__ */ jsxs(Fragment2, { children: [
1554
+ /* @__PURE__ */ jsx(
1555
+ "button",
1556
+ {
1557
+ class: "pp-action-btn",
1558
+ onClick: () => handleStartEdit(msg),
1559
+ title: "Edit",
1560
+ children: /* @__PURE__ */ jsx(EditIcon, { color: actionIconColor })
1561
+ }
1562
+ ),
1563
+ /* @__PURE__ */ jsx(
1564
+ "button",
1565
+ {
1566
+ class: "pp-action-btn pp-action-delete",
1567
+ onClick: () => handleDelete(msg),
1568
+ title: "Delete",
1569
+ children: /* @__PURE__ */ jsx(DeleteIcon, { color: actionIconColor })
1570
+ }
1571
+ )
1572
+ ] })
1573
+ ] }),
1574
+ replyData && (replyData.content || replyData.hasAttachment) && /* @__PURE__ */ jsxs(
1575
+ "div",
1576
+ {
1577
+ class: "pp-reply-quote pp-reply-quote-clickable",
1578
+ onClick: () => scrollToMessage(replyData.id),
1579
+ role: "button",
1580
+ tabIndex: 0,
1581
+ onKeyDown: (e) => e.key === "Enter" && scrollToMessage(replyData.id),
1582
+ children: [
1583
+ /* @__PURE__ */ jsx("span", { class: "pp-reply-sender", children: replyData.sender === "visitor" ? "You" : "Support" }),
1584
+ /* @__PURE__ */ jsx("span", { class: "pp-reply-content", children: replyData.deleted ? "Message deleted" : /* @__PURE__ */ jsxs(Fragment2, { children: [
1585
+ replyData.hasAttachment && /* @__PURE__ */ jsx("span", { class: "pp-reply-attachment-icon", children: replyData.attachmentType?.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
1586
+ replyData.content ? /* @__PURE__ */ jsxs(Fragment2, { children: [
1587
+ (replyData.content || "").slice(0, 50),
1588
+ (replyData.content || "").length > 50 ? "..." : ""
1589
+ ] }) : replyData.attachmentType?.startsWith("image/") ? "Photo" : "File"
1590
+ ] }) })
1591
+ ]
1592
+ }
1593
+ ),
1594
+ isDeleted ? /* @__PURE__ */ jsxs("div", { class: "pp-message-content pp-deleted-content", children: [
1595
+ /* @__PURE__ */ jsx("span", { class: "pp-deleted-icon", children: "\u{1F5D1}\uFE0F" }),
1596
+ " Message deleted"
1597
+ ] }) : /* @__PURE__ */ jsxs(Fragment2, { children: [
1598
+ msg.content && /* @__PURE__ */ jsx("div", { class: "pp-message-content", children: msg.content }),
1599
+ msg.attachments && msg.attachments.length > 0 && /* @__PURE__ */ jsx("div", { class: "pp-message-attachments", children: msg.attachments.map((att) => /* @__PURE__ */ jsx(AttachmentDisplay, { attachment: att }, att.id)) })
1600
+ ] }),
1601
+ /* @__PURE__ */ jsxs("div", { class: "pp-message-time", children: [
1602
+ formatTime(msg.timestamp),
1603
+ isEdited && !isDeleted && /* @__PURE__ */ jsx("span", { class: "pp-edited-badge", children: "edited" }),
1604
+ msg.sender === "ai" && /* @__PURE__ */ jsx("span", { class: "pp-ai-badge", children: "AI" }),
1605
+ msg.sender === "visitor" && !isDeleted && /* @__PURE__ */ jsx("span", { class: `pp-status pp-status-${msg.status ?? "sent"}`, children: /* @__PURE__ */ jsx(StatusIcon, { status: msg.status }) })
1496
1606
  ] })
1497
- ] }),
1498
- replyData && (replyData.content || replyData.hasAttachment) && /* @__PURE__ */ jsxs(
1499
- "div",
1500
- {
1501
- class: "pp-reply-quote pp-reply-quote-clickable",
1502
- onClick: () => scrollToMessage(replyData.id),
1503
- role: "button",
1504
- tabIndex: 0,
1505
- onKeyDown: (e) => e.key === "Enter" && scrollToMessage(replyData.id),
1506
- children: [
1507
- /* @__PURE__ */ jsx("span", { class: "pp-reply-sender", children: replyData.sender === "visitor" ? "You" : "Support" }),
1508
- /* @__PURE__ */ jsx("span", { class: "pp-reply-content", children: replyData.deleted ? "Message deleted" : /* @__PURE__ */ jsxs(Fragment2, { children: [
1509
- replyData.hasAttachment && /* @__PURE__ */ jsx("span", { class: "pp-reply-attachment-icon", children: replyData.attachmentType?.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
1510
- replyData.content ? /* @__PURE__ */ jsxs(Fragment2, { children: [
1511
- (replyData.content || "").slice(0, 50),
1512
- (replyData.content || "").length > 50 ? "..." : ""
1513
- ] }) : replyData.attachmentType?.startsWith("image/") ? "Photo" : "File"
1514
- ] }) })
1515
- ]
1516
- }
1517
- ),
1518
- isDeleted ? /* @__PURE__ */ jsxs("div", { class: "pp-message-content pp-deleted-content", children: [
1519
- /* @__PURE__ */ jsx("span", { class: "pp-deleted-icon", children: "\u{1F5D1}\uFE0F" }),
1520
- " Message deleted"
1521
- ] }) : /* @__PURE__ */ jsxs(Fragment2, { children: [
1522
- msg.content && /* @__PURE__ */ jsx("div", { class: "pp-message-content", children: msg.content }),
1523
- msg.attachments && msg.attachments.length > 0 && /* @__PURE__ */ jsx("div", { class: "pp-message-attachments", children: msg.attachments.map((att) => /* @__PURE__ */ jsx(AttachmentDisplay, { attachment: att }, att.id)) })
1524
- ] }),
1525
- /* @__PURE__ */ jsxs("div", { class: "pp-message-time", children: [
1526
- formatTime(msg.timestamp),
1527
- isEdited && !isDeleted && /* @__PURE__ */ jsx("span", { class: "pp-edited-badge", children: "edited" }),
1528
- msg.sender === "ai" && /* @__PURE__ */ jsx("span", { class: "pp-ai-badge", children: "AI" }),
1529
- msg.sender === "visitor" && !isDeleted && /* @__PURE__ */ jsx("span", { class: `pp-status pp-status-${msg.status ?? "sent"}`, children: /* @__PURE__ */ jsx(StatusIcon, { status: msg.status }) })
1530
- ] })
1531
- ]
1532
- },
1533
- msg.id
1534
- );
1607
+ ]
1608
+ }
1609
+ )
1610
+ ] }, msg.id);
1535
1611
  }),
1536
1612
  isTyping && /* @__PURE__ */ jsxs("div", { class: "pp-message pp-message-operator pp-typing", children: [
1537
1613
  /* @__PURE__ */ jsx("span", {}),
@@ -1807,7 +1883,7 @@ function AttachmentDisplay({ attachment }) {
1807
1883
  }
1808
1884
 
1809
1885
  // src/version.ts
1810
- var VERSION = "0.3.6";
1886
+ var VERSION = "0.3.7";
1811
1887
 
1812
1888
  // src/client.ts
1813
1889
  var PocketPingClient = class {