@jxtools/promptline 1.2.0 → 1.3.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jxtools/promptline",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "type": "module",
5
5
  "license": "ISC",
6
6
  "bin": {
@@ -52,7 +52,7 @@ export function withComputedStatus(session: SessionQueue): SessionQueue & { stat
52
52
  export function isSessionVisible(session: SessionQueue, now: number = Date.now()): boolean {
53
53
  if (hasPendingWork(session)) return true;
54
54
  if (session.closedAt != null) return false;
55
- // Open session visible until abandoned (24h from start)
55
+ if (!session.sessionName) return false;
56
56
  const msSinceStart = now - new Date(session.startedAt).getTime();
57
57
  return msSinceStart <= SESSION_ABANDONED_TIMEOUT_MS;
58
58
  }
@@ -1,6 +1,7 @@
1
1
  import { useState, useRef, useEffect } from 'react';
2
2
  import type { Prompt } from '../types/queue';
3
3
  import { api } from '../api/client';
4
+ import { TrashIcon } from './TrashIcon';
4
5
 
5
6
  interface PromptCardProps {
6
7
  prompt: Prompt;
@@ -206,19 +207,19 @@ export function PromptCard({
206
207
  {styles.label}
207
208
  </span>
208
209
 
209
- {/* Action buttons */}
210
+ {/* Delete button */}
210
211
  {!editing && !isRunning && (
211
212
  <button
212
213
  type="button"
213
214
  onClick={handleDelete}
214
215
  className={[
215
- 'text-xs px-1.5 py-0.5 rounded text-[var(--color-muted)] cursor-pointer opacity-0 group-hover:opacity-100',
216
- 'hover:text-red-400 hover:bg-red-400/10',
216
+ 'p-1 rounded cursor-pointer',
217
+ 'text-[var(--color-muted)]/40 hover:text-red-400 hover:bg-red-400/10',
217
218
  'transition-all duration-100 focus:outline-none',
218
219
  ].join(' ')}
219
220
  aria-label="Delete prompt"
220
221
  >
221
-
222
+ <TrashIcon />
222
223
  </button>
223
224
  )}
224
225
  </div>
@@ -1,6 +1,7 @@
1
1
  import { useState, useRef } from 'react';
2
2
  import { api } from '../api/client';
3
3
  import type { SessionWithStatus, SessionStatus, Prompt } from '../types/queue';
4
+ import { TrashIcon } from './TrashIcon';
4
5
  import { PromptCard } from './PromptCard';
5
6
  import { AddPromptForm } from './AddPromptForm';
6
7
 
@@ -34,6 +35,16 @@ export function SessionSection({ session, project, onMutate, defaultExpanded = t
34
35
  const [draggingId, setDraggingId] = useState<string | null>(null);
35
36
  const dragSourceRef = useRef<string | null>(null);
36
37
 
38
+ async function handleDeleteSession(e: React.MouseEvent) {
39
+ e.stopPropagation();
40
+ try {
41
+ await api.deleteSession(project, session.sessionId);
42
+ onMutate();
43
+ } catch {
44
+ // Silent fail
45
+ }
46
+ }
47
+
37
48
  const activePrompts = session.prompts.filter(p => p.status !== 'completed');
38
49
  const completedPrompts = session.prompts.filter(p => p.status === 'completed').reverse();
39
50
  const pendingCount = session.prompts.filter(p => p.status === 'pending').length;
@@ -107,11 +118,12 @@ export function SessionSection({ session, project, onMutate, defaultExpanded = t
107
118
  return (
108
119
  <div className="border border-[var(--color-border)] rounded-lg overflow-hidden bg-white/[0.02]">
109
120
  {/* Session header */}
121
+ <div className="relative">
110
122
  <button
111
123
  type="button"
112
124
  onClick={() => setExpanded(v => !v)}
113
125
  className={[
114
- 'w-full flex items-center gap-3 px-4 py-3 text-left cursor-pointer',
126
+ 'w-full flex items-center gap-3 pl-4 pr-10 py-3 text-left cursor-pointer',
115
127
  'hover:bg-white/5 transition-colors duration-150 focus:outline-none',
116
128
  ].join(' ')}
117
129
  aria-expanded={expanded}
@@ -136,6 +148,19 @@ export function SessionSection({ session, project, onMutate, defaultExpanded = t
136
148
 
137
149
  </span>
138
150
  </button>
151
+ <button
152
+ type="button"
153
+ onClick={handleDeleteSession}
154
+ className={[
155
+ 'absolute right-2 top-1/2 -translate-y-1/2 p-1.5 rounded cursor-pointer',
156
+ 'text-[var(--color-muted)]/40 hover:text-red-400 hover:bg-red-400/10',
157
+ 'transition-all duration-100 focus:outline-none',
158
+ ].join(' ')}
159
+ aria-label="Delete session"
160
+ >
161
+ <TrashIcon />
162
+ </button>
163
+ </div>
139
164
 
140
165
  {/* Session content */}
141
166
  {expanded && (
@@ -0,0 +1,8 @@
1
+ export function TrashIcon() {
2
+ return (
3
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
4
+ <polyline points="3 6 5 6 21 6" />
5
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
6
+ </svg>
7
+ );
8
+ }