@pocketping/widget 1.5.2 → 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.js CHANGED
@@ -2,8 +2,8 @@
2
2
  import { render, h as h2 } from "preact";
3
3
 
4
4
  // src/components/ChatWidget.tsx
5
- import { Fragment } from "preact";
6
- import { useState, useEffect, useRef, useCallback } from "preact/hooks";
5
+ import { Fragment as Fragment2 } from "preact";
6
+ import { useState as useState2, useEffect as useEffect2, useRef as useRef2, useCallback } from "preact/hooks";
7
7
 
8
8
  // src/components/styles.ts
9
9
  function styles(primaryColor, theme) {
@@ -24,6 +24,17 @@ function styles(primaryColor, theme) {
24
24
  color: ${colors.text};
25
25
  }
26
26
 
27
+ #pocketping-container,
28
+ #pocketping-container * {
29
+ box-sizing: border-box;
30
+ }
31
+
32
+ #pocketping-container img,
33
+ #pocketping-container video {
34
+ max-width: 100%;
35
+ height: auto;
36
+ }
37
+
27
38
  .pp-toggle {
28
39
  position: fixed;
29
40
  width: 56px;
@@ -148,7 +159,7 @@ function styles(primaryColor, theme) {
148
159
  display: flex;
149
160
  align-items: center;
150
161
  justify-content: space-between;
151
- padding: 16px;
162
+ padding: 12px 14px;
152
163
  background: ${primaryColor};
153
164
  color: white;
154
165
  }
@@ -156,24 +167,24 @@ function styles(primaryColor, theme) {
156
167
  .pp-header-info {
157
168
  display: flex;
158
169
  align-items: center;
159
- gap: 12px;
170
+ gap: 10px;
160
171
  }
161
172
 
162
173
  .pp-avatar {
163
- width: 40px;
164
- height: 40px;
174
+ width: 36px;
175
+ height: 36px;
165
176
  border-radius: 50%;
166
177
  object-fit: cover;
167
178
  }
168
179
 
169
180
  .pp-header-title {
170
181
  font-weight: 600;
171
- font-size: 16px;
182
+ font-size: 15px;
172
183
  }
173
184
 
174
185
  .pp-header-status {
175
- font-size: 12px;
176
- opacity: 0.9;
186
+ font-size: 11px;
187
+ opacity: 0.85;
177
188
  display: flex;
178
189
  align-items: center;
179
190
  gap: 4px;
@@ -219,10 +230,14 @@ function styles(primaryColor, theme) {
219
230
  .pp-messages {
220
231
  flex: 1;
221
232
  overflow-y: auto;
222
- padding: 16px;
233
+ padding: 32px 12px 12px 12px;
223
234
  display: flex;
224
235
  flex-direction: column;
225
- gap: 12px;
236
+ gap: 3px;
237
+ overscroll-behavior: contain;
238
+ -webkit-overflow-scrolling: touch;
239
+ /* Ensure proper stacking context for positioned elements */
240
+ position: relative;
226
241
  }
227
242
 
228
243
  .pp-welcome {
@@ -232,20 +247,110 @@ function styles(primaryColor, theme) {
232
247
  font-size: 13px;
233
248
  }
234
249
 
250
+ .pp-date-separator {
251
+ display: flex;
252
+ align-items: center;
253
+ justify-content: center;
254
+ margin: 16px 0 12px;
255
+ }
256
+
257
+ .pp-date-separator span {
258
+ background: ${colors.bgSecondary};
259
+ color: ${colors.textSecondary};
260
+ font-size: 11px;
261
+ padding: 4px 12px;
262
+ border-radius: 12px;
263
+ font-weight: 500;
264
+ }
265
+
266
+ /* Swipe container for mobile actions */
267
+ .pp-message-swipe-container {
268
+ position: relative;
269
+ display: flex;
270
+ align-items: stretch;
271
+ overflow: visible;
272
+ touch-action: pan-y;
273
+ }
274
+
275
+ .pp-swipe-left {
276
+ justify-content: flex-end;
277
+ }
278
+
279
+ .pp-swipe-right {
280
+ justify-content: flex-start;
281
+ }
282
+
283
+ .pp-swipe-actions {
284
+ position: absolute;
285
+ right: 0;
286
+ top: 0;
287
+ bottom: 0;
288
+ display: flex;
289
+ align-items: center;
290
+ gap: 4px;
291
+ padding-right: 8px;
292
+ }
293
+
294
+ .pp-swipe-left .pp-swipe-actions {
295
+ right: 0;
296
+ left: auto;
297
+ }
298
+
299
+ .pp-swipe-right .pp-swipe-actions {
300
+ left: 0;
301
+ right: auto;
302
+ padding-left: 8px;
303
+ padding-right: 0;
304
+ }
305
+
306
+ .pp-swipe-action {
307
+ width: 32px;
308
+ height: 32px;
309
+ border: none;
310
+ border-radius: 50%;
311
+ cursor: pointer;
312
+ display: flex;
313
+ align-items: center;
314
+ justify-content: center;
315
+ opacity: 0.9;
316
+ }
317
+
318
+ .pp-swipe-action svg {
319
+ width: 16px;
320
+ height: 16px;
321
+ }
322
+
323
+ .pp-swipe-reply {
324
+ background: ${primaryColor};
325
+ }
326
+
327
+ .pp-swipe-edit {
328
+ background: #3b82f6;
329
+ }
330
+
331
+ .pp-swipe-delete {
332
+ background: #ef4444;
333
+ }
334
+
235
335
  .pp-message {
236
- max-width: 80%;
237
- padding: 10px 14px;
238
- border-radius: 16px;
336
+ max-width: 85%;
337
+ padding: 6px 10px;
338
+ border-radius: 12px;
239
339
  word-wrap: break-word;
240
340
  position: relative;
241
341
  user-select: text;
242
342
  -webkit-user-select: text;
343
+ font-size: 14px;
344
+ line-height: 1.35;
345
+ display: flex;
346
+ flex-direction: column;
347
+ will-change: transform;
243
348
  }
244
349
 
245
350
  /* Hover actions container - positioned above message (Slack style) */
246
351
  .pp-message-actions {
247
352
  position: absolute;
248
- top: -28px;
353
+ top: -32px;
249
354
  display: flex;
250
355
  gap: 2px;
251
356
  background: ${colors.bg};
@@ -258,6 +363,8 @@ function styles(primaryColor, theme) {
258
363
  z-index: 10;
259
364
  /* Reset color inheritance from message */
260
365
  color: ${colors.textSecondary};
366
+ /* Ensure actions don't interfere with layout */
367
+ pointer-events: auto;
261
368
  }
262
369
 
263
370
  @keyframes pp-actions-fade-in {
@@ -331,7 +438,8 @@ function styles(primaryColor, theme) {
331
438
  align-self: flex-end;
332
439
  background: ${primaryColor};
333
440
  color: white;
334
- border-bottom-right-radius: 4px;
441
+ border-bottom-right-radius: 3px;
442
+ margin-left: 32px;
335
443
  }
336
444
 
337
445
  .pp-message-operator,
@@ -339,19 +447,32 @@ function styles(primaryColor, theme) {
339
447
  align-self: flex-start;
340
448
  background: ${colors.messageBg};
341
449
  color: ${colors.text};
342
- border-bottom-left-radius: 4px;
450
+ border-bottom-left-radius: 3px;
451
+ margin-right: 32px;
452
+ }
453
+
454
+ /* Add spacing between different senders */
455
+ .pp-message-visitor + .pp-message-operator,
456
+ .pp-message-visitor + .pp-message-ai,
457
+ .pp-message-operator + .pp-message-visitor,
458
+ .pp-message-ai + .pp-message-visitor {
459
+ margin-top: 8px;
343
460
  }
344
461
 
345
462
  .pp-message-content {
346
- margin-bottom: 4px;
463
+ display: block;
464
+ flex: 1;
347
465
  }
348
466
 
349
467
  .pp-message-time {
350
- font-size: 11px;
351
- opacity: 0.7;
468
+ font-size: 10px;
469
+ opacity: 0.6;
352
470
  display: flex;
353
471
  align-items: center;
354
- gap: 4px;
472
+ gap: 3px;
473
+ justify-content: flex-end;
474
+ margin-top: 8px;
475
+ flex-shrink: 0;
355
476
  }
356
477
 
357
478
  .pp-ai-badge {
@@ -388,13 +509,13 @@ function styles(primaryColor, theme) {
388
509
 
389
510
  .pp-typing {
390
511
  display: flex;
391
- gap: 4px;
392
- padding: 14px 18px;
512
+ gap: 3px;
513
+ padding: 8px 12px;
393
514
  }
394
515
 
395
516
  .pp-typing span {
396
- width: 8px;
397
- height: 8px;
517
+ width: 6px;
518
+ height: 6px;
398
519
  background: ${colors.textSecondary};
399
520
  border-radius: 50%;
400
521
  animation: pp-bounce 1.4s infinite ease-in-out both;
@@ -410,14 +531,18 @@ function styles(primaryColor, theme) {
410
531
 
411
532
  .pp-input-form {
412
533
  display: flex;
413
- padding: 12px;
534
+ padding: 10px 12px;
414
535
  gap: 8px;
415
536
  border-top: 1px solid ${colors.border};
537
+ align-items: center;
416
538
  }
417
539
 
418
540
  .pp-input {
419
541
  flex: 1;
420
- padding: 10px 14px;
542
+ min-width: 0;
543
+ height: 40px;
544
+ line-height: 40px;
545
+ padding: 0 16px;
421
546
  border: 1px solid ${colors.border};
422
547
  border-radius: 20px;
423
548
  background: ${colors.bg};
@@ -425,6 +550,8 @@ function styles(primaryColor, theme) {
425
550
  font-size: 14px;
426
551
  outline: none;
427
552
  transition: border-color 0.2s;
553
+ box-sizing: border-box;
554
+ margin: 0;
428
555
  }
429
556
 
430
557
  .pp-input:focus {
@@ -438,6 +565,7 @@ function styles(primaryColor, theme) {
438
565
  .pp-send-btn {
439
566
  width: 40px;
440
567
  height: 40px;
568
+ min-width: 40px;
441
569
  border-radius: 50%;
442
570
  background: ${primaryColor};
443
571
  color: white;
@@ -446,7 +574,18 @@ function styles(primaryColor, theme) {
446
574
  display: flex;
447
575
  align-items: center;
448
576
  justify-content: center;
449
- transition: opacity 0.2s;
577
+ transition: opacity 0.2s, transform 0.1s;
578
+ flex-shrink: 0;
579
+ margin: 0;
580
+ padding: 0;
581
+ }
582
+
583
+ .pp-send-btn:not(:disabled):hover {
584
+ transform: scale(1.05);
585
+ }
586
+
587
+ .pp-send-btn:not(:disabled):active {
588
+ transform: scale(0.95);
450
589
  }
451
590
 
452
591
  .pp-send-btn:disabled {
@@ -465,6 +604,7 @@ function styles(primaryColor, theme) {
465
604
  font-size: 11px;
466
605
  color: ${colors.textSecondary};
467
606
  border-top: 1px solid ${colors.border};
607
+ opacity: 0.7;
468
608
  }
469
609
 
470
610
  .pp-footer a {
@@ -493,6 +633,7 @@ function styles(primaryColor, theme) {
493
633
  .pp-attach-btn {
494
634
  width: 40px;
495
635
  height: 40px;
636
+ min-width: 40px;
496
637
  border-radius: 50%;
497
638
  background: transparent;
498
639
  color: ${colors.textSecondary};
@@ -501,6 +642,8 @@ function styles(primaryColor, theme) {
501
642
  display: flex;
502
643
  align-items: center;
503
644
  justify-content: center;
645
+ margin: 0;
646
+ padding: 0;
504
647
  transition: color 0.2s, border-color 0.2s;
505
648
  flex-shrink: 0;
506
649
  }
@@ -621,7 +764,10 @@ function styles(primaryColor, theme) {
621
764
  display: flex;
622
765
  flex-direction: column;
623
766
  gap: 8px;
624
- margin-top: 4px;
767
+ margin-top: 6px;
768
+ max-width: 100%;
769
+ align-items: flex-start;
770
+ flex-shrink: 0;
625
771
  }
626
772
 
627
773
  .pp-attachment {
@@ -632,11 +778,22 @@ function styles(primaryColor, theme) {
632
778
  overflow: hidden;
633
779
  }
634
780
 
781
+ .pp-attachment-image,
782
+ .pp-attachment-video,
783
+ .pp-attachment-audio {
784
+ width: 240px;
785
+ max-width: 100%;
786
+ }
787
+
635
788
  .pp-attachment-image img {
636
- max-width: 200px;
789
+ width: 100% !important;
790
+ height: auto !important;
791
+ max-width: 240px;
637
792
  max-height: 200px;
638
793
  border-radius: 8px;
639
794
  display: block;
795
+ object-fit: cover !important;
796
+ object-position: center;
640
797
  }
641
798
 
642
799
  .pp-attachment-audio {
@@ -646,7 +803,8 @@ function styles(primaryColor, theme) {
646
803
  }
647
804
 
648
805
  .pp-attachment-audio audio {
649
- width: 200px;
806
+ width: 240px;
807
+ max-width: 100%;
650
808
  height: 36px;
651
809
  }
652
810
 
@@ -656,14 +814,18 @@ function styles(primaryColor, theme) {
656
814
  white-space: nowrap;
657
815
  overflow: hidden;
658
816
  text-overflow: ellipsis;
659
- max-width: 200px;
817
+ max-width: 100%;
660
818
  }
661
819
 
662
820
  .pp-attachment-video video {
663
- max-width: 200px;
664
- max-height: 200px;
821
+ width: 100% !important;
822
+ height: auto !important;
823
+ max-width: 240px;
824
+ max-height: none;
665
825
  border-radius: 8px;
666
826
  display: block;
827
+ object-fit: contain !important;
828
+ object-position: center;
667
829
  }
668
830
 
669
831
  .pp-attachment-file {
@@ -1014,34 +1176,665 @@ function styles(primaryColor, theme) {
1014
1176
  margin-left: 4px;
1015
1177
  font-style: italic;
1016
1178
  }
1179
+
1180
+ /* Pre-Chat Form */
1181
+ .pp-prechat {
1182
+ flex: 1;
1183
+ display: flex;
1184
+ flex-direction: column;
1185
+ padding: 24px 20px;
1186
+ overflow-y: auto;
1187
+ }
1188
+
1189
+ .pp-prechat-title {
1190
+ font-size: 18px;
1191
+ font-weight: 600;
1192
+ margin-bottom: 8px;
1193
+ color: ${colors.text};
1194
+ }
1195
+
1196
+ .pp-prechat-subtitle {
1197
+ font-size: 13px;
1198
+ color: ${colors.textSecondary};
1199
+ margin-bottom: 24px;
1200
+ }
1201
+
1202
+ .pp-prechat-tabs {
1203
+ display: flex;
1204
+ gap: 8px;
1205
+ margin-bottom: 20px;
1206
+ }
1207
+
1208
+ .pp-prechat-tab {
1209
+ flex: 1;
1210
+ padding: 10px;
1211
+ border: 1px solid ${colors.border};
1212
+ border-radius: 8px;
1213
+ background: transparent;
1214
+ color: ${colors.textSecondary};
1215
+ font-size: 13px;
1216
+ cursor: pointer;
1217
+ transition: all 0.2s;
1218
+ display: flex;
1219
+ align-items: center;
1220
+ justify-content: center;
1221
+ gap: 6px;
1222
+ }
1223
+
1224
+ .pp-prechat-tab:hover {
1225
+ background: ${colors.bgSecondary};
1226
+ }
1227
+
1228
+ .pp-prechat-tab.active {
1229
+ background: ${primaryColor}15;
1230
+ border-color: ${primaryColor};
1231
+ color: ${primaryColor};
1232
+ }
1233
+
1234
+ .pp-prechat-tab svg {
1235
+ width: 16px;
1236
+ height: 16px;
1237
+ }
1238
+
1239
+ .pp-prechat-field {
1240
+ margin-bottom: 16px;
1241
+ }
1242
+
1243
+ .pp-prechat-label {
1244
+ display: block;
1245
+ font-size: 12px;
1246
+ font-weight: 500;
1247
+ color: ${colors.textSecondary};
1248
+ margin-bottom: 6px;
1249
+ }
1250
+
1251
+ .pp-prechat-input {
1252
+ width: 100%;
1253
+ height: 44px;
1254
+ padding: 0 14px;
1255
+ border: 1px solid ${colors.border};
1256
+ border-radius: 8px;
1257
+ background: ${colors.bg};
1258
+ color: ${colors.text};
1259
+ font-size: 14px;
1260
+ outline: none;
1261
+ transition: border-color 0.2s;
1262
+ box-sizing: border-box;
1263
+ }
1264
+
1265
+ .pp-prechat-input:focus {
1266
+ border-color: ${primaryColor};
1267
+ }
1268
+
1269
+ .pp-prechat-input::placeholder {
1270
+ color: ${colors.textSecondary};
1271
+ }
1272
+
1273
+ .pp-prechat-input.error {
1274
+ border-color: #ef4444;
1275
+ }
1276
+
1277
+ .pp-prechat-error {
1278
+ color: #ef4444;
1279
+ font-size: 12px;
1280
+ margin-top: 4px;
1281
+ }
1282
+
1283
+ .pp-phone-input-wrapper {
1284
+ display: flex;
1285
+ gap: 8px;
1286
+ }
1287
+
1288
+ .pp-country-select {
1289
+ position: relative;
1290
+ }
1291
+
1292
+ .pp-country-btn {
1293
+ display: flex;
1294
+ align-items: center;
1295
+ gap: 6px;
1296
+ height: 44px;
1297
+ padding: 0 10px;
1298
+ border: 1px solid ${colors.border};
1299
+ border-radius: 8px;
1300
+ background: ${colors.bg};
1301
+ color: ${colors.text};
1302
+ font-size: 14px;
1303
+ cursor: pointer;
1304
+ transition: border-color 0.2s;
1305
+ }
1306
+
1307
+ .pp-country-btn:focus {
1308
+ border-color: ${primaryColor};
1309
+ outline: none;
1310
+ }
1311
+
1312
+ .pp-country-flag {
1313
+ font-size: 18px;
1314
+ line-height: 1;
1315
+ }
1316
+
1317
+ .pp-country-code {
1318
+ font-size: 13px;
1319
+ color: ${colors.textSecondary};
1320
+ }
1321
+
1322
+ .pp-country-chevron {
1323
+ width: 12px;
1324
+ height: 12px;
1325
+ color: ${colors.textSecondary};
1326
+ }
1327
+
1328
+ .pp-country-dropdown {
1329
+ position: absolute;
1330
+ top: calc(100% + 4px);
1331
+ left: 0;
1332
+ width: 280px;
1333
+ max-height: 280px;
1334
+ overflow-y: auto;
1335
+ background: ${colors.bg};
1336
+ border: 1px solid ${colors.border};
1337
+ border-radius: 8px;
1338
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1339
+ z-index: 100;
1340
+ }
1341
+
1342
+ .pp-country-search {
1343
+ position: sticky;
1344
+ top: 0;
1345
+ padding: 8px;
1346
+ background: ${colors.bg};
1347
+ border-bottom: 1px solid ${colors.border};
1348
+ }
1349
+
1350
+ .pp-country-search-input {
1351
+ width: 100%;
1352
+ height: 36px;
1353
+ padding: 0 12px;
1354
+ border: 1px solid ${colors.border};
1355
+ border-radius: 6px;
1356
+ background: ${colors.bgSecondary};
1357
+ color: ${colors.text};
1358
+ font-size: 13px;
1359
+ outline: none;
1360
+ box-sizing: border-box;
1361
+ }
1362
+
1363
+ .pp-country-search-input:focus {
1364
+ border-color: ${primaryColor};
1365
+ }
1366
+
1367
+ .pp-country-list {
1368
+ padding: 4px;
1369
+ }
1370
+
1371
+ .pp-country-option {
1372
+ display: flex;
1373
+ align-items: center;
1374
+ gap: 10px;
1375
+ padding: 10px 12px;
1376
+ cursor: pointer;
1377
+ border-radius: 6px;
1378
+ transition: background 0.15s;
1379
+ }
1380
+
1381
+ .pp-country-option:hover {
1382
+ background: ${colors.bgSecondary};
1383
+ }
1384
+
1385
+ .pp-country-option.selected {
1386
+ background: ${primaryColor}15;
1387
+ }
1388
+
1389
+ .pp-country-name {
1390
+ flex: 1;
1391
+ font-size: 13px;
1392
+ color: ${colors.text};
1393
+ }
1394
+
1395
+ .pp-country-dial {
1396
+ font-size: 12px;
1397
+ color: ${colors.textSecondary};
1398
+ }
1399
+
1400
+ .pp-phone-number-input {
1401
+ flex: 1;
1402
+ }
1403
+
1404
+ .pp-prechat-submit {
1405
+ width: 100%;
1406
+ height: 44px;
1407
+ margin-top: 8px;
1408
+ border: none;
1409
+ border-radius: 8px;
1410
+ background: ${primaryColor};
1411
+ color: white;
1412
+ font-size: 14px;
1413
+ font-weight: 500;
1414
+ cursor: pointer;
1415
+ transition: opacity 0.2s, transform 0.1s;
1416
+ }
1417
+
1418
+ .pp-prechat-submit:hover:not(:disabled) {
1419
+ opacity: 0.9;
1420
+ }
1421
+
1422
+ .pp-prechat-submit:active:not(:disabled) {
1423
+ transform: scale(0.98);
1424
+ }
1425
+
1426
+ .pp-prechat-submit:disabled {
1427
+ opacity: 0.5;
1428
+ cursor: not-allowed;
1429
+ }
1430
+
1431
+ .pp-prechat-skip {
1432
+ width: 100%;
1433
+ padding: 12px;
1434
+ margin-top: 8px;
1435
+ border: none;
1436
+ background: transparent;
1437
+ color: ${colors.textSecondary};
1438
+ font-size: 13px;
1439
+ cursor: pointer;
1440
+ transition: color 0.2s;
1441
+ }
1442
+
1443
+ .pp-prechat-skip:hover {
1444
+ color: ${colors.text};
1445
+ }
1017
1446
  `;
1018
1447
  }
1019
1448
 
1449
+ // src/components/PreChatForm.tsx
1450
+ import { useState, useRef, useEffect } from "preact/hooks";
1451
+ import { parsePhoneNumber, isValidPhoneNumber } from "libphonenumber-js/min";
1452
+
1453
+ // src/data/countries.ts
1454
+ var countries = [
1455
+ // Europe
1456
+ { code: "FR", name: "France", dialCode: "+33", flag: "\u{1F1EB}\u{1F1F7}" },
1457
+ { code: "DE", name: "Germany", dialCode: "+49", flag: "\u{1F1E9}\u{1F1EA}" },
1458
+ { code: "GB", name: "United Kingdom", dialCode: "+44", flag: "\u{1F1EC}\u{1F1E7}" },
1459
+ { code: "ES", name: "Spain", dialCode: "+34", flag: "\u{1F1EA}\u{1F1F8}" },
1460
+ { code: "IT", name: "Italy", dialCode: "+39", flag: "\u{1F1EE}\u{1F1F9}" },
1461
+ { code: "PT", name: "Portugal", dialCode: "+351", flag: "\u{1F1F5}\u{1F1F9}" },
1462
+ { code: "NL", name: "Netherlands", dialCode: "+31", flag: "\u{1F1F3}\u{1F1F1}" },
1463
+ { code: "BE", name: "Belgium", dialCode: "+32", flag: "\u{1F1E7}\u{1F1EA}" },
1464
+ { code: "CH", name: "Switzerland", dialCode: "+41", flag: "\u{1F1E8}\u{1F1ED}" },
1465
+ { code: "AT", name: "Austria", dialCode: "+43", flag: "\u{1F1E6}\u{1F1F9}" },
1466
+ { code: "SE", name: "Sweden", dialCode: "+46", flag: "\u{1F1F8}\u{1F1EA}" },
1467
+ { code: "NO", name: "Norway", dialCode: "+47", flag: "\u{1F1F3}\u{1F1F4}" },
1468
+ { code: "DK", name: "Denmark", dialCode: "+45", flag: "\u{1F1E9}\u{1F1F0}" },
1469
+ { code: "FI", name: "Finland", dialCode: "+358", flag: "\u{1F1EB}\u{1F1EE}" },
1470
+ { code: "PL", name: "Poland", dialCode: "+48", flag: "\u{1F1F5}\u{1F1F1}" },
1471
+ { code: "CZ", name: "Czech Republic", dialCode: "+420", flag: "\u{1F1E8}\u{1F1FF}" },
1472
+ { code: "GR", name: "Greece", dialCode: "+30", flag: "\u{1F1EC}\u{1F1F7}" },
1473
+ { code: "IE", name: "Ireland", dialCode: "+353", flag: "\u{1F1EE}\u{1F1EA}" },
1474
+ { code: "RO", name: "Romania", dialCode: "+40", flag: "\u{1F1F7}\u{1F1F4}" },
1475
+ { code: "HU", name: "Hungary", dialCode: "+36", flag: "\u{1F1ED}\u{1F1FA}" },
1476
+ // North America
1477
+ { code: "US", name: "United States", dialCode: "+1", flag: "\u{1F1FA}\u{1F1F8}" },
1478
+ { code: "CA", name: "Canada", dialCode: "+1", flag: "\u{1F1E8}\u{1F1E6}" },
1479
+ { code: "MX", name: "Mexico", dialCode: "+52", flag: "\u{1F1F2}\u{1F1FD}" },
1480
+ // South America
1481
+ { code: "BR", name: "Brazil", dialCode: "+55", flag: "\u{1F1E7}\u{1F1F7}" },
1482
+ { code: "AR", name: "Argentina", dialCode: "+54", flag: "\u{1F1E6}\u{1F1F7}" },
1483
+ { code: "CL", name: "Chile", dialCode: "+56", flag: "\u{1F1E8}\u{1F1F1}" },
1484
+ { code: "CO", name: "Colombia", dialCode: "+57", flag: "\u{1F1E8}\u{1F1F4}" },
1485
+ { code: "PE", name: "Peru", dialCode: "+51", flag: "\u{1F1F5}\u{1F1EA}" },
1486
+ // Asia
1487
+ { code: "CN", name: "China", dialCode: "+86", flag: "\u{1F1E8}\u{1F1F3}" },
1488
+ { code: "JP", name: "Japan", dialCode: "+81", flag: "\u{1F1EF}\u{1F1F5}" },
1489
+ { code: "KR", name: "South Korea", dialCode: "+82", flag: "\u{1F1F0}\u{1F1F7}" },
1490
+ { code: "IN", name: "India", dialCode: "+91", flag: "\u{1F1EE}\u{1F1F3}" },
1491
+ { code: "ID", name: "Indonesia", dialCode: "+62", flag: "\u{1F1EE}\u{1F1E9}" },
1492
+ { code: "TH", name: "Thailand", dialCode: "+66", flag: "\u{1F1F9}\u{1F1ED}" },
1493
+ { code: "VN", name: "Vietnam", dialCode: "+84", flag: "\u{1F1FB}\u{1F1F3}" },
1494
+ { code: "MY", name: "Malaysia", dialCode: "+60", flag: "\u{1F1F2}\u{1F1FE}" },
1495
+ { code: "SG", name: "Singapore", dialCode: "+65", flag: "\u{1F1F8}\u{1F1EC}" },
1496
+ { code: "PH", name: "Philippines", dialCode: "+63", flag: "\u{1F1F5}\u{1F1ED}" },
1497
+ { code: "PK", name: "Pakistan", dialCode: "+92", flag: "\u{1F1F5}\u{1F1F0}" },
1498
+ { code: "BD", name: "Bangladesh", dialCode: "+880", flag: "\u{1F1E7}\u{1F1E9}" },
1499
+ // Middle East
1500
+ { code: "AE", name: "United Arab Emirates", dialCode: "+971", flag: "\u{1F1E6}\u{1F1EA}" },
1501
+ { code: "SA", name: "Saudi Arabia", dialCode: "+966", flag: "\u{1F1F8}\u{1F1E6}" },
1502
+ { code: "IL", name: "Israel", dialCode: "+972", flag: "\u{1F1EE}\u{1F1F1}" },
1503
+ { code: "TR", name: "Turkey", dialCode: "+90", flag: "\u{1F1F9}\u{1F1F7}" },
1504
+ { code: "EG", name: "Egypt", dialCode: "+20", flag: "\u{1F1EA}\u{1F1EC}" },
1505
+ // Africa
1506
+ { code: "ZA", name: "South Africa", dialCode: "+27", flag: "\u{1F1FF}\u{1F1E6}" },
1507
+ { code: "NG", name: "Nigeria", dialCode: "+234", flag: "\u{1F1F3}\u{1F1EC}" },
1508
+ { code: "KE", name: "Kenya", dialCode: "+254", flag: "\u{1F1F0}\u{1F1EA}" },
1509
+ { code: "MA", name: "Morocco", dialCode: "+212", flag: "\u{1F1F2}\u{1F1E6}" },
1510
+ { code: "TN", name: "Tunisia", dialCode: "+216", flag: "\u{1F1F9}\u{1F1F3}" },
1511
+ { code: "DZ", name: "Algeria", dialCode: "+213", flag: "\u{1F1E9}\u{1F1FF}" },
1512
+ // Oceania
1513
+ { code: "AU", name: "Australia", dialCode: "+61", flag: "\u{1F1E6}\u{1F1FA}" },
1514
+ { code: "NZ", name: "New Zealand", dialCode: "+64", flag: "\u{1F1F3}\u{1F1FF}" },
1515
+ // Russia & CIS
1516
+ { code: "RU", name: "Russia", dialCode: "+7", flag: "\u{1F1F7}\u{1F1FA}" },
1517
+ { code: "UA", name: "Ukraine", dialCode: "+380", flag: "\u{1F1FA}\u{1F1E6}" }
1518
+ ].sort((a, b) => a.name.localeCompare(b.name));
1519
+ function findCountryByCode(code) {
1520
+ return countries.find((c) => c.code === code.toUpperCase());
1521
+ }
1522
+ var defaultCountry = findCountryByCode("FR");
1523
+
1524
+ // src/components/PreChatForm.tsx
1525
+ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
1526
+ var EmailIcon = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1527
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "4", width: "20", height: "16", rx: "2" }),
1528
+ /* @__PURE__ */ jsx("path", { d: "M22 7l-10 7L2 7" })
1529
+ ] });
1530
+ var PhoneIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ 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" }) });
1531
+ var ChevronIcon = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" }) });
1532
+ function isValidEmail(email) {
1533
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
1534
+ }
1535
+ function PreChatForm({ client: client2, config, onComplete, onSkip }) {
1536
+ const showEmailOnly = config.fields === "email-only";
1537
+ const showPhoneOnly = config.fields === "phone-only";
1538
+ const showBoth = config.fields === "email-and-phone";
1539
+ const showChoice = config.fields === "email-or-phone";
1540
+ const getDefaultTab = () => {
1541
+ if (showPhoneOnly) return "phone";
1542
+ return "email";
1543
+ };
1544
+ const [activeTab, setActiveTab] = useState(getDefaultTab());
1545
+ const [email, setEmail] = useState("");
1546
+ const [phone, setPhone] = useState("");
1547
+ const [selectedCountry, setSelectedCountry] = useState(defaultCountry);
1548
+ const [isCountryDropdownOpen, setIsCountryDropdownOpen] = useState(false);
1549
+ const [countrySearch, setCountrySearch] = useState("");
1550
+ const [emailError, setEmailError] = useState("");
1551
+ const [phoneError, setPhoneError] = useState("");
1552
+ const [isSubmitting, setIsSubmitting] = useState(false);
1553
+ const countryDropdownRef = useRef(null);
1554
+ const searchInputRef = useRef(null);
1555
+ useEffect(() => {
1556
+ const handleClickOutside = (e) => {
1557
+ if (countryDropdownRef.current && !countryDropdownRef.current.contains(e.target)) {
1558
+ setIsCountryDropdownOpen(false);
1559
+ }
1560
+ };
1561
+ document.addEventListener("mousedown", handleClickOutside);
1562
+ return () => document.removeEventListener("mousedown", handleClickOutside);
1563
+ }, []);
1564
+ useEffect(() => {
1565
+ if (isCountryDropdownOpen && searchInputRef.current) {
1566
+ searchInputRef.current.focus();
1567
+ }
1568
+ }, [isCountryDropdownOpen]);
1569
+ const filteredCountries = countries.filter(
1570
+ (c) => c.name.toLowerCase().includes(countrySearch.toLowerCase()) || c.dialCode.includes(countrySearch) || c.code.toLowerCase().includes(countrySearch.toLowerCase())
1571
+ );
1572
+ const handleCountrySelect = (country) => {
1573
+ setSelectedCountry(country);
1574
+ setIsCountryDropdownOpen(false);
1575
+ setCountrySearch("");
1576
+ };
1577
+ const formatPhoneForDisplay = (value) => {
1578
+ const digits = value.replace(/\D/g, "");
1579
+ return digits;
1580
+ };
1581
+ const handlePhoneChange = (e) => {
1582
+ const target = e.target;
1583
+ const formatted = formatPhoneForDisplay(target.value);
1584
+ setPhone(formatted);
1585
+ setPhoneError("");
1586
+ };
1587
+ const getFullPhoneNumber = () => {
1588
+ if (!phone) return "";
1589
+ return `${selectedCountry.dialCode}${phone}`;
1590
+ };
1591
+ const validateForm = () => {
1592
+ let valid = true;
1593
+ if (showEmailOnly || showBoth) {
1594
+ if (!email.trim()) {
1595
+ setEmailError("Email is required");
1596
+ valid = false;
1597
+ } else if (!isValidEmail(email)) {
1598
+ setEmailError("Please enter a valid email");
1599
+ valid = false;
1600
+ }
1601
+ }
1602
+ if (showPhoneOnly || showBoth) {
1603
+ const fullPhone = getFullPhoneNumber();
1604
+ if (!phone.trim()) {
1605
+ setPhoneError("Phone number is required");
1606
+ valid = false;
1607
+ } else if (!isValidPhoneNumber(fullPhone, selectedCountry.code)) {
1608
+ setPhoneError("Please enter a valid phone number");
1609
+ valid = false;
1610
+ }
1611
+ }
1612
+ if (showChoice) {
1613
+ if (activeTab === "email") {
1614
+ if (!email.trim()) {
1615
+ setEmailError("Email is required");
1616
+ valid = false;
1617
+ } else if (!isValidEmail(email)) {
1618
+ setEmailError("Please enter a valid email");
1619
+ valid = false;
1620
+ }
1621
+ } else {
1622
+ const fullPhone = getFullPhoneNumber();
1623
+ if (!phone.trim()) {
1624
+ setPhoneError("Phone number is required");
1625
+ valid = false;
1626
+ } else if (!isValidPhoneNumber(fullPhone, selectedCountry.code)) {
1627
+ setPhoneError("Please enter a valid phone number");
1628
+ valid = false;
1629
+ }
1630
+ }
1631
+ }
1632
+ return valid;
1633
+ };
1634
+ const handleSubmit = async (e) => {
1635
+ e.preventDefault();
1636
+ if (!validateForm()) return;
1637
+ setIsSubmitting(true);
1638
+ try {
1639
+ const data = {};
1640
+ if (showEmailOnly || showBoth || showChoice && activeTab === "email") {
1641
+ data.email = email.trim();
1642
+ }
1643
+ if (showPhoneOnly || showBoth || showChoice && activeTab === "phone") {
1644
+ const fullPhone = getFullPhoneNumber();
1645
+ const parsed = parsePhoneNumber(fullPhone, selectedCountry.code);
1646
+ if (parsed) {
1647
+ data.phone = parsed.format("E.164");
1648
+ data.phoneCountry = selectedCountry.code;
1649
+ }
1650
+ }
1651
+ await client2.submitPreChat(data);
1652
+ onComplete();
1653
+ } catch (err) {
1654
+ console.error("[PreChatForm] Submit error:", err);
1655
+ if (activeTab === "email" || showEmailOnly || showBoth) {
1656
+ setEmailError("Something went wrong. Please try again.");
1657
+ } else {
1658
+ setPhoneError("Something went wrong. Please try again.");
1659
+ }
1660
+ } finally {
1661
+ setIsSubmitting(false);
1662
+ }
1663
+ };
1664
+ const renderEmailField = () => /* @__PURE__ */ jsxs("div", { class: "pp-prechat-field", children: [
1665
+ /* @__PURE__ */ jsx("label", { class: "pp-prechat-label", children: "Email address" }),
1666
+ /* @__PURE__ */ jsx(
1667
+ "input",
1668
+ {
1669
+ type: "email",
1670
+ class: `pp-prechat-input ${emailError ? "error" : ""}`,
1671
+ placeholder: "you@example.com",
1672
+ value: email,
1673
+ onInput: (e) => {
1674
+ setEmail(e.target.value);
1675
+ setEmailError("");
1676
+ }
1677
+ }
1678
+ ),
1679
+ emailError && /* @__PURE__ */ jsx("div", { class: "pp-prechat-error", children: emailError })
1680
+ ] });
1681
+ const renderPhoneField = () => /* @__PURE__ */ jsxs("div", { class: "pp-prechat-field", children: [
1682
+ /* @__PURE__ */ jsx("label", { class: "pp-prechat-label", children: "Phone number" }),
1683
+ /* @__PURE__ */ jsxs("div", { class: "pp-phone-input-wrapper", children: [
1684
+ /* @__PURE__ */ jsxs("div", { class: "pp-country-select", ref: countryDropdownRef, children: [
1685
+ /* @__PURE__ */ jsxs(
1686
+ "button",
1687
+ {
1688
+ type: "button",
1689
+ class: "pp-country-btn",
1690
+ onClick: () => setIsCountryDropdownOpen(!isCountryDropdownOpen),
1691
+ children: [
1692
+ /* @__PURE__ */ jsx("span", { class: "pp-country-flag", children: selectedCountry.flag }),
1693
+ /* @__PURE__ */ jsx("span", { class: "pp-country-code", children: selectedCountry.dialCode }),
1694
+ /* @__PURE__ */ jsx(ChevronIcon, {})
1695
+ ]
1696
+ }
1697
+ ),
1698
+ isCountryDropdownOpen && /* @__PURE__ */ jsxs("div", { class: "pp-country-dropdown", children: [
1699
+ /* @__PURE__ */ jsx("div", { class: "pp-country-search", children: /* @__PURE__ */ jsx(
1700
+ "input",
1701
+ {
1702
+ ref: searchInputRef,
1703
+ type: "text",
1704
+ class: "pp-country-search-input",
1705
+ placeholder: "Search country...",
1706
+ value: countrySearch,
1707
+ onInput: (e) => setCountrySearch(e.target.value)
1708
+ }
1709
+ ) }),
1710
+ /* @__PURE__ */ jsx("div", { class: "pp-country-list", children: filteredCountries.map((country) => /* @__PURE__ */ jsxs(
1711
+ "div",
1712
+ {
1713
+ class: `pp-country-option ${country.code === selectedCountry.code ? "selected" : ""}`,
1714
+ onClick: () => handleCountrySelect(country),
1715
+ children: [
1716
+ /* @__PURE__ */ jsx("span", { class: "pp-country-flag", children: country.flag }),
1717
+ /* @__PURE__ */ jsx("span", { class: "pp-country-name", children: country.name }),
1718
+ /* @__PURE__ */ jsx("span", { class: "pp-country-dial", children: country.dialCode })
1719
+ ]
1720
+ },
1721
+ country.code
1722
+ )) })
1723
+ ] })
1724
+ ] }),
1725
+ /* @__PURE__ */ jsx(
1726
+ "input",
1727
+ {
1728
+ type: "tel",
1729
+ class: `pp-prechat-input pp-phone-number-input ${phoneError ? "error" : ""}`,
1730
+ placeholder: "612 345 678",
1731
+ value: phone,
1732
+ onInput: handlePhoneChange
1733
+ }
1734
+ )
1735
+ ] }),
1736
+ phoneError && /* @__PURE__ */ jsx("div", { class: "pp-prechat-error", children: phoneError })
1737
+ ] });
1738
+ return /* @__PURE__ */ jsxs("div", { class: "pp-prechat", children: [
1739
+ /* @__PURE__ */ jsx("h2", { class: "pp-prechat-title", children: "How can we reach you?" }),
1740
+ /* @__PURE__ */ 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." }),
1741
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
1742
+ showChoice && /* @__PURE__ */ jsxs("div", { class: "pp-prechat-tabs", children: [
1743
+ /* @__PURE__ */ jsxs(
1744
+ "button",
1745
+ {
1746
+ type: "button",
1747
+ class: `pp-prechat-tab ${activeTab === "email" ? "active" : ""}`,
1748
+ onClick: () => {
1749
+ setActiveTab("email");
1750
+ setPhoneError("");
1751
+ },
1752
+ children: [
1753
+ /* @__PURE__ */ jsx(EmailIcon, {}),
1754
+ "Email"
1755
+ ]
1756
+ }
1757
+ ),
1758
+ /* @__PURE__ */ jsxs(
1759
+ "button",
1760
+ {
1761
+ type: "button",
1762
+ class: `pp-prechat-tab ${activeTab === "phone" ? "active" : ""}`,
1763
+ onClick: () => {
1764
+ setActiveTab("phone");
1765
+ setEmailError("");
1766
+ },
1767
+ children: [
1768
+ /* @__PURE__ */ jsx(PhoneIcon, {}),
1769
+ "Phone"
1770
+ ]
1771
+ }
1772
+ )
1773
+ ] }),
1774
+ showEmailOnly && renderEmailField(),
1775
+ showPhoneOnly && renderPhoneField(),
1776
+ showBoth && /* @__PURE__ */ jsxs(Fragment, { children: [
1777
+ renderEmailField(),
1778
+ renderPhoneField()
1779
+ ] }),
1780
+ showChoice && /* @__PURE__ */ jsxs(Fragment, { children: [
1781
+ activeTab === "email" && renderEmailField(),
1782
+ activeTab === "phone" && renderPhoneField()
1783
+ ] }),
1784
+ /* @__PURE__ */ jsx("button", { type: "submit", class: "pp-prechat-submit", disabled: isSubmitting, children: isSubmitting ? "Submitting..." : "Start chatting" }),
1785
+ !config.required && /* @__PURE__ */ jsx("button", { type: "button", class: "pp-prechat-skip", onClick: onSkip, children: "Skip for now" })
1786
+ ] })
1787
+ ] });
1788
+ }
1789
+
1020
1790
  // src/components/ChatWidget.tsx
1021
- import { Fragment as Fragment2, jsx, jsxs } from "preact/jsx-runtime";
1791
+ import { Fragment as Fragment3, jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
1792
+ function formatDateSeparator(date) {
1793
+ const now = /* @__PURE__ */ new Date();
1794
+ const messageDate = new Date(date);
1795
+ const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
1796
+ const msgDay = new Date(messageDate.getFullYear(), messageDate.getMonth(), messageDate.getDate());
1797
+ const diffDays = Math.floor((today.getTime() - msgDay.getTime()) / (1e3 * 60 * 60 * 24));
1798
+ if (diffDays === 0) return "Today";
1799
+ if (diffDays === 1) return "Yesterday";
1800
+ return messageDate.toLocaleDateString("en-US", {
1801
+ month: "short",
1802
+ day: "numeric",
1803
+ year: messageDate.getFullYear() !== now.getFullYear() ? "numeric" : void 0
1804
+ });
1805
+ }
1806
+ function getDateKey(date) {
1807
+ const d = new Date(date);
1808
+ return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
1809
+ }
1022
1810
  function ChatWidget({ client: client2, config: initialConfig }) {
1023
- const [isOpen, setIsOpen] = useState(false);
1024
- const [messages, setMessages] = useState([]);
1025
- const [inputValue, setInputValue] = useState("");
1026
- const [isTyping, setIsTyping] = useState(false);
1027
- const [operatorOnline, setOperatorOnline] = useState(false);
1028
- const [isConnected, setIsConnected] = useState(false);
1029
- const [unreadCount, setUnreadCount] = useState(0);
1030
- const [pendingAttachments, setPendingAttachments] = useState([]);
1031
- const [isUploading, setIsUploading] = useState(false);
1032
- const [replyingTo, setReplyingTo] = useState(null);
1033
- const [editingMessage, setEditingMessage] = useState(null);
1034
- const [editContent, setEditContent] = useState("");
1035
- const [messageMenu, setMessageMenu] = useState(null);
1036
- const [isDragging, setIsDragging] = useState(false);
1037
- const [hoveredMessageId, setHoveredMessageId] = useState(null);
1038
- const [longPressTimer, setLongPressTimer] = useState(null);
1039
- const [config, setConfig] = useState(initialConfig);
1040
- const messagesEndRef = useRef(null);
1041
- const inputRef = useRef(null);
1042
- const fileInputRef = useRef(null);
1043
- const messagesContainerRef = useRef(null);
1044
- useEffect(() => {
1811
+ const [isOpen, setIsOpen] = useState2(false);
1812
+ const [messages, setMessages] = useState2([]);
1813
+ const [inputValue, setInputValue] = useState2("");
1814
+ const [isTyping, setIsTyping] = useState2(false);
1815
+ const [operatorOnline, setOperatorOnline] = useState2(false);
1816
+ const [isConnected, setIsConnected] = useState2(false);
1817
+ const [unreadCount, setUnreadCount] = useState2(0);
1818
+ const [pendingAttachments, setPendingAttachments] = useState2([]);
1819
+ const [isUploading, setIsUploading] = useState2(false);
1820
+ const [replyingTo, setReplyingTo] = useState2(null);
1821
+ const [editingMessage, setEditingMessage] = useState2(null);
1822
+ const [editContent, setEditContent] = useState2("");
1823
+ const [messageMenu, setMessageMenu] = useState2(null);
1824
+ const [isDragging, setIsDragging] = useState2(false);
1825
+ const [hoveredMessageId, setHoveredMessageId] = useState2(null);
1826
+ const [longPressTimer, setLongPressTimer] = useState2(null);
1827
+ const [swipedMessageId, setSwipedMessageId] = useState2(null);
1828
+ const [swipeOffset, setSwipeOffset] = useState2(0);
1829
+ const touchStartRef = useRef2(null);
1830
+ const [config, setConfig] = useState2(initialConfig);
1831
+ const [preChatForm, setPreChatForm] = useState2(void 0);
1832
+ const [preChatSkipped, setPreChatSkipped] = useState2(false);
1833
+ const messagesEndRef = useRef2(null);
1834
+ const inputRef = useRef2(null);
1835
+ const fileInputRef = useRef2(null);
1836
+ const messagesContainerRef = useRef2(null);
1837
+ useEffect2(() => {
1045
1838
  const unsubOpen = client2.on("openChange", setIsOpen);
1046
1839
  const unsubMessage = client2.on("message", () => {
1047
1840
  setMessages([...client2.getMessages()]);
@@ -1057,6 +1850,10 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1057
1850
  setMessages(client2.getMessages());
1058
1851
  setOperatorOnline(client2.getSession()?.operatorOnline ?? false);
1059
1852
  setConfig(client2.getConfig());
1853
+ setPreChatForm(client2.getSession()?.preChatForm);
1854
+ });
1855
+ const unsubPreChat = client2.on("preChatCompleted", () => {
1856
+ setPreChatForm((prev) => prev ? { ...prev, completed: true } : prev);
1060
1857
  });
1061
1858
  const unsubConfig = client2.on("configUpdate", () => {
1062
1859
  setConfig(client2.getConfig());
@@ -1066,6 +1863,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1066
1863
  setMessages(client2.getMessages());
1067
1864
  setOperatorOnline(client2.getSession()?.operatorOnline ?? false);
1068
1865
  setConfig(client2.getConfig());
1866
+ setPreChatForm(client2.getSession()?.preChatForm);
1069
1867
  }
1070
1868
  return () => {
1071
1869
  unsubOpen();
@@ -1073,15 +1871,16 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1073
1871
  unsubTyping();
1074
1872
  unsubPresence();
1075
1873
  unsubConnect();
1874
+ unsubPreChat();
1076
1875
  unsubConfig();
1077
1876
  };
1078
1877
  }, [client2]);
1079
- useEffect(() => {
1878
+ useEffect2(() => {
1080
1879
  if (isOpen) {
1081
1880
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
1082
1881
  }
1083
1882
  }, [messages, isOpen]);
1084
- useEffect(() => {
1883
+ useEffect2(() => {
1085
1884
  if (isOpen) {
1086
1885
  setTimeout(() => {
1087
1886
  messagesEndRef.current?.scrollIntoView({ behavior: "auto" });
@@ -1090,7 +1889,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1090
1889
  setUnreadCount(0);
1091
1890
  }
1092
1891
  }, [isOpen]);
1093
- useEffect(() => {
1892
+ useEffect2(() => {
1094
1893
  if (!isOpen && messages.length > 0) {
1095
1894
  const unread = messages.filter(
1096
1895
  (msg) => msg.sender !== "visitor" && msg.status !== "read"
@@ -1108,14 +1907,14 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1108
1907
  client2.sendReadStatus(messageIds, "read");
1109
1908
  }
1110
1909
  }, [isOpen, isConnected, messages, client2]);
1111
- useEffect(() => {
1910
+ useEffect2(() => {
1112
1911
  if (!isOpen || !isConnected) return;
1113
1912
  const timer = setTimeout(() => {
1114
1913
  markMessagesAsRead();
1115
1914
  }, 1e3);
1116
1915
  return () => clearTimeout(timer);
1117
1916
  }, [isOpen, isConnected, messages, markMessagesAsRead]);
1118
- useEffect(() => {
1917
+ useEffect2(() => {
1119
1918
  const handleVisibilityChange = () => {
1120
1919
  if (document.visibilityState === "visible" && isOpen) {
1121
1920
  markMessagesAsRead();
@@ -1124,7 +1923,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1124
1923
  document.addEventListener("visibilitychange", handleVisibilityChange);
1125
1924
  return () => document.removeEventListener("visibilitychange", handleVisibilityChange);
1126
1925
  }, [isOpen, markMessagesAsRead]);
1127
- useEffect(() => {
1926
+ useEffect2(() => {
1128
1927
  const unsubRead = client2.on(
1129
1928
  "read",
1130
1929
  () => {
@@ -1263,26 +2062,43 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1263
2062
  y: mouseEvent.clientY
1264
2063
  });
1265
2064
  };
1266
- const handleTouchStart = (message) => {
1267
- const timer = setTimeout(() => {
1268
- if (navigator.vibrate) navigator.vibrate(50);
1269
- setMessageMenu({
1270
- message,
1271
- x: window.innerWidth / 2 - 60,
1272
- // Center horizontally
1273
- y: window.innerHeight / 2 - 50
1274
- // Center vertically
1275
- });
1276
- }, 500);
1277
- setLongPressTimer(timer);
2065
+ const handleTouchStart = (e, message) => {
2066
+ const touch = e.touches[0];
2067
+ touchStartRef.current = { x: touch.clientX, y: touch.clientY, time: Date.now() };
2068
+ if (swipedMessageId && swipedMessageId !== message.id) {
2069
+ setSwipedMessageId(null);
2070
+ setSwipeOffset(0);
2071
+ }
1278
2072
  };
1279
- const handleTouchEnd = () => {
1280
- if (longPressTimer) {
1281
- clearTimeout(longPressTimer);
1282
- setLongPressTimer(null);
2073
+ const handleTouchMove = (e, message) => {
2074
+ if (!touchStartRef.current) return;
2075
+ const touch = e.touches[0];
2076
+ const deltaX = touch.clientX - touchStartRef.current.x;
2077
+ const deltaY = touch.clientY - touchStartRef.current.y;
2078
+ if (Math.abs(deltaY) > Math.abs(deltaX)) return;
2079
+ if (deltaX < 0) {
2080
+ const offset = Math.max(deltaX, -100);
2081
+ setSwipeOffset(offset);
2082
+ setSwipedMessageId(message.id);
1283
2083
  }
1284
2084
  };
1285
- useEffect(() => {
2085
+ const handleTouchEnd = (message) => {
2086
+ if (!touchStartRef.current) return;
2087
+ const elapsed = Date.now() - touchStartRef.current.time;
2088
+ if (swipeOffset < -50 || swipeOffset < -20 && elapsed < 200) {
2089
+ setSwipeOffset(-80);
2090
+ if (navigator.vibrate) navigator.vibrate(30);
2091
+ } else {
2092
+ setSwipeOffset(0);
2093
+ setSwipedMessageId(null);
2094
+ }
2095
+ touchStartRef.current = null;
2096
+ };
2097
+ const resetSwipe = () => {
2098
+ setSwipedMessageId(null);
2099
+ setSwipeOffset(0);
2100
+ };
2101
+ useEffect2(() => {
1286
2102
  if (!messageMenu) return;
1287
2103
  const handleClickOutside = () => setMessageMenu(null);
1288
2104
  document.addEventListener("click", handleClickOutside);
@@ -1298,7 +2114,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1298
2114
  }, 1500);
1299
2115
  }
1300
2116
  };
1301
- const dragCounterRef = useRef(0);
2117
+ const dragCounterRef = useRef2(0);
1302
2118
  const handleDragEnter = (e) => {
1303
2119
  e.preventDefault();
1304
2120
  e.stopPropagation();
@@ -1374,22 +2190,24 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1374
2190
  const theme = getTheme(config.theme ?? "auto");
1375
2191
  const primaryColor = config.primaryColor ?? "#6366f1";
1376
2192
  const actionIconColor = theme === "dark" ? "#9ca3af" : "#6b7280";
1377
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1378
- /* @__PURE__ */ jsx("style", { children: styles(primaryColor, theme) }),
1379
- /* @__PURE__ */ jsxs(
2193
+ const shouldShowPreChat = preChatForm && preChatForm.enabled && !preChatForm.completed && !preChatSkipped && // Before first message: show immediately
2194
+ (preChatForm.timing === "before-first-message" && messages.length === 0 || preChatForm.timing === "after-first-message" && messages.some((m) => m.sender === "visitor"));
2195
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
2196
+ /* @__PURE__ */ jsx2("style", { children: styles(primaryColor, theme) }),
2197
+ /* @__PURE__ */ jsxs2(
1380
2198
  "button",
1381
2199
  {
1382
2200
  class: `pp-toggle pp-${position}`,
1383
2201
  onClick: () => client2.toggleOpen(),
1384
2202
  "aria-label": isOpen ? "Close chat" : "Open chat",
1385
2203
  children: [
1386
- isOpen ? /* @__PURE__ */ jsx(CloseIcon, {}) : /* @__PURE__ */ jsx(ChatIcon, {}),
1387
- !isOpen && unreadCount > 0 && /* @__PURE__ */ jsx("span", { class: "pp-unread-badge", children: unreadCount > 9 ? "9+" : unreadCount }),
1388
- !isOpen && unreadCount === 0 && operatorOnline && /* @__PURE__ */ jsx("span", { class: "pp-online-dot" })
2204
+ isOpen ? /* @__PURE__ */ jsx2(CloseIcon, {}) : /* @__PURE__ */ jsx2(ChatIcon, {}),
2205
+ !isOpen && unreadCount > 0 && /* @__PURE__ */ jsx2("span", { class: "pp-unread-badge", children: unreadCount > 9 ? "9+" : unreadCount }),
2206
+ !isOpen && unreadCount === 0 && operatorOnline && /* @__PURE__ */ jsx2("span", { class: "pp-online-dot" })
1389
2207
  ]
1390
2208
  }
1391
2209
  ),
1392
- isOpen && /* @__PURE__ */ jsxs(
2210
+ isOpen && /* @__PURE__ */ jsxs2(
1393
2211
  "div",
1394
2212
  {
1395
2213
  class: `pp-window pp-${position} pp-theme-${theme} ${isDragging ? "pp-dragging" : ""}`,
@@ -1398,39 +2216,55 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1398
2216
  onDragLeave: handleDragLeave,
1399
2217
  onDrop: handleDrop,
1400
2218
  children: [
1401
- isDragging && /* @__PURE__ */ jsxs("div", { class: "pp-drop-overlay", children: [
1402
- /* @__PURE__ */ jsx("div", { class: "pp-drop-icon", children: /* @__PURE__ */ jsx(AttachIcon, {}) }),
1403
- /* @__PURE__ */ jsx("div", { class: "pp-drop-text", children: "Drop files to upload" })
2219
+ isDragging && /* @__PURE__ */ jsxs2("div", { class: "pp-drop-overlay", children: [
2220
+ /* @__PURE__ */ jsx2("div", { class: "pp-drop-icon", children: /* @__PURE__ */ jsx2(AttachIcon, {}) }),
2221
+ /* @__PURE__ */ jsx2("div", { class: "pp-drop-text", children: "Drop files to upload" })
1404
2222
  ] }),
1405
- /* @__PURE__ */ jsxs("div", { class: "pp-header", children: [
1406
- /* @__PURE__ */ jsxs("div", { class: "pp-header-info", children: [
1407
- config.operatorAvatar && /* @__PURE__ */ jsx("img", { src: config.operatorAvatar, alt: "", class: "pp-avatar" }),
1408
- /* @__PURE__ */ jsxs("div", { children: [
1409
- /* @__PURE__ */ jsx("div", { class: "pp-header-title", children: config.operatorName ?? "Support" }),
1410
- /* @__PURE__ */ jsx("div", { class: "pp-header-status", children: operatorOnline ? /* @__PURE__ */ jsxs(Fragment2, { children: [
1411
- /* @__PURE__ */ jsx("span", { class: "pp-status-dot pp-online" }),
2223
+ /* @__PURE__ */ jsxs2("div", { class: "pp-header", children: [
2224
+ /* @__PURE__ */ jsxs2("div", { class: "pp-header-info", children: [
2225
+ config.operatorAvatar && /* @__PURE__ */ jsx2("img", { src: config.operatorAvatar, alt: "", class: "pp-avatar" }),
2226
+ /* @__PURE__ */ jsxs2("div", { children: [
2227
+ /* @__PURE__ */ jsx2("div", { class: "pp-header-title", children: config.operatorName ?? "Support" }),
2228
+ /* @__PURE__ */ jsx2("div", { class: "pp-header-status", children: operatorOnline ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
2229
+ /* @__PURE__ */ jsx2("span", { class: "pp-status-dot pp-online" }),
1412
2230
  " Online"
1413
- ] }) : /* @__PURE__ */ jsxs(Fragment2, { children: [
1414
- /* @__PURE__ */ jsx("span", { class: "pp-status-dot" }),
2231
+ ] }) : /* @__PURE__ */ jsxs2(Fragment3, { children: [
2232
+ /* @__PURE__ */ jsx2("span", { class: "pp-status-dot" }),
1415
2233
  " Away"
1416
2234
  ] }) })
1417
2235
  ] })
1418
2236
  ] }),
1419
- /* @__PURE__ */ jsx(
2237
+ /* @__PURE__ */ jsx2(
1420
2238
  "button",
1421
2239
  {
1422
2240
  class: "pp-close-btn",
1423
2241
  onClick: () => client2.setOpen(false),
1424
2242
  "aria-label": "Close chat",
1425
- children: /* @__PURE__ */ jsx(CloseIcon, {})
2243
+ children: /* @__PURE__ */ jsx2(CloseIcon, {})
1426
2244
  }
1427
2245
  )
1428
2246
  ] }),
1429
- /* @__PURE__ */ jsxs("div", { class: "pp-messages", ref: messagesContainerRef, children: [
1430
- config.welcomeMessage && messages.length === 0 && /* @__PURE__ */ jsx("div", { class: "pp-welcome", children: config.welcomeMessage }),
1431
- messages.map((msg) => {
2247
+ shouldShowPreChat && preChatForm && /* @__PURE__ */ jsx2(
2248
+ PreChatForm,
2249
+ {
2250
+ client: client2,
2251
+ config: preChatForm,
2252
+ onComplete: () => {
2253
+ setPreChatForm((prev) => prev ? { ...prev, completed: true } : prev);
2254
+ },
2255
+ onSkip: () => {
2256
+ setPreChatSkipped(true);
2257
+ }
2258
+ }
2259
+ ),
2260
+ !shouldShowPreChat && /* @__PURE__ */ jsxs2("div", { class: "pp-messages", ref: messagesContainerRef, onClick: () => swipedMessageId && resetSwipe(), children: [
2261
+ config.welcomeMessage && messages.length === 0 && /* @__PURE__ */ jsx2("div", { class: "pp-welcome", children: config.welcomeMessage }),
2262
+ messages.map((msg, index) => {
1432
2263
  const isDeleted = !!msg.deletedAt;
1433
2264
  const isEdited = !!msg.editedAt;
2265
+ const msgDate = new Date(msg.timestamp);
2266
+ const prevMsg = index > 0 ? messages[index - 1] : null;
2267
+ const showDateSeparator = !prevMsg || getDateKey(new Date(prevMsg.timestamp)) !== getDateKey(msgDate);
1434
2268
  let replyData = null;
1435
2269
  if (msg.replyTo) {
1436
2270
  if (typeof msg.replyTo === "object") {
@@ -1452,123 +2286,168 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1452
2286
  }
1453
2287
  const isHovered = hoveredMessageId === msg.id;
1454
2288
  const showActions = isHovered && !isDeleted;
1455
- return /* @__PURE__ */ jsxs(
1456
- "div",
1457
- {
1458
- id: `pp-msg-${msg.id}`,
1459
- class: `pp-message pp-message-${msg.sender} ${isDeleted ? "pp-message-deleted" : ""}`,
1460
- onContextMenu: (e) => handleMessageContextMenu(e, msg),
1461
- onMouseEnter: () => setHoveredMessageId(msg.id),
1462
- onMouseLeave: () => setHoveredMessageId(null),
1463
- onTouchStart: () => handleTouchStart(msg),
1464
- onTouchEnd: handleTouchEnd,
1465
- onTouchCancel: handleTouchEnd,
1466
- children: [
1467
- showActions && /* @__PURE__ */ jsxs("div", { class: `pp-message-actions ${msg.sender === "visitor" ? "pp-actions-left" : "pp-actions-right"}`, children: [
1468
- /* @__PURE__ */ jsx(
2289
+ const isSwiped = swipedMessageId === msg.id;
2290
+ const msgSwipeOffset = isSwiped ? swipeOffset : 0;
2291
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
2292
+ showDateSeparator && /* @__PURE__ */ jsx2("div", { class: "pp-date-separator", children: /* @__PURE__ */ jsx2("span", { children: formatDateSeparator(msgDate) }) }),
2293
+ /* @__PURE__ */ jsxs2("div", { class: `pp-message-swipe-container ${msg.sender === "visitor" ? "pp-swipe-left" : "pp-swipe-right"}`, children: [
2294
+ /* @__PURE__ */ jsxs2("div", { class: "pp-swipe-actions", children: [
2295
+ /* @__PURE__ */ jsx2(
2296
+ "button",
2297
+ {
2298
+ class: "pp-swipe-action pp-swipe-reply",
2299
+ onClick: () => {
2300
+ handleReply(msg);
2301
+ resetSwipe();
2302
+ },
2303
+ children: /* @__PURE__ */ jsx2(ReplyIcon, { color: "#fff" })
2304
+ }
2305
+ ),
2306
+ msg.sender === "visitor" && !isDeleted && /* @__PURE__ */ jsxs2(Fragment3, { children: [
2307
+ /* @__PURE__ */ jsx2(
1469
2308
  "button",
1470
2309
  {
1471
- class: "pp-action-btn",
1472
- onClick: () => handleReply(msg),
1473
- title: "Reply",
1474
- children: /* @__PURE__ */ jsx(ReplyIcon, { color: actionIconColor })
2310
+ class: "pp-swipe-action pp-swipe-edit",
2311
+ onClick: () => {
2312
+ handleStartEdit(msg);
2313
+ resetSwipe();
2314
+ },
2315
+ children: /* @__PURE__ */ jsx2(EditIcon, { color: "#fff" })
1475
2316
  }
1476
2317
  ),
1477
- msg.sender === "visitor" && /* @__PURE__ */ jsxs(Fragment2, { children: [
1478
- /* @__PURE__ */ jsx(
1479
- "button",
2318
+ /* @__PURE__ */ jsx2(
2319
+ "button",
2320
+ {
2321
+ class: "pp-swipe-action pp-swipe-delete",
2322
+ onClick: () => {
2323
+ handleDelete(msg);
2324
+ resetSwipe();
2325
+ },
2326
+ children: /* @__PURE__ */ jsx2(DeleteIcon, { color: "#fff" })
2327
+ }
2328
+ )
2329
+ ] })
2330
+ ] }),
2331
+ /* @__PURE__ */ jsxs2(
2332
+ "div",
2333
+ {
2334
+ id: `pp-msg-${msg.id}`,
2335
+ class: `pp-message pp-message-${msg.sender} ${isDeleted ? "pp-message-deleted" : ""}`,
2336
+ style: { transform: `translateX(${msgSwipeOffset}px)`, transition: touchStartRef.current ? "none" : "transform 0.2s ease-out" },
2337
+ onContextMenu: (e) => handleMessageContextMenu(e, msg),
2338
+ onMouseEnter: () => setHoveredMessageId(msg.id),
2339
+ onMouseLeave: () => setHoveredMessageId(null),
2340
+ onTouchStart: (e) => handleTouchStart(e, msg),
2341
+ onTouchMove: (e) => handleTouchMove(e, msg),
2342
+ onTouchEnd: () => handleTouchEnd(msg),
2343
+ onTouchCancel: () => handleTouchEnd(msg),
2344
+ children: [
2345
+ showActions && /* @__PURE__ */ jsxs2("div", { class: `pp-message-actions ${msg.sender === "visitor" ? "pp-actions-left" : "pp-actions-right"}`, children: [
2346
+ /* @__PURE__ */ jsx2(
2347
+ "button",
2348
+ {
2349
+ class: "pp-action-btn",
2350
+ onClick: () => handleReply(msg),
2351
+ title: "Reply",
2352
+ children: /* @__PURE__ */ jsx2(ReplyIcon, { color: actionIconColor })
2353
+ }
2354
+ ),
2355
+ msg.sender === "visitor" && /* @__PURE__ */ jsxs2(Fragment3, { children: [
2356
+ /* @__PURE__ */ jsx2(
2357
+ "button",
2358
+ {
2359
+ class: "pp-action-btn",
2360
+ onClick: () => handleStartEdit(msg),
2361
+ title: "Edit",
2362
+ children: /* @__PURE__ */ jsx2(EditIcon, { color: actionIconColor })
2363
+ }
2364
+ ),
2365
+ /* @__PURE__ */ jsx2(
2366
+ "button",
2367
+ {
2368
+ class: "pp-action-btn pp-action-delete",
2369
+ onClick: () => handleDelete(msg),
2370
+ title: "Delete",
2371
+ children: /* @__PURE__ */ jsx2(DeleteIcon, { color: actionIconColor })
2372
+ }
2373
+ )
2374
+ ] })
2375
+ ] }),
2376
+ replyData && (replyData.content || replyData.hasAttachment) && /* @__PURE__ */ jsxs2(
2377
+ "div",
1480
2378
  {
1481
- class: "pp-action-btn",
1482
- onClick: () => handleStartEdit(msg),
1483
- title: "Edit",
1484
- children: /* @__PURE__ */ jsx(EditIcon, { color: actionIconColor })
2379
+ class: "pp-reply-quote pp-reply-quote-clickable",
2380
+ onClick: () => scrollToMessage(replyData.id),
2381
+ role: "button",
2382
+ tabIndex: 0,
2383
+ onKeyDown: (e) => e.key === "Enter" && scrollToMessage(replyData.id),
2384
+ children: [
2385
+ /* @__PURE__ */ jsx2("span", { class: "pp-reply-sender", children: replyData.sender === "visitor" ? "You" : "Support" }),
2386
+ /* @__PURE__ */ jsx2("span", { class: "pp-reply-content", children: replyData.deleted ? "Message deleted" : /* @__PURE__ */ jsxs2(Fragment3, { children: [
2387
+ replyData.hasAttachment && /* @__PURE__ */ jsx2("span", { class: "pp-reply-attachment-icon", children: replyData.attachmentType?.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
2388
+ replyData.content ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
2389
+ (replyData.content || "").slice(0, 50),
2390
+ (replyData.content || "").length > 50 ? "..." : ""
2391
+ ] }) : replyData.attachmentType?.startsWith("image/") ? "Photo" : "File"
2392
+ ] }) })
2393
+ ]
1485
2394
  }
1486
2395
  ),
1487
- /* @__PURE__ */ jsx(
1488
- "button",
1489
- {
1490
- class: "pp-action-btn pp-action-delete",
1491
- onClick: () => handleDelete(msg),
1492
- title: "Delete",
1493
- children: /* @__PURE__ */ jsx(DeleteIcon, { color: actionIconColor })
1494
- }
1495
- )
1496
- ] })
1497
- ] }),
1498
- replyData && (replyData.content || replyData.hasAttachment) && /* @__PURE__ */ jsxs(
1499
- "div",
1500
- {
1501
- class: "pp-reply-quote pp-reply-quote-clickable",
1502
- onClick: () => scrollToMessage(replyData.id),
1503
- role: "button",
1504
- tabIndex: 0,
1505
- onKeyDown: (e) => e.key === "Enter" && scrollToMessage(replyData.id),
1506
- children: [
1507
- /* @__PURE__ */ jsx("span", { class: "pp-reply-sender", children: replyData.sender === "visitor" ? "You" : "Support" }),
1508
- /* @__PURE__ */ jsx("span", { class: "pp-reply-content", children: replyData.deleted ? "Message deleted" : /* @__PURE__ */ jsxs(Fragment2, { children: [
1509
- replyData.hasAttachment && /* @__PURE__ */ jsx("span", { class: "pp-reply-attachment-icon", children: replyData.attachmentType?.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
1510
- replyData.content ? /* @__PURE__ */ jsxs(Fragment2, { children: [
1511
- (replyData.content || "").slice(0, 50),
1512
- (replyData.content || "").length > 50 ? "..." : ""
1513
- ] }) : replyData.attachmentType?.startsWith("image/") ? "Photo" : "File"
1514
- ] }) })
1515
- ]
1516
- }
1517
- ),
1518
- isDeleted ? /* @__PURE__ */ jsxs("div", { class: "pp-message-content pp-deleted-content", children: [
1519
- /* @__PURE__ */ jsx("span", { class: "pp-deleted-icon", children: "\u{1F5D1}\uFE0F" }),
1520
- " Message deleted"
1521
- ] }) : /* @__PURE__ */ jsxs(Fragment2, { children: [
1522
- msg.content && /* @__PURE__ */ jsx("div", { class: "pp-message-content", children: msg.content }),
1523
- msg.attachments && msg.attachments.length > 0 && /* @__PURE__ */ jsx("div", { class: "pp-message-attachments", children: msg.attachments.map((att) => /* @__PURE__ */ jsx(AttachmentDisplay, { attachment: att }, att.id)) })
1524
- ] }),
1525
- /* @__PURE__ */ jsxs("div", { class: "pp-message-time", children: [
1526
- formatTime(msg.timestamp),
1527
- isEdited && !isDeleted && /* @__PURE__ */ jsx("span", { class: "pp-edited-badge", children: "edited" }),
1528
- msg.sender === "ai" && /* @__PURE__ */ jsx("span", { class: "pp-ai-badge", children: "AI" }),
1529
- msg.sender === "visitor" && !isDeleted && /* @__PURE__ */ jsx("span", { class: `pp-status pp-status-${msg.status ?? "sent"}`, children: /* @__PURE__ */ jsx(StatusIcon, { status: msg.status }) })
1530
- ] })
1531
- ]
1532
- },
1533
- msg.id
1534
- );
2396
+ isDeleted ? /* @__PURE__ */ jsxs2("div", { class: "pp-message-content pp-deleted-content", children: [
2397
+ /* @__PURE__ */ jsx2("span", { class: "pp-deleted-icon", children: "\u{1F5D1}\uFE0F" }),
2398
+ " Message deleted"
2399
+ ] }) : /* @__PURE__ */ jsxs2(Fragment3, { children: [
2400
+ msg.content && /* @__PURE__ */ jsx2("div", { class: "pp-message-content", children: msg.content }),
2401
+ msg.attachments && msg.attachments.length > 0 && /* @__PURE__ */ jsx2("div", { class: "pp-message-attachments", children: msg.attachments.map((att) => /* @__PURE__ */ jsx2(AttachmentDisplay, { attachment: att }, att.id)) })
2402
+ ] }),
2403
+ /* @__PURE__ */ jsxs2("div", { class: "pp-message-time", children: [
2404
+ formatTime(msg.timestamp),
2405
+ isEdited && !isDeleted && /* @__PURE__ */ jsx2("span", { class: "pp-edited-badge", children: "edited" }),
2406
+ msg.sender === "ai" && /* @__PURE__ */ jsx2("span", { class: "pp-ai-badge", children: "AI" }),
2407
+ msg.sender === "visitor" && !isDeleted && /* @__PURE__ */ jsx2("span", { class: `pp-status pp-status-${msg.status ?? "sent"}`, children: /* @__PURE__ */ jsx2(StatusIcon, { status: msg.status }) })
2408
+ ] })
2409
+ ]
2410
+ }
2411
+ )
2412
+ ] })
2413
+ ] }, msg.id);
1535
2414
  }),
1536
- isTyping && /* @__PURE__ */ jsxs("div", { class: "pp-message pp-message-operator pp-typing", children: [
1537
- /* @__PURE__ */ jsx("span", {}),
1538
- /* @__PURE__ */ jsx("span", {}),
1539
- /* @__PURE__ */ jsx("span", {})
2415
+ isTyping && /* @__PURE__ */ jsxs2("div", { class: "pp-message pp-message-operator pp-typing", children: [
2416
+ /* @__PURE__ */ jsx2("span", {}),
2417
+ /* @__PURE__ */ jsx2("span", {}),
2418
+ /* @__PURE__ */ jsx2("span", {})
1540
2419
  ] }),
1541
- /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
2420
+ /* @__PURE__ */ jsx2("div", { ref: messagesEndRef })
1542
2421
  ] }),
1543
- messageMenu && /* @__PURE__ */ jsxs(
2422
+ messageMenu && /* @__PURE__ */ jsxs2(
1544
2423
  "div",
1545
2424
  {
1546
2425
  class: "pp-message-menu",
1547
2426
  style: { top: `${messageMenu.y}px`, left: `${messageMenu.x}px` },
1548
2427
  children: [
1549
- /* @__PURE__ */ jsxs("button", { onClick: () => handleReply(messageMenu.message), children: [
1550
- /* @__PURE__ */ jsx(ReplyIcon, { color: actionIconColor }),
2428
+ /* @__PURE__ */ jsxs2("button", { onClick: () => handleReply(messageMenu.message), children: [
2429
+ /* @__PURE__ */ jsx2(ReplyIcon, { color: actionIconColor }),
1551
2430
  " Reply"
1552
2431
  ] }),
1553
- messageMenu.message.sender === "visitor" && !messageMenu.message.deletedAt && /* @__PURE__ */ jsxs(Fragment2, { children: [
1554
- /* @__PURE__ */ jsxs("button", { onClick: () => handleStartEdit(messageMenu.message), children: [
1555
- /* @__PURE__ */ jsx(EditIcon, { color: actionIconColor }),
2432
+ messageMenu.message.sender === "visitor" && !messageMenu.message.deletedAt && /* @__PURE__ */ jsxs2(Fragment3, { children: [
2433
+ /* @__PURE__ */ jsxs2("button", { onClick: () => handleStartEdit(messageMenu.message), children: [
2434
+ /* @__PURE__ */ jsx2(EditIcon, { color: actionIconColor }),
1556
2435
  " Edit"
1557
2436
  ] }),
1558
- /* @__PURE__ */ jsxs("button", { class: "pp-menu-delete", onClick: () => handleDelete(messageMenu.message), children: [
1559
- /* @__PURE__ */ jsx(DeleteIcon, { color: "#ef4444" }),
2437
+ /* @__PURE__ */ jsxs2("button", { class: "pp-menu-delete", onClick: () => handleDelete(messageMenu.message), children: [
2438
+ /* @__PURE__ */ jsx2(DeleteIcon, { color: "#ef4444" }),
1560
2439
  " Delete"
1561
2440
  ] })
1562
2441
  ] })
1563
2442
  ]
1564
2443
  }
1565
2444
  ),
1566
- editingMessage && /* @__PURE__ */ jsxs("div", { class: "pp-edit-modal", children: [
1567
- /* @__PURE__ */ jsxs("div", { class: "pp-edit-header", children: [
1568
- /* @__PURE__ */ jsx("span", { children: "Edit message" }),
1569
- /* @__PURE__ */ jsx("button", { onClick: handleCancelEdit, children: /* @__PURE__ */ jsx(CloseIcon, {}) })
2445
+ editingMessage && /* @__PURE__ */ jsxs2("div", { class: "pp-edit-modal", children: [
2446
+ /* @__PURE__ */ jsxs2("div", { class: "pp-edit-header", children: [
2447
+ /* @__PURE__ */ jsx2("span", { children: "Edit message" }),
2448
+ /* @__PURE__ */ jsx2("button", { onClick: handleCancelEdit, children: /* @__PURE__ */ jsx2(CloseIcon, {}) })
1570
2449
  ] }),
1571
- /* @__PURE__ */ jsx(
2450
+ /* @__PURE__ */ jsx2(
1572
2451
  "textarea",
1573
2452
  {
1574
2453
  class: "pp-edit-input",
@@ -1577,41 +2456,41 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1577
2456
  autoFocus: true
1578
2457
  }
1579
2458
  ),
1580
- /* @__PURE__ */ jsxs("div", { class: "pp-edit-actions", children: [
1581
- /* @__PURE__ */ jsx("button", { class: "pp-edit-cancel", onClick: handleCancelEdit, children: "Cancel" }),
1582
- /* @__PURE__ */ jsx("button", { class: "pp-edit-save", onClick: handleSaveEdit, disabled: !editContent.trim(), children: "Save" })
2459
+ /* @__PURE__ */ jsxs2("div", { class: "pp-edit-actions", children: [
2460
+ /* @__PURE__ */ jsx2("button", { class: "pp-edit-cancel", onClick: handleCancelEdit, children: "Cancel" }),
2461
+ /* @__PURE__ */ jsx2("button", { class: "pp-edit-save", onClick: handleSaveEdit, disabled: !editContent.trim(), children: "Save" })
1583
2462
  ] })
1584
2463
  ] }),
1585
- replyingTo && /* @__PURE__ */ jsxs("div", { class: "pp-reply-preview", children: [
1586
- /* @__PURE__ */ jsxs("div", { class: "pp-reply-preview-content", children: [
1587
- /* @__PURE__ */ jsx("span", { class: "pp-reply-label", children: "Replying to" }),
1588
- /* @__PURE__ */ jsxs("span", { class: "pp-reply-text", children: [
1589
- replyingTo.attachments && replyingTo.attachments.length > 0 && /* @__PURE__ */ jsx("span", { class: "pp-reply-attachment-icon", children: replyingTo.attachments[0].mimeType.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
1590
- replyingTo.content ? /* @__PURE__ */ jsxs(Fragment2, { children: [
2464
+ replyingTo && /* @__PURE__ */ jsxs2("div", { class: "pp-reply-preview", children: [
2465
+ /* @__PURE__ */ jsxs2("div", { class: "pp-reply-preview-content", children: [
2466
+ /* @__PURE__ */ jsx2("span", { class: "pp-reply-label", children: "Replying to" }),
2467
+ /* @__PURE__ */ jsxs2("span", { class: "pp-reply-text", children: [
2468
+ replyingTo.attachments && replyingTo.attachments.length > 0 && /* @__PURE__ */ jsx2("span", { class: "pp-reply-attachment-icon", children: replyingTo.attachments[0].mimeType.startsWith("image/") ? "\u{1F4F7} " : "\u{1F4CE} " }),
2469
+ replyingTo.content ? /* @__PURE__ */ jsxs2(Fragment3, { children: [
1591
2470
  replyingTo.content.slice(0, 50),
1592
2471
  replyingTo.content.length > 50 ? "..." : ""
1593
2472
  ] }) : replyingTo.attachments?.[0]?.mimeType.startsWith("image/") ? "Photo" : "File"
1594
2473
  ] })
1595
2474
  ] }),
1596
- /* @__PURE__ */ jsx("button", { class: "pp-reply-cancel", onClick: handleCancelReply, children: /* @__PURE__ */ jsx(CloseIcon, {}) })
2475
+ /* @__PURE__ */ jsx2("button", { class: "pp-reply-cancel", onClick: handleCancelReply, children: /* @__PURE__ */ jsx2(CloseIcon, {}) })
1597
2476
  ] }),
1598
- pendingAttachments.length > 0 && /* @__PURE__ */ jsx("div", { class: "pp-attachments-preview", children: pendingAttachments.map((pending) => /* @__PURE__ */ jsxs("div", { class: `pp-attachment-preview pp-attachment-${pending.status}`, children: [
1599
- pending.preview ? /* @__PURE__ */ jsx("img", { src: pending.preview, alt: pending.file.name, class: "pp-preview-img" }) : /* @__PURE__ */ jsx("div", { class: "pp-preview-file", children: /* @__PURE__ */ jsx(FileIcon, { mimeType: pending.file.type }) }),
1600
- /* @__PURE__ */ jsx(
2477
+ pendingAttachments.length > 0 && /* @__PURE__ */ jsx2("div", { class: "pp-attachments-preview", children: pendingAttachments.map((pending) => /* @__PURE__ */ jsxs2("div", { class: `pp-attachment-preview pp-attachment-${pending.status}`, children: [
2478
+ pending.preview ? /* @__PURE__ */ jsx2("img", { src: pending.preview, alt: pending.file.name, class: "pp-preview-img" }) : /* @__PURE__ */ jsx2("div", { class: "pp-preview-file", children: /* @__PURE__ */ jsx2(FileIcon, { mimeType: pending.file.type }) }),
2479
+ /* @__PURE__ */ jsx2(
1601
2480
  "button",
1602
2481
  {
1603
2482
  class: "pp-remove-attachment",
1604
2483
  onClick: () => handleRemoveAttachment(pending.id),
1605
2484
  "aria-label": "Remove attachment",
1606
2485
  type: "button",
1607
- children: /* @__PURE__ */ jsx(CloseIcon, {})
2486
+ children: /* @__PURE__ */ jsx2(CloseIcon, {})
1608
2487
  }
1609
2488
  ),
1610
- pending.status === "uploading" && /* @__PURE__ */ jsx("div", { class: "pp-upload-progress", style: { width: `${pending.progress}%` } }),
1611
- pending.status === "error" && /* @__PURE__ */ jsx("div", { class: "pp-upload-error", title: pending.error, children: "!" })
2489
+ pending.status === "uploading" && /* @__PURE__ */ jsx2("div", { class: "pp-upload-progress", style: { width: `${pending.progress}%` } }),
2490
+ pending.status === "error" && /* @__PURE__ */ jsx2("div", { class: "pp-upload-error", title: pending.error, children: "!" })
1612
2491
  ] }, pending.id)) }),
1613
- /* @__PURE__ */ jsxs("form", { class: "pp-input-form", onSubmit: handleSubmit, children: [
1614
- /* @__PURE__ */ jsx(
2492
+ !shouldShowPreChat && /* @__PURE__ */ jsxs2("form", { class: "pp-input-form", onSubmit: handleSubmit, children: [
2493
+ /* @__PURE__ */ jsx2(
1615
2494
  "input",
1616
2495
  {
1617
2496
  ref: (el) => {
@@ -1626,7 +2505,7 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1626
2505
  multiple: true
1627
2506
  }
1628
2507
  ),
1629
- /* @__PURE__ */ jsx(
2508
+ /* @__PURE__ */ jsx2(
1630
2509
  "button",
1631
2510
  {
1632
2511
  type: "button",
@@ -1634,10 +2513,10 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1634
2513
  onClick: () => fileInputRef.current?.click(),
1635
2514
  disabled: !isConnected || isUploading,
1636
2515
  "aria-label": "Attach file",
1637
- children: /* @__PURE__ */ jsx(AttachIcon, {})
2516
+ children: /* @__PURE__ */ jsx2(AttachIcon, {})
1638
2517
  }
1639
2518
  ),
1640
- /* @__PURE__ */ jsx(
2519
+ /* @__PURE__ */ jsx2(
1641
2520
  "input",
1642
2521
  {
1643
2522
  ref: inputRef,
@@ -1649,20 +2528,20 @@ function ChatWidget({ client: client2, config: initialConfig }) {
1649
2528
  disabled: !isConnected
1650
2529
  }
1651
2530
  ),
1652
- /* @__PURE__ */ jsx(
2531
+ /* @__PURE__ */ jsx2(
1653
2532
  "button",
1654
2533
  {
1655
2534
  type: "submit",
1656
2535
  class: "pp-send-btn",
1657
2536
  disabled: !inputValue.trim() && pendingAttachments.filter((a) => a.status === "ready").length === 0 || !isConnected || isUploading,
1658
2537
  "aria-label": "Send message",
1659
- children: /* @__PURE__ */ jsx(SendIcon, {})
2538
+ children: /* @__PURE__ */ jsx2(SendIcon, {})
1660
2539
  }
1661
2540
  )
1662
2541
  ] }),
1663
- /* @__PURE__ */ jsxs("div", { class: "pp-footer", children: [
2542
+ /* @__PURE__ */ jsxs2("div", { class: "pp-footer", children: [
1664
2543
  "Powered by ",
1665
- /* @__PURE__ */ jsx("a", { href: "https://pocketping.io", target: "_blank", rel: "noopener", children: "PocketPing" })
2544
+ /* @__PURE__ */ jsx2("a", { href: "https://pocketping.io", target: "_blank", rel: "noopener", children: "PocketPing" })
1666
2545
  ] })
1667
2546
  ]
1668
2547
  }
@@ -1690,90 +2569,90 @@ function formatTime(timestamp) {
1690
2569
  return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
1691
2570
  }
1692
2571
  function ChatIcon() {
1693
- return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ 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" }) });
2572
+ return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ jsx2("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
1694
2573
  }
1695
2574
  function CloseIcon() {
1696
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1697
- /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1698
- /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
2575
+ return /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2576
+ /* @__PURE__ */ jsx2("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
2577
+ /* @__PURE__ */ jsx2("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1699
2578
  ] });
1700
2579
  }
1701
2580
  function SendIcon() {
1702
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1703
- /* @__PURE__ */ jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
1704
- /* @__PURE__ */ jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
2581
+ return /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2582
+ /* @__PURE__ */ jsx2("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
2583
+ /* @__PURE__ */ jsx2("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
1705
2584
  ] });
1706
2585
  }
1707
2586
  function StatusIcon({ status }) {
1708
2587
  if (!status || status === "sending" || status === "sent") {
1709
- return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check", children: /* @__PURE__ */ jsx("polyline", { points: "3 8 7 12 13 4" }) });
2588
+ return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check", children: /* @__PURE__ */ jsx2("polyline", { points: "3 8 7 12 13 4" }) });
1710
2589
  }
1711
2590
  if (status === "delivered") {
1712
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double", children: [
1713
- /* @__PURE__ */ jsx("polyline", { points: "1 8 5 12 11 4" }),
1714
- /* @__PURE__ */ jsx("polyline", { points: "7 8 11 12 17 4" })
2591
+ return /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double", children: [
2592
+ /* @__PURE__ */ jsx2("polyline", { points: "1 8 5 12 11 4" }),
2593
+ /* @__PURE__ */ jsx2("polyline", { points: "7 8 11 12 17 4" })
1715
2594
  ] });
1716
2595
  }
1717
2596
  if (status === "read") {
1718
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double pp-check-read", children: [
1719
- /* @__PURE__ */ jsx("polyline", { points: "1 8 5 12 11 4" }),
1720
- /* @__PURE__ */ jsx("polyline", { points: "7 8 11 12 17 4" })
2597
+ return /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double pp-check-read", children: [
2598
+ /* @__PURE__ */ jsx2("polyline", { points: "1 8 5 12 11 4" }),
2599
+ /* @__PURE__ */ jsx2("polyline", { points: "7 8 11 12 17 4" })
1721
2600
  ] });
1722
2601
  }
1723
2602
  return null;
1724
2603
  }
1725
2604
  function AttachIcon() {
1726
- return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ 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" }) });
2605
+ return /* @__PURE__ */ jsx2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ jsx2("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" }) });
1727
2606
  }
1728
2607
  function ReplyIcon({ color, size = 16 }) {
1729
2608
  const strokeColor = color || "currentColor";
1730
- return /* @__PURE__ */ 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: [
1731
- /* @__PURE__ */ jsx("polyline", { points: "9 17 4 12 9 7" }),
1732
- /* @__PURE__ */ jsx("path", { d: "M20 18v-2a4 4 0 0 0-4-4H4" })
2609
+ return /* @__PURE__ */ jsxs2("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: [
2610
+ /* @__PURE__ */ jsx2("polyline", { points: "9 17 4 12 9 7" }),
2611
+ /* @__PURE__ */ jsx2("path", { d: "M20 18v-2a4 4 0 0 0-4-4H4" })
1733
2612
  ] });
1734
2613
  }
1735
2614
  function EditIcon({ color, size = 16 }) {
1736
2615
  const strokeColor = color || "currentColor";
1737
- return /* @__PURE__ */ 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__ */ jsx("path", { d: "M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z" }) });
2616
+ return /* @__PURE__ */ jsx2("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__ */ jsx2("path", { d: "M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z" }) });
1738
2617
  }
1739
2618
  function DeleteIcon({ color, size = 16 }) {
1740
2619
  const strokeColor = color || "currentColor";
1741
- return /* @__PURE__ */ 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: [
1742
- /* @__PURE__ */ jsx("polyline", { points: "3 6 5 6 21 6" }),
1743
- /* @__PURE__ */ 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" })
2620
+ return /* @__PURE__ */ jsxs2("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: [
2621
+ /* @__PURE__ */ jsx2("polyline", { points: "3 6 5 6 21 6" }),
2622
+ /* @__PURE__ */ jsx2("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" })
1744
2623
  ] });
1745
2624
  }
1746
2625
  function FileIcon({ mimeType }) {
1747
2626
  if (mimeType === "application/pdf") {
1748
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1749
- /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1750
- /* @__PURE__ */ jsx("polyline", { points: "14 2 14 8 20 8" }),
1751
- /* @__PURE__ */ jsx("path", { d: "M9 15h6" }),
1752
- /* @__PURE__ */ jsx("path", { d: "M9 11h6" })
2627
+ return /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2628
+ /* @__PURE__ */ jsx2("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
2629
+ /* @__PURE__ */ jsx2("polyline", { points: "14 2 14 8 20 8" }),
2630
+ /* @__PURE__ */ jsx2("path", { d: "M9 15h6" }),
2631
+ /* @__PURE__ */ jsx2("path", { d: "M9 11h6" })
1753
2632
  ] });
1754
2633
  }
1755
2634
  if (mimeType.startsWith("audio/")) {
1756
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1757
- /* @__PURE__ */ jsx("path", { d: "M9 18V5l12-2v13" }),
1758
- /* @__PURE__ */ jsx("circle", { cx: "6", cy: "18", r: "3" }),
1759
- /* @__PURE__ */ jsx("circle", { cx: "18", cy: "16", r: "3" })
2635
+ return /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2636
+ /* @__PURE__ */ jsx2("path", { d: "M9 18V5l12-2v13" }),
2637
+ /* @__PURE__ */ jsx2("circle", { cx: "6", cy: "18", r: "3" }),
2638
+ /* @__PURE__ */ jsx2("circle", { cx: "18", cy: "16", r: "3" })
1760
2639
  ] });
1761
2640
  }
1762
2641
  if (mimeType.startsWith("video/")) {
1763
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1764
- /* @__PURE__ */ jsx("rect", { x: "2", y: "2", width: "20", height: "20", rx: "2.18", ry: "2.18" }),
1765
- /* @__PURE__ */ jsx("line", { x1: "7", y1: "2", x2: "7", y2: "22" }),
1766
- /* @__PURE__ */ jsx("line", { x1: "17", y1: "2", x2: "17", y2: "22" }),
1767
- /* @__PURE__ */ jsx("line", { x1: "2", y1: "12", x2: "22", y2: "12" }),
1768
- /* @__PURE__ */ jsx("line", { x1: "2", y1: "7", x2: "7", y2: "7" }),
1769
- /* @__PURE__ */ jsx("line", { x1: "2", y1: "17", x2: "7", y2: "17" }),
1770
- /* @__PURE__ */ jsx("line", { x1: "17", y1: "17", x2: "22", y2: "17" }),
1771
- /* @__PURE__ */ jsx("line", { x1: "17", y1: "7", x2: "22", y2: "7" })
2642
+ return /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2643
+ /* @__PURE__ */ jsx2("rect", { x: "2", y: "2", width: "20", height: "20", rx: "2.18", ry: "2.18" }),
2644
+ /* @__PURE__ */ jsx2("line", { x1: "7", y1: "2", x2: "7", y2: "22" }),
2645
+ /* @__PURE__ */ jsx2("line", { x1: "17", y1: "2", x2: "17", y2: "22" }),
2646
+ /* @__PURE__ */ jsx2("line", { x1: "2", y1: "12", x2: "22", y2: "12" }),
2647
+ /* @__PURE__ */ jsx2("line", { x1: "2", y1: "7", x2: "7", y2: "7" }),
2648
+ /* @__PURE__ */ jsx2("line", { x1: "2", y1: "17", x2: "7", y2: "17" }),
2649
+ /* @__PURE__ */ jsx2("line", { x1: "17", y1: "17", x2: "22", y2: "17" }),
2650
+ /* @__PURE__ */ jsx2("line", { x1: "17", y1: "7", x2: "22", y2: "7" })
1772
2651
  ] });
1773
2652
  }
1774
- return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
1775
- /* @__PURE__ */ jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1776
- /* @__PURE__ */ jsx("polyline", { points: "14 2 14 8 20 8" })
2653
+ return /* @__PURE__ */ jsxs2("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
2654
+ /* @__PURE__ */ jsx2("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
2655
+ /* @__PURE__ */ jsx2("polyline", { points: "14 2 14 8 20 8" })
1777
2656
  ] });
1778
2657
  }
1779
2658
  function AttachmentDisplay({ attachment }) {
@@ -1786,28 +2665,28 @@ function AttachmentDisplay({ attachment }) {
1786
2665
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
1787
2666
  };
1788
2667
  if (isImage) {
1789
- return /* @__PURE__ */ jsx("a", { href: attachment.url, target: "_blank", rel: "noopener", class: "pp-attachment pp-attachment-image", children: /* @__PURE__ */ jsx("img", { src: attachment.thumbnailUrl || attachment.url, alt: attachment.filename }) });
2668
+ return /* @__PURE__ */ jsx2("a", { href: attachment.url, target: "_blank", rel: "noopener", class: "pp-attachment pp-attachment-image", children: /* @__PURE__ */ jsx2("img", { src: attachment.thumbnailUrl || attachment.url, alt: attachment.filename }) });
1790
2669
  }
1791
2670
  if (isAudio) {
1792
- return /* @__PURE__ */ jsxs("div", { class: "pp-attachment pp-attachment-audio", children: [
1793
- /* @__PURE__ */ jsx("audio", { controls: true, preload: "metadata", children: /* @__PURE__ */ jsx("source", { src: attachment.url, type: attachment.mimeType }) }),
1794
- /* @__PURE__ */ jsx("span", { class: "pp-attachment-name", children: attachment.filename })
2671
+ return /* @__PURE__ */ jsxs2("div", { class: "pp-attachment pp-attachment-audio", children: [
2672
+ /* @__PURE__ */ jsx2("audio", { controls: true, preload: "metadata", children: /* @__PURE__ */ jsx2("source", { src: attachment.url, type: attachment.mimeType }) }),
2673
+ /* @__PURE__ */ jsx2("span", { class: "pp-attachment-name", children: attachment.filename })
1795
2674
  ] });
1796
2675
  }
1797
2676
  if (isVideo) {
1798
- return /* @__PURE__ */ jsx("div", { class: "pp-attachment pp-attachment-video", children: /* @__PURE__ */ jsx("video", { controls: true, preload: "metadata", children: /* @__PURE__ */ jsx("source", { src: attachment.url, type: attachment.mimeType }) }) });
2677
+ return /* @__PURE__ */ jsx2("div", { class: "pp-attachment pp-attachment-video", children: /* @__PURE__ */ jsx2("video", { controls: true, preload: "metadata", children: /* @__PURE__ */ jsx2("source", { src: attachment.url, type: attachment.mimeType }) }) });
1799
2678
  }
1800
- return /* @__PURE__ */ jsxs("a", { href: attachment.url, target: "_blank", rel: "noopener", class: "pp-attachment pp-attachment-file", children: [
1801
- /* @__PURE__ */ jsx(FileIcon, { mimeType: attachment.mimeType }),
1802
- /* @__PURE__ */ jsxs("div", { class: "pp-attachment-info", children: [
1803
- /* @__PURE__ */ jsx("span", { class: "pp-attachment-name", children: attachment.filename }),
1804
- /* @__PURE__ */ jsx("span", { class: "pp-attachment-size", children: formatSize(attachment.size) })
2679
+ return /* @__PURE__ */ jsxs2("a", { href: attachment.url, target: "_blank", rel: "noopener", class: "pp-attachment pp-attachment-file", children: [
2680
+ /* @__PURE__ */ jsx2(FileIcon, { mimeType: attachment.mimeType }),
2681
+ /* @__PURE__ */ jsxs2("div", { class: "pp-attachment-info", children: [
2682
+ /* @__PURE__ */ jsx2("span", { class: "pp-attachment-name", children: attachment.filename }),
2683
+ /* @__PURE__ */ jsx2("span", { class: "pp-attachment-size", children: formatSize(attachment.size) })
1805
2684
  ] })
1806
2685
  ] });
1807
2686
  }
1808
2687
 
1809
2688
  // src/version.ts
1810
- var VERSION = "0.3.6";
2689
+ var VERSION = "0.3.7";
1811
2690
 
1812
2691
  // src/client.ts
1813
2692
  var PocketPingClient = class {
@@ -1867,7 +2746,8 @@ var PocketPingClient = class {
1867
2746
  visitorId: response.visitorId,
1868
2747
  operatorOnline: response.operatorOnline ?? false,
1869
2748
  messages: response.messages ?? [],
1870
- identity: response.identity || storedIdentity || void 0
2749
+ identity: response.identity || storedIdentity || void 0,
2750
+ preChatForm: response.preChatForm
1871
2751
  };
1872
2752
  if (response.operatorName) {
1873
2753
  this.config.operatorName = response.operatorName;
@@ -2223,6 +3103,36 @@ var PocketPingClient = class {
2223
3103
  }
2224
3104
  }
2225
3105
  }
3106
+ /**
3107
+ * Submit pre-chat form data (email and/or phone)
3108
+ * @param data - Form data containing email and/or phone
3109
+ */
3110
+ async submitPreChat(data) {
3111
+ if (!this.session) {
3112
+ throw new Error("[PocketPing] Not connected");
3113
+ }
3114
+ if (!data.email && !data.phone) {
3115
+ throw new Error("[PocketPing] Either email or phone is required");
3116
+ }
3117
+ try {
3118
+ await this.fetch("/prechat", {
3119
+ method: "POST",
3120
+ body: JSON.stringify({
3121
+ sessionId: this.session.sessionId,
3122
+ email: data.email,
3123
+ phone: data.phone,
3124
+ phoneCountry: data.phoneCountry
3125
+ })
3126
+ });
3127
+ if (this.session.preChatForm) {
3128
+ this.session.preChatForm.completed = true;
3129
+ }
3130
+ this.emit("preChatCompleted", data);
3131
+ } catch (err) {
3132
+ console.error("[PocketPing] Failed to submit pre-chat form:", err);
3133
+ throw err;
3134
+ }
3135
+ }
2226
3136
  /**
2227
3137
  * Reset the user identity and optionally start a new session
2228
3138
  * Call on user logout to clear user data
@@ -2872,6 +3782,12 @@ var PocketPingClient = class {
2872
3782
  this.session.messages.push(message);
2873
3783
  this.emit("message", message);
2874
3784
  this.config.onMessage?.(message);
3785
+ if (message.sender !== "visitor" && !this.isOpen) {
3786
+ const autoOpen = this.config.autoOpenOnMessage ?? true;
3787
+ if (autoOpen) {
3788
+ this.setOpen(true);
3789
+ }
3790
+ }
2875
3791
  }
2876
3792
  }
2877
3793
  if (message.sender !== "visitor") {
@@ -3030,6 +3946,12 @@ var PocketPingClient = class {
3030
3946
  this.session.messages.push(message);
3031
3947
  this.emit("message", message);
3032
3948
  this.config.onMessage?.(message);
3949
+ if (message.sender !== "visitor" && !this.isOpen) {
3950
+ const autoOpen = this.config.autoOpenOnMessage ?? true;
3951
+ if (autoOpen) {
3952
+ this.setOpen(true);
3953
+ }
3954
+ }
3033
3955
  }
3034
3956
  }
3035
3957
  } catch (err) {