ai-design-system 0.1.47 → 0.1.49
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/prompt-input.tsx +7 -12
- package/components/ai-elements/queue.tsx +2 -2
- package/components/blocks/DataTable/DataTable.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 +11 -11
- 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/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/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 +1 -1
- package/components/features/WorkflowBuilder/WorkflowBuilder.tsx +3 -6
- package/components/index.ts +4 -3
- package/components/primitives/Icon/Icon.tsx +48 -1
- package/dist/index.cjs +731 -228
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +28 -0
- package/dist/index.d.ts +123 -4
- package/dist/index.js +730 -230
- 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/PromptInput.tsx +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
|
};
|
|
@@ -37,26 +37,21 @@ import {
|
|
|
37
37
|
import { cn } from "@/lib/utils";
|
|
38
38
|
import type { ChatStatus, FileUIPart } from "ai";
|
|
39
39
|
import {
|
|
40
|
-
ImageIcon,
|
|
41
40
|
Loader2Icon,
|
|
42
|
-
MicIcon,
|
|
43
|
-
PaperclipIcon,
|
|
44
|
-
PlusIcon,
|
|
45
41
|
SendIcon,
|
|
46
42
|
SquareIcon,
|
|
47
43
|
XIcon,
|
|
48
44
|
} from "lucide-react";
|
|
45
|
+
import React from "react";
|
|
49
46
|
import { nanoid } from "nanoid";
|
|
50
47
|
import {
|
|
51
48
|
type ChangeEvent,
|
|
52
49
|
type ChangeEventHandler,
|
|
53
|
-
Children,
|
|
54
50
|
type ClipboardEventHandler,
|
|
55
51
|
type ComponentProps,
|
|
56
52
|
createContext,
|
|
57
53
|
type FormEvent,
|
|
58
54
|
type FormEventHandler,
|
|
59
|
-
Fragment,
|
|
60
55
|
type HTMLAttributes,
|
|
61
56
|
type KeyboardEventHandler,
|
|
62
57
|
type PropsWithChildren,
|
|
@@ -295,7 +290,7 @@ export function PromptInputAttachment({
|
|
|
295
290
|
/>
|
|
296
291
|
) : (
|
|
297
292
|
<div className="flex size-5 items-center justify-center text-muted-foreground">
|
|
298
|
-
<
|
|
293
|
+
<div className="size-3" />
|
|
299
294
|
</div>
|
|
300
295
|
)}
|
|
301
296
|
</div>
|
|
@@ -365,7 +360,7 @@ export function PromptInputAttachments({
|
|
|
365
360
|
}
|
|
366
361
|
|
|
367
362
|
return attachments.files.map((file) => (
|
|
368
|
-
<Fragment key={file.id}>{children(file)}</Fragment>
|
|
363
|
+
<React.Fragment key={file.id}>{children(file)}</React.Fragment>
|
|
369
364
|
));
|
|
370
365
|
}
|
|
371
366
|
|
|
@@ -389,7 +384,7 @@ export const PromptInputActionAddAttachments = ({
|
|
|
389
384
|
attachments.openFileDialog();
|
|
390
385
|
}}
|
|
391
386
|
>
|
|
392
|
-
|
|
387
|
+
{label}
|
|
393
388
|
</DropdownMenuItem>
|
|
394
389
|
);
|
|
395
390
|
};
|
|
@@ -900,7 +895,7 @@ export const PromptInputButton = ({
|
|
|
900
895
|
...props
|
|
901
896
|
}: PromptInputButtonProps) => {
|
|
902
897
|
const newSize =
|
|
903
|
-
size ?? (Children.count(props.children) > 1 ? "sm" : "icon-sm");
|
|
898
|
+
size ?? (React.Children.count(props.children) > 1 ? "sm" : "icon-sm");
|
|
904
899
|
|
|
905
900
|
return (
|
|
906
901
|
<InputGroupButton
|
|
@@ -927,7 +922,7 @@ export const PromptInputActionMenuTrigger = ({
|
|
|
927
922
|
}: PromptInputActionMenuTriggerProps) => (
|
|
928
923
|
<DropdownMenuTrigger asChild>
|
|
929
924
|
<PromptInputButton className={className} {...props}>
|
|
930
|
-
{children
|
|
925
|
+
{children}
|
|
931
926
|
</PromptInputButton>
|
|
932
927
|
</DropdownMenuTrigger>
|
|
933
928
|
);
|
|
@@ -1150,7 +1145,7 @@ export const PromptInputSpeechButton = ({
|
|
|
1150
1145
|
onClick={toggleListening}
|
|
1151
1146
|
{...props}
|
|
1152
1147
|
>
|
|
1153
|
-
<
|
|
1148
|
+
<div className="size-4" />
|
|
1154
1149
|
</PromptInputButton>
|
|
1155
1150
|
);
|
|
1156
1151
|
};
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "@/components/ui/collapsible";
|
|
9
9
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
|
10
10
|
import { cn } from "@/lib/utils";
|
|
11
|
-
import { ChevronDownIcon
|
|
11
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
12
12
|
import type { ComponentProps } from "react";
|
|
13
13
|
|
|
14
14
|
export type QueueMessagePart = {
|
|
@@ -174,7 +174,7 @@ export const QueueItemFile = ({
|
|
|
174
174
|
)}
|
|
175
175
|
{...props}
|
|
176
176
|
>
|
|
177
|
-
<
|
|
177
|
+
<div className="size-3" />
|
|
178
178
|
<span className="max-w-[100px] truncate">{children}</span>
|
|
179
179
|
</span>
|
|
180
180
|
);
|
|
@@ -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
|
|
@@ -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";
|
|
@@ -222,7 +222,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
222
222
|
disabled={currentQuestionIndex === 0}
|
|
223
223
|
className="hover:text-foreground disabled:opacity-30 p-0.5 transition-colors"
|
|
224
224
|
>
|
|
225
|
-
<
|
|
225
|
+
<Icon name="chevron-left" size="sm" />
|
|
226
226
|
</button>
|
|
227
227
|
<span className="font-medium">{currentQuestionIndex + 1} of {questions.length}</span>
|
|
228
228
|
<button
|
|
@@ -233,7 +233,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
233
233
|
disabled={currentQuestionIndex === questions.length - 1}
|
|
234
234
|
className="hover:text-foreground disabled:opacity-30 p-0.5 transition-colors"
|
|
235
235
|
>
|
|
236
|
-
<
|
|
236
|
+
<Icon name="chevron-right" size="sm" />
|
|
237
237
|
</button>
|
|
238
238
|
</div>
|
|
239
239
|
)}
|
|
@@ -343,13 +343,13 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
343
343
|
>
|
|
344
344
|
{currentQuestionIndex === questions.length - 1 ? (
|
|
345
345
|
<>
|
|
346
|
-
|
|
346
|
+
<Icon name="check" size="sm" className="mr-2" />
|
|
347
347
|
{submitButtonText}
|
|
348
348
|
</>
|
|
349
349
|
) : (
|
|
350
350
|
<>
|
|
351
351
|
Next
|
|
352
|
-
<
|
|
352
|
+
<Icon name="chevron-right" size="sm" className="ml-2" />
|
|
353
353
|
</>
|
|
354
354
|
)}
|
|
355
355
|
</ConfirmationAction>
|
|
@@ -370,7 +370,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
370
370
|
{isEditing ? (
|
|
371
371
|
<div className="space-y-4">
|
|
372
372
|
<div className="flex items-center gap-2 text-sm font-medium text-muted-foreground">
|
|
373
|
-
<
|
|
373
|
+
<Icon name="pencil" size="sm" />
|
|
374
374
|
<span>
|
|
375
375
|
Edit —{" "}
|
|
376
376
|
<code className="font-mono text-xs bg-muted px-1.5 py-0.5 rounded">
|
|
@@ -435,7 +435,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
435
435
|
}}
|
|
436
436
|
disabled={isProcessing}
|
|
437
437
|
>
|
|
438
|
-
|
|
438
|
+
<Icon name="check" size="sm" className="mr-2" />
|
|
439
439
|
Save & Approve
|
|
440
440
|
</ConfirmationAction>
|
|
441
441
|
</ConfirmationActions>
|
|
@@ -511,7 +511,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
511
511
|
}}
|
|
512
512
|
disabled={isProcessing}
|
|
513
513
|
>
|
|
514
|
-
|
|
514
|
+
<Icon name="x" size="sm" className="mr-2" />
|
|
515
515
|
Confirm Rejection
|
|
516
516
|
</ConfirmationAction>
|
|
517
517
|
</>
|
|
@@ -524,7 +524,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
524
524
|
onClick={() => setShowRejectInput(true)}
|
|
525
525
|
disabled={isProcessing}
|
|
526
526
|
>
|
|
527
|
-
|
|
527
|
+
<Icon name="x" size="sm" className="mr-2" />
|
|
528
528
|
{skipButtonText}
|
|
529
529
|
</ConfirmationAction>
|
|
530
530
|
)}
|
|
@@ -535,7 +535,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
535
535
|
onClick={() => setIsEditing(true)}
|
|
536
536
|
disabled={isProcessing}
|
|
537
537
|
>
|
|
538
|
-
<
|
|
538
|
+
<Icon name="pencil" size="sm" className="mr-2" />
|
|
539
539
|
Edit
|
|
540
540
|
</ConfirmationAction>
|
|
541
541
|
)}
|
|
@@ -545,7 +545,7 @@ export const ApprovalCard = React.memo<ApprovalCardProps>(
|
|
|
545
545
|
onClick={onApprove}
|
|
546
546
|
disabled={isProcessing}
|
|
547
547
|
>
|
|
548
|
-
|
|
548
|
+
<Icon name="check" size="sm" className="mr-2" />
|
|
549
549
|
{submitButtonText}
|
|
550
550
|
</ConfirmationAction>
|
|
551
551
|
</>
|
|
@@ -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 },
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "@dnd-kit/core"
|
|
12
12
|
import { restrictToVerticalAxis } from "@dnd-kit/modifiers"
|
|
13
13
|
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"
|
|
14
|
-
import {
|
|
14
|
+
import { Icon } from "@/components/primitives/Icon"
|
|
15
15
|
import { flexRender, type ColumnDef } from "@tanstack/react-table"
|
|
16
16
|
import type { DynamicTableSchema, TableColumn } from "ui-schema-contracts"
|
|
17
17
|
|
|
@@ -35,6 +35,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
|
|
|
35
35
|
|
|
36
36
|
import { DragHandleCell } from "./DragHandleCell"
|
|
37
37
|
import { DraggableRow } from "./DraggableRow"
|
|
38
|
+
import { RowDetailDrawer } from "./RowDetailDrawer"
|
|
38
39
|
import { createTableSelectColumn } from "./TableSelectColumn"
|
|
39
40
|
import type {
|
|
40
41
|
DashboardPaginationState,
|
|
@@ -318,6 +319,16 @@ export function EnhancedDataTable({
|
|
|
318
319
|
const rawValue = row.original[column.key]
|
|
319
320
|
const rowId = String(toRowId(row.original, tableSchema))
|
|
320
321
|
const isRowEditing = editingRowId === rowId
|
|
322
|
+
if (column.renderType === "link") {
|
|
323
|
+
return (
|
|
324
|
+
<div className={alignClass(column.align)}>
|
|
325
|
+
<RowDetailDrawer
|
|
326
|
+
item={row.original}
|
|
327
|
+
onChange={(rowId, key, value) => handleInlineSave(rowId, String(key), value)}
|
|
328
|
+
/>
|
|
329
|
+
</div>
|
|
330
|
+
)
|
|
331
|
+
}
|
|
321
332
|
if (isRowEditing && (column.editable ?? false) && (column.inputType ?? "none") !== "none") {
|
|
322
333
|
return renderEditableCell(row.original, column, rawValue)
|
|
323
334
|
}
|
|
@@ -336,7 +347,7 @@ export function EnhancedDataTable({
|
|
|
336
347
|
<DropdownMenu>
|
|
337
348
|
<DropdownMenuTrigger asChild>
|
|
338
349
|
<Button variant="ghost" className="flex size-8 text-muted-foreground data-[state=open]:bg-muted" size="icon">
|
|
339
|
-
<
|
|
350
|
+
<Icon name="more-vertical" size="sm" />
|
|
340
351
|
<span className="sr-only">Open menu</span>
|
|
341
352
|
</Button>
|
|
342
353
|
</DropdownMenuTrigger>
|
|
@@ -470,10 +481,10 @@ export function EnhancedDataTable({
|
|
|
470
481
|
<DropdownMenu>
|
|
471
482
|
<DropdownMenuTrigger asChild>
|
|
472
483
|
<Button variant="outline" size="sm" className="h-8">
|
|
473
|
-
<
|
|
484
|
+
<Icon name="columns-3" size="sm" />
|
|
474
485
|
<span className="hidden lg:inline">Customize Columns</span>
|
|
475
486
|
<span className="lg:hidden">Columns</span>
|
|
476
|
-
<
|
|
487
|
+
<Icon name="chevron-down" size="sm" />
|
|
477
488
|
</Button>
|
|
478
489
|
</DropdownMenuTrigger>
|
|
479
490
|
<DropdownMenuContent align="end" className="w-56">
|
|
@@ -496,7 +507,7 @@ export function EnhancedDataTable({
|
|
|
496
507
|
</DropdownMenuContent>
|
|
497
508
|
</DropdownMenu>
|
|
498
509
|
<Button variant="outline" size="sm" className="h-8" onClick={onCreateClick}>
|
|
499
|
-
<
|
|
510
|
+
<Icon name="plus" size="sm" />
|
|
500
511
|
<span>{createButtonLabel}</span>
|
|
501
512
|
</Button>
|
|
502
513
|
{rightActions}
|
|
@@ -588,7 +599,7 @@ export function EnhancedDataTable({
|
|
|
588
599
|
disabled={!canPreviousPage}
|
|
589
600
|
>
|
|
590
601
|
<span className="sr-only">Go to first page</span>
|
|
591
|
-
<
|
|
602
|
+
<Icon name="chevrons-left" size="sm" />
|
|
592
603
|
</Button>
|
|
593
604
|
<Button
|
|
594
605
|
variant="outline"
|
|
@@ -602,7 +613,7 @@ export function EnhancedDataTable({
|
|
|
602
613
|
disabled={!canPreviousPage}
|
|
603
614
|
>
|
|
604
615
|
<span className="sr-only">Go to previous page</span>
|
|
605
|
-
<
|
|
616
|
+
<Icon name="chevron-left" size="sm" />
|
|
606
617
|
</Button>
|
|
607
618
|
<Button
|
|
608
619
|
variant="outline"
|
|
@@ -616,7 +627,7 @@ export function EnhancedDataTable({
|
|
|
616
627
|
disabled={!canNextPage}
|
|
617
628
|
>
|
|
618
629
|
<span className="sr-only">Go to next page</span>
|
|
619
|
-
<
|
|
630
|
+
<Icon name="chevron-right" size="sm" />
|
|
620
631
|
</Button>
|
|
621
632
|
<Button
|
|
622
633
|
variant="outline"
|
|
@@ -630,7 +641,7 @@ export function EnhancedDataTable({
|
|
|
630
641
|
disabled={!canNextPage}
|
|
631
642
|
>
|
|
632
643
|
<span className="sr-only">Go to last page</span>
|
|
633
|
-
<
|
|
644
|
+
<Icon name="chevrons-right" size="sm" />
|
|
634
645
|
</Button>
|
|
635
646
|
</div>
|
|
636
647
|
</div>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
|
-
import { toast } from "sonner"
|
|
3
2
|
|
|
4
3
|
import { Input } from "@/components/primitives/Input"
|
|
5
4
|
import { Label } from "@/components/primitives/Label"
|
|
@@ -23,7 +22,6 @@ export function InlineEditCell({ row, field, onSave }: InlineEditCellProps) {
|
|
|
23
22
|
const formData = new FormData(event.currentTarget)
|
|
24
23
|
const value = String(formData.get(field) ?? "").trim()
|
|
25
24
|
onSave(rowId, field, value)
|
|
26
|
-
toast.success(`Saved ${field} for ${rowHeader}`)
|
|
27
25
|
},
|
|
28
26
|
[field, onSave, rowId, rowHeader]
|
|
29
27
|
)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as React from "react"
|
|
2
2
|
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
|
|
3
|
-
import { TrendingUp } from "lucide-react"
|
|
4
|
-
|
|
5
3
|
import { Button } from "@/components/primitives/Button"
|
|
4
|
+
import { Icon } from "@/components/primitives/Icon"
|
|
6
5
|
import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from "@/components/primitives/Chart"
|
|
7
6
|
import {
|
|
8
7
|
Drawer,
|
|
@@ -90,7 +89,7 @@ export function RowDetailDrawer({ item, onChange }: RowDetailDrawerProps) {
|
|
|
90
89
|
<Separator />
|
|
91
90
|
<div className="grid gap-2">
|
|
92
91
|
<div className="flex gap-2 leading-none font-medium">
|
|
93
|
-
Trending up by 5.2% this month <
|
|
92
|
+
Trending up by 5.2% this month <Icon name="trending-up" size="sm" />
|
|
94
93
|
</div>
|
|
95
94
|
<div className="text-muted-foreground">
|
|
96
95
|
Showing total visitors for the last 6 months. This section mirrors the v4 row detail panel.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Badge } from "@/components/primitives/Badge"
|
|
2
|
-
import {
|
|
2
|
+
import { Icon } from "@/components/primitives/Icon"
|
|
3
3
|
|
|
4
4
|
import type { DashboardRow } from "./table-types"
|
|
5
5
|
|
|
@@ -10,9 +10,9 @@ export interface StatusCellProps {
|
|
|
10
10
|
export function StatusCell({ status }: StatusCellProps) {
|
|
11
11
|
return (
|
|
12
12
|
<Badge variant="outline" className="gap-1 px-1.5 text-muted-foreground">
|
|
13
|
-
{status === "Done" ? <
|
|
14
|
-
{status === "In Process" ? <
|
|
15
|
-
{status === "Not Started" ? <
|
|
13
|
+
{status === "Done" ? <Icon name="circle-check" size="xs" className="text-green-500" /> : null}
|
|
14
|
+
{status === "In Process" ? <Icon name="loader-2" size="xs" className="animate-spin" /> : null}
|
|
15
|
+
{status === "Not Started" ? <Icon name="circle-slash" size="xs" /> : null}
|
|
16
16
|
{status as React.ReactNode}
|
|
17
17
|
</Badge>
|
|
18
18
|
)
|
|
@@ -10,8 +10,6 @@ export { InlineEditCell } from './InlineEditCell'
|
|
|
10
10
|
export type { InlineEditCellProps } from './InlineEditCell'
|
|
11
11
|
export { ReviewerCell } from './ReviewerCell'
|
|
12
12
|
export type { ReviewerCellProps } from './ReviewerCell'
|
|
13
|
-
export { StatusCell } from './StatusCell'
|
|
14
|
-
export type { StatusCellProps } from './StatusCell'
|
|
15
13
|
export { RowDetailDrawer } from './RowDetailDrawer'
|
|
16
14
|
export type { RowDetailDrawerProps } from './RowDetailDrawer'
|
|
17
15
|
export { createTableSelectColumn } from './TableSelectColumn'
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import React from 'react'
|
|
9
9
|
import { Tabs, TabsList, TabsTrigger, Button, ScrollArea } from '@/components/primitives'
|
|
10
|
-
import {
|
|
10
|
+
import { Icon } from '@/components/primitives/Icon'
|
|
11
11
|
import { cn } from '@/lib/utils'
|
|
12
12
|
export interface DocumentFile {
|
|
13
13
|
id: string
|
|
@@ -102,8 +102,9 @@ export const DocumentTabBar = React.memo<DocumentTabBarProps>(
|
|
|
102
102
|
<div className="flex items-center gap-2">
|
|
103
103
|
{/* Dirty indicator */}
|
|
104
104
|
{tab.isDirty && (
|
|
105
|
-
<
|
|
106
|
-
|
|
105
|
+
<Icon
|
|
106
|
+
name="circle"
|
|
107
|
+
className="size-2 fill-primary text-primary"
|
|
107
108
|
aria-label="unsaved changes"
|
|
108
109
|
/>
|
|
109
110
|
)}
|
|
@@ -128,7 +129,7 @@ export const DocumentTabBar = React.memo<DocumentTabBarProps>(
|
|
|
128
129
|
)}
|
|
129
130
|
aria-label={`Close ${tab.name}`}
|
|
130
131
|
>
|
|
131
|
-
<
|
|
132
|
+
<Icon name="x" size="xs" />
|
|
132
133
|
</Button>
|
|
133
134
|
</div>
|
|
134
135
|
))}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react"
|
|
2
|
+
import { fn } from "@storybook/test"
|
|
3
|
+
|
|
4
|
+
import { EmptyState } from "./EmptyState"
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: "Composites/EmptyState",
|
|
8
|
+
component: EmptyState,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "centered",
|
|
11
|
+
},
|
|
12
|
+
args: {
|
|
13
|
+
onAction: fn(),
|
|
14
|
+
},
|
|
15
|
+
} satisfies Meta<typeof EmptyState>
|
|
16
|
+
|
|
17
|
+
export default meta
|
|
18
|
+
type Story = StoryObj<typeof meta>
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
args: {
|
|
22
|
+
title: "Distribute Track",
|
|
23
|
+
description: "Upload your first master to start reaching listeners on Spotify, Apple Music, and more.",
|
|
24
|
+
actionLabel: "Create Release",
|
|
25
|
+
},
|
|
26
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { Button } from "@/components/primitives/Button"
|
|
4
|
+
import { Icon } from "@/components/primitives/Icon"
|
|
5
|
+
|
|
6
|
+
export interface EmptyStateProps {
|
|
7
|
+
title: string
|
|
8
|
+
description: string
|
|
9
|
+
actionLabel: string
|
|
10
|
+
onAction?: () => void
|
|
11
|
+
className?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const EmptyState = React.forwardRef<HTMLDivElement, EmptyStateProps>(
|
|
15
|
+
({ title, description, actionLabel, onAction, className }, ref) => {
|
|
16
|
+
return (
|
|
17
|
+
<div
|
|
18
|
+
ref={ref}
|
|
19
|
+
className={`flex flex-col items-center justify-center rounded-3xl border border-border bg-card p-10 text-center shadow-md max-w-[420px] w-full mx-auto ${className || ""}`}
|
|
20
|
+
>
|
|
21
|
+
<div className="mx-auto flex h-14 w-14 items-center justify-center rounded-2xl bg-muted/50 mb-6">
|
|
22
|
+
<Icon name="plus" size="lg" className="text-muted-foreground" />
|
|
23
|
+
</div>
|
|
24
|
+
<h3 className="mb-3 text-xl font-semibold tracking-tight text-card-foreground">
|
|
25
|
+
{title}
|
|
26
|
+
</h3>
|
|
27
|
+
<p className="mb-8 text-sm text-muted-foreground leading-relaxed">
|
|
28
|
+
{description}
|
|
29
|
+
</p>
|
|
30
|
+
<Button onClick={onAction} variant="secondary" className="rounded-full px-6 py-5 font-medium">
|
|
31
|
+
{actionLabel}
|
|
32
|
+
</Button>
|
|
33
|
+
</div>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
EmptyState.displayName = "EmptyState"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./EmptyState"
|