ai-design-system 0.1.15 → 0.1.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.
Files changed (84) hide show
  1. package/components/blocks/AppSidebar/AppSidebar.tsx +12 -2
  2. package/components/blocks/AppSidebar/interfaces.ts +3 -0
  3. package/components/blocks/DashboardChart/DashboardChart.tsx +182 -0
  4. package/components/blocks/DashboardChart/index.ts +2 -0
  5. package/components/blocks/DashboardHeader/DashboardHeader.tsx +20 -0
  6. package/components/blocks/DashboardHeader/index.ts +2 -0
  7. package/components/blocks/DashboardMetrics/DashboardMetrics.tsx +41 -0
  8. package/components/blocks/DashboardMetrics/index.ts +2 -0
  9. package/components/blocks/DataTable/DataTable.tsx +42 -0
  10. package/components/blocks/DataTable/index.ts +2 -0
  11. package/components/blocks/FormReportsSection/FormReportsSection.tsx +46 -0
  12. package/components/blocks/FormReportsSection/index.ts +2 -0
  13. package/components/blocks/SectionLayout/SectionLayout.tsx +2 -2
  14. package/components/blocks/index.ts +15 -0
  15. package/components/composites/AdjustableLayout/AdjustableLayout.tsx +2 -1
  16. package/components/composites/DataTable/DragHandleCell.tsx +25 -0
  17. package/components/composites/DataTable/DraggableRow.tsx +35 -0
  18. package/components/composites/DataTable/EnhancedDataTable.behaviors.stories.tsx +60 -0
  19. package/components/composites/DataTable/EnhancedDataTable.stories.tsx +42 -0
  20. package/components/composites/DataTable/EnhancedDataTable.tsx +616 -0
  21. package/components/composites/DataTable/InlineEditCell.tsx +45 -0
  22. package/components/composites/DataTable/ReviewerCell.tsx +43 -0
  23. package/components/composites/DataTable/RowDetailDrawer.tsx +172 -0
  24. package/components/composites/DataTable/StatusCell.tsx +19 -0
  25. package/components/composites/DataTable/TableSelectColumn.tsx +32 -0
  26. package/components/composites/DataTable/index.ts +24 -0
  27. package/components/composites/DataTable/table-types.ts +31 -0
  28. package/components/composites/DataTable/useEnhancedDataTable.ts +99 -0
  29. package/components/composites/FilePreviewDialog/FilePreviewDialog.tsx +150 -0
  30. package/components/composites/FilePreviewDialog/index.ts +2 -0
  31. package/components/composites/FormReports/FormReportsDrawerForm.tsx +220 -0
  32. package/components/composites/FormReports/FormReportsTable.tsx +181 -0
  33. package/components/composites/FormReports/index.ts +24 -0
  34. package/components/composites/StatsCard/StatsCard.tsx +2 -2
  35. package/components/composites/WorkflowRunObservabilityPanel/WorkflowRunObservabilityPanel.tsx +549 -0
  36. package/components/composites/WorkflowRunObservabilityPanel/index.ts +17 -0
  37. package/components/composites/index.ts +34 -0
  38. package/components/features/DashboardFeature/DashboardFeature.behaviors.stories.tsx +73 -0
  39. package/components/features/DashboardFeature/DashboardFeature.mocks.ts +303 -0
  40. package/components/features/DashboardFeature/DashboardFeature.stories.tsx +63 -0
  41. package/components/features/DashboardFeature/DashboardFeature.tsx +131 -0
  42. package/components/features/DashboardFeature/README.md +48 -0
  43. package/components/features/DashboardFeature/index.ts +11 -0
  44. package/components/features/DashboardFeature/useDashboardFeature.d.ts +65 -0
  45. package/components/features/DashboardFeature/useDashboardFeature.mock.ts +57 -0
  46. package/components/features/FormReportsFeature/FormReportsFeature.behaviors.stories.tsx +87 -0
  47. package/components/features/FormReportsFeature/FormReportsFeature.mocks.ts +183 -0
  48. package/components/features/FormReportsFeature/FormReportsFeature.stories.tsx +51 -0
  49. package/components/features/FormReportsFeature/FormReportsFeature.tsx +132 -0
  50. package/components/features/FormReportsFeature/README.md +43 -0
  51. package/components/features/FormReportsFeature/index.ts +7 -0
  52. package/components/features/FormReportsFeature/useFormReportsFeature.d.ts +31 -0
  53. package/components/features/FormReportsFeature/useFormReportsFeature.mock.ts +47 -0
  54. package/components/features/PageLayout/PageLayout.tsx +8 -5
  55. package/components/features/SpecNavigator/README.md +23 -3
  56. package/components/features/SpecNavigator/SpecNavigator.behaviors.stories.tsx +29 -11
  57. package/components/features/SpecNavigator/SpecNavigator.mocks.ts +35 -8
  58. package/components/features/SpecNavigator/SpecNavigator.stories.tsx +38 -36
  59. package/components/features/SpecNavigator/SpecNavigator.tsx +56 -3
  60. package/components/features/SpecNavigator/index.ts +5 -1
  61. package/components/features/SpecNavigator/useSpecNavigator.d.ts +2 -2
  62. package/components/features/SpecNavigator/useSpecNavigator.mock.ts +4 -4
  63. package/components/features/WorkflowBuilder/WorkflowBuilder.stories.tsx +45 -39
  64. package/components/features/WorkflowBuilder/WorkflowBuilder.tsx +6 -2
  65. package/components/features/WorkflowObservabilityFeature/README.md +114 -0
  66. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.behaviors.stories.tsx +177 -0
  67. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.mocks.ts +145 -0
  68. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.stories.tsx +66 -0
  69. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.tsx +162 -0
  70. package/components/features/WorkflowObservabilityFeature/index.ts +7 -0
  71. package/components/features/WorkflowObservabilityFeature/useWorkflowObservabilityFeature.d.ts +25 -0
  72. package/components/features/WorkflowObservabilityFeature/useWorkflowObservabilityFeature.mock.ts +238 -0
  73. package/components/features/index.ts +12 -0
  74. package/components/ui/chart.tsx +3 -3
  75. package/components/ui/drawer.tsx +6 -2
  76. package/components/ui/input-group.tsx +1 -1
  77. package/components/ui/input.tsx +1 -1
  78. package/dist/index.cjs +2471 -203
  79. package/dist/index.cjs.map +1 -1
  80. package/dist/index.css +625 -16
  81. package/dist/index.d.ts +150 -2
  82. package/dist/index.js +2463 -205
  83. package/dist/index.js.map +1 -1
  84. package/package.json +16 -3
@@ -17,9 +17,19 @@ import { NavUser } from "@/components/composites/NavUser"
17
17
  import type { AppSidebarProps } from "./interfaces"
18
18
 
19
19
  export const AppSidebar = React.memo<AppSidebarProps>(
20
- ({ logo, mainNavigation, secondaryNavigation, documents, user, userActions, ...props }) => {
20
+ ({
21
+ logo,
22
+ mainNavigation,
23
+ secondaryNavigation,
24
+ documents,
25
+ user,
26
+ userActions,
27
+ variant = "inset",
28
+ collapsible = "offcanvas",
29
+ ...props
30
+ }) => {
21
31
  return (
22
- <Sidebar {...props} variant="inset" collapsible="offcanvas">
32
+ <Sidebar {...props} variant={variant} collapsible={collapsible}>
23
33
  <SidebarHeader>
24
34
  {logo && (
25
35
  <SidebarMenu>
@@ -1,4 +1,5 @@
1
1
  import type { NavigationItem } from "@/components/composites/NavigationList/interfaces";
2
+ import type { SidebarProps } from "@/components/primitives/Sidebar";
2
3
 
3
4
  export interface AppSidebarProps {
4
5
  logo?: {
@@ -14,6 +15,8 @@ export interface AppSidebarProps {
14
15
  email: string;
15
16
  avatar?: string;
16
17
  };
18
+ variant?: SidebarProps["variant"];
19
+ collapsible?: SidebarProps["collapsible"];
17
20
  userActions?: { label: string; onClick: () => void }[];
18
21
  className?: string;
19
22
  }
@@ -0,0 +1,182 @@
1
+ import * as React from "react"
2
+ import { Area, AreaChart, CartesianGrid, XAxis } from "recharts"
3
+
4
+ import {
5
+ ChartContainer,
6
+ ChartTooltip,
7
+ ChartTooltipContent,
8
+ } from "@/components/primitives/Chart"
9
+ import {
10
+ Card,
11
+ CardAction,
12
+ CardContent,
13
+ CardDescription,
14
+ CardHeader,
15
+ CardTitle,
16
+ } from "@/components/primitives/Card"
17
+ import {
18
+ Select,
19
+ SelectContent,
20
+ SelectItem,
21
+ SelectTrigger,
22
+ SelectValue,
23
+ } from "@/components/primitives/Select"
24
+ import { ToggleGroup, ToggleGroupItem } from "@/components/primitives/ToggleGroup"
25
+
26
+ export interface DashboardChartPoint {
27
+ date: string
28
+ desktop: number
29
+ mobile: number
30
+ }
31
+
32
+ export type DashboardChartTimeRange = "90d" | "30d" | "7d"
33
+
34
+ export interface DashboardChartProps {
35
+ series: DashboardChartPoint[]
36
+ onTimeRangeChange?: (range: DashboardChartTimeRange) => void
37
+ }
38
+
39
+ export const DashboardChart = React.memo<DashboardChartProps>(({ series, onTimeRangeChange }) => {
40
+ const [timeRange, setTimeRange] = React.useState<DashboardChartTimeRange>("90d")
41
+
42
+ const handleTimeRangeChange = React.useCallback(
43
+ (range: DashboardChartTimeRange) => {
44
+ setTimeRange(range)
45
+ onTimeRangeChange?.(range)
46
+ },
47
+ [onTimeRangeChange]
48
+ )
49
+
50
+ const filteredSeries = React.useMemo(() => {
51
+ const referenceDate = series.length > 0 ? new Date(series[series.length - 1].date) : new Date()
52
+ let daysToSubtract = 90
53
+
54
+ if (timeRange === "30d") {
55
+ daysToSubtract = 30
56
+ } else if (timeRange === "7d") {
57
+ daysToSubtract = 7
58
+ }
59
+
60
+ const startDate = new Date(referenceDate)
61
+ startDate.setDate(startDate.getDate() - daysToSubtract)
62
+
63
+ return series.filter((point) => new Date(point.date) >= startDate)
64
+ }, [series, timeRange])
65
+
66
+ return (
67
+ <section className="px-4 lg:px-6">
68
+ <Card className="@container/card">
69
+ <CardHeader>
70
+ <CardTitle>Total Visitors</CardTitle>
71
+ <CardDescription>
72
+ <span className="hidden @[540px]/card:block">Total for the last 3 months</span>
73
+ <span className="@[540px]/card:hidden">Last 3 months</span>
74
+ </CardDescription>
75
+ <CardAction>
76
+ <ToggleGroup
77
+ type="single"
78
+ value={timeRange}
79
+ onValueChange={(value) => {
80
+ if (value) {
81
+ handleTimeRangeChange(value as DashboardChartTimeRange)
82
+ }
83
+ }}
84
+ variant="outline"
85
+ className="hidden *:data-[slot=toggle-group-item]:px-4! @[767px]/card:flex"
86
+ >
87
+ <ToggleGroupItem value="90d">Last 3 months</ToggleGroupItem>
88
+ <ToggleGroupItem value="30d">Last 30 days</ToggleGroupItem>
89
+ <ToggleGroupItem value="7d">Last 7 days</ToggleGroupItem>
90
+ </ToggleGroup>
91
+ <Select value={timeRange} onValueChange={(value) => handleTimeRangeChange(value as DashboardChartTimeRange)}>
92
+ <SelectTrigger
93
+ className="flex w-40 **:data-[slot=select-value]:block **:data-[slot=select-value]:truncate @[767px]/card:hidden"
94
+ aria-label="Select a value"
95
+ >
96
+ <SelectValue placeholder="Last 3 months" />
97
+ </SelectTrigger>
98
+ <SelectContent className="rounded-xl">
99
+ <SelectItem value="90d" className="rounded-lg">
100
+ Last 3 months
101
+ </SelectItem>
102
+ <SelectItem value="30d" className="rounded-lg">
103
+ Last 30 days
104
+ </SelectItem>
105
+ <SelectItem value="7d" className="rounded-lg">
106
+ Last 7 days
107
+ </SelectItem>
108
+ </SelectContent>
109
+ </Select>
110
+ </CardAction>
111
+ </CardHeader>
112
+ <CardContent className="px-2 pt-4 sm:px-6 sm:pt-6">
113
+ <ChartContainer
114
+ config={{
115
+ desktop: { label: "Desktop", color: "var(--primary)" },
116
+ mobile: { label: "Mobile", color: "var(--primary)" },
117
+ }}
118
+ className="aspect-auto h-[250px] w-full"
119
+ >
120
+ <AreaChart data={filteredSeries}>
121
+ <defs>
122
+ <linearGradient id="fillDesktop" x1="0" y1="0" x2="0" y2="1">
123
+ <stop offset="5%" stopColor="var(--color-desktop)" stopOpacity={1} />
124
+ <stop offset="95%" stopColor="var(--color-desktop)" stopOpacity={0.1} />
125
+ </linearGradient>
126
+ <linearGradient id="fillMobile" x1="0" y1="0" x2="0" y2="1">
127
+ <stop offset="5%" stopColor="var(--color-mobile)" stopOpacity={0.8} />
128
+ <stop offset="95%" stopColor="var(--color-mobile)" stopOpacity={0.1} />
129
+ </linearGradient>
130
+ </defs>
131
+ <CartesianGrid vertical={false} />
132
+ <XAxis
133
+ dataKey="date"
134
+ tickLine={false}
135
+ axisLine={false}
136
+ tickMargin={8}
137
+ minTickGap={32}
138
+ tickFormatter={(value) => {
139
+ const date = new Date(value)
140
+ return date.toLocaleDateString("en-US", {
141
+ month: "short",
142
+ day: "numeric",
143
+ })
144
+ }}
145
+ />
146
+ <ChartTooltip
147
+ cursor={false}
148
+ content={
149
+ <ChartTooltipContent
150
+ labelFormatter={(value) => {
151
+ return new Date(String(value)).toLocaleDateString("en-US", {
152
+ month: "short",
153
+ day: "numeric",
154
+ })
155
+ }}
156
+ indicator="dot"
157
+ />
158
+ }
159
+ />
160
+ <Area
161
+ dataKey="mobile"
162
+ type="natural"
163
+ fill="url(#fillMobile)"
164
+ stroke="var(--color-mobile)"
165
+ stackId="a"
166
+ />
167
+ <Area
168
+ dataKey="desktop"
169
+ type="natural"
170
+ fill="url(#fillDesktop)"
171
+ stroke="var(--color-desktop)"
172
+ stackId="a"
173
+ />
174
+ </AreaChart>
175
+ </ChartContainer>
176
+ </CardContent>
177
+ </Card>
178
+ </section>
179
+ )
180
+ })
181
+
182
+ DashboardChart.displayName = "DashboardChart"
@@ -0,0 +1,2 @@
1
+ export { DashboardChart } from './DashboardChart'
2
+ export type { DashboardChartProps } from './DashboardChart'
@@ -0,0 +1,20 @@
1
+ import * as React from "react"
2
+
3
+ import { Button } from "@/components/primitives/Button"
4
+
5
+ export interface DashboardHeaderProps {
6
+ ctaLabel?: string
7
+ }
8
+
9
+ export const DashboardHeader = React.memo<DashboardHeaderProps>(({ ctaLabel = "Quick Create" }) => {
10
+ return (
11
+ <>
12
+ <Button variant="outline" size="sm" className="hidden sm:flex">
13
+ {ctaLabel}
14
+ </Button>
15
+ <div className="text-xs text-muted-foreground">GitHub</div>
16
+ </>
17
+ )
18
+ })
19
+
20
+ DashboardHeader.displayName = "DashboardHeader"
@@ -0,0 +1,2 @@
1
+ export { DashboardHeader } from './DashboardHeader'
2
+ export type { DashboardHeaderProps } from './DashboardHeader'
@@ -0,0 +1,41 @@
1
+ import * as React from "react"
2
+
3
+ import { StatsCard } from "@/components/composites/StatsCard"
4
+
5
+ export interface DashboardMetricItem {
6
+ title: string
7
+ value: string | number
8
+ trend?: {
9
+ direction: "up" | "down"
10
+ value: string
11
+ }
12
+ footer?: {
13
+ message: string
14
+ description: string
15
+ }
16
+ }
17
+
18
+ export interface DashboardMetricsProps {
19
+ items: DashboardMetricItem[]
20
+ }
21
+
22
+ export const DashboardMetrics = React.memo<DashboardMetricsProps>(({ items }) => {
23
+ return (
24
+ <section className="px-4 lg:px-6">
25
+ <div className="flex gap-4 overflow-x-auto pb-1 [scrollbar-width:thin]">
26
+ {items.map((item) => (
27
+ <StatsCard
28
+ key={item.title}
29
+ title={item.title}
30
+ value={item.value}
31
+ trend={item.trend}
32
+ footer={item.footer}
33
+ className="@container/card basis-[calc((100%-3rem)/4)] min-w-[240px] shrink-0"
34
+ />
35
+ ))}
36
+ </div>
37
+ </section>
38
+ )
39
+ })
40
+
41
+ DashboardMetrics.displayName = "DashboardMetrics"
@@ -0,0 +1,2 @@
1
+ export { DashboardMetrics } from './DashboardMetrics'
2
+ export type { DashboardMetricsProps } from './DashboardMetrics'
@@ -0,0 +1,42 @@
1
+ import * as React from "react"
2
+ import { Plus } from "lucide-react"
3
+
4
+ import {
5
+ EnhancedDataTable,
6
+ type DashboardRow,
7
+ type DashboardTableActionHandlers,
8
+ } from "@/components/composites/DataTable"
9
+ import type { DynamicTableSchema } from "ui-schema-contracts"
10
+ import { Button } from "@/components/primitives/Button"
11
+
12
+ export interface DataTableProps {
13
+ rows: DashboardRow[]
14
+ tableSchema: DynamicTableSchema
15
+ handlers?: DashboardTableActionHandlers
16
+ onCreateClick?: () => void
17
+ createButtonLabel?: string
18
+ }
19
+
20
+ export const DataTable = React.memo<DataTableProps>(({ rows, tableSchema, handlers, onCreateClick, createButtonLabel }) => {
21
+ return (
22
+ <section className="px-4 lg:px-6">
23
+ <EnhancedDataTable
24
+ data={rows}
25
+ tableSchema={tableSchema}
26
+ handlers={handlers}
27
+ onCreateClick={onCreateClick ?? handlers?.onCreateClick ?? handlers?.onAddSection}
28
+ createButtonLabel={createButtonLabel}
29
+ rightActions={
30
+ handlers?.onAddSection ? (
31
+ <Button variant="outline" size="sm" className="h-8" onClick={handlers.onAddSection}>
32
+ <Plus className="size-4" />
33
+ <span className="hidden lg:inline">Add Section</span>
34
+ </Button>
35
+ ) : null
36
+ }
37
+ />
38
+ </section>
39
+ )
40
+ })
41
+
42
+ DataTable.displayName = "DataTable"
@@ -0,0 +1,2 @@
1
+ export { DataTable } from './DataTable'
2
+ export type { DataTableProps } from './DataTable'
@@ -0,0 +1,46 @@
1
+ import * as React from "react"
2
+ import {
3
+ FormReportsTable,
4
+ type FormReportsColumn,
5
+ type FormReportsEntity,
6
+ type FormReportsRowAction,
7
+ type FormReportsTableHandlers,
8
+ } from "@/components/composites/FormReports"
9
+
10
+ export interface FormReportsSectionProps {
11
+ onCreateClick?: () => void
12
+ createButtonLabel?: string
13
+ items: FormReportsEntity[]
14
+ columns: FormReportsColumn[]
15
+ rowActions?: FormReportsRowAction[]
16
+ tableHandlers?: FormReportsTableHandlers
17
+ tableLeftActions?: React.ReactNode
18
+ }
19
+
20
+ export const FormReportsSection = React.memo<FormReportsSectionProps>(
21
+ ({
22
+ onCreateClick,
23
+ createButtonLabel = "Create",
24
+ items,
25
+ columns,
26
+ rowActions,
27
+ tableHandlers,
28
+ tableLeftActions,
29
+ }) => {
30
+ return (
31
+ <section>
32
+ <FormReportsTable
33
+ items={items}
34
+ columns={columns}
35
+ rowActions={rowActions}
36
+ handlers={tableHandlers}
37
+ leftActions={tableLeftActions}
38
+ onCreateClick={onCreateClick}
39
+ createButtonLabel={createButtonLabel}
40
+ />
41
+ </section>
42
+ )
43
+ }
44
+ )
45
+
46
+ FormReportsSection.displayName = "FormReportsSection"
@@ -0,0 +1,2 @@
1
+ export { FormReportsSection } from "./FormReportsSection"
2
+ export type { FormReportsSectionProps } from "./FormReportsSection"
@@ -26,11 +26,11 @@ export const SectionLayout = React.memo<SectionLayoutProps>(
26
26
  const transformedSections = sections.map(section => ({
27
27
  ...section,
28
28
  content: (
29
- <div className="h-full flex flex-col">
29
+ <div className="h-full min-h-0 flex flex-col">
30
30
  {section.header && (
31
31
  <AppHeader {...section.header} />
32
32
  )}
33
- <div className="flex-1">
33
+ <div className="min-h-0 flex-1">
34
34
  {section.content}
35
35
  </div>
36
36
  </div>
@@ -17,3 +17,18 @@ export type { LayoutProviderProps } from './LayoutProvider'
17
17
 
18
18
  export { WorkflowCanvas } from './WorkflowCanvas'
19
19
  export type { WorkflowCanvasProps, WorkflowNode, WorkflowEdge, WorkflowNodeData } from './WorkflowCanvas'
20
+
21
+ export { DashboardHeader } from './DashboardHeader'
22
+ export type { DashboardHeaderProps } from './DashboardHeader'
23
+
24
+ export { DashboardMetrics } from './DashboardMetrics'
25
+ export type { DashboardMetricsProps } from './DashboardMetrics'
26
+
27
+ export { DashboardChart } from './DashboardChart'
28
+ export type { DashboardChartProps } from './DashboardChart'
29
+
30
+ export { DataTable } from './DataTable'
31
+ export type { DataTableProps } from './DataTable'
32
+
33
+ export { FormReportsSection } from './FormReportsSection'
34
+ export type { FormReportsSectionProps } from './FormReportsSection'
@@ -175,11 +175,12 @@ export const AdjustableLayout = React.memo<AdjustableLayoutProps>(
175
175
  <React.Fragment key={section.id}>
176
176
  <div
177
177
  className={cn(
178
- "h-full overflow-hidden bg-card border border-border rounded-md",
178
+ "min-h-0 overflow-hidden bg-card border border-border rounded-md",
179
179
  section.className
180
180
  )}
181
181
  style={{
182
182
  flex: `${size} 1 0%`,
183
+ minHeight: 0,
183
184
  minWidth: 0,
184
185
  }}
185
186
  >
@@ -0,0 +1,25 @@
1
+ import { useSortable } from "@dnd-kit/sortable"
2
+ import { GripVertical } from "lucide-react"
3
+
4
+ import { Button } from "@/components/primitives/Button"
5
+
6
+ export interface DragHandleCellProps {
7
+ id: number | string
8
+ }
9
+
10
+ export function DragHandleCell({ id }: DragHandleCellProps) {
11
+ const { attributes, listeners } = useSortable({ id })
12
+
13
+ return (
14
+ <Button
15
+ {...attributes}
16
+ {...listeners}
17
+ variant="ghost"
18
+ size="icon"
19
+ className="size-7 text-muted-foreground hover:bg-transparent"
20
+ aria-label="Drag to reorder"
21
+ >
22
+ <GripVertical className="size-3" />
23
+ </Button>
24
+ )
25
+ }
@@ -0,0 +1,35 @@
1
+ import { useSortable } from "@dnd-kit/sortable"
2
+ import { CSS } from "@dnd-kit/utilities"
3
+ import { flexRender, type Row } from "@tanstack/react-table"
4
+
5
+ import { TableCell, TableRow } from "@/components/primitives/Table"
6
+ import type { DashboardRow } from "./table-types"
7
+
8
+ export interface DraggableRowProps {
9
+ row: Row<DashboardRow>
10
+ rowId: number | string
11
+ }
12
+
13
+ export function DraggableRow({ row, rowId }: DraggableRowProps) {
14
+ const { transform, transition, setNodeRef, isDragging } = useSortable({
15
+ id: rowId,
16
+ })
17
+
18
+ return (
19
+ <TableRow
20
+ ref={setNodeRef}
21
+ data-row-id={String(rowId)}
22
+ data-state={row.getIsSelected() && "selected"}
23
+ data-dragging={isDragging}
24
+ className="relative z-0 data-[dragging=true]:z-10 data-[dragging=true]:opacity-80"
25
+ style={{
26
+ transform: CSS.Transform.toString(transform),
27
+ transition,
28
+ }}
29
+ >
30
+ {row.getVisibleCells().map((cell) => (
31
+ <TableCell key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>
32
+ ))}
33
+ </TableRow>
34
+ )
35
+ }
@@ -0,0 +1,60 @@
1
+ import type { Meta, StoryObj } from "@storybook/nextjs-vite"
2
+ import { expect, userEvent, within } from "@storybook/test"
3
+ import { Toaster } from "sonner"
4
+
5
+ import { EnhancedDataTable } from "./EnhancedDataTable"
6
+ import type { DashboardRow } from "./table-types"
7
+
8
+ const rows: DashboardRow[] = [
9
+ { id: 1, header: "Cover page", type: "Cover page", status: "In Process", target: "18", limit: "5", reviewer: "Eddie Lake" },
10
+ { id: 2, header: "Table of contents", type: "Table of contents", status: "Done", target: "29", limit: "24", reviewer: "Assign reviewer" },
11
+ { id: 3, header: "Executive summary", type: "Narrative", status: "Done", target: "10", limit: "13", reviewer: "Assign reviewer" },
12
+ ]
13
+
14
+ const meta = {
15
+ title: "Composites/EnhancedDataTable/Behaviors",
16
+ component: EnhancedDataTable,
17
+ tags: ["test"],
18
+ parameters: {
19
+ layout: "fullscreen",
20
+ },
21
+ render: (args) => (
22
+ <>
23
+ <EnhancedDataTable {...args} />
24
+ <Toaster position="bottom-right" />
25
+ </>
26
+ ),
27
+ } satisfies Meta<typeof EnhancedDataTable>
28
+
29
+ export default meta
30
+ type Story = StoryObj<typeof meta>
31
+
32
+ export const SelectAllWorks: Story = {
33
+ args: { data: rows },
34
+ play: async ({ canvasElement }) => {
35
+ const canvas = within(canvasElement)
36
+ const selectAll = canvas.getByLabelText("Select all")
37
+ await userEvent.click(selectAll)
38
+ await expect(selectAll).toBeChecked()
39
+ },
40
+ }
41
+
42
+ export const DrawerOpensFromHeader: Story = {
43
+ args: { data: rows },
44
+ play: async ({ canvasElement }) => {
45
+ const canvas = within(canvasElement)
46
+ const trigger = canvas.getByRole("button", { name: "Cover page" })
47
+ await userEvent.click(trigger)
48
+ await expect(await canvas.findByText("Showing total visitors for the last 6 months")).toBeInTheDocument()
49
+ },
50
+ }
51
+
52
+ export const SwitchesViewTab: Story = {
53
+ args: { data: rows },
54
+ play: async ({ canvasElement }) => {
55
+ const canvas = within(canvasElement)
56
+ const tab = canvas.getByRole("tab", { name: /Past Performance/i })
57
+ await userEvent.click(tab)
58
+ await expect(canvas.getByRole("tabpanel")).toBeInTheDocument()
59
+ },
60
+ }
@@ -0,0 +1,42 @@
1
+ import type { Meta, StoryObj } from "@storybook/nextjs-vite"
2
+ import { Toaster } from "sonner"
3
+
4
+ import { EnhancedDataTable } from "./EnhancedDataTable"
5
+ import type { DashboardRow } from "./table-types"
6
+
7
+ const data: DashboardRow[] = [
8
+ { id: 1, header: "Cover page", type: "Cover page", status: "In Process", target: "18", limit: "5", reviewer: "Eddie Lake" },
9
+ { id: 2, header: "Table of contents", type: "Table of contents", status: "Done", target: "29", limit: "24", reviewer: "Eddie Lake" },
10
+ { id: 3, header: "Executive summary", type: "Narrative", status: "Done", target: "10", limit: "13", reviewer: "Eddie Lake" },
11
+ { id: 4, header: "Technical approach", type: "Narrative", status: "Done", target: "27", limit: "23", reviewer: "Jamik Tashpulatov" },
12
+ { id: 5, header: "Design", type: "Narrative", status: "In Process", target: "2", limit: "16", reviewer: "Jamik Tashpulatov" },
13
+ { id: 6, header: "Capabilities", type: "Narrative", status: "In Process", target: "20", limit: "8", reviewer: "Jamik Tashpulatov" },
14
+ { id: 7, header: "Integration with existing systems", type: "Narrative", status: "In Process", target: "19", limit: "21", reviewer: "Assign reviewer" },
15
+ { id: 8, header: "Innovation and Advantages", type: "Narrative", status: "Done", target: "25", limit: "26", reviewer: "Assign reviewer" },
16
+ { id: 9, header: "Overview of EMR's Innovative Solutions", type: "Technical content", status: "Done", target: "7", limit: "23", reviewer: "Assign reviewer" },
17
+ { id: 10, header: "Advanced Algorithms and Machine Learning", type: "Narrative", status: "Done", target: "30", limit: "28", reviewer: "Assign reviewer" },
18
+ { id: 11, header: "Adaptive Communication Protocols", type: "Narrative", status: "Done", target: "9", limit: "31", reviewer: "Assign reviewer" },
19
+ { id: 12, header: "Advantages Over Current Technologies", type: "Narrative", status: "Not Started", target: "12", limit: "0", reviewer: "Assign reviewer" },
20
+ ]
21
+
22
+ const meta = {
23
+ title: "Composites/EnhancedDataTable",
24
+ component: EnhancedDataTable,
25
+ tags: ["autodocs"],
26
+ parameters: { layout: "fullscreen" },
27
+ render: (args) => (
28
+ <>
29
+ <EnhancedDataTable {...args} />
30
+ <Toaster position="bottom-right" />
31
+ </>
32
+ ),
33
+ } satisfies Meta<typeof EnhancedDataTable>
34
+
35
+ export default meta
36
+ type Story = StoryObj<typeof meta>
37
+
38
+ export const Default: Story = {
39
+ args: {
40
+ data,
41
+ },
42
+ }