@adatechnology/conversations-ui 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +169 -0
  2. package/dist/{ConversationSimulatorPanel-DnXElfY8.d.ts → ConversationSimulatorPanel-CrfFjiWh.d.ts} +2 -268
  3. package/dist/{chunk-PJNR6UMN.js → chunk-CBYEHPX6.js} +1 -63
  4. package/dist/{chunk-HMCOTZAX.js → chunk-HOKNKXIT.js} +1 -1
  5. package/dist/{chunk-4P5KMWOI.js → chunk-JXJCPN34.js} +327 -522
  6. package/dist/chunk-MRVFFJEH.js +64 -0
  7. package/dist/chunk-RJMSM3YA.js +249 -0
  8. package/dist/chunk-WSFGNR5R.js +55 -0
  9. package/dist/flows/index.js +5 -3
  10. package/dist/index.d.ts +9 -3
  11. package/dist/index.js +783 -807
  12. package/dist/participant/index.d.ts +162 -0
  13. package/dist/participant/index.js +1448 -0
  14. package/dist/preview/index.d.ts +4 -2
  15. package/dist/preview/index.js +4 -2
  16. package/dist/quickReply.types-B4gmZsSr.d.ts +274 -0
  17. package/dist/styles.css +591 -0
  18. package/package.json +8 -4
  19. package/src/ChannelIcon.tsx +2 -0
  20. package/src/MessageBubble.test.tsx +2 -2
  21. package/src/MessageText.test.tsx +59 -0
  22. package/src/MessageText.tsx +20 -12
  23. package/src/MessageTextCopiedBadge.tsx +7 -0
  24. package/src/StatusTicks.test.tsx +30 -0
  25. package/src/StatusTicks.tsx +24 -9
  26. package/src/buildOutput.test.ts +41 -0
  27. package/src/channelCapability.test.ts +17 -0
  28. package/src/conversationChannel.test.ts +30 -1
  29. package/src/conversationChannel.ts +19 -1
  30. package/src/participant/ParticipantAttachmentItem.tsx +77 -0
  31. package/src/participant/ParticipantComposer.test.tsx +97 -0
  32. package/src/participant/ParticipantComposer.tsx +167 -0
  33. package/src/participant/ParticipantConversations.test.tsx +90 -0
  34. package/src/participant/ParticipantConversations.tsx +42 -0
  35. package/src/participant/ParticipantConversationsScreen.tsx +67 -0
  36. package/src/participant/ParticipantInbox.test.tsx +147 -0
  37. package/src/participant/ParticipantInbox.tsx +168 -0
  38. package/src/participant/ParticipantLoadState.tsx +27 -0
  39. package/src/participant/ParticipantMessageBubble.test.tsx +165 -0
  40. package/src/participant/ParticipantMessageBubble.tsx +185 -0
  41. package/src/participant/ParticipantThread.test.tsx +132 -0
  42. package/src/participant/ParticipantThread.tsx +174 -0
  43. package/src/participant/ParticipantThreadScreen.tsx +135 -0
  44. package/src/participant/bindAttachmentUrlResolver.test.ts +25 -0
  45. package/src/participant/bindAttachmentUrlResolver.ts +7 -0
  46. package/src/participant/index.ts +25 -0
  47. package/src/participant/participant.types.ts +43 -0
  48. package/src/participant/participantApi.types.ts +59 -0
  49. package/src/participant/participantAttachmentUrl.test.ts +32 -0
  50. package/src/participant/participantAttachmentUrl.ts +10 -0
  51. package/src/participant/participantBubbleActions.test.ts +44 -0
  52. package/src/participant/participantBubbleActions.ts +40 -0
  53. package/src/participant/participantDrafts.test.ts +65 -0
  54. package/src/participant/participantDrafts.ts +50 -0
  55. package/src/participant/participantFileValidation.test.ts +86 -0
  56. package/src/participant/participantFileValidation.ts +72 -0
  57. package/src/participant/participantFixtures.test-helper.ts +41 -0
  58. package/src/participant/participantGrouping.test.ts +138 -0
  59. package/src/participant/participantGrouping.ts +77 -0
  60. package/src/participant/participantInboxState.test.ts +69 -0
  61. package/src/participant/participantInboxState.ts +74 -0
  62. package/src/participant/participantLabels.ts +86 -0
  63. package/src/participant/participantLoadView.test.ts +23 -0
  64. package/src/participant/participantLoadView.ts +21 -0
  65. package/src/participant/participantMessages.test.ts +128 -0
  66. package/src/participant/participantMessages.ts +73 -0
  67. package/src/participant/participantNewMessages.test.ts +54 -0
  68. package/src/participant/participantNewMessages.ts +29 -0
  69. package/src/participant/participantQuickReply.test.ts +23 -0
  70. package/src/participant/participantQuickReply.ts +6 -0
  71. package/src/participant/participantScroll.test.ts +69 -0
  72. package/src/participant/participantScroll.ts +43 -0
  73. package/src/participant/participantSendController.test.ts +201 -0
  74. package/src/participant/participantSendController.ts +134 -0
  75. package/src/participant/participantSendStates.ts +31 -0
  76. package/src/participant/participantTheme.ts +20 -0
  77. package/src/participant/participantThreadState.test.ts +75 -0
  78. package/src/participant/participantThreadState.ts +59 -0
  79. package/src/participant/shouldMarkRead.test.ts +24 -0
  80. package/src/participant/shouldMarkRead.ts +16 -0
  81. package/src/participant/useDocumentVisibility.ts +18 -0
  82. package/src/participant/useParticipantConversationView.ts +60 -0
  83. package/src/participant/useParticipantDraft.ts +45 -0
  84. package/src/participant/useParticipantInbox.ts +57 -0
  85. package/src/participant/useParticipantMarkRead.ts +26 -0
  86. package/src/participant/useParticipantRevalidation.ts +36 -0
  87. package/src/participant/useParticipantSend.ts +84 -0
  88. package/src/participant/useParticipantThread.ts +116 -0
  89. package/src/participant/useParticipantThreadScroll.ts +26 -0
  90. package/src/participant/useStickToBottom.ts +77 -0
  91. package/src/preview/ConversationSimulatorPanel.tsx +8 -0
  92. package/src/styles.css +160 -0
  93. package/src/types.ts +3 -1
package/dist/styles.css CHANGED
@@ -1251,3 +1251,594 @@
1251
1251
  border-top-color: rgb(51 65 85);
1252
1252
  background: rgb(17 24 39);
1253
1253
  }
1254
+ .cv-status-ticks {
1255
+ display: flex;
1256
+ align-items: center;
1257
+ line-height: 1;
1258
+ cursor: help;
1259
+ }
1260
+ .cv-status-ticks--queued,
1261
+ .cv-status-ticks--sent,
1262
+ .cv-status-ticks--delivered {
1263
+ color: rgb(0 0 0 / 40%);
1264
+ }
1265
+ .dark .cv-status-ticks--queued,
1266
+ .dark .cv-status-ticks--sent,
1267
+ .dark .cv-status-ticks--delivered {
1268
+ color: rgb(255 255 255 / 40%);
1269
+ }
1270
+ .cv-status-ticks--read {
1271
+ color: rgb(14 165 233);
1272
+ }
1273
+ .cv-status-ticks--failed {
1274
+ color: rgb(239 68 68);
1275
+ }
1276
+ .cv-message-text {
1277
+ position: relative;
1278
+ font-size: 14.2px;
1279
+ line-height: 19px;
1280
+ white-space: pre-wrap;
1281
+ overflow-wrap: break-word;
1282
+ word-break: break-word;
1283
+ }
1284
+ .cv-message-text--copyable {
1285
+ user-select: all;
1286
+ cursor: pointer;
1287
+ }
1288
+ .cv-message-text strong {
1289
+ font-weight: 700;
1290
+ }
1291
+ .cv-message-text em {
1292
+ font-style: italic;
1293
+ }
1294
+ .cv-message-text del {
1295
+ text-decoration-line: line-through;
1296
+ }
1297
+ .cv-message-text__copied {
1298
+ position: absolute;
1299
+ top: 0;
1300
+ right: 0;
1301
+ transform: translateY(-100%);
1302
+ background: #3b4a54;
1303
+ color: #fff;
1304
+ font-size: 11px;
1305
+ padding: 0.125rem 0.375rem;
1306
+ border-radius: 0.25rem;
1307
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
1308
+ }
1309
+ .cv-p {
1310
+ --cv-p-i-surface: var(--cv-p-surface, #ffffff);
1311
+ --cv-p-i-surface-raised: var(--cv-p-surface-raised, #f3f4f6);
1312
+ --cv-p-i-text: var(--cv-p-text, #111827);
1313
+ --cv-p-i-text-muted: var(--cv-p-text-muted, #5b6573);
1314
+ --cv-p-i-border: var(--cv-p-border, #d5d9df);
1315
+ --cv-p-i-accent: var(--cv-p-accent, #a85a1c);
1316
+ --cv-p-i-accent-contrast: var(--cv-p-accent-contrast, #ffffff);
1317
+ --cv-p-i-highlight: var(--cv-p-highlight, #fbefe2);
1318
+ --cv-p-i-danger: var(--cv-p-danger, #c62828);
1319
+ --cv-p-i-radius: var(--cv-p-radius, 0);
1320
+ --cv-p-i-touch: 2.75rem;
1321
+ display: flex;
1322
+ flex-direction: column;
1323
+ min-height: 0;
1324
+ height: 100%;
1325
+ background: var(--cv-p-i-surface);
1326
+ color: var(--cv-p-i-text);
1327
+ font-family:
1328
+ "Avenir Next",
1329
+ Avenir,
1330
+ "Segoe UI",
1331
+ sans-serif;
1332
+ line-height: 1.4;
1333
+ box-sizing: border-box;
1334
+ }
1335
+ .dark .cv-p {
1336
+ --cv-p-i-surface: var(--cv-p-surface, #10222c);
1337
+ --cv-p-i-surface-raised: var(--cv-p-surface-raised, #1c2b33);
1338
+ --cv-p-i-text: var(--cv-p-text, #f0f2ee);
1339
+ --cv-p-i-text-muted: var(--cv-p-text-muted, #8fa3ad);
1340
+ --cv-p-i-border: var(--cv-p-border, rgb(143 163 173 / 26%));
1341
+ --cv-p-i-accent: var(--cv-p-accent, #d58a47);
1342
+ --cv-p-i-accent-contrast: var(--cv-p-accent-contrast, #10222c);
1343
+ --cv-p-i-highlight: var(--cv-p-highlight, rgb(213 138 71 / 10%));
1344
+ --cv-p-i-danger: var(--cv-p-danger, #ff6b63);
1345
+ }
1346
+ .cv-p *,
1347
+ .cv-p *::before,
1348
+ .cv-p *::after {
1349
+ box-sizing: border-box;
1350
+ }
1351
+ .cv-p :focus-visible {
1352
+ outline: 2px solid var(--cv-p-i-accent);
1353
+ outline-offset: 2px;
1354
+ }
1355
+ .cv-p-sr-only {
1356
+ position: absolute;
1357
+ width: 1px;
1358
+ height: 1px;
1359
+ margin: -1px;
1360
+ padding: 0;
1361
+ overflow: hidden;
1362
+ clip: rect(0 0 0 0);
1363
+ white-space: nowrap;
1364
+ border: 0;
1365
+ }
1366
+ .cv-p-button,
1367
+ .cv-p-chip,
1368
+ .cv-p-row,
1369
+ .cv-p-thread__older,
1370
+ .cv-p-bubble__retry,
1371
+ .cv-p-bubble__action {
1372
+ font: inherit;
1373
+ color: inherit;
1374
+ cursor: pointer;
1375
+ }
1376
+ .cv-p-button {
1377
+ min-height: var(--cv-p-i-touch);
1378
+ min-width: var(--cv-p-i-touch);
1379
+ padding: 0 0.75rem;
1380
+ background: transparent;
1381
+ border: 1px solid var(--cv-p-i-border);
1382
+ border-radius: var(--cv-p-i-radius);
1383
+ display: inline-flex;
1384
+ align-items: center;
1385
+ justify-content: center;
1386
+ }
1387
+ .cv-p-button:disabled {
1388
+ opacity: 0.45;
1389
+ cursor: not-allowed;
1390
+ }
1391
+ .cv-p-button--primary {
1392
+ background: var(--cv-p-i-accent);
1393
+ border-color: var(--cv-p-i-accent);
1394
+ color: var(--cv-p-i-accent-contrast);
1395
+ font-weight: 600;
1396
+ }
1397
+ .cv-p-chip {
1398
+ flex: none;
1399
+ min-height: 2.75rem;
1400
+ padding: 0 0.875rem;
1401
+ display: inline-flex;
1402
+ align-items: center;
1403
+ gap: 0.4rem;
1404
+ background: transparent;
1405
+ border: 1px solid var(--cv-p-i-border);
1406
+ border-radius: var(--cv-p-i-radius);
1407
+ color: var(--cv-p-i-text-muted);
1408
+ font-size: 0.85rem;
1409
+ }
1410
+ .cv-p-chip[aria-pressed=true] {
1411
+ background: var(--cv-p-i-text);
1412
+ border-color: var(--cv-p-i-text);
1413
+ color: var(--cv-p-i-surface);
1414
+ }
1415
+ .cv-p-chip__count {
1416
+ font:
1417
+ 0.7rem "SFMono-Regular",
1418
+ Consolas,
1419
+ monospace;
1420
+ background: var(--cv-p-i-accent);
1421
+ color: var(--cv-p-i-accent-contrast);
1422
+ padding: 0 0.35rem;
1423
+ }
1424
+ .cv-p-inbox {
1425
+ overflow-y: auto;
1426
+ }
1427
+ .cv-p-inbox__title {
1428
+ margin: 0;
1429
+ padding: 0.75rem 1rem;
1430
+ font-size: 1rem;
1431
+ border-bottom: 1px solid var(--cv-p-i-border);
1432
+ }
1433
+ .cv-p-filters {
1434
+ display: flex;
1435
+ gap: 0.5rem;
1436
+ padding: 0.625rem 1rem;
1437
+ overflow-x: auto;
1438
+ border-bottom: 1px solid var(--cv-p-i-border);
1439
+ }
1440
+ .cv-p-error {
1441
+ display: flex;
1442
+ flex-direction: column;
1443
+ align-items: center;
1444
+ gap: 0.5rem;
1445
+ padding: 1.5rem 1rem;
1446
+ text-align: center;
1447
+ color: var(--cv-p-i-danger, #b91c1c);
1448
+ }
1449
+ .cv-p-error__message {
1450
+ margin: 0;
1451
+ }
1452
+ .cv-p-loading {
1453
+ display: flex;
1454
+ flex-direction: column;
1455
+ gap: 0.5rem;
1456
+ padding: 1rem;
1457
+ }
1458
+ .cv-p-skeleton {
1459
+ display: block;
1460
+ height: 3rem;
1461
+ border-radius: var(--cv-p-i-radius);
1462
+ background: var(--cv-p-i-surface-raised);
1463
+ }
1464
+ .cv-p-inbox__more {
1465
+ display: block;
1466
+ margin: 0.75rem auto;
1467
+ padding: 0 1rem;
1468
+ }
1469
+ .cv-p-empty {
1470
+ padding: 2rem 1rem;
1471
+ text-align: center;
1472
+ color: var(--cv-p-i-text-muted);
1473
+ }
1474
+ .cv-p-section__heading {
1475
+ display: flex;
1476
+ justify-content: space-between;
1477
+ margin: 0;
1478
+ padding: 0.875rem 1rem 0.375rem;
1479
+ font:
1480
+ 0.68rem "SFMono-Regular",
1481
+ Consolas,
1482
+ monospace;
1483
+ letter-spacing: 0.1em;
1484
+ text-transform: uppercase;
1485
+ color: var(--cv-p-i-text-muted);
1486
+ list-style: none;
1487
+ }
1488
+ .cv-p-section--awaiting .cv-p-section__heading {
1489
+ color: var(--cv-p-i-accent);
1490
+ }
1491
+ .cv-p-section--closed > summary {
1492
+ cursor: pointer;
1493
+ min-height: var(--cv-p-i-touch);
1494
+ align-items: center;
1495
+ }
1496
+ .cv-p-section--closed > summary::-webkit-details-marker {
1497
+ display: none;
1498
+ }
1499
+ .cv-p-row {
1500
+ width: 100%;
1501
+ min-height: var(--cv-p-i-touch);
1502
+ display: grid;
1503
+ grid-template-columns: 2.25rem 1fr auto;
1504
+ gap: 0.625rem;
1505
+ padding: 0.75rem 1rem;
1506
+ text-align: left;
1507
+ background: transparent;
1508
+ border: 0;
1509
+ border-bottom: 1px solid var(--cv-p-i-border);
1510
+ border-left: 3px solid transparent;
1511
+ }
1512
+ .cv-p-row--awaiting {
1513
+ border-left-color: var(--cv-p-i-accent);
1514
+ background: var(--cv-p-i-highlight);
1515
+ }
1516
+ .cv-p-row__icon {
1517
+ width: 2.25rem;
1518
+ height: 2.25rem;
1519
+ display: grid;
1520
+ place-items: center;
1521
+ border: 1px solid var(--cv-p-i-border);
1522
+ border-radius: var(--cv-p-i-radius);
1523
+ font:
1524
+ 0.7rem "SFMono-Regular",
1525
+ Consolas,
1526
+ monospace;
1527
+ text-transform: uppercase;
1528
+ color: var(--cv-p-i-accent);
1529
+ }
1530
+ .cv-p-row__body {
1531
+ display: flex;
1532
+ flex-direction: column;
1533
+ min-width: 0;
1534
+ }
1535
+ .cv-p-row__kind {
1536
+ font:
1537
+ 0.64rem "SFMono-Regular",
1538
+ Consolas,
1539
+ monospace;
1540
+ letter-spacing: 0.08em;
1541
+ text-transform: uppercase;
1542
+ color: var(--cv-p-i-text-muted);
1543
+ }
1544
+ .cv-p-row__title {
1545
+ font-weight: 600;
1546
+ font-size: 0.92rem;
1547
+ }
1548
+ .cv-p-row__preview {
1549
+ color: var(--cv-p-i-text-muted);
1550
+ font-size: 0.82rem;
1551
+ white-space: nowrap;
1552
+ overflow: hidden;
1553
+ text-overflow: ellipsis;
1554
+ }
1555
+ .cv-p-row__meta {
1556
+ display: flex;
1557
+ flex-direction: column;
1558
+ align-items: flex-end;
1559
+ gap: 0.25rem;
1560
+ font:
1561
+ 0.7rem "SFMono-Regular",
1562
+ Consolas,
1563
+ monospace;
1564
+ color: var(--cv-p-i-text-muted);
1565
+ }
1566
+ .cv-p-row__unread {
1567
+ min-width: 1.25rem;
1568
+ padding: 0 0.3rem;
1569
+ text-align: center;
1570
+ font-weight: 700;
1571
+ background: var(--cv-p-i-accent);
1572
+ color: var(--cv-p-i-accent-contrast);
1573
+ }
1574
+ .cv-p-thread__header {
1575
+ display: flex;
1576
+ align-items: center;
1577
+ gap: 0.5rem;
1578
+ padding: 0.5rem 1rem;
1579
+ border-bottom: 1px solid var(--cv-p-i-border);
1580
+ }
1581
+ .cv-p-thread__title {
1582
+ flex: 1;
1583
+ margin: 0;
1584
+ font-size: 1rem;
1585
+ min-width: 0;
1586
+ }
1587
+ .cv-p-thread__title-button {
1588
+ min-height: var(--cv-p-i-touch);
1589
+ padding: 0;
1590
+ background: none;
1591
+ border: 0;
1592
+ color: inherit;
1593
+ font: inherit;
1594
+ font-weight: 600;
1595
+ text-align: left;
1596
+ text-decoration: underline;
1597
+ cursor: pointer;
1598
+ }
1599
+ .cv-p-thread__subject-card {
1600
+ margin: 0.75rem 1rem 0;
1601
+ padding: 0.625rem 0.75rem;
1602
+ border: 1px solid var(--cv-p-i-border);
1603
+ background: var(--cv-p-i-surface-raised);
1604
+ border-radius: var(--cv-p-i-radius);
1605
+ font-size: 0.82rem;
1606
+ }
1607
+ .cv-p-thread__scroll {
1608
+ flex: 1;
1609
+ min-height: 0;
1610
+ overflow-y: auto;
1611
+ overflow-anchor: none;
1612
+ padding: 0.5rem 1rem 1rem;
1613
+ }
1614
+ .cv-p-thread__older {
1615
+ display: block;
1616
+ margin: 0 auto 0.5rem;
1617
+ min-height: var(--cv-p-i-touch);
1618
+ padding: 0 1rem;
1619
+ background: transparent;
1620
+ border: 1px solid var(--cv-p-i-border);
1621
+ border-radius: var(--cv-p-i-radius);
1622
+ }
1623
+ .cv-p-thread__messages {
1624
+ display: flex;
1625
+ flex-direction: column;
1626
+ gap: 0.5rem;
1627
+ }
1628
+ .cv-p-thread__live {
1629
+ padding: 0 1rem;
1630
+ font-size: 0.75rem;
1631
+ color: var(--cv-p-i-accent);
1632
+ }
1633
+ .cv-p-thread__live:empty {
1634
+ position: absolute;
1635
+ width: 1px;
1636
+ height: 1px;
1637
+ margin: -1px;
1638
+ padding: 0;
1639
+ overflow: hidden;
1640
+ clip: rect(0 0 0 0);
1641
+ white-space: nowrap;
1642
+ border: 0;
1643
+ }
1644
+ .cv-p-thread__closed {
1645
+ margin: 0;
1646
+ padding: 1rem;
1647
+ text-align: center;
1648
+ color: var(--cv-p-i-text-muted);
1649
+ border-top: 1px solid var(--cv-p-i-border);
1650
+ }
1651
+ .cv-p-day {
1652
+ align-self: center;
1653
+ margin: 0.5rem 0;
1654
+ font:
1655
+ 0.65rem "SFMono-Regular",
1656
+ Consolas,
1657
+ monospace;
1658
+ text-transform: uppercase;
1659
+ color: var(--cv-p-i-text-muted);
1660
+ }
1661
+ .cv-p-bubble {
1662
+ max-width: 82%;
1663
+ align-self: flex-start;
1664
+ padding: 0.5rem 0.7rem;
1665
+ font-size: 0.88rem;
1666
+ background: var(--cv-p-i-surface-raised);
1667
+ border: 1px solid var(--cv-p-i-border);
1668
+ border-radius: var(--cv-p-i-radius);
1669
+ }
1670
+ .cv-p-bubble--mine {
1671
+ align-self: flex-end;
1672
+ background: var(--cv-p-i-highlight);
1673
+ border-color: var(--cv-p-i-accent);
1674
+ }
1675
+ .cv-p-bubble__author {
1676
+ display: block;
1677
+ margin-bottom: 0.15rem;
1678
+ font:
1679
+ 0.65rem "SFMono-Regular",
1680
+ Consolas,
1681
+ monospace;
1682
+ text-transform: uppercase;
1683
+ color: var(--cv-p-i-accent);
1684
+ }
1685
+ .cv-p-bubble__meta {
1686
+ display: flex;
1687
+ justify-content: flex-end;
1688
+ align-items: center;
1689
+ gap: 0.35rem;
1690
+ margin-top: 0.25rem;
1691
+ font:
1692
+ 0.65rem "SFMono-Regular",
1693
+ Consolas,
1694
+ monospace;
1695
+ color: var(--cv-p-i-text-muted);
1696
+ }
1697
+ .cv-p-bubble__status {
1698
+ display: inline-flex;
1699
+ align-items: center;
1700
+ gap: 0.25rem;
1701
+ }
1702
+ .cv-p-bubble__retry {
1703
+ min-height: var(--cv-p-i-touch);
1704
+ display: inline-flex;
1705
+ align-items: center;
1706
+ gap: 0.25rem;
1707
+ padding: 0 0.5rem;
1708
+ background: transparent;
1709
+ border: 1px solid var(--cv-p-i-danger);
1710
+ color: var(--cv-p-i-danger);
1711
+ border-radius: var(--cv-p-i-radius);
1712
+ font-size: 0.7rem;
1713
+ }
1714
+ .cv-p-bubble__actions {
1715
+ display: inline-flex;
1716
+ gap: 0.5rem;
1717
+ margin-top: 0.25rem;
1718
+ }
1719
+ .cv-p-bubble__action {
1720
+ min-height: var(--cv-p-i-touch);
1721
+ display: inline-flex;
1722
+ align-items: center;
1723
+ padding: 0 0.75rem;
1724
+ background: transparent;
1725
+ border: 1px solid var(--cv-p-i-border);
1726
+ color: inherit;
1727
+ border-radius: var(--cv-p-i-radius);
1728
+ font-size: 0.7rem;
1729
+ }
1730
+ .cv-p-attachment {
1731
+ display: flex;
1732
+ flex-direction: column;
1733
+ gap: 0.25rem;
1734
+ margin-top: 0.35rem;
1735
+ color: inherit;
1736
+ }
1737
+ .cv-p-attachment--document {
1738
+ flex-direction: row;
1739
+ justify-content: space-between;
1740
+ min-height: var(--cv-p-i-touch);
1741
+ align-items: center;
1742
+ text-decoration: underline;
1743
+ }
1744
+ .cv-p-attachment__image {
1745
+ display: block;
1746
+ max-width: 100%;
1747
+ max-height: 16rem;
1748
+ object-fit: contain;
1749
+ }
1750
+ .cv-p-attachment__audio {
1751
+ width: 100%;
1752
+ min-height: var(--cv-p-i-touch);
1753
+ }
1754
+ .cv-p-attachment__name,
1755
+ .cv-p-attachment__size {
1756
+ font-size: 0.75rem;
1757
+ overflow-wrap: anywhere;
1758
+ }
1759
+ .cv-p-composer {
1760
+ display: flex;
1761
+ flex-direction: column;
1762
+ gap: 0.5rem;
1763
+ padding: 0.5rem 1rem 1rem;
1764
+ border-top: 1px solid var(--cv-p-i-border);
1765
+ }
1766
+ .cv-p-composer__row {
1767
+ display: flex;
1768
+ align-items: flex-end;
1769
+ gap: 0.5rem;
1770
+ }
1771
+ .cv-p-composer__input {
1772
+ flex: 1;
1773
+ min-height: var(--cv-p-i-touch);
1774
+ max-height: 8rem;
1775
+ resize: none;
1776
+ padding: 0.7rem;
1777
+ font: inherit;
1778
+ font-size: 0.9rem;
1779
+ color: inherit;
1780
+ background: var(--cv-p-i-surface);
1781
+ border: 1px solid var(--cv-p-i-border);
1782
+ border-radius: var(--cv-p-i-radius);
1783
+ }
1784
+ .cv-p-composer__error {
1785
+ margin: 0;
1786
+ font-size: 0.8rem;
1787
+ color: var(--cv-p-i-danger);
1788
+ }
1789
+ .cv-p-quick {
1790
+ display: flex;
1791
+ gap: 0.5rem;
1792
+ overflow-x: auto;
1793
+ }
1794
+ .cv-p-files {
1795
+ display: flex;
1796
+ flex-direction: column;
1797
+ gap: 0.25rem;
1798
+ margin: 0;
1799
+ padding: 0;
1800
+ list-style: none;
1801
+ }
1802
+ .cv-p-files__item {
1803
+ display: flex;
1804
+ align-items: center;
1805
+ gap: 0.5rem;
1806
+ font-size: 0.8rem;
1807
+ }
1808
+ .cv-p-files__name {
1809
+ flex: 1;
1810
+ overflow: hidden;
1811
+ text-overflow: ellipsis;
1812
+ white-space: nowrap;
1813
+ }
1814
+ .cv-p-files__size {
1815
+ color: var(--cv-p-i-text-muted);
1816
+ }
1817
+ .cv-p-files__remove {
1818
+ min-width: var(--cv-p-i-touch);
1819
+ min-height: var(--cv-p-i-touch);
1820
+ background: transparent;
1821
+ border: 0;
1822
+ color: inherit;
1823
+ font: inherit;
1824
+ cursor: pointer;
1825
+ }
1826
+ @media (prefers-reduced-motion: no-preference) {
1827
+ .cv-p-row,
1828
+ .cv-p-button,
1829
+ .cv-p-chip {
1830
+ transition: background-color 0.12s, border-color 0.12s;
1831
+ }
1832
+ }
1833
+ .cv-p-root {
1834
+ display: flex;
1835
+ flex-direction: column;
1836
+ min-height: 0;
1837
+ height: 100%;
1838
+ }
1839
+ .cv-p-root__screen {
1840
+ display: flex;
1841
+ flex-direction: column;
1842
+ flex: 1;
1843
+ min-height: 0;
1844
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adatechnology/conversations-ui",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "WhatsApp conversation UI components — parametrizável por endpoint, tema e feature flags",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -23,6 +23,10 @@
23
23
  "import": "./dist/preview/index.js",
24
24
  "types": "./dist/preview/index.d.ts"
25
25
  },
26
+ "./participant": {
27
+ "import": "./dist/participant/index.js",
28
+ "types": "./dist/participant/index.d.ts"
29
+ },
26
30
  "./styles.css": "./dist/styles.css"
27
31
  },
28
32
  "main": "dist/index.js",
@@ -31,7 +35,7 @@
31
35
  "clsx": "^2.1.1",
32
36
  "lucide-react": "^1.21.0",
33
37
  "tailwind-merge": "^3.6.0",
34
- "@adatechnology/conversation-contracts": "0.3.0",
38
+ "@adatechnology/conversation-contracts": "0.4.0",
35
39
  "@adatechnology/meta-whatsapp-contracts": "0.6.0"
36
40
  },
37
41
  "peerDependencies": {
@@ -53,8 +57,8 @@
53
57
  "typescript": "^5.9.3"
54
58
  },
55
59
  "scripts": {
56
- "build": "tsup src/index.ts src/flows/index.ts src/channel/index.ts src/preview/index.ts src/styles.css --dts --clean --format esm --external react --external react-dom --external @xyflow/react",
57
- "build:watch": "tsup src/index.ts src/flows/index.ts src/channel/index.ts src/styles.css --watch --dts --format esm --external react --external react-dom --external @xyflow/react",
60
+ "build": "tsup src/index.ts src/flows/index.ts src/channel/index.ts src/preview/index.ts src/participant/index.ts src/styles.css --dts --clean --format esm --external react --external react-dom --external @xyflow/react",
61
+ "build:watch": "tsup src/index.ts src/flows/index.ts src/channel/index.ts src/preview/index.ts src/participant/index.ts src/styles.css --watch --dts --format esm --external react --external react-dom --external @xyflow/react",
58
62
  "check": "tsc -p tsconfig.json --noEmit",
59
63
  "test": "bun test"
60
64
  }
@@ -14,6 +14,8 @@ export const CHANNEL_BRAND_COLOR: Readonly<Record<ConversationChannel, string>>
14
14
  [CONVERSATION_CHANNEL.WHATSAPP]: '#25D366',
15
15
  [CONVERSATION_CHANNEL.MESSENGER]: '#0084FF',
16
16
  [CONVERSATION_CHANNEL.INSTAGRAM]: '#E4405F',
17
+ [CONVERSATION_CHANNEL.APP]: '#7C3AED',
18
+ [CONVERSATION_CHANNEL.PORTAL]: '#0F766E',
17
19
  [CONVERSATION_CHANNEL.WEBCHAT]: '#64748B',
18
20
  [CONVERSATION_CHANNEL.EMAIL]: '#EA4335',
19
21
  }
@@ -56,13 +56,13 @@ describe('MessageBubble e o selo de lida por canal (D4, CA04)', () => {
56
56
  it('email não confirma leitura — o selo de lida não aparece mesmo com status "read"', () => {
57
57
  const markup = renderToStaticMarkup(<MessageBubble message={TEXT_MESSAGE} isMine channel="email" />)
58
58
 
59
- expect(markup).not.toContain('text-sky-500')
59
+ expect(markup).not.toContain('cv-status-ticks--read')
60
60
  })
61
61
 
62
62
  it('whatsapp confirma leitura — o selo de lida aparece normalmente', () => {
63
63
  const markup = renderToStaticMarkup(<MessageBubble message={TEXT_MESSAGE} isMine channel="whatsapp" />)
64
64
 
65
- expect(markup).toContain('text-sky-500')
65
+ expect(markup).toContain('cv-status-ticks--read')
66
66
  })
67
67
 
68
68
  it('sem channel, o padrão continua sendo whatsapp — comportamento de antes desta mudança', () => {
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from 'bun:test'
2
+ import { renderToStaticMarkup } from 'react-dom/server'
3
+
4
+ import { MessageText } from './MessageText'
5
+ import { MessageTextCopiedBadge } from './MessageTextCopiedBadge'
6
+ import type { MessagePayload } from './types'
7
+
8
+ const TEXT_MESSAGE: MessagePayload = {
9
+ id: 'msg-1',
10
+ type: 'text',
11
+ direction: 'inbound',
12
+ sender: 'customer',
13
+ timestamp: '2026-08-05T12:00:00.000Z',
14
+ content: 'Olá *mundo*',
15
+ }
16
+
17
+ describe('MessageText', () => {
18
+ it('usa a classe cv-message-text e nenhuma utilitária Tailwind', () => {
19
+ const markup = renderToStaticMarkup(<MessageText message={TEXT_MESSAGE} />)
20
+
21
+ expect(markup).toContain('cv-message-text')
22
+ expect(markup).not.toContain('whitespace-pre-wrap')
23
+ expect(markup).not.toContain('select-all')
24
+ expect(markup).not.toContain('text-[')
25
+ expect(markup).not.toContain('[&_')
26
+ })
27
+
28
+ it('o badge usa a classe cv-message-text__copied e nenhuma utilitária Tailwind', () => {
29
+ const markup = renderToStaticMarkup(<MessageTextCopiedBadge />)
30
+
31
+ expect(markup).toContain('cv-message-text__copied')
32
+ expect(markup).not.toContain('absolute')
33
+ expect(markup).not.toContain('bg-[')
34
+ expect(markup).not.toContain('px-1.5')
35
+ expect(markup).not.toContain('-translate-y-full')
36
+ })
37
+
38
+ it('por padrão copia ao toque: role=button, tabindex e classe copiável (user-select só aí)', () => {
39
+ const markup = renderToStaticMarkup(<MessageText message={TEXT_MESSAGE} />)
40
+
41
+ expect(markup).toContain('role="button"')
42
+ expect(markup).toContain('tabindex="0"')
43
+ expect(markup).toContain('cv-message-text--copyable')
44
+ })
45
+
46
+ it('com copyOnClick={false} não copia: sem role, sem tabindex e sem classe copiável', () => {
47
+ const markup = renderToStaticMarkup(<MessageText message={TEXT_MESSAGE} copyOnClick={false} />)
48
+
49
+ expect(markup).not.toContain('role="button"')
50
+ expect(markup).not.toContain('tabindex')
51
+ expect(markup).not.toContain('cv-message-text--copyable')
52
+ expect(markup).toContain('class="cv-message-text"')
53
+ })
54
+
55
+ it('o badge usa "Copied" por padrão e aceita outro rótulo', () => {
56
+ expect(renderToStaticMarkup(<MessageTextCopiedBadge />)).toContain('Copied')
57
+ expect(renderToStaticMarkup(<MessageTextCopiedBadge label="Copiado!" />)).toContain('Copiado!')
58
+ })
59
+ })