@pocketping/widget 1.6.0 → 1.7.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.cjs CHANGED
@@ -44,7 +44,7 @@ var import_preact2 = require("preact");
44
44
 
45
45
  // src/components/ChatWidget.tsx
46
46
  var import_preact = require("preact");
47
- var import_hooks = require("preact/hooks");
47
+ var import_hooks2 = require("preact/hooks");
48
48
 
49
49
  // src/components/styles.ts
50
50
  function styles(primaryColor, theme) {
@@ -65,6 +65,17 @@ function styles(primaryColor, theme) {
65
65
  color: ${colors.text};
66
66
  }
67
67
 
68
+ #pocketping-container,
69
+ #pocketping-container * {
70
+ box-sizing: border-box;
71
+ }
72
+
73
+ #pocketping-container img,
74
+ #pocketping-container video {
75
+ max-width: 100%;
76
+ height: auto;
77
+ }
78
+
68
79
  .pp-toggle {
69
80
  position: fixed;
70
81
  width: 56px;
@@ -260,10 +271,14 @@ function styles(primaryColor, theme) {
260
271
  .pp-messages {
261
272
  flex: 1;
262
273
  overflow-y: auto;
263
- padding: 12px;
274
+ padding: 32px 12px 12px 12px;
264
275
  display: flex;
265
276
  flex-direction: column;
266
277
  gap: 3px;
278
+ overscroll-behavior: contain;
279
+ -webkit-overflow-scrolling: touch;
280
+ /* Ensure proper stacking context for positioned elements */
281
+ position: relative;
267
282
  }
268
283
 
269
284
  .pp-welcome {
@@ -289,6 +304,75 @@ function styles(primaryColor, theme) {
289
304
  font-weight: 500;
290
305
  }
291
306
 
307
+ /* Swipe container for mobile actions */
308
+ .pp-message-swipe-container {
309
+ position: relative;
310
+ display: flex;
311
+ align-items: stretch;
312
+ overflow: visible;
313
+ touch-action: pan-y;
314
+ }
315
+
316
+ .pp-swipe-left {
317
+ justify-content: flex-end;
318
+ }
319
+
320
+ .pp-swipe-right {
321
+ justify-content: flex-start;
322
+ }
323
+
324
+ .pp-swipe-actions {
325
+ position: absolute;
326
+ right: 0;
327
+ top: 0;
328
+ bottom: 0;
329
+ display: flex;
330
+ align-items: center;
331
+ gap: 4px;
332
+ padding-right: 8px;
333
+ }
334
+
335
+ .pp-swipe-left .pp-swipe-actions {
336
+ right: 0;
337
+ left: auto;
338
+ }
339
+
340
+ .pp-swipe-right .pp-swipe-actions {
341
+ left: 0;
342
+ right: auto;
343
+ padding-left: 8px;
344
+ padding-right: 0;
345
+ }
346
+
347
+ .pp-swipe-action {
348
+ width: 32px;
349
+ height: 32px;
350
+ border: none;
351
+ border-radius: 50%;
352
+ cursor: pointer;
353
+ display: flex;
354
+ align-items: center;
355
+ justify-content: center;
356
+ opacity: 0.9;
357
+ }
358
+
359
+ .pp-swipe-action svg {
360
+ width: 16px;
361
+ height: 16px;
362
+ }
363
+
364
+ .pp-swipe-reply {
365
+ background: ${primaryColor};
366
+ }
367
+
368
+ .pp-swipe-edit {
369
+ background: #3b82f6;
370
+ }
371
+
372
+ .pp-swipe-delete {
373
+ background: #ef4444;
374
+ }
375
+
292
376
  .pp-message {
293
377
  max-width: 85%;
294
378
  padding: 6px 10px;
@@ -299,12 +383,15 @@ function styles(primaryColor, theme) {
299
383
  -webkit-user-select: text;
300
384
  font-size: 14px;
301
385
  line-height: 1.35;
386
+ display: flex;
387
+ flex-direction: column;
388
+ will-change: transform;
302
389
  }
303
390
 
304
391
  /* Hover actions container - positioned above message (Slack style) */
305
392
  .pp-message-actions {
306
393
  position: absolute;
307
- top: -28px;
394
+ top: -32px;
308
395
  display: flex;
309
396
  gap: 2px;
310
397
  background: ${colors.bg};
@@ -317,6 +404,8 @@ function styles(primaryColor, theme) {
317
404
  z-index: 10;
318
405
  /* Reset color inheritance from message */
319
406
  color: ${colors.textSecondary};
407
+ /* Ensure actions don't interfere with layout */
408
+ pointer-events: auto;
320
409
  }
321
410
 
322
411
  @keyframes pp-actions-fade-in {
@@ -412,18 +501,19 @@ function styles(primaryColor, theme) {
412
501
  }
413
502
 
414
503
  .pp-message-content {
415
- display: inline;
504
+ display: block;
505
+ flex: 1;
416
506
  }
417
507
 
418
508
  .pp-message-time {
419
509
  font-size: 10px;
420
510
  opacity: 0.6;
421
- display: inline-flex;
511
+ display: flex;
422
512
  align-items: center;
423
513
  gap: 3px;
424
- float: right;
425
- margin-left: 8px;
426
- margin-top: 4px;
514
+ justify-content: flex-end;
515
+ margin-top: 8px;
516
+ flex-shrink: 0;
427
517
  }
428
518
 
429
519
  .pp-ai-badge {
@@ -715,7 +805,10 @@ function styles(primaryColor, theme) {
715
805
  display: flex;
716
806
  flex-direction: column;
717
807
  gap: 8px;
718
- margin-top: 4px;
808
+ margin-top: 6px;
809
+ max-width: 100%;
810
+ align-items: flex-start;
811
+ flex-shrink: 0;
719
812
  }
720
813
 
721
814
  .pp-attachment {
@@ -726,11 +819,22 @@ function styles(primaryColor, theme) {
726
819
  overflow: hidden;
727
820
  }
728
821
 
822
+ .pp-attachment-image,
823
+ .pp-attachment-video,
824
+ .pp-attachment-audio {
825
+ width: 240px;
826
+ max-width: 100%;
827
+ }
828
+
729
829
  .pp-attachment-image img {
730
- max-width: 200px;
830
+ width: 100% !important;
831
+ height: auto !important;
832
+ max-width: 240px;
731
833
  max-height: 200px;
732
834
  border-radius: 8px;
733
835
  display: block;
836
+ object-fit: cover !important;
837
+ object-position: center;
734
838
  }
735
839
 
736
840
  .pp-attachment-audio {
@@ -740,7 +844,8 @@ function styles(primaryColor, theme) {
740
844
  }
741
845
 
742
846
  .pp-attachment-audio audio {
743
- width: 200px;
847
+ width: 240px;
848
+ max-width: 100%;
744
849
  height: 36px;
745
850
  }
746
851
 
@@ -750,14 +855,18 @@ function styles(primaryColor, theme) {
750
855
  white-space: nowrap;
751
856
  overflow: hidden;
752
857
  text-overflow: ellipsis;
753
- max-width: 200px;
858
+ max-width: 100%;
754
859
  }
755
860
 
756
861
  .pp-attachment-video video {
757
- max-width: 200px;
758
- max-height: 200px;
862
+ width: 100% !important;
863
+ height: auto !important;
864
+ max-width: 240px;
865
+ max-height: none;
759
866
  border-radius: 8px;
760
867
  display: block;
868
+ object-fit: contain !important;
869
+ object-position: center;
761
870
  }
762
871
 
763
872
  .pp-attachment-file {
@@ -1108,11 +1217,619 @@ function styles(primaryColor, theme) {
1108
1217
  margin-left: 4px;
1109
1218
  font-style: italic;
1110
1219
  }
1220
+
1221
+ /* Pre-Chat Form */
1222
+ .pp-prechat {
1223
+ flex: 1;
1224
+ display: flex;
1225
+ flex-direction: column;
1226
+ padding: 24px 20px;
1227
+ overflow-y: auto;
1228
+ }
1229
+
1230
+ .pp-prechat-title {
1231
+ font-size: 18px;
1232
+ font-weight: 600;
1233
+ margin-bottom: 8px;
1234
+ color: ${colors.text};
1235
+ }
1236
+
1237
+ .pp-prechat-subtitle {
1238
+ font-size: 13px;
1239
+ color: ${colors.textSecondary};
1240
+ margin-bottom: 24px;
1241
+ }
1242
+
1243
+ .pp-prechat-tabs {
1244
+ display: flex;
1245
+ gap: 8px;
1246
+ margin-bottom: 20px;
1247
+ }
1248
+
1249
+ .pp-prechat-tab {
1250
+ flex: 1;
1251
+ padding: 10px;
1252
+ border: 1px solid ${colors.border};
1253
+ border-radius: 8px;
1254
+ background: transparent;
1255
+ color: ${colors.textSecondary};
1256
+ font-size: 13px;
1257
+ cursor: pointer;
1258
+ transition: all 0.2s;
1259
+ display: flex;
1260
+ align-items: center;
1261
+ justify-content: center;
1262
+ gap: 6px;
1263
+ }
1264
+
1265
+ .pp-prechat-tab:hover {
1266
+ background: ${colors.bgSecondary};
1267
+ }
1268
+
1269
+ .pp-prechat-tab.active {
1270
+ background: ${primaryColor}15;
1271
+ border-color: ${primaryColor};
1272
+ color: ${primaryColor};
1273
+ }
1274
+
1275
+ .pp-prechat-tab svg {
1276
+ width: 16px;
1277
+ height: 16px;
1278
+ }
1279
+
1280
+ .pp-prechat-field {
1281
+ margin-bottom: 16px;
1282
+ }
1283
+
1284
+ .pp-prechat-label {
1285
+ display: block;
1286
+ font-size: 12px;
1287
+ font-weight: 500;
1288
+ color: ${colors.textSecondary};
1289
+ margin-bottom: 6px;
1290
+ }
1291
+
1292
+ .pp-prechat-input {
1293
+ width: 100%;
1294
+ height: 44px;
1295
+ padding: 0 14px;
1296
+ border: 1px solid ${colors.border};
1297
+ border-radius: 8px;
1298
+ background: ${colors.bg};
1299
+ color: ${colors.text};
1300
+ font-size: 14px;
1301
+ outline: none;
1302
+ transition: border-color 0.2s;
1303
+ box-sizing: border-box;
1304
+ }
1305
+
1306
+ .pp-prechat-input:focus {
1307
+ border-color: ${primaryColor};
1308
+ }
1309
+
1310
+ .pp-prechat-input::placeholder {
1311
+ color: ${colors.textSecondary};
1312
+ }
1313
+
1314
+ .pp-prechat-input.error {
1315
+ border-color: #ef4444;
1316
+ }
1317
+
1318
+ .pp-prechat-error {
1319
+ color: #ef4444;
1320
+ font-size: 12px;
1321
+ margin-top: 4px;
1322
+ }
1323
+
1324
+ .pp-phone-input-wrapper {
1325
+ display: flex;
1326
+ gap: 8px;
1327
+ }
1328
+
1329
+ .pp-country-select {
1330
+ position: relative;
1331
+ }
1332
+
1333
+ .pp-country-btn {
1334
+ display: flex;
1335
+ align-items: center;
1336
+ gap: 6px;
1337
+ height: 44px;
1338
+ padding: 0 10px;
1339
+ border: 1px solid ${colors.border};
1340
+ border-radius: 8px;
1341
+ background: ${colors.bg};
1342
+ color: ${colors.text};
1343
+ font-size: 14px;
1344
+ cursor: pointer;
1345
+ transition: border-color 0.2s;
1346
+ }
1347
+
1348
+ .pp-country-btn:focus {
1349
+ border-color: ${primaryColor};
1350
+ outline: none;
1351
+ }
1352
+
1353
+ .pp-country-flag {
1354
+ font-size: 18px;
1355
+ line-height: 1;
1356
+ }
1357
+
1358
+ .pp-country-code {
1359
+ font-size: 13px;
1360
+ color: ${colors.textSecondary};
1361
+ }
1362
+
1363
+ .pp-country-chevron {
1364
+ width: 12px;
1365
+ height: 12px;
1366
+ color: ${colors.textSecondary};
1367
+ }
1368
+
1369
+ .pp-country-dropdown {
1370
+ position: absolute;
1371
+ top: calc(100% + 4px);
1372
+ left: 0;
1373
+ width: 280px;
1374
+ max-height: 280px;
1375
+ overflow-y: auto;
1376
+ background: ${colors.bg};
1377
+ border: 1px solid ${colors.border};
1378
+ border-radius: 8px;
1379
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1380
+ z-index: 100;
1381
+ }
1382
+
1383
+ .pp-country-search {
1384
+ position: sticky;
1385
+ top: 0;
1386
+ padding: 8px;
1387
+ background: ${colors.bg};
1388
+ border-bottom: 1px solid ${colors.border};
1389
+ }
1390
+
1391
+ .pp-country-search-input {
1392
+ width: 100%;
1393
+ height: 36px;
1394
+ padding: 0 12px;
1395
+ border: 1px solid ${colors.border};
1396
+ border-radius: 6px;
1397
+ background: ${colors.bgSecondary};
1398
+ color: ${colors.text};
1399
+ font-size: 13px;
1400
+ outline: none;
1401
+ box-sizing: border-box;
1402
+ }
1403
+
1404
+ .pp-country-search-input:focus {
1405
+ border-color: ${primaryColor};
1406
+ }
1407
+
1408
+ .pp-country-list {
1409
+ padding: 4px;
1410
+ }
1411
+
1412
+ .pp-country-option {
1413
+ display: flex;
1414
+ align-items: center;
1415
+ gap: 10px;
1416
+ padding: 10px 12px;
1417
+ cursor: pointer;
1418
+ border-radius: 6px;
1419
+ transition: background 0.15s;
1420
+ }
1421
+
1422
+ .pp-country-option:hover {
1423
+ background: ${colors.bgSecondary};
1424
+ }
1425
+
1426
+ .pp-country-option.selected {
1427
+ background: ${primaryColor}15;
1428
+ }
1429
+
1430
+ .pp-country-name {
1431
+ flex: 1;
1432
+ font-size: 13px;
1433
+ color: ${colors.text};
1434
+ }
1435
+
1436
+ .pp-country-dial {
1437
+ font-size: 12px;
1438
+ color: ${colors.textSecondary};
1439
+ }
1440
+
1441
+ .pp-phone-number-input {
1442
+ flex: 1;
1443
+ }
1444
+
1445
+ .pp-prechat-submit {
1446
+ width: 100%;
1447
+ height: 44px;
1448
+ margin-top: 8px;
1449
+ border: none;
1450
+ border-radius: 8px;
1451
+ background: ${primaryColor};
1452
+ color: white;
1453
+ font-size: 14px;
1454
+ font-weight: 500;
1455
+ cursor: pointer;
1456
+ transition: opacity 0.2s, transform 0.1s;
1457
+ }
1458
+
1459
+ .pp-prechat-submit:hover:not(:disabled) {
1460
+ opacity: 0.9;
1461
+ }
1462
+
1463
+ .pp-prechat-submit:active:not(:disabled) {
1464
+ transform: scale(0.98);
1465
+ }
1466
+
1467
+ .pp-prechat-submit:disabled {
1468
+ opacity: 0.5;
1469
+ cursor: not-allowed;
1470
+ }
1471
+
1472
+ .pp-prechat-skip {
1473
+ width: 100%;
1474
+ padding: 12px;
1475
+ margin-top: 8px;
1476
+ border: none;
1477
+ background: transparent;
1478
+ color: ${colors.textSecondary};
1479
+ font-size: 13px;
1480
+ cursor: pointer;
1481
+ transition: color 0.2s;
1482
+ }
1483
+
1484
+ .pp-prechat-skip:hover {
1485
+ color: ${colors.text};
1486
+ }
1111
1487
  `;
1112
1488
  }
1113
1489
 
1114
- // src/components/ChatWidget.tsx
1490
+ // src/components/PreChatForm.tsx
1491
+ var import_hooks = require("preact/hooks");
1492
+ var import_min = require("libphonenumber-js/min");
1493
+
1494
+ // src/data/countries.ts
1495
+ var countries = [
1496
+ // Europe
1497
+ { code: "FR", name: "France", dialCode: "+33", flag: "\u{1F1EB}\u{1F1F7}" },
1498
+ { code: "DE", name: "Germany", dialCode: "+49", flag: "\u{1F1E9}\u{1F1EA}" },
1499
+ { code: "GB", name: "United Kingdom", dialCode: "+44", flag: "\u{1F1EC}\u{1F1E7}" },
1500
+ { code: "ES", name: "Spain", dialCode: "+34", flag: "\u{1F1EA}\u{1F1F8}" },
1501
+ { code: "IT", name: "Italy", dialCode: "+39", flag: "\u{1F1EE}\u{1F1F9}" },
1502
+ { code: "PT", name: "Portugal", dialCode: "+351", flag: "\u{1F1F5}\u{1F1F9}" },
1503
+ { code: "NL", name: "Netherlands", dialCode: "+31", flag: "\u{1F1F3}\u{1F1F1}" },
1504
+ { code: "BE", name: "Belgium", dialCode: "+32", flag: "\u{1F1E7}\u{1F1EA}" },
1505
+ { code: "CH", name: "Switzerland", dialCode: "+41", flag: "\u{1F1E8}\u{1F1ED}" },
1506
+ { code: "AT", name: "Austria", dialCode: "+43", flag: "\u{1F1E6}\u{1F1F9}" },
1507
+ { code: "SE", name: "Sweden", dialCode: "+46", flag: "\u{1F1F8}\u{1F1EA}" },
1508
+ { code: "NO", name: "Norway", dialCode: "+47", flag: "\u{1F1F3}\u{1F1F4}" },
1509
+ { code: "DK", name: "Denmark", dialCode: "+45", flag: "\u{1F1E9}\u{1F1F0}" },
1510
+ { code: "FI", name: "Finland", dialCode: "+358", flag: "\u{1F1EB}\u{1F1EE}" },
1511
+ { code: "PL", name: "Poland", dialCode: "+48", flag: "\u{1F1F5}\u{1F1F1}" },
1512
+ { code: "CZ", name: "Czech Republic", dialCode: "+420", flag: "\u{1F1E8}\u{1F1FF}" },
1513
+ { code: "GR", name: "Greece", dialCode: "+30", flag: "\u{1F1EC}\u{1F1F7}" },
1514
+ { code: "IE", name: "Ireland", dialCode: "+353", flag: "\u{1F1EE}\u{1F1EA}" },
1515
+ { code: "RO", name: "Romania", dialCode: "+40", flag: "\u{1F1F7}\u{1F1F4}" },
1516
+ { code: "HU", name: "Hungary", dialCode: "+36", flag: "\u{1F1ED}\u{1F1FA}" },
1517
+ // North America
1518
+ { code: "US", name: "United States", dialCode: "+1", flag: "\u{1F1FA}\u{1F1F8}" },
1519
+ { code: "CA", name: "Canada", dialCode: "+1", flag: "\u{1F1E8}\u{1F1E6}" },
1520
+ { code: "MX", name: "Mexico", dialCode: "+52", flag: "\u{1F1F2}\u{1F1FD}" },
1521
+ // South America
1522
+ { code: "BR", name: "Brazil", dialCode: "+55", flag: "\u{1F1E7}\u{1F1F7}" },
1523
+ { code: "AR", name: "Argentina", dialCode: "+54", flag: "\u{1F1E6}\u{1F1F7}" },
1524
+ { code: "CL", name: "Chile", dialCode: "+56", flag: "\u{1F1E8}\u{1F1F1}" },
1525
+ { code: "CO", name: "Colombia", dialCode: "+57", flag: "\u{1F1E8}\u{1F1F4}" },
1526
+ { code: "PE", name: "Peru", dialCode: "+51", flag: "\u{1F1F5}\u{1F1EA}" },
1527
+ // Asia
1528
+ { code: "CN", name: "China", dialCode: "+86", flag: "\u{1F1E8}\u{1F1F3}" },
1529
+ { code: "JP", name: "Japan", dialCode: "+81", flag: "\u{1F1EF}\u{1F1F5}" },
1530
+ { code: "KR", name: "South Korea", dialCode: "+82", flag: "\u{1F1F0}\u{1F1F7}" },
1531
+ { code: "IN", name: "India", dialCode: "+91", flag: "\u{1F1EE}\u{1F1F3}" },
1532
+ { code: "ID", name: "Indonesia", dialCode: "+62", flag: "\u{1F1EE}\u{1F1E9}" },
1533
+ { code: "TH", name: "Thailand", dialCode: "+66", flag: "\u{1F1F9}\u{1F1ED}" },
1534
+ { code: "VN", name: "Vietnam", dialCode: "+84", flag: "\u{1F1FB}\u{1F1F3}" },
1535
+ { code: "MY", name: "Malaysia", dialCode: "+60", flag: "\u{1F1F2}\u{1F1FE}" },
1536
+ { code: "SG", name: "Singapore", dialCode: "+65", flag: "\u{1F1F8}\u{1F1EC}" },
1537
+ { code: "PH", name: "Philippines", dialCode: "+63", flag: "\u{1F1F5}\u{1F1ED}" },
1538
+ { code: "PK", name: "Pakistan", dialCode: "+92", flag: "\u{1F1F5}\u{1F1F0}" },
1539
+ { code: "BD", name: "Bangladesh", dialCode: "+880", flag: "\u{1F1E7}\u{1F1E9}" },
1540
+ // Middle East
1541
+ { code: "AE", name: "United Arab Emirates", dialCode: "+971", flag: "\u{1F1E6}\u{1F1EA}" },
1542
+ { code: "SA", name: "Saudi Arabia", dialCode: "+966", flag: "\u{1F1F8}\u{1F1E6}" },
1543
+ { code: "IL", name: "Israel", dialCode: "+972", flag: "\u{1F1EE}\u{1F1F1}" },
1544
+ { code: "TR", name: "Turkey", dialCode: "+90", flag: "\u{1F1F9}\u{1F1F7}" },
1545
+ { code: "EG", name: "Egypt", dialCode: "+20", flag: "\u{1F1EA}\u{1F1EC}" },
1546
+ // Africa
1547
+ { code: "ZA", name: "South Africa", dialCode: "+27", flag: "\u{1F1FF}\u{1F1E6}" },
1548
+ { code: "NG", name: "Nigeria", dialCode: "+234", flag: "\u{1F1F3}\u{1F1EC}" },
1549
+ { code: "KE", name: "Kenya", dialCode: "+254", flag: "\u{1F1F0}\u{1F1EA}" },
1550
+ { code: "MA", name: "Morocco", dialCode: "+212", flag: "\u{1F1F2}\u{1F1E6}" },
1551
+ { code: "TN", name: "Tunisia", dialCode: "+216", flag: "\u{1F1F9}\u{1F1F3}" },
1552
+ { code: "DZ", name: "Algeria", dialCode: "+213", flag: "\u{1F1E9}\u{1F1FF}" },
1553
+ // Oceania
1554
+ { code: "AU", name: "Australia", dialCode: "+61", flag: "\u{1F1E6}\u{1F1FA}" },
1555
+ { code: "NZ", name: "New Zealand", dialCode: "+64", flag: "\u{1F1F3}\u{1F1FF}" },
1556
+ // Russia & CIS
1557
+ { code: "RU", name: "Russia", dialCode: "+7", flag: "\u{1F1F7}\u{1F1FA}" },
1558
+ { code: "UA", name: "Ukraine", dialCode: "+380", flag: "\u{1F1FA}\u{1F1E6}" }
1559
+ ].sort((a, b) => a.name.localeCompare(b.name));
1560
+ function findCountryByCode(code) {
1561
+ return countries.find((c) => c.code === code.toUpperCase());
1562
+ }
1563
+ var defaultCountry = findCountryByCode("FR");
1564
+
1565
+ // src/components/PreChatForm.tsx
1115
1566
  var import_jsx_runtime = require("preact/jsx-runtime");
1567
+ var EmailIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1568
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "2", y: "4", width: "20", height: "16", rx: "2" }),
1569
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M22 7l-10 7L2 7" })
1570
+ ] });
1571
+ var PhoneIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.67A2 2 0 014.11 2h3a2 2 0 012 1.72 12.84 12.84 0 00.7 2.81 2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45 12.84 12.84 0 002.81.7A2 2 0 0122 16.92z" }) });
1572
+ var ChevronIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 9l6 6 6-6" }) });
1573
+ function isValidEmail(email) {
1574
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
1575
+ }
1576
+ function PreChatForm({ client: client2, config, onComplete, onSkip }) {
1577
+ const showEmailOnly = config.fields === "email-only";
1578
+ const showPhoneOnly = config.fields === "phone-only";
1579
+ const showBoth = config.fields === "email-and-phone";
1580
+ const showChoice = config.fields === "email-or-phone";
1581
+ const getDefaultTab = () => {
1582
+ if (showPhoneOnly) return "phone";
1583
+ return "email";
1584
+ };
1585
+ const [activeTab, setActiveTab] = (0, import_hooks.useState)(getDefaultTab());
1586
+ const [email, setEmail] = (0, import_hooks.useState)("");
1587
+ const [phone, setPhone] = (0, import_hooks.useState)("");
1588
+ const [selectedCountry, setSelectedCountry] = (0, import_hooks.useState)(defaultCountry);
1589
+ const [isCountryDropdownOpen, setIsCountryDropdownOpen] = (0, import_hooks.useState)(false);
1590
+ const [countrySearch, setCountrySearch] = (0, import_hooks.useState)("");
1591
+ const [emailError, setEmailError] = (0, import_hooks.useState)("");
1592
+ const [phoneError, setPhoneError] = (0, import_hooks.useState)("");
1593
+ const [isSubmitting, setIsSubmitting] = (0, import_hooks.useState)(false);
1594
+ const countryDropdownRef = (0, import_hooks.useRef)(null);
1595
+ const searchInputRef = (0, import_hooks.useRef)(null);
1596
+ (0, import_hooks.useEffect)(() => {
1597
+ const handleClickOutside = (e) => {
1598
+ if (countryDropdownRef.current && !countryDropdownRef.current.contains(e.target)) {
1599
+ setIsCountryDropdownOpen(false);
1600
+ }
1601
+ };
1602
+ document.addEventListener("mousedown", handleClickOutside);
1603
+ return () => document.removeEventListener("mousedown", handleClickOutside);
1604
+ }, []);
1605
+ (0, import_hooks.useEffect)(() => {
1606
+ if (isCountryDropdownOpen && searchInputRef.current) {
1607
+ searchInputRef.current.focus();
1608
+ }
1609
+ }, [isCountryDropdownOpen]);
1610
+ const filteredCountries = countries.filter(
1611
+ (c) => c.name.toLowerCase().includes(countrySearch.toLowerCase()) || c.dialCode.includes(countrySearch) || c.code.toLowerCase().includes(countrySearch.toLowerCase())
1612
+ );
1613
+ const handleCountrySelect = (country) => {
1614
+ setSelectedCountry(country);
1615
+ setIsCountryDropdownOpen(false);
1616
+ setCountrySearch("");
1617
+ };
1618
+ const formatPhoneForDisplay = (value) => {
1619
+ const digits = value.replace(/\D/g, "");
1620
+ return digits;
1621
+ };
1622
+ const handlePhoneChange = (e) => {
1623
+ const target = e.target;
1624
+ const formatted = formatPhoneForDisplay(target.value);
1625
+ setPhone(formatted);
1626
+ setPhoneError("");
1627
+ };
1628
+ const getFullPhoneNumber = () => {
1629
+ if (!phone) return "";
1630
+ return `${selectedCountry.dialCode}${phone}`;
1631
+ };
1632
+ const validateForm = () => {
1633
+ let valid = true;
1634
+ if (showEmailOnly || showBoth) {
1635
+ if (!email.trim()) {
1636
+ setEmailError("Email is required");
1637
+ valid = false;
1638
+ } else if (!isValidEmail(email)) {
1639
+ setEmailError("Please enter a valid email");
1640
+ valid = false;
1641
+ }
1642
+ }
1643
+ if (showPhoneOnly || showBoth) {
1644
+ const fullPhone = getFullPhoneNumber();
1645
+ if (!phone.trim()) {
1646
+ setPhoneError("Phone number is required");
1647
+ valid = false;
1648
+ } else if (!(0, import_min.isValidPhoneNumber)(fullPhone, selectedCountry.code)) {
1649
+ setPhoneError("Please enter a valid phone number");
1650
+ valid = false;
1651
+ }
1652
+ }
1653
+ if (showChoice) {
1654
+ if (activeTab === "email") {
1655
+ if (!email.trim()) {
1656
+ setEmailError("Email is required");
1657
+ valid = false;
1658
+ } else if (!isValidEmail(email)) {
1659
+ setEmailError("Please enter a valid email");
1660
+ valid = false;
1661
+ }
1662
+ } else {
1663
+ const fullPhone = getFullPhoneNumber();
1664
+ if (!phone.trim()) {
1665
+ setPhoneError("Phone number is required");
1666
+ valid = false;
1667
+ } else if (!(0, import_min.isValidPhoneNumber)(fullPhone, selectedCountry.code)) {
1668
+ setPhoneError("Please enter a valid phone number");
1669
+ valid = false;
1670
+ }
1671
+ }
1672
+ }
1673
+ return valid;
1674
+ };
1675
+ const handleSubmit = async (e) => {
1676
+ e.preventDefault();
1677
+ if (!validateForm()) return;
1678
+ setIsSubmitting(true);
1679
+ try {
1680
+ const data = {};
1681
+ if (showEmailOnly || showBoth || showChoice && activeTab === "email") {
1682
+ data.email = email.trim();
1683
+ }
1684
+ if (showPhoneOnly || showBoth || showChoice && activeTab === "phone") {
1685
+ const fullPhone = getFullPhoneNumber();
1686
+ const parsed = (0, import_min.parsePhoneNumber)(fullPhone, selectedCountry.code);
1687
+ if (parsed) {
1688
+ data.phone = parsed.format("E.164");
1689
+ data.phoneCountry = selectedCountry.code;
1690
+ }
1691
+ }
1692
+ await client2.submitPreChat(data);
1693
+ onComplete();
1694
+ } catch (err) {
1695
+ console.error("[PreChatForm] Submit error:", err);
1696
+ if (activeTab === "email" || showEmailOnly || showBoth) {
1697
+ setEmailError("Something went wrong. Please try again.");
1698
+ } else {
1699
+ setPhoneError("Something went wrong. Please try again.");
1700
+ }
1701
+ } finally {
1702
+ setIsSubmitting(false);
1703
+ }
1704
+ };
1705
+ const renderEmailField = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-prechat-field", children: [
1706
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { class: "pp-prechat-label", children: "Email address" }),
1707
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1708
+ "input",
1709
+ {
1710
+ type: "email",
1711
+ class: `pp-prechat-input ${emailError ? "error" : ""}`,
1712
+ placeholder: "you@example.com",
1713
+ value: email,
1714
+ onInput: (e) => {
1715
+ setEmail(e.target.value);
1716
+ setEmailError("");
1717
+ }
1718
+ }
1719
+ ),
1720
+ emailError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-prechat-error", children: emailError })
1721
+ ] });
1722
+ const renderPhoneField = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-prechat-field", children: [
1723
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { class: "pp-prechat-label", children: "Phone number" }),
1724
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-phone-input-wrapper", children: [
1725
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-country-select", ref: countryDropdownRef, children: [
1726
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1727
+ "button",
1728
+ {
1729
+ type: "button",
1730
+ class: "pp-country-btn",
1731
+ onClick: () => setIsCountryDropdownOpen(!isCountryDropdownOpen),
1732
+ children: [
1733
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-country-flag", children: selectedCountry.flag }),
1734
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-country-code", children: selectedCountry.dialCode }),
1735
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronIcon, {})
1736
+ ]
1737
+ }
1738
+ ),
1739
+ isCountryDropdownOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-country-dropdown", children: [
1740
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-country-search", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1741
+ "input",
1742
+ {
1743
+ ref: searchInputRef,
1744
+ type: "text",
1745
+ class: "pp-country-search-input",
1746
+ placeholder: "Search country...",
1747
+ value: countrySearch,
1748
+ onInput: (e) => setCountrySearch(e.target.value)
1749
+ }
1750
+ ) }),
1751
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-country-list", children: filteredCountries.map((country) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1752
+ "div",
1753
+ {
1754
+ class: `pp-country-option ${country.code === selectedCountry.code ? "selected" : ""}`,
1755
+ onClick: () => handleCountrySelect(country),
1756
+ children: [
1757
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-country-flag", children: country.flag }),
1758
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-country-name", children: country.name }),
1759
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-country-dial", children: country.dialCode })
1760
+ ]
1761
+ },
1762
+ country.code
1763
+ )) })
1764
+ ] })
1765
+ ] }),
1766
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1767
+ "input",
1768
+ {
1769
+ type: "tel",
1770
+ class: `pp-prechat-input pp-phone-number-input ${phoneError ? "error" : ""}`,
1771
+ placeholder: "612 345 678",
1772
+ value: phone,
1773
+ onInput: handlePhoneChange
1774
+ }
1775
+ )
1776
+ ] }),
1777
+ phoneError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-prechat-error", children: phoneError })
1778
+ ] });
1779
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-prechat", children: [
1780
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { class: "pp-prechat-title", children: "How can we reach you?" }),
1781
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { class: "pp-prechat-subtitle", children: showBoth ? "Please provide your contact information so we can follow up if needed." : showChoice ? "Choose how you would like us to contact you." : showEmailOnly ? "Enter your email so we can follow up with you." : "Enter your phone number so we can call you back." }),
1782
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: handleSubmit, children: [
1783
+ showChoice && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-prechat-tabs", children: [
1784
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1785
+ "button",
1786
+ {
1787
+ type: "button",
1788
+ class: `pp-prechat-tab ${activeTab === "email" ? "active" : ""}`,
1789
+ onClick: () => {
1790
+ setActiveTab("email");
1791
+ setPhoneError("");
1792
+ },
1793
+ children: [
1794
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmailIcon, {}),
1795
+ "Email"
1796
+ ]
1797
+ }
1798
+ ),
1799
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1800
+ "button",
1801
+ {
1802
+ type: "button",
1803
+ class: `pp-prechat-tab ${activeTab === "phone" ? "active" : ""}`,
1804
+ onClick: () => {
1805
+ setActiveTab("phone");
1806
+ setEmailError("");
1807
+ },
1808
+ children: [
1809
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PhoneIcon, {}),
1810
+ "Phone"
1811
+ ]
1812
+ }
1813
+ )
1814
+ ] }),
1815
+ showEmailOnly && renderEmailField(),
1816
+ showPhoneOnly && renderPhoneField(),
1817
+ showBoth && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1818
+ renderEmailField(),
1819
+ renderPhoneField()
1820
+ ] }),
1821
+ showChoice && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1822
+ activeTab === "email" && renderEmailField(),
1823
+ activeTab === "phone" && renderPhoneField()
1824
+ ] }),
1825
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "submit", class: "pp-prechat-submit", disabled: isSubmitting, children: isSubmitting ? "Submitting..." : "Start chatting" }),
1826
+ !config.required && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", class: "pp-prechat-skip", onClick: onSkip, children: "Skip for now" })
1827
+ ] })
1828
+ ] });
1829
+ }
1830
+
1831
+ // src/components/ChatWidget.tsx
1832
+ var import_jsx_runtime2 = require("preact/jsx-runtime");
1116
1833
  function formatDateSeparator(date) {
1117
1834
  const now = /* @__PURE__ */ new Date();
1118
1835
  const messageDate = new Date(date);
@@ -1132,28 +1849,33 @@ function getDateKey(date) {
1132
1849
  return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
1133
1850
  }
1134
1851
  function ChatWidget({ client: client2, config: initialConfig }) {
1135
- const [isOpen, setIsOpen] = (0, import_hooks.useState)(false);
1136
- const [messages, setMessages] = (0, import_hooks.useState)([]);
1137
- const [inputValue, setInputValue] = (0, import_hooks.useState)("");
1138
- const [isTyping, setIsTyping] = (0, import_hooks.useState)(false);
1139
- const [operatorOnline, setOperatorOnline] = (0, import_hooks.useState)(false);
1140
- const [isConnected, setIsConnected] = (0, import_hooks.useState)(false);
1141
- const [unreadCount, setUnreadCount] = (0, import_hooks.useState)(0);
1142
- const [pendingAttachments, setPendingAttachments] = (0, import_hooks.useState)([]);
1143
- const [isUploading, setIsUploading] = (0, import_hooks.useState)(false);
1144
- const [replyingTo, setReplyingTo] = (0, import_hooks.useState)(null);
1145
- const [editingMessage, setEditingMessage] = (0, import_hooks.useState)(null);
1146
- const [editContent, setEditContent] = (0, import_hooks.useState)("");
1147
- const [messageMenu, setMessageMenu] = (0, import_hooks.useState)(null);
1148
- const [isDragging, setIsDragging] = (0, import_hooks.useState)(false);
1149
- const [hoveredMessageId, setHoveredMessageId] = (0, import_hooks.useState)(null);
1150
- const [longPressTimer, setLongPressTimer] = (0, import_hooks.useState)(null);
1151
- const [config, setConfig] = (0, import_hooks.useState)(initialConfig);
1152
- const messagesEndRef = (0, import_hooks.useRef)(null);
1153
- const inputRef = (0, import_hooks.useRef)(null);
1154
- const fileInputRef = (0, import_hooks.useRef)(null);
1155
- const messagesContainerRef = (0, import_hooks.useRef)(null);
1156
- (0, import_hooks.useEffect)(() => {
1852
+ const [isOpen, setIsOpen] = (0, import_hooks2.useState)(false);
1853
+ const [messages, setMessages] = (0, import_hooks2.useState)([]);
1854
+ const [inputValue, setInputValue] = (0, import_hooks2.useState)("");
1855
+ const [isTyping, setIsTyping] = (0, import_hooks2.useState)(false);
1856
+ const [operatorOnline, setOperatorOnline] = (0, import_hooks2.useState)(false);
1857
+ const [isConnected, setIsConnected] = (0, import_hooks2.useState)(false);
1858
+ const [unreadCount, setUnreadCount] = (0, import_hooks2.useState)(0);
1859
+ const [pendingAttachments, setPendingAttachments] = (0, import_hooks2.useState)([]);
1860
+ const [isUploading, setIsUploading] = (0, import_hooks2.useState)(false);
1861
+ const [replyingTo, setReplyingTo] = (0, import_hooks2.useState)(null);
1862
+ const [editingMessage, setEditingMessage] = (0, import_hooks2.useState)(null);
1863
+ const [editContent, setEditContent] = (0, import_hooks2.useState)("");
1864
+ const [messageMenu, setMessageMenu] = (0, import_hooks2.useState)(null);
1865
+ const [isDragging, setIsDragging] = (0, import_hooks2.useState)(false);
1866
+ const [hoveredMessageId, setHoveredMessageId] = (0, import_hooks2.useState)(null);
1867
+ const [longPressTimer, setLongPressTimer] = (0, import_hooks2.useState)(null);
1868
+ const [swipedMessageId, setSwipedMessageId] = (0, import_hooks2.useState)(null);
1869
+ const [swipeOffset, setSwipeOffset] = (0, import_hooks2.useState)(0);
1870
+ const touchStartRef = (0, import_hooks2.useRef)(null);
1871
+ const [config, setConfig] = (0, import_hooks2.useState)(initialConfig);
1872
+ const [preChatForm, setPreChatForm] = (0, import_hooks2.useState)(void 0);
1873
+ const [preChatSkipped, setPreChatSkipped] = (0, import_hooks2.useState)(false);
1874
+ const messagesEndRef = (0, import_hooks2.useRef)(null);
1875
+ const inputRef = (0, import_hooks2.useRef)(null);
1876
+ const fileInputRef = (0, import_hooks2.useRef)(null);
1877
+ const messagesContainerRef = (0, import_hooks2.useRef)(null);
1878
+ (0, import_hooks2.useEffect)(() => {
1157
1879
  const unsubOpen = client2.on("openChange", setIsOpen);
1158
1880
  const unsubMessage = client2.on("message", () => {
1159
1881
  setMessages([...client2.getMessages()]);
@@ -1169,6 +1891,10 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1169
1891
  setMessages(client2.getMessages());
1170
1892
  setOperatorOnline(client2.getSession()?.operatorOnline ?? false);
1171
1893
  setConfig(client2.getConfig());
1894
+ setPreChatForm(client2.getSession()?.preChatForm);
1895
+ });
1896
+ const unsubPreChat = client2.on("preChatCompleted", () => {
1897
+ setPreChatForm((prev) => prev ? { ...prev, completed: true } : prev);
1172
1898
  });
1173
1899
  const unsubConfig = client2.on("configUpdate", () => {
1174
1900
  setConfig(client2.getConfig());
@@ -1178,6 +1904,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1178
1904
  setMessages(client2.getMessages());
1179
1905
  setOperatorOnline(client2.getSession()?.operatorOnline ?? false);
1180
1906
  setConfig(client2.getConfig());
1907
+ setPreChatForm(client2.getSession()?.preChatForm);
1181
1908
  }
1182
1909
  return () => {
1183
1910
  unsubOpen();
@@ -1185,15 +1912,16 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1185
1912
  unsubTyping();
1186
1913
  unsubPresence();
1187
1914
  unsubConnect();
1915
+ unsubPreChat();
1188
1916
  unsubConfig();
1189
1917
  };
1190
1918
  }, [client2]);
1191
- (0, import_hooks.useEffect)(() => {
1919
+ (0, import_hooks2.useEffect)(() => {
1192
1920
  if (isOpen) {
1193
1921
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
1194
1922
  }
1195
1923
  }, [messages, isOpen]);
1196
- (0, import_hooks.useEffect)(() => {
1924
+ (0, import_hooks2.useEffect)(() => {
1197
1925
  if (isOpen) {
1198
1926
  setTimeout(() => {
1199
1927
  messagesEndRef.current?.scrollIntoView({ behavior: "auto" });
@@ -1202,7 +1930,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1202
1930
  setUnreadCount(0);
1203
1931
  }
1204
1932
  }, [isOpen]);
1205
- (0, import_hooks.useEffect)(() => {
1933
+ (0, import_hooks2.useEffect)(() => {
1206
1934
  if (!isOpen && messages.length > 0) {
1207
1935
  const unread = messages.filter(
1208
1936
  (msg) => msg.sender !== "visitor" && msg.status !== "read"
@@ -1210,7 +1938,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1210
1938
  setUnreadCount(unread);
1211
1939
  }
1212
1940
  }, [messages, isOpen]);
1213
- const markMessagesAsRead = (0, import_hooks.useCallback)(() => {
1941
+ const markMessagesAsRead = (0, import_hooks2.useCallback)(() => {
1214
1942
  if (!isOpen || !isConnected) return;
1215
1943
  const unreadMessages = messages.filter(
1216
1944
  (msg) => msg.sender !== "visitor" && msg.status !== "read"
@@ -1220,14 +1948,14 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1220
1948
  client2.sendReadStatus(messageIds, "read");
1221
1949
  }
1222
1950
  }, [isOpen, isConnected, messages, client2]);
1223
- (0, import_hooks.useEffect)(() => {
1951
+ (0, import_hooks2.useEffect)(() => {
1224
1952
  if (!isOpen || !isConnected) return;
1225
1953
  const timer = setTimeout(() => {
1226
1954
  markMessagesAsRead();
1227
1955
  }, 1e3);
1228
1956
  return () => clearTimeout(timer);
1229
1957
  }, [isOpen, isConnected, messages, markMessagesAsRead]);
1230
- (0, import_hooks.useEffect)(() => {
1958
+ (0, import_hooks2.useEffect)(() => {
1231
1959
  const handleVisibilityChange = () => {
1232
1960
  if (document.visibilityState === "visible" && isOpen) {
1233
1961
  markMessagesAsRead();
@@ -1236,7 +1964,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1236
1964
  document.addEventListener("visibilitychange", handleVisibilityChange);
1237
1965
  return () => document.removeEventListener("visibilitychange", handleVisibilityChange);
1238
1966
  }, [isOpen, markMessagesAsRead]);
1239
- (0, import_hooks.useEffect)(() => {
1967
+ (0, import_hooks2.useEffect)(() => {
1240
1968
  const unsubRead = client2.on(
1241
1969
  "read",
1242
1970
  () => {
@@ -1375,26 +2103,43 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1375
2103
  y: mouseEvent.clientY
1376
2104
  });
1377
2105
  };
1378
- const handleTouchStart = (message) => {
1379
- const timer = setTimeout(() => {
1380
- if (navigator.vibrate) navigator.vibrate(50);
1381
- setMessageMenu({
1382
- message,
1383
- x: window.innerWidth / 2 - 60,
1384
- // Center horizontally
1385
- y: window.innerHeight / 2 - 50
1386
- // Center vertically
1387
- });
1388
- }, 500);
1389
- setLongPressTimer(timer);
2106
+ const handleTouchStart = (e, message) => {
2107
+ const touch = e.touches[0];
2108
+ touchStartRef.current = { x: touch.clientX, y: touch.clientY, time: Date.now() };
2109
+ if (swipedMessageId && swipedMessageId !== message.id) {
2110
+ setSwipedMessageId(null);
2111
+ setSwipeOffset(0);
2112
+ }
1390
2113
  };
1391
- const handleTouchEnd = () => {
1392
- if (longPressTimer) {
1393
- clearTimeout(longPressTimer);
1394
- setLongPressTimer(null);
2114
+ const handleTouchMove = (e, message) => {
2115
+ if (!touchStartRef.current) return;
2116
+ const touch = e.touches[0];
2117
+ const deltaX = touch.clientX - touchStartRef.current.x;
2118
+ const deltaY = touch.clientY - touchStartRef.current.y;
2119
+ if (Math.abs(deltaY) > Math.abs(deltaX)) return;
2120
+ if (deltaX < 0) {
2121
+ const offset = Math.max(deltaX, -100);
2122
+ setSwipeOffset(offset);
2123
+ setSwipedMessageId(message.id);
1395
2124
  }
1396
2125
  };
1397
- (0, import_hooks.useEffect)(() => {
2126
+ const handleTouchEnd = (message) => {
2127
+ if (!touchStartRef.current) return;
2128
+ const elapsed = Date.now() - touchStartRef.current.time;
2129
+ if (swipeOffset < -50 || swipeOffset < -20 && elapsed < 200) {
2130
+ setSwipeOffset(-80);
2131
+ if (navigator.vibrate) navigator.vibrate(30);
2132
+ } else {
2133
+ setSwipeOffset(0);
2134
+ setSwipedMessageId(null);
2135
+ }
2136
+ touchStartRef.current = null;
2137
+ };
2138
+ const resetSwipe = () => {
2139
+ setSwipedMessageId(null);
2140
+ setSwipeOffset(0);
2141
+ };
2142
+ (0, import_hooks2.useEffect)(() => {
1398
2143
  if (!messageMenu) return;
1399
2144
  const handleClickOutside = () => setMessageMenu(null);
1400
2145
  document.addEventListener("click", handleClickOutside);
@@ -1410,7 +2155,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1410
2155
  }, 1500);
1411
2156
  }
1412
2157
  };
1413
- const dragCounterRef = (0, import_hooks.useRef)(0);
2158
+ const dragCounterRef = (0, import_hooks2.useRef)(0);
1414
2159
  const handleDragEnter = (e) => {
1415
2160
  e.preventDefault();
1416
2161
  e.stopPropagation();
@@ -1486,22 +2231,24 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1486
2231
  const theme = getTheme(config.theme ?? "auto");
1487
2232
  const primaryColor = config.primaryColor ?? "#6366f1";
1488
2233
  const actionIconColor = theme === "dark" ? "#9ca3af" : "#6b7280";
1489
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_preact.Fragment, { children: [
1490
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: styles(primaryColor, theme) }),
1491
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2234
+ const shouldShowPreChat = preChatForm && preChatForm.enabled && !preChatForm.completed && !preChatSkipped && // Before first message: show immediately
2235
+ (preChatForm.timing === "before-first-message" && messages.length === 0 || preChatForm.timing === "after-first-message" && messages.some((m) => m.sender === "visitor"));
2236
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_preact.Fragment, { children: [
2237
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: styles(primaryColor, theme) }),
2238
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1492
2239
  "button",
1493
2240
  {
1494
2241
  class: `pp-toggle pp-${position}`,
1495
2242
  onClick: () => client2.toggleOpen(),
1496
2243
  "aria-label": isOpen ? "Close chat" : "Open chat",
1497
2244
  children: [
1498
- isOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChatIcon, {}),
1499
- !isOpen && unreadCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-unread-badge", children: unreadCount > 9 ? "9+" : unreadCount }),
1500
- !isOpen && unreadCount === 0 && operatorOnline && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-online-dot" })
2245
+ isOpen ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChatIcon, {}),
2246
+ !isOpen && unreadCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-unread-badge", children: unreadCount > 9 ? "9+" : unreadCount }),
2247
+ !isOpen && unreadCount === 0 && operatorOnline && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-online-dot" })
1501
2248
  ]
1502
2249
  }
1503
2250
  ),
1504
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2251
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1505
2252
  "div",
1506
2253
  {
1507
2254
  class: `pp-window pp-${position} pp-theme-${theme} ${isDragging ? "pp-dragging" : ""}`,
@@ -1510,36 +2257,49 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1510
2257
  onDragLeave: handleDragLeave,
1511
2258
  onDrop: handleDrop,
1512
2259
  children: [
1513
- isDragging && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-drop-overlay", children: [
1514
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-drop-icon", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AttachIcon, {}) }),
1515
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-drop-text", children: "Drop files to upload" })
2260
+ isDragging && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-drop-overlay", children: [
2261
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-drop-icon", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AttachIcon, {}) }),
2262
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-drop-text", children: "Drop files to upload" })
1516
2263
  ] }),
1517
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-header", children: [
1518
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-header-info", children: [
1519
- config.operatorAvatar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: config.operatorAvatar, alt: "", class: "pp-avatar" }),
1520
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
1521
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-header-title", children: config.operatorName ?? "Support" }),
1522
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-header-status", children: operatorOnline ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1523
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-status-dot pp-online" }),
2264
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-header", children: [
2265
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-header-info", children: [
2266
+ config.operatorAvatar && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { src: config.operatorAvatar, alt: "", class: "pp-avatar" }),
2267
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
2268
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-header-title", children: config.operatorName ?? "Support" }),
2269
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-header-status", children: operatorOnline ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2270
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-status-dot pp-online" }),
1524
2271
  " Online"
1525
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1526
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-status-dot" }),
2272
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2273
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-status-dot" }),
1527
2274
  " Away"
1528
2275
  ] }) })
1529
2276
  ] })
1530
2277
  ] }),
1531
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2278
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1532
2279
  "button",
1533
2280
  {
1534
2281
  class: "pp-close-btn",
1535
2282
  onClick: () => client2.setOpen(false),
1536
2283
  "aria-label": "Close chat",
1537
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {})
2284
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CloseIcon, {})
1538
2285
  }
1539
2286
  )
1540
2287
  ] }),
1541
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-messages", ref: messagesContainerRef, children: [
1542
- config.welcomeMessage && messages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-welcome", children: config.welcomeMessage }),
2288
+ shouldShowPreChat && preChatForm && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2289
+ PreChatForm,
2290
+ {
2291
+ client: client2,
2292
+ config: preChatForm,
2293
+ onComplete: () => {
2294
+ setPreChatForm((prev) => prev ? { ...prev, completed: true } : prev);
2295
+ },
2296
+ onSkip: () => {
2297
+ setPreChatSkipped(true);
2298
+ }
2299
+ }
2300
+ ),
2301
+ !shouldShowPreChat && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-messages", ref: messagesContainerRef, onClick: () => swipedMessageId && resetSwipe(), children: [
2302
+ config.welcomeMessage && messages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-welcome", children: config.welcomeMessage }),
1543
2303
  messages.map((msg, index) => {
1544
2304
  const isDeleted = !!msg.deletedAt;
1545
2305
  const isEdited = !!msg.editedAt;
@@ -1567,125 +2327,168 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1567
2327
  }
1568
2328
  const isHovered = hoveredMessageId === msg.id;
1569
2329
  const showActions = isHovered && !isDeleted;
1570
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_preact.Fragment, { children: [
1571
- showDateSeparator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-date-separator", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: formatDateSeparator(msgDate) }) }),
1572
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1573
- "div",
1574
- {
1575
- id: `pp-msg-${msg.id}`,
1576
- class: `pp-message pp-message-${msg.sender} ${isDeleted ? "pp-message-deleted" : ""}`,
1577
- onContextMenu: (e) => handleMessageContextMenu(e, msg),
1578
- onMouseEnter: () => setHoveredMessageId(msg.id),
1579
- onMouseLeave: () => setHoveredMessageId(null),
1580
- onTouchStart: () => handleTouchStart(msg),
1581
- onTouchEnd: handleTouchEnd,
1582
- onTouchCancel: handleTouchEnd,
1583
- children: [
1584
- showActions && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: `pp-message-actions ${msg.sender === "visitor" ? "pp-actions-left" : "pp-actions-right"}`, children: [
1585
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1586
- "button",
1587
- {
1588
- class: "pp-action-btn",
1589
- onClick: () => handleReply(msg),
1590
- title: "Reply",
1591
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReplyIcon, { color: actionIconColor })
1592
- }
1593
- ),
1594
- msg.sender === "visitor" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1595
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2330
+ const isSwiped = swipedMessageId === msg.id;
2331
+ const msgSwipeOffset = isSwiped ? swipeOffset : 0;
2332
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_preact.Fragment, { children: [
2333
+ showDateSeparator && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-date-separator", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: formatDateSeparator(msgDate) }) }),
2334
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: `pp-message-swipe-container ${msg.sender === "visitor" ? "pp-swipe-left" : "pp-swipe-right"}`, children: [
2335
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-swipe-actions", children: [
2336
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2337
+ "button",
2338
+ {
2339
+ class: "pp-swipe-action pp-swipe-reply",
2340
+ onClick: () => {
2341
+ handleReply(msg);
2342
+ resetSwipe();
2343
+ },
2344
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReplyIcon, { color: "#fff" })
2345
+ }
2346
+ ),
2347
+ msg.sender === "visitor" && !isDeleted && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2348
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2349
+ "button",
2350
+ {
2351
+ class: "pp-swipe-action pp-swipe-edit",
2352
+ onClick: () => {
2353
+ handleStartEdit(msg);
2354
+ resetSwipe();
2355
+ },
2356
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EditIcon, { color: "#fff" })
2357
+ }
2358
+ ),
2359
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2360
+ "button",
2361
+ {
2362
+ class: "pp-swipe-action pp-swipe-delete",
2363
+ onClick: () => {
2364
+ handleDelete(msg);
2365
+ resetSwipe();
2366
+ },
2367
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DeleteIcon, { color: "#fff" })
2368
+ }
2369
+ )
2370
+ ] })
2371
+ ] }),
2372
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2373
+ "div",
2374
+ {
2375
+ id: `pp-msg-${msg.id}`,
2376
+ class: `pp-message pp-message-${msg.sender} ${isDeleted ? "pp-message-deleted" : ""}`,
2377
+ style: { transform: `translateX(${msgSwipeOffset}px)`, transition: touchStartRef.current ? "none" : "transform 0.2s ease-out" },
2378
+ onContextMenu: (e) => handleMessageContextMenu(e, msg),
2379
+ onMouseEnter: () => setHoveredMessageId(msg.id),
2380
+ onMouseLeave: () => setHoveredMessageId(null),
2381
+ onTouchStart: (e) => handleTouchStart(e, msg),
2382
+ onTouchMove: (e) => handleTouchMove(e, msg),
2383
+ onTouchEnd: () => handleTouchEnd(msg),
2384
+ onTouchCancel: () => handleTouchEnd(msg),
2385
+ children: [
2386
+ showActions && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: `pp-message-actions ${msg.sender === "visitor" ? "pp-actions-left" : "pp-actions-right"}`, children: [
2387
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1596
2388
  "button",
1597
2389
  {
1598
2390
  class: "pp-action-btn",
1599
- onClick: () => handleStartEdit(msg),
1600
- title: "Edit",
1601
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EditIcon, { color: actionIconColor })
2391
+ onClick: () => handleReply(msg),
2392
+ title: "Reply",
2393
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReplyIcon, { color: actionIconColor })
1602
2394
  }
1603
2395
  ),
1604
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1605
- "button",
1606
- {
1607
- class: "pp-action-btn pp-action-delete",
1608
- onClick: () => handleDelete(msg),
1609
- title: "Delete",
1610
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeleteIcon, { color: actionIconColor })
1611
- }
1612
- )
2396
+ msg.sender === "visitor" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2397
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2398
+ "button",
2399
+ {
2400
+ class: "pp-action-btn",
2401
+ onClick: () => handleStartEdit(msg),
2402
+ title: "Edit",
2403
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EditIcon, { color: actionIconColor })
2404
+ }
2405
+ ),
2406
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2407
+ "button",
2408
+ {
2409
+ class: "pp-action-btn pp-action-delete",
2410
+ onClick: () => handleDelete(msg),
2411
+ title: "Delete",
2412
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DeleteIcon, { color: actionIconColor })
2413
+ }
2414
+ )
2415
+ ] })
2416
+ ] }),
2417
+ replyData && (replyData.content || replyData.hasAttachment) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2418
+ "div",
2419
+ {
2420
+ class: "pp-reply-quote pp-reply-quote-clickable",
2421
+ onClick: () => scrollToMessage(replyData.id),
2422
+ role: "button",
2423
+ tabIndex: 0,
2424
+ onKeyDown: (e) => e.key === "Enter" && scrollToMessage(replyData.id),
2425
+ children: [
2426
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-reply-sender", children: replyData.sender === "visitor" ? "You" : "Support" }),
2427
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-reply-content", children: replyData.deleted ? "Message deleted" : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2428
+ replyData.hasAttachment && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-reply-attachment-icon", children: replyData.attachmentType?.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
2429
+ replyData.content ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2430
+ (replyData.content || "").slice(0, 50),
2431
+ (replyData.content || "").length > 50 ? "..." : ""
2432
+ ] }) : replyData.attachmentType?.startsWith("image/") ? "Photo" : "File"
2433
+ ] }) })
2434
+ ]
2435
+ }
2436
+ ),
2437
+ isDeleted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-message-content pp-deleted-content", children: [
2438
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-deleted-icon", children: "\u{1F5D1}\uFE0F" }),
2439
+ " Message deleted"
2440
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2441
+ msg.content && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-message-content", children: msg.content }),
2442
+ msg.attachments && msg.attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-message-attachments", children: msg.attachments.map((att) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AttachmentDisplay, { attachment: att }, att.id)) })
2443
+ ] }),
2444
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-message-time", children: [
2445
+ formatTime(msg.timestamp),
2446
+ isEdited && !isDeleted && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-edited-badge", children: "edited" }),
2447
+ msg.sender === "ai" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-ai-badge", children: "AI" }),
2448
+ msg.sender === "visitor" && !isDeleted && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: `pp-status pp-status-${msg.status ?? "sent"}`, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(StatusIcon, { status: msg.status }) })
1613
2449
  ] })
1614
- ] }),
1615
- replyData && (replyData.content || replyData.hasAttachment) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1616
- "div",
1617
- {
1618
- class: "pp-reply-quote pp-reply-quote-clickable",
1619
- onClick: () => scrollToMessage(replyData.id),
1620
- role: "button",
1621
- tabIndex: 0,
1622
- onKeyDown: (e) => e.key === "Enter" && scrollToMessage(replyData.id),
1623
- children: [
1624
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-reply-sender", children: replyData.sender === "visitor" ? "You" : "Support" }),
1625
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-reply-content", children: replyData.deleted ? "Message deleted" : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1626
- replyData.hasAttachment && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-reply-attachment-icon", children: replyData.attachmentType?.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
1627
- replyData.content ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1628
- (replyData.content || "").slice(0, 50),
1629
- (replyData.content || "").length > 50 ? "..." : ""
1630
- ] }) : replyData.attachmentType?.startsWith("image/") ? "Photo" : "File"
1631
- ] }) })
1632
- ]
1633
- }
1634
- ),
1635
- isDeleted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-message-content pp-deleted-content", children: [
1636
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-deleted-icon", children: "\u{1F5D1}\uFE0F" }),
1637
- " Message deleted"
1638
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1639
- msg.content && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-message-content", children: msg.content }),
1640
- msg.attachments && msg.attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-message-attachments", children: msg.attachments.map((att) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AttachmentDisplay, { attachment: att }, att.id)) })
1641
- ] }),
1642
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-message-time", children: [
1643
- formatTime(msg.timestamp),
1644
- isEdited && !isDeleted && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-edited-badge", children: "edited" }),
1645
- msg.sender === "ai" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-ai-badge", children: "AI" }),
1646
- msg.sender === "visitor" && !isDeleted && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: `pp-status pp-status-${msg.status ?? "sent"}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusIcon, { status: msg.status }) })
1647
- ] })
1648
- ]
1649
- }
1650
- )
2450
+ ]
2451
+ }
2452
+ )
2453
+ ] })
1651
2454
  ] }, msg.id);
1652
2455
  }),
1653
- isTyping && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-message pp-message-operator pp-typing", children: [
1654
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
1655
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
1656
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {})
2456
+ isTyping && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-message pp-message-operator pp-typing", children: [
2457
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {}),
2458
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {}),
2459
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {})
1657
2460
  ] }),
1658
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: messagesEndRef })
2461
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { ref: messagesEndRef })
1659
2462
  ] }),
1660
- messageMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2463
+ messageMenu && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1661
2464
  "div",
1662
2465
  {
1663
2466
  class: "pp-message-menu",
1664
2467
  style: { top: `${messageMenu.y}px`, left: `${messageMenu.x}px` },
1665
2468
  children: [
1666
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { onClick: () => handleReply(messageMenu.message), children: [
1667
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReplyIcon, { color: actionIconColor }),
2469
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { onClick: () => handleReply(messageMenu.message), children: [
2470
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReplyIcon, { color: actionIconColor }),
1668
2471
  " Reply"
1669
2472
  ] }),
1670
- messageMenu.message.sender === "visitor" && !messageMenu.message.deletedAt && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1671
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { onClick: () => handleStartEdit(messageMenu.message), children: [
1672
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EditIcon, { color: actionIconColor }),
2473
+ messageMenu.message.sender === "visitor" && !messageMenu.message.deletedAt && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2474
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { onClick: () => handleStartEdit(messageMenu.message), children: [
2475
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(EditIcon, { color: actionIconColor }),
1673
2476
  " Edit"
1674
2477
  ] }),
1675
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { class: "pp-menu-delete", onClick: () => handleDelete(messageMenu.message), children: [
1676
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeleteIcon, { color: "#ef4444" }),
2478
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("button", { class: "pp-menu-delete", onClick: () => handleDelete(messageMenu.message), children: [
2479
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(DeleteIcon, { color: "#ef4444" }),
1677
2480
  " Delete"
1678
2481
  ] })
1679
2482
  ] })
1680
2483
  ]
1681
2484
  }
1682
2485
  ),
1683
- editingMessage && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-edit-modal", children: [
1684
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-edit-header", children: [
1685
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Edit message" }),
1686
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: handleCancelEdit, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {}) })
2486
+ editingMessage && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-edit-modal", children: [
2487
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-edit-header", children: [
2488
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Edit message" }),
2489
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { onClick: handleCancelEdit, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CloseIcon, {}) })
1687
2490
  ] }),
1688
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2491
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1689
2492
  "textarea",
1690
2493
  {
1691
2494
  class: "pp-edit-input",
@@ -1694,41 +2497,41 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1694
2497
  autoFocus: true
1695
2498
  }
1696
2499
  ),
1697
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-edit-actions", children: [
1698
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { class: "pp-edit-cancel", onClick: handleCancelEdit, children: "Cancel" }),
1699
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { class: "pp-edit-save", onClick: handleSaveEdit, disabled: !editContent.trim(), children: "Save" })
2500
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-edit-actions", children: [
2501
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { class: "pp-edit-cancel", onClick: handleCancelEdit, children: "Cancel" }),
2502
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { class: "pp-edit-save", onClick: handleSaveEdit, disabled: !editContent.trim(), children: "Save" })
1700
2503
  ] })
1701
2504
  ] }),
1702
- replyingTo && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-reply-preview", children: [
1703
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-reply-preview-content", children: [
1704
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-reply-label", children: "Replying to" }),
1705
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { class: "pp-reply-text", children: [
1706
- replyingTo.attachments && replyingTo.attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-reply-attachment-icon", children: replyingTo.attachments[0].mimeType.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
1707
- replyingTo.content ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
2505
+ replyingTo && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-reply-preview", children: [
2506
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-reply-preview-content", children: [
2507
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-reply-label", children: "Replying to" }),
2508
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { class: "pp-reply-text", children: [
2509
+ replyingTo.attachments && replyingTo.attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-reply-attachment-icon", children: replyingTo.attachments[0].mimeType.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
2510
+ replyingTo.content ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1708
2511
  replyingTo.content.slice(0, 50),
1709
2512
  replyingTo.content.length > 50 ? "..." : ""
1710
2513
  ] }) : replyingTo.attachments?.[0]?.mimeType.startsWith("image/") ? "Photo" : "File"
1711
2514
  ] })
1712
2515
  ] }),
1713
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { class: "pp-reply-cancel", onClick: handleCancelReply, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {}) })
2516
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { class: "pp-reply-cancel", onClick: handleCancelReply, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CloseIcon, {}) })
1714
2517
  ] }),
1715
- pendingAttachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-attachments-preview", children: pendingAttachments.map((pending) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: `pp-attachment-preview pp-attachment-${pending.status}`, children: [
1716
- pending.preview ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: pending.preview, alt: pending.file.name, class: "pp-preview-img" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-preview-file", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileIcon, { mimeType: pending.file.type }) }),
1717
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2518
+ pendingAttachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-attachments-preview", children: pendingAttachments.map((pending) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: `pp-attachment-preview pp-attachment-${pending.status}`, children: [
2519
+ pending.preview ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { src: pending.preview, alt: pending.file.name, class: "pp-preview-img" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-preview-file", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FileIcon, { mimeType: pending.file.type }) }),
2520
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1718
2521
  "button",
1719
2522
  {
1720
2523
  class: "pp-remove-attachment",
1721
2524
  onClick: () => handleRemoveAttachment(pending.id),
1722
2525
  "aria-label": "Remove attachment",
1723
2526
  type: "button",
1724
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {})
2527
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CloseIcon, {})
1725
2528
  }
1726
2529
  ),
1727
- pending.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-upload-progress", style: { width: `${pending.progress}%` } }),
1728
- pending.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-upload-error", title: pending.error, children: "!" })
2530
+ pending.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-upload-progress", style: { width: `${pending.progress}%` } }),
2531
+ pending.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-upload-error", title: pending.error, children: "!" })
1729
2532
  ] }, pending.id)) }),
1730
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { class: "pp-input-form", onSubmit: handleSubmit, children: [
1731
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2533
+ !shouldShowPreChat && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("form", { class: "pp-input-form", onSubmit: handleSubmit, children: [
2534
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1732
2535
  "input",
1733
2536
  {
1734
2537
  ref: (el) => {
@@ -1743,7 +2546,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1743
2546
  multiple: true
1744
2547
  }
1745
2548
  ),
1746
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2549
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1747
2550
  "button",
1748
2551
  {
1749
2552
  type: "button",
@@ -1751,10 +2554,10 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1751
2554
  onClick: () => fileInputRef.current?.click(),
1752
2555
  disabled: !isConnected || isUploading,
1753
2556
  "aria-label": "Attach file",
1754
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AttachIcon, {})
2557
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(AttachIcon, {})
1755
2558
  }
1756
2559
  ),
1757
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2560
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1758
2561
  "input",
1759
2562
  {
1760
2563
  ref: inputRef,
@@ -1766,20 +2569,20 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1766
2569
  disabled: !isConnected
1767
2570
  }
1768
2571
  ),
1769
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2572
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1770
2573
  "button",
1771
2574
  {
1772
2575
  type: "submit",
1773
2576
  class: "pp-send-btn",
1774
2577
  disabled: !inputValue.trim() && pendingAttachments.filter((a) => a.status === "ready").length === 0 || !isConnected || isUploading,
1775
2578
  "aria-label": "Send message",
1776
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SendIcon, {})
2579
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SendIcon, {})
1777
2580
  }
1778
2581
  )
1779
2582
  ] }),
1780
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-footer", children: [
2583
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-footer", children: [
1781
2584
  "Powered by ",
1782
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "https://pocketping.io", target: "_blank", rel: "noopener", children: "PocketPing" })
2585
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: "https://pocketping.io", target: "_blank", rel: "noopener", children: "PocketPing" })
1783
2586
  ] })
1784
2587
  ]
1785
2588
  }
@@ -1807,90 +2610,90 @@ function formatTime(timestamp) {
1807
2610
  return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
1808
2611
  }
1809
2612
  function ChatIcon() {
1810
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ (0, import_jsx_runtime.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" }) });
2613
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.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" }) });
1811
2614
  }
1812
2615
  function CloseIcon() {
1813
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1814
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1815
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
2616
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2617
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
2618
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1816
2619
  ] });
1817
2620
  }
1818
2621
  function SendIcon() {
1819
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1820
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
1821
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
2622
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2623
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
2624
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
1822
2625
  ] });
1823
2626
  }
1824
2627
  function StatusIcon({ status }) {
1825
2628
  if (!status || status === "sending" || status === "sent") {
1826
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "3 8 7 12 13 4" }) });
2629
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "3 8 7 12 13 4" }) });
1827
2630
  }
1828
2631
  if (status === "delivered") {
1829
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double", children: [
1830
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "1 8 5 12 11 4" }),
1831
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "7 8 11 12 17 4" })
2632
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double", children: [
2633
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "1 8 5 12 11 4" }),
2634
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "7 8 11 12 17 4" })
1832
2635
  ] });
1833
2636
  }
1834
2637
  if (status === "read") {
1835
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double pp-check-read", children: [
1836
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "1 8 5 12 11 4" }),
1837
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "7 8 11 12 17 4" })
2638
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double pp-check-read", children: [
2639
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "1 8 5 12 11 4" }),
2640
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "7 8 11 12 17 4" })
1838
2641
  ] });
1839
2642
  }
1840
2643
  return null;
1841
2644
  }
1842
2645
  function AttachIcon() {
1843
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
2646
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
1844
2647
  }
1845
2648
  function ReplyIcon({ color, size = 16 }) {
1846
2649
  const strokeColor = color || "currentColor";
1847
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", "stroke-width": "2", style: { stroke: strokeColor, width: `${size}px`, minWidth: `${size}px`, height: `${size}px`, display: "block", flexShrink: 0 }, children: [
1848
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "9 17 4 12 9 7" }),
1849
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M20 18v-2a4 4 0 0 0-4-4H4" })
2650
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", "stroke-width": "2", style: { stroke: strokeColor, width: `${size}px`, minWidth: `${size}px`, height: `${size}px`, display: "block", flexShrink: 0 }, children: [
2651
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "9 17 4 12 9 7" }),
2652
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M20 18v-2a4 4 0 0 0-4-4H4" })
1850
2653
  ] });
1851
2654
  }
1852
2655
  function EditIcon({ color, size = 16 }) {
1853
2656
  const strokeColor = color || "currentColor";
1854
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", "stroke-width": "2", style: { stroke: strokeColor, width: `${size}px`, minWidth: `${size}px`, height: `${size}px`, display: "block", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z" }) });
2657
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", "stroke-width": "2", style: { stroke: strokeColor, width: `${size}px`, minWidth: `${size}px`, height: `${size}px`, display: "block", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z" }) });
1855
2658
  }
1856
2659
  function DeleteIcon({ color, size = 16 }) {
1857
2660
  const strokeColor = color || "currentColor";
1858
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", "stroke-width": "2", style: { stroke: strokeColor, width: `${size}px`, minWidth: `${size}px`, height: `${size}px`, display: "block", flexShrink: 0 }, children: [
1859
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "3 6 5 6 21 6" }),
1860
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
2661
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", "stroke-width": "2", style: { stroke: strokeColor, width: `${size}px`, minWidth: `${size}px`, height: `${size}px`, display: "block", flexShrink: 0 }, children: [
2662
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "3 6 5 6 21 6" }),
2663
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
1861
2664
  ] });
1862
2665
  }
1863
2666
  function FileIcon({ mimeType }) {
1864
2667
  if (mimeType === "application/pdf") {
1865
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1866
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1867
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "14 2 14 8 20 8" }),
1868
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 15h6" }),
1869
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 11h6" })
2668
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2669
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
2670
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "14 2 14 8 20 8" }),
2671
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9 15h6" }),
2672
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9 11h6" })
1870
2673
  ] });
1871
2674
  }
1872
2675
  if (mimeType.startsWith("audio/")) {
1873
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1874
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 18V5l12-2v13" }),
1875
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "6", cy: "18", r: "3" }),
1876
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "18", cy: "16", r: "3" })
2676
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2677
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9 18V5l12-2v13" }),
2678
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "6", cy: "18", r: "3" }),
2679
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "18", cy: "16", r: "3" })
1877
2680
  ] });
1878
2681
  }
1879
2682
  if (mimeType.startsWith("video/")) {
1880
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1881
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "2", y: "2", width: "20", height: "20", rx: "2.18", ry: "2.18" }),
1882
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "7", y1: "2", x2: "7", y2: "22" }),
1883
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "17", y1: "2", x2: "17", y2: "22" }),
1884
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "2", y1: "12", x2: "22", y2: "12" }),
1885
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "2", y1: "7", x2: "7", y2: "7" }),
1886
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "2", y1: "17", x2: "7", y2: "17" }),
1887
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "17", y1: "17", x2: "22", y2: "17" }),
1888
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "17", y1: "7", x2: "22", y2: "7" })
2683
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2684
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "2", y: "2", width: "20", height: "20", rx: "2.18", ry: "2.18" }),
2685
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "7", y1: "2", x2: "7", y2: "22" }),
2686
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "17", y1: "2", x2: "17", y2: "22" }),
2687
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "2", y1: "12", x2: "22", y2: "12" }),
2688
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "2", y1: "7", x2: "7", y2: "7" }),
2689
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "2", y1: "17", x2: "7", y2: "17" }),
2690
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "17", y1: "17", x2: "22", y2: "17" }),
2691
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "17", y1: "7", x2: "22", y2: "7" })
1889
2692
  ] });
1890
2693
  }
1891
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1892
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1893
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "14 2 14 8 20 8" })
2694
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2695
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
2696
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("polyline", { points: "14 2 14 8 20 8" })
1894
2697
  ] });
1895
2698
  }
1896
2699
  function AttachmentDisplay({ attachment }) {
@@ -1903,22 +2706,22 @@ function AttachmentDisplay({ attachment }) {
1903
2706
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1904
2707
  };
1905
2708
  if (isImage) {
1906
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: attachment.url, target: "_blank", rel: "noopener", class: "pp-attachment pp-attachment-image", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: attachment.thumbnailUrl || attachment.url, alt: attachment.filename }) });
2709
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: attachment.url, target: "_blank", rel: "noopener", class: "pp-attachment pp-attachment-image", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { src: attachment.thumbnailUrl || attachment.url, alt: attachment.filename }) });
1907
2710
  }
1908
2711
  if (isAudio) {
1909
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-attachment pp-attachment-audio", children: [
1910
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("audio", { controls: true, preload: "metadata", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("source", { src: attachment.url, type: attachment.mimeType }) }),
1911
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-attachment-name", children: attachment.filename })
2712
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-attachment pp-attachment-audio", children: [
2713
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("audio", { controls: true, preload: "metadata", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("source", { src: attachment.url, type: attachment.mimeType }) }),
2714
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-attachment-name", children: attachment.filename })
1912
2715
  ] });
1913
2716
  }
1914
2717
  if (isVideo) {
1915
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-attachment pp-attachment-video", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("video", { controls: true, preload: "metadata", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("source", { src: attachment.url, type: attachment.mimeType }) }) });
2718
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { class: "pp-attachment pp-attachment-video", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("video", { controls: true, preload: "metadata", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("source", { src: attachment.url, type: attachment.mimeType }) }) });
1916
2719
  }
1917
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: attachment.url, target: "_blank", rel: "noopener", class: "pp-attachment pp-attachment-file", children: [
1918
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FileIcon, { mimeType: attachment.mimeType }),
1919
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-attachment-info", children: [
1920
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-attachment-name", children: attachment.filename }),
1921
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-attachment-size", children: formatSize(attachment.size) })
2720
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("a", { href: attachment.url, target: "_blank", rel: "noopener", class: "pp-attachment pp-attachment-file", children: [
2721
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FileIcon, { mimeType: attachment.mimeType }),
2722
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { class: "pp-attachment-info", children: [
2723
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-attachment-name", children: attachment.filename }),
2724
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { class: "pp-attachment-size", children: formatSize(attachment.size) })
1922
2725
  ] })
1923
2726
  ] });
1924
2727
  }
@@ -1984,7 +2787,8 @@ var PocketPingClient = class {
1984
2787
  visitorId: response.visitorId,
1985
2788
  operatorOnline: response.operatorOnline ?? false,
1986
2789
  messages: response.messages ?? [],
1987
- identity: response.identity || storedIdentity || void 0
2790
+ identity: response.identity || storedIdentity || void 0,
2791
+ preChatForm: response.preChatForm
1988
2792
  };
1989
2793
  if (response.operatorName) {
1990
2794
  this.config.operatorName = response.operatorName;
@@ -2340,6 +3144,36 @@ var PocketPingClient = class {
2340
3144
  }
2341
3145
  }
2342
3146
  }
3147
+ /**
3148
+ * Submit pre-chat form data (email and/or phone)
3149
+ * @param data - Form data containing email and/or phone
3150
+ */
3151
+ async submitPreChat(data) {
3152
+ if (!this.session) {
3153
+ throw new Error("[PocketPing] Not connected");
3154
+ }
3155
+ if (!data.email && !data.phone) {
3156
+ throw new Error("[PocketPing] Either email or phone is required");
3157
+ }
3158
+ try {
3159
+ await this.fetch("/prechat", {
3160
+ method: "POST",
3161
+ body: JSON.stringify({
3162
+ sessionId: this.session.sessionId,
3163
+ email: data.email,
3164
+ phone: data.phone,
3165
+ phoneCountry: data.phoneCountry
3166
+ })
3167
+ });
3168
+ if (this.session.preChatForm) {
3169
+ this.session.preChatForm.completed = true;
3170
+ }
3171
+ this.emit("preChatCompleted", data);
3172
+ } catch (err) {
3173
+ console.error("[PocketPing] Failed to submit pre-chat form:", err);
3174
+ throw err;
3175
+ }
3176
+ }
2343
3177
  /**
2344
3178
  * Reset the user identity and optionally start a new session
2345
3179
  * Call on user logout to clear user data
@@ -2989,6 +3823,12 @@ var PocketPingClient = class {
2989
3823
  this.session.messages.push(message);
2990
3824
  this.emit("message", message);
2991
3825
  this.config.onMessage?.(message);
3826
+ if (message.sender !== "visitor" && !this.isOpen) {
3827
+ const autoOpen = this.config.autoOpenOnMessage ?? true;
3828
+ if (autoOpen) {
3829
+ this.setOpen(true);
3830
+ }
3831
+ }
2992
3832
  }
2993
3833
  }
2994
3834
  if (message.sender !== "visitor") {
@@ -3147,6 +3987,12 @@ var PocketPingClient = class {
3147
3987
  this.session.messages.push(message);
3148
3988
  this.emit("message", message);
3149
3989
  this.config.onMessage?.(message);
3990
+ if (message.sender !== "visitor" && !this.isOpen) {
3991
+ const autoOpen = this.config.autoOpenOnMessage ?? true;
3992
+ if (autoOpen) {
3993
+ this.setOpen(true);
3994
+ }
3995
+ }
3150
3996
  }
3151
3997
  }
3152
3998
  } catch (err) {