@ganttloom/gantt-core 0.2.0 → 0.4.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 +147 -5
- package/dist/index.cjs +364 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -1
- package/dist/index.d.ts +69 -1
- package/dist/index.js +364 -44
- package/dist/index.js.map +1 -1
- package/dist/styles.css +51 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
# @ganttloom/gantt-core
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@ganttloom/gantt-core)
|
|
4
|
+
[](../../LICENSE)
|
|
5
|
+
|
|
3
6
|
Framework-agnostic Gantt chart engine: layout, SVG rendering, drag/resize/link
|
|
4
7
|
interactions, grouping, critical path, undo/redo, and more — zero runtime
|
|
5
|
-
dependencies. If you're using React, prefer
|
|
6
|
-
[`@ganttloom/gantt-react`](../gantt-react)
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
dependencies. If you're using React or Vue, prefer
|
|
9
|
+
[`@ganttloom/gantt-react`](../gantt-react) or
|
|
10
|
+
[`@ganttloom/gantt-vue`](../gantt-vue); use this package directly if you're
|
|
11
|
+
integrating with something else (Svelte, vanilla JS) or want full control
|
|
12
|
+
over the DOM lifecycle.
|
|
13
|
+
|
|
14
|
+

|
|
9
15
|
|
|
10
16
|
## Install
|
|
11
17
|
|
|
@@ -186,6 +192,30 @@ reorder columns. The chart applies the change to its own internal copy of
|
|
|
186
192
|
`columns` immediately (so the drag feels live) and calls back so you can
|
|
187
193
|
persist it — same pattern as a task drag and `onDateChange`.
|
|
188
194
|
|
|
195
|
+
## Grid column sorting
|
|
196
|
+
|
|
197
|
+
Mark a column `sortable: true` and clicking its header cycles ascending →
|
|
198
|
+
descending → none, with a `▲`/`▼` indicator:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
new GanttChart(container, tasks, deps, {
|
|
202
|
+
columns: [
|
|
203
|
+
{ id: "name", title: "Task", sortable: true },
|
|
204
|
+
{ id: "assignee", title: "Assignee", accessor: (t) => t.assignees?.[0]?.name, sortable: true },
|
|
205
|
+
],
|
|
206
|
+
onSortChange: (sort) => console.log(sort), // { columnId, direction } | null
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
chart.setSort("assignee", "desc"); // or null to clear
|
|
210
|
+
chart.getSort(); // { columnId: "assignee", direction: "desc" } | null
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Sorting reorders **siblings at every tree level** by the column's value (via
|
|
214
|
+
`accessor`, or `task.name` for the conventional unaccessored "name" column)
|
|
215
|
+
— the group/parent hierarchy itself is never reshuffled, only the order
|
|
216
|
+
within it. A column with neither `accessor` nor the id `"name"` has nothing
|
|
217
|
+
sortable to read and is a no-op if marked sortable.
|
|
218
|
+
|
|
189
219
|
## Task search/filter
|
|
190
220
|
|
|
191
221
|
```ts
|
|
@@ -246,6 +276,39 @@ link fires `onDependencyDblClick` — the engine has no built-in "edit link"
|
|
|
246
276
|
popover (keeping with zero-dependency, minimal-UI scope), so build your own
|
|
247
277
|
and call `chart.updateDependency(...)` (undoable) to apply the result.
|
|
248
278
|
|
|
279
|
+
Double-clicking a task bar itself (not a link) fires the separate
|
|
280
|
+
`onTaskDblClick(task)` — also off by default until you supply a handler.
|
|
281
|
+
|
|
282
|
+
## Filling the viewport at any zoom level
|
|
283
|
+
|
|
284
|
+
A short project at month/year zoom, or a chart with just a handful of
|
|
285
|
+
tasks, naturally renders narrow — the timeline's pixel width is purely a
|
|
286
|
+
function of the task date range and the current zoom, with no awareness of
|
|
287
|
+
how much horizontal space is actually available. Set
|
|
288
|
+
`autoFitToViewport: true` to stretch (never shrink) the timeline so it
|
|
289
|
+
fills the container instead of leaving empty space to the right:
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
new GanttChart(container, tasks, deps, { autoFitToViewport: true });
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Re-evaluated on view-mode/task changes and on container resize (via
|
|
296
|
+
`ResizeObserver`). It never applies if the content is already wider than
|
|
297
|
+
the container — that's what normal horizontal scrolling is for. Off by
|
|
298
|
+
default, so upgrading doesn't silently change an existing chart's pixel
|
|
299
|
+
layout for anyone who hasn't opted in.
|
|
300
|
+
|
|
301
|
+
Separately, and always on: a short project at a coarse zoom no longer
|
|
302
|
+
renders as one or two lonely ticks. The visible date range is padded out to
|
|
303
|
+
a sensible minimum column count per zoom level (year: 5, quarter: 4,
|
|
304
|
+
month/week: 6, day: 7, hour: 8), so a 3-month project at year zoom still
|
|
305
|
+
shows a real multi-year timeline instead of a cramped sliver. Wider ranges
|
|
306
|
+
are unaffected — this only ever pads, never trims.
|
|
307
|
+
|
|
308
|
+
The timeline's date header also stays pinned to the top of the chart while
|
|
309
|
+
you scroll a tall task list vertically (it still scrolls horizontally in
|
|
310
|
+
sync with the bars), instead of scrolling out of view along with the rows.
|
|
311
|
+
|
|
249
312
|
## Multi-select and bulk actions
|
|
250
313
|
|
|
251
314
|
```ts
|
|
@@ -277,10 +340,39 @@ Dragging the whole task shifts every segment together; resizing an edge
|
|
|
277
340
|
only adjusts the first (left) or last (right) segment's outer edge, leaving
|
|
278
341
|
any gap untouched.
|
|
279
342
|
|
|
343
|
+
## Hover tooltips
|
|
344
|
+
|
|
345
|
+
Every bar shows a floating, CSS-customizable tooltip on hover (name, dates,
|
|
346
|
+
progress, assignees, and `task.notes` if set) — not the browser's native
|
|
347
|
+
`title` tooltip, so it's fully styleable:
|
|
348
|
+
|
|
349
|
+
```css
|
|
350
|
+
.gantt-tooltip { background: #111827; border-radius: 8px; }
|
|
351
|
+
.gantt-tooltip-title { font-weight: 700; }
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
For full control over markup, `renderTooltip` works exactly like
|
|
355
|
+
`GanttColumn.render` — return an `HTMLElement` to mount directly, a string
|
|
356
|
+
(rendered as text, never parsed as HTML), or `null`/`undefined` to suppress
|
|
357
|
+
the tooltip for that specific task:
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
new GanttChart(el, tasks, deps, {
|
|
361
|
+
renderTooltip: (task) => {
|
|
362
|
+
if (task.isMilestone) return null; // no tooltip on milestones
|
|
363
|
+
const div = document.createElement("div");
|
|
364
|
+
div.textContent = `${task.name} — ${task.progress ?? 0}%`;
|
|
365
|
+
return div;
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Set `showTooltip: false` to disable it entirely.
|
|
371
|
+
|
|
280
372
|
## Task notes, auto-color, baseline history, and density presets
|
|
281
373
|
|
|
282
374
|
```ts
|
|
283
|
-
{ id: "t1", name: "Ship v2", start, end, notes: "Blocked on legal review" } //
|
|
375
|
+
{ id: "t1", name: "Ship v2", start, end, notes: "Blocked on legal review" } // shown as an extra line in the default tooltip
|
|
284
376
|
```
|
|
285
377
|
|
|
286
378
|
```ts
|
|
@@ -381,6 +473,56 @@ in addition to the JS `theme` option (`Partial<GanttTheme>`) — style via
|
|
|
381
473
|
either, or both. `colorScheme: "auto"` (the default) follows
|
|
382
474
|
`prefers-color-scheme` live.
|
|
383
475
|
|
|
476
|
+
To override a token via CSS, target `.gantt-root` itself (the element the
|
|
477
|
+
chart renders into) rather than an ancestor — the defaults are declared on
|
|
478
|
+
`.gantt-root`, and a same-element declaration always wins over one inherited
|
|
479
|
+
from a parent, regardless of specificity:
|
|
480
|
+
|
|
481
|
+
```css
|
|
482
|
+
.gantt-root {
|
|
483
|
+
--gantt-bar-color: #16a34a;
|
|
484
|
+
--gantt-critical-color: #ea580c;
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
### Styling structural elements (buttons, cells, rows)
|
|
489
|
+
|
|
490
|
+
Beyond color tokens, every structural/interactive element the chart renders
|
|
491
|
+
has a stable, undocumented-nowhere-else class name and **no inline styles
|
|
492
|
+
and no `!important`** — so plain CSS targeting these classes has full
|
|
493
|
+
control, same as any element you'd render yourself:
|
|
494
|
+
|
|
495
|
+
| Class | What it is |
|
|
496
|
+
|---|---|
|
|
497
|
+
| `.gantt-toggle` | The expand/collapse button on a group row |
|
|
498
|
+
| `.gantt-grid-header-cell` | A column header cell |
|
|
499
|
+
| `.gantt-grid-cell` | A grid body cell |
|
|
500
|
+
| `.gantt-grid-row` | A grid body row (has a default `:hover` background) |
|
|
501
|
+
| `.gantt-rename-input` | The inline text input shown while renaming a task |
|
|
502
|
+
| `.gantt-tooltip` | The floating hover tooltip's container (see "Hover tooltips" above) |
|
|
503
|
+
| `.gantt-tooltip-title` / `.gantt-tooltip-row` / `.gantt-tooltip-notes` | Elements inside the *default* tooltip content — irrelevant if you use `renderTooltip` |
|
|
504
|
+
|
|
505
|
+
For example, to make the expand/collapse toggle look like a small round
|
|
506
|
+
button instead of bare text:
|
|
507
|
+
|
|
508
|
+
```css
|
|
509
|
+
.gantt-toggle {
|
|
510
|
+
border-radius: 999px;
|
|
511
|
+
padding: 2px 6px;
|
|
512
|
+
background: var(--gantt-grid-color, #e5e7eb);
|
|
513
|
+
}
|
|
514
|
+
.gantt-toggle:hover {
|
|
515
|
+
background: var(--gantt-bar-color, #3b82f6);
|
|
516
|
+
color: #fff;
|
|
517
|
+
}
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
None of this is specific to the library's own chrome, either — anything
|
|
521
|
+
*you* render, like the playground demo's toolbar (`apps/playground`,
|
|
522
|
+
`apps/vue-playground`), is plain HTML/CSS in your own app code with no
|
|
523
|
+
library involvement at all, so it's exactly as customizable as any other
|
|
524
|
+
element on your page.
|
|
525
|
+
|
|
384
526
|
## API surface
|
|
385
527
|
|
|
386
528
|
The full, current type/function list is re-exported from
|