@luckydraw/cumulus 0.27.16 → 0.27.17

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.
@@ -720,16 +720,32 @@
720
720
  '.cumulus-panel-action-btn:hover { color: #ddd; border-color: #555; }',
721
721
  '.cumulus-panel-action-btn.active { color: #e0e0e0; border-color: #0066cc; background: rgba(0,102,204,0.12); }',
722
722
 
723
- /* ── Sidebar thread delete button ── */
724
- '.cumulus-thread-item { position: relative; }',
725
- '.cumulus-thread-delete-btn {',
726
- ' display: none; position: absolute; right: 6px; top: 50%; transform: translateY(-50%);',
727
- ' background: none; border: none; color: #666;',
728
- ' cursor: pointer; font-size: 14px; padding: 2px 5px; line-height: 1;',
729
- ' border-radius: 3px; z-index: 1;',
723
+ /* ── Context menu (right-click on thread) ── */
724
+ '.cumulus-context-menu {',
725
+ ' position: fixed; z-index: 300; background: #2a2a2a; border: 1px solid #444;',
726
+ ' border-radius: 6px; padding: 4px 0; min-width: 140px;',
727
+ ' box-shadow: 0 4px 12px rgba(0,0,0,0.5); font-size: 13px;',
728
+ '}',
729
+ '.cumulus-context-menu-item {',
730
+ ' padding: 6px 14px; color: #ccc; cursor: pointer; display: block;',
731
+ ' width: 100%; border: none; background: none; text-align: left;',
732
+ ' font-family: inherit; font-size: inherit;',
733
+ '}',
734
+ '.cumulus-context-menu-item:hover { background: #3a3a3a; color: #fff; }',
735
+ '.cumulus-context-menu-item.danger { color: #ef4444; }',
736
+ '.cumulus-context-menu-item.danger:hover { background: rgba(239,68,68,0.15); color: #ff6b6b; }',
737
+
738
+ /* ── Unread dot (glowing) ── */
739
+ '.cumulus-thread-unread {',
740
+ ' width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;',
741
+ ' background: #3b82f6;',
742
+ ' box-shadow: 0 0 4px #3b82f6, 0 0 8px rgba(59,130,246,0.4);',
743
+ ' animation: cumulus-unread-pulse 2s ease-in-out infinite;',
744
+ '}',
745
+ '@keyframes cumulus-unread-pulse {',
746
+ ' 0%, 100% { box-shadow: 0 0 4px #3b82f6, 0 0 8px rgba(59,130,246,0.4); }',
747
+ ' 50% { box-shadow: 0 0 6px #3b82f6, 0 0 14px rgba(59,130,246,0.6); }',
730
748
  '}',
731
- '.cumulus-thread-item:hover .cumulus-thread-delete-btn { display: block; }',
732
- '.cumulus-thread-delete-btn:hover { color: #ef4444; background: rgba(239,68,68,0.1); }',
733
749
 
734
750
  /* ── Message checkbox (selection mode) ── */
735
751
  '.cumulus-msg-checkbox {',
@@ -2201,6 +2217,9 @@
2201
2217
  // Thread list from server: [{ name, messageCount, lastActivity }]
2202
2218
  var allThreads = [];
2203
2219
 
2220
+ // Unread threads: threadName -> true
2221
+ var unreadThreads = {};
2222
+
2204
2223
  // Currently visible panel names (ordered, max 3)
2205
2224
  var visibleThreads = [];
2206
2225
 
@@ -2500,6 +2519,13 @@
2500
2519
  item.appendChild(folderEl);
2501
2520
  }
2502
2521
 
2522
+ // Unread indicator
2523
+ if (unreadThreads[name]) {
2524
+ var unreadDot = document.createElement('span');
2525
+ unreadDot.className = 'cumulus-thread-unread';
2526
+ item.appendChild(unreadDot);
2527
+ }
2528
+
2503
2529
  if (messageCount !== undefined && messageCount !== null) {
2504
2530
  var countEl = document.createElement('span');
2505
2531
  countEl.className = 'cumulus-thread-count';
@@ -2507,17 +2533,12 @@
2507
2533
  item.appendChild(countEl);
2508
2534
  }
2509
2535
 
2510
- // Delete button (revealed on hover via CSS)
2511
- var deleteBtn = document.createElement('button');
2512
- deleteBtn.className = 'cumulus-thread-delete-btn';
2513
- deleteBtn.setAttribute('title', 'Delete thread');
2514
- deleteBtn.setAttribute('data-testid', 'webchat-thread-delete');
2515
- deleteBtn.textContent = '\u2715';
2516
- deleteBtn.addEventListener('click', function (e) {
2536
+ // Right-click context menu
2537
+ item.addEventListener('contextmenu', function (e) {
2538
+ e.preventDefault();
2517
2539
  e.stopPropagation();
2518
- showThreadDeleteConfirm(name, item);
2540
+ showThreadContextMenu(name, e.clientX, e.clientY);
2519
2541
  });
2520
- item.appendChild(deleteBtn);
2521
2542
 
2522
2543
  item.addEventListener('click', function (e) {
2523
2544
  var multiSelect = e.metaKey || e.ctrlKey;
@@ -2531,8 +2552,48 @@
2531
2552
  return item;
2532
2553
  }
2533
2554
 
2555
+ // ── Thread context menu (right-click) ──
2556
+ function dismissContextMenu() {
2557
+ var existing = document.querySelector('.cumulus-context-menu');
2558
+ if (existing) existing.remove();
2559
+ document.removeEventListener('click', dismissContextMenu);
2560
+ document.removeEventListener('contextmenu', dismissContextMenu);
2561
+ }
2562
+
2563
+ function showThreadContextMenu(threadName, x, y) {
2564
+ dismissContextMenu();
2565
+
2566
+ var menu = document.createElement('div');
2567
+ menu.className = 'cumulus-context-menu';
2568
+ menu.style.left = x + 'px';
2569
+ menu.style.top = y + 'px';
2570
+
2571
+ var deleteItem = document.createElement('button');
2572
+ deleteItem.className = 'cumulus-context-menu-item danger';
2573
+ deleteItem.textContent = 'Delete thread';
2574
+ deleteItem.setAttribute('data-testid', 'webchat-thread-delete');
2575
+ deleteItem.addEventListener('click', function () {
2576
+ dismissContextMenu();
2577
+ showThreadDeleteConfirm(threadName);
2578
+ });
2579
+ menu.appendChild(deleteItem);
2580
+
2581
+ document.body.appendChild(menu);
2582
+
2583
+ // Clamp to viewport
2584
+ var rect = menu.getBoundingClientRect();
2585
+ if (rect.right > window.innerWidth) menu.style.left = (window.innerWidth - rect.width - 4) + 'px';
2586
+ if (rect.bottom > window.innerHeight) menu.style.top = (window.innerHeight - rect.height - 4) + 'px';
2587
+
2588
+ // Dismiss on next click or right-click anywhere
2589
+ setTimeout(function () {
2590
+ document.addEventListener('click', dismissContextMenu);
2591
+ document.addEventListener('contextmenu', dismissContextMenu);
2592
+ }, 0);
2593
+ }
2594
+
2534
2595
  // ── Thread delete confirmation ──
2535
- function showThreadDeleteConfirm(threadName, anchorEl) {
2596
+ function showThreadDeleteConfirm(threadName) {
2536
2597
  // Remove any existing confirm dialogs
2537
2598
  var existing = document.querySelector('.cumulus-confirm-dialog[data-context="thread-delete"]');
2538
2599
  if (existing) {
@@ -2602,6 +2663,7 @@
2602
2663
 
2603
2664
  // ── Panel management ──
2604
2665
  function soloThread(name) {
2666
+ delete unreadThreads[name];
2605
2667
  visibleThreads = [name];
2606
2668
  renderSidebar();
2607
2669
  renderContentArea();
@@ -2610,6 +2672,7 @@
2610
2672
  }
2611
2673
 
2612
2674
  function togglePanelThread(name) {
2675
+ delete unreadThreads[name];
2613
2676
  // On mobile, always solo (no side-by-side)
2614
2677
  if (isMobile()) {
2615
2678
  soloThread(name);
@@ -3828,6 +3891,10 @@
3828
3891
  break;
3829
3892
  }
3830
3893
  }
3894
+ // Mark unread if thread is not currently visible
3895
+ if (visibleThreads.indexOf(threadName) === -1) {
3896
+ unreadThreads[threadName] = true;
3897
+ }
3831
3898
  // Re-render sidebar to reflect new sort order / move thread up
3832
3899
  renderSidebar();
3833
3900
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luckydraw/cumulus",
3
- "version": "0.27.16",
3
+ "version": "0.27.17",
4
4
  "description": "RLM-based CLI chat wrapper for Claude with external history context management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",