@adatechnology/conversations-ui 0.6.0 → 0.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.
Files changed (88) hide show
  1. package/README.md +126 -19
  2. package/dist/{chunk-HOKNKXIT.js → chunk-HMCOTZAX.js} +1 -1
  3. package/dist/{chunk-FAQLC3TX.js → chunk-L3OFAQPS.js} +2 -4
  4. package/dist/{chunk-CBYEHPX6.js → chunk-PJNR6UMN.js} +63 -1
  5. package/dist/flows/index.js +3 -5
  6. package/dist/index.js +834 -764
  7. package/dist/participant/index.d.ts +18 -1
  8. package/dist/participant/index.js +1188 -313
  9. package/dist/preview/index.js +2 -3
  10. package/dist/styles.css +591 -19
  11. package/package.json +1 -1
  12. package/src/cssBlocks.test-helper.ts +31 -0
  13. package/src/legacyStyles.golden.test.ts +2 -31
  14. package/src/participant/ParticipantAuthorAvatar.test.tsx +30 -0
  15. package/src/participant/ParticipantAuthorAvatar.tsx +24 -0
  16. package/src/participant/ParticipantBackButton.tsx +14 -0
  17. package/src/participant/ParticipantBubbleStatus.tsx +67 -0
  18. package/src/participant/ParticipantChannelBadges.tsx +13 -4
  19. package/src/participant/ParticipantComposer.tsx +8 -40
  20. package/src/participant/ParticipantComposerControls.tsx +83 -0
  21. package/src/participant/ParticipantConversationAvatar.tsx +13 -0
  22. package/src/participant/ParticipantConversations.tsx +7 -0
  23. package/src/participant/ParticipantConversationsOptions.test.tsx +87 -0
  24. package/src/participant/ParticipantCopyAnnouncer.tsx +48 -0
  25. package/src/participant/ParticipantCopyableToken.tsx +51 -0
  26. package/src/participant/ParticipantDayDivider.tsx +18 -0
  27. package/src/participant/ParticipantInbox.tsx +3 -1
  28. package/src/participant/ParticipantInboxRow.tsx +6 -4
  29. package/src/participant/ParticipantMessageBubble.test.tsx +52 -5
  30. package/src/participant/ParticipantMessageBubble.tsx +25 -81
  31. package/src/participant/ParticipantMessageNodes.tsx +54 -0
  32. package/src/participant/ParticipantMessageText.test.tsx +106 -0
  33. package/src/participant/ParticipantMessageText.tsx +52 -0
  34. package/src/participant/ParticipantProtocolBadge.tsx +15 -7
  35. package/src/participant/ParticipantProtocolView.test.tsx +4 -6
  36. package/src/participant/ParticipantScrollToLatest.test.tsx +153 -0
  37. package/src/participant/ParticipantScrollToLatest.tsx +40 -0
  38. package/src/participant/ParticipantThread.test.tsx +37 -0
  39. package/src/participant/ParticipantThread.tsx +45 -95
  40. package/src/participant/ParticipantThreadAvatarSequence.test.tsx +65 -0
  41. package/src/participant/ParticipantThreadHeader.test.tsx +181 -0
  42. package/src/participant/ParticipantThreadHeader.tsx +73 -0
  43. package/src/participant/ParticipantThreadScreen.tsx +24 -10
  44. package/src/participant/ParticipantTimeline.tsx +103 -0
  45. package/src/participant/index.ts +1 -0
  46. package/src/participant/participantAutoGrow.test.ts +43 -0
  47. package/src/participant/participantAutoGrow.ts +12 -0
  48. package/src/participant/participantAvatar.test.ts +74 -0
  49. package/src/participant/participantAvatar.ts +48 -0
  50. package/src/participant/participantBubbleTail.test.tsx +107 -0
  51. package/src/participant/participantChatDesign.test.tsx +198 -0
  52. package/src/participant/participantCopyAnnouncement.test.ts +52 -0
  53. package/src/participant/participantCopyAnnouncement.ts +37 -0
  54. package/src/participant/participantCss.test-helper.ts +34 -0
  55. package/src/participant/participantDay.test.ts +22 -0
  56. package/src/participant/participantDay.ts +8 -0
  57. package/src/participant/participantDocuments.ts +45 -0
  58. package/src/participant/participantHeaderA11y.test.tsx +85 -0
  59. package/src/participant/participantHeaderDesign.test.tsx +111 -0
  60. package/src/participant/participantLabels.ts +11 -0
  61. package/src/participant/participantMessageAtoms.ts +53 -0
  62. package/src/participant/participantMessageCopyables.test.ts +141 -0
  63. package/src/participant/participantMessageCopyables.ts +76 -0
  64. package/src/participant/participantMessageFormat.test-helper.ts +21 -0
  65. package/src/participant/participantMessageFormat.test.ts +177 -0
  66. package/src/participant/participantMessageFormat.ts +135 -0
  67. package/src/participant/participantMessageFormat.types.ts +22 -0
  68. package/src/participant/participantMessageInline.test.ts +82 -0
  69. package/src/participant/participantMessageInline.ts +99 -0
  70. package/src/participant/participantMessageLinks.test.ts +100 -0
  71. package/src/participant/participantMessageLinks.ts +54 -0
  72. package/src/participant/participantMessageTextStyle.test.ts +137 -0
  73. package/src/participant/participantScrollFocus.test.ts +22 -0
  74. package/src/participant/participantScrollFocus.ts +10 -0
  75. package/src/participant/participantScrollView.test.ts +74 -0
  76. package/src/participant/participantScrollView.ts +38 -0
  77. package/src/participant/participantScrollbars.test.ts +156 -0
  78. package/src/participant/participantSubjectIcon.test.tsx +27 -0
  79. package/src/participant/participantSubjectIcon.ts +26 -0
  80. package/src/participant/useParticipantCopyFeedback.ts +33 -0
  81. package/src/participant/useParticipantThreadScroll.ts +10 -2
  82. package/src/participant/useRevealActiveChip.ts +20 -0
  83. package/src/participant/useScrollAwayState.ts +24 -0
  84. package/src/participant/useStickToBottom.ts +16 -2
  85. package/src/participantLayoutShrink.test.ts +82 -0
  86. package/src/styles.css +140 -21
  87. package/dist/chunk-MRVFFJEH.js +0 -64
  88. package/dist/chunk-OVFCLRQQ.js +0 -84
package/src/styles.css CHANGED
@@ -1139,7 +1139,7 @@
1139
1139
 
1140
1140
  /* Participant view (.cv-p-*). Public theming API: override --cv-p-surface, --cv-p-surface-raised,
1141
1141
  --cv-p-text, --cv-p-text-muted, --cv-p-border, --cv-p-accent, --cv-p-accent-contrast,
1142
- --cv-p-highlight, --cv-p-danger, --cv-p-radius, --cv-p-channel-app, --cv-p-channel-whatsapp on .cv-p or any
1142
+ --cv-p-highlight, --cv-p-danger, --cv-p-radius, --cv-p-wallpaper, --cv-p-scrollbar-thumb, --cv-p-scrollbar-thumb-hover, --cv-p-channel-app, --cv-p-channel-whatsapp on .cv-p or any
1143
1143
  ancestor. Channel colors must keep 3:1 against surface, surface-raised and highlight. */
1144
1144
  .cv-p {
1145
1145
  --cv-p-i-surface: var(--cv-p-surface, #ffffff);
@@ -1153,6 +1153,10 @@
1153
1153
  --cv-p-i-danger: var(--cv-p-danger, #c62828);
1154
1154
  --cv-p-i-radius: var(--cv-p-radius, 0);
1155
1155
  --cv-p-i-touch: 2.75rem;
1156
+ --cv-p-i-scrollbar-thumb: var(--cv-p-scrollbar-thumb, var(--cv-p-i-border));
1157
+ --cv-p-i-scrollbar-thumb-hover: var(--cv-p-scrollbar-thumb-hover, var(--cv-p-i-accent));
1158
+ --cv-p-i-wallpaper-ink: var(--cv-p-i-border);
1159
+ --cv-p-i-wallpaper: radial-gradient(circle at 2px 2px, var(--cv-p-i-wallpaper-ink) 1px, transparent 1.5px), radial-gradient(circle at 14px 14px, var(--cv-p-i-wallpaper-ink) 1px, transparent 1.5px);
1156
1160
  display: flex;
1157
1161
  flex-direction: column;
1158
1162
  min-height: 0;
@@ -1202,9 +1206,9 @@
1202
1206
  color: var(--cv-p-i-accent-contrast); padding: 0 0.35rem;
1203
1207
  }
1204
1208
 
1205
- .cv-p-inbox { overflow-y: auto; }
1209
+ .cv-p-inbox { overflow-y: auto; touch-action: pan-y pinch-zoom; }
1206
1210
  .cv-p-inbox__title { margin: 0; padding: 0.75rem 1rem; font-size: 1rem; border-bottom: 1px solid var(--cv-p-i-border); }
1207
- .cv-p-filters { display: flex; gap: 0.5rem; padding: 0.625rem 1rem; overflow-x: auto; border-bottom: 1px solid var(--cv-p-i-border); }
1211
+ .cv-p-filters { --cv-p-i-fade: 1rem; display: flex; gap: 0.5rem; padding: 0.625rem 1rem; overflow-x: auto; border-bottom: 1px solid var(--cv-p-i-border); }
1208
1212
  .cv-p-error { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1.5rem 1rem; text-align: center; color: var(--cv-p-i-danger, #b91c1c); }
1209
1213
  .cv-p-error__message { margin: 0; }
1210
1214
  .cv-p-loading { display: flex; flex-direction: column; gap: 0.5rem; padding: 1rem; }
@@ -1245,23 +1249,59 @@
1245
1249
  .cv-p-row__meta { display: flex; flex-direction: column; align-items: flex-end; gap: 0.25rem; font: 0.7rem 'SFMono-Regular', Consolas, monospace; color: var(--cv-p-i-text-muted); }
1246
1250
  .cv-p-row__unread { min-width: 1.25rem; padding: 0 0.3rem; text-align: center; font-weight: 700; background: var(--cv-p-i-accent); color: var(--cv-p-i-accent-contrast); }
1247
1251
 
1248
- .cv-p-thread__header { display: flex; align-items: center; gap: 0.5rem; padding: 0.5rem 1rem; border-bottom: 1px solid var(--cv-p-i-border); }
1249
- .cv-p-thread__heading { flex: 1; min-width: 0; display: flex; flex-direction: column; }
1250
- .cv-p-thread__title { flex: 1; margin: 0; font-size: 1rem; min-width: 0; }
1251
- .cv-p-thread__title-button { min-height: var(--cv-p-i-touch); padding: 0; background: none; border: 0; color: inherit; font: inherit; font-weight: 600; text-align: left; text-decoration: underline; cursor: pointer; }
1252
+ .cv-p-thread__header { display: flex; align-items: center; gap: 0.5rem; min-height: 4rem; padding: 0.25rem 0.75rem; background: var(--cv-p-i-surface-raised); border-bottom: 1px solid var(--cv-p-i-border); }
1253
+ .cv-p-thread__back { flex: 0 0 auto; display: inline-grid; place-items: center; min-width: var(--cv-p-i-touch); min-height: var(--cv-p-i-touch); margin-inline-start: -0.5rem; padding: 0; background: transparent; border: 0; border-radius: var(--cv-p-i-radius); color: var(--cv-p-i-text); font: inherit; cursor: pointer; }
1254
+ .cv-p-thread__back svg { display: block; }
1255
+ .cv-p-thread__avatar { flex: 0 0 auto; display: grid; place-items: center; width: 2.5rem; height: 2.5rem; background: var(--cv-p-i-surface); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); color: var(--cv-p-i-accent); font: 700 0.75rem 'SFMono-Regular', Consolas, monospace; text-transform: uppercase; }
1256
+ .cv-p-thread__avatar svg { width: 1.25rem; height: 1.25rem; }
1257
+ .cv-p-thread__heading { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
1258
+ .cv-p-thread__eyebrow { margin: 0; font: 0.64rem 'SFMono-Regular', Consolas, monospace; letter-spacing: 0.08em; text-transform: uppercase; color: var(--cv-p-i-text-muted); }
1259
+ .cv-p-thread__title { margin: 0; font-size: 1rem; font-weight: 600; line-height: 1.3; min-width: 0; overflow-wrap: anywhere; }
1260
+ .cv-p-thread__title-text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; line-clamp: 1; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
1261
+ .cv-p-thread__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.125rem 0.5rem; min-width: 0; padding-top: 0.5rem; }
1262
+ .cv-p-thread__title-button { display: flex; align-items: center; max-width: 100%; min-height: var(--cv-p-i-touch); padding: 0; background: none; border: 0; color: inherit; font: inherit; font-weight: 600; text-align: start; text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.2em; cursor: pointer; }
1252
1263
  .cv-p-thread__subject-card { margin: 0.75rem 1rem 0; padding: 0.625rem 0.75rem; border: 1px solid var(--cv-p-i-border); background: var(--cv-p-i-surface-raised); border-radius: var(--cv-p-i-radius); font-size: 0.82rem; }
1253
- .cv-p-thread__scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-anchor: none; padding: 0.5rem 1rem 1rem; }
1264
+ .cv-p-thread__scroll:focus { outline: none; }
1265
+ .cv-p-thread__scroll { flex: 1; min-height: 0; overflow-y: auto; overflow-anchor: none; touch-action: pan-y pinch-zoom; padding: 0.5rem 0.75rem 1rem; background-image: var(--cv-p-wallpaper, var(--cv-p-i-wallpaper)); background-size: var(--cv-p-wallpaper-size, 24px 24px); }
1254
1266
  .cv-p-thread__older { display: block; margin: 0 auto 0.5rem; min-height: var(--cv-p-i-touch); padding: 0 1rem; background: transparent; border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); }
1255
1267
  .cv-p-thread__messages { display: flex; flex-direction: column; gap: 0.5rem; }
1256
1268
  .cv-p-thread__live { padding: 0 1rem; font-size: 0.75rem; color: var(--cv-p-i-accent); }
1257
1269
  .cv-p-thread__live:empty { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
1258
1270
  .cv-p-thread__closed { margin: 0; padding: 1rem; text-align: center; color: var(--cv-p-i-text-muted); border-top: 1px solid var(--cv-p-i-border); }
1259
- .cv-p-day { align-self: center; margin: 0.5rem 0; font: 0.65rem 'SFMono-Regular', Consolas, monospace; text-transform: uppercase; color: var(--cv-p-i-text-muted); }
1260
-
1261
- .cv-p-bubble { max-width: 82%; align-self: flex-start; padding: 0.5rem 0.7rem; font-size: 0.88rem; background: var(--cv-p-i-surface-raised); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); }
1262
- .cv-p-bubble--mine { align-self: flex-end; background: var(--cv-p-i-highlight); border-color: var(--cv-p-i-accent); }
1263
- .cv-p-bubble__author { display: block; margin-bottom: 0.15rem; font: 0.65rem 'SFMono-Regular', Consolas, monospace; text-transform: uppercase; color: var(--cv-p-i-accent); }
1264
- .cv-p-bubble__meta { display: flex; justify-content: flex-end; align-items: center; gap: 0.35rem; margin-top: 0.25rem; font: 0.65rem 'SFMono-Regular', Consolas, monospace; color: var(--cv-p-i-text-muted); }
1271
+ .cv-p-day { align-self: center; margin: 0.5rem 0; padding: 0.25rem 0.75rem; background: var(--cv-p-i-surface-raised); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); font: 0.65rem 'SFMono-Regular', Consolas, monospace; letter-spacing: 0.06em; text-transform: uppercase; color: var(--cv-p-i-text-muted); }
1272
+
1273
+ .cv-p-bubble { max-width: 85%; align-self: flex-start; position: relative; display: flex; flex-wrap: wrap; align-items: flex-end; column-gap: 0.5rem; padding: 0.5rem 0.7rem; font-size: 0.88rem; background: var(--cv-p-i-surface-raised); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); border-bottom-left-radius: 0; --cv-p-tail-edge: var(--cv-p-i-border); --cv-p-tail-fill: var(--cv-p-i-surface-raised); }
1274
+ .cv-p-bubble-row { display: flex; align-items: flex-start; gap: 0.5rem; align-self: flex-start; max-width: 92%; }
1275
+ .cv-p-bubble-row__avatar { flex: 0 0 auto; width: 2rem; }
1276
+ .cv-p-bubble-row > .cv-p-bubble { max-width: none; min-width: 0; }
1277
+ .cv-p-avatar { display: grid; place-items: center; width: 2rem; height: 2rem; overflow: hidden; background: var(--cv-p-i-surface-raised); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); color: var(--cv-p-i-text); font: 700 0.7rem 'SFMono-Regular', Consolas, monospace; letter-spacing: 0.02em; }
1278
+ .cv-p-avatar > img { display: block; width: 100%; height: 100%; object-fit: cover; }
1279
+ .cv-p-bubble--mine { align-self: flex-end; background: var(--cv-p-i-highlight); border-color: var(--cv-p-i-accent); --cv-p-tail-edge: var(--cv-p-i-accent); --cv-p-tail-fill: var(--cv-p-i-highlight); border-bottom-left-radius: var(--cv-p-i-radius); border-bottom-right-radius: 0; }
1280
+ .cv-p-bubble::before, .cv-p-bubble::after { content: ''; position: absolute; width: 0; height: 0; border-style: solid; border-color: transparent; pointer-events: none; }
1281
+ .cv-p-bubble::before { left: -10px; bottom: -1px; border-width: 0 0 9px 9px; border-bottom-color: var(--cv-p-tail-edge); }
1282
+ .cv-p-bubble::after { left: -8px; bottom: 0; border-width: 0 0 8px 8px; border-bottom-color: var(--cv-p-tail-fill); }
1283
+ .cv-p-bubble--mine::before { left: auto; right: -10px; border-width: 0 9px 9px 0; border-bottom-color: var(--cv-p-tail-edge); }
1284
+ .cv-p-bubble--mine::after { left: auto; right: -8px; border-width: 0 8px 8px 0; border-bottom-color: var(--cv-p-tail-fill); }
1285
+ .cv-p-bubble-row > .cv-p-bubble:not(.cv-p-bubble--no-tail) { margin-left: 0.25rem; }
1286
+ .cv-p-bubble--no-tail { border-radius: var(--cv-p-i-radius); }
1287
+ .cv-p-bubble--no-tail::before, .cv-p-bubble--no-tail::after { content: none; }
1288
+ @media (forced-colors: active) {
1289
+ .cv-p-bubble::before, .cv-p-bubble::after { content: none; }
1290
+ .cv-p-bubble, .cv-p-bubble--mine { border-radius: var(--cv-p-i-radius); }
1291
+ .cv-p-thread__scroll { background-image: none; }
1292
+ .cv-p-thread__scroll, .cv-p-inbox, .cv-p-composer__input { scrollbar-width: auto; scrollbar-color: auto; }
1293
+ .cv-p-filters, .cv-p-quick { mask-image: none; -webkit-mask-image: none; }
1294
+ .cv-p-thread__latest-badge { border: 1px solid ButtonText; }
1295
+ }
1296
+ @media print {
1297
+ .cv-p-bubble::before, .cv-p-bubble::after { content: none; }
1298
+ .cv-p-bubble, .cv-p-bubble--mine { border-radius: var(--cv-p-i-radius); }
1299
+ .cv-p-thread__scroll { background-image: none; }
1300
+ }
1301
+ .cv-p-bubble__author { display: block; flex: 1 0 100%; margin-bottom: 0.15rem; font: 0.65rem 'SFMono-Regular', Consolas, monospace; text-transform: uppercase; color: var(--cv-p-i-accent); }
1302
+ .cv-p-bubble > .cv-p-text { flex: 0 1 auto; min-width: 0; margin-inline-end: auto; }
1303
+ .cv-p-bubble > .cv-p-attachment, .cv-p-bubble > .cv-p-bubble__actions { flex: 1 0 100%; }
1304
+ .cv-p-bubble__meta { display: flex; flex: 0 0 auto; justify-content: flex-end; align-items: center; gap: 0.35rem; margin-inline-start: auto; margin-top: 0.25rem; font: 0.65rem 'SFMono-Regular', Consolas, monospace; color: var(--cv-p-i-text-muted); }
1265
1305
  .cv-p-bubble__status { display: inline-flex; align-items: center; gap: 0.25rem; }
1266
1306
  .cv-p-bubble__retry { min-height: var(--cv-p-i-touch); display: inline-flex; align-items: center; gap: 0.25rem; padding: 0 0.5rem; background: transparent; border: 1px solid var(--cv-p-i-danger); color: var(--cv-p-i-danger); border-radius: var(--cv-p-i-radius); font-size: 0.7rem; }
1267
1307
  .cv-p-bubble__actions { display: inline-flex; gap: 0.5rem; margin-top: 0.25rem; }
@@ -1272,11 +1312,15 @@
1272
1312
  .cv-p-attachment__audio { width: 100%; min-height: var(--cv-p-i-touch); }
1273
1313
  .cv-p-attachment__name, .cv-p-attachment__size { font-size: 0.75rem; overflow-wrap: anywhere; }
1274
1314
 
1275
- .cv-p-composer { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.5rem 1rem 1rem; border-top: 1px solid var(--cv-p-i-border); }
1276
- .cv-p-composer__row { display: flex; align-items: flex-end; gap: 0.5rem; }
1277
- .cv-p-composer__input { flex: 1; min-height: var(--cv-p-i-touch); max-height: 8rem; resize: none; padding: 0.7rem; font: inherit; font-size: 0.9rem; color: inherit; background: var(--cv-p-i-surface); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); }
1315
+ .cv-p-composer { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.5rem 0.75rem 0.75rem; background: var(--cv-p-i-surface-raised); border-top: 1px solid var(--cv-p-i-border); }
1316
+ .cv-p-composer__row { display: flex; align-items: flex-end; gap: 0.25rem; }
1317
+ .cv-p-composer__attach { flex: 0 0 auto; display: inline-grid; place-items: center; min-width: var(--cv-p-i-touch); min-height: var(--cv-p-i-touch); padding: 0; background: transparent; border: 0; border-radius: var(--cv-p-i-radius); color: var(--cv-p-i-text-muted); font: inherit; cursor: pointer; }
1318
+ .cv-p-composer__attach:disabled { opacity: 0.45; cursor: not-allowed; }
1319
+ .cv-p-composer__attach svg, .cv-p-composer__send svg { display: block; }
1320
+ .cv-p-composer__input { flex: 1 1 auto; min-width: 0; min-height: var(--cv-p-i-touch); max-height: 6.5rem; overflow-y: auto; resize: none; padding: 0.7rem 0.75rem; font: inherit; font-size: 0.9rem; color: inherit; background: var(--cv-p-i-surface); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); }
1321
+ .cv-p-composer__send { flex: 0 0 auto; padding: 0; margin-inline-start: 0.25rem; }
1278
1322
  .cv-p-composer__error { margin: 0; font-size: 0.8rem; color: var(--cv-p-i-danger); }
1279
- .cv-p-quick { display: flex; gap: 0.5rem; overflow-x: auto; }
1323
+ .cv-p-quick { --cv-p-i-fade: 0.75rem; display: flex; gap: 0.5rem; overflow-x: auto; margin: -0.25rem calc(-1 * var(--cv-p-i-fade)); padding-block: 0.25rem; }
1280
1324
  .cv-p-files { display: flex; flex-direction: column; gap: 0.25rem; margin: 0; padding: 0; list-style: none; }
1281
1325
  .cv-p-files__item { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; }
1282
1326
  .cv-p-files__name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -1284,16 +1328,91 @@
1284
1328
  .cv-p-files__remove { min-width: var(--cv-p-i-touch); min-height: var(--cv-p-i-touch); background: transparent; border: 0; color: inherit; font: inherit; cursor: pointer; }
1285
1329
 
1286
1330
  .cv-p-protocol { min-width: 0; overflow-wrap: anywhere; font: 0.7rem 'SFMono-Regular', Consolas, monospace; letter-spacing: 0.04em; color: var(--cv-p-i-text-muted); }
1287
- .cv-p-protocol--header { display: flex; align-items: center; gap: 0.5rem; }
1288
- .cv-p-protocol__copy { min-height: var(--cv-p-i-touch); min-width: var(--cv-p-i-touch); padding: 0 0.75rem; background: transparent; border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); color: var(--cv-p-i-text); font: inherit; font-size: 0.75rem; cursor: pointer; }
1331
+ .cv-p-protocol--header { display: inline-flex; align-items: center; gap: 0.125rem; }
1332
+ .cv-p-protocol__copy { display: inline-flex; align-items: center; justify-content: center; gap: 0.25rem; min-height: 2.25rem; min-width: 2.75rem; margin: -0.5rem -0.5rem; padding: 0 0.5rem; background: transparent; border: 0; border-radius: var(--cv-p-i-radius); color: var(--cv-p-i-text-muted); font: inherit; cursor: pointer; }
1333
+ .cv-p-protocol__copied { font-size: 0.7rem; color: var(--cv-p-i-accent); white-space: nowrap; }
1289
1334
  .cv-p-search { padding: 0.625rem 1rem; border-bottom: 1px solid var(--cv-p-i-border); }
1290
1335
  .cv-p-search__input { width: 100%; box-sizing: border-box; min-height: var(--cv-p-i-touch); padding: 0 0.75rem; font: inherit; font-size: 0.9rem; color: var(--cv-p-i-text); background: var(--cv-p-i-surface); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); }
1291
1336
  .cv-p-search__input:focus-visible, .cv-p-protocol__copy:focus-visible { outline: 2px solid var(--cv-p-i-accent); outline-offset: 2px; }
1292
1337
 
1293
1338
  @media (prefers-reduced-motion: no-preference) {
1339
+ .cv-p-inbox, .cv-p-filters, .cv-p-quick { scroll-behavior: smooth; }
1340
+ .cv-p-thread__latest-button { animation: cv-p-latest-in 0.16s ease-out; }
1294
1341
  .cv-p-protocol__copy, .cv-p-search__input { transition: border-color 0.12s, background-color 0.12s; }
1295
- .cv-p-row, .cv-p-button, .cv-p-chip { transition: background-color 0.12s, border-color 0.12s; }
1342
+ .cv-p-row, .cv-p-button, .cv-p-chip, .cv-p-thread__back, .cv-p-composer__attach { transition: background-color 0.12s, border-color 0.12s; }
1343
+ }
1344
+
1345
+ /* Scrolls. Verticais: barra fina no tema. Faixas horizontais: sem barra, com esmaecimento nas bordas. O
1346
+ scroller da conversa NUNCA ganha scroll-behavior: smooth, porque o posicionamento inicial e a âncora ao
1347
+ carregar mensagens antigas atribuem scrollTop e precisam ser instantâneos. */
1348
+ .cv-p-thread__scroll, .cv-p-inbox, .cv-p-composer__input {
1349
+ scrollbar-width: thin; scrollbar-color: var(--cv-p-i-scrollbar-thumb) transparent; overscroll-behavior-y: contain;
1350
+ }
1351
+ @media not (forced-colors: active) {
1352
+ .cv-p-thread__scroll::-webkit-scrollbar, .cv-p-inbox::-webkit-scrollbar, .cv-p-composer__input::-webkit-scrollbar { width: 6px; height: 6px; }
1353
+ .cv-p-thread__scroll::-webkit-scrollbar-track, .cv-p-inbox::-webkit-scrollbar-track, .cv-p-composer__input::-webkit-scrollbar-track { background: transparent; }
1354
+ .cv-p-thread__scroll::-webkit-scrollbar-button, .cv-p-inbox::-webkit-scrollbar-button, .cv-p-composer__input::-webkit-scrollbar-button { display: none; }
1355
+ .cv-p-thread__scroll::-webkit-scrollbar-thumb, .cv-p-inbox::-webkit-scrollbar-thumb, .cv-p-composer__input::-webkit-scrollbar-thumb { background-color: var(--cv-p-i-scrollbar-thumb); border-radius: var(--cv-p-i-radius); }
1356
+ .cv-p-thread__scroll::-webkit-scrollbar-thumb:hover, .cv-p-inbox::-webkit-scrollbar-thumb:hover, .cv-p-composer__input::-webkit-scrollbar-thumb:hover,
1357
+ .cv-p-thread__scroll::-webkit-scrollbar-thumb:active, .cv-p-inbox::-webkit-scrollbar-thumb:active, .cv-p-composer__input::-webkit-scrollbar-thumb:active { background-color: var(--cv-p-i-scrollbar-thumb-hover); }
1358
+ }
1359
+ .cv-p-filters, .cv-p-quick {
1360
+ padding-inline: var(--cv-p-i-fade); scroll-padding-inline: var(--cv-p-i-fade);
1361
+ scrollbar-width: none; -ms-overflow-style: none; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity;
1362
+ mask-image: linear-gradient(to right, transparent, #000 var(--cv-p-i-fade), #000 calc(100% - var(--cv-p-i-fade)), transparent);
1363
+ -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--cv-p-i-fade), #000 calc(100% - var(--cv-p-i-fade)), transparent);
1364
+ }
1365
+ .cv-p-filters::-webkit-scrollbar, .cv-p-quick::-webkit-scrollbar { display: none; }
1366
+ .cv-p-filters > .cv-p-chip, .cv-p-quick > .cv-p-chip { scroll-snap-align: start; }
1367
+
1368
+ .cv-p-thread__latest { position: sticky; bottom: 0; height: 0; }
1369
+ .cv-p-thread__latest-button {
1370
+ position: absolute; inset-inline-end: 0.25rem; bottom: 0.75rem; display: grid; place-items: center; width: var(--cv-p-i-touch); height: var(--cv-p-i-touch); padding: 0;
1371
+ background: var(--cv-p-i-surface-raised); border: 1px solid var(--cv-p-i-border); border-radius: var(--cv-p-i-radius); color: var(--cv-p-i-text);
1372
+ box-shadow: 0 1px 4px rgb(0 0 0 / 35%); font: inherit; cursor: pointer;
1373
+ }
1374
+ .cv-p-thread__latest-button:hover { border-color: var(--cv-p-i-accent); }
1375
+ .cv-p-thread__latest-button svg { display: block; }
1376
+ .cv-p-thread__latest-badge {
1377
+ position: absolute; top: -0.5rem; inset-inline-end: -0.375rem; display: grid; place-items: center; min-width: 1.25rem; height: 1.25rem; padding: 0 0.3rem;
1378
+ background: var(--cv-p-i-accent); color: var(--cv-p-i-accent-contrast); border-radius: var(--cv-p-i-radius); font: 700 0.7rem 'SFMono-Regular', Consolas, monospace;
1379
+ }
1380
+ @keyframes cv-p-latest-in {
1381
+ from { opacity: 0; transform: translateY(0.5rem); }
1382
+ to { opacity: 1; transform: none; }
1296
1383
  }
1297
1384
 
1385
+ /* Item de coluna flex com overflow ≠ visible (no próprio item) perde o min-height:auto e encolhe; os quatro últimos são defensivos. */
1386
+ .cv-p-filters, .cv-p-quick, .cv-p-search, .cv-p-composer, .cv-p-thread__header, .cv-p-thread__subject-card { flex: 0 0 auto; }
1387
+
1298
1388
  .cv-p-root { display: flex; flex-direction: column; min-height: 0; height: 100%; }
1299
1389
  .cv-p-root__screen { display: flex; flex-direction: column; flex: 1; min-height: 0; }
1390
+
1391
+ /* Texto da mensagem do participante (renderizador próprio; o MessageText dos outros fluxos não muda). */
1392
+ .cv-p-text { font-size: 14.2px; line-height: 19px; white-space: pre-wrap; overflow-wrap: break-word; word-break: break-word; user-select: text; }
1393
+ .cv-p-text__code, .cv-p-text__pre { font-family: 'SFMono-Regular', Consolas, monospace; background: color-mix(in srgb, var(--cv-p-i-border) 45%, var(--cv-p-i-surface)); }
1394
+ .cv-p-text__code { padding: 0 0.25rem; font-size: 0.9em; border-radius: var(--cv-p-i-radius); }
1395
+ .cv-p-text__pre { display: block; margin: 0.25rem 0; padding: 0.5rem; overflow-x: auto; white-space: pre; font-size: 0.9em; line-height: 1.4; border-inline-start: 2px solid var(--cv-p-i-accent); border-radius: var(--cv-p-i-radius); scrollbar-width: thin; scrollbar-color: var(--cv-p-i-scrollbar-thumb) transparent; }
1396
+ .cv-p-text__pre > code { font: inherit; }
1397
+ .cv-p-text__quote { margin: 0.25rem 0; padding-inline-start: 0.5rem; border-inline-start: 3px solid var(--cv-p-i-border); color: var(--cv-p-i-text-muted); }
1398
+ .cv-p-text__list { margin: 0.25rem 0; padding-inline-start: 1.25rem; }
1399
+ .cv-p-text__link { color: var(--cv-p-i-accent); text-decoration: underline; text-underline-offset: 0.15em; padding-block: 0.2em; overflow-wrap: anywhere; }
1400
+ .cv-p-text__link:focus-visible, .cv-p-text__link-copy:focus-visible, .cv-p-copyable:focus-visible { outline: 2px solid var(--cv-p-i-accent); outline-offset: 2px; }
1401
+ .cv-p-text__link-group { white-space: normal; }
1402
+ .cv-p-text__link-copy, .cv-p-copyable { position: relative; display: inline; margin: 0; padding: 0; background: transparent; border: 0; color: inherit; font: inherit; text-align: inherit; cursor: pointer; user-select: text; }
1403
+ .cv-p-text__link-copy { margin-inline-start: 0.25rem; color: var(--cv-p-i-text-muted); vertical-align: -0.1em; }
1404
+ .cv-p-text__link-copy::after, .cv-p-copyable::after { content: ''; position: absolute; inset-inline: 0; top: 50%; min-height: 1.5rem; transform: translateY(-50%); }
1405
+ .cv-p-text__link-copy::after { inset-inline: 0 auto; min-width: var(--cv-p-i-touch); }
1406
+ .cv-p-copyable { padding: 0 0.15rem; font-family: 'SFMono-Regular', Consolas, monospace; font-size: 0.92em; background: color-mix(in srgb, var(--cv-p-i-accent) 14%, transparent); border-bottom: 1px dotted var(--cv-p-i-accent); border-radius: var(--cv-p-i-radius); }
1407
+ .cv-p-copyable--email { font-family: inherit; }
1408
+ .cv-p-copyable__done { margin-inline-start: 0.35rem; font-size: 0.85em; color: var(--cv-p-i-accent); }
1409
+ @media (forced-colors: active) {
1410
+ .cv-p-text__code, .cv-p-text__pre, .cv-p-copyable { border: 1px solid; background: none; }
1411
+ .cv-p-text__link, .cv-p-text__link-copy { color: LinkText; }
1412
+ }
1413
+ @media not (forced-colors: active) {
1414
+ .cv-p-text__pre::-webkit-scrollbar { height: 6px; }
1415
+ .cv-p-text__pre::-webkit-scrollbar-track { background: transparent; }
1416
+ .cv-p-text__pre::-webkit-scrollbar-thumb { background-color: var(--cv-p-i-scrollbar-thumb); border-radius: var(--cv-p-i-radius); }
1417
+ .cv-p-text__pre::-webkit-scrollbar-thumb:hover { background-color: var(--cv-p-i-scrollbar-thumb-hover); }
1418
+ }
@@ -1,64 +0,0 @@
1
- // src/useDarkMode.ts
2
- import { useState, useEffect, useCallback } from "react";
3
- var STORAGE_KEY = "conversations-ui-dark-mode";
4
- function getInitialDark() {
5
- if (typeof window === "undefined") return false;
6
- const stored = localStorage.getItem(STORAGE_KEY);
7
- if (stored !== null) {
8
- return stored === "true";
9
- }
10
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
11
- }
12
- function useIsDarkTheme() {
13
- const [isDark, setIsDark] = useState(
14
- () => typeof document !== "undefined" && document.documentElement.classList.contains("dark")
15
- );
16
- useEffect(() => {
17
- const root = document.documentElement;
18
- const observer = new MutationObserver(() => setIsDark(root.classList.contains("dark")));
19
- observer.observe(root, { attributes: true, attributeFilter: ["class"] });
20
- setIsDark(root.classList.contains("dark"));
21
- return () => observer.disconnect();
22
- }, []);
23
- return isDark;
24
- }
25
- function useDarkMode() {
26
- const [isDark, setIsDark] = useState(getInitialDark);
27
- useEffect(() => {
28
- const root = document.documentElement;
29
- if (isDark) {
30
- root.classList.add("dark");
31
- } else {
32
- root.classList.remove("dark");
33
- }
34
- localStorage.setItem(STORAGE_KEY, String(isDark));
35
- }, [isDark]);
36
- useEffect(() => {
37
- const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
38
- const handleChange = (event) => {
39
- const stored = localStorage.getItem(STORAGE_KEY);
40
- if (stored === null) {
41
- setIsDark(event.matches);
42
- }
43
- };
44
- mediaQuery.addEventListener("change", handleChange);
45
- return () => mediaQuery.removeEventListener("change", handleChange);
46
- }, []);
47
- const toggle = useCallback(() => {
48
- setIsDark((prev) => !prev);
49
- }, []);
50
- return { isDark, toggle };
51
- }
52
-
53
- // src/lib/cn.ts
54
- import { clsx } from "clsx";
55
- import { twMerge } from "tailwind-merge";
56
- function cn(...inputs) {
57
- return twMerge(clsx(inputs));
58
- }
59
-
60
- export {
61
- cn,
62
- useIsDarkTheme,
63
- useDarkMode
64
- };
@@ -1,84 +0,0 @@
1
- import {
2
- parseWhatsAppFormatting
3
- } from "./chunk-CBYEHPX6.js";
4
-
5
- // src/MessageText.tsx
6
- import { useCallback, useState } from "react";
7
-
8
- // src/theme.ts
9
- var CHAT_TEXT_PRIMARY_CLASS = "text-[#111b21] dark:text-[#e9edef]";
10
- var CHAT_TEXT_SECONDARY_CLASS = "text-[#667781] dark:text-[#8696a0]";
11
-
12
- // src/messageTextCopyInteraction.ts
13
- function resolveCopyInteraction({
14
- copyOnClick,
15
- accessibleCopy,
16
- onCopy
17
- }) {
18
- if (!copyOnClick) return {};
19
- if (!accessibleCopy) return { onClick: onCopy };
20
- return {
21
- onClick: onCopy,
22
- role: "button",
23
- tabIndex: 0,
24
- onKeyDown: (event) => {
25
- if (event.key !== "Enter" && event.key !== " ") return;
26
- event.preventDefault();
27
- onCopy();
28
- }
29
- };
30
- }
31
-
32
- // src/MessageTextCopiedBadge.tsx
33
- import { jsx } from "react/jsx-runtime";
34
- var TAILWIND_CLASS = "absolute top-0 right-0 -translate-y-full bg-[#3b4a54] text-white text-[11px] px-1.5 py-0.5 rounded shadow-lg";
35
- function MessageTextCopiedBadge({ label = "Copiado!", appearance = "tailwind" }) {
36
- const className = appearance === "stylesheet" ? "cv-message-text__copied" : TAILWIND_CLASS;
37
- return /* @__PURE__ */ jsx("span", { className, children: label });
38
- }
39
-
40
- // src/MessageText.tsx
41
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
42
- var TAILWIND_CLASS2 = "text-[14.2px] leading-[19px] whitespace-pre-wrap break-words select-all [&_strong]:font-bold [&_em]:italic [&_del]:line-through";
43
- function resolveClassName(appearance, copyOnClick) {
44
- if (appearance === "tailwind") return TAILWIND_CLASS2;
45
- return copyOnClick ? "cv-message-text cv-message-text--copyable" : "cv-message-text";
46
- }
47
- function MessageText({
48
- message,
49
- copyOnClick = true,
50
- accessibleCopy = false,
51
- copiedLabel,
52
- appearance = "tailwind"
53
- }) {
54
- const [copied, setCopied] = useState(false);
55
- const handleCopy = useCallback(async () => {
56
- if (!copyOnClick || !message.content) return;
57
- try {
58
- await navigator.clipboard.writeText(message.content);
59
- setCopied(true);
60
- setTimeout(() => setCopied(false), 2e3);
61
- } catch {
62
- }
63
- }, [copyOnClick, message.content]);
64
- if (message.type === "template")
65
- return /* @__PURE__ */ jsx2("p", { className: `text-sm italic ${CHAT_TEXT_SECONDARY_CLASS}`, children: message.content ?? "Template message" });
66
- const interactionProps = resolveCopyInteraction({ copyOnClick, accessibleCopy, onCopy: handleCopy });
67
- return /* @__PURE__ */ jsxs(
68
- "div",
69
- {
70
- className: resolveClassName(appearance, copyOnClick),
71
- ...interactionProps,
72
- children: [
73
- /* @__PURE__ */ jsx2("div", { children: parseWhatsAppFormatting(message.content ?? "") }),
74
- copied && /* @__PURE__ */ jsx2(MessageTextCopiedBadge, { label: copiedLabel, appearance })
75
- ]
76
- }
77
- );
78
- }
79
-
80
- export {
81
- CHAT_TEXT_PRIMARY_CLASS,
82
- CHAT_TEXT_SECONDARY_CLASS,
83
- MessageText
84
- };