Skip to content

Commit 109dbe9

Browse files
authored
Merge pull request #3 from sp-yduck/feature/data-provider
Add KanbanProvider to globally manage the columnItems and KanbanCardItems
2 parents fd2a59a + 23c0494 commit 109dbe9

File tree

11 files changed

+130
-50
lines changed

11 files changed

+130
-50
lines changed

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,30 +27,30 @@ You can find all the sample codes [here](https://github.com/sp-yduck/fast-kanban
2727
```example.ts
2828
// simple example implementation
2929

30-
export function DefaultKanban({
31-
columnItems,
32-
kanbanCardItems,
33-
}: {
34-
columnItems: { id: UniqueIdentifier }[];
35-
kanbanCardItems: { id: UniqueIdentifier; column_id: UniqueIdentifier }[];
36-
}) {
30+
function App() {
31+
return (
32+
<KanbanProvider>
33+
<DefaultKanban />
34+
</KanbanProvider>
35+
)
36+
}
37+
38+
export function DefaultKanban() {
3739
return (
3840
<Kanban>
3941
<KanbanHeader>
4042
<KanbanTitle>Kanban Board</KanbanTitle>
4143
</KanbanHeader>
4244
<KanbanContent>
4345
<SortableColumnsContainer
44-
items={columnItems}
45-
kanbanCardItems={kanbanCardItems}
4646
columnRenderFunc={renderColumn}
4747
/>
4848
</KanbanContent>
4949
</Kanban>
5050
);
5151
}
5252

53-
function renderColumn(id: UniqueIdentifier, items: { id: UniqueIdentifier }[]) {
53+
function renderColumn(id: UniqueIdentifier, column_id: UniqueIdentifier) {
5454
return (
5555
<Column key={id} id={id}>
5656
<ColumnHandler>
@@ -59,7 +59,7 @@ function renderColumn(id: UniqueIdentifier, items: { id: UniqueIdentifier }[]) {
5959
</ColumnHeader>
6060
</ColumnHandler>
6161
<ColumnContent>
62-
<KanbanCardsContainer items={items} cardRenderFunc={renderKanbanCard} />
62+
<KanbanCardsContainer column_id={id} cardRenderFunc={renderKanbanCard} />
6363
</ColumnContent>
6464
</Column>
6565
);

packages/fast-kanban/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ export {
55
KanbanTitle,
66
KanbanContent,
77
} from "./src/components/kanban/Board";
8+
export {
9+
KanbanProvider,
10+
useColumnItems,
11+
useKanbanCardItems,
12+
} from "./src/components/kanban/Context";
813
export {
914
Column,
1015
ColumnHandler,
@@ -21,4 +26,8 @@ export {
2126
KanbanCardTitle,
2227
KanbanCardContent,
2328
} from "./src/components/kanban/Card";
24-
export type { UniqueIdentifier } from "./src/components/kanban/types";
29+
export type {
30+
UniqueIdentifier,
31+
ColumnItems,
32+
KanbanCardItems,
33+
} from "./src/components/kanban/types";

packages/fast-kanban/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/fast-kanban/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "fast-kanban",
33
"private": false,
4-
"version": "0.0.1",
4+
"version": "0.1.0",
55
"type": "module",
66
"main": "./dist/index.cjs",
77
"module": "./dist/index.js",

packages/fast-kanban/src/components/kanban/Card.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { SortableContext, useSortable } from "@dnd-kit/sortable";
44
import { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities";
55
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
66
import { cn } from "@/lib/utils";
7+
import { useKanbanCardItems } from "./Context";
78

89
export const KanbanCardHeader = CardHeader;
910
export const KanbanCardTitle = CardTitle;
@@ -74,15 +75,17 @@ export function KanbanCardHandler({
7475

7576
export function KanbanCardsContainer({
7677
className,
77-
items,
78+
column_id,
7879
data,
7980
cardRenderFunc,
8081
}: {
8182
className?: string;
82-
items: { id: UniqueIdentifier }[];
83+
column_id: UniqueIdentifier;
8384
data?: unknown;
8485
cardRenderFunc: (id: UniqueIdentifier, data: unknown) => React.ReactNode;
8586
}) {
87+
const [kanbanCards] = useKanbanCardItems();
88+
const items = kanbanCards.filter((item) => item.column_id === column_id);
8689
return (
8790
<SortableContext id="kanban-card" items={items}>
8891
<div className={cn(className)}>

packages/fast-kanban/src/components/kanban/ColumnsContainer.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from "react";
1+
import React from "react";
22
import {
33
DndContext,
44
DragEndEvent,
@@ -9,30 +9,25 @@ import {
99
import { SortableContext, arrayMove } from "@dnd-kit/sortable";
1010
import { CardContent } from "@/components/ui/card";
1111
import { cn } from "@/lib/utils";
12+
import { useColumnItems, useKanbanCardItems } from "./Context";
13+
import { ColumnItems } from "./types";
1214

1315
export function SortableColumnsContainer({
1416
className,
15-
items,
16-
kanbanCardItems,
1717
data,
1818
columnRenderFunc,
1919
}: {
2020
className?: string;
21-
items: { id: UniqueIdentifier }[];
22-
kanbanCardItems: { id: UniqueIdentifier; column_id: UniqueIdentifier }[];
2321
data?: unknown;
2422
columnRenderFunc: (
2523
id: UniqueIdentifier,
26-
items: { id: UniqueIdentifier }[],
24+
items: ColumnItems,
2725
data?: unknown
2826
) => React.ReactNode;
2927
}) {
3028
const { setNodeRef } = useDroppable({ id: "droppable" });
31-
const [cols, setCols] = useState<{ id: UniqueIdentifier }[]>(items);
32-
const [kanbanCards, setKanbanCards] =
33-
useState<{ id: UniqueIdentifier; column_id: UniqueIdentifier }[]>(
34-
kanbanCardItems
35-
);
29+
const [cols, setCols] = useColumnItems();
30+
const [kanbanCards, setKanbanCards] = useKanbanCardItems();
3631
return (
3732
<DndContext onDragEnd={onDragEnd} onDragOver={onDragOver}>
3833
<SortableContext id="columns" items={cols}>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React, { useContext } from "react";
2+
import { ColumnItems, KanbanCardItems } from "./types";
3+
4+
// Context for managing the state of ColumnItems
5+
const ColumnsItemContext = React.createContext<ColumnItems>({} as ColumnItems);
6+
const SetColumnsItemContext = React.createContext<
7+
React.Dispatch<React.SetStateAction<ColumnItems>>
8+
>(() => {});
9+
export const useColumnItems = (): [
10+
ColumnItems,
11+
React.Dispatch<React.SetStateAction<ColumnItems>>
12+
] => [useContext(ColumnsItemContext), useContext(SetColumnsItemContext)];
13+
14+
// Context for managing the state of KanbanCardItems
15+
const KanbanCardItemContext = React.createContext<KanbanCardItems>(
16+
{} as KanbanCardItems
17+
);
18+
const SetKanbanCardItemContext = React.createContext<
19+
React.Dispatch<React.SetStateAction<KanbanCardItems>>
20+
>(() => {});
21+
export const useKanbanCardItems = (): [
22+
KanbanCardItems,
23+
React.Dispatch<React.SetStateAction<KanbanCardItems>>
24+
] => [useContext(KanbanCardItemContext), useContext(SetKanbanCardItemContext)];
25+
26+
// Context Provider for managing the state of ColumnItems and KanbanCardItems
27+
export function KanbanProvider({ children }: { children: React.ReactNode }) {
28+
const [columnItems, setColumnItems] = React.useState<ColumnItems>(
29+
[] as ColumnItems
30+
);
31+
const [kanbanCardItems, setKanbanCardItems] = React.useState<KanbanCardItems>(
32+
[] as KanbanCardItems
33+
);
34+
return (
35+
<ColumnsItemContext.Provider value={columnItems}>
36+
<SetColumnsItemContext.Provider value={setColumnItems}>
37+
<KanbanCardItemContext.Provider value={kanbanCardItems}>
38+
<SetKanbanCardItemContext.Provider value={setKanbanCardItems}>
39+
{children}
40+
</SetKanbanCardItemContext.Provider>
41+
</KanbanCardItemContext.Provider>
42+
</SetColumnsItemContext.Provider>
43+
</ColumnsItemContext.Provider>
44+
);
45+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
export type UniqueIdentifier = string | number;
2+
3+
export type ColumnItems = { id: UniqueIdentifier }[];
4+
export type KanbanCardItems = {
5+
id: UniqueIdentifier;
6+
column_id: UniqueIdentifier;
7+
}[];

src/App.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
import { KanbanProvider } from "fast-kanban";
12
import DefaultKanban from "./components/DefaultKanban";
23
import JiraStyleKanban from "./components/JiraStyleKanban";
34

45
function App() {
5-
const columnItems = [
6+
const initialColumnItems = [
67
{ id: "backlog" },
78
{ id: "to do" },
89
{ id: "in progress" },
910
{ id: "done" },
1011
];
11-
const kanbanCardItems = [
12+
const initialKanbanCardItems = [
1213
{ id: "1", column_id: "backlog" },
1314
{ id: "2", column_id: "backlog" },
1415
{ id: "3", column_id: "to do" },
@@ -22,18 +23,22 @@ function App() {
2223
<div>
2324
<div className="bg-gray-100 p-8">
2425
<div className="text-xl px-2 py-4">Default UI</div>
25-
<DefaultKanban
26-
columnItems={columnItems}
27-
kanbanCardItems={kanbanCardItems}
28-
/>
26+
<KanbanProvider>
27+
<DefaultKanban
28+
columnItems={initialColumnItems}
29+
kanbanCardItems={initialKanbanCardItems}
30+
/>
31+
</KanbanProvider>
2932
</div>
3033
<div className="p-8">
3134
<div className="text-xl px-2 py-4">Jira Style UI</div>
3235
<div>
33-
<JiraStyleKanban
34-
columnItems={columnItems}
35-
kanbanCardItems={kanbanCardItems}
36-
/>
36+
<KanbanProvider>
37+
<JiraStyleKanban
38+
columnItems={initialColumnItems}
39+
kanbanCardItems={initialKanbanCardItems}
40+
/>
41+
</KanbanProvider>
3742
</div>
3843
</div>
3944
</div>

src/components/DefaultKanban.tsx

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,39 @@ import {
1616
KanbanCardContent,
1717
KanbanCardHandler,
1818
KanbanCardsContainer,
19+
ColumnItems,
20+
KanbanCardItems,
21+
useColumnItems,
22+
useKanbanCardItems,
1923
} from "fast-kanban";
24+
import { useEffect } from "react";
2025

2126
export default function DefaultKanban({
2227
columnItems,
2328
kanbanCardItems,
2429
}: {
25-
columnItems: { id: UniqueIdentifier }[];
26-
kanbanCardItems: { id: UniqueIdentifier; column_id: UniqueIdentifier }[];
30+
columnItems: ColumnItems;
31+
kanbanCardItems: KanbanCardItems;
2732
}) {
33+
const [, setColumnsItems] = useColumnItems();
34+
const [, setKanbanCardItems] = useKanbanCardItems();
35+
useEffect(() => {
36+
setColumnsItems(columnItems);
37+
setKanbanCardItems(kanbanCardItems);
38+
}, [setColumnsItems, setKanbanCardItems, columnItems, kanbanCardItems]);
2839
return (
2940
<Kanban>
3041
<KanbanHeader>
3142
<KanbanTitle>Kanban Board</KanbanTitle>
3243
</KanbanHeader>
3344
<KanbanContent>
34-
<SortableColumnsContainer
35-
items={columnItems}
36-
kanbanCardItems={kanbanCardItems}
37-
columnRenderFunc={renderColumn}
38-
/>
45+
<SortableColumnsContainer columnRenderFunc={renderColumn} />
3946
</KanbanContent>
4047
</Kanban>
4148
);
4249
}
4350

44-
function renderColumn(id: UniqueIdentifier, items: { id: UniqueIdentifier }[]) {
51+
function renderColumn(id: UniqueIdentifier) {
4552
return (
4653
<Column key={id} id={id}>
4754
<ColumnHandler>
@@ -50,7 +57,10 @@ function renderColumn(id: UniqueIdentifier, items: { id: UniqueIdentifier }[]) {
5057
</ColumnHeader>
5158
</ColumnHandler>
5259
<ColumnContent>
53-
<KanbanCardsContainer items={items} cardRenderFunc={renderKanbanCard} />
60+
<KanbanCardsContainer
61+
column_id={id}
62+
cardRenderFunc={renderKanbanCard}
63+
/>
5464
</ColumnContent>
5565
</Column>
5666
);

src/components/JiraStyleKanban.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useEffect } from "react";
12
import {
23
EllipsisIcon,
34
PlusIcon,
@@ -21,6 +22,8 @@ import {
2122
KanbanCardContent,
2223
KanbanCardHandler,
2324
KanbanCardsContainer,
25+
useColumnItems,
26+
useKanbanCardItems,
2427
} from "fast-kanban";
2528

2629
export default function JiraStyleKanban({
@@ -30,6 +33,12 @@ export default function JiraStyleKanban({
3033
columnItems: { id: UniqueIdentifier }[];
3134
kanbanCardItems: { id: UniqueIdentifier; column_id: UniqueIdentifier }[];
3235
}) {
36+
const [, setColumnsItems] = useColumnItems();
37+
const [, setKanbanCardItems] = useKanbanCardItems();
38+
useEffect(() => {
39+
setColumnsItems(columnItems);
40+
setKanbanCardItems(kanbanCardItems);
41+
}, [setColumnsItems, setKanbanCardItems, columnItems, kanbanCardItems]);
3342
return (
3443
<Kanban className="rounded-md shadow-none">
3544
<KanbanHeader>
@@ -38,8 +47,6 @@ export default function JiraStyleKanban({
3847
<KanbanContent>
3948
<SortableColumnsContainer
4049
className="space-x-3"
41-
items={columnItems}
42-
kanbanCardItems={kanbanCardItems}
4350
columnRenderFunc={renderColumn}
4451
/>
4552
</KanbanContent>
@@ -72,7 +79,7 @@ function renderColumn(id: UniqueIdentifier, items: { id: UniqueIdentifier }[]) {
7279
<ColumnContent className="p-0 px-1 py-2">
7380
<KanbanCardsContainer
7481
className="space-y-1 w-full"
75-
items={items}
82+
column_id={id}
7683
cardRenderFunc={renderKanbanCard}
7784
/>
7885
<div className="flex rounded-sm hover:bg-gray-200 p-2 space-x-1 text-center text-md text-gray-500 ">

0 commit comments

Comments
 (0)