@libxai/board 0.16.4 → 0.16.6
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 +324 -29
- package/dist/index.cjs +19 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +19 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,16 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://libxai.com/logo.svg" alt="LibXAI Board" width="120" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">@libxai/board</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Professional Gantt Chart + Kanban Board for React</strong><br>
|
|
9
|
+
Production-ready. TypeScript. Zero configuration.
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<a href="https://www.npmjs.com/package/@libxai/board"><img src="https://img.shields.io/npm/v/@libxai/board.svg" alt="npm version"></a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/@libxai/board"><img src="https://img.shields.io/npm/dm/@libxai/board.svg" alt="npm downloads"></a>
|
|
15
|
+
<a href="https://github.com/libxai/libxai-suite/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-BUSL--1.1-blue.svg" alt="license"></a>
|
|
16
|
+
<a href="https://github.com/libxai/libxai-suite"><img src="https://img.shields.io/github/stars/libxai/libxai-suite?style=social" alt="GitHub stars"></a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Why LibXAI Board?
|
|
22
|
+
|
|
23
|
+
| Feature | LibXAI | DHTMLX | Bryntum |
|
|
24
|
+
|---------|--------|--------|---------|
|
|
25
|
+
| **Critical Path (CPM)** | FREE | $1,299/dev | $2,995/dev |
|
|
26
|
+
| **Auto-Scheduling** | FREE | Manual config | Manual config |
|
|
27
|
+
| **Split Tasks** | FREE | Not available | Premium only |
|
|
28
|
+
| **i18n (EN/ES)** | Built-in | Manual | Manual |
|
|
29
|
+
| **TypeScript** | Full types | Partial | Partial |
|
|
30
|
+
| **React Native** | Coming soon | No | No |
|
|
6
31
|
|
|
7
|
-
|
|
8
|
-
- **AI-Powered**: Optional AI features for plan generation, risk prediction, and more
|
|
9
|
-
- **Keyboard First**: Full keyboard navigation support
|
|
10
|
-
- **Customizable**: Styled by default, fully customizable via render props
|
|
11
|
-
- **Tiny Bundle**: <100KB gzipped core (AI features optional)
|
|
12
|
-
- **Type Safe**: Written in TypeScript with complete type definitions
|
|
13
|
-
- **Framework Agnostic Backend**: Works with any backend (Supabase, Firebase, REST, GraphQL)
|
|
32
|
+
---
|
|
14
33
|
|
|
15
34
|
## Installation
|
|
16
35
|
|
|
@@ -23,45 +42,321 @@ For AI features (optional):
|
|
|
23
42
|
npm install ai
|
|
24
43
|
```
|
|
25
44
|
|
|
45
|
+
---
|
|
46
|
+
|
|
26
47
|
## Quick Start
|
|
27
48
|
|
|
49
|
+
### Gantt Chart
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { GanttBoard } from '@libxai/board';
|
|
53
|
+
import '@libxai/board/styles.css';
|
|
54
|
+
|
|
55
|
+
function App() {
|
|
56
|
+
const [tasks, setTasks] = useState([
|
|
57
|
+
{
|
|
58
|
+
id: '1',
|
|
59
|
+
name: 'Project Planning',
|
|
60
|
+
startDate: new Date('2024-01-01'),
|
|
61
|
+
endDate: new Date('2024-01-15'),
|
|
62
|
+
progress: 50,
|
|
63
|
+
status: 'in-progress',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: '2',
|
|
67
|
+
name: 'Development',
|
|
68
|
+
startDate: new Date('2024-01-16'),
|
|
69
|
+
endDate: new Date('2024-02-15'),
|
|
70
|
+
progress: 0,
|
|
71
|
+
status: 'todo',
|
|
72
|
+
dependencies: ['1'], // Depends on task 1
|
|
73
|
+
},
|
|
74
|
+
]);
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<GanttBoard
|
|
78
|
+
tasks={tasks}
|
|
79
|
+
onTasksChange={setTasks}
|
|
80
|
+
config={{
|
|
81
|
+
theme: 'dark',
|
|
82
|
+
locale: 'es', // Spanish UI
|
|
83
|
+
timeScale: 'week',
|
|
84
|
+
|
|
85
|
+
// Callbacks for persistence
|
|
86
|
+
onTaskUpdate: async (task) => {
|
|
87
|
+
await saveToDatabase(task);
|
|
88
|
+
},
|
|
89
|
+
onMultiTaskDelete: async (taskIds) => {
|
|
90
|
+
await deleteFromDatabase(taskIds);
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
// Permissions (CASL compatible)
|
|
94
|
+
permissions: {
|
|
95
|
+
canCreateTask: true,
|
|
96
|
+
canUpdateTask: true,
|
|
97
|
+
canDeleteTask: true,
|
|
98
|
+
},
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Kanban Board
|
|
106
|
+
|
|
28
107
|
```tsx
|
|
29
|
-
import { KanbanBoard, useKanbanState } from '@libxai/board'
|
|
30
|
-
import '@libxai/board/styles.css'
|
|
108
|
+
import { KanbanBoard, useKanbanState } from '@libxai/board';
|
|
109
|
+
import '@libxai/board/styles.css';
|
|
31
110
|
|
|
32
111
|
function App() {
|
|
33
112
|
const { board, callbacks } = useKanbanState({
|
|
34
113
|
initialBoard: {
|
|
35
114
|
id: 'my-board',
|
|
36
115
|
columns: [
|
|
37
|
-
{ id: '
|
|
38
|
-
{ id: '
|
|
116
|
+
{ id: 'todo', title: 'To Do', position: 1000, cardIds: [] },
|
|
117
|
+
{ id: 'doing', title: 'In Progress', position: 2000, cardIds: [] },
|
|
118
|
+
{ id: 'done', title: 'Done', position: 3000, cardIds: [] },
|
|
39
119
|
],
|
|
40
|
-
cards: []
|
|
41
|
-
}
|
|
42
|
-
})
|
|
120
|
+
cards: [],
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
return <KanbanBoard board={board} callbacks={callbacks} />;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Features
|
|
131
|
+
|
|
132
|
+
### Gantt Chart
|
|
133
|
+
|
|
134
|
+
- **40+ Callbacks** for full integration with any backend
|
|
135
|
+
- **Critical Path Method (CPM)** - Automatic calculation, FREE
|
|
136
|
+
- **Auto-Scheduling** - Dependency cascade on drag
|
|
137
|
+
- **Split Tasks** - Pause work with gaps (Bryntum-style)
|
|
138
|
+
- **Dependencies** - SS, FF, SF, FS with circular detection
|
|
139
|
+
- **Export** - PDF, Excel, PNG, CSV
|
|
140
|
+
- **Zoom Levels** - Hour, Day, Week, Month, Quarter, Year
|
|
141
|
+
- **Undo/Redo** - 50 levels of history
|
|
142
|
+
- **Multi-level Hierarchy** - Unlimited nesting
|
|
143
|
+
- **Milestones** - Diamond markers
|
|
144
|
+
- **Today Line** - Visual indicator
|
|
145
|
+
|
|
146
|
+
### Kanban Board
|
|
147
|
+
|
|
148
|
+
- **Drag & Drop** - Powered by @dnd-kit
|
|
149
|
+
- **Virtual Scrolling** - Handle 10,000+ cards
|
|
150
|
+
- **Filtering & Search** - Advanced queries
|
|
151
|
+
- **Multi-select** - Bulk operations
|
|
152
|
+
- **Command Palette** - Cmd+K / Ctrl+K
|
|
153
|
+
- **Import/Export** - JSON, CSV, PDF
|
|
154
|
+
|
|
155
|
+
### Core
|
|
156
|
+
|
|
157
|
+
- **TypeScript** - Complete type definitions
|
|
158
|
+
- **Themes** - Dark, Light, Neutral (or custom)
|
|
159
|
+
- **i18n** - English, Spanish (extensible)
|
|
160
|
+
- **Accessibility** - WCAG AA compliant
|
|
161
|
+
- **Keyboard Shortcuts** - Full navigation
|
|
162
|
+
- **Zero Config** - Works out of the box
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Configuration
|
|
167
|
+
|
|
168
|
+
### GanttBoard Config
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
interface GanttConfig {
|
|
172
|
+
// Appearance
|
|
173
|
+
theme?: 'dark' | 'light' | 'neutral';
|
|
174
|
+
locale?: 'en' | 'es';
|
|
175
|
+
timeScale?: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year';
|
|
176
|
+
rowDensity?: 'compact' | 'comfortable' | 'spacious';
|
|
177
|
+
|
|
178
|
+
// Features
|
|
179
|
+
enableAutoCriticalPath?: boolean;
|
|
180
|
+
showThemeSelector?: boolean;
|
|
181
|
+
showCreateTaskButton?: boolean;
|
|
182
|
+
|
|
183
|
+
// Permissions (CASL compatible)
|
|
184
|
+
permissions?: {
|
|
185
|
+
canCreateTask?: boolean;
|
|
186
|
+
canUpdateTask?: boolean;
|
|
187
|
+
canDeleteTask?: boolean;
|
|
188
|
+
canReorderTasks?: boolean;
|
|
189
|
+
canExport?: boolean;
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Callbacks
|
|
193
|
+
onTaskClick?: (task: Task) => void;
|
|
194
|
+
onTaskDblClick?: (task: Task) => void;
|
|
195
|
+
onTaskUpdate?: (task: Task) => void;
|
|
196
|
+
onMultiTaskDelete?: (taskIds: string[]) => void;
|
|
197
|
+
onProgressChange?: (taskId: string, oldProgress: number, newProgress: number) => void;
|
|
198
|
+
|
|
199
|
+
// Context Menu Callbacks (v0.16.0+)
|
|
200
|
+
onTaskEdit?: (task: Task) => void;
|
|
201
|
+
onTaskAddSubtask?: (parentTask: Task) => void;
|
|
202
|
+
onTaskMarkIncomplete?: (task: Task) => void;
|
|
203
|
+
onTaskSetInProgress?: (task: Task) => void;
|
|
204
|
+
|
|
205
|
+
// AI Assistant (optional)
|
|
206
|
+
aiAssistant?: {
|
|
207
|
+
enabled: boolean;
|
|
208
|
+
onCommand: (command: string) => Promise<AIResponse>;
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Task Type
|
|
43
214
|
|
|
44
|
-
|
|
215
|
+
```tsx
|
|
216
|
+
interface Task {
|
|
217
|
+
id: string;
|
|
218
|
+
name: string;
|
|
219
|
+
startDate?: Date;
|
|
220
|
+
endDate?: Date;
|
|
221
|
+
progress?: number; // 0-100
|
|
222
|
+
status?: 'todo' | 'in-progress' | 'completed';
|
|
223
|
+
color?: string; // Custom color
|
|
224
|
+
isMilestone?: boolean;
|
|
225
|
+
parentId?: string; // For subtasks
|
|
226
|
+
dependencies?: string[]; // Task IDs
|
|
227
|
+
assignees?: Array<{ id: string; name: string; initials: string; color: string }>;
|
|
228
|
+
subtasks?: Task[]; // Nested tasks
|
|
45
229
|
}
|
|
46
230
|
```
|
|
47
231
|
|
|
48
|
-
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Internationalization (i18n)
|
|
235
|
+
|
|
236
|
+
Built-in support for English and Spanish:
|
|
237
|
+
|
|
238
|
+
```tsx
|
|
239
|
+
<GanttBoard
|
|
240
|
+
config={{
|
|
241
|
+
locale: 'es', // Spanish
|
|
242
|
+
customTranslations: {
|
|
243
|
+
// Override specific strings
|
|
244
|
+
toolbar: {
|
|
245
|
+
createTask: 'Crear Nueva Tarea',
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
}}
|
|
249
|
+
/>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Adding New Languages
|
|
49
253
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
254
|
+
```tsx
|
|
255
|
+
const frenchTranslations = {
|
|
256
|
+
columns: { taskName: 'Nom de la tâche', ... },
|
|
257
|
+
toolbar: { createTask: 'Nouvelle tâche', ... },
|
|
258
|
+
contextMenu: { editTask: 'Modifier', ... },
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
<GanttBoard
|
|
262
|
+
config={{
|
|
263
|
+
locale: 'en', // Base
|
|
264
|
+
customTranslations: frenchTranslations,
|
|
265
|
+
}}
|
|
266
|
+
/>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Imperative API
|
|
272
|
+
|
|
273
|
+
Access methods via ref:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
import { GanttBoard, GanttBoardRef } from '@libxai/board';
|
|
277
|
+
|
|
278
|
+
function App() {
|
|
279
|
+
const ganttRef = useRef<GanttBoardRef>(null);
|
|
280
|
+
|
|
281
|
+
const handleAddTask = () => {
|
|
282
|
+
ganttRef.current?.addTask({
|
|
283
|
+
name: 'New Task',
|
|
284
|
+
startDate: new Date(),
|
|
285
|
+
endDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
return (
|
|
290
|
+
<>
|
|
291
|
+
<button onClick={handleAddTask}>Add Task</button>
|
|
292
|
+
<button onClick={() => ganttRef.current?.undo()}>Undo</button>
|
|
293
|
+
<button onClick={() => ganttRef.current?.exportToPDF()}>Export PDF</button>
|
|
294
|
+
<GanttBoard ref={ganttRef} tasks={tasks} />
|
|
295
|
+
</>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Available Methods
|
|
301
|
+
|
|
302
|
+
- `addTask(task)`, `updateTask(id, updates)`, `deleteTask(id)`
|
|
303
|
+
- `splitTask(id, splitDate, gapDays)`
|
|
304
|
+
- `calculateCriticalPath()`
|
|
305
|
+
- `undo()`, `redo()`
|
|
306
|
+
- `exportToPDF()`, `exportToExcel()`, `exportToPNG()`, `exportToCSV()`
|
|
307
|
+
- `setZoom(level)`, `scrollToTask(id)`, `scrollToToday()`
|
|
308
|
+
|
|
309
|
+
---
|
|
53
310
|
|
|
54
311
|
## Performance
|
|
55
312
|
|
|
56
|
-
- Renders 1,000
|
|
57
|
-
-
|
|
58
|
-
- Automatic virtualization for large
|
|
59
|
-
-
|
|
313
|
+
- Renders 1,000 tasks in <1 second
|
|
314
|
+
- 60 FPS during drag operations
|
|
315
|
+
- Automatic virtualization for large datasets
|
|
316
|
+
- Tree-shaking ready (ESM + CJS)
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## Bundle Size
|
|
321
|
+
|
|
322
|
+
| Import | Size (gzip) |
|
|
323
|
+
|--------|-------------|
|
|
324
|
+
| GanttBoard only | ~80KB |
|
|
325
|
+
| KanbanBoard only | ~60KB |
|
|
326
|
+
| Full package | ~120KB |
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## Browser Support
|
|
331
|
+
|
|
332
|
+
- Chrome 90+
|
|
333
|
+
- Firefox 90+
|
|
334
|
+
- Safari 14+
|
|
335
|
+
- Edge 90+
|
|
336
|
+
|
|
337
|
+
---
|
|
60
338
|
|
|
61
339
|
## License
|
|
62
340
|
|
|
63
|
-
Business Source License 1.1 -
|
|
341
|
+
**Business Source License 1.1 (BUSL-1.1)**
|
|
342
|
+
|
|
343
|
+
- Free for non-production use
|
|
344
|
+
- Commercial license required for production
|
|
345
|
+
- Converts to Apache 2.0 on October 12, 2027
|
|
346
|
+
|
|
347
|
+
[View full license](./LICENSE)
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## Links
|
|
352
|
+
|
|
353
|
+
- [NPM Package](https://www.npmjs.com/package/@libxai/board)
|
|
354
|
+
- [GitHub Repository](https://github.com/libxai/libxai-suite)
|
|
355
|
+
- [Changelog](./CHANGELOG.md)
|
|
356
|
+
- [Issue Tracker](https://github.com/libxai/libxai-suite/issues)
|
|
64
357
|
|
|
65
|
-
|
|
358
|
+
---
|
|
66
359
|
|
|
67
|
-
|
|
360
|
+
<p align="center">
|
|
361
|
+
Made with care by <a href="https://libxai.com">LibXAI</a>
|
|
362
|
+
</p>
|