iris-gantt 1.0.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 ADDED
@@ -0,0 +1,279 @@
1
+ # SVAR Gantt Chart - Complete React Implementation
2
+
3
+ A comprehensive, production-ready Gantt chart component built with React and TypeScript, featuring all FREE and PRO capabilities from SVAR Gantt in a single, unified component.
4
+
5
+ ![Gantt Chart Demo](https://img.shields.io/badge/React-19.2.0-blue)
6
+ ![TypeScript](https://img.shields.io/badge/TypeScript-5.9.3-blue)
7
+ ![Storybook](https://img.shields.io/badge/Storybook-10.1.11-ff69b4)
8
+ ![License](https://img.shields.io/badge/License-MIT-green)
9
+
10
+ ## ✨ Features
11
+
12
+ ### 🎯 Core Features
13
+ - ✅ **Multi-column Task Grid** - Name, dates, duration, progress
14
+ - ✅ **Hierarchical Structure** - Parent/child tasks with expand/collapse
15
+ - ✅ **Configurable Timeline** - Hour/day/week/month/quarter/year scales
16
+ - ✅ **Zoom Controls** - In, out, reset with smooth transitions
17
+ - ✅ **Synchronized Scrolling** - Grid and timeline stay in sync
18
+ - ✅ **Weekend & Holiday Highlighting** - Visual differentiation
19
+ - ✅ **Light & Dark Themes** - Professional styling
20
+
21
+ ### 🎨 Interactive Features
22
+ - ✅ **Drag & Drop** - Move tasks by dragging bars
23
+ - ✅ **Task Resize** - Adjust start/end dates from edges
24
+ - ✅ **Dependencies** - 4 types with curved arrows (e2s, s2s, e2e, s2e)
25
+ - ✅ **Progress Tracking** - Visual indicators on bars
26
+ - ✅ **Task Types** - Regular tasks, milestones, projects
27
+ - ✅ **Color Coding** - Custom colors per task
28
+
29
+ ### 💎 PRO Features
30
+ - ✅ **Undo/Redo System** - 50-action history with Ctrl+Z/Y
31
+ - ✅ **Critical Path Analysis** - Automatic calculation and highlighting
32
+ - ✅ **Auto-Scheduling** - Forward/backward scheduling modes
33
+ - ✅ **Baselines** - Visual variance tracking with purple bars
34
+ - ✅ **Resource Leveling** - Prevent overallocation
35
+ - ✅ **Task Creation UI** - Beautiful modal form
36
+ - ✅ **Task Editing UI** - Double-click to edit
37
+ - ✅ **Advanced Filtering** - By status, priority, owner
38
+ - ✅ **Search** - Real-time across all fields
39
+ - ✅ **Export** - CSV, Excel, JSON, PDF
40
+
41
+ ## 🚀 Quick Start
42
+
43
+ ### Installation
44
+
45
+ ```bash
46
+ npm install
47
+ ```
48
+
49
+ ### Run Storybook
50
+
51
+ ```bash
52
+ npm run storybook
53
+ ```
54
+
55
+ Or use the helper script:
56
+
57
+ ```bash
58
+ ./run-storybook.sh
59
+ ```
60
+
61
+ Visit http://localhost:6006 to see all demos!
62
+
63
+ ## 📖 Usage
64
+
65
+ ```tsx
66
+ import { Gantt } from './components/Gantt';
67
+ import type { Task, Link } from './components/types';
68
+
69
+ const tasks: Task[] = [
70
+ {
71
+ id: '1',
72
+ text: 'Project Planning',
73
+ start: new Date(2024, 0, 1),
74
+ end: new Date(2024, 0, 15),
75
+ duration: 14,
76
+ progress: 100,
77
+ type: 'project',
78
+ owner: 'John Smith',
79
+ priority: 'high',
80
+ },
81
+ {
82
+ id: '2',
83
+ text: 'Development',
84
+ start: new Date(2024, 0, 15),
85
+ end: new Date(2024, 1, 15),
86
+ duration: 31,
87
+ progress: 60,
88
+ owner: 'Jane Doe',
89
+ priority: 'high',
90
+ },
91
+ ];
92
+
93
+ const links: Link[] = [
94
+ { id: 'l1', source: '1', target: '2', type: 'e2s' },
95
+ ];
96
+
97
+ function App() {
98
+ return (
99
+ <Gantt
100
+ tasks={tasks}
101
+ links={links}
102
+ config={{
103
+ weekends: true,
104
+ theme: 'light',
105
+ }}
106
+ onTaskUpdate={(task) => console.log('Updated:', task)}
107
+ onTaskCreate={(task) => console.log('Created:', task)}
108
+ onTaskDelete={(id) => console.log('Deleted:', id)}
109
+ />
110
+ );
111
+ }
112
+ ```
113
+
114
+ ## 🎨 Storybook Demos
115
+
116
+ The project includes comprehensive Storybook demos:
117
+
118
+ - **Gantt Chart/Basic Examples** - Simple projects and use cases
119
+ - **Gantt Chart/Advanced Features** - All PRO features in action
120
+ - **Gantt Chart/Baselines** - Baseline tracking demonstrations
121
+
122
+ ## 🛠️ Configuration
123
+
124
+ ```tsx
125
+ interface GanttConfig {
126
+ columns?: Column[]; // Custom columns
127
+ scales?: Scale[]; // Timeline scales
128
+ readonly?: boolean; // Disable editing
129
+ editable?: boolean; // Enable inline editing
130
+ taskHeight?: number; // Task bar height
131
+ rowHeight?: number; // Row height
132
+ columnWidth?: number; // Timeline column width
133
+ weekends?: boolean; // Highlight weekends
134
+ holidays?: Date[]; // Holiday dates
135
+ theme?: 'light' | 'dark'; // Theme
136
+ }
137
+ ```
138
+
139
+ ## 🎯 Interactive Controls
140
+
141
+ ### Toolbar Buttons
142
+ - **+ Add Task** - Create new tasks
143
+ - **↶ Undo / ↷ Redo** - Undo/redo with Ctrl+Z/Y
144
+ - **⚡ Auto-Schedule** - Auto-schedule based on dependencies
145
+ - **📊 Level Resources** - Balance workload
146
+ - **🎯 Critical Path** - Highlight critical tasks
147
+ - **📍 Baselines** - Create and toggle baselines
148
+ - **🔍 Zoom** - Zoom in/out/reset
149
+ - **💾 Export** - CSV, Excel, JSON, PDF
150
+
151
+ ### Keyboard Shortcuts
152
+ - **Ctrl+Z** - Undo
153
+ - **Ctrl+Y** or **Ctrl+Shift+Z** - Redo
154
+ - **Double-click task** - Edit task
155
+
156
+ ### Mouse Actions
157
+ - **Drag task bar** - Move task
158
+ - **Drag task edges** - Resize (adjust dates)
159
+ - **Click task** - Select
160
+ - **Hover dependencies** - Highlight relationships
161
+
162
+ ## 📁 Project Structure
163
+
164
+ ```
165
+ src/
166
+ ├── components/
167
+ │ ├── Gantt/
168
+ │ │ ├── Gantt.tsx # Main unified component
169
+ │ │ ├── Grid.tsx # Task list grid
170
+ │ │ ├── Timeline.tsx # Timeline rendering
171
+ │ │ ├── TaskBar.tsx # Task visualization
172
+ │ │ ├── TaskCreator.tsx # Task creation modal
173
+ │ │ ├── TaskEditor.tsx # Task editing modal
174
+ │ │ ├── LinkRenderer.tsx # Dependency arrows
175
+ │ │ ├── DragDrop.tsx # Drag & drop logic
176
+ │ │ ├── FilterSearch.tsx # Filtering system
177
+ │ │ ├── UndoRedo.tsx # Undo/redo system
178
+ │ │ ├── CriticalPath.tsx # Critical path algorithm
179
+ │ │ ├── AutoScheduler.tsx # Auto-scheduling
180
+ │ │ ├── Baselines.tsx # Baseline tracking
181
+ │ │ ├── ExportUtils.tsx # Export functionality
182
+ │ │ └── gantt.css # All styles
183
+ │ ├── types.ts # TypeScript interfaces
184
+ │ └── utils/
185
+ │ └── dateUtils.ts # Date calculations
186
+ └── stories/
187
+ ├── AdvancedGantt.stories.tsx # Basic examples
188
+ ├── GanttProFeatures.stories.tsx # Advanced features
189
+ └── BaselinesDemo.stories.tsx # Baseline demos
190
+ ```
191
+
192
+ ## 🎭 Task Types
193
+
194
+ ```tsx
195
+ interface Task {
196
+ id: string;
197
+ text: string;
198
+ start: Date;
199
+ end: Date;
200
+ duration: number;
201
+ progress: number;
202
+ type?: 'task' | 'milestone' | 'project';
203
+ parent?: string;
204
+ color?: string;
205
+ owner?: string;
206
+ priority?: 'low' | 'medium' | 'high';
207
+ details?: string;
208
+ }
209
+ ```
210
+
211
+ ## 🔗 Dependency Types
212
+
213
+ - **e2s** (End-to-Start) - Task B starts when Task A ends
214
+ - **s2s** (Start-to-Start) - Tasks start together
215
+ - **e2e** (End-to-End) - Tasks end together
216
+ - **s2e** (Start-to-End) - Task B ends when Task A starts
217
+
218
+ ## 🎨 Theming
219
+
220
+ ```tsx
221
+ <Gantt
222
+ tasks={tasks}
223
+ config={{ theme: 'dark' }} // or 'light'
224
+ />
225
+ ```
226
+
227
+ Custom colors can be applied per task:
228
+ ```tsx
229
+ {
230
+ id: '1',
231
+ text: 'High Priority',
232
+ color: '#E74C3C', // Red
233
+ // ...
234
+ }
235
+ ```
236
+
237
+ ## 📊 Export Formats
238
+
239
+ - **CSV** - Simple comma-separated values
240
+ - **Excel** - .xls format with UTF-8 BOM
241
+ - **JSON** - Complete project data (can be imported)
242
+ - **PDF** - Text report (can be enhanced with jsPDF)
243
+
244
+ ## 🤝 Comparison with SVAR Gantt
245
+
246
+ This implementation provides **ALL** features from both SVAR Free and PRO editions in a single component:
247
+
248
+ | Feature | SVAR Free | SVAR PRO | This Implementation |
249
+ |---------|-----------|----------|---------------------|
250
+ | Task Management | ✅ | ✅ | ✅ |
251
+ | Dependencies | ✅ | ✅ | ✅ |
252
+ | Drag & Drop | ✅ | ✅ | ✅ |
253
+ | Progress Tracking | ✅ | ✅ | ✅ |
254
+ | Undo/Redo | ❌ | ✅ | ✅ |
255
+ | Auto-Scheduling | ❌ | ✅ | ✅ |
256
+ | Critical Path | ❌ | ✅ | ✅ |
257
+ | Baselines | ❌ | ✅ | ✅ |
258
+ | Resource Leveling | ❌ | ✅ | ✅ |
259
+ | Export | ❌ | ✅ | ✅ |
260
+ | Filtering | ❌ | ✅ | ✅ |
261
+
262
+ ## 📝 License
263
+
264
+ MIT - Free for commercial and personal use
265
+
266
+ ## 🙏 Acknowledgments
267
+
268
+ - Inspired by [SVAR Gantt Chart](https://svar.dev/demos/react/gantt/)
269
+ - Built with React 19, TypeScript 5.9, and Storybook 10
270
+
271
+ ## 🔗 Links
272
+
273
+ - [GitHub Repository](https://github.com/TimJerry725/ganttchart)
274
+ - [Documentation](./GANTT_FEATURES.md)
275
+ - [Storybook Demos](http://localhost:6006)
276
+
277
+ ---
278
+
279
+ **Made with ❤️ using React + TypeScript**
@@ -0,0 +1 @@
1
+ :root{--wx-gantt-primary: #37a9ef;--wx-gantt-primary-selected: #d5eaf7;--wx-gantt-success: #77d257;--wx-gantt-warning: #fcba2e;--wx-gantt-danger: #fe6158;--wx-gantt-font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;--gantt-header-height: 84px;--gantt-row-height: 44px;--gantt-scale-height: 28px;--wx-gantt-border: 1px solid #e6e6e6;--wx-gantt-border-color: #e6e6e6;--wx-gantt-background: #ffffff;--wx-gantt-background-alt: #f2f3f7;--wx-gantt-background-hover: #eaedf5;--wx-gantt-select-color: #eaedf5;--wx-gantt-task-color: #37a9ef;--wx-gantt-task-fill-color: rgba(0, 0, 0, .15);--wx-gantt-project-color: #81C784;--wx-gantt-milestone-color: #9c27b0;--wx-gantt-milestone-border-radius: 2px;--wx-gantt-bar-border-radius: 3px;--wx-gantt-bar-shadow: 0 1px 2px rgba(44, 47, 60, .06), 0 3px 10px rgba(44, 47, 60, .12);--wx-gantt-font-color: #2c2f3c;--wx-gantt-font-color-alt: #9fa1ae;--wx-gantt-icon-color: #9fa1ae;--font-body: var(--wx-gantt-font-family);--color-primary: var(--wx-gantt-task-color);--color-text-main: var(--wx-gantt-font-color)}.gantt-page-wrapper{display:flex;flex-direction:column;height:calc(100vh - 40px);width:100%}.gantt-container{display:flex;flex-direction:column;flex:1;min-height:0;min-width:0;max-width:100%;overflow:hidden;background-color:var(--wx-gantt-background);border:var(--wx-gantt-border);margin:0;border-radius:var(--wx-gantt-bar-border-radius)}.gantt-container.theme-dark{background-color:#1e1e1e;border-color:#333;color:#e0e0e0;box-shadow:0 4px 12px #0003}.gantt-layout{display:flex;flex:1;overflow-x:auto;overflow-y:auto;position:relative;background-color:#fafafa;scroll-behavior:smooth;min-height:0;min-width:0;width:100%}.theme-dark .gantt-layout{background-color:#1a1a1a}.gantt-grid{display:flex;flex-direction:column;width:720px;min-width:720px;max-width:720px;border-right:var(--wx-gantt-border);background-color:#fff;flex-shrink:0;position:sticky;left:0;z-index:100!important;box-shadow:2px 0 5px #0000000d;height:100%;align-self:flex-start}.theme-dark .gantt-grid{background-color:#252525;border-right-color:#333;box-shadow:2px 0 5px #0000001a}.gantt-grid-header{position:sticky;top:0;z-index:110!important;height:var(--gantt-header-height);display:flex;border-bottom:var(--wx-gantt-border);background-color:#fff;box-shadow:none}.theme-dark .gantt-grid-header{background-color:#2d2d2d;border-bottom-color:#444}.gantt-grid-header-cell{height:100%;padding:0 16px;font-weight:600;font-size:14px;font-family:var(--font-body);border-right:var(--wx-gantt-border);background-color:var(--wx-gantt-background);color:var(--wx-gantt-font-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;justify-content:flex-start;flex-shrink:0;text-transform:none;letter-spacing:0}.gantt-grid-header-cell:last-child{border-right:none}.theme-dark .gantt-grid-header-cell{border-right-color:#333;background-color:#2d2d2d;color:#a0a0a0}.gantt-grid-body{flex:1}.gantt-grid-row{display:flex;border-bottom:var(--wx-gantt-border);cursor:pointer;transition:background-color .2s cubic-bezier(.4,0,.2,1);background-color:var(--wx-gantt-background);height:var(--gantt-row-height);min-height:var(--gantt-row-height);max-height:var(--gantt-row-height)}.gantt-grid-row:hover{background-color:#f8fafc;border-left:2px solid var(--color-primary)}.theme-dark .gantt-grid-row{background-color:#252525;border-bottom-color:#333}.theme-dark .gantt-grid-row:hover{background-color:#2d2d2d}.gantt-grid-row.dragging-row,.gantt-grid-row.descendant-dragging-row{opacity:.3;background-color:#f8f9fa;pointer-events:none}.gantt-ghost-descendant-count{margin-left:8px;background:#2196f3;color:#fff;padding:2px 6px;border-radius:10px;font-size:11px;font-weight:400}.gantt-grid-row.ghost-row{transition:none!important}body.gantt-dragging{-webkit-user-select:none!important;user-select:none!important;cursor:grabbing!important}.gantt-drop-indicator{position:absolute;left:0;right:0;height:2px;background-color:#2196f3;z-index:10;pointer-events:none}.gantt-drop-indicator.above{top:-1px}.gantt-drop-indicator.below{bottom:-1px}.gantt-drop-indicator.inside{top:0;bottom:0;height:auto;background-color:#2196f31a;border:2px solid #2196F3}.gantt-grid-body{position:relative}.gantt-grid-row.selected{background-color:#eff6ff;border-left:3px solid var(--color-primary)}.theme-dark .gantt-grid-row.selected{background-color:#2b3a4a}.gantt-grid-cell{padding:0 12px;font-size:14px;border-right:var(--wx-gantt-border);display:flex;align-items:center;overflow:hidden;font-family:var(--font-body);color:var(--wx-gantt-font-color);white-space:nowrap;text-overflow:ellipsis;flex-shrink:0}.gantt-grid-cell:last-child{border-right:none}.theme-dark .gantt-grid-cell{border-right-color:#2d2d2d;color:#dee2e6}.gantt-grid-cell-text{display:flex;align-items:center;gap:8px;white-space:nowrap;overflow:hidden;width:100%;color:#1a1f23;font-weight:400}.gantt-row-drag-handle{cursor:grab;color:#adb5bd;font-size:14px;line-height:1;padding:0 4px;-webkit-user-select:none;user-select:none;opacity:0;transition:opacity .2s}.gantt-grid-row:hover .gantt-row-drag-handle{opacity:1}.gantt-dragging .gantt-row-drag-handle{cursor:grabbing!important;z-index:100}.gantt-tree-icon{width:16px;height:16px;display:flex;align-items:center;justify-content:center;font-size:10px;color:#666;cursor:pointer;-webkit-user-select:none;user-select:none;background-color:transparent;border:none}.gantt-tree-icon:hover{background-color:#efefef}.gantt-progress-cell{display:flex;align-items:center;gap:8px;width:100%}.gantt-progress-bar-bg{flex:1;height:16px;background-color:#e0e0e0;border-radius:8px;overflow:hidden;position:relative}.gantt-progress-bar-fill{height:100%;background:linear-gradient(90deg,#81c784,#a5d6a7);transition:width .3s}.gantt-progress-text{font-size:11px;color:#666;min-width:35px;text-align:right}.gantt-timeline-container{display:flex;flex-direction:column;background-color:#fff;flex-shrink:0;min-width:0;overflow:visible}.theme-dark .gantt-timeline-container{background-color:#1e1e1e}.gantt-timeline-header{position:sticky;top:0;z-index:30;background-color:var(--wx-gantt-background);border-bottom:var(--wx-gantt-border);height:var(--gantt-header-height);box-shadow:none;overflow:visible}.gantt-timeline-scale{display:flex;border-bottom:var(--wx-gantt-border);align-items:center;min-height:var(--gantt-scale-height);width:100%}.theme-dark .gantt-timeline-header{background-color:#1e1e1e;border-bottom-color:#444}.gantt-timeline-scale-month{height:var(--gantt-scale-height);background-color:var(--wx-gantt-background);font-weight:600;display:flex;align-items:center;justify-content:center;border-bottom:var(--wx-gantt-border);font-size:13px;color:var(--wx-gantt-font-color);text-transform:none;font-family:var(--font-body)}.theme-dark .gantt-timeline-scale-month{background-color:#2a2a2a;color:#adb5bd;border-bottom-color:#333}.gantt-timeline-scale-range{height:var(--gantt-scale-height);background-color:var(--wx-gantt-background);font-size:13px;font-weight:600;color:var(--wx-gantt-font-color);display:flex;align-items:center;justify-content:center;border-bottom:var(--wx-gantt-border);text-transform:none;letter-spacing:0;font-family:var(--font-body)}.theme-dark .gantt-timeline-scale-range{background-color:#1e1e1e;color:#888;border-bottom-color:#333}.gantt-timeline-scale-day{height:var(--gantt-scale-height);background-color:var(--wx-gantt-background);border-bottom:none;display:flex;align-items:center;justify-content:center;font-size:13px;color:var(--wx-gantt-font-color);font-weight:400;font-family:var(--font-body)}.theme-dark .gantt-timeline-scale-day{background-color:#1e1e1e;color:#dee2e6}.gantt-timeline-cell{flex-shrink:0;height:100%;display:flex;align-items:center;justify-content:center;border-right:var(--wx-gantt-border);font-size:13px;white-space:nowrap;padding:0 4px;color:var(--wx-gantt-font-color);font-family:var(--font-body);min-width:0;overflow:hidden;text-overflow:ellipsis}.theme-dark .gantt-timeline-cell{border-right-color:#444}.gantt-timeline-cell.weekend{background-color:#f8fafc}.theme-dark .gantt-timeline-cell.weekend{background-color:#2a2a2a}.gantt-timeline-cell.holiday{background-color:#fff8f0}.theme-dark .gantt-timeline-cell.holiday{background-color:#3a2a1a}.gantt-timeline-body{position:relative;min-height:0}.gantt-timeline-grid{display:flex;position:absolute;top:0;left:0;bottom:0;pointer-events:none;z-index:0}.gantt-timeline-grid-column{flex-shrink:0;border-right:1px solid #e5e7eb}.theme-dark .gantt-timeline-grid-column{border-right-color:#2d2d2d}.gantt-timeline-grid-column.weekend{background-color:#f8fafc}.theme-dark .gantt-timeline-grid-column.weekend{background-color:#252525}.gantt-timeline-grid-column.holiday{background-color:#fff8f0}.theme-dark .gantt-timeline-grid-column.holiday{background-color:#332a1a}.gantt-timeline-tasks{position:relative;z-index:1;display:flex;flex-direction:column}.gantt-links-layer{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:1;overflow:visible}.gantt-link{pointer-events:all;cursor:pointer;transition:all .2s ease}.gantt-link-line{transition:all .2s ease;stroke:#cbd5e0;stroke-width:1.5}.theme-dark .gantt-link-line{stroke:#4a5568}.gantt-link:hover .gantt-link-line{stroke-width:2;stroke:#a0aec0}.theme-dark .gantt-link:hover .gantt-link-line{stroke:#90caf9}.gantt-link-arrow{transition:all .2s ease;fill:#cbd5e0}.theme-dark .gantt-link-arrow{fill:#64b5f6}.gantt-link:hover .gantt-link-arrow{fill:#2196f3;filter:drop-shadow(0 2px 4px rgba(33,150,243,.4))}.theme-dark .gantt-link:hover .gantt-link-arrow{fill:#90caf9}.gantt-timeline-row{position:relative;width:100%;border-bottom:1px solid #e5e7eb;height:var(--gantt-row-height);min-height:var(--gantt-row-height);max-height:var(--gantt-row-height);flex-shrink:0}.theme-dark .gantt-timeline-row{border-bottom-color:#333}.gantt-task-bar{position:absolute;height:28px;top:50%;transform:translateY(-50%);border-radius:var(--wx-gantt-bar-border-radius);cursor:move;transition:box-shadow .2s,transform .1s;display:flex;align-items:center;overflow:visible;border:none;box-shadow:0 1px 3px #0000001a}.gantt-task-bar:hover{box-shadow:0 4px 12px #00000026;transform:translateY(-50%) scale(1.02);z-index:100!important;filter:brightness(1.05)}.gantt-task-bar.selected{box-shadow:0 0 0 2px #fff,0 0 0 4px var(--color-primary);z-index:10;border:2px solid var(--color-primary)}.gantt-task-bar.dragging{opacity:.85;cursor:grabbing;box-shadow:0 10px 20px #00000030,0 6px 6px #0000003b;transition:none}.gantt-task-bar.project{height:28px;border-radius:var(--wx-gantt-bar-border-radius);font-weight:600;background-color:var(--wx-gantt-project-color)!important}.gantt-task-bar.milestone{width:0!important;height:0!important;overflow:visible;border:none;background:none!important;box-shadow:none}.gantt-milestone-diamond{position:absolute;top:50%;left:50%;width:14px;height:14px;background-color:var(--wx-gantt-milestone-color);transform:translate(-50%,-50%) rotate(45deg);border-radius:var(--wx-gantt-milestone-border-radius);box-shadow:var(--wx-gantt-bar-shadow);z-index:2;cursor:pointer}.gantt-milestone-text{position:absolute;left:20px;top:50%;transform:translateY(-50%);white-space:nowrap;color:var(--wx-gantt-font-color);font-size:13px;font-weight:400;pointer-events:none;font-family:var(--font-body)}.gantt-task-progress{position:absolute;left:0;top:0;height:100%;background-color:var(--wx-gantt-task-fill-color);pointer-events:none;z-index:1;border-radius:inherit}.gantt-task-content{position:relative;z-index:2;padding:0 12px;color:#fff;font-size:12px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;text-shadow:0 1px 2px rgba(0,0,0,.25);font-family:var(--font-body);height:100%;display:flex;align-items:center}.milestone .gantt-task-content{overflow:visible}.gantt-task-text{display:block;overflow:hidden;text-overflow:ellipsis}.gantt-task-resize-handle{position:absolute;top:0;width:8px;height:100%;cursor:ew-resize;z-index:3}.gantt-task-resize-left{left:0}.gantt-task-resize-right{right:0}.gantt-task-resize-handle:hover{background-color:#ffffff4d}.gantt-toolbar-wrapper{background-color:#f8f9fa;border-bottom:1px solid #dfe3e6;padding:4px 0}.gantt-toolbar{padding:8px 20px;background-color:transparent;display:flex;justify-content:space-between;align-items:center;z-index:100}.theme-dark .gantt-toolbar{background-color:#252525;border-bottom-color:#333}.gantt-toolbar-left,.gantt-toolbar-right{display:flex;align-items:center}.gantt-tooltip{padding:8px 12px;max-width:250px}.gantt-tooltip-title{font-weight:600;font-size:14px;margin-bottom:4px;color:#fff}.gantt-tooltip-dates{font-size:12px;color:#ced4da;margin-bottom:4px}.gantt-tooltip-progress,.gantt-tooltip-owner{font-size:12px;color:#fff}.gantt-task-group{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none}.gantt-task-bar.segment{pointer-events:all;background:repeating-linear-gradient(45deg,transparent,transparent 10px,rgba(255,255,255,.1) 10px,rgba(255,255,255,.1) 20px);border:1px dashed rgba(255,255,255,.4)}.gantt-task-bar.segment:hover{transform:translateY(-50%) scale(1.05);box-shadow:0 4px 8px #0000004d}.gantt-layout::-webkit-scrollbar{width:8px;height:8px}.gantt-layout::-webkit-scrollbar-track{background:transparent}.gantt-layout::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:10px;border:2px solid #ffffff}.gantt-layout::-webkit-scrollbar-thumb:hover{background:#94a3b8}.theme-dark .gantt-layout::-webkit-scrollbar-track{background:transparent;border-color:transparent}.theme-dark .gantt-layout::-webkit-scrollbar-thumb{background:#4a5568;border-color:#1a1a1a}.theme-dark .gantt-layout::-webkit-scrollbar-thumb:hover{background:#718096}.gantt-modal-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000}.gantt-modal{background-color:#fff;border-radius:8px;box-shadow:0 4px 20px #0000004d;max-width:600px;width:90%;max-height:90vh;overflow:hidden;display:flex;flex-direction:column}.theme-dark .gantt-modal{background-color:#2d2d2d;color:#fff}.gantt-modal-header{padding:20px;border-bottom:1px solid #e0e0e0;display:flex;justify-content:space-between;align-items:center}.theme-dark .gantt-modal-header{border-bottom-color:#444}.gantt-modal-header h3{margin:0;font-size:20px;font-weight:600}.gantt-modal-close{background:none;border:none;font-size:24px;cursor:pointer;color:#666;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all .2s}.gantt-modal-close:hover{background-color:#f0f0f0;color:#333}.theme-dark .gantt-modal-close:hover{background-color:#3a3a3a;color:#fff}.gantt-modal-body{padding:20px;overflow-y:auto;flex:1}.gantt-form-row{margin-bottom:16px}.gantt-form-row label{display:block;margin-bottom:6px;font-weight:500;font-size:14px;color:#333}.theme-dark .gantt-form-row label{color:#ddd}.gantt-form-row input[type=text],.gantt-form-row input[type=date],.gantt-form-row input[type=number],.gantt-form-row select,.gantt-form-row textarea{width:100%;padding:10px 12px;border:1px solid #d1d5da;border-radius:6px;font-size:14px;font-family:inherit;transition:border-color .2s}.theme-dark .gantt-form-row input,.theme-dark .gantt-form-row select,.theme-dark .gantt-form-row textarea{background-color:#3a3a3a;border-color:#555;color:#fff}.gantt-form-row input:focus,.gantt-form-row select:focus,.gantt-form-row textarea:focus{outline:none;border-color:#2196f3}.gantt-form-row textarea{resize:vertical;min-height:80px}.gantt-form-row-group{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-bottom:16px}.gantt-progress-value{margin-left:10px;font-weight:600;color:#2196f3}.gantt-modal-footer{padding:16px 20px;border-top:1px solid #e0e0e0;display:flex;justify-content:space-between;align-items:center}.theme-dark .gantt-modal-footer{border-top-color:#444}.gantt-modal-footer-right{display:flex;gap:10px}.gantt-btn{padding:10px 20px;border:none;border-radius:6px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s}.gantt-btn-primary{background-color:#2196f3;color:#fff}.gantt-btn-primary:hover{background-color:#1976d2;box-shadow:0 2px 8px #2196f34d}.gantt-btn-secondary{background-color:#f0f0f0;color:#333}.theme-dark .gantt-btn-secondary{background-color:#3a3a3a;color:#fff}.gantt-btn-secondary:hover{background-color:#e0e0e0}.theme-dark .gantt-btn-secondary:hover{background-color:#4a4a4a}.gantt-btn-danger{background-color:#f44336;color:#fff}.gantt-btn-danger:hover{background-color:#d32f2f}.gantt-filter-container{background-color:#f8f9fa;border-bottom:1px solid #e0e0e0}.theme-dark .gantt-filter-container{background-color:#2a2a2a;border-bottom-color:#444}.gantt-filter-bar{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;gap:16px}.gantt-filter-left{display:flex;align-items:center;gap:10px}.gantt-filter-right{display:flex;align-items:center;gap:10px;margin-left:auto}.gantt-search-antd .ant-input-affix-wrapper{border-radius:6px;font-family:var(--font-body)}.gantt-filter-select-antd .ant-select-selector{border-radius:6px!important;font-family:var(--font-body)}.gantt-filter-clear-antd{border-radius:6px;font-family:var(--font-body);font-weight:500}.theme-dark .gantt-search-antd .ant-input-affix-wrapper,.theme-dark .gantt-filter-select-antd .ant-select-selector{background-color:#3a3a3a;border-color:#555;color:#fff}.theme-dark .gantt-search-antd .ant-input,.theme-dark .gantt-filter-select-antd .ant-select-selection-item{color:#fff}.theme-dark .gantt-search-antd .ant-input-prefix,.theme-dark .gantt-filter-select-antd .ant-select-arrow{color:#aaa}.gantt-task-bar.critical{background-color:#f44336!important;box-shadow:0 0 0 2px #f443364d}.gantt-task-bar.critical .gantt-task-progress{background-color:#fff6}.gantt-baseline-container{position:relative;width:100%;height:100%}.gantt-baseline-bar{position:absolute;height:8px;background-color:#bdbdbd;top:50%;transform:translateY(calc(-50% + 20px));border-radius:4px;z-index:0;pointer-events:none}.gantt-variance-indicator{position:absolute;height:2px;bottom:0;opacity:.5}.gantt-variance-indicator.delayed{background-color:#f44336}.gantt-variance-indicator.ahead{background-color:#4caf50}.gantt-variance-label{position:absolute;top:-18px;right:0;font-size:11px;font-weight:600;padding:2px 6px;border-radius:3px;background-color:#ffffffe6}.gantt-toolbar{display:flex;justify-content:space-between;align-items:center}.gantt-toolbar-left,.gantt-toolbar-right{display:flex;gap:8px;align-items:center}.gantt-toolbar button.active{background-color:#1976d2}.gantt-milestone-marker{width:14px;height:14px;background-color:#9c27b0;transform:rotate(45deg);margin:0 auto}.gantt-milestone-text{position:absolute;left:100%;top:50%;transform:translateY(-50%);margin-left:10px;white-space:nowrap;font-size:11px;color:#555;font-family:var(--font-body);pointer-events:none}.theme-dark .gantt-milestone-text{color:#ccc}.gantt-toolbar-separator{width:1px;height:24px;background-color:#ddd;margin:0 4px}.theme-dark .gantt-toolbar-separator{background-color:#555}.gantt-dependency-editor-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:10000;animation:fadeIn .2s ease-out}.gantt-dependency-editor{background:#fff;border-radius:8px;box-shadow:0 4px 20px #00000026;width:700px;max-width:90vw;max-height:90vh;overflow:hidden;display:flex;flex-direction:column;animation:slideUp .3s ease-out}.gantt-dependency-editor-header{display:flex;justify-content:space-between;align-items:center;padding:20px 24px;border-bottom:1px solid #e0e0e0;background-color:#f8f9fa}.gantt-dependency-editor-header h3{margin:0;font-size:18px;font-weight:600;color:#333}.gantt-dependency-editor-body{padding:24px;overflow-y:auto;flex:1}.gantt-dependency-section{margin-bottom:32px}.gantt-dependency-section h4{margin:0 0 12px;font-size:14px;font-weight:600;color:#555;text-transform:uppercase;letter-spacing:.5px}.gantt-dependency-section h5{margin:0 0 8px;font-size:13px;font-weight:600;color:#666}.gantt-empty-message{color:#999;font-style:italic;padding:12px;background-color:#f8f9fa;border-radius:4px;text-align:center}.gantt-dependency-list{list-style:none;padding:0;margin:0}.gantt-dependency-item{display:flex;justify-content:space-between;align-items:center;padding:12px;margin-bottom:8px;background-color:#f8f9fa;border-radius:6px;border:1px solid #e0e0e0;transition:all .2s}.gantt-dependency-item:hover{background-color:#e9ecef;border-color:#007bff}.gantt-dependency-info{display:flex;flex-direction:column;gap:4px;flex:1}.gantt-dependency-task-name{font-weight:500;color:#333;font-size:14px}.gantt-dependency-type{font-size:12px;color:#666;padding:2px 8px;background-color:#e3f2fd;border-radius:12px;display:inline-block;width:fit-content}.gantt-dependency-lag{font-size:11px;color:#ff9800;font-weight:600;padding:2px 6px;background-color:#fff3e0;border-radius:10px;display:inline-block;width:fit-content}.gantt-dependency-remove{background-color:transparent;border:none;font-size:16px;cursor:pointer;padding:4px 8px;border-radius:4px;transition:all .2s}.gantt-dependency-remove:hover{background-color:#ffebee}.gantt-add-dependency{border-top:2px dashed #dee2e6;padding-top:24px}.gantt-dependency-form{display:flex;flex-direction:column;gap:16px}.gantt-form-row{display:flex;flex-direction:column;gap:6px}.gantt-form-row label{font-size:13px;font-weight:500;color:#555;display:flex;flex-direction:column;gap:2px}.gantt-help-text{font-size:11px;color:#999;font-weight:400}.gantt-select,.gantt-input{padding:10px 12px;border:1px solid #ced4da;border-radius:6px;font-size:14px;font-family:inherit;transition:all .2s;background-color:#fff}.gantt-select:focus,.gantt-input:focus{outline:none;border-color:#007bff;box-shadow:0 0 0 3px #007bff1a}.gantt-form-actions{display:flex;gap:12px;margin-top:8px}.gantt-btn{padding:10px 20px;border:none;border-radius:6px;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s;font-family:inherit}.gantt-btn-primary{background-color:#007bff;color:#fff}.gantt-btn-primary:hover:not(:disabled){background-color:#0056b3;transform:translateY(-1px);box-shadow:0 2px 8px #007bff4d}.gantt-btn-primary:disabled{background-color:#ccc;cursor:not-allowed;opacity:.6}.gantt-dependency-help{background-color:#f8f9fa;border:1px solid #dee2e6;border-radius:8px;padding:16px;margin-top:24px}.gantt-dependency-help ul{margin:8px 0;padding-left:20px}.gantt-dependency-help li{margin-bottom:6px;font-size:13px;line-height:1.5;color:#555}.gantt-dependency-help strong{color:#333}.gantt-dependency-help code{background-color:#e9ecef;padding:2px 6px;border-radius:3px;font-family:var(--font-heading);font-size:12px;color:#d63384}.gantt-dependency-help p{margin:4px 0;font-size:13px;color:#666}.theme-dark .gantt-dependency-editor{background-color:#2d2d2d}.theme-dark .gantt-dependency-editor-header{background-color:#252525;border-bottom-color:#444}.theme-dark .gantt-dependency-editor-header h3{color:#e0e0e0}.theme-dark .gantt-empty-message{background-color:#252525;color:#888}.theme-dark .gantt-dependency-item{background-color:#252525;border-color:#444}.theme-dark .gantt-dependency-item:hover{background-color:#333;border-color:#007bff}.theme-dark .gantt-dependency-task-name{color:#e0e0e0}.theme-dark .gantt-dependency-type{background-color:#1a2332;color:#64b5f6}.theme-dark .gantt-dependency-help{background-color:#252525;border-color:#444}.theme-dark .gantt-dependency-help code{background-color:#333;color:#ff79c6}.theme-dark .gantt-select,.theme-dark .gantt-input{background-color:#333;border-color:#555;color:#e0e0e0}.theme-dark .gantt-dependency-section h4,.theme-dark .gantt-dependency-section h5,.theme-dark .gantt-form-row label{color:#b0b0b0}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}h1,h2,h3,h4,h5,h6,.gantt-toolbar button,.gantt-filter-label,.gantt-dependency-section h4,.gantt-dependency-section h5{font-family:var(--font-heading)}.gantt-grid-cell,.gantt-task-text,.gantt-dependency-task-name,.gantt-form-row label,.gantt-dependency-help p,.gantt-dependency-help li{font-family:var(--font-body)}.gantt-dependency-modal .ant-modal-header{font-family:var(--font-heading)}.gantt-dependency-modal .ant-modal-body,.gantt-dependency-modal .ant-list-item-meta-title{font-family:var(--font-body)}.gantt-dependency-modal .ant-typography{font-family:inherit}.gantt-dependency-modal code{font-family:var(--font-heading)}.gantt-dependency-modal .ant-btn,.gantt-dependency-modal .ant-select,.gantt-dependency-modal .ant-input-number{font-family:var(--font-body)}.gantt-context-menu-overlay{position:fixed;inset:0;z-index:9999;background:transparent}.gantt-context-menu{font-family:var(--font-body)}.gantt-context-menu .ant-menu{font-family:var(--font-body);min-width:180px}.gantt-context-menu .ant-menu-item{font-family:var(--font-body);font-size:13px;padding:8px 16px;height:auto;line-height:1.5}.gantt-context-menu .ant-menu-item-icon{margin-right:8px;font-size:14px}.theme-dark .gantt-context-menu .ant-menu{background-color:#2d2d2d;border-color:#444}.theme-dark .gantt-context-menu .ant-menu-item{color:#e0e0e0}.theme-dark .gantt-context-menu .ant-menu-item:hover{background-color:#3a3a3a;color:#fff}@media(max-width:1024px){.gantt-grid{min-width:250px;width:300px;max-width:40%}.gantt-toolbar,.gantt-toolbar-left,.gantt-toolbar-right{flex-wrap:wrap;gap:8px}.gantt-toolbar button{font-size:12px;padding:6px 12px}.gantt-toolbar button svg{margin-right:4px}}@media(max-width:768px){.gantt-page-wrapper{height:100vh;overflow:auto}.gantt-container{min-height:auto}.gantt-layout{flex-direction:column;height:auto;min-height:600px}.gantt-grid{min-width:100%;width:100%;max-width:100%;max-height:300px;border-right:none;border-bottom:2px solid #ddd}.gantt-timeline-container{flex:1;min-height:400px;overflow-x:auto;overflow-y:auto}.gantt-toolbar{padding:8px;flex-direction:column;align-items:stretch}.gantt-toolbar-left,.gantt-toolbar-right{width:100%;justify-content:flex-start;flex-wrap:wrap;gap:6px}.gantt-toolbar button{flex:1 1 auto;min-width:80px;font-size:11px;padding:8px 10px}.gantt-toolbar button svg{margin-right:4px;font-size:12px}.gantt-toolbar button{position:relative}.gantt-toolbar button svg{margin-right:0!important}.gantt-toolbar button:after{content:""}.gantt-filter-bar{flex-direction:column;gap:8px;padding:8px}.gantt-filter-left,.gantt-filter-right{width:100%;flex-direction:column;gap:8px}.gantt-search-antd,.gantt-filter-select-antd{width:100%!important}}@media(max-width:480px){.gantt-page-wrapper{height:100vh;overflow:auto}.gantt-toolbar{padding:6px}.gantt-toolbar button{font-size:10px;padding:6px 8px;min-width:60px}.gantt-toolbar button svg{font-size:11px;margin-right:2px}.gantt-toolbar button{display:inline-flex;align-items:center;justify-content:center;padding:8px!important;min-width:44px;position:relative}.gantt-toolbar button svg{margin-right:0!important;flex-shrink:0}.gantt-toolbar button{text-indent:-9999px;overflow:hidden;white-space:nowrap}.gantt-toolbar button svg{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);text-indent:0}.gantt-grid{max-height:250px}.gantt-grid-header-cell{padding:6px 8px;font-size:11px}.gantt-grid-cell{padding:6px 8px;font-size:12px}.gantt-timeline-container{min-height:350px}.gantt-timeline-cell{padding:6px 4px;font-size:11px;min-width:40px}.gantt-timeline-scale{font-size:10px}.gantt-dependency-modal .ant-modal{max-width:95vw!important;margin:10px auto!important}.gantt-dependency-editor{width:95vw!important;max-width:95vw!important}}@media(hover:none)and (pointer:coarse){.gantt-toolbar button{min-height:44px;min-width:44px;padding:10px 12px}.gantt-grid-row{min-height:48px}.gantt-grid-cell{padding:10px 12px}.gantt-timeline-cell{min-width:50px;padding:10px}}@media(-webkit-min-device-pixel-ratio:2),(min-resolution:192dpi){.gantt-grid,.gantt-timeline-container{border-width:.5px}}@media(max-width:768px)and (orientation:landscape){.gantt-layout{flex-direction:row}.gantt-grid{max-height:none;height:100%;width:500px;min-width:500px;max-width:500px}.gantt-timeline-container{min-height:auto;height:100%}}@media print{.gantt-toolbar,.gantt-filter-container{display:none}.gantt-layout{flex-direction:row}.gantt-grid{width:500px;max-width:500px;min-width:500px}.gantt-container,.gantt-grid,.gantt-timeline-container{overflow:visible}}@media(prefers-reduced-motion:reduce){.gantt-grid,.gantt-toolbar button,.gantt-grid-row,.gantt-progress-bar-fill{transition:none}}@media(max-width:768px){.gantt-timeline-header{overflow-x:auto;-webkit-overflow-scrolling:touch}.gantt-timeline-scale{min-width:max-content}.gantt-timeline-body{overflow-x:auto;-webkit-overflow-scrolling:touch}}.gantt-page-wrapper{position:relative;width:100%;max-width:100vw;overflow-x:hidden}.gantt-container{max-width:100%;overflow:hidden}.gantt-layout{max-width:100%;overflow-x:auto;overflow-y:auto}.dependency-popover .task-list-item{transition:background-color .2s ease,border-left .2s ease;border-left:3px solid transparent}.dependency-popover .task-list-item:hover{background-color:#f0f7ff!important;border-left-color:#1890ff}.dependency-popover .task-list-item.selected{background-color:#e6f4ff!important;border-left-color:#1890ff;font-weight:500}.dependency-popover .ant-list-item{border-bottom:1px solid #f0f0f0}.dependency-popover .ant-list-item:last-child{border-bottom:none}.gantt-dependency-modal .ant-modal-body{padding:24px}.gantt-dependency-modal .ant-card{box-shadow:0 1px 2px #00000008;border:1px solid #f0f0f0}.gantt-dependency-modal .ant-list-item{padding:12px 16px;transition:background-color .2s ease}.gantt-dependency-modal .ant-list-item:hover{background-color:#fafafa}.dependency-popover .ant-input:focus,.dependency-popover .ant-select-focused .ant-select-selector,.dependency-popover .ant-input-number-focused{border-color:#1890ff;box-shadow:0 0 0 2px #1890ff1a}.dependency-popover .ant-btn-primary{background-color:#5c67f2;border-color:#5c67f2;font-weight:500;transition:all .3s ease}.dependency-popover .ant-btn-primary:hover{background-color:#4854e0;border-color:#4854e0;transform:translateY(-1px);box-shadow:0 4px 12px #5c67f24d}.dependency-popover .ant-btn-primary:disabled{background-color:#f5f5f5;border-color:#d9d9d9;color:#00000040;transform:none;box-shadow:none}