@workiom/frappe-gantt 1.0.22 → 1.0.23

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 CHANGED
@@ -78,6 +78,7 @@ Frappe Gantt offers a wide range of options to customize your chart.
78
78
 
79
79
  | **Option** | **Description** | **Possible Values** | **Default** |
80
80
  | ------------------------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
81
+ | `allow_dependency_creation` | Enables interactive dependency creation by dragging between connector circles on task bars. When enabled, hovering a bar reveals circles at its start and end; drag from one circle to another to create a typed dependency. | `true`, `false` | `true` |
81
82
  | `arrow_curve` | Curve radius of arrows connecting dependencies. | Any positive integer. | `5` |
82
83
  | `auto_move_label` | Move task labels when user scrolls horizontally. | `true`, `false` | `false` |
83
84
  | `bar_corner_radius` | Radius of the task bar corners (in pixels). | Any positive integer. | `3` |
@@ -257,6 +258,9 @@ Frappe Gantt provides event callbacks to respond to user interactions:
257
258
  | `on_hover` | Triggered when hovering over a task. | `task`, `screenX`, `screenY`, `event` |
258
259
  | `on_task_add` | Triggered when the add task icon is clicked. | `task` - the parent task object |
259
260
  | `on_arrow_click` | Triggered when a dependency arrow is clicked (activated). Clicking the same arrow again or clicking outside deselects it — deselection does not re-fire this event. | `from_task`, `to_task` — the connected task objects |
261
+ | `on_dependency_create` | Triggered when a new dependency is created via interactive linking (no prior connection between the two tasks). | `from_task`, `to_task`, `type` — the dependency type string (e.g. `'finish-to-start'`) |
262
+ | `on_dependency_changed` | Triggered when an existing dependency between two tasks is replaced with a different type. | `from_task`, `to_task`, `old_type`, `new_type` |
263
+ | `on_dependency_delete` | Triggered when a dependency is removed — either by pressing Delete/Backspace while an arrow is active, or by re-connecting the same two tasks with the same type (toggle off). | `from_task`, `to_task`, `type` |
260
264
 
261
265
  #### Arrow Active State
262
266
 
@@ -280,6 +284,44 @@ let gantt = new Gantt("#gantt", tasks, {
280
284
  });
281
285
  ```
282
286
 
287
+ #### Interactive Dependency Linking
288
+
289
+ When `allow_dependency_creation` is `true` (the default), hovering over any task bar reveals connector circles at its start (green) and end (orange). Drag from one circle to a circle on a different bar to create a dependency between them.
290
+
291
+ The dependency type is determined automatically by which circles are connected:
292
+
293
+ | From endpoint | To endpoint | Type created |
294
+ |---|---|---|
295
+ | End | Start | `finish-to-start` |
296
+ | Start | Start | `start-to-start` |
297
+ | End | End | `finish-to-finish` |
298
+ | Start | End | `start-to-finish` |
299
+
300
+ **Behaviors:**
301
+ - Only one dependency between any two tasks is stored at a time. If the two tasks are already linked, dragging replaces the old type with the new one.
302
+ - Dragging from one task to itself is ignored.
303
+ - If you re-connect the same two tasks with the **same** type, the dependency is toggled off (removed).
304
+ - Dependency creation is disabled when `readonly: true`.
305
+
306
+ **Deleting a dependency:**
307
+ 1. Click a dependency arrow to activate it (it stays highlighted).
308
+ 2. Press **Delete** or **Backspace** — the arrow and its underlying dependency are removed.
309
+
310
+ ```js
311
+ let gantt = new Gantt("#gantt", tasks, {
312
+ allow_dependency_creation: true,
313
+ on_dependency_create: (from_task, to_task, type) => {
314
+ console.log(`Created: ${from_task.id} → ${to_task.id} (${type})`);
315
+ },
316
+ on_dependency_changed: (from_task, to_task, old_type, new_type) => {
317
+ console.log(`Changed: ${from_task.id} → ${to_task.id} (${old_type} → ${new_type})`);
318
+ },
319
+ on_dependency_delete: (from_task, to_task, type) => {
320
+ console.log(`Deleted: ${from_task.id} → ${to_task.id} (${type})`);
321
+ }
322
+ });
323
+ ```
324
+
283
325
  **Example:**
284
326
 
285
327
  ```js
@@ -1 +1 @@
1
- :root{--g-arrow-color: #1f2937;--g-arrow-hover-color: #007bff;--g-arrow-critical-color: #f5c044;--g-arrow-invalid-color: #ff7676;--g-bar-color: #fff;--g-bar-border: #fff;--g-tick-color-thick: #ededed;--g-tick-color: #f3f3f3;--g-actions-background: #f3f3f3;--g-border-color: #ebeff2;--g-text-muted: #7c7c7c;--g-text-light: #fff;--g-text-dark: #171717;--g-progress-color: #dbdbdb;--g-handle-color: transparent;--g-weekend-label-color: #dcdce4;--g-expected-progress: #c4c4e9;--g-header-background: #fff;--g-row-color: #fdfdfd;--g-row-border-color: #c7c7c7;--g-today-highlight: #37352f;--g-popup-actions: #ebeff2;--g-arrow-type-label-bg: #dbdbdb;--g-arrow-type-label-color: #000;--g-weekend-highlight-color: #f7f7f7;--g-task-column-bg: #ffffff;--g-task-row-bg: #ffffff;--g-resize-handle-hover: rgba(59, 130, 246, .3);--g-resize-handle-active: rgba(59, 130, 246, .5)}.gantt-wrapper{display:flex;width:100%;position:relative}.gantt-wrapper.rtl{flex-direction:row-reverse}.gantt-container{line-height:14.5px;position:relative;overflow:auto;font-size:12px;height:var(--gv-grid-height);flex:1;min-width:0;border-radius:8px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:#fff;box-shadow:0 10px 24px -3px #0003;padding:10px;border-radius:5px;width:max-content;z-index:1000}.gantt-container .popup-wrapper .title{margin-bottom:2px;color:var(--g-text-dark);font-size:.85rem;font-weight:650;line-height:15px}.gantt-container .popup-wrapper .subtitle{color:var(--g-text-dark);font-size:.8rem;margin-bottom:5px}.gantt-container .popup-wrapper .details{color:var(--g-text-muted);font-size:.7rem}.gantt-container .popup-wrapper .actions{margin-top:10px;margin-left:3px}.gantt-container .popup-wrapper .action-btn{border:none;padding:5px 8px;background-color:var(--g-popup-actions);border-right:1px solid var(--g-text-light)}.gantt-container .popup-wrapper .action-btn:hover{background-color:brightness(97%)}.gantt-container .popup-wrapper .action-btn:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px}.gantt-container .popup-wrapper .action-btn:last-child{border-right:none;border-top-right-radius:4px;border-bottom-right-radius:4px}.gantt-container .grid-header{height:calc(var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);background-color:var(--g-header-background);position:sticky;top:0;left:0;border-bottom:1px solid var(--g-row-border-color);z-index:1000}.gantt-container .lower-text,.gantt-container .upper-text{text-anchor:middle}.gantt-container .upper-header{height:var(--gv-upper-header-height)}.gantt-container .lower-header{height:var(--gv-lower-header-height)}.gantt-container .lower-text{font-size:12px;position:absolute;width:calc(var(--gv-column-width) * .8);height:calc(var(--gv-lower-header-height) * .8);margin:0 calc(var(--gv-column-width) * .1);align-content:center;text-align:center;color:var(--g-text-muted)}.gantt-container .upper-text{position:absolute;width:fit-content;font-weight:500;font-size:14px;color:var(--g-text-dark);height:calc(var(--gv-lower-header-height) * .66)}.gantt-container .current-upper{position:sticky;left:0!important;padding-left:17px;background:#fff}.gantt-container .side-header{position:sticky;top:0;right:0;float:right;z-index:1000;line-height:20px;font-weight:400;width:max-content;margin-left:auto;padding-right:10px;padding-top:10px;background:var(--g-header-background);display:flex}.gantt-container .side-header *{transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;background-color:var(--g-actions-background);border-radius:.5rem;border:none;padding:5px 8px;color:var(--g-text-dark);font-size:14px;letter-spacing:.02em;font-weight:420;box-sizing:content-box;margin-right:5px}.gantt-container .side-header *:last-child{margin-right:0}.gantt-container .side-header *:hover{filter:brightness(97.5%)}.gantt-container .side-header select{width:60px;padding-top:2px;padding-bottom:2px}.gantt-container .side-header select:focus{outline:none}.gantt-container .date-range-highlight{background-color:var(--g-progress-color);border-radius:12px;height:calc(var(--gv-lower-header-height) - 6px);top:calc(var(--gv-upper-header-height) + 5px);position:absolute}.gantt-container .current-highlight{position:absolute;background:var(--g-today-highlight);width:1px;z-index:999}.gantt-container .current-ball-highlight{position:absolute;background:var(--g-today-highlight);z-index:1001;border-radius:50%}.gantt-container .current-date-highlight{background:var(--g-today-highlight);color:var(--g-text-light);border-radius:5px}.gantt-container .holiday-label{position:absolute;top:0;left:0;opacity:0;z-index:1000;background:--g-weekend-label-color;border-radius:5px;padding:2px 5px}.gantt-container .holiday-label.show{opacity:100}.gantt-container .extras{position:sticky;left:0}.gantt-container .extras .adjust{position:absolute;left:8px;top:calc(var(--gv-grid-height) - 60px);background-color:#000000b3;color:#fff;border:none;padding:8px;border-radius:3px}.gantt-container .hide{display:none}.gantt{user-select:none;-webkit-user-select:none;position:absolute;left:0}.gantt .grid-background{fill:none}.gantt .grid-row{fill:var(--g-row-color)}.gantt .row-line{stroke:var(--g-border-color)}.gantt .tick{stroke:var(--g-tick-color);stroke-width:.4}.gantt .tick.thick{stroke:var(--g-tick-color-thick);stroke-width:.7}.gantt .arrow{fill:none;stroke:var(--g-arrow-color);stroke-width:1.5}.gantt .arrow-critical{stroke:var(--g-arrow-critical-color)}.gantt .arrow-invalid{stroke:var(--g-arrow-invalid-color)}.gantt .arrow-hover,.gantt .arrow-active{stroke:var(--g-arrow-hover-color)}.gantt .arrow-type-label{stroke-width:0;cursor:pointer}.gantt .arrow-type-label rect{fill:var(--g-arrow-type-label-bg)}.gantt .arrow-type-label text{fill:var(--g-arrow-type-label-color);font-size:10px;font-weight:600;font-family:inherit;pointer-events:none}.gantt .bar-wrapper .bar{fill:var(--g-bar-color);stroke:var(--g-bar-border);stroke-width:0;transition:stroke-width .3s ease}.gantt .bar-wrapper .bar.bar-arrow-active{outline-color:var(--g-arrow-hover-color);outline-width:2px;outline-style:solid}.gantt .bar-wrapper .bar.bar-arrow-critical{outline-color:var(--g-arrow-critical-color)}.gantt .bar-wrapper .bar.bar-arrow-invalid{outline-color:var(--g-arrow-invalid-color)}.gantt .bar-progress{fill:var(--g-progress-color);border-radius:4px}.gantt .bar-expected-progress{fill:var(--g-expected-progress)}.gantt .bar-invalid{fill:transparent;stroke:var(--g-bar-border);stroke-width:1;stroke-dasharray:5}:is(.gantt .bar-invalid)~.bar-label{fill:var(--g-text-light)}.gantt .bar-label{fill:var(--g-text-dark);dominant-baseline:central;font-family:Helvetica;font-size:13px;font-weight:400}.gantt .bar-label.big{fill:var(--g-text-dark);text-anchor:start}.gantt .handle{fill:var(--g-handle-color);opacity:0;transition:opacity .3s ease}.gantt .handle.active,.gantt .handle.visible{cursor:ew-resize;opacity:1}.gantt .handle.progress{fill:var(--g-text-muted)}.gantt .bar-wrapper{cursor:pointer}.gantt .bar-wrapper .bar{outline:1px solid var(--g-row-border-color);border-radius:3px}.gantt .bar-wrapper:hover .bar{transition:transform .3s ease}.gantt .bar-wrapper:hover .date-range-highlight{display:block}.gantt .add-task-icon{cursor:pointer;transition:opacity .2s ease}.gantt .add-task-icon .add-task-icon-bg{fill:var(--g-bar-color);stroke:var(--g-bar-border);stroke-width:1;transition:all .2s ease}.gantt .add-task-icon .add-task-icon-plus{stroke:var(--g-text-dark);stroke-width:2;stroke-linecap:round;transition:stroke .2s ease}.gantt .add-task-icon.active .add-task-icon-bg,.gantt .add-task-icon:hover .add-task-icon-bg{fill:var(--g-progress-color);stroke:var(--g-progress-color)}.gantt .add-task-icon.active .add-task-icon-plus,.gantt .add-task-icon:hover .add-task-icon-plus{stroke:var(--g-text-light)}.task-column{flex-shrink:0;width:var(--gv-task-column-width, 150px);height:var(--gv-grid-height);background-color:var(--g-task-column-bg);border-right:1px solid var(--g-row-border-color);overflow-y:auto;overflow-x:hidden;-webkit-user-select:none;user-select:none;position:relative;scrollbar-width:none;-ms-overflow-style:none}.task-column::-webkit-scrollbar{display:none}.task-column-header{height:calc(var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);background-color:var(--g-header-background);border-bottom:1px solid var(--g-row-border-color);position:sticky;top:0;z-index:1001;display:flex;align-items:center;padding:0 12px;font-weight:600;font-size:13px;color:var(--g-text-dark)}.task-column-content{position:relative;width:100%;padding-top:calc(var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);overflow:visible}.task-row{position:absolute;width:100%;padding:0 12px;display:flex;align-items:center;font-size:13px;color:var(--g-text-dark);border-bottom:1px solid var(--g-row-border-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background-color:var(--g-task-row-bg)}.task-column-resize-handle{position:absolute;top:0;right:0;width:6px;height:100%;min-height:calc(var(--gv-task-column-content-height) + var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);cursor:col-resize;z-index:1002;background-color:transparent;transition:background-color .2s ease}.task-column-resize-handle:hover{background-color:var(--g-resize-handle-hover)}.task-column.resizing .task-column-resize-handle{background-color:var(--g-resize-handle-active)}.task-column.resizing{-webkit-user-select:none;user-select:none}.gantt-wrapper.rtl .task-column{border-right:none;border-left:1px solid var(--g-row-border-color)}.gantt-wrapper.rtl .task-column-resize-handle{right:auto;left:0}
1
+ :root{--g-arrow-color: #1f2937;--g-arrow-hover-color: #007bff;--g-arrow-critical-color: #f5c044;--g-arrow-invalid-color: #ff7676;--g-bar-color: #fff;--g-bar-border: #fff;--g-tick-color-thick: #ededed;--g-tick-color: #f3f3f3;--g-actions-background: #f3f3f3;--g-border-color: #ebeff2;--g-text-muted: #7c7c7c;--g-text-light: #fff;--g-text-dark: #171717;--g-progress-color: #dbdbdb;--g-handle-color: transparent;--g-weekend-label-color: #dcdce4;--g-expected-progress: #c4c4e9;--g-header-background: #fff;--g-row-color: #fdfdfd;--g-row-border-color: #c7c7c7;--g-today-highlight: #37352f;--g-popup-actions: #ebeff2;--g-arrow-type-label-bg: #dbdbdb;--g-arrow-type-label-color: #000;--g-weekend-highlight-color: #f7f7f7;--g-task-column-bg: #ffffff;--g-task-row-bg: #ffffff;--g-resize-handle-hover: rgba(59, 130, 246, .3);--g-resize-handle-active: rgba(59, 130, 246, .5);--g-connector-start-color: #22c55e;--g-connector-end-color: #f97316;--g-connector-linking-color: #6366f1;--g-connector-fill: #ffffff}.gantt-wrapper{display:flex;width:100%;position:relative}.gantt-wrapper.rtl{flex-direction:row-reverse}.gantt-container{line-height:14.5px;position:relative;overflow:auto;font-size:12px;height:var(--gv-grid-height);flex:1;min-width:0;border-radius:8px}.gantt-container .popup-wrapper{position:absolute;top:0;left:0;background:#fff;box-shadow:0 10px 24px -3px #0003;padding:10px;border-radius:5px;width:max-content;z-index:1000}.gantt-container .popup-wrapper .title{margin-bottom:2px;color:var(--g-text-dark);font-size:.85rem;font-weight:650;line-height:15px}.gantt-container .popup-wrapper .subtitle{color:var(--g-text-dark);font-size:.8rem;margin-bottom:5px}.gantt-container .popup-wrapper .details{color:var(--g-text-muted);font-size:.7rem}.gantt-container .popup-wrapper .actions{margin-top:10px;margin-left:3px}.gantt-container .popup-wrapper .action-btn{border:none;padding:5px 8px;background-color:var(--g-popup-actions);border-right:1px solid var(--g-text-light)}.gantt-container .popup-wrapper .action-btn:hover{background-color:brightness(97%)}.gantt-container .popup-wrapper .action-btn:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px}.gantt-container .popup-wrapper .action-btn:last-child{border-right:none;border-top-right-radius:4px;border-bottom-right-radius:4px}.gantt-container .grid-header{height:calc(var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);background-color:var(--g-header-background);position:sticky;top:0;left:0;border-bottom:1px solid var(--g-row-border-color);z-index:1000}.gantt-container .lower-text,.gantt-container .upper-text{text-anchor:middle}.gantt-container .upper-header{height:var(--gv-upper-header-height)}.gantt-container .lower-header{height:var(--gv-lower-header-height)}.gantt-container .lower-text{font-size:12px;position:absolute;width:calc(var(--gv-column-width) * .8);height:calc(var(--gv-lower-header-height) * .8);margin:0 calc(var(--gv-column-width) * .1);align-content:center;text-align:center;color:var(--g-text-muted)}.gantt-container .upper-text{position:absolute;width:fit-content;font-weight:500;font-size:14px;color:var(--g-text-dark);height:calc(var(--gv-lower-header-height) * .66)}.gantt-container .current-upper{position:sticky;left:0!important;padding-left:17px;background:#fff}.gantt-container .side-header{position:sticky;top:0;right:0;float:right;z-index:1000;line-height:20px;font-weight:400;width:max-content;margin-left:auto;padding-right:10px;padding-top:10px;background:var(--g-header-background);display:flex}.gantt-container .side-header *{transition-property:background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;background-color:var(--g-actions-background);border-radius:.5rem;border:none;padding:5px 8px;color:var(--g-text-dark);font-size:14px;letter-spacing:.02em;font-weight:420;box-sizing:content-box;margin-right:5px}.gantt-container .side-header *:last-child{margin-right:0}.gantt-container .side-header *:hover{filter:brightness(97.5%)}.gantt-container .side-header select{width:60px;padding-top:2px;padding-bottom:2px}.gantt-container .side-header select:focus{outline:none}.gantt-container .date-range-highlight{background-color:var(--g-progress-color);border-radius:12px;height:calc(var(--gv-lower-header-height) - 6px);top:calc(var(--gv-upper-header-height) + 5px);position:absolute}.gantt-container .current-highlight{position:absolute;background:var(--g-today-highlight);width:1px;z-index:999}.gantt-container .current-ball-highlight{position:absolute;background:var(--g-today-highlight);z-index:1001;border-radius:50%}.gantt-container .current-date-highlight{background:var(--g-today-highlight);color:var(--g-text-light);border-radius:5px}.gantt-container .holiday-label{position:absolute;top:0;left:0;opacity:0;z-index:1000;background:--g-weekend-label-color;border-radius:5px;padding:2px 5px}.gantt-container .holiday-label.show{opacity:100}.gantt-container .extras{position:sticky;left:0}.gantt-container .extras .adjust{position:absolute;left:8px;top:calc(var(--gv-grid-height) - 60px);background-color:#000000b3;color:#fff;border:none;padding:8px;border-radius:3px}.gantt-container .hide{display:none}.gantt{user-select:none;-webkit-user-select:none;position:absolute;left:0}.gantt .grid-background{fill:none}.gantt .grid-row{fill:var(--g-row-color)}.gantt .row-line{stroke:var(--g-border-color)}.gantt .tick{stroke:var(--g-tick-color);stroke-width:.4}.gantt .tick.thick{stroke:var(--g-tick-color-thick);stroke-width:.7}.gantt .arrow{fill:none;stroke:var(--g-arrow-color);stroke-width:1.5}.gantt .arrow-critical{stroke:var(--g-arrow-critical-color)}.gantt .arrow-invalid{stroke:var(--g-arrow-invalid-color)}.gantt .arrow-hover,.gantt .arrow-active{stroke:var(--g-arrow-hover-color)}.gantt .arrow-type-label{stroke-width:0;cursor:pointer}.gantt .arrow-type-label rect{fill:var(--g-arrow-type-label-bg)}.gantt .arrow-type-label text{fill:var(--g-arrow-type-label-color);font-size:10px;font-weight:600;font-family:inherit;pointer-events:none}.gantt .bar-wrapper .bar{fill:var(--g-bar-color);stroke:var(--g-bar-border);stroke-width:0;transition:stroke-width .3s ease}.gantt .bar-wrapper .bar.bar-arrow-active{outline-color:var(--g-arrow-hover-color);outline-width:2px;outline-style:solid}.gantt .bar-wrapper .bar.bar-arrow-critical{outline-color:var(--g-arrow-critical-color)}.gantt .bar-wrapper .bar.bar-arrow-invalid{outline-color:var(--g-arrow-invalid-color)}.gantt .bar-progress{fill:var(--g-progress-color);border-radius:4px}.gantt .bar-expected-progress{fill:var(--g-expected-progress)}.gantt .bar-invalid{fill:transparent;stroke:var(--g-bar-border);stroke-width:1;stroke-dasharray:5}:is(.gantt .bar-invalid)~.bar-label{fill:var(--g-text-light)}.gantt .bar-label{fill:var(--g-text-dark);dominant-baseline:central;font-family:Helvetica;font-size:13px;font-weight:400}.gantt .bar-label.big{fill:var(--g-text-dark);text-anchor:start}.gantt .handle{fill:var(--g-handle-color);opacity:0;transition:opacity .3s ease}.gantt .handle.active,.gantt .handle.visible{cursor:ew-resize;opacity:1}.gantt .handle.progress{fill:var(--g-text-muted)}.gantt .bar-wrapper{cursor:pointer}.gantt .bar-wrapper .bar{outline:1px solid var(--g-row-border-color);border-radius:3px}.gantt .bar-wrapper:hover .bar{transition:transform .3s ease}.gantt .bar-wrapper:hover .date-range-highlight{display:block}.gantt .bar-wrapper .connector-circle{fill:var(--g-connector-fill);opacity:0;cursor:crosshair;transition:opacity .2s ease;pointer-events:all}.gantt .bar-wrapper .connector-circle.connector-start{stroke:var(--g-connector-start-color);stroke-width:2}.gantt .bar-wrapper .connector-circle.connector-end{stroke:var(--g-connector-end-color);stroke-width:2}.gantt .bar-wrapper:hover .connector-circle{opacity:1}.gantt .add-task-icon{cursor:pointer;transition:opacity .2s ease}.gantt .add-task-icon .add-task-icon-bg{fill:var(--g-bar-color);stroke:var(--g-bar-border);stroke-width:1;transition:all .2s ease}.gantt .add-task-icon .add-task-icon-plus{stroke:var(--g-text-dark);stroke-width:2;stroke-linecap:round;transition:stroke .2s ease}.gantt .add-task-icon.active .add-task-icon-bg,.gantt .add-task-icon:hover .add-task-icon-bg{fill:var(--g-progress-color);stroke:var(--g-progress-color)}.gantt .add-task-icon.active .add-task-icon-plus,.gantt .add-task-icon:hover .add-task-icon-plus{stroke:var(--g-text-light)}.gantt .linking-temp-line{stroke:var(--g-connector-linking-color);stroke-width:2;stroke-dasharray:5,4;fill:none;pointer-events:none}.gantt .linking-temp-line.snap{stroke:var(--g-connector-start-color);stroke-dasharray:0}.gantt .linking-snap-badge{font-size:11px;font-weight:700;fill:var(--g-connector-start-color);pointer-events:none;-webkit-user-select:none;user-select:none}.task-column{flex-shrink:0;width:var(--gv-task-column-width, 150px);height:var(--gv-grid-height);background-color:var(--g-task-column-bg);border-right:1px solid var(--g-row-border-color);overflow-y:auto;overflow-x:hidden;-webkit-user-select:none;user-select:none;position:relative;scrollbar-width:none;-ms-overflow-style:none}.task-column::-webkit-scrollbar{display:none}.task-column-header{height:calc(var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);background-color:var(--g-header-background);border-bottom:1px solid var(--g-row-border-color);position:sticky;top:0;z-index:1001;display:flex;align-items:center;padding:0 12px;font-weight:600;font-size:13px;color:var(--g-text-dark)}.task-column-content{position:relative;width:100%;padding-top:calc(var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);overflow:visible}.task-row{position:absolute;width:100%;padding:0 12px;display:flex;align-items:center;font-size:13px;color:var(--g-text-dark);border-bottom:1px solid var(--g-row-border-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background-color:var(--g-task-row-bg)}.task-column-resize-handle{position:absolute;top:0;right:0;width:6px;height:100%;min-height:calc(var(--gv-task-column-content-height) + var(--gv-lower-header-height) + var(--gv-upper-header-height) + 10px);cursor:col-resize;z-index:1002;background-color:transparent;transition:background-color .2s ease}.task-column-resize-handle:hover{background-color:var(--g-resize-handle-hover)}.task-column.resizing .task-column-resize-handle{background-color:var(--g-resize-handle-active)}.task-column.resizing{-webkit-user-select:none;user-select:none}.gantt-wrapper.rtl .task-column{border-right:none;border-left:1px solid var(--g-row-border-color)}.gantt-wrapper.rtl .task-column-resize-handle{right:auto;left:0}