@emberai-engg/task-board 0.3.0
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/README.md +160 -0
- package/dist/index.d.mts +442 -0
- package/dist/index.d.ts +442 -0
- package/dist/index.js +2337 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2259 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +42 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# @emberai-engg/task-board
|
|
2
|
+
|
|
3
|
+
Reusable Kanban task board component with built-in create/detail UI.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @emberai-engg/task-board
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
No render props needed. The package ships with a complete UI out of the box:
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { TaskBoardProvider, TaskBoard } from '@emberai-engg/task-board';
|
|
17
|
+
import '@emberai-engg/task-board/styles.css';
|
|
18
|
+
import { apiClient } from './lib/api';
|
|
19
|
+
|
|
20
|
+
function App() {
|
|
21
|
+
const user = useAuth();
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<TaskBoardProvider
|
|
25
|
+
apiClient={apiClient}
|
|
26
|
+
user={{
|
|
27
|
+
username: user.username,
|
|
28
|
+
name: user.name,
|
|
29
|
+
email: user.email,
|
|
30
|
+
apps: user.apps,
|
|
31
|
+
is_internal: user.is_internal,
|
|
32
|
+
is_reviewer: user.is_reviewer,
|
|
33
|
+
}}
|
|
34
|
+
projects={[
|
|
35
|
+
{ slug: 'my-project', name: 'My Project' },
|
|
36
|
+
]}
|
|
37
|
+
>
|
|
38
|
+
<TaskBoard onShareFeedback={() => router.push('/feedback')} />
|
|
39
|
+
</TaskBoardProvider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This gives you:
|
|
45
|
+
- Kanban board with drag-and-drop
|
|
46
|
+
- Built-in **CreateTaskModal** (two-column layout with title, structured description, priority, status, tags)
|
|
47
|
+
- Built-in **TaskDetailPanel** (slide-over with properties grid, description sections, activity timeline, comments with @mentions)
|
|
48
|
+
- Notification bell with polling
|
|
49
|
+
- Tag filtering
|
|
50
|
+
- Share links
|
|
51
|
+
- Loading skeletons and empty states
|
|
52
|
+
|
|
53
|
+
## Props / Config Reference
|
|
54
|
+
|
|
55
|
+
### `TaskBoardProvider`
|
|
56
|
+
|
|
57
|
+
| Prop | Type | Required | Description |
|
|
58
|
+
|------|------|----------|-------------|
|
|
59
|
+
| `apiClient` | `ApiClient` | Yes | Axios-like HTTP client with auth headers |
|
|
60
|
+
| `user` | `TaskBoardUser` | Yes | Current logged-in user |
|
|
61
|
+
| `projects` | `Project[]` | No | Available projects |
|
|
62
|
+
| `columns` | `ColumnConfig[]` | No | Column definitions (defaults to 8-column kanban) |
|
|
63
|
+
| `priorities` | `PriorityConfig[]` | No | Priority levels |
|
|
64
|
+
| `tags` | `TagConfig[]` | No | Predefined tags |
|
|
65
|
+
| `apiBasePath` | `string` | No | API prefix (defaults to `/api/v1/taskboard`) |
|
|
66
|
+
| `features` | `object` | No | Feature flags for enabling/disabling features |
|
|
67
|
+
| `onTaskCreate` | `(task) => void` | No | Callback on task creation |
|
|
68
|
+
| `onTaskUpdate` | `(task) => void` | No | Callback on task update |
|
|
69
|
+
| `onTaskDelete` | `(id) => void` | No | Callback on task deletion |
|
|
70
|
+
| `onError` | `(error) => void` | No | Error handler callback |
|
|
71
|
+
|
|
72
|
+
### `TaskBoard`
|
|
73
|
+
|
|
74
|
+
| Prop | Type | Description |
|
|
75
|
+
|------|------|-------------|
|
|
76
|
+
| `className` | `string` | CSS class for the outer container |
|
|
77
|
+
| `headerActions` | `ReactNode` | Additional buttons in the header |
|
|
78
|
+
| `onShareFeedback` | `() => void` | Callback for Share Feedback button. Hidden if omitted. |
|
|
79
|
+
| `onTaskOpen` | `(task) => void` | Callback when a task is clicked |
|
|
80
|
+
| `renderTaskDetail` | `function` | Override for task detail panel (built-in used if omitted) |
|
|
81
|
+
| `renderCreateTask` | `function` | Override for create task modal (built-in used if omitted) |
|
|
82
|
+
|
|
83
|
+
### Overriding built-in UI
|
|
84
|
+
|
|
85
|
+
If you need custom create/detail UI, pass render props:
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
<TaskBoard
|
|
89
|
+
renderCreateTask={({ projectSlug, defaultStatus, onClose, onCreate }) => (
|
|
90
|
+
<MyCustomCreateModal ... />
|
|
91
|
+
)}
|
|
92
|
+
renderTaskDetail={({ task, onClose, onUpdate }) => (
|
|
93
|
+
<MyCustomDetailPanel ... />
|
|
94
|
+
)}
|
|
95
|
+
/>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Using Individual Components
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
import {
|
|
102
|
+
TaskCard, PriorityBadge, UserAvatar,
|
|
103
|
+
CreateTaskModal, TaskDetailPanel,
|
|
104
|
+
useTaskActions,
|
|
105
|
+
} from '@emberai-engg/task-board';
|
|
106
|
+
|
|
107
|
+
// Use hooks independently
|
|
108
|
+
function MyCustomUI() {
|
|
109
|
+
const { createTask, moveTask } = useTaskActions(tasks, setTasks, fetchTasks);
|
|
110
|
+
// ...
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Use small components
|
|
114
|
+
<PriorityBadge priority="high" />
|
|
115
|
+
<UserAvatar name="John Smith" size="sm" showTooltip />
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Hooks API
|
|
119
|
+
|
|
120
|
+
| Hook | Purpose |
|
|
121
|
+
|------|---------|
|
|
122
|
+
| `useTaskBoard()` | Board state: projects, tasks, loading, pagination |
|
|
123
|
+
| `useTaskActions(tasks, setTasks, fetchTasks)` | CRUD: create, update, delete, move tasks |
|
|
124
|
+
| `useTaskDetail(taskId)` | Single task: comments, activity, field updates |
|
|
125
|
+
| `useShareLink()` | Copy shareable task URLs |
|
|
126
|
+
|
|
127
|
+
## Feature Flags
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
<TaskBoardProvider
|
|
131
|
+
features={{
|
|
132
|
+
dragAndDrop: true, // Drag-and-drop between columns
|
|
133
|
+
comments: true, // Comment system
|
|
134
|
+
mentions: true, // @mention users
|
|
135
|
+
notifications: true, // Notification bell
|
|
136
|
+
internalComments: true, // Internal-only comments
|
|
137
|
+
tags: true, // Tag system
|
|
138
|
+
sharing: true, // Shareable task links
|
|
139
|
+
filters: true, // Tag filtering
|
|
140
|
+
unreadIndicators: true, // Unread dots on cards
|
|
141
|
+
}}
|
|
142
|
+
/>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm install
|
|
149
|
+
npm run dev # Watch mode
|
|
150
|
+
npm run build # Production build
|
|
151
|
+
npm test # Run tests
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Backend
|
|
155
|
+
|
|
156
|
+
The `backend-reference/` folder contains a Python FastAPI reference implementation for the task board API. Copy it into your app's backend and adapt the auth and database setup to match your app. See [`backend-reference/README.md`](backend-reference/README.md) for details.
|
|
157
|
+
|
|
158
|
+
## License
|
|
159
|
+
|
|
160
|
+
Private — internal use only.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React$1 from 'react';
|
|
3
|
+
import React__default from 'react';
|
|
4
|
+
|
|
5
|
+
interface Project {
|
|
6
|
+
slug: string;
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
interface StructuredDescription {
|
|
10
|
+
problem: string;
|
|
11
|
+
user_story: string;
|
|
12
|
+
proposed_behavior: string;
|
|
13
|
+
acceptance_criteria: string;
|
|
14
|
+
open_questions: string;
|
|
15
|
+
}
|
|
16
|
+
interface Task {
|
|
17
|
+
id: string;
|
|
18
|
+
project_slug: string;
|
|
19
|
+
title: string;
|
|
20
|
+
description: StructuredDescription;
|
|
21
|
+
status: string;
|
|
22
|
+
priority: string;
|
|
23
|
+
position: number;
|
|
24
|
+
created_by: string;
|
|
25
|
+
created_by_name: string;
|
|
26
|
+
comment_count: number;
|
|
27
|
+
tags?: string[];
|
|
28
|
+
created_at: string;
|
|
29
|
+
updated_at: string;
|
|
30
|
+
has_unread?: boolean;
|
|
31
|
+
}
|
|
32
|
+
interface ActivityEntry {
|
|
33
|
+
id: string;
|
|
34
|
+
type: string;
|
|
35
|
+
from_status: string;
|
|
36
|
+
to_status: string;
|
|
37
|
+
user: string;
|
|
38
|
+
user_name: string;
|
|
39
|
+
created_at: string;
|
|
40
|
+
}
|
|
41
|
+
interface Comment {
|
|
42
|
+
id: string;
|
|
43
|
+
task_id: string;
|
|
44
|
+
content: string;
|
|
45
|
+
author_id: string;
|
|
46
|
+
author_name: string;
|
|
47
|
+
is_internal?: boolean;
|
|
48
|
+
edited?: boolean;
|
|
49
|
+
edited_at?: string;
|
|
50
|
+
created_at: string;
|
|
51
|
+
}
|
|
52
|
+
interface Notification {
|
|
53
|
+
id: string;
|
|
54
|
+
type: string;
|
|
55
|
+
context: string;
|
|
56
|
+
actor_name: string;
|
|
57
|
+
actor_username: string;
|
|
58
|
+
task_id: string;
|
|
59
|
+
task_title: string;
|
|
60
|
+
project_slug: string;
|
|
61
|
+
snippet: string;
|
|
62
|
+
read: boolean;
|
|
63
|
+
created_at: string;
|
|
64
|
+
}
|
|
65
|
+
interface MentionUser {
|
|
66
|
+
username: string;
|
|
67
|
+
name: string;
|
|
68
|
+
email: string;
|
|
69
|
+
}
|
|
70
|
+
type TasksByStatus = Record<string, Task[]>;
|
|
71
|
+
type ColumnTotals = Record<string, number>;
|
|
72
|
+
type ColumnUnreads = Record<string, number>;
|
|
73
|
+
interface ColumnConfig {
|
|
74
|
+
key: string;
|
|
75
|
+
label: string;
|
|
76
|
+
color: string;
|
|
77
|
+
description: string;
|
|
78
|
+
}
|
|
79
|
+
interface PriorityConfig {
|
|
80
|
+
value: string;
|
|
81
|
+
label: string;
|
|
82
|
+
className: string;
|
|
83
|
+
}
|
|
84
|
+
interface TagConfig {
|
|
85
|
+
value: string;
|
|
86
|
+
label: string;
|
|
87
|
+
className: string;
|
|
88
|
+
}
|
|
89
|
+
interface DescriptionSectionConfig {
|
|
90
|
+
key: keyof StructuredDescription;
|
|
91
|
+
label: string;
|
|
92
|
+
}
|
|
93
|
+
interface TaskBoardUser {
|
|
94
|
+
username: string;
|
|
95
|
+
name: string;
|
|
96
|
+
email: string;
|
|
97
|
+
apps: string[];
|
|
98
|
+
role?: string;
|
|
99
|
+
is_reviewer?: boolean;
|
|
100
|
+
is_internal?: boolean;
|
|
101
|
+
}
|
|
102
|
+
interface ApiClientConfig {
|
|
103
|
+
params?: Record<string, string | number | boolean | undefined>;
|
|
104
|
+
headers?: Record<string, string>;
|
|
105
|
+
signal?: AbortSignal;
|
|
106
|
+
[key: string]: unknown;
|
|
107
|
+
}
|
|
108
|
+
interface ApiClient {
|
|
109
|
+
get: <T>(url: string, config?: ApiClientConfig) => Promise<{
|
|
110
|
+
data: T;
|
|
111
|
+
}>;
|
|
112
|
+
post: <T>(url: string, data?: unknown, config?: ApiClientConfig) => Promise<{
|
|
113
|
+
data: T;
|
|
114
|
+
}>;
|
|
115
|
+
put: <T>(url: string, data?: unknown, config?: ApiClientConfig) => Promise<{
|
|
116
|
+
data: T;
|
|
117
|
+
}>;
|
|
118
|
+
patch: <T>(url: string, data?: unknown, config?: ApiClientConfig) => Promise<{
|
|
119
|
+
data: T;
|
|
120
|
+
}>;
|
|
121
|
+
delete: <T>(url: string, config?: ApiClientConfig) => Promise<{
|
|
122
|
+
data: T;
|
|
123
|
+
}>;
|
|
124
|
+
}
|
|
125
|
+
interface ColumnResponse {
|
|
126
|
+
tasks: Task[];
|
|
127
|
+
total: number;
|
|
128
|
+
unread: number;
|
|
129
|
+
}
|
|
130
|
+
interface TaskDetailResponse extends Task {
|
|
131
|
+
comments: Comment[];
|
|
132
|
+
activity: ActivityEntry[];
|
|
133
|
+
}
|
|
134
|
+
interface NotificationCountResponse {
|
|
135
|
+
count: number;
|
|
136
|
+
}
|
|
137
|
+
interface CreateTaskPayload {
|
|
138
|
+
project_slug: string;
|
|
139
|
+
title: string;
|
|
140
|
+
description?: StructuredDescription;
|
|
141
|
+
priority: string;
|
|
142
|
+
status: string;
|
|
143
|
+
tags: string[];
|
|
144
|
+
}
|
|
145
|
+
interface UpdateTaskPayload {
|
|
146
|
+
title?: string;
|
|
147
|
+
description?: StructuredDescription;
|
|
148
|
+
priority?: string;
|
|
149
|
+
status?: string;
|
|
150
|
+
position?: number;
|
|
151
|
+
tags?: string[];
|
|
152
|
+
}
|
|
153
|
+
interface CreateCommentPayload {
|
|
154
|
+
content: string;
|
|
155
|
+
is_internal?: boolean;
|
|
156
|
+
}
|
|
157
|
+
interface EditCommentPayload {
|
|
158
|
+
content: string;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
interface TaskBoardProps {
|
|
162
|
+
/** Optional class name for the outer container */
|
|
163
|
+
className?: string;
|
|
164
|
+
/** Optional header content (e.g., feedback link) to render in the header bar */
|
|
165
|
+
headerActions?: React__default.ReactNode;
|
|
166
|
+
/** Callback when a task detail panel should open */
|
|
167
|
+
onTaskOpen?: (task: Task) => void;
|
|
168
|
+
/** Callback for the Share Feedback button. If not provided, the button is hidden. */
|
|
169
|
+
onShareFeedback?: () => void;
|
|
170
|
+
/** Render function for the task detail panel. If omitted, uses built-in TaskDetailPanel. */
|
|
171
|
+
renderTaskDetail?: (props: {
|
|
172
|
+
task: Task;
|
|
173
|
+
onClose: () => void;
|
|
174
|
+
onUpdate: () => void;
|
|
175
|
+
}) => React__default.ReactNode;
|
|
176
|
+
/** Render function for the create task modal. If omitted, uses built-in CreateTaskModal. */
|
|
177
|
+
renderCreateTask?: (props: {
|
|
178
|
+
projectSlug: string;
|
|
179
|
+
defaultStatus: string;
|
|
180
|
+
onClose: () => void;
|
|
181
|
+
onCreate: () => void;
|
|
182
|
+
}) => React__default.ReactNode;
|
|
183
|
+
}
|
|
184
|
+
declare function TaskBoard({ className, headerActions, onTaskOpen, onShareFeedback, renderTaskDetail, renderCreateTask, }: TaskBoardProps): react_jsx_runtime.JSX.Element;
|
|
185
|
+
|
|
186
|
+
interface TaskCardProps {
|
|
187
|
+
task: Task;
|
|
188
|
+
index: number;
|
|
189
|
+
onClick: () => void;
|
|
190
|
+
onShare: (e: React__default.MouseEvent) => void;
|
|
191
|
+
copied: boolean;
|
|
192
|
+
}
|
|
193
|
+
declare const TaskCard: React__default.NamedExoticComponent<TaskCardProps>;
|
|
194
|
+
|
|
195
|
+
interface KanbanColumnProps {
|
|
196
|
+
column: ColumnConfig;
|
|
197
|
+
tasks: Task[];
|
|
198
|
+
totalCount: number;
|
|
199
|
+
unreadCount: number;
|
|
200
|
+
loadingMore: boolean;
|
|
201
|
+
onAddTask: () => void;
|
|
202
|
+
onTaskClick: (task: Task) => void;
|
|
203
|
+
onTaskShare: (taskId: string, e: React__default.MouseEvent) => void;
|
|
204
|
+
copiedTaskId: string | null;
|
|
205
|
+
onLoadMore: () => void;
|
|
206
|
+
}
|
|
207
|
+
declare function KanbanColumn({ column, tasks, totalCount, unreadCount, loadingMore, onAddTask, onTaskClick, onTaskShare, copiedTaskId, onLoadMore, }: KanbanColumnProps): react_jsx_runtime.JSX.Element;
|
|
208
|
+
|
|
209
|
+
interface FilterBarProps {
|
|
210
|
+
projects: Project[];
|
|
211
|
+
selectedProject: string;
|
|
212
|
+
onSelectProject: (slug: string) => void;
|
|
213
|
+
filterTags: string[];
|
|
214
|
+
onSetFilterTags: (tags: string[]) => void;
|
|
215
|
+
}
|
|
216
|
+
declare function FilterBar({ projects, selectedProject, onSelectProject, filterTags, onSetFilterTags, }: FilterBarProps): react_jsx_runtime.JSX.Element;
|
|
217
|
+
|
|
218
|
+
interface NotificationBellProps {
|
|
219
|
+
onOpenTask: (taskId: string, projectSlug: string) => void;
|
|
220
|
+
}
|
|
221
|
+
declare function NotificationBell({ onOpenTask }: NotificationBellProps): react_jsx_runtime.JSX.Element;
|
|
222
|
+
|
|
223
|
+
interface PriorityBadgeProps {
|
|
224
|
+
priority: string;
|
|
225
|
+
size?: 'sm' | 'md';
|
|
226
|
+
}
|
|
227
|
+
declare function PriorityBadge({ priority, size }: PriorityBadgeProps): react_jsx_runtime.JSX.Element;
|
|
228
|
+
|
|
229
|
+
interface UserAvatarProps {
|
|
230
|
+
name: string;
|
|
231
|
+
size?: 'xs' | 'sm' | 'md';
|
|
232
|
+
showTooltip?: boolean;
|
|
233
|
+
className?: string;
|
|
234
|
+
}
|
|
235
|
+
declare function UserAvatar({ name, size, showTooltip, className }: UserAvatarProps): react_jsx_runtime.JSX.Element;
|
|
236
|
+
|
|
237
|
+
interface TagBadgeProps {
|
|
238
|
+
tag: string;
|
|
239
|
+
onRemove?: () => void;
|
|
240
|
+
size?: 'sm' | 'md';
|
|
241
|
+
}
|
|
242
|
+
declare function TagBadge({ tag, onRemove, size }: TagBadgeProps): react_jsx_runtime.JSX.Element;
|
|
243
|
+
|
|
244
|
+
/** Renders text with @mentions highlighted as styled badges. */
|
|
245
|
+
declare function MentionText({ text, className }: {
|
|
246
|
+
text: string;
|
|
247
|
+
className?: string;
|
|
248
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
249
|
+
/** Convert stored @[Name](username) to display @Name for textarea */
|
|
250
|
+
declare function toDisplayText(stored: string): string;
|
|
251
|
+
/** Convert display @Name back to stored @[Name](username) using a mention map */
|
|
252
|
+
declare function toStoredText(display: string, mentionMap: Map<string, string>): string;
|
|
253
|
+
|
|
254
|
+
interface MentionTextareaProps {
|
|
255
|
+
value: string;
|
|
256
|
+
onChange: (val: string) => void;
|
|
257
|
+
onKeyDown?: (e: React__default.KeyboardEvent<HTMLTextAreaElement>) => void;
|
|
258
|
+
placeholder?: string;
|
|
259
|
+
rows?: number;
|
|
260
|
+
className?: string;
|
|
261
|
+
disabled?: boolean;
|
|
262
|
+
}
|
|
263
|
+
declare function MentionTextarea({ value, onChange, onKeyDown, placeholder, rows, className, disabled, }: MentionTextareaProps): react_jsx_runtime.JSX.Element;
|
|
264
|
+
|
|
265
|
+
declare function SkeletonPulse({ className }: {
|
|
266
|
+
className?: string;
|
|
267
|
+
}): react_jsx_runtime.JSX.Element;
|
|
268
|
+
declare function SkeletonCard(): react_jsx_runtime.JSX.Element;
|
|
269
|
+
declare function BoardSkeleton(): react_jsx_runtime.JSX.Element;
|
|
270
|
+
|
|
271
|
+
interface CreateTaskModalProps {
|
|
272
|
+
projectSlug: string;
|
|
273
|
+
defaultStatus?: string;
|
|
274
|
+
onClose: () => void;
|
|
275
|
+
onCreate: () => void;
|
|
276
|
+
}
|
|
277
|
+
declare function CreateTaskModal({ projectSlug, defaultStatus, onClose, onCreate, }: CreateTaskModalProps): react_jsx_runtime.JSX.Element;
|
|
278
|
+
|
|
279
|
+
interface TaskDetailPanelProps {
|
|
280
|
+
task: Task;
|
|
281
|
+
projectSlug: string;
|
|
282
|
+
onClose: () => void;
|
|
283
|
+
onUpdate: () => void;
|
|
284
|
+
}
|
|
285
|
+
declare function TaskDetailPanel({ task, projectSlug, onClose, onUpdate }: TaskDetailPanelProps): react_jsx_runtime.JSX.Element;
|
|
286
|
+
|
|
287
|
+
interface TaskBoardService {
|
|
288
|
+
listTasks(projectSlug: string, perColumn?: number): Promise<Record<string, ColumnResponse>>;
|
|
289
|
+
listColumnTasks(projectSlug: string, statusKey: string, offset: number, limit: number): Promise<Task[]>;
|
|
290
|
+
getTask(taskId: string): Promise<TaskDetailResponse>;
|
|
291
|
+
createTask(data: CreateTaskPayload): Promise<Task>;
|
|
292
|
+
updateTask(taskId: string, data: UpdateTaskPayload): Promise<Task>;
|
|
293
|
+
deleteTask(taskId: string): Promise<void>;
|
|
294
|
+
markTaskRead(taskId: string): Promise<void>;
|
|
295
|
+
listComments(taskId: string): Promise<Comment[]>;
|
|
296
|
+
addComment(taskId: string, data: CreateCommentPayload): Promise<Comment>;
|
|
297
|
+
editComment(taskId: string, commentId: string, data: EditCommentPayload): Promise<Comment>;
|
|
298
|
+
deleteComment(taskId: string, commentId: string): Promise<void>;
|
|
299
|
+
searchMentionUsers(query: string): Promise<MentionUser[]>;
|
|
300
|
+
getNotificationCount(): Promise<number>;
|
|
301
|
+
listNotifications(limit?: number): Promise<Notification[]>;
|
|
302
|
+
markNotificationRead(notificationId: string): Promise<void>;
|
|
303
|
+
markAllNotificationsRead(): Promise<void>;
|
|
304
|
+
}
|
|
305
|
+
declare function createTaskBoardService(apiClient: ApiClient, basePath?: string): TaskBoardService;
|
|
306
|
+
|
|
307
|
+
interface TaskBoardConfig {
|
|
308
|
+
/** Axios-like API client with auth headers pre-configured */
|
|
309
|
+
apiClient: ApiClient;
|
|
310
|
+
/** Current logged-in user */
|
|
311
|
+
user: TaskBoardUser;
|
|
312
|
+
/** Available projects (if not provided, derived from user.apps) */
|
|
313
|
+
projects?: Project[];
|
|
314
|
+
/** Column configuration (defaults to 8-column kanban) */
|
|
315
|
+
columns?: ColumnConfig[];
|
|
316
|
+
/** Priority levels (defaults to Critical/High/Medium/Low) */
|
|
317
|
+
priorities?: PriorityConfig[];
|
|
318
|
+
/** Predefined tags (defaults to 6 built-in tags) */
|
|
319
|
+
tags?: TagConfig[];
|
|
320
|
+
/** Base API path (defaults to '/api/v1/taskboard') */
|
|
321
|
+
apiBasePath?: string;
|
|
322
|
+
/** Callbacks */
|
|
323
|
+
onTaskCreate?: (task: Task) => void;
|
|
324
|
+
onTaskUpdate?: (task: Task) => void;
|
|
325
|
+
onTaskDelete?: (taskId: string) => void;
|
|
326
|
+
onError?: (error: Error) => void;
|
|
327
|
+
onNavigate?: (path: string) => void;
|
|
328
|
+
/** Feature flags */
|
|
329
|
+
features?: {
|
|
330
|
+
dragAndDrop?: boolean;
|
|
331
|
+
comments?: boolean;
|
|
332
|
+
mentions?: boolean;
|
|
333
|
+
notifications?: boolean;
|
|
334
|
+
internalComments?: boolean;
|
|
335
|
+
tags?: boolean;
|
|
336
|
+
sharing?: boolean;
|
|
337
|
+
filters?: boolean;
|
|
338
|
+
unreadIndicators?: boolean;
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
interface TaskBoardContextValue {
|
|
342
|
+
service: TaskBoardService;
|
|
343
|
+
user: TaskBoardUser;
|
|
344
|
+
projects: Project[];
|
|
345
|
+
columns: ColumnConfig[];
|
|
346
|
+
priorities: PriorityConfig[];
|
|
347
|
+
tags: TagConfig[];
|
|
348
|
+
config: TaskBoardConfig;
|
|
349
|
+
features: Required<NonNullable<TaskBoardConfig['features']>>;
|
|
350
|
+
}
|
|
351
|
+
declare function useTaskBoardContext(): TaskBoardContextValue;
|
|
352
|
+
declare function TaskBoardProvider({ children, ...config }: TaskBoardConfig & {
|
|
353
|
+
children: React__default.ReactNode;
|
|
354
|
+
}): react_jsx_runtime.JSX.Element;
|
|
355
|
+
|
|
356
|
+
declare function useTaskBoard(): {
|
|
357
|
+
projects: Project[];
|
|
358
|
+
selectedProject: string;
|
|
359
|
+
setSelectedProject: React$1.Dispatch<React$1.SetStateAction<string>>;
|
|
360
|
+
tasks: TasksByStatus;
|
|
361
|
+
setTasks: React$1.Dispatch<React$1.SetStateAction<TasksByStatus>>;
|
|
362
|
+
columnTotals: ColumnTotals;
|
|
363
|
+
columnUnreads: ColumnUnreads;
|
|
364
|
+
setColumnUnreads: React$1.Dispatch<React$1.SetStateAction<ColumnUnreads>>;
|
|
365
|
+
boardLoading: boolean;
|
|
366
|
+
loadingMore: Record<string, boolean>;
|
|
367
|
+
error: string;
|
|
368
|
+
setError: React$1.Dispatch<React$1.SetStateAction<string>>;
|
|
369
|
+
successMessage: string;
|
|
370
|
+
showSuccess: (msg: string) => void;
|
|
371
|
+
fetchTasks: () => Promise<void>;
|
|
372
|
+
loadMoreTasks: (statusKey: string) => Promise<void>;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
declare function useTaskActions(tasks: TasksByStatus, setTasks: React.Dispatch<React.SetStateAction<TasksByStatus>>, fetchTasks: () => Promise<void>): {
|
|
376
|
+
createTask: (data: CreateTaskPayload) => Promise<Task>;
|
|
377
|
+
updateTask: (taskId: string, data: UpdateTaskPayload) => Promise<Task>;
|
|
378
|
+
deleteTask: (taskId: string) => Promise<void>;
|
|
379
|
+
markTaskRead: (taskId: string) => Promise<void>;
|
|
380
|
+
moveTask: (taskId: string, sourceStatus: string, destStatus: string, sourceIndex: number, destIndex: number) => Promise<void>;
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
declare function useTaskDetail(taskId: string): {
|
|
384
|
+
comments: Comment[];
|
|
385
|
+
activity: ActivityEntry[];
|
|
386
|
+
commentsLoaded: boolean;
|
|
387
|
+
commentLoading: boolean;
|
|
388
|
+
addComment: (content: string, isInternal?: boolean) => Promise<void>;
|
|
389
|
+
editComment: (commentId: string, content: string) => Promise<void>;
|
|
390
|
+
deleteComment: (commentId: string) => Promise<void>;
|
|
391
|
+
saveField: (field: string, value: unknown) => Promise<void>;
|
|
392
|
+
refreshDetail: () => Promise<void>;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
declare function useShareLink(): {
|
|
396
|
+
copiedTaskId: string | null;
|
|
397
|
+
copyShareLink: (taskId: string, projectSlug: string) => void;
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
declare function getPriorityStyle(priority: string): PriorityConfig;
|
|
401
|
+
declare function getTagStyle(tag: string): TagConfig;
|
|
402
|
+
declare function getInitials(name: string): string;
|
|
403
|
+
declare function formatDate(dateStr: string): string;
|
|
404
|
+
declare function formatDateTime(dateStr: string): string;
|
|
405
|
+
declare function getDescriptionPreview(desc: StructuredDescription | string | undefined): string;
|
|
406
|
+
declare function hasDescription(desc: StructuredDescription | string | undefined): boolean;
|
|
407
|
+
declare function getUserProjects(apps: string[], allProjects: {
|
|
408
|
+
slug: string;
|
|
409
|
+
name: string;
|
|
410
|
+
}[]): {
|
|
411
|
+
slug: string;
|
|
412
|
+
name: string;
|
|
413
|
+
}[];
|
|
414
|
+
|
|
415
|
+
declare const DEFAULT_COLUMNS: ColumnConfig[];
|
|
416
|
+
declare const DEFAULT_PRIORITIES: PriorityConfig[];
|
|
417
|
+
declare const PREDEFINED_TAGS: TagConfig[];
|
|
418
|
+
declare const DESCRIPTION_SECTIONS: DescriptionSectionConfig[];
|
|
419
|
+
declare const EMPTY_DESCRIPTION: StructuredDescription;
|
|
420
|
+
declare const POSITION_GAP = 1000;
|
|
421
|
+
declare const DEFAULT_PAGE_SIZE = 10;
|
|
422
|
+
|
|
423
|
+
interface IconProps {
|
|
424
|
+
className?: string;
|
|
425
|
+
size?: number;
|
|
426
|
+
strokeWidth?: number;
|
|
427
|
+
}
|
|
428
|
+
declare const PlusIcon: React__default.FC<IconProps>;
|
|
429
|
+
declare const XIcon: React__default.FC<IconProps>;
|
|
430
|
+
declare const ChevronDownIcon: React__default.FC<IconProps>;
|
|
431
|
+
declare const MessageSquareIcon: React__default.FC<IconProps>;
|
|
432
|
+
declare const KanbanIcon: React__default.FC<IconProps>;
|
|
433
|
+
declare const LinkIcon: React__default.FC<IconProps>;
|
|
434
|
+
declare const CheckIcon: React__default.FC<IconProps>;
|
|
435
|
+
declare const BellIcon: React__default.FC<IconProps>;
|
|
436
|
+
declare const FilterIcon: React__default.FC<IconProps>;
|
|
437
|
+
declare const PencilIcon: React__default.FC<IconProps>;
|
|
438
|
+
declare const TrashIcon: React__default.FC<IconProps>;
|
|
439
|
+
declare const LockIcon: React__default.FC<IconProps>;
|
|
440
|
+
declare const FeedbackIcon: React__default.FC<IconProps>;
|
|
441
|
+
|
|
442
|
+
export { type ActivityEntry, type ApiClient, type ApiClientConfig, BellIcon, BoardSkeleton, CheckIcon, ChevronDownIcon, type ColumnConfig, type ColumnResponse, type ColumnTotals, type ColumnUnreads, type Comment, type CreateCommentPayload, CreateTaskModal, type CreateTaskModalProps, type CreateTaskPayload, DEFAULT_COLUMNS, DEFAULT_PAGE_SIZE, DEFAULT_PRIORITIES, DESCRIPTION_SECTIONS, type DescriptionSectionConfig, EMPTY_DESCRIPTION, type EditCommentPayload, FeedbackIcon, FilterBar, type FilterBarProps, FilterIcon, KanbanColumn, type KanbanColumnProps, KanbanIcon, LinkIcon, LockIcon, MentionText, MentionTextarea, type MentionTextareaProps, type MentionUser, MessageSquareIcon, type Notification, NotificationBell, type NotificationBellProps, type NotificationCountResponse, POSITION_GAP, PREDEFINED_TAGS, PencilIcon, PlusIcon, PriorityBadge, type PriorityBadgeProps, type PriorityConfig, type Project, SkeletonCard, SkeletonPulse, type StructuredDescription, TagBadge, type TagBadgeProps, type TagConfig, type Task, TaskBoard, type TaskBoardConfig, type TaskBoardContextValue, type TaskBoardProps, TaskBoardProvider, type TaskBoardService, type TaskBoardUser, TaskCard, type TaskCardProps, TaskDetailPanel, type TaskDetailPanelProps, type TaskDetailResponse, type TasksByStatus, TrashIcon, type UpdateTaskPayload, UserAvatar, type UserAvatarProps, XIcon, createTaskBoardService, formatDate, formatDateTime, getDescriptionPreview, getInitials, getPriorityStyle, getTagStyle, getUserProjects, hasDescription, toDisplayText, toStoredText, useShareLink, useTaskActions, useTaskBoard, useTaskBoardContext, useTaskDetail };
|