@convokitapp/vue-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.
package/dist/index.css CHANGED
@@ -176,6 +176,12 @@
176
176
  font-weight: 600;
177
177
  line-height: 1;
178
178
  }
179
+ .ckui-unread-badge--dot {
180
+ min-width: 8px;
181
+ width: 8px;
182
+ height: 8px;
183
+ padding: 0;
184
+ }
179
185
  .ckui-avatar {
180
186
  display: inline-grid;
181
187
  flex: 0 0 auto;
@@ -472,6 +478,10 @@ button.ckui-media-card {
472
478
  height: 18px;
473
479
  font-size: 10px;
474
480
  }
481
+ .ckui[data-density=compact] .ckui-unread-badge--dot {
482
+ min-width: 8px;
483
+ height: 8px;
484
+ }
475
485
  .ckui[data-density=compact] .ckui-message-list {
476
486
  gap: 5px;
477
487
  padding: 10px 12px;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/styles.css"],"sourcesContent":[".ckui-theme,\n.ckui {\n --ckui-background: #fafafa;\n --ckui-surface: #ffffff;\n --ckui-primary: #18181b;\n --ckui-text: #09090b;\n --ckui-muted: #71717a;\n --ckui-border: #e4e4e7;\n --ckui-error: #dc2626;\n --ckui-incoming: #f4f4f5;\n --ckui-outgoing: #18181b;\n --ckui-outgoing-text: #fafafa;\n --ckui-badge: #18181b;\n --ckui-radius: 10px;\n --ckui-avatar-size: 40px;\n --ckui-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n}\n\n.ckui-theme .ckui {\n --ckui-background: inherit;\n --ckui-surface: inherit;\n --ckui-primary: inherit;\n --ckui-text: inherit;\n --ckui-muted: inherit;\n --ckui-border: inherit;\n --ckui-error: inherit;\n --ckui-incoming: inherit;\n --ckui-outgoing: inherit;\n --ckui-outgoing-text: inherit;\n --ckui-badge: inherit;\n --ckui-radius: inherit;\n --ckui-avatar-size: inherit;\n --ckui-font: inherit;\n}\n\n.ckui,\n.ckui *,\n.ckui *::before,\n.ckui *::after { box-sizing: border-box; }\n\n.ckui { color: var(--ckui-text); font-family: var(--ckui-font); font-size: 14px; line-height: 1.45; }\n.ckui button, .ckui textarea { color: inherit; font: inherit; }\n.ckui button:focus-visible, .ckui textarea:focus-visible { outline: 2px solid color-mix(in srgb, var(--ckui-primary) 38%, white); outline-offset: 2px; }\n\n.ckui-conversation-list,\n.ckui-conversation {\n display: flex;\n min-width: 0;\n min-height: 0;\n height: 100%;\n overflow: hidden;\n flex-direction: column;\n border: 1px solid var(--ckui-border);\n border-radius: var(--ckui-radius);\n background: var(--ckui-surface);\n box-shadow: 0 1px 2px rgb(0 0 0 / 0.04);\n}\n\n.ckui-scroll-area, .ckui-message-list { min-height: 0; overflow: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }\n.ckui-scroll-area { flex: 1; background: var(--ckui-surface); }\n\n.ckui-conversation-list__toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 52px;\n padding: 8px 10px 8px 16px;\n border-bottom: 1px solid var(--ckui-border);\n background: var(--ckui-surface);\n color: var(--ckui-text);\n font-size: 14px;\n font-weight: 600;\n letter-spacing: -0.01em;\n}\n\n.ckui-conversation-list__items { display: grid; }\n.ckui-conversation-item {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n grid-auto-flow: column;\n grid-auto-columns: auto;\n gap: 12px;\n align-items: center;\n width: 100%;\n min-height: 68px;\n padding: 10px 14px;\n border: 0;\n border-bottom: 1px solid var(--ckui-border);\n border-radius: 0;\n background: var(--ckui-surface);\n cursor: pointer;\n text-align: left;\n transition: background-color 120ms ease;\n}\n.ckui-conversation-item:hover { background: color-mix(in srgb, var(--ckui-primary) 4%, var(--ckui-surface)); }\n.ckui-conversation-item[data-selected] { background: color-mix(in srgb, var(--ckui-primary) 7%, var(--ckui-surface)); }\n.ckui-conversation-item__body { display: grid; min-width: 0; gap: 2px; }\n.ckui-conversation-item__body strong, .ckui-conversation-item__body span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ckui-conversation-item__body strong { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }\n.ckui-conversation-item__body span { color: var(--ckui-muted); font-size: 12px; }\n.ckui-conversation-item[data-unread] .ckui-conversation-item__body strong { font-weight: 700; }\n.ckui-conversation-item[data-unread] .ckui-conversation-item__body span { color: var(--ckui-text); }\n.ckui-conversation-item__meta { display: grid; flex: 0 0 auto; gap: 4px; justify-items: end; align-self: start; padding-top: 2px; }\n.ckui-conversation-item__time { color: var(--ckui-muted); font-size: 11px; white-space: nowrap; }\n.ckui-unread-badge { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--ckui-badge); color: var(--ckui-outgoing-text); font-size: 11px; font-weight: 600; line-height: 1; }\n\n.ckui-avatar {\n display: inline-grid;\n flex: 0 0 auto;\n width: var(--ckui-avatar-size);\n height: var(--ckui-avatar-size);\n overflow: hidden;\n place-items: center;\n border: 1px solid var(--ckui-border);\n border-radius: 999px;\n background: color-mix(in srgb, var(--ckui-primary) 6%, var(--ckui-surface));\n color: var(--ckui-text);\n font-size: 12px;\n font-weight: 600;\n}\n.ckui-avatar__image, .ckui-avatar__fallback { width: 100%; height: 100%; }\n.ckui-avatar__image { object-fit: cover; }\n.ckui-avatar__fallback { display: grid; place-items: center; }\n.ckui-separator { display: none; }\n\n.ckui-icon-button, .ckui-send-button, .ckui-link-button { border: 0; background: transparent; cursor: pointer; }\n.ckui-icon-button { display: inline-grid; flex: 0 0 auto; width: 34px; height: 34px; place-items: center; border-radius: 7px; color: var(--ckui-muted); }\n.ckui-icon-button:hover { background: color-mix(in srgb, var(--ckui-primary) 6%, transparent); color: var(--ckui-text); }\n.ckui-state, .ckui-inline-state { display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 120px; padding: 20px; color: var(--ckui-muted); text-align: center; }\n.ckui-inline-state { min-height: 52px; font-size: 12px; }\n.ckui-state--error, .ckui-conversation-error { color: var(--ckui-error); }\n.ckui-link-button { color: currentColor; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }\n\n.ckui-conversation-header { display: flex; align-items: center; gap: 10px; min-height: 60px; padding: 8px 12px; border-bottom: 1px solid var(--ckui-border); background: var(--ckui-surface); }\n.ckui-conversation-header__body { display: grid; flex: 1; min-width: 0; gap: 1px; }\n.ckui-conversation-header__body strong { overflow: hidden; font-size: 14px; font-weight: 600; letter-spacing: -0.01em; text-overflow: ellipsis; white-space: nowrap; }\n.ckui-conversation-header__body span { color: var(--ckui-muted); font-size: 12px; }\n.ckui-conversation-error { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 14px; border-bottom: 1px solid color-mix(in srgb, var(--ckui-error) 22%, var(--ckui-border)); background: color-mix(in srgb, var(--ckui-error) 5%, var(--ckui-surface)); font-size: 12px; }\n\n.ckui-message-list { display: flex; flex: 1; flex-direction: column; gap: 12px; padding: 18px; background: var(--ckui-background); }\n.ckui-message-row { display: flex; flex-direction: column; align-items: flex-start; }\n.ckui-message-row--outgoing { align-items: flex-end; }\n.ckui-message-bubble { max-width: min(74%, 560px); padding: 9px 12px 7px; border: 1px solid var(--ckui-border); border-radius: calc(var(--ckui-radius) + 2px); background: var(--ckui-incoming); }\n.ckui-message-row--outgoing .ckui-message-bubble { border-color: var(--ckui-outgoing); background: var(--ckui-outgoing); color: var(--ckui-outgoing-text); }\n.ckui-message-sender { display: block; margin-bottom: 3px; color: var(--ckui-muted); font-size: 11px; font-weight: 600; }\n.ckui-message-text { overflow-wrap: anywhere; white-space: pre-wrap; }\n.ckui-message-time { display: flex; align-items: center; justify-content: flex-end; gap: 3px; margin-top: 5px; color: color-mix(in srgb, currentColor 62%, transparent); font-size: 10px; }\n.ckui-read-receipt { min-height: 16px; padding-top: 3px; color: var(--ckui-muted); font-size: 10px; }\n\n.ckui-media { margin-top: 8px; }\n.ckui-media-card { display: flex; align-items: center; gap: 9px; width: 100%; min-width: 210px; padding: 9px; overflow: hidden; border: 1px solid color-mix(in srgb, currentColor 16%, transparent); border-radius: 8px; background: color-mix(in srgb, var(--ckui-surface) 94%, transparent); color: var(--ckui-text); text-align: left; }\nbutton.ckui-media-card { cursor: pointer; }\n.ckui-media-card > span { display: grid; flex: 1; min-width: 0; }\n.ckui-media-card strong, .ckui-media-card small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ckui-media-card small { color: var(--ckui-muted); }\n.ckui-media-card--image { display: grid; max-width: 330px; padding: 0; }\n.ckui-media-card--image img { display: block; width: 100%; max-height: 280px; object-fit: cover; }\n.ckui-media-name { padding: 0 10px 9px; font-size: 11px; }\n.ckui-media-placeholder { min-height: 120px; place-items: center; padding: 20px; }\n\n.ckui-typing { min-height: 26px; padding: 5px 16px; border-top: 1px solid var(--ckui-border); background: var(--ckui-surface); color: var(--ckui-muted); font-size: 11px; }\n.ckui-composer { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ckui-border); background: var(--ckui-surface); }\n.ckui-composer__input { flex: 1; min-width: 0; min-height: 38px; max-height: 132px; padding: 9px 11px; resize: none; border: 1px solid var(--ckui-border); border-radius: 8px; outline: 0; background: var(--ckui-surface); box-shadow: 0 1px 2px rgb(0 0 0 / 0.03); }\n.ckui-composer__input::placeholder { color: var(--ckui-muted); }\n.ckui-composer__input:focus { border-color: color-mix(in srgb, var(--ckui-primary) 45%, var(--ckui-border)); }\n.ckui-send-button { display: inline-grid; flex: 0 0 auto; width: 38px; height: 38px; place-items: center; border-radius: 8px; background: var(--ckui-primary); color: var(--ckui-outgoing-text); box-shadow: 0 1px 2px rgb(0 0 0 / 0.08); }\n.ckui-send-button:hover:not(:disabled) { opacity: 0.9; }\n.ckui-send-button:disabled, .ckui-icon-button:disabled { cursor: not-allowed; opacity: 0.45; }\n\n.ckui[data-density='compact'] { font-size: 12px; }\n.ckui[data-density='compact'] .ckui-conversation-list__toolbar { min-height: 44px; }\n.ckui[data-density='compact'] .ckui-conversation-item { min-height: 46px; padding: 6px 10px; }\n.ckui[data-density='compact'] .ckui-avatar { --ckui-avatar-size: 30px; font-size: 10px; }\n.ckui[data-density='compact'] .ckui-conversation-item__meta { align-self: center; padding-top: 0; }\n.ckui[data-density='compact'] .ckui-unread-badge { min-width: 18px; height: 18px; font-size: 10px; }\n.ckui[data-density='compact'] .ckui-message-list { gap: 5px; padding: 10px 12px; }\n.ckui[data-density='compact'] .ckui-message-bubble { max-width: 88%; padding: 6px 9px; border-radius: 8px; }\n.ckui[data-density='compact'] .ckui-conversation-header { min-height: 48px; }\n.ckui[data-density='compact'] .ckui-typing { min-height: 22px; padding-block: 3px; }\n.ckui[data-density='compact'] .ckui-composer { padding: 6px 8px; }\n.ckui-spin { animation: ckui-spin 900ms linear infinite; }\n@keyframes ckui-spin { to { transform: rotate(360deg); } }\n@media (prefers-reduced-motion: reduce) { .ckui *, .ckui *::before, .ckui *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; } }\n@media (max-width: 560px) { .ckui-message-bubble { max-width: 88%; } .ckui-message-list { padding-inline: 12px; } }\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/styles.css"],"sourcesContent":[".ckui-theme,\n.ckui {\n --ckui-background: #fafafa;\n --ckui-surface: #ffffff;\n --ckui-primary: #18181b;\n --ckui-text: #09090b;\n --ckui-muted: #71717a;\n --ckui-border: #e4e4e7;\n --ckui-error: #dc2626;\n --ckui-incoming: #f4f4f5;\n --ckui-outgoing: #18181b;\n --ckui-outgoing-text: #fafafa;\n --ckui-badge: #18181b;\n --ckui-radius: 10px;\n --ckui-avatar-size: 40px;\n --ckui-font: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n}\n\n.ckui-theme .ckui {\n --ckui-background: inherit;\n --ckui-surface: inherit;\n --ckui-primary: inherit;\n --ckui-text: inherit;\n --ckui-muted: inherit;\n --ckui-border: inherit;\n --ckui-error: inherit;\n --ckui-incoming: inherit;\n --ckui-outgoing: inherit;\n --ckui-outgoing-text: inherit;\n --ckui-badge: inherit;\n --ckui-radius: inherit;\n --ckui-avatar-size: inherit;\n --ckui-font: inherit;\n}\n\n.ckui,\n.ckui *,\n.ckui *::before,\n.ckui *::after { box-sizing: border-box; }\n\n.ckui { color: var(--ckui-text); font-family: var(--ckui-font); font-size: 14px; line-height: 1.45; }\n.ckui button, .ckui textarea { color: inherit; font: inherit; }\n.ckui button:focus-visible, .ckui textarea:focus-visible { outline: 2px solid color-mix(in srgb, var(--ckui-primary) 38%, white); outline-offset: 2px; }\n\n.ckui-conversation-list,\n.ckui-conversation {\n display: flex;\n min-width: 0;\n min-height: 0;\n height: 100%;\n overflow: hidden;\n flex-direction: column;\n border: 1px solid var(--ckui-border);\n border-radius: var(--ckui-radius);\n background: var(--ckui-surface);\n box-shadow: 0 1px 2px rgb(0 0 0 / 0.04);\n}\n\n.ckui-scroll-area, .ckui-message-list { min-height: 0; overflow: auto; overscroll-behavior: contain; scrollbar-gutter: stable; }\n.ckui-scroll-area { flex: 1; background: var(--ckui-surface); }\n\n.ckui-conversation-list__toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n min-height: 52px;\n padding: 8px 10px 8px 16px;\n border-bottom: 1px solid var(--ckui-border);\n background: var(--ckui-surface);\n color: var(--ckui-text);\n font-size: 14px;\n font-weight: 600;\n letter-spacing: -0.01em;\n}\n\n.ckui-conversation-list__items { display: grid; }\n.ckui-conversation-item {\n display: grid;\n grid-template-columns: auto minmax(0, 1fr);\n grid-auto-flow: column;\n grid-auto-columns: auto;\n gap: 12px;\n align-items: center;\n width: 100%;\n min-height: 68px;\n padding: 10px 14px;\n border: 0;\n border-bottom: 1px solid var(--ckui-border);\n border-radius: 0;\n background: var(--ckui-surface);\n cursor: pointer;\n text-align: left;\n transition: background-color 120ms ease;\n}\n.ckui-conversation-item:hover { background: color-mix(in srgb, var(--ckui-primary) 4%, var(--ckui-surface)); }\n.ckui-conversation-item[data-selected] { background: color-mix(in srgb, var(--ckui-primary) 7%, var(--ckui-surface)); }\n.ckui-conversation-item__body { display: grid; min-width: 0; gap: 2px; }\n.ckui-conversation-item__body strong, .ckui-conversation-item__body span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ckui-conversation-item__body strong { font-size: 14px; font-weight: 600; letter-spacing: -0.01em; }\n.ckui-conversation-item__body span { color: var(--ckui-muted); font-size: 12px; }\n.ckui-conversation-item[data-unread] .ckui-conversation-item__body strong { font-weight: 700; }\n.ckui-conversation-item[data-unread] .ckui-conversation-item__body span { color: var(--ckui-text); }\n.ckui-conversation-item__meta { display: grid; flex: 0 0 auto; gap: 4px; justify-items: end; align-self: start; padding-top: 2px; }\n.ckui-conversation-item__time { color: var(--ckui-muted); font-size: 11px; white-space: nowrap; }\n.ckui-unread-badge { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--ckui-badge); color: var(--ckui-outgoing-text); font-size: 11px; font-weight: 600; line-height: 1; }\n.ckui-unread-badge--dot { min-width: 8px; width: 8px; height: 8px; padding: 0; }\n\n.ckui-avatar {\n display: inline-grid;\n flex: 0 0 auto;\n width: var(--ckui-avatar-size);\n height: var(--ckui-avatar-size);\n overflow: hidden;\n place-items: center;\n border: 1px solid var(--ckui-border);\n border-radius: 999px;\n background: color-mix(in srgb, var(--ckui-primary) 6%, var(--ckui-surface));\n color: var(--ckui-text);\n font-size: 12px;\n font-weight: 600;\n}\n.ckui-avatar__image, .ckui-avatar__fallback { width: 100%; height: 100%; }\n.ckui-avatar__image { object-fit: cover; }\n.ckui-avatar__fallback { display: grid; place-items: center; }\n.ckui-separator { display: none; }\n\n.ckui-icon-button, .ckui-send-button, .ckui-link-button { border: 0; background: transparent; cursor: pointer; }\n.ckui-icon-button { display: inline-grid; flex: 0 0 auto; width: 34px; height: 34px; place-items: center; border-radius: 7px; color: var(--ckui-muted); }\n.ckui-icon-button:hover { background: color-mix(in srgb, var(--ckui-primary) 6%, transparent); color: var(--ckui-text); }\n.ckui-state, .ckui-inline-state { display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 120px; padding: 20px; color: var(--ckui-muted); text-align: center; }\n.ckui-inline-state { min-height: 52px; font-size: 12px; }\n.ckui-state--error, .ckui-conversation-error { color: var(--ckui-error); }\n.ckui-link-button { color: currentColor; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }\n\n.ckui-conversation-header { display: flex; align-items: center; gap: 10px; min-height: 60px; padding: 8px 12px; border-bottom: 1px solid var(--ckui-border); background: var(--ckui-surface); }\n.ckui-conversation-header__body { display: grid; flex: 1; min-width: 0; gap: 1px; }\n.ckui-conversation-header__body strong { overflow: hidden; font-size: 14px; font-weight: 600; letter-spacing: -0.01em; text-overflow: ellipsis; white-space: nowrap; }\n.ckui-conversation-header__body span { color: var(--ckui-muted); font-size: 12px; }\n.ckui-conversation-error { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 14px; border-bottom: 1px solid color-mix(in srgb, var(--ckui-error) 22%, var(--ckui-border)); background: color-mix(in srgb, var(--ckui-error) 5%, var(--ckui-surface)); font-size: 12px; }\n\n.ckui-message-list { display: flex; flex: 1; flex-direction: column; gap: 12px; padding: 18px; background: var(--ckui-background); }\n.ckui-message-row { display: flex; flex-direction: column; align-items: flex-start; }\n.ckui-message-row--outgoing { align-items: flex-end; }\n.ckui-message-bubble { max-width: min(74%, 560px); padding: 9px 12px 7px; border: 1px solid var(--ckui-border); border-radius: calc(var(--ckui-radius) + 2px); background: var(--ckui-incoming); }\n.ckui-message-row--outgoing .ckui-message-bubble { border-color: var(--ckui-outgoing); background: var(--ckui-outgoing); color: var(--ckui-outgoing-text); }\n.ckui-message-sender { display: block; margin-bottom: 3px; color: var(--ckui-muted); font-size: 11px; font-weight: 600; }\n.ckui-message-text { overflow-wrap: anywhere; white-space: pre-wrap; }\n.ckui-message-time { display: flex; align-items: center; justify-content: flex-end; gap: 3px; margin-top: 5px; color: color-mix(in srgb, currentColor 62%, transparent); font-size: 10px; }\n.ckui-read-receipt { min-height: 16px; padding-top: 3px; color: var(--ckui-muted); font-size: 10px; }\n\n.ckui-media { margin-top: 8px; }\n.ckui-media-card { display: flex; align-items: center; gap: 9px; width: 100%; min-width: 210px; padding: 9px; overflow: hidden; border: 1px solid color-mix(in srgb, currentColor 16%, transparent); border-radius: 8px; background: color-mix(in srgb, var(--ckui-surface) 94%, transparent); color: var(--ckui-text); text-align: left; }\nbutton.ckui-media-card { cursor: pointer; }\n.ckui-media-card > span { display: grid; flex: 1; min-width: 0; }\n.ckui-media-card strong, .ckui-media-card small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.ckui-media-card small { color: var(--ckui-muted); }\n.ckui-media-card--image { display: grid; max-width: 330px; padding: 0; }\n.ckui-media-card--image img { display: block; width: 100%; max-height: 280px; object-fit: cover; }\n.ckui-media-name { padding: 0 10px 9px; font-size: 11px; }\n.ckui-media-placeholder { min-height: 120px; place-items: center; padding: 20px; }\n\n.ckui-typing { min-height: 26px; padding: 5px 16px; border-top: 1px solid var(--ckui-border); background: var(--ckui-surface); color: var(--ckui-muted); font-size: 11px; }\n.ckui-composer { display: flex; align-items: flex-end; gap: 8px; padding: 10px 12px; border-top: 1px solid var(--ckui-border); background: var(--ckui-surface); }\n.ckui-composer__input { flex: 1; min-width: 0; min-height: 38px; max-height: 132px; padding: 9px 11px; resize: none; border: 1px solid var(--ckui-border); border-radius: 8px; outline: 0; background: var(--ckui-surface); box-shadow: 0 1px 2px rgb(0 0 0 / 0.03); }\n.ckui-composer__input::placeholder { color: var(--ckui-muted); }\n.ckui-composer__input:focus { border-color: color-mix(in srgb, var(--ckui-primary) 45%, var(--ckui-border)); }\n.ckui-send-button { display: inline-grid; flex: 0 0 auto; width: 38px; height: 38px; place-items: center; border-radius: 8px; background: var(--ckui-primary); color: var(--ckui-outgoing-text); box-shadow: 0 1px 2px rgb(0 0 0 / 0.08); }\n.ckui-send-button:hover:not(:disabled) { opacity: 0.9; }\n.ckui-send-button:disabled, .ckui-icon-button:disabled { cursor: not-allowed; opacity: 0.45; }\n\n.ckui[data-density='compact'] { font-size: 12px; }\n.ckui[data-density='compact'] .ckui-conversation-list__toolbar { min-height: 44px; }\n.ckui[data-density='compact'] .ckui-conversation-item { min-height: 46px; padding: 6px 10px; }\n.ckui[data-density='compact'] .ckui-avatar { --ckui-avatar-size: 30px; font-size: 10px; }\n.ckui[data-density='compact'] .ckui-conversation-item__meta { align-self: center; padding-top: 0; }\n.ckui[data-density='compact'] .ckui-unread-badge { min-width: 18px; height: 18px; font-size: 10px; }\n.ckui[data-density='compact'] .ckui-unread-badge--dot { min-width: 8px; height: 8px; }\n.ckui[data-density='compact'] .ckui-message-list { gap: 5px; padding: 10px 12px; }\n.ckui[data-density='compact'] .ckui-message-bubble { max-width: 88%; padding: 6px 9px; border-radius: 8px; }\n.ckui[data-density='compact'] .ckui-conversation-header { min-height: 48px; }\n.ckui[data-density='compact'] .ckui-typing { min-height: 22px; padding-block: 3px; }\n.ckui[data-density='compact'] .ckui-composer { padding: 6px 8px; }\n.ckui-spin { animation: ckui-spin 900ms linear infinite; }\n@keyframes ckui-spin { to { transform: rotate(360deg); } }\n@media (prefers-reduced-motion: reduce) { .ckui *, .ckui *::before, .ckui *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; } }\n@media (max-width: 560px) { .ckui-message-bubble { max-width: 88%; } .ckui-message-list { padding-inline: 12px; } }\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Conversation as Conversation$1, InboxPage, MessageListOptions, Message, SendMessageInput, MarkConversationReadOptions, RealtimeConnectionHandlers, RealtimeSubscription, MessageEvent, MessageDeletedEvent, ReadEvent, TypingEvent, ReadPosition, InboxSummary, MessageMedia, ConvoKitClient, InboxEntry } from '@convokitapp/sdk';
1
+ import { Conversation as Conversation$1, InboxPage, MessageListOptions, Message, SendMessageInput, MarkConversationReadOptions, ConversationPrivateState, ClearConversationUnreadOptions, ClearUnreadResult, RealtimeConnectionHandlers, RealtimeSubscription, MessageEvent, MessageDeletedEvent, ReadEvent, TypingEvent, ReadPosition, InboxSummary, MessageMedia, ConvoKitClient, InboxEntry } from '@convokitapp/sdk';
2
2
  import * as vue from 'vue';
3
3
  import { CSSProperties, HTMLAttributes, Ref, VNodeChild, PropType, MaybeRefOrGetter, TextareaHTMLAttributes } from 'vue';
4
4
 
@@ -20,17 +20,30 @@ interface ConvoKitUiClient {
20
20
  cursor: string | null;
21
21
  archived: boolean;
22
22
  }): Promise<InboxPage>;
23
+ /** The room and, from a 0.7 core and backend, the caller's own `membership`; the room store captures
24
+ * `membership.privateStateVersion` once per open for that open's acknowledgements.
25
+ */
23
26
  getConversation(conversationId: string): Promise<Conversation$1>;
24
27
  /** Newest first, with a paired value cursor; never derive an offset from rendered rows. */
25
28
  getMessages(options: MessageListOptions): Promise<Message[]>;
26
29
  /** Complete authorized message, including related media absent from raw row events. */
27
30
  getMessage(id: string): Promise<Message>;
28
31
  sendMessage(input: SendMessageInput): Promise<Message>;
29
- /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward it
30
- * and reject a missing target with `code: 'MESSAGE_NOT_FOUND'` (or a 404 without a code); the UI never sends a
31
- * request without a target. Membership failures keep their error code, if any, so they surface as errors.
32
+ /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward the
33
+ * options unchanged (0.7 adds `privateStateVersion`, the version captured when the room opened; an adapter that
34
+ * drops it acknowledges the position but never clears the caller's unread marker) and reject a missing target
35
+ * with `code: 'MESSAGE_NOT_FOUND'` (or a 404 without a code); the UI never sends a request without a target.
36
+ * Membership failures keep their error code, if any, so they surface as errors.
32
37
  */
33
38
  markConversationRead(conversationId: string, options?: MarkConversationReadOptions): Promise<void>;
39
+ /** Mark the room unread for the caller only (0.7.0). Optional: `markUnread` rejects without it. */
40
+ markConversationUnread?(conversationId: string): Promise<ConversationPrivateState>;
41
+ /** Remove the caller's unread marker, only while it still has `options.ifVersion` when given (0.7.0); a mismatch or
42
+ * an unmarked room answers `cleared: false`, never an error. Optional: `clearUnread` rejects without it, and a room
43
+ * opened with a marker that renders nothing leaves the marker in place (the room store clears it through this
44
+ * member, never through an untargeted acknowledgement).
45
+ */
46
+ clearConversationUnread?(conversationId: string, options?: ClearConversationUnreadOptions): Promise<ClearUnreadResult>;
34
47
  sendTyping(input: {
35
48
  conversationId: string;
36
49
  isTyping: boolean;
@@ -38,8 +51,9 @@ interface ConvoKitUiClient {
38
51
  onConnectionEvent(handlers: RealtimeConnectionHandlers): RealtimeSubscription;
39
52
  /** Notify on inbox mutations AND on initial subscription/reconnect. No room data in the signal. */
40
53
  onInboxChanged(handler: () => void, onError?: (error: Error) => void): RealtimeSubscription;
41
- /** Message inserts/edits and read-position advances in the caller's rooms; never fires on join/rejoin. The list
42
- * store throttles these (`activityRefreshWindowMs`); room stores ignore them.
54
+ /** Message inserts/edits, read-position advances and the caller's own unread-marker changes in the caller's
55
+ * rooms; never fires on join/rejoin. The list store throttles these (`activityRefreshWindowMs`); room stores
56
+ * ignore them.
43
57
  */
44
58
  onInboxActivity?(handler: () => void, onError?: (error: Error) => void): RealtimeSubscription;
45
59
  onMessage(conversationId: string, handler: (event: MessageEvent) => void, onError?: (error: Error) => void): RealtimeSubscription;
@@ -64,7 +78,9 @@ interface ConversationPageRequest {
64
78
  type ConversationPageLoader = (request: ConversationPageRequest) => Promise<Conversation$1[]>;
65
79
  interface ConversationListState {
66
80
  conversations: Readonly<Ref<Conversation$1[]>>;
67
- /** Per-room preview, unread count and read state by conversation ID; empty on the legacy `getConversations` path. */
81
+ /** Per-room preview, unread count, read state and private unread marker (`isUnread`, `unreadMarkedAt`,
82
+ * `privateStateVersion`, 0.7.0) by conversation ID; empty on the legacy `getConversations` path.
83
+ */
68
84
  summaries: Readonly<Ref<ReadonlyMap<string, InboxSummary>>>;
69
85
  /** The bound session's user; `''` without a session, on the legacy path and after disposal. */
70
86
  currentUserId: Readonly<Ref<string>>;
@@ -106,7 +122,9 @@ interface ConversationItemSlotProps {
106
122
  index: number;
107
123
  selected: boolean;
108
124
  select: () => void;
109
- /** Present when the list carries an inbox summary for this row (0.6.0). */
125
+ /** Present when the list carries an inbox summary for this row (0.6.0); `summary.isUnread` (0.7.0) is the row's
126
+ * unread state including the viewer's private marker.
127
+ */
110
128
  summary?: InboxSummary;
111
129
  /** Present when the list knows the viewer (0.6.0); compare with `summary.latestMessage.senderId`. */
112
130
  currentUserId?: string;
@@ -1009,13 +1027,23 @@ interface ConversationListController extends ConversationListState {
1009
1027
  loadMore(): Promise<void>;
1010
1028
  setFilter(filter: ConversationFilter): Promise<void>;
1011
1029
  setQuery(query: string): Promise<void>;
1030
+ /** Mark a room unread for the viewer only (0.7.0); its summary shows the marker at once. Rejects when the adapter
1031
+ * lacks `markConversationUnread`.
1032
+ */
1033
+ markUnread(conversationId: string): Promise<void>;
1034
+ /** Remove the viewer's marker, only while it still has `options.ifVersion` when given; resolves to whether this
1035
+ * request removed it. Rejects when the adapter lacks `clearConversationUnread`.
1036
+ */
1037
+ clearUnread(conversationId: string, options?: ClearConversationUnreadOptions): Promise<boolean>;
1012
1038
  dispose(): Promise<void>;
1013
1039
  }
1014
1040
  declare function useConversationList(options: UseConversationListOptions): ConversationListController;
1015
1041
 
1016
1042
  interface ConversationListViewProps extends ConvoKitAppearanceProps {
1017
1043
  conversations: readonly Conversation$1[];
1018
- /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge. */
1044
+ /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge: the count, or
1045
+ * a numberless dot when `isUnread` is set without one (0.7.0).
1046
+ */
1019
1047
  summaries?: ReadonlyMap<string, InboxSummary>;
1020
1048
  /** The viewer; a preview from them reads `You: …`. Absent → no prefix. */
1021
1049
  currentUserId?: string;
@@ -1697,7 +1725,7 @@ interface ConvoKitTheme {
1697
1725
  incomingBubble: string;
1698
1726
  outgoingBubble: string;
1699
1727
  outgoingText: string;
1700
- /** Unread badge background (0.6.0); its label uses `outgoingText`. Defaults to the primary color. */
1728
+ /** Unread badge and dot background (0.6.0); the badge label uses `outgoingText`. Defaults to the primary color. */
1701
1729
  badge: string;
1702
1730
  radius: string;
1703
1731
  avatarSize: string;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Conversation as Conversation$1, InboxPage, MessageListOptions, Message, SendMessageInput, MarkConversationReadOptions, RealtimeConnectionHandlers, RealtimeSubscription, MessageEvent, MessageDeletedEvent, ReadEvent, TypingEvent, ReadPosition, InboxSummary, MessageMedia, ConvoKitClient, InboxEntry } from '@convokitapp/sdk';
1
+ import { Conversation as Conversation$1, InboxPage, MessageListOptions, Message, SendMessageInput, MarkConversationReadOptions, ConversationPrivateState, ClearConversationUnreadOptions, ClearUnreadResult, RealtimeConnectionHandlers, RealtimeSubscription, MessageEvent, MessageDeletedEvent, ReadEvent, TypingEvent, ReadPosition, InboxSummary, MessageMedia, ConvoKitClient, InboxEntry } from '@convokitapp/sdk';
2
2
  import * as vue from 'vue';
3
3
  import { CSSProperties, HTMLAttributes, Ref, VNodeChild, PropType, MaybeRefOrGetter, TextareaHTMLAttributes } from 'vue';
4
4
 
@@ -20,17 +20,30 @@ interface ConvoKitUiClient {
20
20
  cursor: string | null;
21
21
  archived: boolean;
22
22
  }): Promise<InboxPage>;
23
+ /** The room and, from a 0.7 core and backend, the caller's own `membership`; the room store captures
24
+ * `membership.privateStateVersion` once per open for that open's acknowledgements.
25
+ */
23
26
  getConversation(conversationId: string): Promise<Conversation$1>;
24
27
  /** Newest first, with a paired value cursor; never derive an offset from rendered rows. */
25
28
  getMessages(options: MessageListOptions): Promise<Message[]>;
26
29
  /** Complete authorized message, including related media absent from raw row events. */
27
30
  getMessage(id: string): Promise<Message>;
28
31
  sendMessage(input: SendMessageInput): Promise<Message>;
29
- /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward it
30
- * and reject a missing target with `code: 'MESSAGE_NOT_FOUND'` (or a 404 without a code); the UI never sends a
31
- * request without a target. Membership failures keep their error code, if any, so they surface as errors.
32
+ /** Acknowledge through `options.throughMessageId` (the newest rendered row). Custom adapters must forward the
33
+ * options unchanged (0.7 adds `privateStateVersion`, the version captured when the room opened; an adapter that
34
+ * drops it acknowledges the position but never clears the caller's unread marker) and reject a missing target
35
+ * with `code: 'MESSAGE_NOT_FOUND'` (or a 404 without a code); the UI never sends a request without a target.
36
+ * Membership failures keep their error code, if any, so they surface as errors.
32
37
  */
33
38
  markConversationRead(conversationId: string, options?: MarkConversationReadOptions): Promise<void>;
39
+ /** Mark the room unread for the caller only (0.7.0). Optional: `markUnread` rejects without it. */
40
+ markConversationUnread?(conversationId: string): Promise<ConversationPrivateState>;
41
+ /** Remove the caller's unread marker, only while it still has `options.ifVersion` when given (0.7.0); a mismatch or
42
+ * an unmarked room answers `cleared: false`, never an error. Optional: `clearUnread` rejects without it, and a room
43
+ * opened with a marker that renders nothing leaves the marker in place (the room store clears it through this
44
+ * member, never through an untargeted acknowledgement).
45
+ */
46
+ clearConversationUnread?(conversationId: string, options?: ClearConversationUnreadOptions): Promise<ClearUnreadResult>;
34
47
  sendTyping(input: {
35
48
  conversationId: string;
36
49
  isTyping: boolean;
@@ -38,8 +51,9 @@ interface ConvoKitUiClient {
38
51
  onConnectionEvent(handlers: RealtimeConnectionHandlers): RealtimeSubscription;
39
52
  /** Notify on inbox mutations AND on initial subscription/reconnect. No room data in the signal. */
40
53
  onInboxChanged(handler: () => void, onError?: (error: Error) => void): RealtimeSubscription;
41
- /** Message inserts/edits and read-position advances in the caller's rooms; never fires on join/rejoin. The list
42
- * store throttles these (`activityRefreshWindowMs`); room stores ignore them.
54
+ /** Message inserts/edits, read-position advances and the caller's own unread-marker changes in the caller's
55
+ * rooms; never fires on join/rejoin. The list store throttles these (`activityRefreshWindowMs`); room stores
56
+ * ignore them.
43
57
  */
44
58
  onInboxActivity?(handler: () => void, onError?: (error: Error) => void): RealtimeSubscription;
45
59
  onMessage(conversationId: string, handler: (event: MessageEvent) => void, onError?: (error: Error) => void): RealtimeSubscription;
@@ -64,7 +78,9 @@ interface ConversationPageRequest {
64
78
  type ConversationPageLoader = (request: ConversationPageRequest) => Promise<Conversation$1[]>;
65
79
  interface ConversationListState {
66
80
  conversations: Readonly<Ref<Conversation$1[]>>;
67
- /** Per-room preview, unread count and read state by conversation ID; empty on the legacy `getConversations` path. */
81
+ /** Per-room preview, unread count, read state and private unread marker (`isUnread`, `unreadMarkedAt`,
82
+ * `privateStateVersion`, 0.7.0) by conversation ID; empty on the legacy `getConversations` path.
83
+ */
68
84
  summaries: Readonly<Ref<ReadonlyMap<string, InboxSummary>>>;
69
85
  /** The bound session's user; `''` without a session, on the legacy path and after disposal. */
70
86
  currentUserId: Readonly<Ref<string>>;
@@ -106,7 +122,9 @@ interface ConversationItemSlotProps {
106
122
  index: number;
107
123
  selected: boolean;
108
124
  select: () => void;
109
- /** Present when the list carries an inbox summary for this row (0.6.0). */
125
+ /** Present when the list carries an inbox summary for this row (0.6.0); `summary.isUnread` (0.7.0) is the row's
126
+ * unread state including the viewer's private marker.
127
+ */
110
128
  summary?: InboxSummary;
111
129
  /** Present when the list knows the viewer (0.6.0); compare with `summary.latestMessage.senderId`. */
112
130
  currentUserId?: string;
@@ -1009,13 +1027,23 @@ interface ConversationListController extends ConversationListState {
1009
1027
  loadMore(): Promise<void>;
1010
1028
  setFilter(filter: ConversationFilter): Promise<void>;
1011
1029
  setQuery(query: string): Promise<void>;
1030
+ /** Mark a room unread for the viewer only (0.7.0); its summary shows the marker at once. Rejects when the adapter
1031
+ * lacks `markConversationUnread`.
1032
+ */
1033
+ markUnread(conversationId: string): Promise<void>;
1034
+ /** Remove the viewer's marker, only while it still has `options.ifVersion` when given; resolves to whether this
1035
+ * request removed it. Rejects when the adapter lacks `clearConversationUnread`.
1036
+ */
1037
+ clearUnread(conversationId: string, options?: ClearConversationUnreadOptions): Promise<boolean>;
1012
1038
  dispose(): Promise<void>;
1013
1039
  }
1014
1040
  declare function useConversationList(options: UseConversationListOptions): ConversationListController;
1015
1041
 
1016
1042
  interface ConversationListViewProps extends ConvoKitAppearanceProps {
1017
1043
  conversations: readonly Conversation$1[];
1018
- /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge. */
1044
+ /** Inbox summaries by conversation ID (0.6.0). Rows with one show a preview, time and unread badge: the count, or
1045
+ * a numberless dot when `isUnread` is set without one (0.7.0).
1046
+ */
1019
1047
  summaries?: ReadonlyMap<string, InboxSummary>;
1020
1048
  /** The viewer; a preview from them reads `You: …`. Absent → no prefix. */
1021
1049
  currentUserId?: string;
@@ -1697,7 +1725,7 @@ interface ConvoKitTheme {
1697
1725
  incomingBubble: string;
1698
1726
  outgoingBubble: string;
1699
1727
  outgoingText: string;
1700
- /** Unread badge background (0.6.0); its label uses `outgoingText`. Defaults to the primary color. */
1728
+ /** Unread badge and dot background (0.6.0); the badge label uses `outgoingText`. Defaults to the primary color. */
1701
1729
  badge: string;
1702
1730
  radius: string;
1703
1731
  avatarSize: string;
package/dist/index.js CHANGED
@@ -27,6 +27,8 @@ function createConvoKitUiClient(client) {
27
27
  getMessage: (id) => client.getMessage(id),
28
28
  sendMessage: (input) => client.sendMessage(input),
29
29
  markConversationRead: (conversationId, options) => client.markConversationRead(conversationId, options),
30
+ markConversationUnread: (conversationId) => client.markConversationUnread(conversationId),
31
+ clearConversationUnread: (conversationId, options) => client.clearConversationUnread(conversationId, options),
30
32
  sendTyping: (input) => client.sendTyping(input),
31
33
  onMessage: (conversationId, handler, onError) => client.realtime.onMessage(conversationId, {
32
34
  onEvent: handler,
@@ -217,6 +219,10 @@ function readEntry(participant) {
217
219
  function acknowledgement() {
218
220
  return { inFlight: void 0, followUp: false, suppressed: false, target: void 0, acknowledged: void 0, unacknowledgeable: /* @__PURE__ */ new Set() };
219
221
  }
222
+ function capture(conversation) {
223
+ const membership = conversation?.membership;
224
+ return { version: membership?.privateStateVersion, clearPending: membership?.unreadMarkedAt != null };
225
+ }
220
226
  function isTargetMiss(cause) {
221
227
  if (typeof cause !== "object" || cause === null) return false;
222
228
  const { code, status } = cause;
@@ -277,6 +283,7 @@ var ConversationStore = class {
277
283
  // Keep tombstones until an explicit reload/session change, including across refreshes.
278
284
  deleted = /* @__PURE__ */ new Set();
279
285
  ack = acknowledgement();
286
+ captured = capture();
280
287
  // Visible until the platform reports otherwise; unknown/prerender/no document count as visible.
281
288
  visible = true;
282
289
  sendRevision;
@@ -342,6 +349,7 @@ var ConversationStore = class {
342
349
  this.hydrationPool.queued.clear();
343
350
  this.deleted.clear();
344
351
  this.ack = acknowledgement();
352
+ this.captured = capture();
345
353
  this.sendRevision = void 0;
346
354
  this.activeSend = void 0;
347
355
  this.refreshQueued = false;
@@ -586,9 +594,13 @@ var ConversationStore = class {
586
594
  this.validatePage(page);
587
595
  this.cursor = page.at(-1);
588
596
  this.patch({ conversation, messages: this.overlay(page, revision), hasOlderMessages: page.length === this.pageSize });
597
+ this.captured = capture(conversation);
589
598
  this.mergeReads(conversation.participants.map(readEntry));
590
599
  this.prune(revision);
591
- if (this.options.markReadOnLoad ?? true) await this.acknowledge(true);
600
+ if ((this.options.markReadOnLoad ?? true) || this.ack.suppressed) {
601
+ this.ack.suppressed = false;
602
+ await this.acknowledge(true);
603
+ }
592
604
  } catch (cause) {
593
605
  this.fail(cause, generation, true);
594
606
  } finally {
@@ -645,9 +657,12 @@ var ConversationStore = class {
645
657
  const survivingIds = new Set(reconciled.map((message) => message.id));
646
658
  const known = this.state.messages.filter((message) => !isConvoKitPendingMessage(message)).map((message) => message.id).concat([...this.changes].filter(([, change]) => change.insert && change.revision <= revision).map(([id]) => id));
647
659
  for (const id of known) if (!survivingIds.has(id)) this.forget(id);
660
+ const opening = this.state.conversation === null;
648
661
  this.patch({ conversation, messages: reconciled, hasOlderMessages: hasOlder });
662
+ if (opening) this.captured = capture(conversation);
649
663
  this.mergeReads(conversation.participants.map(readEntry));
650
664
  this.prune(revision);
665
+ if (opening) void this.resumeAcknowledgement();
651
666
  } catch (cause) {
652
667
  this.fail(cause, generation, true);
653
668
  } finally {
@@ -681,15 +696,22 @@ var ConversationStore = class {
681
696
  }
682
697
  }
683
698
  };
684
- /** Acknowledge through the newest rendered row now, regardless of visibility; no request without a target. */
699
+ /** Acknowledge through the newest rendered row now, regardless of visibility; no acknowledgement without a
700
+ * target (a room opened with a marker that renders nothing clears the marker instead, once).
701
+ */
685
702
  markRead = () => this.alive() ? this.acknowledge(false) : Promise.resolve();
686
703
  /** Automatic acknowledgements wait while hidden and are re-issued (once) on becoming visible. */
687
704
  setVisible = (visible) => {
688
705
  this.visible = visible;
689
- if (!visible || !this.ack.suppressed || !this.alive()) return;
690
- this.ack.suppressed = false;
691
- void this.acknowledge(true);
706
+ if (!visible || !this.alive()) return;
707
+ void this.resumeAcknowledgement();
692
708
  };
709
+ /** Re-issue (once) the automatic acknowledgement that waited while hidden or before this open's DTO, if any. */
710
+ resumeAcknowledgement() {
711
+ if (!this.ack.suppressed) return Promise.resolve();
712
+ this.ack.suppressed = false;
713
+ return this.acknowledge(true);
714
+ }
693
715
  /** The newest non-pending rendered row by (createdAt, id), never by list index and never a raw realtime
694
716
  * row; rows the server does not know are skipped, and nothing at or before the accepted target is re-sent.
695
717
  */
@@ -704,7 +726,7 @@ var ConversationStore = class {
704
726
  /** Resolves when the request this call issued or joined settles; a follow-up is issued, not awaited. */
705
727
  acknowledge(automatic) {
706
728
  const ack = this.ack;
707
- if (automatic && !this.visible) {
729
+ if (automatic && (!this.visible || this.state.conversation === null)) {
708
730
  ack.suppressed = true;
709
731
  return Promise.resolve();
710
732
  }
@@ -717,9 +739,10 @@ var ConversationStore = class {
717
739
  issue(ack, generation) {
718
740
  ack.followUp = false;
719
741
  const target = this.ackTarget(ack);
720
- if (!target) return void 0;
721
- ack.target = target.id;
722
- ack.inFlight = this.send(ack, generation, target).finally(() => {
742
+ const request = target ? this.send(ack, generation, target) : this.clearMarker(ack, generation);
743
+ if (!request) return void 0;
744
+ ack.target = target?.id;
745
+ ack.inFlight = request.finally(() => {
723
746
  ack.inFlight = void 0;
724
747
  ack.target = void 0;
725
748
  if (!this.alive(generation) || !ack.followUp) return;
@@ -730,9 +753,31 @@ var ConversationStore = class {
730
753
  });
731
754
  return ack.inFlight;
732
755
  }
756
+ /** A room opened with the caller's unread marker that renders no non-pending, acknowledgeable row cannot clear
757
+ * it through a targeted acknowledgement, so it asks the adapter to clear the marker conditionally on the captured
758
+ * version, once per open, under the acknowledgement triggers and visibility gating. Rows rendered later clear it
759
+ * through their acknowledgements; adapters without the member leave it; `cleared: false` is not an error.
760
+ */
761
+ clearMarker(ack, generation) {
762
+ const captured = this.captured;
763
+ if (!captured.clearPending || captured.version === void 0 || typeof this.client.clearConversationUnread !== "function" || this.state.messages.some((message) => !isConvoKitPendingMessage(message) && !ack.unacknowledgeable.has(message.id))) return void 0;
764
+ captured.clearPending = false;
765
+ return this.clearUnread(captured.version, generation);
766
+ }
767
+ async clearUnread(version2, generation) {
768
+ try {
769
+ await this.client.clearConversationUnread(this.room, { ifVersion: version2 });
770
+ } catch (cause) {
771
+ if (this.alive(generation)) this.fail(cause, generation);
772
+ }
773
+ }
733
774
  async send(ack, generation, target) {
734
775
  try {
735
- await this.client.markConversationRead(this.room, { throughMessageId: target.id });
776
+ const version2 = this.captured.version;
777
+ await this.client.markConversationRead(this.room, {
778
+ throughMessageId: target.id,
779
+ ...version2 === void 0 ? {} : { privateStateVersion: version2 }
780
+ });
736
781
  if (!this.alive(generation)) return;
737
782
  if (!ack.acknowledged || compare(target, ack.acknowledged) > 0) ack.acknowledged = target;
738
783
  } catch (cause) {
@@ -1918,6 +1963,66 @@ var ConversationListStore = class {
1918
1963
  else if (!this.state.conversations.length && this.state.hasMore) await this.loadMore();
1919
1964
  };
1920
1965
  setQuery = (query) => this.setFilter({ ...this.state.filter, query });
1966
+ /** Mark a room unread for the viewer only; the row's summary takes the response (D10). Rejects when the adapter
1967
+ * lacks `markConversationUnread` or the store is not active; a request failure is reported through `error`
1968
+ * without evicting rows and rejects.
1969
+ */
1970
+ markUnread = async (conversationId) => {
1971
+ const client = this.options.client;
1972
+ if (typeof client.markConversationUnread !== "function") {
1973
+ throw new TypeError("markUnread requires a ConvoKitUiClient adapter with markConversationUnread (core SDK 0.7)");
1974
+ }
1975
+ this.assertActive();
1976
+ this.applyPrivateState(conversationId, await this.mutate(client.markConversationUnread(conversationId)));
1977
+ };
1978
+ /** Remove the viewer's marker (conditionally on `options.ifVersion`); resolves to the response's `cleared` ("this
1979
+ * request removed the marker", not "the room is read") and patches the summary on true and false alike (D10).
1980
+ * Rejects when the adapter lacks `clearConversationUnread` or the store is not active; failures are reported like
1981
+ * `markUnread`.
1982
+ */
1983
+ clearUnread = async (conversationId, options) => {
1984
+ const client = this.options.client;
1985
+ if (typeof client.clearConversationUnread !== "function") {
1986
+ throw new TypeError("clearUnread requires a ConvoKitUiClient adapter with clearConversationUnread (core SDK 0.7)");
1987
+ }
1988
+ this.assertActive();
1989
+ const result = await this.mutate(client.clearConversationUnread(conversationId, options));
1990
+ this.applyPrivateState(conversationId, result);
1991
+ return result.cleared;
1992
+ };
1993
+ /** A disposed or session-evicted store never sends a private-state mutation: on a shared client it could go out
1994
+ * under a replacement login. Rejected without touching `error` (there is no live snapshot to report into).
1995
+ */
1996
+ assertActive() {
1997
+ if (!this.alive()) throw new Error("ConversationListStore is not active");
1998
+ }
1999
+ async mutate(request) {
2000
+ try {
2001
+ return await request;
2002
+ } catch (cause) {
2003
+ if (this.alive()) this.patch({ error: cause });
2004
+ throw cause;
2005
+ }
2006
+ }
2007
+ /** Apply a mark/clear response to the row's CURRENT summary (a refresh may have swapped it) as one unit, only while
2008
+ * the store is alive and the response is not older than the stored version: a delayed response never resurrects a
2009
+ * marker a newer action removed (equal versions are an idempotent no-op). `isUnread` is recomputed from the stored
2010
+ * counts and the response marker. Other devices learn of the change through `inbox_activity`.
2011
+ */
2012
+ applyPrivateState(conversationId, state) {
2013
+ if (!this.alive()) return;
2014
+ const current = this.entries.find((entry) => entry.conversation.id === conversationId);
2015
+ if (!current || state.privateStateVersion < current.privateStateVersion) return;
2016
+ const { unreadMarkedAt, privateStateVersion } = state;
2017
+ const patched = {
2018
+ ...current,
2019
+ unreadMarkedAt,
2020
+ privateStateVersion,
2021
+ isUnread: current.unreadCount > 0 || current.unreadCountCapped || unreadMarkedAt !== null
2022
+ };
2023
+ this.entries = this.entries.map((entry) => entry === current ? patched : entry);
2024
+ this.patch({ summaries: new Map(this.entries.map((entry) => [entry.conversation.id, summaryOf(entry)])) });
2025
+ }
1921
2026
  };
1922
2027
 
1923
2028
  // src/composables/use-conversation-list.ts
@@ -1965,6 +2070,8 @@ function useConversationList(options) {
1965
2070
  loadMore: () => store.loadMore(),
1966
2071
  setFilter: (filter) => store.setFilter(filter),
1967
2072
  setQuery: (query) => store.setQuery(query),
2073
+ markUnread: (conversationId) => store.markUnread(conversationId),
2074
+ clearUnread: (conversationId, options2) => store.clearUnread(conversationId, options2),
1968
2075
  dispose
1969
2076
  };
1970
2077
  }
@@ -2041,13 +2148,16 @@ var ConversationListView = defineComponent4({
2041
2148
  return void 0;
2042
2149
  };
2043
2150
  const unreadBadge = (summary) => {
2044
- if (summary.unreadCount <= 0 && !summary.unreadCountCapped) return null;
2045
- const capped = summary.unreadCountCapped || summary.unreadCount > 99;
2046
- return h4("span", {
2047
- class: "ckui-unread-badge",
2048
- role: "img",
2049
- "aria-label": `${summary.unreadCountCapped ? "99+" : summary.unreadCount} unread`
2050
- }, [h4("span", { "aria-hidden": "true" }, capped ? "99+" : String(summary.unreadCount))]);
2151
+ if (summary.unreadCount > 0 || summary.unreadCountCapped) {
2152
+ const capped = summary.unreadCountCapped || summary.unreadCount > 99;
2153
+ return [h4("span", {
2154
+ class: "ckui-unread-badge",
2155
+ role: "img",
2156
+ "aria-label": `${summary.unreadCountCapped ? "99+" : summary.unreadCount} unread`
2157
+ }, [h4("span", { "aria-hidden": "true" }, capped ? "99+" : String(summary.unreadCount))])];
2158
+ }
2159
+ if (summary.isUnread) return [h4("span", { class: "ckui-unread-badge ckui-unread-badge--dot", role: "img", "aria-label": "Unread" })];
2160
+ return [];
2051
2161
  };
2052
2162
  const renderContent = () => {
2053
2163
  const currentAppearance = appearance();
@@ -2090,7 +2200,7 @@ var ConversationListView = defineComponent4({
2090
2200
  ...props.currentUserId === void 0 ? {} : { currentUserId: props.currentUserId }
2091
2201
  };
2092
2202
  const preview = inboxPreview(conversation, summary, props.currentUserId);
2093
- const unread = summary !== void 0 && (summary.unreadCount > 0 || summary.unreadCountCapped);
2203
+ const unread = summary !== void 0 && (summary.isUnread || summary.unreadCount > 0 || summary.unreadCountCapped);
2094
2204
  const item = slots["conversation-item"]?.(slotProps) ?? h4("button", {
2095
2205
  type: "button",
2096
2206
  "data-selected": selected || void 0,
@@ -2114,7 +2224,7 @@ var ConversationListView = defineComponent4({
2114
2224
  // summary must keep 0.5's exact markup.
2115
2225
  ...summary ? [h4("span", { class: "ckui-conversation-item__meta" }, [
2116
2226
  h4("time", { class: "ckui-conversation-item__time", datetime: summary.activityAt.toISOString() }, formatMessageTime(summary.activityAt)),
2117
- unreadBadge(summary)
2227
+ ...unreadBadge(summary)
2118
2228
  ])] : [],
2119
2229
  h4(ChevronRight, { size: 18, "aria-hidden": "true" })
2120
2230
  ]);