Skip to content

Commit 1812b78

Browse files
Copilothuangyiirene
andcommitted
Add Kanban board component with drag-and-drop support
Co-authored-by: huangyiirene <7665279+huangyiirene@users.noreply.github.com>
1 parent 5039d5d commit 1812b78

6 files changed

Lines changed: 451 additions & 0 deletions

File tree

packages/components/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
"test": "vitest run"
1919
},
2020
"dependencies": {
21+
"@dnd-kit/core": "^6.3.1",
22+
"@dnd-kit/sortable": "^8.0.0",
23+
"@dnd-kit/utilities": "^3.2.2",
2124
"@object-ui/core": "workspace:*",
2225
"@object-ui/react": "workspace:*",
2326
"@radix-ui/react-accordion": "^1.2.12",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import './carousel';
2+
import './kanban';
23
import './scroll-area';
34
import './resizable';
45
import './table';
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { ComponentRegistry } from '@object-ui/core';
2+
import { KanbanBoard, type KanbanColumn, type KanbanCard } from '@/ui';
3+
import React from 'react';
4+
5+
ComponentRegistry.register('kanban',
6+
({ schema, className, ...props }) => {
7+
const [columns, setColumns] = React.useState<KanbanColumn[]>(schema.columns || []);
8+
9+
React.useEffect(() => {
10+
if (schema.columns) {
11+
setColumns(schema.columns);
12+
}
13+
}, [schema.columns]);
14+
15+
const handleCardMove = (
16+
cardId: string,
17+
fromColumnId: string,
18+
toColumnId: string,
19+
newIndex: number
20+
) => {
21+
// This is where you would handle the card move event
22+
// For example, you could call an API or trigger an action
23+
console.log('Card moved:', { cardId, fromColumnId, toColumnId, newIndex });
24+
25+
// If there's an onCardMove callback in schema, call it
26+
if (schema.onCardMove) {
27+
schema.onCardMove({ cardId, fromColumnId, toColumnId, newIndex });
28+
}
29+
};
30+
31+
return (
32+
<KanbanBoard
33+
columns={columns}
34+
onCardMove={schema.onCardMove ? handleCardMove : undefined}
35+
className={className}
36+
{...props}
37+
/>
38+
);
39+
},
40+
{
41+
label: 'Kanban Board',
42+
icon: 'LayoutDashboard',
43+
inputs: [
44+
{
45+
name: 'columns',
46+
type: 'array',
47+
label: 'Columns',
48+
description: 'Array of { id, title, cards, limit, className }',
49+
required: true
50+
},
51+
{
52+
name: 'onCardMove',
53+
type: 'code',
54+
label: 'On Card Move',
55+
description: 'Callback when a card is moved',
56+
advanced: true
57+
},
58+
{
59+
name: 'className',
60+
type: 'string',
61+
label: 'CSS Class'
62+
}
63+
],
64+
defaultProps: {
65+
columns: [
66+
{
67+
id: 'todo',
68+
title: 'To Do',
69+
cards: [
70+
{
71+
id: 'card-1',
72+
title: 'Task 1',
73+
description: 'This is the first task',
74+
badges: [
75+
{ label: 'High Priority', variant: 'destructive' },
76+
{ label: 'Feature', variant: 'default' }
77+
]
78+
},
79+
{
80+
id: 'card-2',
81+
title: 'Task 2',
82+
description: 'This is the second task',
83+
badges: [
84+
{ label: 'Bug', variant: 'destructive' }
85+
]
86+
}
87+
]
88+
},
89+
{
90+
id: 'in-progress',
91+
title: 'In Progress',
92+
limit: 3,
93+
cards: [
94+
{
95+
id: 'card-3',
96+
title: 'Task 3',
97+
description: 'Currently working on this',
98+
badges: [
99+
{ label: 'In Progress', variant: 'default' }
100+
]
101+
}
102+
]
103+
},
104+
{
105+
id: 'done',
106+
title: 'Done',
107+
cards: [
108+
{
109+
id: 'card-4',
110+
title: 'Task 4',
111+
description: 'This task is completed',
112+
badges: [
113+
{ label: 'Completed', variant: 'outline' }
114+
]
115+
},
116+
{
117+
id: 'card-5',
118+
title: 'Task 5',
119+
description: 'Another completed task',
120+
badges: [
121+
{ label: 'Completed', variant: 'outline' }
122+
]
123+
}
124+
]
125+
}
126+
],
127+
className: 'w-full'
128+
}
129+
}
130+
);

packages/components/src/ui/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export * from './input-group';
2626
export * from './input-otp';
2727
export * from './input';
2828
export * from './item';
29+
export * from './kanban';
2930
export * from './kbd';
3031
export * from './label';
3132
export * from './menubar';

0 commit comments

Comments
 (0)