ai-design-system 0.1.117 → 0.1.119
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/components/composites/AccountDialog/AccountDialog.tsx +1 -1
- package/components/composites/ApprovalCard/ApprovalCard.tsx +42 -12
- package/components/composites/PromptInput/PromptInput.tsx +6 -6
- package/components/composites/StoriesBar/StoriesBar.stories.tsx +6 -25
- package/components/composites/StoriesBar/StoriesBar.tsx +26 -21
- package/components/composites/StoryPlayer/StoryPlayer.tsx +2 -2
- package/components/features/ChatPanel/ChatPanel.tsx +4 -0
- package/dist/index.cjs +56 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +30 -15
- package/dist/index.d.ts +124 -103
- package/dist/index.js +56 -39
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -55,7 +55,7 @@ export const AccountButton = React.forwardRef<HTMLButtonElement, AccountButtonPr
|
|
|
55
55
|
<div
|
|
56
56
|
className={cn(
|
|
57
57
|
"w-6 h-6 rounded-full flex items-center justify-center text-xs font-semibold select-none text-white",
|
|
58
|
-
avatarColor ? "" : "bg-emerald-
|
|
58
|
+
avatarColor ? "" : "bg-gradient-to-br from-teal-800 to-emerald-600"
|
|
59
59
|
)}
|
|
60
60
|
style={avatarColor ? { backgroundColor: avatarColor } : undefined}
|
|
61
61
|
>
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useState, useRef, useEffect } from "react";
|
|
5
5
|
import { Icon } from "@/components/primitives/Icon";
|
|
6
|
+
import { Button } from "@/components/primitives/Button";
|
|
6
7
|
import { Input } from "@/components/primitives/Input";
|
|
7
8
|
import { Textarea } from "@/components/primitives/Textarea";
|
|
8
9
|
import { Label } from "@/components/primitives/Label";
|
|
@@ -48,6 +49,12 @@ export interface ApprovalCardProps {
|
|
|
48
49
|
state?: ToolUIState;
|
|
49
50
|
approval?: ToolApproval;
|
|
50
51
|
className?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Opens the file a question is about (`args.file_path`). With it, the
|
|
54
|
+
* question shows the file's name as a link; without it, or when the question
|
|
55
|
+
* names no file, nothing is shown.
|
|
56
|
+
*/
|
|
57
|
+
onOpenFile?: (path: string) => void;
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
function formatValue(value: unknown): string {
|
|
@@ -92,6 +99,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
92
99
|
state = "approval-requested",
|
|
93
100
|
approval = {},
|
|
94
101
|
className,
|
|
102
|
+
onOpenFile,
|
|
95
103
|
}) => {
|
|
96
104
|
const [isEditing, setIsEditing] = useState(false);
|
|
97
105
|
const [prevArgs, setPrevArgs] = useState(actionRequest.args);
|
|
@@ -99,6 +107,12 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
99
107
|
const [rejectReason, setRejectReason] = useState("");
|
|
100
108
|
const [showRejectInput, setShowRejectInput] = useState(false);
|
|
101
109
|
|
|
110
|
+
// The file the question is about, when the asker named one.
|
|
111
|
+
const questionFile =
|
|
112
|
+
typeof actionRequest.args?.file_path === "string" && actionRequest.args.file_path.trim()
|
|
113
|
+
? actionRequest.args.file_path
|
|
114
|
+
: null;
|
|
115
|
+
|
|
102
116
|
const hideSkipButton = (actionRequest.args?.hide_skip_button as boolean) ?? false;
|
|
103
117
|
const submitButtonText = (actionRequest.args?.button_submit_text as string) || 'Continue';
|
|
104
118
|
const skipButtonText = (actionRequest.args?.button_skip_text as string) || 'Skip';
|
|
@@ -267,29 +281,45 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
267
281
|
<StreamingMarkdown controls={false}>
|
|
268
282
|
{currentQuestion.question}
|
|
269
283
|
</StreamingMarkdown>
|
|
284
|
+
{questionFile && onOpenFile && (
|
|
285
|
+
<Button
|
|
286
|
+
type="button"
|
|
287
|
+
variant="link"
|
|
288
|
+
onClick={() => onOpenFile(questionFile)}
|
|
289
|
+
className="mt-2 h-auto p-0 inline-flex max-w-full items-center gap-1.5 text-sm font-medium text-primary hover:underline"
|
|
290
|
+
data-testid="approval-card-file-link"
|
|
291
|
+
>
|
|
292
|
+
<Icon name="file-text" className="h-4 w-4 flex-shrink-0" />
|
|
293
|
+
<span className="truncate">{questionFile.split("/").pop()}</span>
|
|
294
|
+
</Button>
|
|
295
|
+
)}
|
|
270
296
|
</div>
|
|
271
297
|
</div>
|
|
272
298
|
{questions.length > 1 && (
|
|
273
299
|
<div className="flex items-center gap-1.5 text-xs text-muted-foreground flex-shrink-0 font-normal">
|
|
274
|
-
<
|
|
300
|
+
<Button
|
|
275
301
|
type="button"
|
|
302
|
+
variant="ghost"
|
|
303
|
+
size="icon-sm"
|
|
276
304
|
onClick={() => setCurrentQuestionIndex((prev) => Math.max(0, prev - 1))}
|
|
277
305
|
disabled={currentQuestionIndex === 0}
|
|
278
|
-
className="hover:text-foreground disabled:opacity-30
|
|
306
|
+
className="h-6 w-6 p-0 hover:text-foreground disabled:opacity-30 transition-colors"
|
|
279
307
|
>
|
|
280
308
|
<Icon name="chevron-left" size="sm" />
|
|
281
|
-
</
|
|
309
|
+
</Button>
|
|
282
310
|
<span className="font-medium">{currentQuestionIndex + 1} of {questions.length}</span>
|
|
283
|
-
<
|
|
311
|
+
<Button
|
|
284
312
|
type="button"
|
|
313
|
+
variant="ghost"
|
|
314
|
+
size="icon-sm"
|
|
285
315
|
onClick={() =>
|
|
286
316
|
setCurrentQuestionIndex((prev) => Math.min(questions.length - 1, prev + 1))
|
|
287
317
|
}
|
|
288
318
|
disabled={currentQuestionIndex === questions.length - 1}
|
|
289
|
-
className="hover:text-foreground disabled:opacity-30
|
|
319
|
+
className="h-6 w-6 p-0 hover:text-foreground disabled:opacity-30 transition-colors"
|
|
290
320
|
>
|
|
291
321
|
<Icon name="chevron-right" size="sm" />
|
|
292
|
-
</
|
|
322
|
+
</Button>
|
|
293
323
|
</div>
|
|
294
324
|
)}
|
|
295
325
|
</div>
|
|
@@ -301,8 +331,8 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
301
331
|
const isOther = index === allOptions.length - 1;
|
|
302
332
|
const isSelected = isMultiSelect
|
|
303
333
|
? (selectedAnswers[currentQuestionIndex] as string[])?.includes(
|
|
304
|
-
|
|
305
|
-
|
|
334
|
+
isOther ? otherTexts[currentQuestionIndex] || "" : option
|
|
335
|
+
)
|
|
306
336
|
: selectedOptionIndices[currentQuestionIndex] === index;
|
|
307
337
|
|
|
308
338
|
return (
|
|
@@ -500,7 +530,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
500
530
|
}}
|
|
501
531
|
disabled={isProcessing}
|
|
502
532
|
>
|
|
503
|
-
|
|
533
|
+
<Icon name="check" size="sm" className="mr-2" />
|
|
504
534
|
Save & Approve
|
|
505
535
|
</ConfirmationAction>
|
|
506
536
|
</ConfirmationActions>
|
|
@@ -576,7 +606,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
576
606
|
}}
|
|
577
607
|
disabled={isProcessing}
|
|
578
608
|
>
|
|
579
|
-
|
|
609
|
+
<Icon name="x" size="sm" className="mr-2" />
|
|
580
610
|
Confirm Rejection
|
|
581
611
|
</ConfirmationAction>
|
|
582
612
|
</>
|
|
@@ -589,7 +619,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
589
619
|
onClick={() => setShowRejectInput(true)}
|
|
590
620
|
disabled={isProcessing}
|
|
591
621
|
>
|
|
592
|
-
|
|
622
|
+
<Icon name="x" size="sm" className="mr-2" />
|
|
593
623
|
{skipButtonText}
|
|
594
624
|
</ConfirmationAction>
|
|
595
625
|
)}
|
|
@@ -610,7 +640,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
610
640
|
onClick={onApprove}
|
|
611
641
|
disabled={isProcessing}
|
|
612
642
|
>
|
|
613
|
-
|
|
643
|
+
<Icon name="check" size="sm" className="mr-2" />
|
|
614
644
|
{submitButtonText}
|
|
615
645
|
</ConfirmationAction>
|
|
616
646
|
</>
|
|
@@ -145,7 +145,7 @@ export const PromptInput = React.memo<PromptInputBlockProps>(
|
|
|
145
145
|
className={cn(
|
|
146
146
|
"[&>[data-slot=input-group]]:rounded-2xl",
|
|
147
147
|
className?.includes("border") &&
|
|
148
|
-
|
|
148
|
+
"[&>[data-slot=input-group]]:border-0 [&>[data-slot=input-group]]:bg-transparent [&>[data-slot=input-group]]:shadow-none",
|
|
149
149
|
className
|
|
150
150
|
)}
|
|
151
151
|
{...props}
|
|
@@ -155,15 +155,15 @@ export const PromptInput = React.memo<PromptInputBlockProps>(
|
|
|
155
155
|
placeholder={placeholder}
|
|
156
156
|
disabled={disabled}
|
|
157
157
|
onChange={isControlled ? handleControlledChange : undefined}
|
|
158
|
-
className="min-h-
|
|
158
|
+
className="min-h-12 py-3 pl-3 pr-2 text-sm resize-none border-0 shadow-none focus-visible:ring-0 bg-transparent flex-1 field-sizing-content"
|
|
159
159
|
/>
|
|
160
|
-
<InputGroupAddon align="inline-end" className="self-end pb-
|
|
160
|
+
<InputGroupAddon align="inline-end" className="self-end pb-3 pr-3 pt-3 shrink-0 has-[>button]:mr-0 !mr-0">
|
|
161
161
|
<PromptInputSubmit
|
|
162
162
|
disabled={disabled || (loading && !onStop)}
|
|
163
163
|
status={loading ? (onStop ? "streaming" : "submitted") : undefined}
|
|
164
164
|
onClick={isStopping ? (e: React.MouseEvent) => { e.preventDefault(); onStop?.(); } : undefined}
|
|
165
165
|
className={cn(
|
|
166
|
-
"rounded-lg
|
|
166
|
+
"rounded-lg text-white transition-colors",
|
|
167
167
|
isStopping && "bg-transparent hover:bg-accent"
|
|
168
168
|
)}
|
|
169
169
|
>
|
|
@@ -181,7 +181,7 @@ export const PromptInput = React.memo<PromptInputBlockProps>(
|
|
|
181
181
|
onError={onError}
|
|
182
182
|
className={cn(
|
|
183
183
|
className?.includes("border") &&
|
|
184
|
-
|
|
184
|
+
"[&>[data-slot=input-group]]:border-0 [&>[data-slot=input-group]]:bg-transparent [&>[data-slot=input-group]]:shadow-none",
|
|
185
185
|
className
|
|
186
186
|
)}
|
|
187
187
|
{...props}
|
|
@@ -218,7 +218,7 @@ export const PromptInput = React.memo<PromptInputBlockProps>(
|
|
|
218
218
|
status={loading ? (onStop ? "streaming" : "submitted") : undefined}
|
|
219
219
|
onClick={isStopping ? (e: React.MouseEvent) => { e.preventDefault(); onStop?.(); } : undefined}
|
|
220
220
|
className={cn(
|
|
221
|
-
"rounded-lg
|
|
221
|
+
"rounded-lg text-white transition-colors",
|
|
222
222
|
isStopping && "bg-transparent hover:bg-accent"
|
|
223
223
|
)}
|
|
224
224
|
>
|
|
@@ -21,31 +21,12 @@ export default meta;
|
|
|
21
21
|
type Story = StoryObj<typeof meta>;
|
|
22
22
|
|
|
23
23
|
const mockStories: StoryItem[] = [
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
id: "story-2",
|
|
31
|
-
title: "Waypoint",
|
|
32
|
-
status: "ready",
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
id: "story-3",
|
|
36
|
-
title: "Design Sys",
|
|
37
|
-
status: "generating",
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
id: "story-4",
|
|
41
|
-
title: "Workspace",
|
|
42
|
-
status: "ready",
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
id: "story-5",
|
|
46
|
-
title: "ZeroOps",
|
|
47
|
-
status: "draft",
|
|
48
|
-
},
|
|
24
|
+
{ id: "story-1", title: "Devin iOS", status: "ready", unread: true },
|
|
25
|
+
{ id: "story-2", title: "Waypoint", status: "ready" },
|
|
26
|
+
{ id: "story-3", title: "Design Sys", status: "working" },
|
|
27
|
+
{ id: "story-4", title: "Workspace", status: "working", unread: true },
|
|
28
|
+
{ id: "story-5", title: "Render", status: "failed", unread: true },
|
|
29
|
+
{ id: "story-6", title: "ZeroOps", status: "stopped" },
|
|
49
30
|
];
|
|
50
31
|
|
|
51
32
|
/**
|
|
@@ -13,7 +13,20 @@ export interface StoryItem {
|
|
|
13
13
|
subtitle?: string;
|
|
14
14
|
icon?: string;
|
|
15
15
|
time?: string;
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* The video's state, drawn as the story's colour:
|
|
18
|
+
* - "failed": red — the video has stopped on an error
|
|
19
|
+
* - "ready": green — the finished video is available
|
|
20
|
+
* - "stopped": grey — not ready, and nothing is running to finish it
|
|
21
|
+
* - "working": orange — in progress
|
|
22
|
+
* "generating" and "draft" are the earlier names of "working" and "stopped".
|
|
23
|
+
*/
|
|
24
|
+
status?: "failed" | "ready" | "stopped" | "working" | "generating" | "draft";
|
|
25
|
+
/**
|
|
26
|
+
* Whether the story holds a notification the user has not seen. Shown as the
|
|
27
|
+
* badge, on any status, and only then.
|
|
28
|
+
*/
|
|
29
|
+
unread?: boolean;
|
|
17
30
|
thumbnailUrl?: string;
|
|
18
31
|
avatarColor?: string;
|
|
19
32
|
avatarInitials?: string;
|
|
@@ -28,22 +41,17 @@ export interface StoriesBarProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
28
41
|
|
|
29
42
|
function getStoryStatusStyle(status?: StoryItem["status"]) {
|
|
30
43
|
switch (status) {
|
|
31
|
-
case "
|
|
32
|
-
return {
|
|
33
|
-
iconColor: "text-amber-500",
|
|
34
|
-
badgeBg: "bg-amber-500",
|
|
35
|
-
};
|
|
44
|
+
case "failed":
|
|
45
|
+
return { iconColor: "text-red-500", badgeBg: "bg-red-500" };
|
|
36
46
|
case "ready":
|
|
37
|
-
return {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
47
|
+
return { iconColor: "text-emerald-500", badgeBg: "bg-emerald-500" };
|
|
48
|
+
case "working":
|
|
49
|
+
case "generating":
|
|
50
|
+
return { iconColor: "text-amber-500", badgeBg: "bg-amber-500" };
|
|
51
|
+
case "stopped":
|
|
41
52
|
case "draft":
|
|
42
53
|
default:
|
|
43
|
-
return {
|
|
44
|
-
iconColor: "text-muted-foreground",
|
|
45
|
-
badgeBg: "bg-muted-foreground",
|
|
46
|
-
};
|
|
54
|
+
return { iconColor: "text-muted-foreground", badgeBg: "bg-muted-foreground" };
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
57
|
|
|
@@ -61,7 +69,6 @@ export const StoriesBar = React.forwardRef<HTMLDivElement, StoriesBarProps>(
|
|
|
61
69
|
<div className="flex items-center gap-2.5 px-3 py-1.5 overflow-x-auto no-scrollbar scroll-smooth">
|
|
62
70
|
{stories.map((story) => {
|
|
63
71
|
const isActive = story.id === activeStoryId;
|
|
64
|
-
const isGenerating = story.status === "generating";
|
|
65
72
|
const statusStyle = getStoryStatusStyle(story.status);
|
|
66
73
|
const iconName = story.icon || defaultIcon;
|
|
67
74
|
|
|
@@ -100,17 +107,15 @@ export const StoriesBar = React.forwardRef<HTMLDivElement, StoriesBarProps>(
|
|
|
100
107
|
)}
|
|
101
108
|
</div>
|
|
102
109
|
|
|
103
|
-
{
|
|
104
|
-
|
|
105
|
-
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-500 opacity-75" />
|
|
106
|
-
<span className="relative inline-flex rounded-full h-2 w-2 bg-amber-500" />
|
|
107
|
-
</span>
|
|
108
|
-
) : (
|
|
110
|
+
{/* The badge: an unseen notification, on any status. */}
|
|
111
|
+
{story.unread && (
|
|
109
112
|
<span
|
|
110
113
|
className={cn(
|
|
111
114
|
"absolute bottom-0 right-0 inline-flex rounded-full h-2 w-2 ring-1.5 ring-background",
|
|
112
115
|
statusStyle.badgeBg
|
|
113
116
|
)}
|
|
117
|
+
data-testid={`story-badge-${story.id}`}
|
|
118
|
+
aria-label="New notification"
|
|
114
119
|
/>
|
|
115
120
|
)}
|
|
116
121
|
</div>
|
|
@@ -592,14 +592,14 @@ export const StoryPlayer = React.forwardRef<HTMLDivElement, StoryPlayerProps>(
|
|
|
592
592
|
data-testid="btn-prev-story"
|
|
593
593
|
aria-label="Previous story"
|
|
594
594
|
onClick={handlePrev}
|
|
595
|
-
className="flex-1 h-full cursor-pointer bg-transparent hover
|
|
595
|
+
className="flex-1 h-full cursor-pointer bg-transparent hover:!bg-transparent p-0 rounded-none border-none focus-visible:ring-0 focus-visible:outline-none"
|
|
596
596
|
/>
|
|
597
597
|
<Button
|
|
598
598
|
variant="ghost"
|
|
599
599
|
data-testid="btn-next-story"
|
|
600
600
|
aria-label="Next story"
|
|
601
601
|
onClick={handleNext}
|
|
602
|
-
className="flex-1 h-full cursor-pointer bg-transparent hover
|
|
602
|
+
className="flex-1 h-full cursor-pointer bg-transparent hover:!bg-transparent p-0 rounded-none border-none focus-visible:ring-0 focus-visible:outline-none"
|
|
603
603
|
/>
|
|
604
604
|
</div>
|
|
605
605
|
</div>
|
|
@@ -95,6 +95,8 @@ export interface ChatPanelProps {
|
|
|
95
95
|
* Handler to edit HITL approval request arguments
|
|
96
96
|
*/
|
|
97
97
|
onApprovalEdit?: (editedArgs: Record<string, unknown>) => void;
|
|
98
|
+
/** Opens the file a pending question is about (its `file_path`). The card shows the link only when this is given. */
|
|
99
|
+
onOpenFile?: (path: string) => void;
|
|
98
100
|
/**
|
|
99
101
|
* Processing state for HITL approval request
|
|
100
102
|
*/
|
|
@@ -284,6 +286,7 @@ export const ChatPanel = React.memo<ChatPanelProps>(
|
|
|
284
286
|
onApprovalApprove,
|
|
285
287
|
onApprovalReject,
|
|
286
288
|
onApprovalEdit,
|
|
289
|
+
onOpenFile,
|
|
287
290
|
isApprovalProcessing = false,
|
|
288
291
|
loading = false,
|
|
289
292
|
onStop,
|
|
@@ -446,6 +449,7 @@ export const ChatPanel = React.memo<ChatPanelProps>(
|
|
|
446
449
|
isProcessing={isApprovalProcessing}
|
|
447
450
|
state={approvalCardState}
|
|
448
451
|
approval={approvalCardApproval}
|
|
452
|
+
onOpenFile={onOpenFile}
|
|
449
453
|
/>
|
|
450
454
|
</div>
|
|
451
455
|
);
|
package/dist/index.cjs
CHANGED
|
@@ -7194,10 +7194,10 @@ var PromptInput2 = React3__namespace.memo(
|
|
|
7194
7194
|
placeholder,
|
|
7195
7195
|
disabled,
|
|
7196
7196
|
onChange: isControlled ? handleControlledChange : void 0,
|
|
7197
|
-
className: "min-h-
|
|
7197
|
+
className: "min-h-12 py-3 pl-3 pr-2 text-sm resize-none border-0 shadow-none focus-visible:ring-0 bg-transparent flex-1 field-sizing-content"
|
|
7198
7198
|
}
|
|
7199
7199
|
),
|
|
7200
|
-
/* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon2, { align: "inline-end", className: "self-end pb-
|
|
7200
|
+
/* @__PURE__ */ jsxRuntime.jsx(InputGroupAddon2, { align: "inline-end", className: "self-end pb-3 pr-3 pt-3 shrink-0 has-[>button]:mr-0 !mr-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7201
7201
|
PromptInputSubmit,
|
|
7202
7202
|
{
|
|
7203
7203
|
disabled: disabled || loading && !onStop,
|
|
@@ -7207,7 +7207,7 @@ var PromptInput2 = React3__namespace.memo(
|
|
|
7207
7207
|
onStop == null ? void 0 : onStop();
|
|
7208
7208
|
} : void 0,
|
|
7209
7209
|
className: cn(
|
|
7210
|
-
"rounded-lg
|
|
7210
|
+
"rounded-lg text-white transition-colors",
|
|
7211
7211
|
isStopping && "bg-transparent hover:bg-accent"
|
|
7212
7212
|
),
|
|
7213
7213
|
children: loading ? void 0 : /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "corner-down-left", size: "sm" })
|
|
@@ -7269,7 +7269,7 @@ var PromptInput2 = React3__namespace.memo(
|
|
|
7269
7269
|
onStop == null ? void 0 : onStop();
|
|
7270
7270
|
} : void 0,
|
|
7271
7271
|
className: cn(
|
|
7272
|
-
"rounded-lg
|
|
7272
|
+
"rounded-lg text-white transition-colors",
|
|
7273
7273
|
isStopping && "bg-transparent hover:bg-accent"
|
|
7274
7274
|
),
|
|
7275
7275
|
children: loading ? void 0 : /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "corner-down-left", size: "sm" })
|
|
@@ -7665,17 +7665,19 @@ var ApprovalCard = React3__namespace.memo(
|
|
|
7665
7665
|
isProcessing = false,
|
|
7666
7666
|
state = "approval-requested",
|
|
7667
7667
|
approval = {},
|
|
7668
|
-
className
|
|
7668
|
+
className,
|
|
7669
|
+
onOpenFile
|
|
7669
7670
|
}) => {
|
|
7670
|
-
var _a, _b, _c, _d, _e, _f;
|
|
7671
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
7671
7672
|
const [isEditing, setIsEditing] = React3.useState(false);
|
|
7672
7673
|
const [prevArgs, setPrevArgs] = React3.useState(actionRequest.args);
|
|
7673
7674
|
const [editedArgs, setEditedArgs] = React3.useState(() => actionRequest.args);
|
|
7674
7675
|
const [rejectReason, setRejectReason] = React3.useState("");
|
|
7675
7676
|
const [showRejectInput, setShowRejectInput] = React3.useState(false);
|
|
7676
|
-
const
|
|
7677
|
-
const
|
|
7678
|
-
const
|
|
7677
|
+
const questionFile = typeof ((_a = actionRequest.args) == null ? void 0 : _a.file_path) === "string" && actionRequest.args.file_path.trim() ? actionRequest.args.file_path : null;
|
|
7678
|
+
const hideSkipButton = (_c = (_b = actionRequest.args) == null ? void 0 : _b.hide_skip_button) != null ? _c : false;
|
|
7679
|
+
const submitButtonText = ((_d = actionRequest.args) == null ? void 0 : _d.button_submit_text) || "Continue";
|
|
7680
|
+
const skipButtonText = ((_e = actionRequest.args) == null ? void 0 : _e.button_skip_text) || "Skip";
|
|
7679
7681
|
const [currentQuestionIndex, setCurrentQuestionIndex] = React3.useState(0);
|
|
7680
7682
|
const [selectedAnswers, setSelectedAnswers] = React3.useState({});
|
|
7681
7683
|
const [otherTexts, setOtherTexts] = React3.useState({});
|
|
@@ -7685,7 +7687,7 @@ var ApprovalCard = React3__namespace.memo(
|
|
|
7685
7687
|
setPrevArgs(actionRequest.args);
|
|
7686
7688
|
setEditedArgs(actionRequest.args);
|
|
7687
7689
|
}
|
|
7688
|
-
const allowed = (
|
|
7690
|
+
const allowed = (_f = reviewConfig == null ? void 0 : reviewConfig.allowedDecisions) != null ? _f : ["approve", "reject"];
|
|
7689
7691
|
const canEdit = allowed.includes("edit");
|
|
7690
7692
|
const canReject = allowed.includes("reject");
|
|
7691
7693
|
const isQuestionAction = actionRequest.name === "ask_question" || actionRequest.args && (typeof actionRequest.args.question === "string" || Array.isArray(actionRequest.args.questions) && actionRequest.args.questions.length > 0);
|
|
@@ -7744,7 +7746,7 @@ var ApprovalCard = React3__namespace.memo(
|
|
|
7744
7746
|
return false;
|
|
7745
7747
|
};
|
|
7746
7748
|
const allQuestionsAnswered = questions.length > 0 && questions.every((_, idx) => isQuestionAnswered(idx));
|
|
7747
|
-
const isApprovalType = ((
|
|
7749
|
+
const isApprovalType = ((_g = actionRequest.args) == null ? void 0 : _g.type) === "approval";
|
|
7748
7750
|
const isLastQuestion = currentQuestionIndex === questions.length - 1;
|
|
7749
7751
|
const handleContinue = () => {
|
|
7750
7752
|
if (!isApprovalType && !allQuestionsAnswered) {
|
|
@@ -7799,16 +7801,34 @@ var ApprovalCard = React3__namespace.memo(
|
|
|
7799
7801
|
/* @__PURE__ */ jsxRuntime.jsx(ConfirmationTitle, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-4", children: [
|
|
7800
7802
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 min-w-0 flex-1", children: [
|
|
7801
7803
|
/* @__PURE__ */ jsxRuntime.jsx(QuestionIcon, { className: "h-5 w-5 text-muted-foreground mt-0.5 flex-shrink-0" }),
|
|
7802
|
-
/* @__PURE__ */ jsxRuntime.
|
|
7804
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 max-h-60 overflow-y-auto pr-1 text-sm leading-relaxed text-foreground [&>*:first-child]:mt-0 [&>*:last-child]:mb-0", children: [
|
|
7805
|
+
/* @__PURE__ */ jsxRuntime.jsx(StreamingMarkdown, { controls: false, children: currentQuestion.question }),
|
|
7806
|
+
questionFile && onOpenFile && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7807
|
+
Button2,
|
|
7808
|
+
{
|
|
7809
|
+
type: "button",
|
|
7810
|
+
variant: "link",
|
|
7811
|
+
onClick: () => onOpenFile(questionFile),
|
|
7812
|
+
className: "mt-2 h-auto p-0 inline-flex max-w-full items-center gap-1.5 text-sm font-medium text-primary hover:underline",
|
|
7813
|
+
"data-testid": "approval-card-file-link",
|
|
7814
|
+
children: [
|
|
7815
|
+
/* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "file-text", className: "h-4 w-4 flex-shrink-0" }),
|
|
7816
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: questionFile.split("/").pop() })
|
|
7817
|
+
]
|
|
7818
|
+
}
|
|
7819
|
+
)
|
|
7820
|
+
] })
|
|
7803
7821
|
] }),
|
|
7804
7822
|
questions.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground flex-shrink-0 font-normal", children: [
|
|
7805
7823
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7806
|
-
|
|
7824
|
+
Button2,
|
|
7807
7825
|
{
|
|
7808
7826
|
type: "button",
|
|
7827
|
+
variant: "ghost",
|
|
7828
|
+
size: "icon-sm",
|
|
7809
7829
|
onClick: () => setCurrentQuestionIndex((prev) => Math.max(0, prev - 1)),
|
|
7810
7830
|
disabled: currentQuestionIndex === 0,
|
|
7811
|
-
className: "hover:text-foreground disabled:opacity-30
|
|
7831
|
+
className: "h-6 w-6 p-0 hover:text-foreground disabled:opacity-30 transition-colors",
|
|
7812
7832
|
children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron-left", size: "sm" })
|
|
7813
7833
|
}
|
|
7814
7834
|
),
|
|
@@ -7818,12 +7838,14 @@ var ApprovalCard = React3__namespace.memo(
|
|
|
7818
7838
|
questions.length
|
|
7819
7839
|
] }),
|
|
7820
7840
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7821
|
-
|
|
7841
|
+
Button2,
|
|
7822
7842
|
{
|
|
7823
7843
|
type: "button",
|
|
7844
|
+
variant: "ghost",
|
|
7845
|
+
size: "icon-sm",
|
|
7824
7846
|
onClick: () => setCurrentQuestionIndex((prev) => Math.min(questions.length - 1, prev + 1)),
|
|
7825
7847
|
disabled: currentQuestionIndex === questions.length - 1,
|
|
7826
|
-
className: "hover:text-foreground disabled:opacity-30
|
|
7848
|
+
className: "h-6 w-6 p-0 hover:text-foreground disabled:opacity-30 transition-colors",
|
|
7827
7849
|
children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron-right", size: "sm" })
|
|
7828
7850
|
}
|
|
7829
7851
|
)
|
|
@@ -8416,6 +8438,7 @@ var ChatPanel = React3__namespace.memo(
|
|
|
8416
8438
|
onApprovalApprove,
|
|
8417
8439
|
onApprovalReject,
|
|
8418
8440
|
onApprovalEdit,
|
|
8441
|
+
onOpenFile,
|
|
8419
8442
|
isApprovalProcessing = false,
|
|
8420
8443
|
loading = false,
|
|
8421
8444
|
onStop,
|
|
@@ -8548,7 +8571,8 @@ var ChatPanel = React3__namespace.memo(
|
|
|
8548
8571
|
onEdit: handleApprovalEdit,
|
|
8549
8572
|
isProcessing: isApprovalProcessing,
|
|
8550
8573
|
state: approvalCardState,
|
|
8551
|
-
approval: approvalCardApproval
|
|
8574
|
+
approval: approvalCardApproval,
|
|
8575
|
+
onOpenFile
|
|
8552
8576
|
}
|
|
8553
8577
|
) });
|
|
8554
8578
|
} else if (fileChanges.length > 0) {
|
|
@@ -14959,22 +14983,17 @@ var WorkspaceEmptyState = React3__namespace.memo(
|
|
|
14959
14983
|
WorkspaceEmptyState.displayName = "WorkspaceEmptyState";
|
|
14960
14984
|
function getStoryStatusStyle(status) {
|
|
14961
14985
|
switch (status) {
|
|
14962
|
-
case "
|
|
14963
|
-
return {
|
|
14964
|
-
iconColor: "text-amber-500",
|
|
14965
|
-
badgeBg: "bg-amber-500"
|
|
14966
|
-
};
|
|
14986
|
+
case "failed":
|
|
14987
|
+
return { iconColor: "text-red-500", badgeBg: "bg-red-500" };
|
|
14967
14988
|
case "ready":
|
|
14968
|
-
return {
|
|
14969
|
-
|
|
14970
|
-
|
|
14971
|
-
};
|
|
14989
|
+
return { iconColor: "text-emerald-500", badgeBg: "bg-emerald-500" };
|
|
14990
|
+
case "working":
|
|
14991
|
+
case "generating":
|
|
14992
|
+
return { iconColor: "text-amber-500", badgeBg: "bg-amber-500" };
|
|
14993
|
+
case "stopped":
|
|
14972
14994
|
case "draft":
|
|
14973
14995
|
default:
|
|
14974
|
-
return {
|
|
14975
|
-
iconColor: "text-muted-foreground",
|
|
14976
|
-
badgeBg: "bg-muted-foreground"
|
|
14977
|
-
};
|
|
14996
|
+
return { iconColor: "text-muted-foreground", badgeBg: "bg-muted-foreground" };
|
|
14978
14997
|
}
|
|
14979
14998
|
}
|
|
14980
14999
|
var StoriesBar = React3__namespace.forwardRef(
|
|
@@ -14990,7 +15009,6 @@ var StoriesBar = React3__namespace.forwardRef(
|
|
|
14990
15009
|
}, props), {
|
|
14991
15010
|
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2.5 px-3 py-1.5 overflow-x-auto no-scrollbar scroll-smooth", children: stories.map((story) => {
|
|
14992
15011
|
const isActive = story.id === activeStoryId;
|
|
14993
|
-
const isGenerating = story.status === "generating";
|
|
14994
15012
|
const statusStyle = getStoryStatusStyle(story.status);
|
|
14995
15013
|
const iconName = story.icon || defaultIcon;
|
|
14996
15014
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -15029,16 +15047,15 @@ var StoriesBar = React3__namespace.forwardRef(
|
|
|
15029
15047
|
)
|
|
15030
15048
|
}
|
|
15031
15049
|
),
|
|
15032
|
-
|
|
15033
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-500 opacity-75" }),
|
|
15034
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-amber-500" })
|
|
15035
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
15050
|
+
story.unread && /* @__PURE__ */ jsxRuntime.jsx(
|
|
15036
15051
|
"span",
|
|
15037
15052
|
{
|
|
15038
15053
|
className: cn(
|
|
15039
15054
|
"absolute bottom-0 right-0 inline-flex rounded-full h-2 w-2 ring-1.5 ring-background",
|
|
15040
15055
|
statusStyle.badgeBg
|
|
15041
|
-
)
|
|
15056
|
+
),
|
|
15057
|
+
"data-testid": `story-badge-${story.id}`,
|
|
15058
|
+
"aria-label": "New notification"
|
|
15042
15059
|
}
|
|
15043
15060
|
)
|
|
15044
15061
|
] }),
|
|
@@ -15557,7 +15574,7 @@ var StoryPlayer = React3__namespace.forwardRef(
|
|
|
15557
15574
|
"data-testid": "btn-prev-story",
|
|
15558
15575
|
"aria-label": "Previous story",
|
|
15559
15576
|
onClick: handlePrev,
|
|
15560
|
-
className: "flex-1 h-full cursor-pointer bg-transparent hover
|
|
15577
|
+
className: "flex-1 h-full cursor-pointer bg-transparent hover:!bg-transparent p-0 rounded-none border-none focus-visible:ring-0 focus-visible:outline-none"
|
|
15561
15578
|
}
|
|
15562
15579
|
),
|
|
15563
15580
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -15567,7 +15584,7 @@ var StoryPlayer = React3__namespace.forwardRef(
|
|
|
15567
15584
|
"data-testid": "btn-next-story",
|
|
15568
15585
|
"aria-label": "Next story",
|
|
15569
15586
|
onClick: handleNext,
|
|
15570
|
-
className: "flex-1 h-full cursor-pointer bg-transparent hover
|
|
15587
|
+
className: "flex-1 h-full cursor-pointer bg-transparent hover:!bg-transparent p-0 rounded-none border-none focus-visible:ring-0 focus-visible:outline-none"
|
|
15571
15588
|
}
|
|
15572
15589
|
)
|
|
15573
15590
|
] })
|
|
@@ -15629,7 +15646,7 @@ var AccountButton = React3__namespace.forwardRef(
|
|
|
15629
15646
|
{
|
|
15630
15647
|
className: cn(
|
|
15631
15648
|
"w-6 h-6 rounded-full flex items-center justify-center text-xs font-semibold select-none text-white",
|
|
15632
|
-
avatarColor ? "" : "bg-emerald-
|
|
15649
|
+
avatarColor ? "" : "bg-gradient-to-br from-teal-800 to-emerald-600"
|
|
15633
15650
|
),
|
|
15634
15651
|
style: avatarColor ? { backgroundColor: avatarColor } : void 0,
|
|
15635
15652
|
children: initial
|