tg-ganttchart 0.0.13 → 0.0.14

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.
@@ -3427,8 +3427,8 @@ var render = function render() {
3427
3427
  };
3428
3428
  var staticRenderFns = [];
3429
3429
 
3430
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/GanttElastic.vue?vue&type=template&id=0a0b0d9f
3431
- var GanttElasticvue_type_template_id_0a0b0d9f_render = function render() {
3430
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/GanttElastic.vue?vue&type=template&id=95091692
3431
+ var GanttElasticvue_type_template_id_95091692_render = function render() {
3432
3432
  var _vm = this,
3433
3433
  _c = _vm._self._c,
3434
3434
  _setup = _vm._self._setupProxy;
@@ -3457,7 +3457,7 @@ var GanttElasticvue_type_template_id_0a0b0d9f_render = function render() {
3457
3457
  }
3458
3458
  }), _vm._t("footer")], 2);
3459
3459
  };
3460
- var GanttElasticvue_type_template_id_0a0b0d9f_staticRenderFns = [];
3460
+ var GanttElasticvue_type_template_id_95091692_staticRenderFns = [];
3461
3461
 
3462
3462
  // EXTERNAL MODULE: ./node_modules/core-js/modules/es.array.push.js
3463
3463
  var es_array_push = __webpack_require__(4114);
@@ -3812,8 +3812,8 @@ var MainViewvue_type_template_id_79e1eba9_render = function render() {
3812
3812
  };
3813
3813
  var MainViewvue_type_template_id_79e1eba9_staticRenderFns = [];
3814
3814
 
3815
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/TaskList/TaskList.vue?vue&type=template&id=74ce1216
3816
- var TaskListvue_type_template_id_74ce1216_render = function render() {
3815
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/TaskList/TaskList.vue?vue&type=template&id=b705a4ea
3816
+ var TaskListvue_type_template_id_b705a4ea_render = function render() {
3817
3817
  var _vm = this,
3818
3818
  _c = _vm._self._c;
3819
3819
  return _c('div', {
@@ -3842,17 +3842,36 @@ var TaskListvue_type_template_id_74ce1216_render = function render() {
3842
3842
  style: {
3843
3843
  ..._vm.root.style['task-list-items'],
3844
3844
  height: _vm.root.state.options.rowsHeight + 'px'
3845
+ },
3846
+ on: {
3847
+ "scroll": _vm.onScroll
3845
3848
  }
3846
- }, _vm._l(_vm.root.visibleTasks, function (task) {
3849
+ }, [_c('div', {
3850
+ style: {
3851
+ height: _vm.totalHeight + 'px',
3852
+ position: 'relative'
3853
+ }
3854
+ }, [_c('div', {
3855
+ style: {
3856
+ transform: `translateY(${_vm.offsetY}px)`,
3857
+ position: 'absolute',
3858
+ top: 0,
3859
+ left: 0,
3860
+ right: 0
3861
+ }
3862
+ }, _vm._l(_vm.visibleTasks, function (task) {
3847
3863
  return _c('task-list-item', {
3848
3864
  key: task.id,
3865
+ style: {
3866
+ height: _vm.taskHeight + 'px'
3867
+ },
3849
3868
  attrs: {
3850
3869
  "task": task
3851
3870
  }
3852
3871
  });
3853
- }), 1)], 1)]);
3872
+ }), 1)])])], 1)]);
3854
3873
  };
3855
- var TaskListvue_type_template_id_74ce1216_staticRenderFns = [];
3874
+ var TaskListvue_type_template_id_b705a4ea_staticRenderFns = [];
3856
3875
 
3857
3876
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/TaskList/TaskListHeader.vue?vue&type=template&id=2ecc0032
3858
3877
  var TaskListHeadervue_type_template_id_2ecc0032_render = function render() {
@@ -3905,8 +3924,8 @@ var TaskListHeadervue_type_template_id_2ecc0032_render = function render() {
3905
3924
  };
3906
3925
  var TaskListHeadervue_type_template_id_2ecc0032_staticRenderFns = [];
3907
3926
 
3908
- ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Expander.vue?vue&type=template&id=ac398cf4
3909
- var Expandervue_type_template_id_ac398cf4_render = function render() {
3927
+ ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/templateLoader.js??ruleSet[1].rules[3]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Expander.vue?vue&type=template&id=4831d194
3928
+ var Expandervue_type_template_id_4831d194_render = function render() {
3910
3929
  var _vm = this,
3911
3930
  _c = _vm._self._c;
3912
3931
  return _c('div', {
@@ -3943,7 +3962,7 @@ var Expandervue_type_template_id_ac398cf4_render = function render() {
3943
3962
  }
3944
3963
  })]) : _vm._e()]);
3945
3964
  };
3946
- var Expandervue_type_template_id_ac398cf4_staticRenderFns = [];
3965
+ var Expandervue_type_template_id_4831d194_staticRenderFns = [];
3947
3966
 
3948
3967
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/Expander.vue?vue&type=script&lang=js
3949
3968
 
@@ -4000,7 +4019,9 @@ var Expandervue_type_template_id_ac398cf4_staticRenderFns = [];
4000
4019
  }
4001
4020
  let collapsed = 0;
4002
4021
  for (let i = 0, len = this.tasks.length; i < len; i++) {
4003
- if (this.tasks[i].collapsed) {
4022
+ // Use original task if available (for virtual scrolling), otherwise use the task itself
4023
+ const originalTask = this.tasks[i]._originalTask || this.tasks[i];
4024
+ if (originalTask.collapsed) {
4004
4025
  collapsed++;
4005
4026
  }
4006
4027
  }
@@ -4025,7 +4046,9 @@ var Expandervue_type_template_id_ac398cf4_staticRenderFns = [];
4025
4046
  }
4026
4047
  const collapsed = !this.collapsed;
4027
4048
  this.tasks.forEach(task => {
4028
- task.collapsed = collapsed;
4049
+ // Use original task if available (for virtual scrolling), otherwise use the task itself
4050
+ const originalTask = task._originalTask || task;
4051
+ originalTask.collapsed = collapsed;
4029
4052
  });
4030
4053
 
4031
4054
  // Force reactivity update
@@ -4046,8 +4069,8 @@ var Expandervue_type_template_id_ac398cf4_staticRenderFns = [];
4046
4069
  ;
4047
4070
  var Expander_component = normalizeComponent(
4048
4071
  components_Expandervue_type_script_lang_js,
4049
- Expandervue_type_template_id_ac398cf4_render,
4050
- Expandervue_type_template_id_ac398cf4_staticRenderFns,
4072
+ Expandervue_type_template_id_4831d194_render,
4073
+ Expandervue_type_template_id_4831d194_staticRenderFns,
4051
4074
  false,
4052
4075
  null,
4053
4076
  null,
@@ -4576,6 +4599,7 @@ var TaskListItem_component = normalizeComponent(
4576
4599
  ;// ./node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/components/TaskList/TaskList.vue?vue&type=script&lang=js
4577
4600
 
4578
4601
 
4602
+
4579
4603
  /* harmony default export */ var TaskListvue_type_script_lang_js = ({
4580
4604
  name: 'TaskList',
4581
4605
  components: {
@@ -4584,7 +4608,104 @@ var TaskListItem_component = normalizeComponent(
4584
4608
  },
4585
4609
  inject: ['root'],
4586
4610
  data() {
4587
- return {};
4611
+ return {
4612
+ scrollTop: 0,
4613
+ containerHeight: 0,
4614
+ bufferSize: 5,
4615
+ // Number of extra items to render above and below viewport
4616
+ lastScrollTime: 0,
4617
+ scrollThrottleDelay: 16 // ~60fps
4618
+ };
4619
+ },
4620
+ computed: {
4621
+ /**
4622
+ * Get all tasks that should be visible
4623
+ */
4624
+ allVisibleTasks() {
4625
+ return this.root.visibleTasks || [];
4626
+ },
4627
+ /**
4628
+ * Get task height
4629
+ */
4630
+ taskHeight() {
4631
+ return this.root.state.options.row.height + this.root.state.options.chart.grid.horizontal.gap * 2;
4632
+ },
4633
+ /**
4634
+ * Get total height of all tasks
4635
+ */
4636
+ totalHeight() {
4637
+ return this.allVisibleTasks.length * this.taskHeight;
4638
+ },
4639
+ /**
4640
+ * Get visible range for virtual scrolling
4641
+ */
4642
+ visibleRange() {
4643
+ const start = Math.max(0, Math.floor(this.scrollTop / this.taskHeight) - this.bufferSize);
4644
+ const end = Math.min(this.allVisibleTasks.length, Math.ceil((this.scrollTop + this.containerHeight) / this.taskHeight) + this.bufferSize);
4645
+ return {
4646
+ start,
4647
+ end
4648
+ };
4649
+ },
4650
+ /**
4651
+ * Get visible tasks for virtual scrolling
4652
+ * This respects the expand/collapse state from the root component
4653
+ */
4654
+ visibleTasks() {
4655
+ // First get all tasks that should be visible based on expand/collapse state
4656
+ const allVisibleTasks = this.root.visibleTasks || [];
4657
+
4658
+ // If we have virtual scrolling enabled and enough tasks, apply viewport culling
4659
+ if (allVisibleTasks.length > 100 && this.containerHeight > 0) {
4660
+ const {
4661
+ start,
4662
+ end
4663
+ } = this.visibleRange;
4664
+ return allVisibleTasks.slice(start, end).map((task, index) => {
4665
+ // Create a wrapper object that preserves the original task reference
4666
+ return {
4667
+ ...task,
4668
+ virtualIndex: start + index,
4669
+ _originalTask: task // Keep reference to original task for expander
4670
+ };
4671
+ });
4672
+ }
4673
+
4674
+ // For smaller datasets or when virtual scrolling is not needed, return all visible tasks
4675
+ return allVisibleTasks.map((task, index) => ({
4676
+ ...task,
4677
+ virtualIndex: index,
4678
+ _originalTask: task // Keep reference to original task for expander
4679
+ }));
4680
+ },
4681
+ /**
4682
+ * Get offset for virtual scrolling
4683
+ */
4684
+ offsetY() {
4685
+ return this.visibleRange.start * this.taskHeight;
4686
+ }
4687
+ },
4688
+ methods: {
4689
+ /**
4690
+ * Handle scroll event with throttling
4691
+ */
4692
+ onScroll(event) {
4693
+ const now = Date.now();
4694
+ if (now - this.lastScrollTime < this.scrollThrottleDelay) {
4695
+ return;
4696
+ }
4697
+ this.lastScrollTime = now;
4698
+ this.scrollTop = event.target.scrollTop;
4699
+ this.containerHeight = event.target.clientHeight;
4700
+ },
4701
+ /**
4702
+ * Update container height when component updates
4703
+ */
4704
+ updateContainerHeight() {
4705
+ if (this.$refs.taskListItems) {
4706
+ this.containerHeight = this.$refs.taskListItems.clientHeight;
4707
+ }
4708
+ }
4588
4709
  },
4589
4710
  /**
4590
4711
  * Mounted
@@ -4593,6 +4714,30 @@ var TaskListItem_component = normalizeComponent(
4593
4714
  this.root.state.refs.taskListWrapper = this.$refs.taskListWrapper;
4594
4715
  this.root.state.refs.taskList = this.$refs.taskList;
4595
4716
  this.root.state.refs.taskListItems = this.$refs.taskListItems;
4717
+
4718
+ // Initialize container height
4719
+ this.$nextTick(() => {
4720
+ this.updateContainerHeight();
4721
+ });
4722
+ },
4723
+ /**
4724
+ * Watch for changes in visible tasks to update virtual scrolling
4725
+ */
4726
+ watch: {
4727
+ 'root.visibleTasks': {
4728
+ handler() {
4729
+ this.$nextTick(() => {
4730
+ this.updateContainerHeight();
4731
+ });
4732
+ },
4733
+ deep: true
4734
+ }
4735
+ },
4736
+ /**
4737
+ * Updated lifecycle hook
4738
+ */
4739
+ updated() {
4740
+ this.updateContainerHeight();
4596
4741
  }
4597
4742
  });
4598
4743
  ;// ./src/components/TaskList/TaskList.vue?vue&type=script&lang=js
@@ -4607,8 +4752,8 @@ var TaskListItem_component = normalizeComponent(
4607
4752
  ;
4608
4753
  var TaskList_component = normalizeComponent(
4609
4754
  TaskList_TaskListvue_type_script_lang_js,
4610
- TaskListvue_type_template_id_74ce1216_render,
4611
- TaskListvue_type_template_id_74ce1216_staticRenderFns,
4755
+ TaskListvue_type_template_id_b705a4ea_render,
4756
+ TaskListvue_type_template_id_b705a4ea_staticRenderFns,
4612
4757
  false,
4613
4758
  null,
4614
4759
  null,
@@ -11381,12 +11526,99 @@ const GanttElastic = {
11381
11526
  unwatchOutputTasks: null,
11382
11527
  unwatchOutputOptions: null,
11383
11528
  unwatchOutputStyle: null
11384
- }
11529
+ },
11530
+ // Performance optimization properties
11531
+ updateQueue: [],
11532
+ updateTimeout: null,
11533
+ lastUpdateTime: 0,
11534
+ updateThrottleDelay: 16,
11535
+ // ~60fps
11536
+ isUpdating: false
11385
11537
  };
11386
11538
  },
11387
11539
  methods: {
11388
11540
  mergeDeep,
11389
11541
  mergeDeepReactive,
11542
+ /**
11543
+ * Debounced update method to prevent excessive re-renders
11544
+ */
11545
+ debouncedUpdate(updateFn, context = 'general') {
11546
+ const now = Date.now();
11547
+
11548
+ // Add to update queue
11549
+ this.updateQueue.push({
11550
+ fn: updateFn,
11551
+ context,
11552
+ timestamp: now
11553
+ });
11554
+
11555
+ // Clear existing timeout
11556
+ if (this.updateTimeout) {
11557
+ clearTimeout(this.updateTimeout);
11558
+ }
11559
+
11560
+ // Set new timeout
11561
+ this.updateTimeout = setTimeout(() => {
11562
+ this.processUpdateQueue();
11563
+ }, this.updateThrottleDelay);
11564
+ },
11565
+ /**
11566
+ * Process the update queue
11567
+ */
11568
+ processUpdateQueue() {
11569
+ if (this.isUpdating || this.updateQueue.length === 0) {
11570
+ return;
11571
+ }
11572
+ this.isUpdating = true;
11573
+ const startTime = performance.now();
11574
+ try {
11575
+ // Group updates by context
11576
+ const groupedUpdates = {};
11577
+ this.updateQueue.forEach(update => {
11578
+ if (!groupedUpdates[update.context]) {
11579
+ groupedUpdates[update.context] = [];
11580
+ }
11581
+ groupedUpdates[update.context].push(update);
11582
+ });
11583
+
11584
+ // Process each group
11585
+ Object.keys(groupedUpdates).forEach(context => {
11586
+ const updates = groupedUpdates[context];
11587
+ const latestUpdate = updates[updates.length - 1]; // Use the latest update
11588
+ latestUpdate.fn();
11589
+ });
11590
+
11591
+ // Clear the queue
11592
+ this.updateQueue = [];
11593
+
11594
+ // Performance monitoring
11595
+ const endTime = performance.now();
11596
+ const duration = endTime - startTime;
11597
+ if (duration > 16) {
11598
+ // Log if update takes longer than one frame
11599
+ console.warn(`Gantt update took ${duration.toFixed(2)}ms for ${Object.keys(groupedUpdates).length} contexts`);
11600
+ }
11601
+ } finally {
11602
+ this.isUpdating = false;
11603
+ }
11604
+ },
11605
+ /**
11606
+ * Performance monitoring method
11607
+ */
11608
+ logPerformanceMetrics() {
11609
+ const metrics = {
11610
+ totalTasks: this.state.tasks.length,
11611
+ visibleTasks: this.visibleTasks.length,
11612
+ updateQueueLength: this.updateQueue.length,
11613
+ isUpdating: this.isUpdating,
11614
+ memoryUsage: performance.memory ? {
11615
+ used: Math.round(performance.memory.usedJSHeapSize / 1024 / 1024) + 'MB',
11616
+ total: Math.round(performance.memory.totalJSHeapSize / 1024 / 1024) + 'MB'
11617
+ } : 'Not available'
11618
+ };
11619
+ console.log('Gantt Performance Metrics:', metrics);
11620
+ return metrics;
11621
+ },
11390
11622
  onViewModeChanged(mode) {
11391
11623
  // Update the calendar view mode
11392
11624
  this.options.calendar.viewMode = mode;
@@ -12673,7 +12905,9 @@ const GanttElastic = {
12673
12905
  this.state.options.height = this.getHeight(visibleTasks) - heightCompensation;
12674
12906
  this.state.options.allVisibleTasksHeight = this.getTasksHeight(visibleTasks);
12675
12907
  this.state.options.outerHeight = this.getHeight(visibleTasks, true) - heightCompensation;
12676
- let len = visibleTasks.length;
12908
+
12909
+ // Calculate task positions only for visible tasks
12910
+ const len = visibleTasks.length;
12677
12911
  for (let index = 0; index < len; index++) {
12678
12912
  let task = visibleTasks[index];
12679
12913
  task.width = task.duration / this.state.options.times.timePerPixel - this.style['grid-line-vertical']['stroke-width'];
@@ -12721,19 +12955,22 @@ const GanttElastic = {
12721
12955
  this.state.unwatchTasks = this.$watch('tasks', tasks => {
12722
12956
  const notEqual = notEqualDeep(tasks, this.outputTasks);
12723
12957
  if (notEqual) {
12724
- this.setup('tasks');
12958
+ this.debouncedUpdate(() => {
12959
+ this.setup('tasks');
12960
+ this.$nextTick(() => {
12961
+ this.recalculateHeight();
12962
+ });
12963
+ }, 'tasks');
12725
12964
  }
12726
- // Recalculate height when tasks change
12727
- this.$nextTick(() => {
12728
- this.recalculateHeight();
12729
- });
12730
12965
  }, {
12731
12966
  deep: true
12732
12967
  });
12733
12968
  this.state.unwatchOptions = this.$watch('options', opts => {
12734
12969
  const notEqual = notEqualDeep(opts, this.outputOptions);
12735
12970
  if (notEqual) {
12736
- this.setup('options');
12971
+ this.debouncedUpdate(() => {
12972
+ this.setup('options');
12973
+ }, 'options');
12737
12974
  }
12738
12975
  }, {
12739
12976
  deep: true
@@ -12868,10 +13105,10 @@ const GanttElastic = {
12868
13105
  /* harmony default export */ var GanttElasticvue_type_script_lang_js = (GanttElastic);
12869
13106
  ;// ./src/GanttElastic.vue?vue&type=script&lang=js
12870
13107
  /* harmony default export */ var src_GanttElasticvue_type_script_lang_js = (GanttElasticvue_type_script_lang_js);
12871
- ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/GanttElastic.vue?vue&type=style&index=0&id=0a0b0d9f&prod&lang=css
13108
+ ;// ./node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-12.use[0]!./node_modules/@vue/cli-service/node_modules/css-loader/dist/cjs.js??clonedRuleSet-12.use[1]!./node_modules/@vue/vue-loader-v15/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-12.use[2]!./node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./src/GanttElastic.vue?vue&type=style&index=0&id=95091692&prod&lang=css
12872
13109
  // extracted by mini-css-extract-plugin
12873
13110
 
12874
- ;// ./src/GanttElastic.vue?vue&type=style&index=0&id=0a0b0d9f&prod&lang=css
13111
+ ;// ./src/GanttElastic.vue?vue&type=style&index=0&id=95091692&prod&lang=css
12875
13112
 
12876
13113
  ;// ./src/GanttElastic.vue
12877
13114
 
@@ -12884,8 +13121,8 @@ const GanttElastic = {
12884
13121
 
12885
13122
  var GanttElastic_component = normalizeComponent(
12886
13123
  src_GanttElasticvue_type_script_lang_js,
12887
- GanttElasticvue_type_template_id_0a0b0d9f_render,
12888
- GanttElasticvue_type_template_id_0a0b0d9f_staticRenderFns,
13124
+ GanttElasticvue_type_template_id_95091692_render,
13125
+ GanttElasticvue_type_template_id_95091692_staticRenderFns,
12889
13126
  false,
12890
13127
  null,
12891
13128
  null,