ai-design-system 0.1.33 → 0.1.35
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/edge.tsx +93 -42
- package/components/ai-elements/node.tsx +1 -1
- package/components/blocks/DataTable/DataTable.tsx +1 -4
- package/components/blocks/FormReportsSection/FormReportsSection.tsx +0 -4
- package/components/blocks/SectionLayout/SectionLayout.stories.tsx +0 -106
- package/components/blocks/SectionLayout/SectionLayout.tsx +2 -4
- package/components/blocks/SectionLayout/interfaces.ts +0 -2
- package/components/blocks/WorkflowCanvas/WorkflowCanvas.tsx +0 -1
- package/components/blocks/index.ts +0 -3
- package/components/composites/AdjustableLayout/AdjustableLayout.tsx +3 -17
- package/components/composites/AppHeader/AppHeader.tsx +9 -15
- package/components/composites/DataTable/DragHandleCell.tsx +1 -1
- package/components/composites/DataTable/DraggableRow.tsx +2 -4
- package/components/composites/DataTable/EnhancedDataTable.behaviors.stories.tsx +3 -20
- package/components/composites/DataTable/EnhancedDataTable.stories.tsx +0 -18
- package/components/composites/DataTable/EnhancedDataTable.tsx +131 -336
- package/components/composites/DataTable/index.ts +0 -1
- package/components/composites/DataTable/table-types.ts +12 -17
- package/components/composites/DataTable/useEnhancedDataTable.ts +9 -30
- package/components/composites/FormReports/FormReportsDrawerForm.tsx +16 -10
- package/components/composites/FormReports/FormReportsTable.tsx +56 -96
- package/components/composites/FormReports/index.ts +0 -1
- package/components/composites/ModeSwitcher/ModeSwitcher.tsx +62 -0
- package/components/composites/ModeSwitcher/index.ts +2 -0
- package/components/composites/StateNode/StateNode.tsx +5 -8
- package/components/composites/TransitionNode/TransitionNode.tsx +5 -7
- package/components/composites/index.ts +4 -24
- package/components/features/DashboardFeature/DashboardFeature.mocks.ts +0 -158
- package/components/features/DashboardFeature/DashboardFeature.stories.tsx +0 -6
- package/components/features/DashboardFeature/DashboardFeature.tsx +49 -6
- package/components/features/DashboardFeature/useDashboardFeature.d.ts +1 -3
- package/components/features/DashboardFeature/useDashboardFeature.mock.ts +1 -34
- package/components/features/FormReportsFeature/FormReportsFeature.mocks.ts +54 -155
- package/components/features/FormReportsFeature/FormReportsFeature.tsx +16 -29
- package/components/features/FormReportsFeature/useFormReportsFeature.d.ts +0 -2
- package/components/features/FormReportsFeature/useFormReportsFeature.mock.ts +0 -5
- package/components/features/PageLayout/PageLayout.mocks.ts +0 -27
- package/components/features/PageLayout/PageLayout.stories.tsx +51 -31
- package/components/features/PageLayout/PageLayout.tsx +19 -54
- package/components/features/PageLayout/usePageLayout.d.ts +0 -4
- package/components/features/PageLayout/usePageLayout.mock.ts +1 -64
- package/components/features/RefinementPanel/RefinementPanel.stories.tsx +2 -2
- package/components/features/RefinementPanel/useRefinementPanel.mock.ts +0 -8
- package/components/features/SpecNavigator/README.md +3 -23
- package/components/features/SpecNavigator/SpecNavigator.behaviors.stories.tsx +11 -29
- package/components/features/SpecNavigator/SpecNavigator.mocks.ts +8 -35
- package/components/features/SpecNavigator/SpecNavigator.stories.tsx +36 -38
- package/components/features/SpecNavigator/SpecNavigator.tsx +3 -56
- package/components/features/SpecNavigator/index.ts +1 -5
- package/components/features/SpecNavigator/useSpecNavigator.d.ts +2 -2
- package/components/features/SpecNavigator/useSpecNavigator.mock.ts +4 -4
- package/components/features/WorkflowBuilder/WorkflowBuilder.stories.tsx +39 -45
- package/components/features/WorkflowBuilder/WorkflowBuilder.tsx +2 -6
- package/components/features/index.ts +0 -5
- package/components/index.ts +14 -7
- package/components/ui/chart.tsx +3 -3
- package/components/ui/input-group.tsx +1 -1
- package/components/ui/input.tsx +1 -1
- package/dist/index.cjs +6311 -6859
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +32 -393
- package/dist/index.d.ts +728 -215
- package/dist/index.js +6064 -6829
- package/dist/index.js.map +1 -1
- package/package.json +1 -3
- package/components/blocks/InboxPanel/InboxPanel.stories.tsx +0 -48
- package/components/blocks/InboxPanel/InboxPanel.tsx +0 -55
- package/components/blocks/InboxPanel/index.ts +0 -2
- package/components/composites/FilePreviewDialog/FilePreviewDialog.tsx +0 -150
- package/components/composites/FilePreviewDialog/index.ts +0 -2
- package/components/composites/InboxList/InboxList.stories.tsx +0 -45
- package/components/composites/InboxList/InboxList.tsx +0 -99
- package/components/composites/InboxList/index.ts +0 -2
- package/components/composites/LoadingShimmer/LoadingShimmer.tsx +0 -24
- package/components/composites/LoadingShimmer/index.ts +0 -2
- package/components/composites/LoadingShimmer/interfaces.ts +0 -4
- package/components/composites/WorkflowRunObservabilityPanel/WorkflowRunObservabilityPanel.tsx +0 -549
- package/components/composites/WorkflowRunObservabilityPanel/index.ts +0 -17
- package/components/features/WorkflowObservabilityFeature/README.md +0 -114
- package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.behaviors.stories.tsx +0 -206
- package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.mocks.ts +0 -165
- package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.stories.tsx +0 -151
- package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.tsx +0 -227
- package/components/features/WorkflowObservabilityFeature/index.ts +0 -7
- package/components/features/WorkflowObservabilityFeature/useWorkflowObservabilityFeature.d.ts +0 -37
- 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
|
-
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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-
|
|
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,
|
|
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
|
|
29
|
+
<div className="h-full flex flex-col">
|
|
32
30
|
{section.header && (
|
|
33
31
|
<AppHeader {...section.header} />
|
|
34
32
|
)}
|
|
35
|
-
<div className="
|
|
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
|
}
|
|
@@ -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
|
-
"
|
|
178
|
+
"h-full overflow-hidden bg-card border border-border rounded-md",
|
|
192
179
|
section.className
|
|
193
180
|
)}
|
|
194
181
|
style={{
|
|
195
|
-
|
|
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="
|
|
20
|
-
<
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
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
|
)
|
|
@@ -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
|
|
12
|
+
export function DraggableRow({ row }: DraggableRowProps) {
|
|
14
13
|
const { transform, transition, setNodeRef, isDragging } = useSortable({
|
|
15
|
-
id:
|
|
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
|
|
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
|
|
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
|
|
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
|
}
|