ai-design-system 0.1.32 → 0.1.34

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 (86) hide show
  1. package/components/ai-elements/edge.tsx +93 -42
  2. package/components/ai-elements/node.tsx +1 -1
  3. package/components/blocks/DataTable/DataTable.tsx +1 -4
  4. package/components/blocks/FormReportsSection/FormReportsSection.tsx +0 -4
  5. package/components/blocks/SectionLayout/SectionLayout.stories.tsx +0 -106
  6. package/components/blocks/SectionLayout/SectionLayout.tsx +2 -4
  7. package/components/blocks/SectionLayout/interfaces.ts +0 -2
  8. package/components/blocks/WorkflowCanvas/WorkflowCanvas.tsx +0 -1
  9. package/components/blocks/index.ts +0 -3
  10. package/components/composites/AdjustableLayout/AdjustableLayout.tsx +3 -17
  11. package/components/composites/AppHeader/AppHeader.tsx +9 -15
  12. package/components/composites/DataTable/DragHandleCell.tsx +1 -1
  13. package/components/composites/DataTable/DraggableRow.tsx +2 -4
  14. package/components/composites/DataTable/EnhancedDataTable.behaviors.stories.tsx +3 -20
  15. package/components/composites/DataTable/EnhancedDataTable.stories.tsx +0 -18
  16. package/components/composites/DataTable/EnhancedDataTable.tsx +131 -336
  17. package/components/composites/DataTable/index.ts +0 -1
  18. package/components/composites/DataTable/table-types.ts +12 -17
  19. package/components/composites/DataTable/useEnhancedDataTable.ts +9 -30
  20. package/components/composites/FormReports/FormReportsDrawerForm.tsx +16 -10
  21. package/components/composites/FormReports/FormReportsTable.tsx +56 -96
  22. package/components/composites/FormReports/index.ts +0 -1
  23. package/components/composites/ModeSwitcher/ModeSwitcher.tsx +62 -0
  24. package/components/composites/ModeSwitcher/index.ts +2 -0
  25. package/components/composites/StateNode/StateNode.tsx +5 -8
  26. package/components/composites/TransitionNode/TransitionNode.tsx +5 -7
  27. package/components/composites/index.ts +4 -24
  28. package/components/features/DashboardFeature/DashboardFeature.mocks.ts +0 -158
  29. package/components/features/DashboardFeature/DashboardFeature.stories.tsx +0 -6
  30. package/components/features/DashboardFeature/DashboardFeature.tsx +49 -6
  31. package/components/features/DashboardFeature/useDashboardFeature.d.ts +1 -3
  32. package/components/features/DashboardFeature/useDashboardFeature.mock.ts +1 -34
  33. package/components/features/FormReportsFeature/FormReportsFeature.mocks.ts +54 -155
  34. package/components/features/FormReportsFeature/FormReportsFeature.tsx +16 -29
  35. package/components/features/FormReportsFeature/useFormReportsFeature.d.ts +0 -2
  36. package/components/features/FormReportsFeature/useFormReportsFeature.mock.ts +0 -5
  37. package/components/features/PageLayout/PageLayout.mocks.ts +0 -27
  38. package/components/features/PageLayout/PageLayout.stories.tsx +51 -31
  39. package/components/features/PageLayout/PageLayout.tsx +19 -54
  40. package/components/features/PageLayout/usePageLayout.d.ts +0 -4
  41. package/components/features/PageLayout/usePageLayout.mock.ts +1 -64
  42. package/components/features/RefinementPanel/RefinementPanel.stories.tsx +2 -2
  43. package/components/features/RefinementPanel/useRefinementPanel.mock.ts +0 -8
  44. package/components/features/SpecNavigator/README.md +3 -23
  45. package/components/features/SpecNavigator/SpecNavigator.behaviors.stories.tsx +11 -29
  46. package/components/features/SpecNavigator/SpecNavigator.mocks.ts +8 -35
  47. package/components/features/SpecNavigator/SpecNavigator.stories.tsx +36 -38
  48. package/components/features/SpecNavigator/SpecNavigator.tsx +3 -56
  49. package/components/features/SpecNavigator/index.ts +1 -5
  50. package/components/features/SpecNavigator/useSpecNavigator.d.ts +2 -2
  51. package/components/features/SpecNavigator/useSpecNavigator.mock.ts +4 -4
  52. package/components/features/WorkflowBuilder/WorkflowBuilder.stories.tsx +39 -45
  53. package/components/features/WorkflowBuilder/WorkflowBuilder.tsx +2 -6
  54. package/components/features/index.ts +0 -5
  55. package/components/index.ts +14 -7
  56. package/components/ui/chart.tsx +3 -3
  57. package/components/ui/input-group.tsx +1 -1
  58. package/components/ui/input.tsx +1 -1
  59. package/dist/index.cjs +6312 -6855
  60. package/dist/index.cjs.map +1 -1
  61. package/dist/index.css +32 -393
  62. package/dist/index.d.ts +163 -278
  63. package/dist/index.js +6066 -6826
  64. package/dist/index.js.map +1 -1
  65. package/package.json +1 -3
  66. package/components/blocks/InboxPanel/InboxPanel.stories.tsx +0 -48
  67. package/components/blocks/InboxPanel/InboxPanel.tsx +0 -55
  68. package/components/blocks/InboxPanel/index.ts +0 -2
  69. package/components/composites/FilePreviewDialog/FilePreviewDialog.tsx +0 -150
  70. package/components/composites/FilePreviewDialog/index.ts +0 -2
  71. package/components/composites/InboxList/InboxList.stories.tsx +0 -45
  72. package/components/composites/InboxList/InboxList.tsx +0 -99
  73. package/components/composites/InboxList/index.ts +0 -2
  74. package/components/composites/LoadingShimmer/LoadingShimmer.tsx +0 -24
  75. package/components/composites/LoadingShimmer/index.ts +0 -2
  76. package/components/composites/LoadingShimmer/interfaces.ts +0 -4
  77. package/components/composites/WorkflowRunObservabilityPanel/WorkflowRunObservabilityPanel.tsx +0 -549
  78. package/components/composites/WorkflowRunObservabilityPanel/index.ts +0 -17
  79. package/components/features/WorkflowObservabilityFeature/README.md +0 -114
  80. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.behaviors.stories.tsx +0 -206
  81. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.mocks.ts +0 -165
  82. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.stories.tsx +0 -151
  83. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.tsx +0 -227
  84. package/components/features/WorkflowObservabilityFeature/index.ts +0 -7
  85. package/components/features/WorkflowObservabilityFeature/useWorkflowObservabilityFeature.d.ts +0 -37
  86. package/components/features/WorkflowObservabilityFeature/useWorkflowObservabilityFeature.mock.ts +0 -286
@@ -1,8 +1,12 @@
1
1
  import {
2
2
  BaseEdge,
3
3
  type EdgeProps,
4
+ getBezierPath,
4
5
  getSimpleBezierPath,
5
- getSmoothStepPath,
6
+ type InternalNode,
7
+ type Node,
8
+ Position,
9
+ useInternalNode,
6
10
  } from "@xyflow/react";
7
11
 
8
12
  const Temporary = ({
@@ -35,49 +39,97 @@ const Temporary = ({
35
39
  );
36
40
  };
37
41
 
38
- const Strict = ({
39
- id,
40
- sourceX,
41
- sourceY,
42
- targetX,
43
- targetY,
44
- sourcePosition,
45
- targetPosition,
46
- markerEnd,
47
- style,
48
- }: EdgeProps) => {
49
- const [edgePath] = getSmoothStepPath({
50
- sourceX,
51
- sourceY,
52
- sourcePosition,
53
- targetX,
54
- targetY,
55
- targetPosition,
56
- borderRadius: 0,
57
- });
42
+ const getHandleCoordsByPosition = (
43
+ node: InternalNode<Node>,
44
+ handlePosition: Position,
45
+ handleType: "source" | "target"
46
+ ) => {
47
+ const handle = node.internals.handleBounds?.[handleType]?.find(
48
+ (h) => h.position === handlePosition
49
+ );
50
+
51
+ if (!handle) {
52
+ return [0, 0] as const;
53
+ }
54
+
55
+ let offsetX = handle.width / 2;
56
+ let offsetY = handle.height / 2;
58
57
 
59
- return <BaseEdge id={id} markerEnd={markerEnd} path={edgePath} style={style} />;
58
+ switch (handlePosition) {
59
+ case Position.Left:
60
+ offsetX = 0;
61
+ break;
62
+ case Position.Right:
63
+ offsetX = handle.width;
64
+ break;
65
+ case Position.Top:
66
+ offsetY = 0;
67
+ break;
68
+ case Position.Bottom:
69
+ offsetY = handle.height;
70
+ break;
71
+ default:
72
+ throw new Error(`Invalid handle position: ${handlePosition}`);
73
+ }
74
+
75
+ const x = node.internals.positionAbsolute.x + handle.x + offsetX;
76
+ const y = node.internals.positionAbsolute.y + handle.y + offsetY;
77
+
78
+ return [x, y] as const;
60
79
  };
61
80
 
62
- const Animated = ({
63
- id,
64
- sourceX,
65
- sourceY,
66
- targetX,
67
- targetY,
68
- sourcePosition,
69
- targetPosition,
70
- markerEnd,
71
- style,
72
- }: EdgeProps) => {
73
- const [edgePath] = getSmoothStepPath({
74
- sourceX,
75
- sourceY,
76
- sourcePosition,
77
- targetX,
78
- targetY,
79
- targetPosition,
80
- borderRadius: 0,
81
+ const getEdgeParams = (
82
+ source: InternalNode<Node>,
83
+ target: InternalNode<Node>
84
+ ) => {
85
+ const sx = source.internals.positionAbsolute.x + (source.measured?.width ?? 0) / 2;
86
+ const sy = source.internals.positionAbsolute.y + (source.measured?.height ?? 0) / 2;
87
+ const tx = target.internals.positionAbsolute.x + (target.measured?.width ?? 0) / 2;
88
+ const ty = target.internals.positionAbsolute.y + (target.measured?.height ?? 0) / 2;
89
+
90
+ const dx = tx - sx;
91
+ const dy = ty - sy;
92
+
93
+ // Pick source/target positions based on dominant direction
94
+ let sourcePos: Position;
95
+ let targetPos: Position;
96
+
97
+ if (Math.abs(dx) > Math.abs(dy)) {
98
+ // Horizontal dominant
99
+ sourcePos = dx > 0 ? Position.Right : Position.Left;
100
+ targetPos = dx > 0 ? Position.Left : Position.Right;
101
+ } else {
102
+ // Vertical dominant
103
+ sourcePos = dy > 0 ? Position.Bottom : Position.Top;
104
+ targetPos = dy > 0 ? Position.Top : Position.Bottom;
105
+ }
106
+
107
+ const [srcX, srcY] = getHandleCoordsByPosition(source, sourcePos, "source");
108
+ const [tgtX, tgtY] = getHandleCoordsByPosition(target, targetPos, "target");
109
+
110
+ return { sx: srcX, sy: srcY, tx: tgtX, ty: tgtY, sourcePos, targetPos };
111
+ };
112
+
113
+ const Animated = ({ id, source, target, markerEnd, style }: EdgeProps) => {
114
+ const sourceNode = useInternalNode(source);
115
+ const targetNode = useInternalNode(target);
116
+
117
+ if (!(sourceNode && targetNode)) {
118
+ return null;
119
+ }
120
+
121
+ const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(
122
+ sourceNode,
123
+ targetNode
124
+ );
125
+
126
+ const [edgePath] = getBezierPath({
127
+ sourceX: sx,
128
+ sourceY: sy,
129
+ sourcePosition: sourcePos,
130
+ targetX: tx,
131
+ targetY: ty,
132
+ targetPosition: targetPos,
81
133
  });
82
134
 
83
135
  return (
@@ -91,7 +143,6 @@ const Animated = ({
91
143
  };
92
144
 
93
145
  export const Edge = {
94
- Strict,
95
146
  Temporary,
96
147
  Animated,
97
148
  };
@@ -23,7 +23,7 @@ export type NodeProps = ComponentProps<typeof Card> & {
23
23
  export const Node = ({ handles, className, status, ...props }: NodeProps) => (
24
24
  <Card
25
25
  className={cn(
26
- "node-container relative h-[52px] w-[180px] gap-0 overflow-hidden rounded-md bg-card p-0 transition-all duration-200",
26
+ "node-container relative size-full h-auto w-sm gap-0 rounded-md bg-card p-0 transition-all duration-200",
27
27
  status === "success" && "border-green-500 border-2",
28
28
  status === "error" && "border-red-500 border-2",
29
29
  className
@@ -6,23 +6,20 @@ import {
6
6
  type DashboardRow,
7
7
  type DashboardTableActionHandlers,
8
8
  } from "@/components/composites/DataTable"
9
- import type { DynamicTableSchema } from "ui-schema-contracts"
10
9
  import { Button } from "@/components/primitives/Button"
11
10
 
12
11
  export interface DataTableProps {
13
12
  rows: DashboardRow[]
14
- tableSchema: DynamicTableSchema
15
13
  handlers?: DashboardTableActionHandlers
16
14
  onCreateClick?: () => void
17
15
  createButtonLabel?: string
18
16
  }
19
17
 
20
- export const DataTable = React.memo<DataTableProps>(({ rows, tableSchema, handlers, onCreateClick, createButtonLabel }) => {
18
+ export const DataTable = React.memo<DataTableProps>(({ rows, handlers, onCreateClick, createButtonLabel }) => {
21
19
  return (
22
20
  <section className="px-4 lg:px-6">
23
21
  <EnhancedDataTable
24
22
  data={rows}
25
- tableSchema={tableSchema}
26
23
  handlers={handlers}
27
24
  onCreateClick={onCreateClick ?? handlers?.onCreateClick ?? handlers?.onAddSection}
28
25
  createButtonLabel={createButtonLabel}
@@ -5,7 +5,6 @@ import {
5
5
  type FormReportsEntity,
6
6
  type FormReportsRowAction,
7
7
  type FormReportsTableHandlers,
8
- type DashboardPaginationState,
9
8
  } from "@/components/composites/FormReports"
10
9
 
11
10
  export interface FormReportsSectionProps {
@@ -14,7 +13,6 @@ export interface FormReportsSectionProps {
14
13
  items: FormReportsEntity[]
15
14
  columns: FormReportsColumn[]
16
15
  rowActions?: FormReportsRowAction[]
17
- pagination?: DashboardPaginationState
18
16
  tableHandlers?: FormReportsTableHandlers
19
17
  tableLeftActions?: React.ReactNode
20
18
  }
@@ -26,7 +24,6 @@ export const FormReportsSection = React.memo<FormReportsSectionProps>(
26
24
  items,
27
25
  columns,
28
26
  rowActions,
29
- pagination,
30
27
  tableHandlers,
31
28
  tableLeftActions,
32
29
  }) => {
@@ -36,7 +33,6 @@ export const FormReportsSection = React.memo<FormReportsSectionProps>(
36
33
  items={items}
37
34
  columns={columns}
38
35
  rowActions={rowActions}
39
- pagination={pagination}
40
36
  handlers={tableHandlers}
41
37
  leftActions={tableLeftActions}
42
38
  onCreateClick={onCreateClick}
@@ -1,32 +1,6 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react'
2
2
  import { SectionLayout } from './SectionLayout'
3
3
 
4
- function ScrollablePanelContent({
5
- description,
6
- items,
7
- title,
8
- }: {
9
- description: string
10
- items: string[]
11
- title: string
12
- }) {
13
- return (
14
- <div className="flex min-h-0 flex-col gap-3 rounded-lg border bg-muted p-4">
15
- <div>
16
- <h3 className="mb-1 font-medium">{title}</h3>
17
- <p className="text-sm text-muted-foreground">{description}</p>
18
- </div>
19
- <div className="grid gap-2">
20
- {items.map((item, index) => (
21
- <div key={`${title}-${index}`} className="rounded-md border bg-background px-3 py-2 text-sm">
22
- {item}
23
- </div>
24
- ))}
25
- </div>
26
- </div>
27
- )
28
- }
29
-
30
4
  /**
31
5
  * SectionLayout Block Stories
32
6
  *
@@ -300,83 +274,3 @@ export const AccentDragHandles: Story = {
300
274
  )
301
275
  },
302
276
  }
303
-
304
- /**
305
- * Independent Panel Scrolling
306
- *
307
- * Demonstrates that each panel owns its own vertical scroll region.
308
- */
309
- export const IndependentPanelScrolling: Story = {
310
- render: () => {
311
- const leftItems = Array.from({ length: 24 }, (_, index) => `Run record ${index + 1}`)
312
- const centerItems = Array.from({ length: 18 }, (_, index) => `Trace span ${index + 1}`)
313
- const rightItems = Array.from({ length: 20 }, (_, index) => `Details block ${index + 1}`)
314
-
315
- const sections = [
316
- {
317
- id: 'left-scroll-panel',
318
- content: (
319
- <ScrollablePanelContent
320
- title="Left Panel"
321
- description="Scroll this panel independently. The center and right panels should keep their own scroll positions."
322
- items={leftItems}
323
- />
324
- ),
325
- defaultSize: 25,
326
- minSize: 20,
327
- header: {
328
- tabs: [{ value: 'runs', label: 'runs' }],
329
- defaultTab: 'runs',
330
- showSidebarToggle: false,
331
- showTitle: false,
332
- },
333
- },
334
- {
335
- id: 'center-scroll-panel',
336
- content: (
337
- <ScrollablePanelContent
338
- title="Center Panel"
339
- description="This panel should keep a separate scrollbar from the left list and the right details column."
340
- items={centerItems}
341
- />
342
- ),
343
- defaultSize: 50,
344
- minSize: 35,
345
- header: {
346
- tabs: [{ value: 'trace', label: 'trace' }],
347
- defaultTab: 'trace',
348
- showSidebarToggle: false,
349
- showTitle: false,
350
- },
351
- },
352
- {
353
- id: 'right-scroll-panel',
354
- content: (
355
- <ScrollablePanelContent
356
- title="Right Panel"
357
- description="Use this to confirm the details panel can overflow and scroll without affecting the other panels."
358
- items={rightItems}
359
- />
360
- ),
361
- defaultSize: 25,
362
- minSize: 20,
363
- header: {
364
- tabs: [{ value: 'details', label: 'details' }],
365
- defaultTab: 'details',
366
- showSidebarToggle: false,
367
- showTitle: false,
368
- },
369
- },
370
- ]
371
-
372
- return (
373
- <div className="h-screen p-4">
374
- <SectionLayout
375
- sections={sections}
376
- storageKey="section-layout-independent-scroll"
377
- dragHandleColor="primary"
378
- />
379
- </div>
380
- )
381
- },
382
- }
@@ -18,7 +18,6 @@ export const SectionLayout = React.memo<SectionLayoutProps>(
18
18
  orientation = "horizontal",
19
19
  storageKey,
20
20
  onSectionResize,
21
- resizable = true,
22
21
  dragHandleColor = "border",
23
22
  className,
24
23
  ...props
@@ -26,13 +25,12 @@ export const SectionLayout = React.memo<SectionLayoutProps>(
26
25
  // Transform sections to include headers
27
26
  const transformedSections = sections.map(section => ({
28
27
  ...section,
29
- resizable,
30
28
  content: (
31
- <div className="h-full min-h-0 flex flex-col overflow-hidden">
29
+ <div className="h-full flex flex-col">
32
30
  {section.header && (
33
31
  <AppHeader {...section.header} />
34
32
  )}
35
- <div className="min-h-0 flex-1 overflow-auto [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden">
33
+ <div className="flex-1">
36
34
  {section.content}
37
35
  </div>
38
36
  </div>
@@ -4,7 +4,6 @@ import type { AppHeaderProps } from "@/components/composites/AppHeader/interface
4
4
  export interface SectionLayoutSection {
5
5
  id: string;
6
6
  content: React.ReactNode;
7
- fixedSize?: string;
8
7
  defaultSize?: number;
9
8
  minSize?: number;
10
9
  maxSize?: number;
@@ -18,6 +17,5 @@ export interface SectionLayoutProps extends React.ComponentPropsWithoutRef<"div"
18
17
  orientation?: "horizontal" | "vertical";
19
18
  storageKey?: string;
20
19
  onSectionResize?: (sectionId: string, newSize: number) => void;
21
- resizable?: boolean;
22
20
  dragHandleColor?: "primary" | "secondary" | "accent" | "border" | "muted";
23
21
  }
@@ -24,7 +24,6 @@ import type { WorkflowCanvasProps, WorkflowEdge } from "./interfaces";
24
24
  import "@xyflow/react/dist/style.css";
25
25
 
26
26
  const edgeTypes = {
27
- straight: Edge.Strict,
28
27
  animated: Edge.Animated,
29
28
  temporary: Edge.Temporary,
30
29
  };
@@ -32,6 +32,3 @@ export type { DataTableProps } from './DataTable'
32
32
 
33
33
  export { FormReportsSection } from './FormReportsSection'
34
34
  export type { FormReportsSectionProps } from './FormReportsSection'
35
-
36
- export { InboxPanel } from './InboxPanel'
37
- export type { InboxPanelProps } from './InboxPanel'
@@ -4,7 +4,6 @@ import { cn } from "@/lib/utils"
4
4
  export interface AdjustableLayoutSection {
5
5
  id: string
6
6
  content: React.ReactNode
7
- fixedSize?: string // CSS size value, e.g. "16rem"
8
7
  defaultSize?: number // percentage (0-100)
9
8
  minSize?: number // minimum percentage
10
9
  maxSize?: number // maximum percentage
@@ -169,31 +168,18 @@ export const AdjustableLayout = React.memo<AdjustableLayoutProps>(
169
168
  }, [draggingIndex, handleMouseMove, handleMouseUp])
170
169
 
171
170
  const renderPanel = (section: AdjustableLayoutSection, size: number, index: number) => {
172
- const nextSection = sections[index + 1]
173
171
  // Drag handles should be between panels, so only show for panels that aren't the last one
174
- const isResizable =
175
- section.resizable !== false &&
176
- sections.length > 1 &&
177
- index < sections.length - 1 &&
178
- !section.fixedSize &&
179
- !nextSection?.fixedSize
180
-
181
- const fixedStyle = section.fixedSize
182
- ? orientation === "horizontal"
183
- ? { flex: `0 0 ${section.fixedSize}`, width: section.fixedSize, minWidth: section.fixedSize }
184
- : { flex: `0 0 ${section.fixedSize}`, height: section.fixedSize, minHeight: section.fixedSize }
185
- : null
172
+ const isResizable = section.resizable !== false && sections.length > 1 && index < sections.length - 1
186
173
 
187
174
  return (
188
175
  <React.Fragment key={section.id}>
189
176
  <div
190
177
  className={cn(
191
- "min-h-0 overflow-hidden bg-card border border-border rounded-md",
178
+ "h-full overflow-hidden bg-card border border-border rounded-md",
192
179
  section.className
193
180
  )}
194
181
  style={{
195
- ...(fixedStyle ?? { flex: `${size} 1 0%` }),
196
- minHeight: 0,
182
+ flex: `${size} 1 0%`,
197
183
  minWidth: 0,
198
184
  }}
199
185
  >
@@ -16,17 +16,12 @@ export const AppHeader = React.memo<AppHeaderProps>(({
16
16
  }) => {
17
17
  return (
18
18
  <header className={`flex h-14 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-data-[collapsible=icon]/sidebar-wrapper:h-14 ${className || ""}`}>
19
- <div className="grid w-full grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center px-4 lg:px-6">
20
- <div className="min-w-0 flex items-center gap-1 lg:gap-2">
21
- {showSidebarToggle && <SidebarTrigger className="-ml-1" />}
22
- {showSidebarToggle && showTitle && title && (
23
- <Separator orientation="vertical" className="mx-2 data-[orientation=vertical]:h-4" />
24
- )}
25
- {showTitle && title && <h1 className="max-w-[28rem] truncate text-base font-medium">{title}</h1>}
26
- </div>
27
-
28
- <div className="justify-self-center">
29
- {tabs && tabs.length > 0 && (
19
+ <div className="flex w-full items-center gap-1 px-4 lg:gap-2 lg:px-6">
20
+ {showSidebarToggle && <SidebarTrigger className="-ml-1" />}
21
+ {showSidebarToggle && title && <Separator orientation="vertical" className="mx-2 data-[orientation=vertical]:h-4" />}
22
+ {showTitle && title && <h1 className="text-base font-medium">{title}</h1>}
23
+ {tabs && tabs.length > 0 && (
24
+ <div className="flex-1 flex justify-center">
30
25
  <Tabs defaultValue={defaultTab || tabs[0]?.value} onValueChange={onTabChange}>
31
26
  <TabsList>
32
27
  {tabs.map((tab) => (
@@ -36,10 +31,9 @@ export const AppHeader = React.memo<AppHeaderProps>(({
36
31
  ))}
37
32
  </TabsList>
38
33
  </Tabs>
39
- )}
40
- </div>
41
-
42
- <div className="flex min-w-0 items-center justify-end gap-2">{actions}</div>
34
+ </div>
35
+ )}
36
+ <div className="ml-auto flex items-center gap-2">{actions}</div>
43
37
  </div>
44
38
  </header>
45
39
  )
@@ -4,7 +4,7 @@ import { GripVertical } from "lucide-react"
4
4
  import { Button } from "@/components/primitives/Button"
5
5
 
6
6
  export interface DragHandleCellProps {
7
- id: number | string
7
+ id: number
8
8
  }
9
9
 
10
10
  export function DragHandleCell({ id }: DragHandleCellProps) {
@@ -7,18 +7,16 @@ import type { DashboardRow } from "./table-types"
7
7
 
8
8
  export interface DraggableRowProps {
9
9
  row: Row<DashboardRow>
10
- rowId: number | string
11
10
  }
12
11
 
13
- export function DraggableRow({ row, rowId }: DraggableRowProps) {
12
+ export function DraggableRow({ row }: DraggableRowProps) {
14
13
  const { transform, transition, setNodeRef, isDragging } = useSortable({
15
- id: rowId,
14
+ id: row.original.id,
16
15
  })
17
16
 
18
17
  return (
19
18
  <TableRow
20
19
  ref={setNodeRef}
21
- data-row-id={String(rowId)}
22
20
  data-state={row.getIsSelected() && "selected"}
23
21
  data-dragging={isDragging}
24
22
  className="relative z-0 data-[dragging=true]:z-10 data-[dragging=true]:opacity-80"
@@ -1,7 +1,6 @@
1
1
  import type { Meta, StoryObj } from "@storybook/nextjs-vite"
2
2
  import { expect, userEvent, within } from "@storybook/test"
3
3
  import { Toaster } from "sonner"
4
- import { DYNAMIC_TABLE_SCHEMA_VERSION, dynamicTableSchema } from "ui-schema-contracts"
5
4
 
6
5
  import { EnhancedDataTable } from "./EnhancedDataTable"
7
6
  import type { DashboardRow } from "./table-types"
@@ -12,22 +11,6 @@ const rows: DashboardRow[] = [
12
11
  { id: 3, header: "Executive summary", type: "Narrative", status: "Done", target: "10", limit: "13", reviewer: "Assign reviewer" },
13
12
  ]
14
13
 
15
- const tableSchema = dynamicTableSchema.parse({
16
- schemaVersion: DYNAMIC_TABLE_SCHEMA_VERSION,
17
- rowKey: "id",
18
- enableFiltering: true,
19
- enablePagination: true,
20
- enableRowSelection: true,
21
- columns: [
22
- { key: "header", label: "Header", sortable: true, hideable: false },
23
- { key: "type", label: "Type", sortable: true },
24
- { key: "status", label: "Status", renderType: "badge", sortable: true },
25
- { key: "target", label: "Target", align: "right", sortable: true },
26
- { key: "limit", label: "Limit", align: "right", sortable: true },
27
- { key: "reviewer", label: "Reviewer", sortable: true },
28
- ],
29
- })
30
-
31
14
  const meta = {
32
15
  title: "Composites/EnhancedDataTable/Behaviors",
33
16
  component: EnhancedDataTable,
@@ -47,7 +30,7 @@ export default meta
47
30
  type Story = StoryObj<typeof meta>
48
31
 
49
32
  export const SelectAllWorks: Story = {
50
- args: { data: rows, tableSchema },
33
+ args: { data: rows },
51
34
  play: async ({ canvasElement }) => {
52
35
  const canvas = within(canvasElement)
53
36
  const selectAll = canvas.getByLabelText("Select all")
@@ -57,7 +40,7 @@ export const SelectAllWorks: Story = {
57
40
  }
58
41
 
59
42
  export const DrawerOpensFromHeader: Story = {
60
- args: { data: rows, tableSchema },
43
+ args: { data: rows },
61
44
  play: async ({ canvasElement }) => {
62
45
  const canvas = within(canvasElement)
63
46
  const trigger = canvas.getByRole("button", { name: "Cover page" })
@@ -67,7 +50,7 @@ export const DrawerOpensFromHeader: Story = {
67
50
  }
68
51
 
69
52
  export const SwitchesViewTab: Story = {
70
- args: { data: rows, tableSchema },
53
+ args: { data: rows },
71
54
  play: async ({ canvasElement }) => {
72
55
  const canvas = within(canvasElement)
73
56
  const tab = canvas.getByRole("tab", { name: /Past Performance/i })
@@ -1,6 +1,5 @@
1
1
  import type { Meta, StoryObj } from "@storybook/nextjs-vite"
2
2
  import { Toaster } from "sonner"
3
- import { DYNAMIC_TABLE_SCHEMA_VERSION, dynamicTableSchema } from "ui-schema-contracts"
4
3
 
5
4
  import { EnhancedDataTable } from "./EnhancedDataTable"
6
5
  import type { DashboardRow } from "./table-types"
@@ -20,22 +19,6 @@ const data: DashboardRow[] = [
20
19
  { id: 12, header: "Advantages Over Current Technologies", type: "Narrative", status: "Not Started", target: "12", limit: "0", reviewer: "Assign reviewer" },
21
20
  ]
22
21
 
23
- const tableSchema = dynamicTableSchema.parse({
24
- schemaVersion: DYNAMIC_TABLE_SCHEMA_VERSION,
25
- rowKey: "id",
26
- enableFiltering: true,
27
- enablePagination: true,
28
- enableRowSelection: true,
29
- columns: [
30
- { key: "header", label: "Header", sortable: true, hideable: false },
31
- { key: "type", label: "Type", sortable: true },
32
- { key: "status", label: "Status", renderType: "badge", sortable: true },
33
- { key: "target", label: "Target", align: "right", sortable: true },
34
- { key: "limit", label: "Limit", align: "right", sortable: true },
35
- { key: "reviewer", label: "Reviewer", sortable: true },
36
- ],
37
- })
38
-
39
22
  const meta = {
40
23
  title: "Composites/EnhancedDataTable",
41
24
  component: EnhancedDataTable,
@@ -55,6 +38,5 @@ type Story = StoryObj<typeof meta>
55
38
  export const Default: Story = {
56
39
  args: {
57
40
  data,
58
- tableSchema,
59
41
  },
60
42
  }