ai-design-system 0.1.46 → 0.1.48
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/ai-elements/code-block.tsx +2 -4
- package/components/ai-elements/conversation.tsx +1 -1
- package/components/ai-elements/prompt-input.tsx +4 -6
- package/components/blocks/AIConversation/AIConversation.tsx +9 -4
- package/components/blocks/DataTable/DataTable.tsx +2 -2
- package/components/blocks/InboxPanel/InboxPanel.tsx +12 -1
- package/components/blocks/SectionLayout/SectionLayout.tsx +2 -2
- package/components/blocks/index.ts +0 -11
- package/components/composites/AppHeader/AppHeader.tsx +5 -1
- package/components/composites/AppHeader/interfaces.ts +1 -1
- package/components/composites/ApprovalCard/ApprovalCard.tsx +81 -53
- package/components/composites/CommentBox/CommentBox.tsx +3 -3
- package/components/{blocks → composites}/DashboardHeader/DashboardHeader.tsx +2 -0
- package/components/composites/DataTable/DragHandleCell.tsx +2 -2
- package/components/composites/DataTable/EnhancedDataTable.behaviors.stories.tsx +1 -1
- package/components/composites/DataTable/EnhancedDataTable.tsx +20 -9
- package/components/composites/DataTable/InlineEditCell.tsx +0 -2
- package/components/composites/DataTable/RowDetailDrawer.tsx +2 -3
- package/components/composites/DataTable/StatusCell.tsx +4 -4
- package/components/composites/DataTable/index.ts +0 -2
- package/components/composites/DocumentTabBar/DocumentTabBar.tsx +5 -4
- package/components/composites/EmptyState/EmptyState.stories.tsx +26 -0
- package/components/composites/EmptyState/EmptyState.tsx +38 -0
- package/components/composites/EmptyState/index.ts +1 -0
- package/components/composites/OrchestratorMessage/OrchestratorMessage.tsx +2 -1
- package/components/composites/ProjectSwitcher/ProjectSwitcher.tsx +105 -0
- package/components/composites/ProjectSwitcher/index.ts +1 -0
- package/components/{blocks → composites}/PromptInput/PromptInput.stories.tsx +1 -1
- package/components/{blocks → composites}/PromptInput/PromptInput.tsx +3 -1
- package/components/composites/SpecialistMessage/SpecialistMessage.tsx +14 -6
- package/components/composites/StateNode/StateNode.tsx +5 -5
- package/components/composites/TransitionNode/TransitionNode.tsx +4 -4
- package/components/composites/TriggerNode/TriggerNode.tsx +2 -2
- package/components/composites/WorkflowToolbar/WorkflowToolbar.tsx +3 -4
- package/components/composites/index.ts +24 -0
- package/components/features/DashboardFeature/DashboardFeature.behaviors.stories.tsx +4 -0
- package/components/features/DashboardFeature/DashboardFeature.mocks.ts +1 -1
- package/components/features/DashboardFeature/DashboardFeature.stories.tsx +21 -0
- package/components/features/DashboardFeature/DashboardFeature.tsx +95 -24
- package/components/features/DashboardFeature/useDashboardFeature.d.ts +21 -0
- package/components/features/DashboardFeature/useDashboardFeature.mock.ts +39 -30
- package/components/features/PageLayout/PageLayout.stories.tsx +33 -10
- package/components/features/PageLayout/PageLayout.tsx +1 -1
- package/components/features/PageLayout/useDashboardIntegration.mock.ts +108 -0
- package/components/features/RefinementPanel/RefinementPanel.tsx +31 -26
- package/components/features/RefinementPanel/useRefinementPanel.d.ts +13 -8
- package/components/features/RefinementPanel/useRefinementPanel.mock.ts +6 -0
- package/components/features/WorkflowBuilder/WorkflowBuilder.tsx +3 -6
- package/components/index.ts +2 -1
- package/components/primitives/Icon/Icon.tsx +48 -1
- package/components/ui/dropdown-menu.tsx +2 -2
- package/dist/index.cjs +918 -358
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +28 -0
- package/dist/index.d.ts +128 -8
- package/dist/index.js +919 -360
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- /package/components/{blocks → composites}/DashboardChart/DashboardChart.tsx +0 -0
- /package/components/{blocks → composites}/DashboardChart/index.ts +0 -0
- /package/components/{blocks → composites}/DashboardHeader/index.ts +0 -0
- /package/components/{blocks → composites}/LayoutProvider/LayoutProvider.tsx +0 -0
- /package/components/{blocks → composites}/LayoutProvider/index.ts +0 -0
- /package/components/{blocks → composites}/PromptInput/index.ts +0 -0
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { Button } from "@/components/ui/button";
|
|
4
4
|
import { cn } from "@/lib/utils";
|
|
5
5
|
import type { Element } from "hast";
|
|
6
|
-
import { CheckIcon
|
|
6
|
+
import { CheckIcon } from "lucide-react";
|
|
7
7
|
import {
|
|
8
8
|
type ComponentProps,
|
|
9
9
|
createContext,
|
|
@@ -163,8 +163,6 @@ export const CodeBlockCopyButton = ({
|
|
|
163
163
|
}
|
|
164
164
|
};
|
|
165
165
|
|
|
166
|
-
const Icon = isCopied ? CheckIcon : CopyIcon;
|
|
167
|
-
|
|
168
166
|
return (
|
|
169
167
|
<Button
|
|
170
168
|
className={cn("shrink-0", className)}
|
|
@@ -173,7 +171,7 @@ export const CodeBlockCopyButton = ({
|
|
|
173
171
|
variant="ghost"
|
|
174
172
|
{...props}
|
|
175
173
|
>
|
|
176
|
-
{children ?? <
|
|
174
|
+
{children ?? <CheckIcon size={14} />}
|
|
177
175
|
</Button>
|
|
178
176
|
);
|
|
179
177
|
};
|
|
@@ -11,7 +11,7 @@ export type ConversationProps = ComponentProps<typeof StickToBottom>;
|
|
|
11
11
|
|
|
12
12
|
export const Conversation = ({ className, ...props }: ConversationProps) => (
|
|
13
13
|
<StickToBottom
|
|
14
|
-
className={cn("relative flex-1 overflow-
|
|
14
|
+
className={cn("relative flex-1 overflow-hidden", className)}
|
|
15
15
|
initial="smooth"
|
|
16
16
|
resize="smooth"
|
|
17
17
|
role="log"
|
|
@@ -40,23 +40,21 @@ import {
|
|
|
40
40
|
ImageIcon,
|
|
41
41
|
Loader2Icon,
|
|
42
42
|
MicIcon,
|
|
43
|
-
PaperclipIcon,
|
|
44
43
|
PlusIcon,
|
|
45
44
|
SendIcon,
|
|
46
45
|
SquareIcon,
|
|
47
46
|
XIcon,
|
|
48
47
|
} from "lucide-react";
|
|
48
|
+
import React from "react";
|
|
49
49
|
import { nanoid } from "nanoid";
|
|
50
50
|
import {
|
|
51
51
|
type ChangeEvent,
|
|
52
52
|
type ChangeEventHandler,
|
|
53
|
-
Children,
|
|
54
53
|
type ClipboardEventHandler,
|
|
55
54
|
type ComponentProps,
|
|
56
55
|
createContext,
|
|
57
56
|
type FormEvent,
|
|
58
57
|
type FormEventHandler,
|
|
59
|
-
Fragment,
|
|
60
58
|
type HTMLAttributes,
|
|
61
59
|
type KeyboardEventHandler,
|
|
62
60
|
type PropsWithChildren,
|
|
@@ -295,7 +293,7 @@ export function PromptInputAttachment({
|
|
|
295
293
|
/>
|
|
296
294
|
) : (
|
|
297
295
|
<div className="flex size-5 items-center justify-center text-muted-foreground">
|
|
298
|
-
<
|
|
296
|
+
<div className="size-3" />
|
|
299
297
|
</div>
|
|
300
298
|
)}
|
|
301
299
|
</div>
|
|
@@ -365,7 +363,7 @@ export function PromptInputAttachments({
|
|
|
365
363
|
}
|
|
366
364
|
|
|
367
365
|
return attachments.files.map((file) => (
|
|
368
|
-
<Fragment key={file.id}>{children(file)}</Fragment>
|
|
366
|
+
<React.Fragment key={file.id}>{children(file)}</React.Fragment>
|
|
369
367
|
));
|
|
370
368
|
}
|
|
371
369
|
|
|
@@ -900,7 +898,7 @@ export const PromptInputButton = ({
|
|
|
900
898
|
...props
|
|
901
899
|
}: PromptInputButtonProps) => {
|
|
902
900
|
const newSize =
|
|
903
|
-
size ?? (Children.count(props.children) > 1 ? "sm" : "icon-sm");
|
|
901
|
+
size ?? (React.Children.count(props.children) > 1 ? "sm" : "icon-sm");
|
|
904
902
|
|
|
905
903
|
return (
|
|
906
904
|
<InputGroupButton
|
|
@@ -92,9 +92,14 @@ export const AIConversation = React.memo<AIConversationProps>(
|
|
|
92
92
|
[emptyState?.description]
|
|
93
93
|
)
|
|
94
94
|
|
|
95
|
+
const toMessageString = (content: unknown): string =>
|
|
96
|
+
typeof content === 'string' ? content : ''
|
|
97
|
+
|
|
95
98
|
const renderedMessages = React.useMemo(
|
|
96
99
|
() =>
|
|
97
100
|
messages.map((message) => {
|
|
101
|
+
const contentStr = toMessageString(message.content)
|
|
102
|
+
|
|
98
103
|
// Render based on role field
|
|
99
104
|
if (message.role === "user") {
|
|
100
105
|
return (
|
|
@@ -102,7 +107,7 @@ export const AIConversation = React.memo<AIConversationProps>(
|
|
|
102
107
|
key={message.id}
|
|
103
108
|
message={{
|
|
104
109
|
id: message.id,
|
|
105
|
-
content:
|
|
110
|
+
content: contentStr,
|
|
106
111
|
avatarSrc: message.avatarSrc,
|
|
107
112
|
avatarName: message.avatarName,
|
|
108
113
|
}}
|
|
@@ -122,7 +127,7 @@ export const AIConversation = React.memo<AIConversationProps>(
|
|
|
122
127
|
(tc) => tc.name !== "task" && tc.name !== "ask_user"
|
|
123
128
|
) || []
|
|
124
129
|
|
|
125
|
-
const hasContent =
|
|
130
|
+
const hasContent = contentStr.trim() !== ""
|
|
126
131
|
if (!hasContent && directToolCalls.length === 0 && subAgents.length === 0 && !message.isLoading) {
|
|
127
132
|
return null;
|
|
128
133
|
}
|
|
@@ -132,7 +137,7 @@ export const AIConversation = React.memo<AIConversationProps>(
|
|
|
132
137
|
key={message.id}
|
|
133
138
|
message={{
|
|
134
139
|
id: message.id,
|
|
135
|
-
content:
|
|
140
|
+
content: contentStr,
|
|
136
141
|
avatarSrc: message.avatarSrc,
|
|
137
142
|
avatarName: message.avatarName,
|
|
138
143
|
isLoading: message.isLoading,
|
|
@@ -170,7 +175,7 @@ export const AIConversation = React.memo<AIConversationProps>(
|
|
|
170
175
|
message={{
|
|
171
176
|
id: message.id,
|
|
172
177
|
name: message.avatarName || "Agent",
|
|
173
|
-
content:
|
|
178
|
+
content: contentStr,
|
|
174
179
|
toolCalls: message.toolCalls?.filter((tc) => tc.name !== "task"),
|
|
175
180
|
status: "completed",
|
|
176
181
|
}}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
|
-
import { Plus } from "lucide-react"
|
|
3
2
|
|
|
4
3
|
import {
|
|
5
4
|
EnhancedDataTable,
|
|
@@ -8,6 +7,7 @@ import {
|
|
|
8
7
|
} from "@/components/composites/DataTable"
|
|
9
8
|
import type { DynamicTableSchema } from "ui-schema-contracts"
|
|
10
9
|
import { Button } from "@/components/primitives/Button"
|
|
10
|
+
import { Icon } from "@/components/primitives/Icon"
|
|
11
11
|
|
|
12
12
|
export interface DataTableProps {
|
|
13
13
|
rows: DashboardRow[]
|
|
@@ -29,7 +29,7 @@ export const DataTable = React.memo<DataTableProps>(({ rows, tableSchema, handle
|
|
|
29
29
|
rightActions={
|
|
30
30
|
handlers?.onAddSection ? (
|
|
31
31
|
<Button variant="outline" size="sm" className="h-8" onClick={handlers.onAddSection}>
|
|
32
|
-
<
|
|
32
|
+
<Icon name="plus" size="sm" />
|
|
33
33
|
<span className="hidden lg:inline">Add Section</span>
|
|
34
34
|
</Button>
|
|
35
35
|
) : null
|
|
@@ -13,6 +13,8 @@ export interface InboxPanelProps {
|
|
|
13
13
|
isLoading?: boolean
|
|
14
14
|
emptyMessage?: string
|
|
15
15
|
className?: string
|
|
16
|
+
title?: string
|
|
17
|
+
headerAction?: React.ReactNode
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export const InboxPanel = React.memo<InboxPanelProps>(
|
|
@@ -26,10 +28,19 @@ export const InboxPanel = React.memo<InboxPanelProps>(
|
|
|
26
28
|
isLoading = false,
|
|
27
29
|
emptyMessage,
|
|
28
30
|
className,
|
|
31
|
+
title,
|
|
32
|
+
headerAction,
|
|
29
33
|
}) => {
|
|
30
34
|
return (
|
|
31
35
|
<section className={`flex min-h-0 flex-1 flex-col overflow-hidden ${className ?? ""}`}>
|
|
32
|
-
|
|
36
|
+
{title || headerAction ? (
|
|
37
|
+
<div className="flex items-center justify-between px-4 pt-4 pb-2">
|
|
38
|
+
{title ? <h2 className="text-sm font-semibold text-muted-foreground">{title}</h2> : <div />}
|
|
39
|
+
{headerAction ? <div>{headerAction}</div> : null}
|
|
40
|
+
</div>
|
|
41
|
+
) : null}
|
|
42
|
+
|
|
43
|
+
<div className="px-4 pb-2">
|
|
33
44
|
<Input
|
|
34
45
|
aria-label="Search inbox items"
|
|
35
46
|
className="h-8"
|
|
@@ -28,11 +28,11 @@ export const SectionLayout = React.memo<SectionLayoutProps>(
|
|
|
28
28
|
...section,
|
|
29
29
|
resizable,
|
|
30
30
|
content: (
|
|
31
|
-
<div className="h-full min-h-0 flex flex-col overflow-
|
|
31
|
+
<div className="h-full min-h-0 flex flex-col overflow-hidden">
|
|
32
32
|
{section.header && (
|
|
33
33
|
<AppHeader {...section.header} />
|
|
34
34
|
)}
|
|
35
|
-
<div className="min-h-0 flex-1 overflow-hidden">
|
|
35
|
+
<div className="min-h-0 flex-1 overflow-hidden flex flex-col">
|
|
36
36
|
{section.content}
|
|
37
37
|
</div>
|
|
38
38
|
</div>
|
|
@@ -10,26 +10,15 @@ export type { DocumentEditorWithCommentsProps } from './DocumentEditorWithCommen
|
|
|
10
10
|
export { FileChangeQueue } from './FileChangeQueue'
|
|
11
11
|
export type { FileChangeQueueProps } from './FileChangeQueue'
|
|
12
12
|
|
|
13
|
-
export { PromptInput } from './PromptInput'
|
|
14
|
-
export type { PromptInputBlockProps } from './PromptInput'
|
|
15
|
-
|
|
16
13
|
// Blocks
|
|
17
|
-
export * from './LayoutProvider'
|
|
18
14
|
export * from './SectionLayout'
|
|
19
|
-
export type { LayoutProviderProps } from './LayoutProvider'
|
|
20
15
|
|
|
21
16
|
export { WorkflowCanvas, getLayoutedElements } from './WorkflowCanvas'
|
|
22
17
|
export type { WorkflowCanvasProps, WorkflowNode, WorkflowEdge, WorkflowNodeData } from './WorkflowCanvas'
|
|
23
18
|
|
|
24
|
-
export { DashboardHeader } from './DashboardHeader'
|
|
25
|
-
export type { DashboardHeaderProps } from './DashboardHeader'
|
|
26
|
-
|
|
27
19
|
export { DashboardMetrics } from './DashboardMetrics'
|
|
28
20
|
export type { DashboardMetricsProps } from './DashboardMetrics'
|
|
29
21
|
|
|
30
|
-
export { DashboardChart } from './DashboardChart'
|
|
31
|
-
export type { DashboardChartProps } from './DashboardChart'
|
|
32
|
-
|
|
33
22
|
export { DataTable } from './DataTable'
|
|
34
23
|
export type { DataTableProps } from './DataTable'
|
|
35
24
|
|
|
@@ -22,7 +22,11 @@ export const AppHeader = React.memo<AppHeaderProps>(({
|
|
|
22
22
|
{showSidebarToggle && showTitle && title && (
|
|
23
23
|
<Separator orientation="vertical" className="mx-2 data-[orientation=vertical]:h-4" />
|
|
24
24
|
)}
|
|
25
|
-
{showTitle && title &&
|
|
25
|
+
{showTitle && title && (
|
|
26
|
+
typeof title === 'string'
|
|
27
|
+
? <h1 className="max-w-[28rem] truncate text-base font-medium">{title}</h1>
|
|
28
|
+
: title
|
|
29
|
+
)}
|
|
26
30
|
</div>
|
|
27
31
|
|
|
28
32
|
<div className="justify-self-center">
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useState } from "react";
|
|
5
|
-
import {
|
|
5
|
+
import { Icon } from "@/components/primitives/Icon";
|
|
6
6
|
import { Input } from "@/components/primitives/Input";
|
|
7
7
|
import { Textarea } from "@/components/primitives/Textarea";
|
|
8
8
|
import { Label } from "@/components/primitives/Label";
|
|
@@ -98,6 +98,10 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
98
98
|
const [rejectReason, setRejectReason] = useState("");
|
|
99
99
|
const [showRejectInput, setShowRejectInput] = useState(false);
|
|
100
100
|
|
|
101
|
+
const hideSkipButton = (actionRequest.args?.hide_skip_button as boolean) ?? false;
|
|
102
|
+
const submitButtonText = (actionRequest.args?.button_submit_text as string) || 'Continue';
|
|
103
|
+
const skipButtonText = (actionRequest.args?.button_skip_text as string) || 'Skip';
|
|
104
|
+
|
|
101
105
|
// Question states
|
|
102
106
|
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
|
|
103
107
|
const [selectedAnswers, setSelectedAnswers] = useState<Record<number, string | string[]>>({});
|
|
@@ -117,13 +121,15 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
117
121
|
const isQuestionAction =
|
|
118
122
|
actionRequest.name === "ask_question" ||
|
|
119
123
|
(actionRequest.args &&
|
|
120
|
-
(typeof actionRequest.args.question === "string" ||
|
|
121
|
-
Array.isArray(actionRequest.args.questions)));
|
|
124
|
+
((typeof actionRequest.args.question === "string") ||
|
|
125
|
+
(Array.isArray(actionRequest.args.questions) && actionRequest.args.questions.length > 0)));
|
|
122
126
|
|
|
123
127
|
// Parse questions
|
|
124
128
|
let questions: Question[] = [];
|
|
125
129
|
if (actionRequest.args && Array.isArray(actionRequest.args.questions)) {
|
|
126
130
|
questions = actionRequest.args.questions as Question[];
|
|
131
|
+
} else if (actionRequest.args && actionRequest.args.questions && typeof actionRequest.args.questions === "object") {
|
|
132
|
+
questions = Object.values(actionRequest.args.questions) as Question[];
|
|
127
133
|
} else if (actionRequest.args && typeof actionRequest.args.question === "string") {
|
|
128
134
|
questions = [
|
|
129
135
|
{
|
|
@@ -144,19 +150,37 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
144
150
|
// Render interactive question view
|
|
145
151
|
if (isQuestionAction && currentQuestion) {
|
|
146
152
|
const handleContinue = () => {
|
|
153
|
+
const qIdx = currentQuestionIndex;
|
|
154
|
+
const selIdx = selectedOptionIndices[qIdx];
|
|
155
|
+
const hasOtherSelected = selIdx === options.length;
|
|
156
|
+
const hasRegularSelection = selIdx !== null && selIdx !== undefined && !hasOtherSelected;
|
|
157
|
+
const hasMultiSelectItems = isMultiSelect && Array.isArray(selectedAnswers[qIdx]) && (selectedAnswers[qIdx] as string[]).length > 0;
|
|
158
|
+
|
|
159
|
+
const isApprovalType = actionRequest.args?.type === 'approval';
|
|
160
|
+
const isOtherEmpty = hasOtherSelected && !otherTexts[qIdx]?.trim();
|
|
161
|
+
const hasNoValidSelection = (!hasRegularSelection && !hasMultiSelectItems && !hasOtherSelected) || isOtherEmpty;
|
|
162
|
+
|
|
163
|
+
let answer: string | string[] = "Approved";
|
|
164
|
+
|
|
165
|
+
if (hasOtherSelected) {
|
|
166
|
+
answer = otherTexts[qIdx] || "Approved";
|
|
167
|
+
} else if (isMultiSelect) {
|
|
168
|
+
answer = (selectedAnswers[qIdx] as string[]).join(", ") || "Approved";
|
|
169
|
+
} else if (hasRegularSelection) {
|
|
170
|
+
answer = selectedAnswers[qIdx] as string || "Approved";
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (!isApprovalType && hasNoValidSelection) return;
|
|
174
|
+
|
|
147
175
|
if (currentQuestionIndex === questions.length - 1) {
|
|
148
176
|
const finalAnswers = questions.map((q, idx) => {
|
|
149
|
-
if (
|
|
150
|
-
return otherTexts[idx] || "";
|
|
151
|
-
}
|
|
177
|
+
if (idx === qIdx) return answer;
|
|
152
178
|
return selectedAnswers[idx] || "";
|
|
153
179
|
});
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
onEdit({ ...actionRequest.args, answers: finalAnswers });
|
|
157
|
-
}
|
|
158
|
-
onApprove();
|
|
180
|
+
if (onEdit) onEdit({ ...actionRequest.args, answers: finalAnswers });
|
|
181
|
+
else onApprove();
|
|
159
182
|
} else {
|
|
183
|
+
setSelectedAnswers((prev) => ({ ...prev, [qIdx]: answer }));
|
|
160
184
|
setCurrentQuestionIndex((prev) => prev + 1);
|
|
161
185
|
}
|
|
162
186
|
};
|
|
@@ -198,7 +222,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
198
222
|
disabled={currentQuestionIndex === 0}
|
|
199
223
|
className="hover:text-foreground disabled:opacity-30 p-0.5 transition-colors"
|
|
200
224
|
>
|
|
201
|
-
<
|
|
225
|
+
<Icon name="chevron-left" size="sm" />
|
|
202
226
|
</button>
|
|
203
227
|
<span className="font-medium">{currentQuestionIndex + 1} of {questions.length}</span>
|
|
204
228
|
<button
|
|
@@ -209,7 +233,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
209
233
|
disabled={currentQuestionIndex === questions.length - 1}
|
|
210
234
|
className="hover:text-foreground disabled:opacity-30 p-0.5 transition-colors"
|
|
211
235
|
>
|
|
212
|
-
<
|
|
236
|
+
<Icon name="chevron-right" size="sm" />
|
|
213
237
|
</button>
|
|
214
238
|
</div>
|
|
215
239
|
)}
|
|
@@ -297,17 +321,19 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
297
321
|
</div>
|
|
298
322
|
|
|
299
323
|
<ConfirmationActions>
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
onReject
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
324
|
+
{!hideSkipButton && (
|
|
325
|
+
<ConfirmationAction
|
|
326
|
+
variant="outline"
|
|
327
|
+
type="button"
|
|
328
|
+
onClick={() => {
|
|
329
|
+
if (onReject) {
|
|
330
|
+
onReject("Skipped question");
|
|
331
|
+
}
|
|
332
|
+
}}
|
|
333
|
+
>
|
|
334
|
+
{skipButtonText}
|
|
335
|
+
</ConfirmationAction>
|
|
336
|
+
)}
|
|
311
337
|
|
|
312
338
|
<ConfirmationAction
|
|
313
339
|
type="button"
|
|
@@ -317,13 +343,13 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
317
343
|
>
|
|
318
344
|
{currentQuestionIndex === questions.length - 1 ? (
|
|
319
345
|
<>
|
|
320
|
-
|
|
321
|
-
|
|
346
|
+
<Icon name="check" size="sm" className="mr-2" />
|
|
347
|
+
{submitButtonText}
|
|
322
348
|
</>
|
|
323
349
|
) : (
|
|
324
350
|
<>
|
|
325
351
|
Next
|
|
326
|
-
<
|
|
352
|
+
<Icon name="chevron-right" size="sm" className="ml-2" />
|
|
327
353
|
</>
|
|
328
354
|
)}
|
|
329
355
|
</ConfirmationAction>
|
|
@@ -344,7 +370,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
344
370
|
{isEditing ? (
|
|
345
371
|
<div className="space-y-4">
|
|
346
372
|
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
|
|
347
|
-
<
|
|
373
|
+
<Icon name="pencil" size="sm" />
|
|
348
374
|
<span>
|
|
349
375
|
Edit —{" "}
|
|
350
376
|
<code className="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">
|
|
@@ -409,7 +435,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
409
435
|
}}
|
|
410
436
|
disabled={isProcessing}
|
|
411
437
|
>
|
|
412
|
-
|
|
438
|
+
<Icon name="check" size="sm" className="mr-2" />
|
|
413
439
|
Save & Approve
|
|
414
440
|
</ConfirmationAction>
|
|
415
441
|
</ConfirmationActions>
|
|
@@ -423,24 +449,26 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
423
449
|
)}
|
|
424
450
|
|
|
425
451
|
<div className="mt-3 space-y-3">
|
|
426
|
-
{Object.entries(actionRequest.args)
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
452
|
+
{Object.entries(actionRequest.args)
|
|
453
|
+
.filter(([_, value]) => typeof value === "string" || typeof value === "number" || typeof value === "boolean")
|
|
454
|
+
.map(([key, value]) => {
|
|
455
|
+
const strValue = formatValue(value);
|
|
456
|
+
const isMultiline = strValue.includes("\n");
|
|
457
|
+
return (
|
|
458
|
+
<div key={key} className="space-y-1">
|
|
459
|
+
<div className="text-[10px] font-semibold text-muted-foreground uppercase tracking-wider">
|
|
460
|
+
{key}
|
|
461
|
+
</div>
|
|
462
|
+
{isMultiline ? (
|
|
463
|
+
<pre className="text-xs text-card-foreground whitespace-pre-wrap break-all font-mono bg-muted/50 rounded-md px-2.5 py-1.5 border border-border">
|
|
464
|
+
{strValue}
|
|
465
|
+
</pre>
|
|
466
|
+
) : (
|
|
467
|
+
<div className="text-sm text-card-foreground break-all">{strValue}</div>
|
|
468
|
+
)}
|
|
433
469
|
</div>
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
{strValue}
|
|
437
|
-
</pre>
|
|
438
|
-
) : (
|
|
439
|
-
<div className="text-sm text-card-foreground break-all">{strValue}</div>
|
|
440
|
-
)}
|
|
441
|
-
</div>
|
|
442
|
-
);
|
|
443
|
-
})}
|
|
470
|
+
);
|
|
471
|
+
})}
|
|
444
472
|
</div>
|
|
445
473
|
</div>
|
|
446
474
|
|
|
@@ -483,21 +511,21 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
483
511
|
}}
|
|
484
512
|
disabled={isProcessing}
|
|
485
513
|
>
|
|
486
|
-
|
|
514
|
+
<Icon name="x" size="sm" className="mr-2" />
|
|
487
515
|
Confirm Rejection
|
|
488
516
|
</ConfirmationAction>
|
|
489
517
|
</>
|
|
490
518
|
) : (
|
|
491
519
|
<>
|
|
492
|
-
{canReject && (
|
|
520
|
+
{canReject && !hideSkipButton && (
|
|
493
521
|
<ConfirmationAction
|
|
494
522
|
type="button"
|
|
495
523
|
variant="outline"
|
|
496
524
|
onClick={() => setShowRejectInput(true)}
|
|
497
525
|
disabled={isProcessing}
|
|
498
526
|
>
|
|
499
|
-
|
|
500
|
-
|
|
527
|
+
<Icon name="x" size="sm" className="mr-2" />
|
|
528
|
+
{skipButtonText}
|
|
501
529
|
</ConfirmationAction>
|
|
502
530
|
)}
|
|
503
531
|
{canEdit && (
|
|
@@ -507,7 +535,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
507
535
|
onClick={() => setIsEditing(true)}
|
|
508
536
|
disabled={isProcessing}
|
|
509
537
|
>
|
|
510
|
-
<
|
|
538
|
+
<Icon name="pencil" size="sm" className="mr-2" />
|
|
511
539
|
Edit
|
|
512
540
|
</ConfirmationAction>
|
|
513
541
|
)}
|
|
@@ -517,8 +545,8 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
517
545
|
onClick={onApprove}
|
|
518
546
|
disabled={isProcessing}
|
|
519
547
|
>
|
|
520
|
-
|
|
521
|
-
|
|
548
|
+
<Icon name="check" size="sm" className="mr-2" />
|
|
549
|
+
{submitButtonText}
|
|
522
550
|
</ConfirmationAction>
|
|
523
551
|
</>
|
|
524
552
|
)}
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
InputGroupTextarea,
|
|
57
57
|
InputGroupButton,
|
|
58
58
|
} from '@/components/primitives/InputGroup'
|
|
59
|
-
import {
|
|
59
|
+
import { Icon } from '@/components/primitives/Icon'
|
|
60
60
|
import { formatCommentDate } from '@/utils/ai-editor'
|
|
61
61
|
import type { CommentBoxProps, Comment } from '@/types/ai-editor'
|
|
62
62
|
import { cn } from '@/lib/utils'
|
|
@@ -132,7 +132,7 @@ const CommentThreadDisplay = React.memo<{
|
|
|
132
132
|
}
|
|
133
133
|
}}
|
|
134
134
|
>
|
|
135
|
-
<
|
|
135
|
+
<Icon name="send" size="sm" />
|
|
136
136
|
</InputGroupButton>
|
|
137
137
|
</InputGroup>
|
|
138
138
|
</ConversationContent>
|
|
@@ -208,7 +208,7 @@ export const CommentBox = React.memo<CommentBoxProps>(
|
|
|
208
208
|
}
|
|
209
209
|
}}
|
|
210
210
|
>
|
|
211
|
-
<
|
|
211
|
+
<Icon name="send" size="sm" />
|
|
212
212
|
</InputGroupButton>
|
|
213
213
|
</InputGroup>
|
|
214
214
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useSortable } from "@dnd-kit/sortable"
|
|
2
|
-
import { GripVertical } from "lucide-react"
|
|
3
2
|
|
|
4
3
|
import { Button } from "@/components/primitives/Button"
|
|
4
|
+
import { Icon } from "@/components/primitives/Icon"
|
|
5
5
|
|
|
6
6
|
export interface DragHandleCellProps {
|
|
7
7
|
id: number | string
|
|
@@ -19,7 +19,7 @@ export function DragHandleCell({ id }: DragHandleCellProps) {
|
|
|
19
19
|
className="size-7 text-muted-foreground hover:bg-transparent"
|
|
20
20
|
aria-label="Drag to reorder"
|
|
21
21
|
>
|
|
22
|
-
<
|
|
22
|
+
<Icon name="grip-vertical" size="xs" />
|
|
23
23
|
</Button>
|
|
24
24
|
)
|
|
25
25
|
}
|
|
@@ -19,7 +19,7 @@ const tableSchema = dynamicTableSchema.parse({
|
|
|
19
19
|
enablePagination: true,
|
|
20
20
|
enableRowSelection: true,
|
|
21
21
|
columns: [
|
|
22
|
-
{ key: "header", label: "Header", sortable: true, hideable: false },
|
|
22
|
+
{ key: "header", label: "Header", renderType: "link", sortable: true, hideable: false },
|
|
23
23
|
{ key: "type", label: "Type", sortable: true },
|
|
24
24
|
{ key: "status", label: "Status", renderType: "badge", sortable: true },
|
|
25
25
|
{ key: "target", label: "Target", align: "right", sortable: true },
|