gantt-lib 0.86.1 → 0.87.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/dist/index.d.mts CHANGED
@@ -303,7 +303,7 @@ declare const progressInRange: (min: number, max: number) => TaskPredicate;
303
303
  */
304
304
  declare const nameContains: (substring: string, caseSensitive?: boolean) => TaskPredicate;
305
305
 
306
- type BuiltInTaskListColumnId = 'number' | 'name' | 'startDate' | 'endDate' | 'duration' | 'progress' | 'dependencies' | 'actions';
306
+ type BuiltInTaskListColumnId = 'selection' | 'number' | 'name' | 'startDate' | 'endDate' | 'duration' | 'progress' | 'dependencies' | 'actions';
307
307
  type TaskListColumnId = BuiltInTaskListColumnId | (string & {});
308
308
  type TaskListColumnAnchor = {
309
309
  after: BuiltInTaskListColumnId | string;
@@ -495,6 +495,12 @@ interface GanttModeProps<TTask extends Task = Task> {
495
495
  onToggleCollapse?: (parentId: string) => void;
496
496
  /** Task IDs to highlight in the task list (for search results) */
497
497
  highlightedTaskIds?: Set<string>;
498
+ /** Enable a leading checkbox column for multi-selecting task rows (default: false) */
499
+ enableTaskMultiSelect?: boolean;
500
+ /** Controlled selected task IDs for multi-select mode */
501
+ selectedTaskIds?: Set<string>;
502
+ /** Callback when multi-selected task IDs change */
503
+ onSelectedTaskIdsChange?: (taskIds: Set<string>) => void;
498
504
  /** Disable task drag and resize on the calendar grid (default: false) */
499
505
  disableTaskDrag?: boolean;
500
506
  /** Show calendar chart area (default: true) */
@@ -766,6 +772,12 @@ interface TaskListProps {
766
772
  businessDays?: boolean;
767
773
  /** Task IDs highlighted by the active filter */
768
774
  highlightedTaskIds?: Set<string>;
775
+ /** Enable a leading checkbox column for multi-selecting task rows (default: false) */
776
+ enableTaskMultiSelect?: boolean;
777
+ /** Controlled selected task IDs for multi-select mode */
778
+ selectedTaskIds?: Set<string>;
779
+ /** Callback when multi-selected task IDs change */
780
+ onSelectedTaskIdsChange?: (taskIds: Set<string>) => void;
769
781
  /** Filter mode: 'highlight' shows yellow highlight on matches, 'hide' hides non-matching tasks */
770
782
  filterMode?: 'highlight' | 'hide';
771
783
  /** Task IDs that match the filter (used for hide mode). When undefined, no filtering is applied */
package/dist/index.d.ts CHANGED
@@ -303,7 +303,7 @@ declare const progressInRange: (min: number, max: number) => TaskPredicate;
303
303
  */
304
304
  declare const nameContains: (substring: string, caseSensitive?: boolean) => TaskPredicate;
305
305
 
306
- type BuiltInTaskListColumnId = 'number' | 'name' | 'startDate' | 'endDate' | 'duration' | 'progress' | 'dependencies' | 'actions';
306
+ type BuiltInTaskListColumnId = 'selection' | 'number' | 'name' | 'startDate' | 'endDate' | 'duration' | 'progress' | 'dependencies' | 'actions';
307
307
  type TaskListColumnId = BuiltInTaskListColumnId | (string & {});
308
308
  type TaskListColumnAnchor = {
309
309
  after: BuiltInTaskListColumnId | string;
@@ -495,6 +495,12 @@ interface GanttModeProps<TTask extends Task = Task> {
495
495
  onToggleCollapse?: (parentId: string) => void;
496
496
  /** Task IDs to highlight in the task list (for search results) */
497
497
  highlightedTaskIds?: Set<string>;
498
+ /** Enable a leading checkbox column for multi-selecting task rows (default: false) */
499
+ enableTaskMultiSelect?: boolean;
500
+ /** Controlled selected task IDs for multi-select mode */
501
+ selectedTaskIds?: Set<string>;
502
+ /** Callback when multi-selected task IDs change */
503
+ onSelectedTaskIdsChange?: (taskIds: Set<string>) => void;
498
504
  /** Disable task drag and resize on the calendar grid (default: false) */
499
505
  disableTaskDrag?: boolean;
500
506
  /** Show calendar chart area (default: true) */
@@ -766,6 +772,12 @@ interface TaskListProps {
766
772
  businessDays?: boolean;
767
773
  /** Task IDs highlighted by the active filter */
768
774
  highlightedTaskIds?: Set<string>;
775
+ /** Enable a leading checkbox column for multi-selecting task rows (default: false) */
776
+ enableTaskMultiSelect?: boolean;
777
+ /** Controlled selected task IDs for multi-select mode */
778
+ selectedTaskIds?: Set<string>;
779
+ /** Callback when multi-selected task IDs change */
780
+ onSelectedTaskIdsChange?: (taskIds: Set<string>) => void;
769
781
  /** Filter mode: 'highlight' shows yellow highlight on matches, 'hide' hides non-matching tasks */
770
782
  filterMode?: 'highlight' | 'hide';
771
783
  /** Task IDs that match the filter (used for hide mode). When undefined, no filtering is applied */
package/dist/index.js CHANGED
@@ -4757,6 +4757,8 @@ var TaskListRow = import_react10.default.memo(
4757
4757
  isFilterMatch = false,
4758
4758
  isFilterHideMode = false,
4759
4759
  resolvedColumns,
4760
+ isTaskSelected = false,
4761
+ onTaskSelectionChange,
4760
4762
  taskListMenuCommands = []
4761
4763
  }) => {
4762
4764
  const [editingColumnId, setEditingColumnId] = (0, import_react10.useState)(null);
@@ -5550,6 +5552,23 @@ var TaskListRow = import_react10.default.memo(
5550
5552
  const isSelectedDependencyOwner = selectedChip != null && selectedChip.successorId === task.id;
5551
5553
  const startDateISO = toISODate2(normalizedTask.startDate);
5552
5554
  const endDateISO = editingDuration ? getEndDate(normalizedTask.startDate, durationValue) : toISODate2(normalizedTask.endDate);
5555
+ const selectionCell = /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5556
+ "div",
5557
+ {
5558
+ className: "gantt-tl-cell gantt-tl-cell-selection",
5559
+ onClick: (e) => e.stopPropagation(),
5560
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
5561
+ "input",
5562
+ {
5563
+ type: "checkbox",
5564
+ className: "gantt-tl-selection-checkbox",
5565
+ "aria-label": `\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443 ${taskNumber ? `${taskNumber}. ` : ""}${task.name}`,
5566
+ checked: isTaskSelected,
5567
+ onChange: (event) => onTaskSelectionChange?.(task.id, event.target.checked)
5568
+ }
5569
+ )
5570
+ }
5571
+ );
5553
5572
  const numberCell = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
5554
5573
  "div",
5555
5574
  {
@@ -6267,6 +6286,7 @@ var TaskListRow = import_react10.default.memo(
6267
6286
  }
6268
6287
  );
6269
6288
  const builtInCells = {
6289
+ selection: selectionCell,
6270
6290
  number: numberCell,
6271
6291
  name: nameCell,
6272
6292
  startDate: startDateCell,
@@ -6419,6 +6439,7 @@ var NewTaskRow = ({
6419
6439
 
6420
6440
  // src/components/TaskList/columns/createBuiltInColumns.tsx
6421
6441
  var BUILT_IN_COLUMN_WIDTHS = {
6442
+ selection: 36,
6422
6443
  number: 40,
6423
6444
  name: 200,
6424
6445
  startDate: 90,
@@ -6429,7 +6450,7 @@ var BUILT_IN_COLUMN_WIDTHS = {
6429
6450
  actions: 80
6430
6451
  };
6431
6452
  function createBuiltInColumns(opts) {
6432
- return [
6453
+ const columns = [
6433
6454
  { id: "number", header: "\u2116", width: BUILT_IN_COLUMN_WIDTHS.number, renderCell: () => null },
6434
6455
  { id: "name", header: "\u0418\u043C\u044F", width: BUILT_IN_COLUMN_WIDTHS.name, renderCell: () => null },
6435
6456
  { id: "startDate", header: "\u041D\u0430\u0447\u0430\u043B\u043E", width: BUILT_IN_COLUMN_WIDTHS.startDate, renderCell: () => null },
@@ -6438,6 +6459,15 @@ function createBuiltInColumns(opts) {
6438
6459
  { id: "progress", header: "%", width: BUILT_IN_COLUMN_WIDTHS.progress, renderCell: () => null },
6439
6460
  { id: "dependencies", header: null, width: BUILT_IN_COLUMN_WIDTHS.dependencies, renderCell: () => null }
6440
6461
  ];
6462
+ if (opts?.enableTaskMultiSelect) {
6463
+ columns.unshift({
6464
+ id: "selection",
6465
+ header: null,
6466
+ width: BUILT_IN_COLUMN_WIDTHS.selection,
6467
+ renderCell: () => null
6468
+ });
6469
+ }
6470
+ return columns;
6441
6471
  }
6442
6472
 
6443
6473
  // src/components/TaskList/columns/resolveTaskListColumns.ts
@@ -6498,6 +6528,7 @@ var import_jsx_runtime14 = require("react/jsx-runtime");
6498
6528
  var LINK_TYPE_ORDER2 = ["FS", "SS", "FF", "SF"];
6499
6529
  var MIN_TASK_LIST_WIDTH = 530;
6500
6530
  var BUILT_IN_CSS_CLASSES = {
6531
+ selection: "gantt-tl-cell-selection",
6501
6532
  number: "gantt-tl-cell-number",
6502
6533
  name: "gantt-tl-cell-name",
6503
6534
  startDate: "gantt-tl-cell-date",
@@ -6573,6 +6604,30 @@ function getTaskNumber(tasks, taskIndex) {
6573
6604
  }
6574
6605
  return `${parentNumber}.${siblingIndex + 1}`;
6575
6606
  }
6607
+ var SelectAllCheckbox = ({
6608
+ checked,
6609
+ indeterminate,
6610
+ onChange
6611
+ }) => {
6612
+ const ref = (0, import_react12.useRef)(null);
6613
+ (0, import_react12.useEffect)(() => {
6614
+ if (ref.current) {
6615
+ ref.current.indeterminate = indeterminate;
6616
+ }
6617
+ }, [indeterminate]);
6618
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
6619
+ "input",
6620
+ {
6621
+ ref,
6622
+ type: "checkbox",
6623
+ className: "gantt-tl-selection-checkbox",
6624
+ "aria-label": "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0432\u0441\u0435 \u0432\u0438\u0434\u0438\u043C\u044B\u0435 \u0437\u0430\u0434\u0430\u0447\u0438",
6625
+ checked,
6626
+ onChange: (event) => onChange(event.target.checked),
6627
+ onClick: (event) => event.stopPropagation()
6628
+ }
6629
+ );
6630
+ };
6576
6631
  var TaskList = ({
6577
6632
  tasks,
6578
6633
  rowHeight,
@@ -6603,6 +6658,9 @@ var TaskList = ({
6603
6658
  isWeekend: isWeekend3,
6604
6659
  businessDays,
6605
6660
  highlightedTaskIds = /* @__PURE__ */ new Set(),
6661
+ enableTaskMultiSelect = false,
6662
+ selectedTaskIds,
6663
+ onSelectedTaskIdsChange,
6606
6664
  filterMode = "highlight",
6607
6665
  filteredTaskIds = /* @__PURE__ */ new Set(),
6608
6666
  isFilterActive = false,
@@ -6610,6 +6668,14 @@ var TaskList = ({
6610
6668
  hiddenTaskListColumns,
6611
6669
  taskListMenuCommands
6612
6670
  }) => {
6671
+ const [internalSelectedTaskIds, setInternalSelectedTaskIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
6672
+ const effectiveSelectedTaskIds = selectedTaskIds ?? internalSelectedTaskIds;
6673
+ const emitSelectedTaskIdsChange = (0, import_react12.useCallback)((nextSelectedTaskIds) => {
6674
+ if (!selectedTaskIds) {
6675
+ setInternalSelectedTaskIds(nextSelectedTaskIds);
6676
+ }
6677
+ onSelectedTaskIdsChange?.(nextSelectedTaskIds);
6678
+ }, [onSelectedTaskIdsChange, selectedTaskIds]);
6613
6679
  const [internalCollapsedParentIds, setInternalCollapsedParentIds] = (0, import_react12.useState)(/* @__PURE__ */ new Set());
6614
6680
  const collapsedParentIds = externalCollapsedParentIds ?? internalCollapsedParentIds;
6615
6681
  const handleToggleCollapse = externalOnToggleCollapse ?? (0, import_react12.useCallback)((parentId) => {
@@ -6656,6 +6722,33 @@ var TaskList = ({
6656
6722
  ),
6657
6723
  [visibleTasks]
6658
6724
  );
6725
+ const visibleTaskIds = (0, import_react12.useMemo)(() => visibleTasks.map((task) => task.id), [visibleTasks]);
6726
+ const selectedVisibleTaskCount = (0, import_react12.useMemo)(
6727
+ () => visibleTaskIds.filter((taskId) => effectiveSelectedTaskIds.has(taskId)).length,
6728
+ [effectiveSelectedTaskIds, visibleTaskIds]
6729
+ );
6730
+ const areAllVisibleTasksSelected = visibleTaskIds.length > 0 && selectedVisibleTaskCount === visibleTaskIds.length;
6731
+ const areSomeVisibleTasksSelected = selectedVisibleTaskCount > 0 && !areAllVisibleTasksSelected;
6732
+ const handleToggleTaskSelection = (0, import_react12.useCallback)((taskId, checked) => {
6733
+ const nextSelectedTaskIds = new Set(effectiveSelectedTaskIds);
6734
+ if (checked) {
6735
+ nextSelectedTaskIds.add(taskId);
6736
+ } else {
6737
+ nextSelectedTaskIds.delete(taskId);
6738
+ }
6739
+ emitSelectedTaskIdsChange(nextSelectedTaskIds);
6740
+ }, [effectiveSelectedTaskIds, emitSelectedTaskIdsChange]);
6741
+ const handleToggleAllVisibleTaskSelection = (0, import_react12.useCallback)((checked) => {
6742
+ const nextSelectedTaskIds = new Set(effectiveSelectedTaskIds);
6743
+ for (const taskId of visibleTaskIds) {
6744
+ if (checked) {
6745
+ nextSelectedTaskIds.add(taskId);
6746
+ } else {
6747
+ nextSelectedTaskIds.delete(taskId);
6748
+ }
6749
+ }
6750
+ emitSelectedTaskIdsChange(nextSelectedTaskIds);
6751
+ }, [effectiveSelectedTaskIds, emitSelectedTaskIdsChange, visibleTaskIds]);
6659
6752
  const originalTaskNumberMap = (0, import_react12.useMemo)(
6660
6753
  () => {
6661
6754
  const numberMap = /* @__PURE__ */ new Map();
@@ -7137,7 +7230,10 @@ var TaskList = ({
7137
7230
  const duplicatedTasks = duplicateTaskSubtree(taskId, orderedTasks);
7138
7231
  onReorder?.(duplicatedTasks);
7139
7232
  }, [orderedTasks, onReorder]);
7140
- const builtInColumns = (0, import_react12.useMemo)(() => createBuiltInColumns({ businessDays }), [businessDays]);
7233
+ const builtInColumns = (0, import_react12.useMemo)(
7234
+ () => createBuiltInColumns({ businessDays, enableTaskMultiSelect }),
7235
+ [businessDays, enableTaskMultiSelect]
7236
+ );
7141
7237
  const resolvedColumns = (0, import_react12.useMemo)(
7142
7238
  () => resolveTaskListColumns(
7143
7239
  builtInColumns,
@@ -7161,6 +7257,24 @@ var TaskList = ({
7161
7257
  style: { "--tasklist-width": `${effectiveTaskListWidth}px` },
7162
7258
  children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "gantt-tl-table", children: [
7163
7259
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "gantt-tl-header", style: { height: `${tableHeaderHeight}px` }, children: resolvedColumns.map((col) => {
7260
+ if (col.id === "selection") {
7261
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
7262
+ "div",
7263
+ {
7264
+ className: "gantt-tl-headerCell gantt-tl-cell-selection",
7265
+ "data-column-id": "selection",
7266
+ children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
7267
+ SelectAllCheckbox,
7268
+ {
7269
+ checked: areAllVisibleTasksSelected,
7270
+ indeterminate: areSomeVisibleTasksSelected,
7271
+ onChange: handleToggleAllVisibleTaskSelection
7272
+ }
7273
+ )
7274
+ },
7275
+ col.id
7276
+ );
7277
+ }
7164
7278
  if (col.id === "dependencies") {
7165
7279
  return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
7166
7280
  "div",
@@ -7286,6 +7400,8 @@ var TaskList = ({
7286
7400
  isFilterMatch: filterMode === "highlight" ? highlightedTaskIds.has(task.id) : false,
7287
7401
  isFilterHideMode: filterMode === "hide" && isFilterActive,
7288
7402
  resolvedColumns,
7403
+ isTaskSelected: effectiveSelectedTaskIds.has(task.id),
7404
+ onTaskSelectionChange: handleToggleTaskSelection,
7289
7405
  taskListMenuCommands
7290
7406
  }
7291
7407
  ),
@@ -9366,6 +9482,9 @@ function TaskGanttChartInner(props, ref) {
9366
9482
  collapsedParentIds: externalCollapsedParentIds,
9367
9483
  onToggleCollapse: externalOnToggleCollapse,
9368
9484
  highlightedTaskIds,
9485
+ enableTaskMultiSelect = false,
9486
+ selectedTaskIds,
9487
+ onSelectedTaskIdsChange,
9369
9488
  disableTaskDrag = false,
9370
9489
  showChart = true,
9371
9490
  additionalColumns,
@@ -9936,6 +10055,9 @@ function TaskGanttChartInner(props, ref) {
9936
10055
  onDemoteTask: onDemoteTask ?? handleDemoteTask,
9937
10056
  onUngroupTask: onUngroupTask ?? handleUngroupTask,
9938
10057
  highlightedTaskIds: taskListHighlightedTaskIds,
10058
+ enableTaskMultiSelect,
10059
+ selectedTaskIds,
10060
+ onSelectedTaskIdsChange,
9939
10061
  customDays,
9940
10062
  isWeekend: isWeekend3,
9941
10063
  businessDays,